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  }