@@ -223,6 +223,300 @@ func TestGetUpperPWLM(t *testing.T) {
223223 }
224224}
225225
226+ // Test dependency recursion.
227+ // This tests A --- A
228+ // If not checked it will cause an infinite recursion.
229+ func TestRecursiveDep1 (t * testing.T ) {
230+ dir , err := ioutil .TempDir ("" , tstprefix )
231+ if err != nil {
232+ t .Fatalf ("error creating tempdir: %v" , err )
233+ }
234+ defer os .RemoveAll (dir )
235+ ds := NewTestStore ()
236+
237+ // B
238+ imj := `
239+ {
240+ "acKind": "ImageManifest",
241+ "acVersion": "0.1.1",
242+ "name": "example.com/test01"
243+ }
244+ `
245+
246+ imj , err = addDependencies (imj ,
247+ types.Dependency {
248+ ImageName : "example.com/test01" ,
249+ },
250+ )
251+ if err != nil {
252+ t .Fatalf ("unexpected error: %v" , err )
253+ }
254+
255+ entries := []* testTarEntry {
256+ {
257+ contents : imj ,
258+ header : & tar.Header {
259+ Name : "manifest" ,
260+ Size : int64 (len (imj )),
261+ },
262+ },
263+ // An empty dir
264+ {
265+ header : & tar.Header {
266+ Name : "rootfs/a" ,
267+ Typeflag : tar .TypeDir ,
268+ },
269+ },
270+ }
271+
272+ key1 , err := newTestACI (entries , dir , ds )
273+
274+ expectedFiles := []* fileInfo {
275+ & fileInfo {path : "manifest" , typeflag : tar .TypeReg },
276+ & fileInfo {path : "rootfs/a" , typeflag : tar .TypeDir },
277+ }
278+
279+ err = checkRenderACI ("example.com/test01" , expectedFiles , ds )
280+ if err == nil {
281+ t .Fatalf ("expected recursion error" )
282+ } else {
283+ expectedErr := fmt .Errorf ("recursion error, image with key %s already referenced by a parent image" , key1 )
284+ if err .Error () != expectedErr .Error () {
285+ t .Fatalf ("expected error: %v, got: %v" , expectedErr , err )
286+ }
287+ }
288+ }
289+
290+ // Test dependency recursion.
291+ // This tests A --- B --- A
292+ // If not checked it will cause an infinite recursion.
293+ func TestRecursiveDep2 (t * testing.T ) {
294+ dir , err := ioutil .TempDir ("" , tstprefix )
295+ if err != nil {
296+ t .Fatalf ("error creating tempdir: %v" , err )
297+ }
298+ defer os .RemoveAll (dir )
299+ ds := NewTestStore ()
300+
301+ // B
302+ imj := `
303+ {
304+ "acKind": "ImageManifest",
305+ "acVersion": "0.1.1",
306+ "name": "example.com/test01"
307+ }
308+ `
309+
310+ // Make B depend on A
311+ imj , err = addDependencies (imj ,
312+ types.Dependency {
313+ ImageName : "example.com/test02" ,
314+ },
315+ )
316+ if err != nil {
317+ t .Fatalf ("unexpected error: %v" , err )
318+ }
319+
320+ entries := []* testTarEntry {
321+ {
322+ contents : imj ,
323+ header : & tar.Header {
324+ Name : "manifest" ,
325+ Size : int64 (len (imj )),
326+ },
327+ },
328+ // An empty dir
329+ {
330+ header : & tar.Header {
331+ Name : "rootfs/a" ,
332+ Typeflag : tar .TypeDir ,
333+ },
334+ },
335+ }
336+
337+ key1 , err := newTestACI (entries , dir , ds )
338+ if err != nil {
339+ t .Fatalf ("unexpected error: %v" , err )
340+ }
341+
342+ // A
343+ imj = `
344+ {
345+ "acKind": "ImageManifest",
346+ "acVersion": "0.1.1",
347+ "name": "example.com/test02"
348+ }
349+ `
350+
351+ k1 , _ := types .NewHash (key1 )
352+ imj , err = addDependencies (imj ,
353+ types.Dependency {
354+ ImageName : "example.com/test01" ,
355+ ImageID : k1 },
356+ )
357+ if err != nil {
358+ t .Fatalf ("unexpected error: %v" , err )
359+ }
360+
361+ entries = []* testTarEntry {
362+ {
363+ contents : imj ,
364+ header : & tar.Header {
365+ Name : "manifest" ,
366+ Size : int64 (len (imj )),
367+ },
368+ },
369+ }
370+
371+ key2 , err := newTestACI (entries , dir , ds )
372+ if err != nil {
373+ t .Fatalf ("unexpected error: %v" , err )
374+ }
375+
376+ expectedFiles := []* fileInfo {
377+ & fileInfo {path : "manifest" , typeflag : tar .TypeReg },
378+ & fileInfo {path : "rootfs/a" , typeflag : tar .TypeDir },
379+ }
380+
381+ err = checkRenderACI ("example.com/test02" , expectedFiles , ds )
382+ if err == nil {
383+ t .Fatalf ("expected recursion error" )
384+ } else {
385+ expectedErr := fmt .Errorf ("recursion error, image with key %s already referenced by a parent image" , key2 )
386+ if err .Error () != expectedErr .Error () {
387+ t .Fatalf ("expected error: %v, got: %v" , expectedErr , err )
388+ }
389+ }
390+ }
391+
392+ // Having an image referenced inside different branches is not a recursion problem
393+ // This tests this dep tree:
394+ // A --- B --- C
395+ // \-- C
396+ func TestNonRecursiveDep (t * testing.T ) {
397+ dir , err := ioutil .TempDir ("" , tstprefix )
398+ if err != nil {
399+ t .Fatalf ("error creating tempdir: %v" , err )
400+ }
401+ defer os .RemoveAll (dir )
402+ ds := NewTestStore ()
403+
404+ // C
405+ imj := `
406+ {
407+ "acKind": "ImageManifest",
408+ "acVersion": "0.1.1",
409+ "name": "example.com/test01"
410+ }
411+ `
412+
413+ entries := []* testTarEntry {
414+ {
415+ contents : imj ,
416+ header : & tar.Header {
417+ Name : "manifest" ,
418+ Size : int64 (len (imj )),
419+ },
420+ },
421+ // An empty dir
422+ {
423+ header : & tar.Header {
424+ Name : "rootfs/a" ,
425+ Typeflag : tar .TypeDir ,
426+ },
427+ },
428+ }
429+
430+ key1 , err := newTestACI (entries , dir , ds )
431+ if err != nil {
432+ t .Fatalf ("unexpected error: %v" , err )
433+ }
434+
435+ // B
436+ imj = `
437+ {
438+ "acKind": "ImageManifest",
439+ "acVersion": "0.1.1",
440+ "name": "example.com/test02"
441+ }
442+ `
443+
444+ k1 , _ := types .NewHash (key1 )
445+ imj , err = addDependencies (imj ,
446+ // C
447+ types.Dependency {
448+ ImageName : "example.com/test01" ,
449+ ImageID : k1 },
450+ )
451+ if err != nil {
452+ t .Fatalf ("unexpected error: %v" , err )
453+ }
454+
455+ entries = []* testTarEntry {
456+ {
457+ contents : imj ,
458+ header : & tar.Header {
459+ Name : "manifest" ,
460+ Size : int64 (len (imj )),
461+ },
462+ },
463+ }
464+
465+ key2 , err := newTestACI (entries , dir , ds )
466+ if err != nil {
467+ t .Fatalf ("unexpected error: %v" , err )
468+ }
469+
470+ // A
471+ imj = `
472+ {
473+ "acKind": "ImageManifest",
474+ "acVersion": "0.1.1",
475+ "name": "example.com/test03"
476+ }
477+ `
478+
479+ k2 , _ := types .NewHash (key2 )
480+ imj , err = addDependencies (imj ,
481+ // B
482+ types.Dependency {
483+ ImageName : "example.com/test02" ,
484+ ImageID : k2 },
485+ // C
486+ types.Dependency {
487+ ImageName : "example.com/test01" ,
488+ ImageID : k1 },
489+ )
490+ if err != nil {
491+ t .Fatalf ("unexpected error: %v" , err )
492+ }
493+
494+ entries = []* testTarEntry {
495+ {
496+ contents : imj ,
497+ header : & tar.Header {
498+ Name : "manifest" ,
499+ Size : int64 (len (imj )),
500+ },
501+ },
502+ }
503+
504+ _ , err = newTestACI (entries , dir , ds )
505+ if err != nil {
506+ t .Fatalf ("unexpected error: %v" , err )
507+ }
508+
509+ expectedFiles := []* fileInfo {
510+ & fileInfo {path : "manifest" , typeflag : tar .TypeReg },
511+ & fileInfo {path : "rootfs/a" , typeflag : tar .TypeDir },
512+ }
513+
514+ err = checkRenderACI ("example.com/test03" , expectedFiles , ds )
515+ if err != nil {
516+ t .Fatalf ("unexpected error: %v" , err )
517+ }
518+ }
519+
226520// Test an image with 1 dep. The parent provides a dir not provided by the image.
227521func TestDirFromParent (t * testing.T ) {
228522 dir , err := ioutil .TempDir ("" , tstprefix )
0 commit comments