@@ -44,6 +44,97 @@ void main() {
4444 expect (fileSystem.file ('out/test' ), exists);
4545 });
4646
47+ testWithoutContext ('ArtifactUpdater will not validate the md5 hash if the '
48+ 'x-goog-hash header is present but missing an md5 entry' , () async {
49+ final MockOperatingSystemUtils operatingSystemUtils = MockOperatingSystemUtils ();
50+ final MemoryFileSystem fileSystem = MemoryFileSystem .test ();
51+ final BufferLogger logger = BufferLogger .test ();
52+ final MockHttpClient client = MockHttpClient ();
53+ client.testRequest.testResponse.headers = FakeHttpHeaders (< String , List <String >> {
54+ 'x-goog-hash' : < String > [],
55+ });
56+
57+ final ArtifactUpdater artifactUpdater = ArtifactUpdater (
58+ fileSystem: fileSystem,
59+ logger: logger,
60+ operatingSystemUtils: operatingSystemUtils,
61+ platform: testPlatform,
62+ httpClient: client,
63+ tempStorage: fileSystem.currentDirectory.childDirectory ('temp' )
64+ ..createSync (),
65+ );
66+
67+ await artifactUpdater.downloadZipArchive (
68+ 'test message' ,
69+ Uri .parse ('http:///test.zip' ),
70+ fileSystem.currentDirectory.childDirectory ('out' ),
71+ );
72+ expect (logger.statusText, contains ('test message' ));
73+ expect (fileSystem.file ('out/test' ), exists);
74+ });
75+
76+ testWithoutContext ('ArtifactUpdater will validate the md5 hash if the '
77+ 'x-goog-hash header is present' , () async {
78+ final MockOperatingSystemUtils operatingSystemUtils = MockOperatingSystemUtils ();
79+ final MemoryFileSystem fileSystem = MemoryFileSystem .test ();
80+ final BufferLogger logger = BufferLogger .test ();
81+ final MockHttpClient client = MockHttpClient ();
82+ client.testRequest.testResponse.headers = FakeHttpHeaders (< String , List <String >> {
83+ 'x-goog-hash' : < String > [
84+ 'foo-bar-baz' ,
85+ 'md5=k7iFrf4NoInN9jSQT9WfcQ=='
86+ ],
87+ });
88+
89+ final ArtifactUpdater artifactUpdater = ArtifactUpdater (
90+ fileSystem: fileSystem,
91+ logger: logger,
92+ operatingSystemUtils: operatingSystemUtils,
93+ platform: testPlatform,
94+ httpClient: client,
95+ tempStorage: fileSystem.currentDirectory.childDirectory ('temp' )
96+ ..createSync (),
97+ );
98+
99+ await artifactUpdater.downloadZipArchive (
100+ 'test message' ,
101+ Uri .parse ('http:///test.zip' ),
102+ fileSystem.currentDirectory.childDirectory ('out' ),
103+ );
104+ expect (logger.statusText, contains ('test message' ));
105+ expect (fileSystem.file ('out/test' ), exists);
106+ });
107+
108+ testWithoutContext ('ArtifactUpdater will validate the md5 hash if the '
109+ 'x-goog-hash header is present and throw if it does not match' , () async {
110+ final MockOperatingSystemUtils operatingSystemUtils = MockOperatingSystemUtils ();
111+ final MemoryFileSystem fileSystem = MemoryFileSystem .test ();
112+ final BufferLogger logger = BufferLogger .test ();
113+ final MockHttpClient client = MockHttpClient ();
114+ client.testRequest.testResponse.headers = FakeHttpHeaders (< String , List <String >> {
115+ 'x-goog-hash' : < String > [
116+ 'foo-bar-baz' ,
117+ 'md5=k7iFrf4SQT9WfcQ=='
118+ ],
119+ });
120+
121+ final ArtifactUpdater artifactUpdater = ArtifactUpdater (
122+ fileSystem: fileSystem,
123+ logger: logger,
124+ operatingSystemUtils: operatingSystemUtils,
125+ platform: testPlatform,
126+ httpClient: client,
127+ tempStorage: fileSystem.currentDirectory.childDirectory ('temp' )
128+ ..createSync (),
129+ );
130+
131+ await expectLater (() async => await artifactUpdater.downloadZipArchive (
132+ 'test message' ,
133+ Uri .parse ('http:///test.zip' ),
134+ fileSystem.currentDirectory.childDirectory ('out' ),
135+ ), throwsToolExit (message: 'k7iFrf4SQT9WfcQ==' )); // validate that the hash mismatch message is included.
136+ });
137+
47138 testWithoutContext ('ArtifactUpdater will restart the status ticker if it needs to retry the download' , () async {
48139 final MockOperatingSystemUtils operatingSystemUtils = MockOperatingSystemUtils ();
49140 final MemoryFileSystem fileSystem = MemoryFileSystem .test ();
@@ -353,6 +444,7 @@ class MockHttpClient extends Mock implements HttpClient {
353444 return testRequest;
354445 }
355446}
447+
356448class MockHttpClientRequest extends Mock implements HttpClientRequest {
357449 final MockHttpClientResponse testResponse = MockHttpClientResponse ();
358450
@@ -361,13 +453,28 @@ class MockHttpClientRequest extends Mock implements HttpClientRequest {
361453 return testResponse;
362454 }
363455}
456+
364457class MockHttpClientResponse extends Mock implements HttpClientResponse {
365458 @override
366459 int statusCode = HttpStatus .ok;
367460
461+ @override
462+ HttpHeaders headers = FakeHttpHeaders (< String , List <String >> {});
463+
368464 @override
369465 Future <void > forEach (void Function (List <int > element) action) async {
370466 action (< int > [0 ]);
371467 return ;
372468 }
373469}
470+
471+ class FakeHttpHeaders extends Fake implements HttpHeaders {
472+ FakeHttpHeaders (this .values);
473+
474+ final Map <String , List <String >> values;
475+
476+ @override
477+ List <String > operator [](String key) {
478+ return values[key];
479+ }
480+ }
0 commit comments