...

Source file src/github.com/docker/distribution/registry/storage/driver/base/regulator_test.go

Documentation: github.com/docker/distribution/registry/storage/driver/base

     1  package base
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  	"testing"
     7  	"time"
     8  )
     9  
    10  func TestRegulatorEnterExit(t *testing.T) {
    11  	const limit = 500
    12  
    13  	r := NewRegulator(nil, limit).(*regulator)
    14  
    15  	for try := 0; try < 50; try++ {
    16  		run := make(chan struct{})
    17  
    18  		var firstGroupReady sync.WaitGroup
    19  		var firstGroupDone sync.WaitGroup
    20  		firstGroupReady.Add(limit)
    21  		firstGroupDone.Add(limit)
    22  		for i := 0; i < limit; i++ {
    23  			go func() {
    24  				r.enter()
    25  				firstGroupReady.Done()
    26  				<-run
    27  				r.exit()
    28  				firstGroupDone.Done()
    29  			}()
    30  		}
    31  		firstGroupReady.Wait()
    32  
    33  		// now we exhausted all the limit, let's run a little bit more
    34  		var secondGroupReady sync.WaitGroup
    35  		var secondGroupDone sync.WaitGroup
    36  		for i := 0; i < 50; i++ {
    37  			secondGroupReady.Add(1)
    38  			secondGroupDone.Add(1)
    39  			go func() {
    40  				secondGroupReady.Done()
    41  				r.enter()
    42  				r.exit()
    43  				secondGroupDone.Done()
    44  			}()
    45  		}
    46  		secondGroupReady.Wait()
    47  
    48  		// allow the first group to return resources
    49  		close(run)
    50  
    51  		done := make(chan struct{})
    52  		go func() {
    53  			secondGroupDone.Wait()
    54  			close(done)
    55  		}()
    56  		select {
    57  		case <-done:
    58  		case <-time.After(5 * time.Second):
    59  			t.Fatal("some r.enter() are still locked")
    60  		}
    61  
    62  		firstGroupDone.Wait()
    63  
    64  		if r.available != limit {
    65  			t.Fatalf("r.available: got %d, want %d", r.available, limit)
    66  		}
    67  	}
    68  }
    69  
    70  func TestGetLimitFromParameter(t *testing.T) {
    71  	tests := []struct {
    72  		Input    interface{}
    73  		Expected uint64
    74  		Min      uint64
    75  		Default  uint64
    76  		Err      error
    77  	}{
    78  		{"foo", 0, 5, 5, fmt.Errorf("parameter must be an integer, 'foo' invalid")},
    79  		{"50", 50, 5, 5, nil},
    80  		{"5", 25, 25, 50, nil}, // lower than Min returns Min
    81  		{nil, 50, 25, 50, nil}, // nil returns default
    82  		{812, 812, 25, 50, nil},
    83  	}
    84  
    85  	for _, item := range tests {
    86  		t.Run(fmt.Sprint(item.Input), func(t *testing.T) {
    87  			actual, err := GetLimitFromParameter(item.Input, item.Min, item.Default)
    88  
    89  			if err != nil && item.Err != nil && err.Error() != item.Err.Error() {
    90  				t.Fatalf("GetLimitFromParameter error, expected %#v got %#v", item.Err, err)
    91  			}
    92  
    93  			if actual != item.Expected {
    94  				t.Fatalf("GetLimitFromParameter result error, expected %d got %d", item.Expected, actual)
    95  			}
    96  		})
    97  	}
    98  }
    99  

View as plain text