github.com/filecoin-project/bacalhau@v0.3.23-0.20230228154132-45c989550ace/pkg/test/devstack/timeout_test.go (about) 1 //go:build integration 2 3 package devstack 4 5 import ( 6 "context" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/filecoin-project/bacalhau/pkg/devstack" 12 "github.com/filecoin-project/bacalhau/pkg/executor" 13 "github.com/filecoin-project/bacalhau/pkg/executor/noop" 14 "github.com/filecoin-project/bacalhau/pkg/job" 15 _ "github.com/filecoin-project/bacalhau/pkg/logger" 16 "github.com/filecoin-project/bacalhau/pkg/model" 17 "github.com/filecoin-project/bacalhau/pkg/node" 18 "github.com/filecoin-project/bacalhau/pkg/system" 19 "github.com/filecoin-project/bacalhau/pkg/test/scenario" 20 "github.com/stretchr/testify/suite" 21 ) 22 23 type DevstackTimeoutSuite struct { 24 scenario.ScenarioRunner 25 } 26 27 func TestDevstackTimeoutSuite(t *testing.T) { 28 suite.Run(t, new(DevstackTimeoutSuite)) 29 } 30 31 func (suite *DevstackTimeoutSuite) TestRunningTimeout() { 32 type TestCase struct { 33 name string 34 nodeCount int 35 minBids int 36 concurrency int 37 computeJobNegotiationTimeout time.Duration 38 computeJobExecutionBypassList []string 39 computeMinJobExecutionTimeout time.Duration 40 computeMaxJobExecutionTimeout time.Duration 41 requesterMinJobExecutionTimeout time.Duration 42 requesterDefaultJobExecutionTimeout time.Duration 43 jobTimeout time.Duration 44 sleepTime time.Duration 45 completedCount int 46 rejectedCount int // when no bids are received 47 errorCount int // when execution takes too long 48 } 49 50 runTest := func(testCase TestCase) { 51 testScenario := scenario.Scenario{ 52 Stack: &scenario.StackConfig{ 53 DevStackOptions: &devstack.DevStackOptions{NumberOfHybridNodes: testCase.nodeCount}, 54 ComputeConfig: node.NewComputeConfigWith(node.ComputeConfigParams{ 55 JobNegotiationTimeout: testCase.computeJobNegotiationTimeout, 56 MinJobExecutionTimeout: testCase.computeMinJobExecutionTimeout, 57 MaxJobExecutionTimeout: testCase.computeMaxJobExecutionTimeout, 58 JobExecutionTimeoutClientIDBypassList: testCase.computeJobExecutionBypassList, 59 }), 60 RequesterConfig: node.NewRequesterConfigWith(node.RequesterConfigParams{ 61 MinJobExecutionTimeout: testCase.requesterMinJobExecutionTimeout, 62 DefaultJobExecutionTimeout: testCase.requesterDefaultJobExecutionTimeout, 63 HousekeepingBackgroundTaskInterval: 1 * time.Second, 64 }), 65 ExecutorConfig: noop.ExecutorConfig{ 66 ExternalHooks: noop.ExecutorConfigExternalHooks{ 67 JobHandler: func(ctx context.Context, shard model.JobShard, resultsDir string) (*model.RunCommandResult, error) { 68 time.Sleep(testCase.sleepTime) 69 return executor.WriteJobResults(resultsDir, strings.NewReader(""), strings.NewReader(""), 0, nil) 70 }, 71 }, 72 }, 73 }, 74 Spec: model.Spec{ 75 Engine: model.EngineNoop, 76 Verifier: model.VerifierNoop, 77 Publisher: model.PublisherNoop, 78 Timeout: testCase.jobTimeout.Seconds(), 79 }, 80 Deal: model.Deal{ 81 Concurrency: testCase.concurrency, 82 MinBids: testCase.minBids, 83 }, 84 JobCheckers: []job.CheckStatesFunction{ 85 job.WaitForExecutionStates(map[model.ExecutionStateType]int{ 86 model.ExecutionStateCompleted: testCase.completedCount, 87 model.ExecutionStateFailed: testCase.errorCount, 88 model.ExecutionStateAskForBidRejected: testCase.rejectedCount, 89 }), 90 }, 91 } 92 93 suite.RunScenario(testScenario) 94 } 95 96 for _, testCase := range []TestCase{ 97 { 98 name: "sleep_within_default_timeout", 99 computeJobNegotiationTimeout: 10 * time.Second, 100 computeMinJobExecutionTimeout: 0 * time.Nanosecond, 101 computeMaxJobExecutionTimeout: 1 * time.Minute, 102 requesterDefaultJobExecutionTimeout: 10 * time.Second, 103 requesterMinJobExecutionTimeout: 1 * time.Nanosecond, 104 nodeCount: 1, 105 minBids: 1, 106 concurrency: 1, 107 sleepTime: 100 * time.Millisecond, 108 completedCount: 1, 109 }, 110 { 111 name: "sleep_within_defined_timeout", 112 computeJobNegotiationTimeout: 10 * time.Second, 113 computeMinJobExecutionTimeout: 1 * time.Nanosecond, 114 computeMaxJobExecutionTimeout: 1 * time.Minute, 115 requesterDefaultJobExecutionTimeout: 20 * time.Second, 116 requesterMinJobExecutionTimeout: 1 * time.Nanosecond, 117 nodeCount: 1, 118 minBids: 1, 119 concurrency: 1, 120 jobTimeout: 10 * time.Second, 121 sleepTime: 100 * time.Millisecond, 122 completedCount: 1, 123 }, 124 { 125 name: "sleep_longer_than_default_running_timeout", 126 computeJobNegotiationTimeout: 10 * time.Second, 127 computeMinJobExecutionTimeout: 1 * time.Nanosecond, 128 computeMaxJobExecutionTimeout: 1 * time.Minute, 129 requesterDefaultJobExecutionTimeout: 1 * time.Millisecond, 130 requesterMinJobExecutionTimeout: 1 * time.Nanosecond, 131 nodeCount: 1, 132 minBids: 1, 133 concurrency: 1, 134 sleepTime: 20 * time.Second, 135 errorCount: 1, 136 }, 137 { 138 name: "sleep_longer_than_defined_running_timeout", 139 computeJobNegotiationTimeout: 10 * time.Second, 140 computeMinJobExecutionTimeout: 1 * time.Nanosecond, 141 computeMaxJobExecutionTimeout: 1 * time.Minute, 142 requesterDefaultJobExecutionTimeout: 40 * time.Second, 143 requesterMinJobExecutionTimeout: 1 * time.Nanosecond, 144 nodeCount: 1, 145 minBids: 1, 146 concurrency: 1, 147 sleepTime: 20 * time.Second, 148 jobTimeout: 1 * time.Millisecond, 149 errorCount: 1, 150 }, 151 { 152 // no bid will be submitted, so the requester node should time out 153 name: "job_timeout_longer_than_max_running_timeout", 154 computeJobNegotiationTimeout: 10 * time.Second, 155 computeMinJobExecutionTimeout: 1 * time.Nanosecond, 156 computeMaxJobExecutionTimeout: 1 * time.Minute, 157 requesterDefaultJobExecutionTimeout: 40 * time.Second, 158 requesterMinJobExecutionTimeout: 1 * time.Nanosecond, 159 nodeCount: 1, 160 minBids: 1, 161 concurrency: 1, 162 sleepTime: 20 * time.Second, 163 jobTimeout: 2 * time.Minute, 164 rejectedCount: 1, 165 }, 166 { 167 // no bid will be submitted, so the requester node should time out 168 name: "job_timeout_less_than_min_running_timeout", 169 computeJobNegotiationTimeout: 10 * time.Second, 170 computeMinJobExecutionTimeout: 5 * time.Minute, 171 computeMaxJobExecutionTimeout: 10 * time.Minute, 172 requesterDefaultJobExecutionTimeout: 40 * time.Second, 173 requesterMinJobExecutionTimeout: 1 * time.Nanosecond, 174 nodeCount: 1, 175 minBids: 1, 176 concurrency: 1, 177 sleepTime: 20 * time.Second, 178 jobTimeout: 2 * time.Minute, 179 rejectedCount: 1, 180 }, 181 { 182 name: "job_timeout_greater_than_max", 183 computeJobNegotiationTimeout: 10 * time.Second, 184 computeMinJobExecutionTimeout: 1 * time.Nanosecond, 185 computeMaxJobExecutionTimeout: 1 * time.Minute, 186 requesterDefaultJobExecutionTimeout: 40 * time.Second, 187 requesterMinJobExecutionTimeout: 1 * time.Nanosecond, 188 nodeCount: 1, 189 minBids: 1, 190 concurrency: 1, 191 sleepTime: 1 * time.Second, 192 jobTimeout: 2 * time.Minute, 193 rejectedCount: 1, 194 }, 195 { 196 name: "job_timeout_greater_than_max_but_on_allowed_list", 197 computeJobExecutionBypassList: []string{system.GetClientID()}, 198 computeJobNegotiationTimeout: 10 * time.Second, 199 computeMinJobExecutionTimeout: 1 * time.Nanosecond, 200 computeMaxJobExecutionTimeout: 1 * time.Minute, 201 requesterDefaultJobExecutionTimeout: 40 * time.Second, 202 requesterMinJobExecutionTimeout: 1 * time.Nanosecond, 203 nodeCount: 1, 204 minBids: 1, 205 concurrency: 1, 206 sleepTime: 1 * time.Second, 207 jobTimeout: 2 * time.Minute, 208 completedCount: 1, 209 }, 210 } { 211 suite.Run(testCase.name, func() { 212 runTest(testCase) 213 }) 214 } 215 }