@@ -201,6 +201,35 @@ mod tests {
201201
202202 use super :: * ;
203203
204+ /// Build a source bundle from the standard pair of sourcemap fixtures.
205+ fn make_test_bundle ( ) -> TempFile {
206+ let projects_slice = & [ "wat-project" . into ( ) ] ;
207+ let context = BundleContext {
208+ org : "wat-org" ,
209+ projects : Some ( projects_slice. into ( ) ) ,
210+ release : None ,
211+ dist : None ,
212+ note : None ,
213+ } ;
214+
215+ let source_files = [ "bundle.min.js.map" , "vendor.min.js.map" ]
216+ . into_iter ( )
217+ . map ( |name| SourceFile {
218+ url : format ! ( "~/{name}" ) ,
219+ path : format ! ( "tests/integration/_fixtures/{name}" ) . into ( ) ,
220+ contents : std:: fs:: read ( format ! ( "tests/integration/_fixtures/{name}" ) )
221+ . unwrap ( )
222+ . into ( ) ,
223+ ty : SourceFileType :: SourceMap ,
224+ headers : Default :: default ( ) ,
225+ messages : Default :: default ( ) ,
226+ already_uploaded : false ,
227+ } )
228+ . collect :: < Vec < _ > > ( ) ;
229+
230+ build ( context, & source_files, None ) . unwrap ( )
231+ }
232+
204233 #[ test]
205234 fn test_url_to_bundle_path ( ) {
206235 assert_eq ! ( url_to_bundle_path( "~/bar" ) . unwrap( ) , "_/_/bar" ) ;
@@ -228,37 +257,35 @@ mod tests {
228257
229258 #[ test]
230259 fn build_deterministic ( ) {
231- let make_bundle = || {
232- let projects_slice = & [ "wat-project" . into ( ) ] ;
233- let context = BundleContext {
234- org : "wat-org" ,
235- projects : Some ( projects_slice. into ( ) ) ,
236- release : None ,
237- dist : None ,
238- note : None ,
239- } ;
240-
241- let source_files = [ "bundle.min.js.map" , "vendor.min.js.map" ]
242- . into_iter ( )
243- . map ( |name| SourceFile {
244- url : format ! ( "~/{name}" ) ,
245- path : format ! ( "tests/integration/_fixtures/{name}" ) . into ( ) ,
246- contents : std:: fs:: read ( format ! ( "tests/integration/_fixtures/{name}" ) )
247- . unwrap ( )
248- . into ( ) ,
249- ty : SourceFileType :: SourceMap ,
250- headers : Default :: default ( ) ,
251- messages : Default :: default ( ) ,
252- already_uploaded : false ,
253- } )
254- . collect :: < Vec < _ > > ( ) ;
255-
256- let file = build ( context, & source_files, None ) . unwrap ( ) ;
257- std:: fs:: read ( file. path ( ) ) . unwrap ( )
258- } ;
259-
260- let first = make_bundle ( ) ;
261- let second = make_bundle ( ) ;
260+ let first = std:: fs:: read ( make_test_bundle ( ) . path ( ) ) . unwrap ( ) ;
261+ let second = std:: fs:: read ( make_test_bundle ( ) . path ( ) ) . unwrap ( ) ;
262262 assert_eq ! ( first, second, "bundle output should be deterministic" ) ;
263263 }
264+
265+ /// Canary against silent compression-method changes from upstream bundle
266+ /// writers. The allowlist is a starting bound, not a verified server
267+ /// contract. We can widen it if a real incompatibility surfaces.
268+ #[ test]
269+ fn build_compression_method_canary ( ) {
270+ let bundle = make_test_bundle ( ) ;
271+ let mut archive =
272+ zip:: ZipArchive :: new ( std:: fs:: File :: open ( bundle. path ( ) ) . unwrap ( ) ) . unwrap ( ) ;
273+
274+ // Two source files plus the manifest.json that the source bundle
275+ // writer adds automatically.
276+ assert_eq ! ( archive. len( ) , 3 , "unexpected bundle entry count" ) ;
277+ for i in 0 ..archive. len ( ) {
278+ let entry = archive. by_index ( i) . unwrap ( ) ;
279+ let method = entry. compression ( ) ;
280+ assert ! (
281+ matches!(
282+ method,
283+ zip:: CompressionMethod :: Stored | zip:: CompressionMethod :: Deflated
284+ ) ,
285+ "entry {:?} uses {method:?}, outside the current allowlist: \
286+ verify backend compatibility before widening",
287+ entry. name( ) ,
288+ ) ;
289+ }
290+ }
264291}
0 commit comments