launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/utils/parallel/parallel_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package parallel_test
     5  
     6  import (
     7  	gc "launchpad.net/gocheck"
     8  	"sort"
     9  	"sync"
    10  	stdtesting "testing"
    11  	"time"
    12  
    13  	"launchpad.net/juju-core/utils/parallel"
    14  )
    15  
    16  func Test(t *stdtesting.T) {
    17  	gc.TestingT(t)
    18  }
    19  
    20  type parallelSuite struct{}
    21  
    22  var _ = gc.Suite(&parallelSuite{})
    23  
    24  func (*parallelSuite) TestParallelMaxPar(c *gc.C) {
    25  	const (
    26  		totalDo                 = 10
    27  		maxConcurrentRunnersPar = 3
    28  	)
    29  	var mu sync.Mutex
    30  	maxConcurrentRunners := 0
    31  	nbRunners := 0
    32  	nbRuns := 0
    33  	parallelRunner := parallel.NewRun(maxConcurrentRunnersPar)
    34  	for i := 0; i < totalDo; i++ {
    35  		parallelRunner.Do(func() error {
    36  			mu.Lock()
    37  			nbRuns++
    38  			nbRunners++
    39  			if nbRunners > maxConcurrentRunners {
    40  				maxConcurrentRunners = nbRunners
    41  			}
    42  			mu.Unlock()
    43  			time.Sleep(time.Second / 10)
    44  			mu.Lock()
    45  			nbRunners--
    46  			mu.Unlock()
    47  			return nil
    48  		})
    49  	}
    50  	err := parallelRunner.Wait()
    51  	if nbRunners != 0 {
    52  		c.Errorf("%d functions still running", nbRunners)
    53  	}
    54  	if nbRuns != totalDo {
    55  		c.Errorf("all functions not executed; want %d got %d", totalDo, nbRuns)
    56  	}
    57  	c.Check(err, gc.IsNil)
    58  	if maxConcurrentRunners != maxConcurrentRunnersPar {
    59  		c.Errorf("wrong number of do's ran at once; want %d got %d", maxConcurrentRunnersPar, maxConcurrentRunners)
    60  	}
    61  }
    62  
    63  type intError int
    64  
    65  func (intError) Error() string {
    66  	return "error"
    67  }
    68  
    69  func (*parallelSuite) TestParallelError(c *gc.C) {
    70  	const (
    71  		totalDo = 10
    72  		errDo   = 5
    73  	)
    74  	parallelRun := parallel.NewRun(6)
    75  	for i := 0; i < totalDo; i++ {
    76  		i := i
    77  		if i >= errDo {
    78  			parallelRun.Do(func() error {
    79  				return intError(i)
    80  			})
    81  		} else {
    82  			parallelRun.Do(func() error {
    83  				return nil
    84  			})
    85  		}
    86  	}
    87  	err := parallelRun.Wait()
    88  	c.Check(err, gc.NotNil)
    89  	errs := err.(parallel.Errors)
    90  	c.Check(len(errs), gc.Equals, totalDo-errDo)
    91  	ints := make([]int, len(errs))
    92  	for i, err := range errs {
    93  		ints[i] = int(err.(intError))
    94  	}
    95  	sort.Ints(ints)
    96  	for i, n := range ints {
    97  		c.Check(n, gc.Equals, i+errDo)
    98  	}
    99  }
   100  
   101  func (*parallelSuite) TestZeroWorkerPanics(c *gc.C) {
   102  	defer func() {
   103  		r := recover()
   104  		c.Check(r, gc.Matches, "parameter maxParallel must be >= 1")
   105  	}()
   106  	parallel.NewRun(0)
   107  }