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