gitlab.com/jfprevost/gitlab-runner-notlscheck@v11.11.4+incompatible/commands/multi_test.go (about) 1 package commands 2 3 import ( 4 "sync" 5 "sync/atomic" 6 "testing" 7 "time" 8 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/mock" 11 "gitlab.com/gitlab-org/gitlab-runner/common" 12 ) 13 14 func TestProcessRunner_BuildLimit(t *testing.T) { 15 cfg := common.RunnerConfig{ 16 Limit: 2, 17 RequestConcurrency: 10, 18 RunnerSettings: common.RunnerSettings{ 19 Executor: "multi-runner-build-limit", 20 }, 21 } 22 23 jobData := common.JobResponse{ 24 ID: 1, 25 Steps: []common.Step{ 26 { 27 Name: "sleep", 28 Script: common.StepScript{"sleep 10"}, 29 Timeout: 15, 30 When: "", 31 AllowFailure: false, 32 }, 33 }, 34 } 35 36 mJobTrace := common.MockJobTrace{} 37 defer mJobTrace.AssertExpectations(t) 38 mJobTrace.On("SetFailuresCollector", mock.Anything) 39 mJobTrace.On("Write", mock.Anything).Return(0, nil) 40 mJobTrace.On("IsStdout").Return(false) 41 mJobTrace.On("SetCancelFunc", mock.Anything) 42 mJobTrace.On("SetMasked", mock.Anything) 43 mJobTrace.On("Success") 44 mJobTrace.On("Fail", mock.Anything, mock.Anything) 45 46 mNetwork := common.MockNetwork{} 47 defer mNetwork.AssertExpectations(t) 48 mNetwork.On("RequestJob", mock.Anything, mock.Anything).Return(&jobData, true) 49 mNetwork.On("ProcessJob", mock.Anything, mock.Anything).Return(&mJobTrace) 50 51 var runningBuilds uint32 52 e := common.MockExecutor{} 53 defer e.AssertExpectations(t) 54 e.On("Prepare", mock.Anything, mock.Anything, mock.Anything).Return(nil) 55 e.On("Cleanup").Maybe().Return() 56 e.On("Shell").Return(&common.ShellScriptInfo{Shell: "script-shell"}) 57 e.On("Finish", mock.Anything).Return(nil).Maybe() 58 e.On("Run", mock.Anything).Run(func(args mock.Arguments) { 59 atomic.AddUint32(&runningBuilds, 1) 60 61 // Simulate work to fill up build queue. 62 time.Sleep(1 * time.Second) 63 }).Return(nil) 64 65 p := common.MockExecutorProvider{} 66 defer p.AssertExpectations(t) 67 p.On("Acquire", mock.Anything).Return(nil, nil) 68 p.On("Release", mock.Anything, mock.Anything).Return(nil).Maybe() 69 p.On("CanCreate").Return(true).Once() 70 p.On("GetDefaultShell").Return("bash").Once() 71 p.On("GetFeatures", mock.Anything).Return(nil) 72 p.On("Create").Return(&e) 73 74 common.RegisterExecutor("multi-runner-build-limit", &p) 75 76 cmd := RunCommand{ 77 network: &mNetwork, 78 buildsHelper: newBuildsHelper(), 79 configOptionsWithListenAddress: configOptionsWithListenAddress{ 80 configOptions: configOptions{ 81 config: &common.Config{ 82 User: "git", 83 }, 84 }, 85 }, 86 } 87 88 runners := make(chan *common.RunnerConfig) 89 90 // Start 5 builds. 91 wg := sync.WaitGroup{} 92 wg.Add(5) 93 for i := 0; i < 5; i++ { 94 go func(i int) { 95 defer wg.Done() 96 97 cmd.processRunner(i, &cfg, runners) 98 }(i) 99 } 100 101 // Wait until at least two builds have started. 102 for atomic.LoadUint32(&runningBuilds) < 2 { 103 time.Sleep(10 * time.Millisecond) 104 } 105 106 err := cmd.processRunner(6, &cfg, runners) 107 assert.EqualError(t, err, "failed to request job, runner limit met") 108 109 // Wait for all builds to finish. 110 wg.Wait() 111 }