@@ -54,6 +54,8 @@ func ContentSuite(t *testing.T, name string, storeFn func(ctx context.Context, r
5454
5555 t .Run ("CrossNamespaceAppend" , makeTest (t , name , storeFn , checkCrossNSAppend ))
5656 t .Run ("CrossNamespaceShare" , makeTest (t , name , storeFn , checkCrossNSShare ))
57+
58+ t .Run ("CommitErrorState" , makeTest (t , name , storeFn , checkCommitErrorState ))
5759}
5860
5961// ContextWrapper is used to decorate new context used inside the test
@@ -312,7 +314,175 @@ func checkCommitExists(ctx context.Context, t *testing.T, cs content.Store) {
312314 } else if ! errdefs .IsAlreadyExists (err ) {
313315 t .Fatalf ("(%d) Unexpected error: %+v" , i , err )
314316 }
317+ }
318+ }
319+
320+ func checkRefNotAvailable (ctx context.Context , t * testing.T , cs content.Store , ref string ) {
321+ t .Helper ()
322+
323+ w , err := cs .Writer (ctx , content .WithRef (ref ))
324+ if err == nil {
325+ w .Close ()
326+ t .Fatal ("writer created with ref, expected to be in use" )
327+ }
328+ if ! errdefs .IsUnavailable (err ) {
329+ t .Fatalf ("Expected unavailable error, got %+v" , err )
330+ }
331+ }
332+
333+ func checkCommitErrorState (ctx context.Context , t * testing.T , cs content.Store ) {
334+ c1 , d1 := createContent (256 )
335+ _ , d2 := createContent (256 )
336+ if err := content .WriteBlob (ctx , cs , "c1" , bytes .NewReader (c1 ), ocispec.Descriptor {Digest : d1 }); err != nil {
337+ t .Fatal (err )
338+ }
339+
340+ ref := "c1-commiterror-state"
341+ w , err := cs .Writer (ctx , content .WithRef (ref ))
342+ if err != nil {
343+ t .Fatal (err )
344+ }
345+ if _ , err := w .Write (c1 ); err != nil {
346+ if err := w .Close (); err != nil {
347+ t .Errorf ("Close error: %+v" , err )
348+ }
349+ t .Fatal (err )
350+ }
351+
352+ checkRefNotAvailable (ctx , t , cs , ref )
353+
354+ // Check exists
355+ err = w .Commit (ctx , int64 (len (c1 )), d1 )
356+ if err == nil {
357+ t .Fatalf ("Expected already exists error" )
358+ } else if ! errdefs .IsAlreadyExists (err ) {
359+ if err := w .Close (); err != nil {
360+ t .Errorf ("Close error: %+v" , err )
361+ }
362+ t .Fatalf ("Unexpected error: %+v" , err )
363+ }
364+
365+ w , err = cs .Writer (ctx , content .WithRef (ref ))
366+ if err != nil {
367+ t .Fatal (err )
368+ }
369+
370+ checkRefNotAvailable (ctx , t , cs , ref )
371+
372+ if _ , err := w .Write (c1 ); err != nil {
373+ if err := w .Close (); err != nil {
374+ t .Errorf ("close error: %+v" , err )
375+ }
376+ t .Fatal (err )
377+ }
378+
379+ // Check exists without providing digest
380+ err = w .Commit (ctx , int64 (len (c1 )), "" )
381+ if err == nil {
382+ t .Fatalf ("Expected already exists error" )
383+ } else if ! errdefs .IsAlreadyExists (err ) {
384+ if err := w .Close (); err != nil {
385+ t .Errorf ("Close error: %+v" , err )
386+ }
387+ t .Fatalf ("Unexpected error: %+v" , err )
388+ }
389+
390+ w , err = cs .Writer (ctx , content .WithRef (ref ))
391+ if err != nil {
392+ t .Fatal (err )
393+ }
394+
395+ checkRefNotAvailable (ctx , t , cs , ref )
396+
397+ if _ , err := w .Write (append (c1 , []byte ("more" )... )); err != nil {
398+ if err := w .Close (); err != nil {
399+ t .Errorf ("close error: %+v" , err )
400+ }
401+ t .Fatal (err )
402+ }
403+
404+ // Commit with the wrong digest should produce an error
405+ err = w .Commit (ctx , int64 (len (c1 ))+ 4 , d2 )
406+ if err == nil {
407+ t .Fatalf ("Expected error from wrong digest" )
408+ } else if ! errdefs .IsFailedPrecondition (err ) {
409+ t .Errorf ("Unexpected error: %+v" , err )
410+ }
411+
412+ w , err = cs .Writer (ctx , content .WithRef (ref ))
413+ if err != nil {
414+ t .Fatal (err )
415+ }
416+
417+ checkRefNotAvailable (ctx , t , cs , ref )
418+
419+ // Commit with wrong size should also produce an error
420+ err = w .Commit (ctx , int64 (len (c1 )), "" )
421+ if err == nil {
422+ t .Fatalf ("Expected error from wrong size" )
423+ } else if ! errdefs .IsFailedPrecondition (err ) {
424+ t .Errorf ("Unexpected error: %+v" , err )
425+ }
426+
427+ w , err = cs .Writer (ctx , content .WithRef (ref ))
428+ if err != nil {
429+ t .Fatal (err )
430+ }
431+
432+ checkRefNotAvailable (ctx , t , cs , ref )
433+
434+ // Now expect commit to succeed
435+ if err := w .Commit (ctx , int64 (len (c1 ))+ 4 , "" ); err != nil {
436+ if err := w .Close (); err != nil {
437+ t .Errorf ("close error: %+v" , err )
438+ }
439+ t .Fatalf ("Failed to commit: %+v" , err )
440+ }
315441
442+ // Create another writer with same reference
443+ w , err = cs .Writer (ctx , content .WithRef (ref ))
444+ if err != nil {
445+ t .Fatalf ("Failed to open writer: %+v" , err )
446+ }
447+
448+ if _ , err := w .Write (c1 ); err != nil {
449+ if err := w .Close (); err != nil {
450+ t .Errorf ("close error: %+v" , err )
451+ }
452+ t .Fatal (err )
453+ }
454+
455+ checkRefNotAvailable (ctx , t , cs , ref )
456+
457+ // Commit should fail due to already exists
458+ err = w .Commit (ctx , int64 (len (c1 )), d1 )
459+ if err == nil {
460+ t .Fatalf ("Expected already exists error" )
461+ } else if ! errdefs .IsAlreadyExists (err ) {
462+ if err := w .Close (); err != nil {
463+ t .Errorf ("close error: %+v" , err )
464+ }
465+ t .Fatalf ("Unexpected error: %+v" , err )
466+ }
467+
468+ w , err = cs .Writer (ctx , content .WithRef (ref ))
469+ if err != nil {
470+ t .Fatal (err )
471+ }
472+
473+ checkRefNotAvailable (ctx , t , cs , ref )
474+
475+ if err := w .Close (); err != nil {
476+ t .Fatalf ("Close failed: %+v" , err )
477+ }
478+
479+ // Create another writer with same reference to check available
480+ w , err = cs .Writer (ctx , content .WithRef (ref ))
481+ if err != nil {
482+ t .Fatalf ("Failed to open writer: %+v" , err )
483+ }
484+ if err := w .Close (); err != nil {
485+ t .Fatalf ("Close failed: %+v" , err )
316486 }
317487}
318488
0 commit comments