diff --git a/pkg/beholder/client.go b/pkg/beholder/client.go index 03d3e65ad..289eb5938 100644 --- a/pkg/beholder/client.go +++ b/pkg/beholder/client.go @@ -120,6 +120,15 @@ func newGRPCClient(cfg Config, otlploggrpcNew otlploggrpcFactory) (*Client, erro if cfg.LogExportTimeout > 0 { batchProcessorOpts = append(batchProcessorOpts, sdklog.WithExportTimeout(cfg.LogExportTimeout)) // Default is 30s } + if cfg.LogExportMaxBatchSize > 0 { + batchProcessorOpts = append(batchProcessorOpts, sdklog.WithExportMaxBatchSize(cfg.LogExportMaxBatchSize)) // Default is 512, must be <= maxQueueSize + } + if cfg.LogExportInterval > 0 { + batchProcessorOpts = append(batchProcessorOpts, sdklog.WithExportInterval(cfg.LogExportInterval)) // Default is 1s + } + if cfg.LogMaxQueueSize > 0 { + batchProcessorOpts = append(batchProcessorOpts, sdklog.WithMaxQueueSize(cfg.LogMaxQueueSize)) // Default is 2048 + } loggerProcessor = sdklog.NewBatchProcessor( sharedLogExporter, batchProcessorOpts..., @@ -164,6 +173,15 @@ func newGRPCClient(cfg Config, otlploggrpcNew otlploggrpcFactory) (*Client, erro if cfg.EmitterExportTimeout > 0 { batchProcessorOpts = append(batchProcessorOpts, sdklog.WithExportTimeout(cfg.EmitterExportTimeout)) // Default is 30s } + if cfg.EmitterExportMaxBatchSize > 0 { + batchProcessorOpts = append(batchProcessorOpts, sdklog.WithExportMaxBatchSize(cfg.EmitterExportMaxBatchSize)) // Default is 512, must be <= maxQueueSize + } + if cfg.EmitterExportInterval > 0 { + batchProcessorOpts = append(batchProcessorOpts, sdklog.WithExportInterval(cfg.EmitterExportInterval)) // Default is 1s + } + if cfg.EmitterMaxQueueSize > 0 { + batchProcessorOpts = append(batchProcessorOpts, sdklog.WithMaxQueueSize(cfg.EmitterMaxQueueSize)) // Default is 2048 + } messageLogProcessor = sdklog.NewBatchProcessor( sharedLogExporter, batchProcessorOpts..., @@ -374,7 +392,6 @@ func newMeterProvider(config Config, resource *sdkresource.Resource, creds crede if err != nil { return nil, err } - mp := sdkmetric.NewMeterProvider( sdkmetric.WithReader( sdkmetric.NewPeriodicReader( diff --git a/pkg/beholder/config.go b/pkg/beholder/config.go index f424465ae..5ce58e2b3 100644 --- a/pkg/beholder/config.go +++ b/pkg/beholder/config.go @@ -17,24 +17,29 @@ type Config struct { // OTel Resource ResourceAttributes []otelattr.KeyValue // Message Emitter - EmitterExportTimeout time.Duration - // Batch processing is enabled by default - // Disable it only for testing - EmitterBatchProcessor bool + EmitterExportTimeout time.Duration + EmitterExportInterval time.Duration + EmitterExportMaxBatchSize int + EmitterMaxQueueSize int + EmitterBatchProcessor bool // Enabled by default. Disable only for testing. + // OTel Trace TraceSampleRatio float64 TraceBatchTimeout time.Duration TraceSpanExporter sdktrace.SpanExporter // optional additional exporter TraceRetryConfig *RetryConfig + // OTel Metric MetricReaderInterval time.Duration MetricRetryConfig *RetryConfig MetricViews []sdkmetric.View + // OTel Log - LogExportTimeout time.Duration - // Batch processing is enabled by default - // Disable it only for testing - LogBatchProcessor bool + LogExportTimeout time.Duration + LogExportInterval time.Duration + LogExportMaxBatchSize int + LogMaxQueueSize int + LogBatchProcessor bool // Enabled by default. Disable only for testing. // Retry config for shared log exporter, used by Emitter and Logger LogRetryConfig *RetryConfig @@ -82,8 +87,11 @@ func DefaultConfig() Config { // Resource ResourceAttributes: defaultOtelAttributes, // Message Emitter - EmitterExportTimeout: 1 * time.Second, - EmitterBatchProcessor: true, + EmitterExportTimeout: 30 * time.Second, + EmitterExportMaxBatchSize: 512, + EmitterExportInterval: 1 * time.Second, + EmitterMaxQueueSize: 2048, + EmitterBatchProcessor: true, // OTel message log exporter retry config LogRetryConfig: defaultRetryConfig.Copy(), // Trace @@ -96,8 +104,11 @@ func DefaultConfig() Config { // OTel metric exporter retry config MetricRetryConfig: defaultRetryConfig.Copy(), // Log - LogExportTimeout: 1 * time.Second, - LogBatchProcessor: true, + LogExportTimeout: 30 * time.Second, + LogExportMaxBatchSize: 512, + LogExportInterval: 1 * time.Second, + LogMaxQueueSize: 2048, + LogBatchProcessor: true, } } diff --git a/pkg/beholder/config_test.go b/pkg/beholder/config_test.go index 0d130efd6..03a82f9db 100644 --- a/pkg/beholder/config_test.go +++ b/pkg/beholder/config_test.go @@ -25,8 +25,11 @@ func ExampleConfig() { otelattr.String("sender", "beholderclient"), }, // Message Emitter - EmitterExportTimeout: 1 * time.Second, - EmitterBatchProcessor: true, + EmitterExportTimeout: 1 * time.Second, + EmitterExportMaxBatchSize: 512, + EmitterExportInterval: 1 * time.Second, + EmitterMaxQueueSize: 2048, + EmitterBatchProcessor: true, // OTel message log exporter retry config LogRetryConfig: nil, // Trace @@ -39,8 +42,11 @@ func ExampleConfig() { // OTel metric exporter retry config MetricRetryConfig: nil, // Log - LogExportTimeout: 1 * time.Second, - LogBatchProcessor: true, + LogExportTimeout: 1 * time.Second, + LogExportMaxBatchSize: 512, + LogExportInterval: 1 * time.Second, + LogMaxQueueSize: 2048, + LogBatchProcessor: true, } fmt.Printf("%+v\n", config) config.LogRetryConfig = &beholder.RetryConfig{ @@ -50,6 +56,6 @@ func ExampleConfig() { } fmt.Printf("%+v\n", *config.LogRetryConfig) // Output: - // {InsecureConnection:true CACertFile: OtelExporterGRPCEndpoint:localhost:4317 OtelExporterHTTPEndpoint:localhost:4318 ResourceAttributes:[{Key:package_name Value:{vtype:4 numeric:0 stringly:beholder slice:}} {Key:sender Value:{vtype:4 numeric:0 stringly:beholderclient slice:}}] EmitterExportTimeout:1s EmitterBatchProcessor:true TraceSampleRatio:1 TraceBatchTimeout:1s TraceSpanExporter: TraceRetryConfig: MetricReaderInterval:1s MetricRetryConfig: MetricViews:[] LogExportTimeout:1s LogBatchProcessor:true LogRetryConfig: AuthPublicKeyHex: AuthHeaders:map[] AuthHeaderProvider:} + // {InsecureConnection:true CACertFile: OtelExporterGRPCEndpoint:localhost:4317 OtelExporterHTTPEndpoint:localhost:4318 ResourceAttributes:[{Key:package_name Value:{vtype:4 numeric:0 stringly:beholder slice:}} {Key:sender Value:{vtype:4 numeric:0 stringly:beholderclient slice:}}] EmitterExportTimeout:1s EmitterExportInterval:1s EmitterExportMaxBatchSize:512 EmitterMaxQueueSize:2048 EmitterBatchProcessor:true TraceSampleRatio:1 TraceBatchTimeout:1s TraceSpanExporter: TraceRetryConfig: MetricReaderInterval:1s MetricRetryConfig: MetricViews:[] LogExportTimeout:1s LogExportInterval:1s LogExportMaxBatchSize:512 LogMaxQueueSize:2048 LogBatchProcessor:true LogRetryConfig: AuthPublicKeyHex: AuthHeaders:map[] AuthHeaderProvider:} // {InitialInterval:5s MaxInterval:30s MaxElapsedTime:1m0s} } diff --git a/pkg/beholder/httpclient.go b/pkg/beholder/httpclient.go index 0df44e647..7427af5d8 100644 --- a/pkg/beholder/httpclient.go +++ b/pkg/beholder/httpclient.go @@ -80,6 +80,16 @@ func newHTTPClient(cfg Config, otlploghttpNew otlploghttpFactory) (*Client, erro if cfg.LogExportTimeout > 0 { batchProcessorOpts = append(batchProcessorOpts, sdklog.WithExportTimeout(cfg.LogExportTimeout)) // Default is 30s } + if cfg.LogExportMaxBatchSize > 0 { + + batchProcessorOpts = append(batchProcessorOpts, sdklog.WithExportMaxBatchSize(cfg.LogExportMaxBatchSize)) // Default is 512, must be <= maxQueueSize + } + if cfg.LogExportInterval > 0 { + batchProcessorOpts = append(batchProcessorOpts, sdklog.WithExportInterval(cfg.LogExportInterval)) // Default is 1s + } + if cfg.LogMaxQueueSize > 0 { + batchProcessorOpts = append(batchProcessorOpts, sdklog.WithMaxQueueSize(cfg.LogMaxQueueSize)) // Default is 2048 + } loggerProcessor = sdklog.NewBatchProcessor( sharedLogExporter, batchProcessorOpts..., @@ -124,9 +134,18 @@ func newHTTPClient(cfg Config, otlploghttpNew otlploghttpFactory) (*Client, erro if cfg.EmitterExportTimeout > 0 { batchProcessorOpts = append(batchProcessorOpts, sdklog.WithExportTimeout(cfg.EmitterExportTimeout)) // Default is 30s } + if cfg.EmitterExportMaxBatchSize > 0 { + batchProcessorOpts = append(batchProcessorOpts, sdklog.WithExportMaxBatchSize(cfg.EmitterExportMaxBatchSize)) // Default is 512, must be <= maxQueueSize + } + if cfg.EmitterExportInterval > 0 { + batchProcessorOpts = append(batchProcessorOpts, sdklog.WithExportInterval(cfg.EmitterExportInterval)) // Default is 1s + } + if cfg.EmitterMaxQueueSize > 0 { + batchProcessorOpts = append(batchProcessorOpts, sdklog.WithMaxQueueSize(cfg.EmitterMaxQueueSize)) // Default is 2048 + } messageLogProcessor = sdklog.NewBatchProcessor( sharedLogExporter, - batchProcessorOpts..., // Default is 30s + batchProcessorOpts..., ) } else { messageLogProcessor = sdklog.NewSimpleProcessor(sharedLogExporter) diff --git a/pkg/loop/config.go b/pkg/loop/config.go index e63f72f2f..ea68cfa4a 100644 --- a/pkg/loop/config.go +++ b/pkg/loop/config.go @@ -21,16 +21,19 @@ const ( envTracingAttribute = "CL_TRACING_ATTRIBUTE_" envTracingTLSCertPath = "CL_TRACING_TLS_CERT_PATH" - envTelemetryEnabled = "CL_TELEMETRY_ENABLED" - envTelemetryEndpoint = "CL_TELEMETRY_ENDPOINT" - envTelemetryInsecureConn = "CL_TELEMETRY_INSECURE_CONNECTION" - envTelemetryCACertFile = "CL_TELEMETRY_CA_CERT_FILE" - envTelemetryAttribute = "CL_TELEMETRY_ATTRIBUTE_" - envTelemetryTraceSampleRatio = "CL_TELEMETRY_TRACE_SAMPLE_RATIO" - envTelemetryAuthHeader = "CL_TELEMETRY_AUTH_HEADER" - envTelemetryAuthPubKeyHex = "CL_TELEMETRY_AUTH_PUB_KEY_HEX" - envTelemetryEmitterBatchProcessor = "CL_TELEMETRY_EMITTER_BATCH_PROCESSOR" - envTelemetryEmitterExportTimeout = "CL_TELEMETRY_EMITTER_EXPORT_TIMEOUT" + envTelemetryEnabled = "CL_TELEMETRY_ENABLED" + envTelemetryEndpoint = "CL_TELEMETRY_ENDPOINT" + envTelemetryInsecureConn = "CL_TELEMETRY_INSECURE_CONNECTION" + envTelemetryCACertFile = "CL_TELEMETRY_CA_CERT_FILE" + envTelemetryAttribute = "CL_TELEMETRY_ATTRIBUTE_" + envTelemetryTraceSampleRatio = "CL_TELEMETRY_TRACE_SAMPLE_RATIO" + envTelemetryAuthHeader = "CL_TELEMETRY_AUTH_HEADER" + envTelemetryAuthPubKeyHex = "CL_TELEMETRY_AUTH_PUB_KEY_HEX" + envTelemetryEmitterBatchProcessor = "CL_TELEMETRY_EMITTER_BATCH_PROCESSOR" + envTelemetryEmitterExportTimeout = "CL_TELEMETRY_EMITTER_EXPORT_TIMEOUT" + envTelemetryEmitterExportInterval = "CL_TELEMETRY_EMITTER_EXPORT_INTERVAL" + envTelemetryEmitterExportMaxBatchSize = "CL_TELEMETRY_EMITTER_EXPORT_MAX_BATCH_SIZE" + envTelemetryEmitterMaxQueueSize = "CL_TELEMETRY_EMITTER_MAX_QUEUE_SIZE" ) // EnvConfig is the configuration between the application and the LOOP executable. The values @@ -46,16 +49,19 @@ type EnvConfig struct { TracingTLSCertPath string TracingAttributes map[string]string - TelemetryEnabled bool - TelemetryEndpoint string - TelemetryInsecureConnection bool - TelemetryCACertFile string - TelemetryAttributes OtelAttributes - TelemetryTraceSampleRatio float64 - TelemetryAuthHeaders map[string]string - TelemetryAuthPubKeyHex string - TelemetryEmitterBatchProcessor bool - TelemetryEmitterExportTimeout time.Duration + TelemetryEnabled bool + TelemetryEndpoint string + TelemetryInsecureConnection bool + TelemetryCACertFile string + TelemetryAttributes OtelAttributes + TelemetryTraceSampleRatio float64 + TelemetryAuthHeaders map[string]string + TelemetryAuthPubKeyHex string + TelemetryEmitterBatchProcessor bool + TelemetryEmitterExportTimeout time.Duration + TelemetryEmitterExportInterval time.Duration + TelemetryEmitterExportMaxBatchSize int + TelemetryEmitterMaxQueueSize int } // AsCmdEnv returns a slice of environment variable key/value pairs for an exec.Cmd. @@ -93,7 +99,9 @@ func (e *EnvConfig) AsCmdEnv() (env []string) { add(envTelemetryAuthPubKeyHex, e.TelemetryAuthPubKeyHex) add(envTelemetryEmitterBatchProcessor, strconv.FormatBool(e.TelemetryEmitterBatchProcessor)) add(envTelemetryEmitterExportTimeout, e.TelemetryEmitterExportTimeout.String()) - + add(envTelemetryEmitterExportInterval, e.TelemetryEmitterExportInterval.String()) + add(envTelemetryEmitterExportMaxBatchSize, strconv.Itoa(e.TelemetryEmitterExportMaxBatchSize)) + add(envTelemetryEmitterMaxQueueSize, strconv.Itoa(e.TelemetryEmitterMaxQueueSize)) return } @@ -150,6 +158,18 @@ func (e *EnvConfig) parse() error { if err != nil { return fmt.Errorf("failed to parse %s: %w", envTelemetryEmitterExportTimeout, err) } + e.TelemetryEmitterExportInterval, err = time.ParseDuration(os.Getenv(envTelemetryEmitterExportInterval)) + if err != nil { + return fmt.Errorf("failed to parse %s: %w", envTelemetryEmitterExportInterval, err) + } + e.TelemetryEmitterExportMaxBatchSize, err = strconv.Atoi(os.Getenv(envTelemetryEmitterExportMaxBatchSize)) + if err != nil { + return fmt.Errorf("failed to parse %s: %w", envTelemetryEmitterExportMaxBatchSize, err) + } + e.TelemetryEmitterMaxQueueSize, err = strconv.Atoi(os.Getenv(envTelemetryEmitterMaxQueueSize)) + if err != nil { + return fmt.Errorf("failed to parse %s: %w", envTelemetryEmitterMaxQueueSize, err) + } } return nil } diff --git a/pkg/loop/config_test.go b/pkg/loop/config_test.go index 78d177aa4..f57eff666 100644 --- a/pkg/loop/config_test.go +++ b/pkg/loop/config_test.go @@ -19,25 +19,28 @@ import ( func TestEnvConfig_parse(t *testing.T) { cases := []struct { - name string - envVars map[string]string - expectError bool - expectedDatabaseURL string - expectedPrometheusPort int - expectedTracingEnabled bool - expectedTracingCollectorTarget string - expectedTracingSamplingRatio float64 - expectedTracingTLSCertPath string - expectedTelemetryEnabled bool - expectedTelemetryEndpoint string - expectedTelemetryInsecureConn bool - expectedTelemetryCACertFile string - expectedTelemetryAttributes OtelAttributes - expectedTelemetryTraceSampleRatio float64 - expectedTelemetryAuthHeaders map[string]string - expectedTelemetryAuthPubKeyHex string - expectedTelemetryEmitterBatchProcessor bool - expectedTelemetryEmitterExportTimeout time.Duration + name string + envVars map[string]string + expectError bool + expectedDatabaseURL string + expectedPrometheusPort int + expectedTracingEnabled bool + expectedTracingCollectorTarget string + expectedTracingSamplingRatio float64 + expectedTracingTLSCertPath string + expectedTelemetryEnabled bool + expectedTelemetryEndpoint string + expectedTelemetryInsecureConn bool + expectedTelemetryCACertFile string + expectedTelemetryAttributes OtelAttributes + expectedTelemetryTraceSampleRatio float64 + expectedTelemetryAuthHeaders map[string]string + expectedTelemetryAuthPubKeyHex string + expectedTelemetryEmitterBatchProcessor bool + expectedTelemetryEmitterExportTimeout time.Duration + expectedTelemetryEmitterExportInterval time.Duration + expectedTelemetryEmitterExportMaxBatchSize int + expectedTelemetryEmitterMaxQueueSize int }{ { name: "All variables set correctly", @@ -60,24 +63,30 @@ func TestEnvConfig_parse(t *testing.T) { envTelemetryAuthPubKeyHex: "pub-key-hex", envTelemetryEmitterBatchProcessor: "true", envTelemetryEmitterExportTimeout: "1s", + envTelemetryEmitterExportInterval: "2s", + envTelemetryEmitterExportMaxBatchSize: "100", + envTelemetryEmitterMaxQueueSize: "1000", }, - expectError: false, - expectedDatabaseURL: "postgres://user:password@localhost:5432/db", - expectedPrometheusPort: 8080, - expectedTracingEnabled: true, - expectedTracingCollectorTarget: "some:target", - expectedTracingSamplingRatio: 1.0, - expectedTracingTLSCertPath: "internal/test/fixtures/client.pem", - expectedTelemetryEnabled: true, - expectedTelemetryEndpoint: "example.com/beholder", - expectedTelemetryInsecureConn: true, - expectedTelemetryCACertFile: "foo/bar", - expectedTelemetryAttributes: OtelAttributes{"foo": "bar", "baz": "42"}, - expectedTelemetryTraceSampleRatio: 0.42, - expectedTelemetryAuthHeaders: map[string]string{"header-key": "header-value"}, - expectedTelemetryAuthPubKeyHex: "pub-key-hex", - expectedTelemetryEmitterBatchProcessor: true, - expectedTelemetryEmitterExportTimeout: 1 * time.Second, + expectError: false, + expectedDatabaseURL: "postgres://user:password@localhost:5432/db", + expectedPrometheusPort: 8080, + expectedTracingEnabled: true, + expectedTracingCollectorTarget: "some:target", + expectedTracingSamplingRatio: 1.0, + expectedTracingTLSCertPath: "internal/test/fixtures/client.pem", + expectedTelemetryEnabled: true, + expectedTelemetryEndpoint: "example.com/beholder", + expectedTelemetryInsecureConn: true, + expectedTelemetryCACertFile: "foo/bar", + expectedTelemetryAttributes: OtelAttributes{"foo": "bar", "baz": "42"}, + expectedTelemetryTraceSampleRatio: 0.42, + expectedTelemetryAuthHeaders: map[string]string{"header-key": "header-value"}, + expectedTelemetryAuthPubKeyHex: "pub-key-hex", + expectedTelemetryEmitterBatchProcessor: true, + expectedTelemetryEmitterExportTimeout: 1 * time.Second, + expectedTelemetryEmitterExportInterval: 2 * time.Second, + expectedTelemetryEmitterExportMaxBatchSize: 100, + expectedTelemetryEmitterMaxQueueSize: 1000, }, { name: "CL_DATABASE_URL parse error", @@ -168,12 +177,45 @@ func TestEnvConfig_parse(t *testing.T) { if config.TelemetryEmitterExportTimeout != tc.expectedTelemetryEmitterExportTimeout { t.Errorf("Expected telemetryEmitterExportTimeout %v, got %v", tc.expectedTelemetryEmitterExportTimeout, config.TelemetryEmitterExportTimeout) } + if config.TelemetryEmitterExportInterval != tc.expectedTelemetryEmitterExportInterval { + t.Errorf("Expected telemetryEmitterExportInterval %v, got %v", tc.expectedTelemetryEmitterExportInterval, config.TelemetryEmitterExportInterval) + } + if config.TelemetryEmitterExportMaxBatchSize != tc.expectedTelemetryEmitterExportMaxBatchSize { + t.Errorf("Expected telemetryEmitterExportMaxBatchSize %d, got %d", tc.expectedTelemetryEmitterExportMaxBatchSize, config.TelemetryEmitterExportMaxBatchSize) + } + if config.TelemetryEmitterMaxQueueSize != tc.expectedTelemetryEmitterMaxQueueSize { + t.Errorf("Expected telemetryEmitterMaxQueueSize %d, got %d", tc.expectedTelemetryEmitterMaxQueueSize, config.TelemetryEmitterMaxQueueSize) + } } } }) } } +func equalOtelAttributes(a, b OtelAttributes) bool { + if len(a) != len(b) { + return false + } + for k, v := range a { + if b[k] != v { + return false + } + } + return true +} + +func equalStringMaps(a, b map[string]string) bool { + if len(a) != len(b) { + return false + } + for k, v := range a { + if b[k] != v { + return false + } + } + return true +} + func TestEnvConfig_AsCmdEnv(t *testing.T) { envCfg := EnvConfig{ DatabaseURL: &url.URL{Scheme: "postgres", Host: "localhost:5432", User: url.UserPassword("user", "password"), Path: "/db"}, @@ -185,16 +227,19 @@ func TestEnvConfig_AsCmdEnv(t *testing.T) { TracingTLSCertPath: "some/path", TracingAttributes: map[string]string{"key": "value"}, - TelemetryEnabled: true, - TelemetryEndpoint: "example.com/beholder", - TelemetryInsecureConnection: true, - TelemetryCACertFile: "foo/bar", - TelemetryAttributes: OtelAttributes{"foo": "bar", "baz": "42"}, - TelemetryTraceSampleRatio: 0.42, - TelemetryAuthHeaders: map[string]string{"header-key": "header-value"}, - TelemetryAuthPubKeyHex: "pub-key-hex", - TelemetryEmitterBatchProcessor: true, - TelemetryEmitterExportTimeout: 1 * time.Second, + TelemetryEnabled: true, + TelemetryEndpoint: "example.com/beholder", + TelemetryInsecureConnection: true, + TelemetryCACertFile: "foo/bar", + TelemetryAttributes: OtelAttributes{"foo": "bar", "baz": "42"}, + TelemetryTraceSampleRatio: 0.42, + TelemetryAuthHeaders: map[string]string{"header-key": "header-value"}, + TelemetryAuthPubKeyHex: "pub-key-hex", + TelemetryEmitterBatchProcessor: true, + TelemetryEmitterExportTimeout: 1 * time.Second, + TelemetryEmitterExportInterval: 2 * time.Second, + TelemetryEmitterExportMaxBatchSize: 100, + TelemetryEmitterMaxQueueSize: 1000, } got := map[string]string{} for _, kv := range envCfg.AsCmdEnv() { @@ -223,6 +268,9 @@ func TestEnvConfig_AsCmdEnv(t *testing.T) { assert.Equal(t, "pub-key-hex", got[envTelemetryAuthPubKeyHex]) assert.Equal(t, "true", got[envTelemetryEmitterBatchProcessor]) assert.Equal(t, "1s", got[envTelemetryEmitterExportTimeout]) + assert.Equal(t, "2s", got[envTelemetryEmitterExportInterval]) + assert.Equal(t, "100", got[envTelemetryEmitterExportMaxBatchSize]) + assert.Equal(t, "1000", got[envTelemetryEmitterMaxQueueSize]) } func TestGetMap(t *testing.T) { diff --git a/pkg/loop/internal/relayer/pluginprovider/contractreader/contract_reader_test.go b/pkg/loop/internal/relayer/pluginprovider/contractreader/contract_reader_test.go index 88a87031c..c050f9cf9 100644 --- a/pkg/loop/internal/relayer/pluginprovider/contractreader/contract_reader_test.go +++ b/pkg/loop/internal/relayer/pluginprovider/contractreader/contract_reader_test.go @@ -85,6 +85,7 @@ func TestContractReaderInterfaceTests(t *testing.T) { contractreadertest.WithContractReaderLoopEncoding(version), ), true, + false, ) } }) @@ -1162,6 +1163,7 @@ func runContractReaderByIDQueryKey(t *testing.T) { func(t *testing.T) { t.Parallel() fake := &fakeContractReader{} + fakeCW := &fakeContractWriter{cr: fake} tester := &fakeContractReaderInterfaceTester{impl: fake} tester.Setup(t) @@ -1179,14 +1181,14 @@ func runContractReaderByIDQueryKey(t *testing.T) { require.NoError(t, cr.Bind(ctx, toBind)) ts1AnyContract := CreateTestStruct(0, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts1AnyContract, anyContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, fakeCW, MethodTriggeringEvent, ts1AnyContract, anyContract, types.Unconfirmed) ts2AnyContract := CreateTestStruct(1, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts2AnyContract, anyContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, fakeCW, MethodTriggeringEvent, ts2AnyContract, anyContract, types.Unconfirmed) ts1AnySecondContract := CreateTestStruct(0, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts1AnySecondContract, anySecondContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, fakeCW, MethodTriggeringEvent, ts1AnySecondContract, anySecondContract, types.Unconfirmed) ts2AnySecondContract := CreateTestStruct(1, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts2AnySecondContract, anySecondContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, fakeCW, MethodTriggeringEvent, ts2AnySecondContract, anySecondContract, types.Unconfirmed) tsAnyContractType := &TestStruct{} require.Eventually(t, func() bool { @@ -1205,6 +1207,8 @@ func runContractReaderByIDQueryKey(t *testing.T) { func(t *testing.T) { t.Parallel() fake := &fakeContractReader{} + fakeCW := &fakeContractWriter{cr: fake} + tester := &fakeContractReaderInterfaceTester{impl: fake} tester.Setup(t) @@ -1225,22 +1229,22 @@ func runContractReaderByIDQueryKey(t *testing.T) { require.NoError(t, cr.Bind(ctx, toBind)) ts1AnyContract1 := CreateTestStruct(0, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts1AnyContract1, anyContract1, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, fakeCW, MethodTriggeringEvent, ts1AnyContract1, anyContract1, types.Unconfirmed) ts2AnyContract1 := CreateTestStruct(1, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts2AnyContract1, anyContract1, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, fakeCW, MethodTriggeringEvent, ts2AnyContract1, anyContract1, types.Unconfirmed) ts1AnyContract2 := CreateTestStruct(2, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts1AnyContract2, anyContract2, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, fakeCW, MethodTriggeringEvent, ts1AnyContract2, anyContract2, types.Unconfirmed) ts2AnyContract2 := CreateTestStruct(3, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts2AnyContract2, anyContract2, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, fakeCW, MethodTriggeringEvent, ts2AnyContract2, anyContract2, types.Unconfirmed) ts1AnySecondContract1 := CreateTestStruct(4, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts1AnySecondContract1, anySecondContract1, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, fakeCW, MethodTriggeringEvent, ts1AnySecondContract1, anySecondContract1, types.Unconfirmed) ts2AnySecondContract1 := CreateTestStruct(5, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts2AnySecondContract1, anySecondContract1, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, fakeCW, MethodTriggeringEvent, ts2AnySecondContract1, anySecondContract1, types.Unconfirmed) ts1AnySecondContract2 := CreateTestStruct(6, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts1AnySecondContract2, anySecondContract2, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, fakeCW, MethodTriggeringEvent, ts1AnySecondContract2, anySecondContract2, types.Unconfirmed) ts2AnySecondContract2 := CreateTestStruct(7, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts2AnySecondContract2, anySecondContract2, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, fakeCW, MethodTriggeringEvent, ts2AnySecondContract2, anySecondContract2, types.Unconfirmed) tsAnyContractType := &TestStruct{} require.Eventually(t, func() bool { diff --git a/pkg/loop/internal/relayer/pluginprovider/contractreader/test/contract_reader_loop_tester.go b/pkg/loop/internal/relayer/pluginprovider/contractreader/test/contract_reader_loop_tester.go index 8bd159de5..23671fbe5 100644 --- a/pkg/loop/internal/relayer/pluginprovider/contractreader/test/contract_reader_loop_tester.go +++ b/pkg/loop/internal/relayer/pluginprovider/contractreader/test/contract_reader_loop_tester.go @@ -56,6 +56,7 @@ func WithContractReaderLoopEncoding(version contractreader.EncodingVersion) Loop type contractReaderLoopTester struct { ChainComponentsInterfaceTester[*testing.T] lst loopServerTester + conn *grpc.ClientConn encodeWith contractreader.EncodingVersion } @@ -71,10 +72,11 @@ func (c *contractReaderLoopTester) Setup(t *testing.T) { } c.lst.Setup(t) + c.conn = c.lst.GetConn(t) } func (c *contractReaderLoopTester) GetContractReader(t *testing.T) types.ContractReader { - return contractreader.NewClient(nil, c.lst.GetConn(t), contractreader.WithClientEncoding(c.encodeWith)) + return contractreader.NewClient(nil, c.conn, contractreader.WithClientEncoding(c.encodeWith)) } func (c *contractReaderLoopTester) Name() string { diff --git a/pkg/loop/server.go b/pkg/loop/server.go index c866be20b..6cf4f0c5b 100644 --- a/pkg/loop/server.go +++ b/pkg/loop/server.go @@ -92,15 +92,18 @@ func (s *Server) start() error { } beholderCfg := beholder.Config{ - InsecureConnection: envCfg.TelemetryInsecureConnection, - CACertFile: envCfg.TelemetryCACertFile, - OtelExporterGRPCEndpoint: envCfg.TelemetryEndpoint, - ResourceAttributes: append(attributes, envCfg.TelemetryAttributes.AsStringAttributes()...), - TraceSampleRatio: envCfg.TelemetryTraceSampleRatio, - AuthHeaders: envCfg.TelemetryAuthHeaders, - AuthPublicKeyHex: envCfg.TelemetryAuthPubKeyHex, - EmitterBatchProcessor: envCfg.TelemetryEmitterBatchProcessor, - EmitterExportTimeout: envCfg.TelemetryEmitterExportTimeout, + InsecureConnection: envCfg.TelemetryInsecureConnection, + CACertFile: envCfg.TelemetryCACertFile, + OtelExporterGRPCEndpoint: envCfg.TelemetryEndpoint, + ResourceAttributes: append(attributes, envCfg.TelemetryAttributes.AsStringAttributes()...), + TraceSampleRatio: envCfg.TelemetryTraceSampleRatio, + AuthHeaders: envCfg.TelemetryAuthHeaders, + AuthPublicKeyHex: envCfg.TelemetryAuthPubKeyHex, + EmitterBatchProcessor: envCfg.TelemetryEmitterBatchProcessor, + EmitterExportTimeout: envCfg.TelemetryEmitterExportTimeout, + EmitterExportInterval: envCfg.TelemetryEmitterExportInterval, + EmitterExportMaxBatchSize: envCfg.TelemetryEmitterExportMaxBatchSize, + EmitterMaxQueueSize: envCfg.TelemetryEmitterMaxQueueSize, } if tracingConfig.Enabled { diff --git a/pkg/types/interfacetests/chain_components_interface_tests.go b/pkg/types/interfacetests/chain_components_interface_tests.go index 7d32471ce..c65f9b6ff 100644 --- a/pkg/types/interfacetests/chain_components_interface_tests.go +++ b/pkg/types/interfacetests/chain_components_interface_tests.go @@ -111,12 +111,12 @@ var AnySliceToReadWithoutAnArgument = []uint64{3, 4} const AnyExtraValue = 3 -func RunContractReaderInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], mockRun bool) { +func RunContractReaderInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], mockRun bool, parallel bool) { t.Run(tester.Name(), func(t T) { - t.Run("GetLatestValue", func(t T) { runContractReaderGetLatestValueInterfaceTests(t, tester, mockRun) }) - t.Run("BatchGetLatestValues", func(t T) { runContractReaderBatchGetLatestValuesInterfaceTests(t, tester, mockRun) }) - t.Run("QueryKey", func(t T) { runQueryKeyInterfaceTests(t, tester) }) - t.Run("QueryKeys", func(t T) { runQueryKeysInterfaceTests(t, tester) }) + t.Run("GetLatestValue", func(t T) { runContractReaderGetLatestValueInterfaceTests(t, tester, mockRun, parallel) }) + t.Run("BatchGetLatestValues", func(t T) { runContractReaderBatchGetLatestValuesInterfaceTests(t, tester, mockRun, parallel) }) + t.Run("QueryKey", func(t T) { runQueryKeyInterfaceTests(t, tester, parallel) }) + t.Run("QueryKeys", func(t T) { runQueryKeysInterfaceTests(t, tester, parallel) }) }) } @@ -129,19 +129,21 @@ type sequenceWithKey struct { Key string } -func runQueryKeysInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T]) { +func runQueryKeysInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], parallel bool) { tests := []Testcase[T]{ { Name: ContractReaderQueryKeysReturnsDataTwoEventTypes, Test: func(t T) { ctx := tests.Context(t) cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) + bindings := tester.GetBindings(t) require.NoError(t, cr.Bind(ctx, bindings)) boundContract := BindingsByName(bindings, AnyContractName)[0] - expectedSequenceData := createMixedEventTypeSequence(t, tester, boundContract) + expectedSequenceData := createMixedEventTypeSequence(t, tester, cw, boundContract) ts := &TestStruct{} require.Eventually(t, func() bool { @@ -181,7 +183,7 @@ func runQueryKeysInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterf bindings := tester.GetBindings(t) bound := BindingsByName(bindings, AnyContractName)[0] - require.NoError(t, cr.Bind(ctx, tester.GetBindings(t))) + require.NoError(t, cr.Bind(ctx, bindings)) contractFilter := types.ContractKeyFilter{ Contract: bound, @@ -204,12 +206,13 @@ func runQueryKeysInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterf Test: func(t T) { ctx := tests.Context(t) cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) bindings := tester.GetBindings(t) require.NoError(t, cr.Bind(ctx, bindings)) bound := BindingsByName(bindings, AnyContractName)[0] - expectedSequenceData := createMixedEventTypeSequence(t, tester, bound) + expectedSequenceData := createMixedEventTypeSequence(t, tester, cw, bound) var value values.Value require.Eventually(t, func() bool { @@ -268,12 +271,15 @@ func runQueryKeysInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterf Test: func(t T) { ctx := tests.Context(t) cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) + bindings := tester.GetBindings(t) require.NoError(t, cr.Bind(ctx, bindings)) boundContract := BindingsByName(bindings, AnyContractName)[0] - expectedSequenceData := createMixedEventTypeSequence(t, tester, boundContract) + expectedSequenceData := createMixedEventTypeSequence(t, tester, cw, boundContract) + fmt.Println("expectedSequenceData", expectedSequenceData) ts := &TestStruct{} require.Eventually(t, func() bool { @@ -321,6 +327,7 @@ func runQueryKeysInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterf Test: func(t T) { ctx := tests.Context(t) cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) bindings := tester.GetBindings(t) require.NoError(t, cr.Bind(ctx, bindings)) @@ -330,26 +337,26 @@ func runQueryKeysInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterf ts1 := CreateTestStruct[T](0, tester) expectedSequenceData = append(expectedSequenceData, &ts1) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) ts2 := CreateTestStruct[T](1, tester) expectedSequenceData = append(expectedSequenceData, &ts2) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) ds1 := SomeDynamicTopicEvent{Field: "1"} expectedSequenceData = append(expectedSequenceData, &ds1) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEventWithDynamicTopic, ds1, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEventWithDynamicTopic, ds1, boundContract, types.Unconfirmed) ts3 := CreateTestStruct[T](2, tester) expectedSequenceData = append(expectedSequenceData, &ts3) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) ds2 := SomeDynamicTopicEvent{Field: "2"} expectedSequenceData = append(expectedSequenceData, &ds2) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEventWithDynamicTopic, ds2, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEventWithDynamicTopic, ds2, boundContract, types.Unconfirmed) ts4 := CreateTestStruct[T](3, tester) expectedSequenceData = append(expectedSequenceData, &ts4) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts4, boundContract, types.Finalized) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts4, boundContract, types.Finalized) require.Eventually(t, func() bool { var allSequences []sequenceWithKey @@ -399,35 +406,38 @@ func runQueryKeysInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterf }, } - RunTests(t, tester, tests) + if parallel { + RunTestsInParallel(t, tester, tests) + } else { + RunTests(t, tester, tests) + } } -func createMixedEventTypeSequence[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], boundContract types.BoundContract) []any { +func createMixedEventTypeSequence[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], cw types.ContractWriter, boundContract types.BoundContract) []any { var expectedSequenceData []any ts1 := CreateTestStruct[T](0, tester) expectedSequenceData = append(expectedSequenceData, &ts1) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) ts2 := CreateTestStruct[T](1, tester) expectedSequenceData = append(expectedSequenceData, &ts2) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) ds1 := SomeDynamicTopicEvent{Field: "1"} expectedSequenceData = append(expectedSequenceData, &ds1) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEventWithDynamicTopic, ds1, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEventWithDynamicTopic, ds1, boundContract, types.Unconfirmed) ts3 := CreateTestStruct[T](2, tester) expectedSequenceData = append(expectedSequenceData, &ts3) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) ds2 := SomeDynamicTopicEvent{Field: "2"} expectedSequenceData = append(expectedSequenceData, &ds2) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEventWithDynamicTopic, ds2, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEventWithDynamicTopic, ds2, boundContract, types.Unconfirmed) ts4 := CreateTestStruct[T](3, tester) expectedSequenceData = append(expectedSequenceData, &ts4) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts4, boundContract, types.Unconfirmed) - + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts4, boundContract, types.Unconfirmed) return expectedSequenceData } @@ -445,26 +455,26 @@ func sequenceDataEqual(expectedSequenceData []any, sequences []sequenceWithKey) return true } -func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], mockRun bool) { +func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], mockRun bool, parallel bool) { tests := []Testcase[T]{ { Name: ContractReaderGetLatestValueAsValuesDotValue, Test: func(t T) { + cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) + contracts := tester.GetBindings(t) ctx := tests.Context(t) firstItem := CreateTestStruct(0, tester) - contracts := tester.GetBindings(t) - _ = SubmitTransactionToCW(t, tester, MethodSettingStruct, firstItem, contracts[0], types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodSettingStruct, firstItem, contracts[0], types.Unconfirmed) secondItem := CreateTestStruct(1, tester) - _ = SubmitTransactionToCW(t, tester, MethodSettingStruct, secondItem, contracts[0], types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodSettingStruct, secondItem, contracts[0], types.Unconfirmed) - cr := tester.GetContractReader(t) - bindings := tester.GetBindings(t) - bound := BindingsByName(bindings, AnyContractName)[0] // minimum of one bound contract expected, otherwise panics + bound := BindingsByName(contracts, AnyContractName)[0] // minimum of one bound contract expected, otherwise panics - require.NoError(t, cr.Bind(ctx, bindings)) + require.NoError(t, cr.Bind(ctx, contracts)) params := &LatestParams{I: 1} var value values.Value @@ -491,9 +501,9 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch { Name: ContractReaderGetLatestValueNoArgumentsAndPrimitiveReturnAsValuesDotValue, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) bound := BindingsByName(bindings, AnyContractName)[0] require.NoError(t, cr.Bind(ctx, bindings)) @@ -512,9 +522,9 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch { Name: ContractReaderGetLatestValueNoArgumentsAndSliceReturnAsValueDotValue, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) bound := BindingsByName(bindings, AnyContractName)[0] require.NoError(t, cr.Bind(ctx, bindings)) @@ -532,21 +542,21 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch { Name: ContractReaderGetLatestValue, Test: func(t T) { + cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) + contracts := tester.GetBindings(t) ctx := tests.Context(t) firstItem := CreateTestStruct(0, tester) - contracts := tester.GetBindings(t) - _ = SubmitTransactionToCW(t, tester, MethodSettingStruct, firstItem, contracts[0], types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodSettingStruct, firstItem, contracts[0], types.Unconfirmed) secondItem := CreateTestStruct(1, tester) - _ = SubmitTransactionToCW(t, tester, MethodSettingStruct, secondItem, contracts[0], types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodSettingStruct, secondItem, contracts[0], types.Unconfirmed) - cr := tester.GetContractReader(t) - bindings := tester.GetBindings(t) - bound := BindingsByName(bindings, AnyContractName)[0] // minimum of one bound contract expected, otherwise panics + bound := BindingsByName(contracts, AnyContractName)[0] // minimum of one bound contract expected, otherwise panics - require.NoError(t, cr.Bind(ctx, bindings)) + require.NoError(t, cr.Bind(ctx, contracts)) actual := &TestStruct{} params := &LatestParams{I: 1} @@ -562,9 +572,10 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch { Name: ContractReaderGetLatestValueWithPrimitiveReturn, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) + bound := BindingsByName(bindings, AnyContractName)[0] require.NoError(t, cr.Bind(ctx, bindings)) @@ -578,9 +589,10 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch { Name: ContractReaderGetLatestValueBasedOnConfidenceLevel, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) require.NoError(t, cr.Bind(ctx, bindings)) @@ -593,22 +605,18 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch ReturnVal: &returnVal1, } - contracts := tester.GetBindings(t) - - txID := SubmitTransactionToCW(t, tester, MethodSettingUint64, PrimitiveArgs{Value: 10}, contracts[0], types.Unconfirmed) + txID := SubmitTransactionToCW(t, tester, cw, MethodSettingUint64, PrimitiveArgs{Value: 10}, bindings[0], types.Unconfirmed) var prim1 uint64 bound := BindingsByName(bindings, callArgs.ContractName)[0] - require.Error(t, cr.GetLatestValue(ctx, bound.ReadIdentifier(callArgs.ReadName), primitives.Finalized, callArgs.Params, &prim1)) - - err := WaitForTransactionStatus(t, tester, txID, types.Finalized, mockRun) + err := WaitForTransactionStatus(t, tester, cw, txID, types.Finalized, mockRun) require.NoError(t, err) require.NoError(t, cr.GetLatestValue(ctx, bound.ReadIdentifier(MethodReturningAlterableUint64), primitives.Finalized, nil, &prim1)) assert.Equal(t, uint64(10), prim1) - _ = SubmitTransactionToCW(t, tester, MethodSettingUint64, PrimitiveArgs{Value: 20}, contracts[0], types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodSettingUint64, PrimitiveArgs{Value: 20}, bindings[0], types.Unconfirmed) var prim2 uint64 require.NoError(t, cr.GetLatestValue(ctx, bound.ReadIdentifier(callArgs.ReadName), callArgs.ConfidenceLevel, callArgs.Params, &prim2)) @@ -618,9 +626,9 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch { Name: ContractReaderGetLatestValueFromMultipleContractsNamesSameFunction, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) bound := BindingsByName(bindings, AnySecondContractName)[0] require.NoError(t, cr.Bind(ctx, bindings)) @@ -634,9 +642,9 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch { Name: ContractReaderGetLatestValueNoArgumentsAndSliceReturn, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) bound := BindingsByName(bindings, AnyContractName)[0] require.NoError(t, cr.Bind(ctx, bindings)) @@ -650,15 +658,16 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch { Name: ContractReaderGetLatestValueWithModifiersUsingOwnMapstrctureOverrides, Test: func(t T) { + cr := tester.GetContractReader(t) + bindings := tester.GetBindings(t) + ctx := tests.Context(t) testStruct := CreateTestStruct(0, tester) testStruct.BigField = nil testStruct.AccountStruct.Account = nil - bindings := tester.GetBindings(t) bound := BindingsByName(bindings, AnyContractName)[0] - cr := tester.GetContractReader(t) require.NoError(t, cr.Bind(ctx, bindings)) actual := &TestStructWithExtraField{} @@ -675,19 +684,19 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch { Name: ContractReaderGetLatestValueGetsLatestForEvent, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) bound := BindingsByName(bindings, AnyContractName)[0] require.NoError(t, cr.Bind(ctx, bindings)) - contracts := tester.GetBindings(t) ts := CreateTestStruct[T](0, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts, contracts[0], types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts, bindings[0], types.Unconfirmed) ts = CreateTestStruct[T](1, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts, contracts[0], types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts, bindings[0], types.Unconfirmed) result := &TestStruct{} require.Eventually(t, func() bool { @@ -699,27 +708,24 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch { Name: ContractReaderGetLatestValueBasedOnConfidenceLevelForEvent, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) bound := BindingsByName(bindings, AnyContractName)[0] require.NoError(t, cr.Bind(ctx, bindings)) ts1 := CreateTestStruct[T](2, tester) - txID := SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts1, bindings[0], types.Unconfirmed) + txID := SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts1, bindings[0], types.Unconfirmed) result := &TestStruct{} - require.Eventually(t, func() bool { - err := cr.GetLatestValue(ctx, bound.ReadIdentifier(EventName), primitives.Finalized, nil, &result) - return err != nil && assert.ErrorContains(t, err, types.ErrNotFound.Error()) - }, tester.MaxWaitTimeForEvents(), time.Millisecond*10) - err := WaitForTransactionStatus(t, tester, txID, types.Finalized, mockRun) + err := WaitForTransactionStatus(t, tester, cw, txID, types.Finalized, mockRun) require.NoError(t, err) ts2 := CreateTestStruct[T](3, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts2, bindings[0], types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts2, bindings[0], types.Unconfirmed) require.Eventually(t, func() bool { err := cr.GetLatestValue(ctx, bound.ReadIdentifier(EventName), primitives.Finalized, nil, &result) @@ -735,9 +741,9 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch { Name: ContractReaderGetLatestValueReturnsNotFoundWhenNotTriggeredForEvent, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) bound := BindingsByName(bindings, AnyContractName)[0] require.NoError(t, cr.Bind(ctx, bindings)) @@ -750,18 +756,19 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch { Name: ContractReaderGetLatestValueWithFilteringForEvent, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) + bound := BindingsByName(bindings, AnyContractName)[0] require.NoError(t, cr.Bind(ctx, bindings)) ts0 := CreateTestStruct(0, tester) - contracts := tester.GetBindings(t) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts0, contracts[0], types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts0, bindings[0], types.Unconfirmed) ts1 := CreateTestStruct(1, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts1, contracts[0], types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts1, bindings[0], types.Unconfirmed) filterParams := &FilterEventParams{Field: *ts0.Field} assert.Never(t, func() bool { @@ -779,22 +786,28 @@ func runContractReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Ch }, }, } - RunTests(t, tester, tests) + if parallel { + RunTestsInParallel(t, tester, tests) + } else { + RunTests(t, tester, tests) + } } -func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], mockRun bool) { +func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], mockRun bool, parallel bool) { testCases := []Testcase[T]{ { Name: ContractReaderBatchGetLatestValue, Test: func(t T) { + cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) + bindings := tester.GetBindings(t) // setup test data firstItem := CreateTestStruct(1, tester) - bindings := tester.GetBindings(t) bound := BindingsByName(bindings, AnyContractName)[0] batchCallEntry := make(BatchCallEntry) batchCallEntry[bound] = ContractBatchEntry{{Name: MethodTakingLatestParamsReturningTestStruct, ReturnValue: &firstItem}} - batchContractWrite(t, tester, batchCallEntry, mockRun) + batchContractWrite(t, tester, cw, bindings, batchCallEntry, mockRun) // setup call data params, actual := &LatestParams{I: 1}, &TestStruct{} @@ -808,7 +821,6 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes } ctx := tests.Context(t) - cr := tester.GetContractReader(t) require.NoError(t, cr.Bind(ctx, bindings)) result, err := cr.BatchGetLatestValues(ctx, batchGetLatestValueRequest) @@ -824,10 +836,11 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes { Name: ContractReaderBatchGetLatestValueNoArgumentsPrimitiveReturn, Test: func(t T) { + cr := tester.GetContractReader(t) + bindings := tester.GetBindings(t) // setup call data var primitiveReturnValue uint64 batchGetLatestValuesRequest := make(types.BatchGetLatestValuesRequest) - bindings := tester.GetBindings(t) bound := BindingsByName(bindings, AnyContractName)[0] batchGetLatestValuesRequest[bound] = []types.BatchRead{ @@ -839,7 +852,6 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes } ctx := tests.Context(t) - cr := tester.GetContractReader(t) require.NoError(t, cr.Bind(ctx, bindings)) result, err := cr.BatchGetLatestValues(ctx, batchGetLatestValuesRequest) @@ -855,9 +867,11 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes { Name: ContractReaderBatchGetLatestValueMultipleContractNamesSameFunction, Test: func(t T) { + cr := tester.GetContractReader(t) + bindings := tester.GetBindings(t) + var primitiveReturnValueAnyContract, primitiveReturnValueAnySecondContract uint64 batchGetLatestValuesRequest := make(types.BatchGetLatestValuesRequest) - bindings := tester.GetBindings(t) bound1 := BindingsByName(bindings, AnyContractName)[0] bound2 := BindingsByName(bindings, AnySecondContractName)[0] @@ -865,7 +879,6 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes batchGetLatestValuesRequest[bound2] = []types.BatchRead{{ReadName: MethodReturningUint64, Params: nil, ReturnVal: &primitiveReturnValueAnySecondContract}} ctx := tests.Context(t) - cr := tester.GetContractReader(t) require.NoError(t, cr.Bind(ctx, bindings)) result, err := cr.BatchGetLatestValues(ctx, batchGetLatestValuesRequest) @@ -885,16 +898,16 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes { Name: ContractReaderBatchGetLatestValueNoArgumentsWithSliceReturn, Test: func(t T) { + cr := tester.GetContractReader(t) + bindings := tester.GetBindings(t) // setup call data var sliceReturnValue []uint64 batchGetLatestValueRequest := make(types.BatchGetLatestValuesRequest) - bindings := tester.GetBindings(t) bound := BindingsByName(bindings, AnyContractName)[0] batchGetLatestValueRequest[bound] = []types.BatchRead{{ReadName: MethodReturningUint64Slice, Params: nil, ReturnVal: &sliceReturnValue}} ctx := tests.Context(t) - cr := tester.GetContractReader(t) require.NoError(t, cr.Bind(ctx, bindings)) result, err := cr.BatchGetLatestValues(ctx, batchGetLatestValueRequest) require.NoError(t, err) @@ -909,19 +922,19 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes { Name: ContractReaderBatchGetLatestValueWithModifiersOwnMapstructureOverride, Test: func(t T) { + cr := tester.GetContractReader(t) + bindings := tester.GetBindings(t) // setup call data testStruct := CreateTestStruct(0, tester) testStruct.BigField = nil testStruct.AccountStruct.Account = nil actual := &TestStructWithExtraField{} batchGetLatestValueRequest := make(types.BatchGetLatestValuesRequest) - bindings := tester.GetBindings(t) bound := BindingsByName(bindings, AnyContractName)[0] batchGetLatestValueRequest[bound] = []types.BatchRead{{ReadName: MethodReturningSeenStruct, Params: testStruct, ReturnVal: actual}} ctx := tests.Context(t) - cr := tester.GetContractReader(t) require.NoError(t, cr.Bind(ctx, bindings)) result, err := cr.BatchGetLatestValues(ctx, batchGetLatestValueRequest) require.NoError(t, err) @@ -941,9 +954,11 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes { Name: ContractReaderBatchGetLatestValueDifferentParamsResultsRetainOrder, Test: func(t T) { + cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) + bindings := tester.GetBindings(t) batchCallEntry := make(BatchCallEntry) batchGetLatestValueRequest := make(types.BatchGetLatestValuesRequest) - bindings := tester.GetBindings(t) bound := BindingsByName(bindings, AnyContractName)[0] for i := 0; i < 10; i++ { @@ -956,10 +971,9 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes types.BatchRead{ReadName: MethodTakingLatestParamsReturningTestStruct, Params: &LatestParams{I: 1 + i}, ReturnVal: &TestStruct{}}, ) } - batchContractWrite(t, tester, batchCallEntry, mockRun) + batchContractWrite(t, tester, cw, bindings, batchCallEntry, mockRun) ctx := tests.Context(t) - cr := tester.GetContractReader(t) require.NoError(t, cr.Bind(ctx, bindings)) result, err := cr.BatchGetLatestValues(ctx, batchGetLatestValueRequest) @@ -977,9 +991,11 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes { Name: ContractReaderBatchGetLatestValueDifferentParamsResultsRetainOrderMultipleContracts, Test: func(t T) { + cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) + bindings := tester.GetBindings(t) batchCallEntry := make(BatchCallEntry) batchGetLatestValueRequest := make(types.BatchGetLatestValuesRequest) - bindings := tester.GetBindings(t) bound1 := BindingsByName(bindings, AnyContractName)[0] bound2 := BindingsByName(bindings, AnySecondContractName)[0] @@ -992,10 +1008,9 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes batchGetLatestValueRequest[bound1] = append(batchGetLatestValueRequest[bound1], types.BatchRead{ReadName: MethodTakingLatestParamsReturningTestStruct, Params: &LatestParams{I: 1 + i}, ReturnVal: &TestStruct{}}) batchGetLatestValueRequest[bound2] = append(batchGetLatestValueRequest[bound2], types.BatchRead{ReadName: MethodTakingLatestParamsReturningTestStruct, Params: &LatestParams{I: 1 + i}, ReturnVal: &TestStruct{}}) } - batchContractWrite(t, tester, batchCallEntry, mockRun) + batchContractWrite(t, tester, cw, bindings, batchCallEntry, mockRun) ctx := tests.Context(t) - cr := tester.GetContractReader(t) require.NoError(t, cr.Bind(ctx, bindings)) result, err := cr.BatchGetLatestValues(ctx, batchGetLatestValueRequest) @@ -1026,6 +1041,7 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes Name: ContractReaderBatchGetLatestValueSetsErrorsProperly, Test: func(t T) { batchGetLatestValueRequest := make(types.BatchGetLatestValuesRequest) + cr := tester.GetContractReader(t) bindings := tester.GetBindings(t) bound1 := BindingsByName(bindings, AnyContractName)[0] bound2 := BindingsByName(bindings, AnySecondContractName)[0] @@ -1037,7 +1053,6 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes } ctx := tests.Context(t) - cr := tester.GetContractReader(t) require.NoError(t, cr.Bind(ctx, bindings)) result, err := cr.BatchGetLatestValues(ctx, batchGetLatestValueRequest) @@ -1057,20 +1072,24 @@ func runContractReaderBatchGetLatestValuesInterfaceTests[T TestingT[T]](t T, tes }, }, } - RunTests(t, tester, testCases) + if parallel { + RunTestsInParallel(t, tester, testCases) + } else { + RunTests(t, tester, testCases) + } } -func runQueryKeyInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T]) { +func runQueryKeyInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], parallel bool) { tests := []Testcase[T]{ { Name: ContractReaderQueryKeyNotFound, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) bound := BindingsByName(bindings, AnyContractName)[0] - require.NoError(t, cr.Bind(ctx, tester.GetBindings(t))) + require.NoError(t, cr.Bind(ctx, bindings)) logs, err := cr.QueryKey(ctx, bound, query.KeyFilter{Key: EventName}, query.LimitAndSort{}, &TestStruct{}) @@ -1081,17 +1100,18 @@ func runQueryKeyInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfa { Name: ContractReaderQueryKeyReturnsData, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) require.NoError(t, cr.Bind(ctx, bindings)) boundContract := BindingsByName(bindings, AnyContractName)[0] ts1 := CreateTestStruct[T](0, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) ts2 := CreateTestStruct[T](1, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) ts := &TestStruct{} require.Eventually(t, func() bool { @@ -1104,17 +1124,18 @@ func runQueryKeyInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfa { Name: ContractReaderQueryKeyReturnsDataAsValuesDotValue, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) require.NoError(t, cr.Bind(ctx, bindings)) bound := BindingsByName(bindings, AnyContractName)[0] ts1 := CreateTestStruct[T](0, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts1, bindings[0], types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts1, bindings[0], types.Unconfirmed) ts2 := CreateTestStruct[T](1, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts2, bindings[0], types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts2, bindings[0], types.Unconfirmed) var value values.Value @@ -1144,19 +1165,20 @@ func runQueryKeyInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfa { Name: ContractReaderQueryKeyCanFilterWithValueComparator, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) require.NoError(t, cr.Bind(ctx, bindings)) boundContract := BindingsByName(bindings, AnyContractName)[0] ts1 := CreateTestStruct[T](0, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) ts2 := CreateTestStruct[T](15, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) ts3 := CreateTestStruct[T](35, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) ts := &TestStruct{} require.Eventually(t, func() bool { @@ -1180,9 +1202,10 @@ func runQueryKeyInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfa { Name: ContractReaderQueryKeyCanLimitResultsWithCursor, Test: func(t T) { - ctx := tests.Context(t) cr := tester.GetContractReader(t) + cw := tester.GetContractWriter(t) bindings := tester.GetBindings(t) + ctx := tests.Context(t) require.NoError(t, cr.Bind(ctx, bindings)) boundContract := BindingsByName(bindings, AnyContractName)[0] @@ -1194,7 +1217,7 @@ func runQueryKeyInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfa for idx := range testStructs { testStructs[idx] = CreateTestStruct(idx*2, tester) - _ = SubmitTransactionToCW(t, tester, MethodTriggeringEvent, testStructs[idx], boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, tester, cw, MethodTriggeringEvent, testStructs[idx], boundContract, types.Unconfirmed) } require.Eventually(t, func() bool { @@ -1230,7 +1253,11 @@ func runQueryKeyInterfaceTests[T TestingT[T]](t T, tester ChainComponentsInterfa }, } - RunTests(t, tester, tests) + if parallel { + RunTestsInParallel(t, tester, tests) + } else { + RunTests(t, tester, tests) + } } func BindingsByName(bindings []types.BoundContract, name string) []types.BoundContract { diff --git a/pkg/types/interfacetests/utils.go b/pkg/types/interfacetests/utils.go index 5f81cd206..93c35c0fe 100644 --- a/pkg/types/interfacetests/utils.go +++ b/pkg/types/interfacetests/utils.go @@ -52,6 +52,7 @@ type TestingT[T any] interface { tests.TestingT Failed() bool Run(name string, f func(t T)) bool + Parallel() } // Tests execution utility function that will consider enabled / disabled test cases according to @@ -69,17 +70,29 @@ func RunTests[T TestingT[T]](t T, tester BasicTester[T], tests []Testcase[T]) { }) } +func RunTestsInParallel[T TestingT[T]](t T, tester BasicTester[T], tests []Testcase[T]) { + // Assumes Setup() called on tester initialization to avoid race conditions on tester setup + t.Run(tester.Name(), func(t T) { + for _, test := range tests { + if !tester.IsDisabled(test.Name) { + t.Run(test.Name, func(t T) { + t.Parallel() + test.Test(t) + }) + } + } + }) +} + // Batch contract write takes a batch call entry and writes it to the chain using the ContractWriter. -func batchContractWrite[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], batchCallEntry BatchCallEntry, mockRun bool) { +func batchContractWrite[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], cw types.ContractWriter, boundContracts []types.BoundContract, batchCallEntry BatchCallEntry, mockRun bool) { // This is necessary because the mock helper function requires the entire batchCallEntry rather than an individual testStruct if mockRun { - cw := tester.GetContractWriter(t) err := cw.SubmitTransaction(tests.Context(t), AnyContractName, "batchContractWrite", batchCallEntry, "", "", nil, big.NewInt(0)) require.NoError(t, err) return } nameToAddress := make(map[string]string) - boundContracts := tester.GetBindings(t) for _, bc := range boundContracts { nameToAddress[bc.Name] = bc.Address } @@ -92,27 +105,26 @@ func batchContractWrite[T TestingT[T]](t T, tester ChainComponentsInterfaceTeste if !isOk { require.Fail(t, "expected *TestStruct for contract: %s read: %s, but received %T", contract.Name, readEntry.Name, readEntry.ReturnValue) } - SubmitTransactionToCW(t, tester, MethodSettingStruct, val, types.BoundContract{Name: contract.Name, Address: nameToAddress[contract.Name]}, types.Unconfirmed) + SubmitTransactionToCW(t, tester, cw, MethodSettingStruct, val, types.BoundContract{Name: contract.Name, Address: nameToAddress[contract.Name]}, types.Unconfirmed) } } } // SubmitTransactionToCW submits a transaction to the ContractWriter and waits for it to reach the given status. -func SubmitTransactionToCW[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], method string, args any, contract types.BoundContract, status types.TransactionStatus) string { +func SubmitTransactionToCW[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], cw types.ContractWriter, method string, args any, contract types.BoundContract, status types.TransactionStatus) string { tester.DirtyContracts() txID := uuid.New().String() - cw := tester.GetContractWriter(t) err := cw.SubmitTransaction(tests.Context(t), contract.Name, method, args, txID, contract.Address, nil, big.NewInt(0)) require.NoError(t, err) - err = WaitForTransactionStatus(t, tester, txID, status, false) + err = WaitForTransactionStatus(t, tester, cw, txID, status, false) require.NoError(t, err) return txID } // WaitForTransactionStatus waits for a transaction to reach the given status. -func WaitForTransactionStatus[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], txID string, status types.TransactionStatus, mockRun bool) error { +func WaitForTransactionStatus[T TestingT[T]](t T, tester ChainComponentsInterfaceTester[T], cw types.ContractWriter, txID string, status types.TransactionStatus, mockRun bool) error { ctx, cancel := context.WithTimeout(tests.Context(t), 15*time.Minute) defer cancel() @@ -128,7 +140,7 @@ func WaitForTransactionStatus[T TestingT[T]](t T, tester ChainComponentsInterfac tester.GenerateBlocksTillConfidenceLevel(t, "", "", primitives.Finalized) return nil } - current, err := tester.GetContractWriter(t).GetTransactionStatus(ctx, txID) + current, err := cw.GetTransactionStatus(ctx, txID) if err != nil { return fmt.Errorf("failed to get transaction status: %w", err) } diff --git a/pkg/workflows/utils.go b/pkg/workflows/utils.go index 250912c63..2d6816c75 100644 --- a/pkg/workflows/utils.go +++ b/pkg/workflows/utils.go @@ -72,3 +72,15 @@ func GenerateWorkflowID(owner []byte, name string, workflow []byte, config []byt return sha, nil } + +// HashTruncateName returns the SHA-256 hash of the workflow name truncated to the first 10 bytes. +func HashTruncateName(name string) [10]byte { + // Compute SHA-256 hash of the input string + hash := sha256.Sum256([]byte(name)) + + // Truncate the hash to 10 bytes + var result [10]byte + copy(result[:], hash[:10]) + + return result +} diff --git a/pkg/workflows/utils_test.go b/pkg/workflows/utils_test.go index 477807733..ae506a7df 100644 --- a/pkg/workflows/utils_test.go +++ b/pkg/workflows/utils_test.go @@ -66,3 +66,36 @@ func Test_GenerateWorkflowIDFromStrings(t *testing.T) { _, err = GenerateWorkflowIDFromStrings(owner, "porporpore", []byte("workflow"), []byte("config"), "http://mysecrets.com") assert.ErrorContains(t, err, "encoding/hex") } + +func TestNormalizeWorkflowName(t *testing.T) { + tt := []struct { + input string + expected [10]byte + }{ + { + input: "Hello, world!", + expected: [10]byte{0x31, 0x5f, 0x5b, 0xdb, 0x76, 0xd0, 0x78, 0xc4, 0x3b, 0x8a}, + }, + { + input: "My Incredible Workflow Name", + expected: [10]byte{0x84, 0x00, 0x2e, 0xb9, 0xe2, 0xa0, 0x6b, 0x09, 0x97, 0x7c}, + }, + { + input: "You either die a hero, or live long enough to see yourself become the villain.", + expected: [10]byte{0x6b, 0xa1, 0xf7, 0xa6, 0xa0, 0x91, 0x95, 0x1a, 0x2d, 0xd2}, + }, + } + + for _, tc := range tt { + t.Run(tc.input, func(t *testing.T) { + // Call the function with the test input + result := HashTruncateName(tc.input) + + // Assert that the result is exactly the expected output + require.Equal(t, tc.expected, result) + + // Assert that the result is 10 bytes long + require.Len(t, result, 10) + }) + } +}