@@ -17,29 +17,22 @@ import 'package:test/test.dart';
1717import '../../shared/test_services.dart' ;
1818
1919void main () {
20- testWithFakeTime ('ExportedApi' , (fakeTime) async {
20+ final retryPkgData1 = PackageData (
21+ name: 'retry' ,
22+ latest: VersionInfo (
23+ version: '1.2.3' ,
24+ retracted: false ,
25+ pubspec: {},
26+ archiveUrl: '-' ,
27+ archiveSha256: '-' ,
28+ published: clock.now (),
29+ ),
30+ versions: [],
31+ );
32+
33+ testWithFakeTime ('ExportedApi.garbageCollect()' , (fakeTime) async {
2134 await storageService.createBucket ('exported-api' );
2235 final bucket = storageService.bucket ('exported-api' );
23-
24- /// Read bytes from bucket
25- Future <Uint8List ?> readBytes (String path) async {
26- try {
27- return await bucket.readAsBytes (path);
28- } on DetailedApiRequestError catch (e) {
29- if (e.status == 404 ) return null ;
30- rethrow ;
31- }
32- }
33-
34- /// Read gzipped JSON from bucket
35- Future <Object ?> readGzippedJson (String path) async {
36- final bytes = await readBytes (path);
37- if (bytes == null ) {
38- return null ;
39- }
40- return utf8JsonDecoder.convert (gzip.decode (bytes));
41- }
42-
4336 final exportedApi = ExportedApi (storageService, bucket);
4437
4538 // Test that deletion works when bucket is empty
@@ -48,47 +41,80 @@ void main() {
4841 // Test that GC works when bucket is empty
4942 await exportedApi.garbageCollect ({});
5043
51- final retryPkgData1 = PackageData (
52- name: 'retry' ,
53- latest: VersionInfo (
54- version: '1.2.3' ,
55- retracted: false ,
56- pubspec: {},
57- archiveUrl: '-' ,
58- archiveSha256: '-' ,
59- published: clock.now (),
60- ),
61- versions: [],
62- );
63-
6444 await exportedApi.package ('retry' ).versions.write (retryPkgData1);
6545
6646 expect (
67- await readGzippedJson ('latest/api/packages/retry' ),
47+ await bucket. readGzippedJson ('latest/api/packages/retry' ),
6848 json.decode (json.encode (retryPkgData1.toJson ())),
6949 );
7050
7151 // Check that GC after 10 mins won't delete a package we don't recognize
7252 fakeTime.elapseSync (minutes: 10 );
7353 await exportedApi.garbageCollect ({});
7454 expect (
75- await readGzippedJson ('latest/api/packages/retry' ),
55+ await bucket. readGzippedJson ('latest/api/packages/retry' ),
7656 isNotNull,
7757 );
7858
7959 // Check that GC after 2 days won't delete a package we know
8060 fakeTime.elapseSync (days: 2 );
8161 await exportedApi.garbageCollect ({'retry' });
8262 expect (
83- await readGzippedJson ('latest/api/packages/retry' ),
63+ await bucket. readGzippedJson ('latest/api/packages/retry' ),
8464 isNotNull,
8565 );
8666
8767 // Check retry after 2 days will delete a package we don't know.
8868 await exportedApi.garbageCollect ({});
8969 expect (
90- await readGzippedJson ('latest/api/packages/retry' ),
70+ await bucket. readGzippedJson ('latest/api/packages/retry' ),
9171 isNull,
9272 );
73+
74+ // Check that stray files in old-runtimeVersions will be GC'ed
75+ final oldFiles = [
76+ '2023.08.10/api/packages/retry' ,
77+ '2023.08.10/api/stray-file1' ,
78+ '2023.08.10/stray-file2' ,
79+ ];
80+ for (final f in oldFiles) {
81+ await bucket.writeBytes (f, [0 ]);
82+ expect (
83+ await bucket.readBytes (f),
84+ isNotNull,
85+ );
86+ }
87+
88+ // Run GC to delete all stray files
89+ await exportedApi.garbageCollect ({});
90+
91+ for (final f in oldFiles) {
92+ expect (
93+ await bucket.readBytes (f),
94+ isNull,
95+ reason: 'expected "$f " to be GCed' ,
96+ );
97+ }
9398 });
9499}
100+
101+ extension on Bucket {
102+ /// Read bytes from bucket, retur null if missing
103+ Future <Uint8List ?> readBytes (String path) async {
104+ try {
105+ return await readAsBytes (path);
106+ } on DetailedApiRequestError catch (e) {
107+ if (e.status == 404 ) return null ;
108+ rethrow ;
109+ }
110+ }
111+
112+ /// Read gzipped JSON from bucket
113+ Future <Object ?> readGzippedJson (String path) async {
114+ final bytes = await readBytes (path);
115+ if (bytes == null ) {
116+ return null ;
117+ }
118+ return utf8JsonDecoder.convert (gzip.decode (bytes));
119+ }
120+ }
0 commit comments