Skip to content

Commit 03e5642

Browse files
committed
Add timeout configuration support
1 parent ddca10c commit 03e5642

File tree

8 files changed

+50
-20
lines changed

8 files changed

+50
-20
lines changed

op-acceptor/config.go

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type Config struct {
2020
RunInterval time.Duration // Interval between test runs
2121
RunOnce bool // Indicates if the service should exit after one test run
2222
AllowSkips bool // Allow tests to be skipped instead of failing when preconditions are not met
23+
DefaultTimeout time.Duration // Default timeout for individual tests, can be overriden by test config
2324

2425
Log log.Logger
2526
}
@@ -53,6 +54,8 @@ func NewConfig(ctx *cli.Context, log log.Logger, testDir string, validatorConfig
5354
runInterval := ctx.Duration(flags.RunInterval.Name)
5455
runOnce := runInterval == 0
5556

57+
defaultTimeout := ctx.Duration(flags.DefaultTimeout.Name)
58+
5659
return &Config{
5760
TestDir: absTestDir,
5861
ValidatorConfig: absValidatorConfig,
@@ -62,5 +65,6 @@ func NewConfig(ctx *cli.Context, log log.Logger, testDir string, validatorConfig
6265
RunOnce: runOnce,
6366
AllowSkips: ctx.Bool(flags.AllowSkips.Name),
6467
Log: log,
68+
DefaultTimeout: defaultTimeout,
6569
}, nil
6670
}

op-acceptor/flags/flags.go

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package flags
22

33
import (
44
"fmt"
5+
"time"
56

67
"github.com/urfave/cli/v2"
78

@@ -53,6 +54,12 @@ var (
5354
EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "ALLOW_SKIPS"),
5455
Usage: "Allow tests to be skipped instead of failing when preconditions are not met.",
5556
}
57+
DefaultTimeout = &cli.DurationFlag{
58+
Name: "default-timeout",
59+
Value: 5 * time.Minute,
60+
EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "DEFAULT_TIMEOUT"),
61+
Usage: "Default timeout of an individual test (e.g. '30s', '5m', etc.). This setting is superseded by test or suite level timeout configuration. Set to '0' to disable any default timeout. Defaults to '5m'.",
62+
}
5663
)
5764

5865
var requiredFlags = []cli.Flag{
@@ -65,6 +72,7 @@ var optionalFlags = []cli.Flag{
6572
GoBinary,
6673
RunInterval,
6774
AllowSkips,
75+
DefaultTimeout,
6876
}
6977
var Flags []cli.Flag
7078

op-acceptor/nat.go

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ func New(ctx context.Context, config *Config, version string, shutdownCallback f
4848
reg, err := registry.NewRegistry(registry.Config{
4949
Log: config.Log,
5050
ValidatorConfigFile: config.ValidatorConfig,
51+
DefaultTimeout: config.DefaultTimeout,
5152
})
5253
if err != nil {
5354
return nil, fmt.Errorf("failed to create registry: %w", err)

op-acceptor/registry/registry.go

+12
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"os"
66
"sync"
7+
"time"
78

89
"github.com/ethereum-optimism/infra/op-acceptor/types"
910
"github.com/ethereum/go-ethereum/log"
@@ -21,6 +22,7 @@ type Registry struct {
2122
type Config struct {
2223
Log log.Logger
2324
ValidatorConfigFile string
25+
DefaultTimeout time.Duration
2426
}
2527

2628
// NewRegistry creates a new registry instance
@@ -200,6 +202,14 @@ func (r *Registry) discoverTestsInConfig(configs []types.TestConfig, gateID stri
200202
var tests []types.ValidatorMetadata
201203

202204
for _, cfg := range configs {
205+
206+
var timeout time.Duration
207+
if cfg.Timeout != nil {
208+
timeout = *cfg.Timeout
209+
} else {
210+
timeout = r.config.DefaultTimeout
211+
}
212+
203213
// If only package is specified (no name), treat it as "run all"
204214
if cfg.Name == "" {
205215
tests = append(tests, types.ValidatorMetadata{
@@ -209,6 +219,7 @@ func (r *Registry) discoverTestsInConfig(configs []types.TestConfig, gateID stri
209219
Package: cfg.Package,
210220
RunAll: true,
211221
Type: types.ValidatorTypeTest,
222+
Timeout: timeout,
212223
})
213224
continue
214225
}
@@ -221,6 +232,7 @@ func (r *Registry) discoverTestsInConfig(configs []types.TestConfig, gateID stri
221232
FuncName: cfg.Name,
222233
Package: cfg.Package,
223234
Type: types.ValidatorTypeTest,
235+
Timeout: timeout,
224236
})
225237
}
226238

op-acceptor/runner/runner.go

+18-15
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,17 @@ type runner struct {
7272
workDir string // Directory for running tests
7373
log log.Logger
7474
runID string
75-
timeout time.Duration // Test timeout
76-
goBinary string // Path to the Go binary
77-
allowSkips bool // Whether to allow skipping tests when preconditions are not met
75+
goBinary string // Path to the Go binary
76+
allowSkips bool // Whether to allow skipping tests when preconditions are not met
7877
}
7978

8079
type Config struct {
8180
Registry *registry.Registry
8281
TargetGate string
8382
WorkDir string
8483
Log log.Logger
85-
Timeout time.Duration // Test timeout
86-
GoBinary string // path to the Go binary
87-
AllowSkips bool // Whether to allow skipping tests when preconditions are not met
84+
GoBinary string // path to the Go binary
85+
AllowSkips bool // Whether to allow skipping tests when preconditions are not met
8886
}
8987

9088
// NewTestRunner creates a new test runner instance
@@ -111,10 +109,6 @@ func NewTestRunner(cfg Config) (TestRunner, error) {
111109
return nil, fmt.Errorf("no validators found")
112110
}
113111

114-
if cfg.Timeout == 0 {
115-
cfg.Timeout = 5 * time.Minute // Default timeout
116-
}
117-
118112
if cfg.GoBinary == "" {
119113
cfg.GoBinary = "go" // Default to "go" if not specified
120114
}
@@ -124,7 +118,6 @@ func NewTestRunner(cfg Config) (TestRunner, error) {
124118
validators: validators,
125119
workDir: cfg.WorkDir,
126120
log: cfg.Log,
127-
timeout: cfg.Timeout,
128121
goBinary: cfg.GoBinary,
129122
allowSkips: cfg.AllowSkips,
130123
}, nil
@@ -504,8 +497,13 @@ type TestEvent struct {
504497

505498
// runSingleTest runs a specific test
506499
func (r *runner) runSingleTest(metadata types.ValidatorMetadata) (*types.TestResult, error) {
507-
ctx, cancel := context.WithTimeout(context.Background(), r.timeout)
508-
defer cancel()
500+
501+
ctx := context.Background()
502+
if metadata.Timeout != 0 {
503+
var cancel func()
504+
ctx, cancel = context.WithTimeout(ctx, metadata.Timeout)
505+
defer cancel()
506+
}
509507

510508
args := r.buildTestArgs(metadata)
511509
cmd := exec.CommandContext(ctx, r.goBinary, args...)
@@ -528,7 +526,7 @@ func (r *runner) runSingleTest(metadata types.ValidatorMetadata) (*types.TestRes
528526
"package", metadata.Package,
529527
"test", metadata.FuncName,
530528
"command", cmd.String(),
531-
"timeout", r.timeout,
529+
"timeout", metadata.Timeout,
532530
"allowSkips", r.allowSkips)
533531

534532
// Run the command
@@ -539,7 +537,7 @@ func (r *runner) runSingleTest(metadata types.ValidatorMetadata) (*types.TestRes
539537
return &types.TestResult{
540538
Metadata: metadata,
541539
Status: types.TestStatusFail,
542-
Error: fmt.Errorf("test timed out after %v", r.timeout),
540+
Error: fmt.Errorf("test timed out after %v", metadata.Timeout),
543541
}, nil
544542
}
545543

@@ -763,6 +761,11 @@ func (r *runner) buildTestArgs(metadata types.ValidatorMetadata) []string {
763761
// Always disable caching
764762
args = append(args, "-count", "1")
765763

764+
// Add timeout if it's not 0
765+
if metadata.Timeout != 0 {
766+
args = append(args, "-timeout", metadata.Timeout.String())
767+
}
768+
766769
// Always use verbose output
767770
args = append(args, "-v")
768771

op-acceptor/runner/runner_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,9 @@ func TestBuildTestArgs(t *testing.T) {
177177
metadata: types.ValidatorMetadata{
178178
FuncName: "TestFoo",
179179
Package: "pkg/foo",
180+
Timeout: 10 * time.Second,
180181
},
181-
want: []string{"test", "pkg/foo", "-run", "^TestFoo$", "-count", "1", "-v", "-json"},
182+
want: []string{"test", "pkg/foo", "-run", "^TestFoo$", "-count", "1", "-timeout", "10s", "-v", "-json"},
182183
},
183184
{
184185
name: "run all in package",

op-acceptor/types/test.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ type TestResult struct {
2727

2828
// TestConfig represents a test configuration
2929
type TestConfig struct {
30-
Name string `yaml:"name,omitempty"`
31-
Package string `yaml:"package"`
32-
RunAll bool `yaml:"run_all,omitempty"`
30+
Name string `yaml:"name,omitempty"`
31+
Package string `yaml:"package"`
32+
RunAll bool `yaml:"run_all,omitempty"`
33+
Timeout *time.Duration `yaml:"timeout,omitempty"`
3334
}
3435

3536
// GetTestDisplayName returns a formatted display name for a test based on its name and metadata

op-acceptor/types/validator.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type ValidatorMetadata struct {
3333
Suite string
3434
FuncName string
3535
Package string
36-
Timeout string
36+
Timeout time.Duration
3737
RunAll bool
3838
}
3939

0 commit comments

Comments
 (0)