github.com/docker/cnab-to-oci@v0.3.0-beta4/remotes/promises_test.go (about) 1 package remotes 2 3 import ( 4 "context" 5 "errors" 6 "sync" 7 "testing" 8 "time" 9 10 "gotest.tools/assert" 11 ) 12 13 func TestPromisesNominal(t *testing.T) { 14 var mut sync.Mutex 15 var n int 16 var dependingValue int 17 ctx, cancel := context.WithCancel(context.Background()) 18 defer cancel() 19 scheduler := newErrgroupScheduler(ctx, 4, 5) 20 var deps []dependency 21 for i := 0; i < 4; i++ { 22 deps = append(deps, scheduler.schedule(func(ctx context.Context) error { 23 mut.Lock() 24 defer mut.Unlock() 25 n++ 26 return nil 27 })) 28 } 29 final := newPromise(scheduler, whenAll(deps)).then(func(ctx context.Context) error { 30 dependingValue = n 31 return nil 32 }) 33 assert.NilError(t, final.wait()) 34 assert.Equal(t, n, 4) 35 assert.Equal(t, dependingValue, 4) 36 } 37 38 func TestPromisesCancelUnblock(t *testing.T) { 39 ctx, cancel := context.WithCancel(context.Background()) 40 defer cancel() 41 scheduler := newErrgroupScheduler(ctx, 4, 5) 42 var done bool 43 started := make(chan struct{}) 44 p := scheduler.schedule(func(ctx context.Context) error { 45 close(started) 46 <-ctx.Done() 47 done = true 48 return nil 49 }) 50 <-started 51 cancel() 52 assert.NilError(t, p.wait()) 53 assert.Check(t, done) 54 } 55 56 func TestPromisesErrorUnblock(t *testing.T) { 57 ctx, cancel := context.WithCancel(context.Background()) 58 defer cancel() 59 scheduler := newErrgroupScheduler(ctx, 4, 5) 60 var done bool 61 p := scheduler.schedule(func(ctx context.Context) error { 62 <-ctx.Done() 63 done = true 64 return nil 65 }) 66 erroring := scheduler.schedule(func(ctx context.Context) error { 67 return errors.New("boom") 68 }) 69 assert.ErrorContains(t, erroring.wait(), "boom") 70 assert.NilError(t, p.wait()) 71 assert.Check(t, done) 72 } 73 74 func TestPromisesScheduleErroredDontBlockDontRun(t *testing.T) { 75 ctx, cancel := context.WithCancel(context.Background()) 76 defer cancel() 77 scheduler := newErrgroupScheduler(ctx, 4, 5) 78 errErroringTask := scheduler.schedule(func(ctx context.Context) error { 79 return errors.New("boom") 80 }).wait() 81 var done bool 82 errAfterError := scheduler.schedule(func(ctx context.Context) error { 83 done = true 84 return nil 85 }).wait() 86 assert.ErrorContains(t, errErroringTask, "boom") 87 assert.ErrorContains(t, errAfterError, "context canceled") 88 assert.Check(t, !done) 89 } 90 91 func TestPromisesErrorUnblockDeps(t *testing.T) { 92 ctx, cancel := context.WithCancel(context.Background()) 93 defer cancel() 94 scheduler := newErrgroupScheduler(ctx, 4, 5) 95 dep := scheduler.schedule(func(ctx context.Context) error { 96 time.Sleep(200) 97 return errors.New("boom") 98 }) 99 for i := 0; i < 50; i++ { 100 dep = dep.then(func(ctx context.Context) error { 101 return nil 102 }) 103 } 104 assert.ErrorContains(t, dep.wait(), "boom") 105 } 106 107 func TestPromisesUnwrwap(t *testing.T) { 108 ctx, cancel := context.WithCancel(context.Background()) 109 defer cancel() 110 scheduler := newErrgroupScheduler(ctx, 4, 5) 111 var done1, done2 bool 112 p := scheduleAndUnwrap(scheduler, func(ctx context.Context) (dependency, error) { 113 done1 = true 114 return scheduler.schedule(func(ctx context.Context) error { 115 time.Sleep(200) 116 done2 = true 117 return nil 118 }), nil 119 }) 120 assert.NilError(t, p.wait()) 121 assert.Check(t, done1) 122 assert.Check(t, done2) 123 } 124 125 func TestPromisesUnwrwapWithError(t *testing.T) { 126 ctx, cancel := context.WithCancel(context.Background()) 127 defer cancel() 128 scheduler := newErrgroupScheduler(ctx, 4, 5) 129 var done bool 130 p := scheduleAndUnwrap(scheduler, func(ctx context.Context) (dependency, error) { 131 done = true 132 return nil, errors.New("boom") 133 }) 134 assert.ErrorContains(t, p.wait(), "boom") 135 assert.Check(t, done) 136 } 137 138 func TestWhenAllWithErrorUnblocks(t *testing.T) { 139 ctx, cancel := context.WithCancel(context.Background()) 140 defer cancel() 141 scheduler := newErrgroupScheduler(ctx, 4, 5) 142 var dependencies []dependency 143 // add a blocking task 144 dependencies = append(dependencies, scheduler.schedule(func(ctx context.Context) error { 145 <-ctx.Done() 146 return nil 147 })) 148 dependencies = append(dependencies, failedDependency{errors.New("boom")}) 149 p := newPromise(scheduler, whenAll(dependencies)) // first error should be returned without waiting other 150 // tasks to complete 151 assert.ErrorContains(t, p.wait(), "boom") 152 } 153 154 func TestWhenAllWithErrorReported(t *testing.T) { 155 ctx, cancel := context.WithCancel(context.Background()) 156 defer cancel() 157 scheduler := newErrgroupScheduler(ctx, 4, 5) 158 var dependencies []dependency 159 // add a blocking task 160 dependencies = append(dependencies, doneDependency{}) 161 dependencies = append(dependencies, failedDependency{errors.New("boom")}) 162 p := newPromise(scheduler, whenAll(dependencies)) // first error should be returned without waiting other 163 // tasks to complete 164 assert.ErrorContains(t, p.wait(), "boom") 165 }