@@ -3,7 +3,9 @@ package libimage
33import (
44 "context"
55 "errors"
6+ "fmt"
67 "os"
8+ "sync"
79 "testing"
810
911 "github.com/containers/common/pkg/config"
@@ -261,21 +263,8 @@ func TestInspectHealthcheck(t *testing.T) {
261263}
262264
263265func TestTag (t * testing.T ) {
264- // Note: this will resolve pull from the GCR registry (see
265- // testdata/registries.conf).
266- busyboxLatest := "docker.io/library/busybox:latest"
267-
268- runtime , cleanup := testNewRuntime (t )
266+ runtime , image , cleanup := getImageAndRuntime (t )
269267 defer cleanup ()
270- ctx := context .Background ()
271-
272- pullOptions := & PullOptions {}
273- pullOptions .Writer = os .Stdout
274- pulledImages , err := runtime .Pull (ctx , busyboxLatest , config .PullPolicyMissing , pullOptions )
275- require .NoError (t , err )
276- require .Len (t , pulledImages , 1 )
277-
278- image := pulledImages [0 ]
279268
280269 digest := "sha256:adab3844f497ab9171f070d4cae4114b5aec565ac772e2f2579405b78be67c96"
281270
@@ -307,26 +296,65 @@ func TestTag(t *testing.T) {
307296 }
308297
309298 // Check for specific error.
310- err = image .Tag ("foo@" + digest )
299+ err : = image .Tag ("foo@" + digest )
311300 require .True (t , errors .Is (err , errTagDigest ), "check for specific digest error" )
312301}
313302
314- func TestUntag (t * testing.T ) {
315- // Note: this will resolve pull from the GCR registry (see
316- // testdata/registries.conf).
317- busyboxLatest := "docker.io/library/busybox:latest"
318-
319- runtime , cleanup := testNewRuntime (t )
303+ func TestTagAndUntagParallel (t * testing.T ) {
304+ runtime , image , cleanup := getImageAndRuntime (t )
320305 defer cleanup ()
321- ctx := context .Background ()
322306
323- pullOptions := & PullOptions {}
324- pullOptions .Writer = os .Stdout
325- pulledImages , err := runtime .Pull (ctx , busyboxLatest , config .PullPolicyMissing , pullOptions )
326- require .NoError (t , err )
327- require .Len (t , pulledImages , 1 )
307+ tagCount := 10
308+ wg := sync.WaitGroup {}
328309
329- image := pulledImages [0 ]
310+ origNames := image .Names ()
311+
312+ names := make ([]string , 0 , tagCount )
313+ names = append (names , origNames ... )
314+
315+ // Test tag in parallel, the extra go routine is critical for the test do not remove that.
316+ wg .Add (tagCount )
317+ for i := 0 ; i < tagCount ; i ++ {
318+ name := fmt .Sprintf ("localhost/tag-%d:latest" , i )
319+ names = append (names , name )
320+ go func (name string ) {
321+ defer wg .Done ()
322+ err := image .Tag (name )
323+ require .NoError (t , err , "parallel tag should have succeeded" )
324+ }(name )
325+ }
326+
327+ // wait for all routines to finish
328+ wg .Wait ()
329+
330+ newImg , _ , err := runtime .LookupImage (image .ID (), nil )
331+ require .NoError (t , err , "image should have resolved locally" )
332+ // Note use ElementsMatch because teh order is unspecified to the parallel nature
333+ require .ElementsMatch (t , names , newImg .Names (), "tag image names should contain same elements" )
334+
335+ // Test untag in parallel
336+ wg .Add (tagCount )
337+ for i := 0 ; i < tagCount ; i ++ {
338+ name := fmt .Sprintf ("localhost/tag-%d:latest" , i )
339+ names = append (names , name )
340+ go func (name string ) {
341+ defer wg .Done ()
342+ err := image .Untag (name )
343+ require .NoError (t , err , "parallel untag should have succeeded" )
344+ }(name )
345+ }
346+ // wait for all routines to finish
347+ wg .Wait ()
348+
349+ newImg , _ , err = runtime .LookupImage (image .ID (), nil )
350+ require .NoError (t , err , "image should have resolved locally" )
351+ // Note use ElementsMatch because teh order is unspecified to the parallel nature
352+ require .ElementsMatch (t , origNames , newImg .Names (), "untag image names should contain same elements" )
353+ }
354+
355+ func TestUntag (t * testing.T ) {
356+ runtime , image , cleanup := getImageAndRuntime (t )
357+ defer cleanup ()
330358
331359 digest := "sha256:adab3844f497ab9171f070d4cae4114b5aec565ac772e2f2579405b78be67c96"
332360
@@ -360,6 +388,25 @@ func TestUntag(t *testing.T) {
360388 }
361389
362390 // Check for specific error.
363- err = image .Untag (digest )
391+ err : = image .Untag (digest )
364392 require .True (t , errors .Is (err , errUntagDigest ), "check for specific digest error" )
365393}
394+
395+ func getImageAndRuntime (t * testing.T ) (* Runtime , * Image , func ()) {
396+ // Note: this will resolve pull from the GCR registry (see
397+ // testdata/registries.conf).
398+ busyboxLatest := "docker.io/library/busybox:latest"
399+
400+ runtime , cleanup := testNewRuntime (t )
401+ ctx := context .Background ()
402+
403+ pullOptions := & PullOptions {}
404+ pullOptions .Writer = os .Stdout
405+ pulledImages , err := runtime .Pull (ctx , busyboxLatest , config .PullPolicyMissing , pullOptions )
406+ require .NoError (t , err )
407+ require .Len (t , pulledImages , 1 )
408+
409+ image := pulledImages [0 ]
410+
411+ return runtime , image , cleanup
412+ }
0 commit comments