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  }