From d7d2d4960ab0d2c7e99610ed85bdc22a5be6b91a Mon Sep 17 00:00:00 2001 From: Rodrigo Arguello Date: Mon, 23 Sep 2024 14:51:15 +0200 Subject: [PATCH] chore: run ddapm-test-agent in docker --- .github/workflows/validate.yml | 8 - .github/workflows/workflow_call.yml | 8 - _integration-tests/README.md | 9 +- _integration-tests/tests/aws.v1/aws.go | 4 +- _integration-tests/tests/aws.v2/base.go | 4 +- .../tests/gcp_pubsub/gcp_pubsub.go | 6 +- .../tests/go-redis.v7/go-redis.go | 10 +- .../tests/go-redis.v8/go-redis.go | 10 +- .../tests/go-redis.v9/go-redis.go | 7 +- _integration-tests/tests/gocql/base.go | 6 +- .../tests/ibm_sarama/ibm_sarama.go | 10 +- _integration-tests/tests/mongo/mongo.go | 12 +- _integration-tests/tests/redigo/redigo.go | 9 +- .../tests/shopify_sarama/shopify_sarama.go | 6 +- _integration-tests/tests/vault/vault.go | 10 +- _integration-tests/utils/agent/agent.go | 215 +++++++----------- .../utils/agent/requirements.txt | 19 -- _integration-tests/utils/suite.go | 25 +- .../logs.go} | 2 +- .../{ => testcontainers}/testcontainers.go | 8 +- 20 files changed, 144 insertions(+), 244 deletions(-) delete mode 100644 _integration-tests/utils/agent/requirements.txt rename _integration-tests/utils/{containerlogs.go => testcontainers/logs.go} (96%) rename _integration-tests/utils/{ => testcontainers}/testcontainers.go (89%) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 9e3b416d..640ad914 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -257,14 +257,6 @@ jobs: with: go-version: ${{ matrix.go-version }} cache-dependency-path: "**/go.mod" - - name: Setup python - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5 - with: - python-version: 3.x - cache: pip - cache-dependency-path: _integration-tests/utils/agent/requirements.txt - - name: Install python dependencies - run: pip install -r _integration-tests/utils/agent/requirements.txt - name: Build orchestrion binary shell: bash run: |- diff --git a/.github/workflows/workflow_call.yml b/.github/workflows/workflow_call.yml index 1a155b6f..7ce94267 100644 --- a/.github/workflows/workflow_call.yml +++ b/.github/workflows/workflow_call.yml @@ -51,14 +51,6 @@ jobs: with: go-version: stable cache-dependency-path: "**/go.mod" - - name: Setup python - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5 - with: - python-version: 3.x - cache: pip - cache-dependency-path: orchestrion/_integration-tests/utils/agent/requirements.txt - - name: Install python dependencies - run: pip install -r orchestrion/_integration-tests/utils/agent/requirements.txt - name: Build orchestrion binary run: go -C orchestrion/ build -o="./_integration-tests/orchestrion.exe" . - name: Run Integration Tests diff --git a/_integration-tests/README.md b/_integration-tests/README.md index 2974adfa..8848b617 100644 --- a/_integration-tests/README.md +++ b/_integration-tests/README.md @@ -9,15 +9,8 @@ Each test is a directory within the `tests` directory. This directory must conta ## Running Tests Locally Tests can be run locally with `go test`, using Orchestrion. -First, install the `ddapm-test-agent` if you haven't already: -``` console -$ python3 -m venv venv -$ source ./venv/bin/activate -$ pip install -r ./utils/agent/requirements.txt -``` - -Then, ensure that Docker is installed and the daemon is running. +First, ensure that Docker is installed and the daemon is running. Then, compile Orchestrion and use it to run the tests: diff --git a/_integration-tests/tests/aws.v1/aws.go b/_integration-tests/tests/aws.v1/aws.go index 665d9946..b1e39517 100644 --- a/_integration-tests/tests/aws.v1/aws.go +++ b/_integration-tests/tests/aws.v1/aws.go @@ -20,7 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" - "orchestrion/integration/utils" + testcontainersutils "orchestrion/integration/utils/testcontainers" "orchestrion/integration/validator/trace" ) @@ -30,7 +30,7 @@ type TestCase struct { } func (tc *TestCase) Setup(t *testing.T) { - server, host, port := utils.StartDynamoDBTestContainer(t) + server, host, port := testcontainersutils.StartDynamoDBTestContainer(t) tc.server = server tc.cfg = &aws.Config{ diff --git a/_integration-tests/tests/aws.v2/base.go b/_integration-tests/tests/aws.v2/base.go index 88fb3d00..1019b679 100644 --- a/_integration-tests/tests/aws.v2/base.go +++ b/_integration-tests/tests/aws.v2/base.go @@ -18,7 +18,7 @@ import ( "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" - "orchestrion/integration/utils" + testcontainersutils "orchestrion/integration/utils/testcontainers" "orchestrion/integration/validator/trace" ) @@ -30,7 +30,7 @@ type base struct { } func (b *base) setup(t *testing.T) { - b.server, b.host, b.port = utils.StartDynamoDBTestContainer(t) + b.server, b.host, b.port = testcontainersutils.StartDynamoDBTestContainer(t) } func (b *base) teardown(t *testing.T) { diff --git a/_integration-tests/tests/gcp_pubsub/gcp_pubsub.go b/_integration-tests/tests/gcp_pubsub/gcp_pubsub.go index 95d4f4e8..5713d63d 100644 --- a/_integration-tests/tests/gcp_pubsub/gcp_pubsub.go +++ b/_integration-tests/tests/gcp_pubsub/gcp_pubsub.go @@ -21,7 +21,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - "orchestrion/integration/utils" + testcontainersutils "orchestrion/integration/utils/testcontainers" "orchestrion/integration/validator/trace" ) @@ -47,9 +47,9 @@ func (tc *TestCase) Setup(t *testing.T) { "gcr.io/google.com/cloudsdktool/cloud-sdk:490.0.0-emulators", gcloud.WithProjectID("pstest-orchestrion"), testcontainers.WithLogger(testcontainers.TestLogger(t)), - utils.WithTestLogConsumer(t), + testcontainersutils.WithTestLogConsumer(t), ) - utils.AssertTestContainersError(t, err) + testcontainersutils.AssertError(t, err) projectID := tc.container.Settings.ProjectID diff --git a/_integration-tests/tests/go-redis.v7/go-redis.go b/_integration-tests/tests/go-redis.v7/go-redis.go index eb965873..77727cc7 100644 --- a/_integration-tests/tests/go-redis.v7/go-redis.go +++ b/_integration-tests/tests/go-redis.v7/go-redis.go @@ -11,11 +11,10 @@ import ( "context" "log" "net/url" - "orchestrion/integration/utils" - "orchestrion/integration/validator/trace" "testing" "time" + "github.com/go-redis/redis/v7" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" @@ -23,7 +22,8 @@ import ( "github.com/testcontainers/testcontainers-go/wait" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" - "github.com/go-redis/redis/v7" + testcontainersutils "orchestrion/integration/utils/testcontainers" + "orchestrion/integration/validator/trace" ) type TestCase struct { @@ -38,7 +38,7 @@ func (tc *TestCase) Setup(t *testing.T) { tc.server, err = testredis.Run(ctx, "redis:7", testcontainers.WithLogger(testcontainers.TestLogger(t)), - utils.WithTestLogConsumer(t), + testcontainersutils.WithTestLogConsumer(t), testcontainers.WithWaitStrategy( wait.ForAll( wait.ForLog("* Ready to accept connections"), @@ -47,7 +47,7 @@ func (tc *TestCase) Setup(t *testing.T) { ), ), ) - utils.AssertTestContainersError(t, err) + testcontainersutils.AssertError(t, err) redisURI, err := tc.server.ConnectionString(ctx) if err != nil { diff --git a/_integration-tests/tests/go-redis.v8/go-redis.go b/_integration-tests/tests/go-redis.v8/go-redis.go index dbed6606..9a47f6bd 100644 --- a/_integration-tests/tests/go-redis.v8/go-redis.go +++ b/_integration-tests/tests/go-redis.v8/go-redis.go @@ -11,11 +11,10 @@ import ( "context" "log" "net/url" - "orchestrion/integration/utils" - "orchestrion/integration/validator/trace" "testing" "time" + "github.com/go-redis/redis/v8" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" @@ -23,7 +22,8 @@ import ( "github.com/testcontainers/testcontainers-go/wait" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" - "github.com/go-redis/redis/v8" + testcontainersutils "orchestrion/integration/utils/testcontainers" + "orchestrion/integration/validator/trace" ) type TestCase struct { @@ -38,7 +38,7 @@ func (tc *TestCase) Setup(t *testing.T) { tc.server, err = testredis.Run(ctx, "redis:7", testcontainers.WithLogger(testcontainers.TestLogger(t)), - utils.WithTestLogConsumer(t), + testcontainersutils.WithTestLogConsumer(t), testcontainers.WithWaitStrategy( wait.ForAll( wait.ForLog("* Ready to accept connections"), @@ -47,7 +47,7 @@ func (tc *TestCase) Setup(t *testing.T) { ), ), ) - utils.AssertTestContainersError(t, err) + testcontainersutils.AssertError(t, err) redisURI, err := tc.server.ConnectionString(ctx) if err != nil { diff --git a/_integration-tests/tests/go-redis.v9/go-redis.go b/_integration-tests/tests/go-redis.v9/go-redis.go index 7df5ca5e..1778f08c 100644 --- a/_integration-tests/tests/go-redis.v9/go-redis.go +++ b/_integration-tests/tests/go-redis.v9/go-redis.go @@ -11,8 +11,6 @@ import ( "context" "log" "net/url" - "orchestrion/integration/utils" - "orchestrion/integration/validator/trace" "testing" "time" @@ -23,6 +21,9 @@ import ( testredis "github.com/testcontainers/testcontainers-go/modules/redis" "github.com/testcontainers/testcontainers-go/wait" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + + testcontainersutils "orchestrion/integration/utils/testcontainers" + "orchestrion/integration/validator/trace" ) type TestCase struct { @@ -37,7 +38,7 @@ func (tc *TestCase) Setup(t *testing.T) { tc.server, err = testredis.Run(ctx, "redis:7", testcontainers.WithLogger(testcontainers.TestLogger(t)), - utils.WithTestLogConsumer(t), + testcontainersutils.WithTestLogConsumer(t), testcontainers.WithWaitStrategy( wait.ForAll( wait.ForLog("* Ready to accept connections"), diff --git a/_integration-tests/tests/gocql/base.go b/_integration-tests/tests/gocql/base.go index 64f545b0..e79820d5 100644 --- a/_integration-tests/tests/gocql/base.go +++ b/_integration-tests/tests/gocql/base.go @@ -20,7 +20,7 @@ import ( testcassandra "github.com/testcontainers/testcontainers-go/modules/cassandra" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" - "orchestrion/integration/utils" + testcontainersutils "orchestrion/integration/utils/testcontainers" "orchestrion/integration/validator/trace" ) @@ -38,9 +38,9 @@ func (b *base) setup(t *testing.T) { b.container, err = testcassandra.Run(ctx, "cassandra:4.1", testcontainers.WithLogger(testcontainers.TestLogger(t)), - utils.WithTestLogConsumer(t), + testcontainersutils.WithTestLogConsumer(t), ) - utils.AssertTestContainersError(t, err) + testcontainersutils.AssertError(t, err) b.hostPort, err = b.container.ConnectionHost(ctx) require.NoError(t, err) diff --git a/_integration-tests/tests/ibm_sarama/ibm_sarama.go b/_integration-tests/tests/ibm_sarama/ibm_sarama.go index 3d8521ef..c9ae6762 100644 --- a/_integration-tests/tests/ibm_sarama/ibm_sarama.go +++ b/_integration-tests/tests/ibm_sarama/ibm_sarama.go @@ -13,14 +13,14 @@ import ( "testing" "time" - "orchestrion/integration/utils" - "orchestrion/integration/validator/trace" - "github.com/IBM/sarama" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/redpanda" + + testcontainersutils "orchestrion/integration/utils/testcontainers" + "orchestrion/integration/validator/trace" ) const ( @@ -47,9 +47,9 @@ func (tc *TestCase) Setup(t *testing.T) { "docker.redpanda.com/redpandadata/redpanda:v24.2.1", redpanda.WithAutoCreateTopics(), testcontainers.WithLogger(testcontainers.TestLogger(t)), - utils.WithTestLogConsumer(t), + testcontainersutils.WithTestLogConsumer(t), ) - utils.AssertTestContainersError(t, err) + testcontainersutils.AssertError(t, err) addr, err := tc.server.KafkaSeedBroker(ctx) require.NoError(t, err, "failed to get seed broker address") diff --git a/_integration-tests/tests/mongo/mongo.go b/_integration-tests/tests/mongo/mongo.go index e6d8b3cb..af1a636b 100644 --- a/_integration-tests/tests/mongo/mongo.go +++ b/_integration-tests/tests/mongo/mongo.go @@ -11,8 +11,6 @@ import ( "context" "log" "net/url" - "orchestrion/integration/utils" - "orchestrion/integration/validator/trace" "testing" "time" @@ -20,11 +18,13 @@ import ( "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" testmongo "github.com/testcontainers/testcontainers-go/modules/mongodb" - "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" - "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" + "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + + testcontainersutils "orchestrion/integration/utils/testcontainers" + "orchestrion/integration/validator/trace" ) type TestCase struct { @@ -39,9 +39,9 @@ func (tc *TestCase) Setup(t *testing.T) { tc.server, err = testmongo.Run(ctx, "mongo:6", testcontainers.WithLogger(testcontainers.TestLogger(t)), - utils.WithTestLogConsumer(t), + testcontainersutils.WithTestLogConsumer(t), ) - utils.AssertTestContainersError(t, err) + testcontainersutils.AssertError(t, err) mongoURI, err := tc.server.ConnectionString(ctx) if err != nil { diff --git a/_integration-tests/tests/redigo/redigo.go b/_integration-tests/tests/redigo/redigo.go index cb38d22e..e30089ed 100644 --- a/_integration-tests/tests/redigo/redigo.go +++ b/_integration-tests/tests/redigo/redigo.go @@ -11,8 +11,6 @@ import ( "context" "log" "net/url" - "orchestrion/integration/utils" - "orchestrion/integration/validator/trace" "testing" "time" @@ -23,6 +21,9 @@ import ( testredis "github.com/testcontainers/testcontainers-go/modules/redis" "github.com/testcontainers/testcontainers-go/wait" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + + testcontainersutils "orchestrion/integration/utils/testcontainers" + "orchestrion/integration/validator/trace" ) type TestCase struct { @@ -37,7 +38,7 @@ func (tc *TestCase) Setup(t *testing.T) { tc.server, err = testredis.Run(ctx, "redis:7", testcontainers.WithLogger(testcontainers.TestLogger(t)), - utils.WithTestLogConsumer(t), + testcontainersutils.WithTestLogConsumer(t), testcontainers.WithWaitStrategy( wait.ForAll( wait.ForLog("* Ready to accept connections"), @@ -46,7 +47,7 @@ func (tc *TestCase) Setup(t *testing.T) { ), ), ) - utils.AssertTestContainersError(t, err) + testcontainersutils.AssertError(t, err) redisURI, err := tc.server.ConnectionString(ctx) if err != nil { diff --git a/_integration-tests/tests/shopify_sarama/shopify_sarama.go b/_integration-tests/tests/shopify_sarama/shopify_sarama.go index 1de7bdef..b80e7dd3 100644 --- a/_integration-tests/tests/shopify_sarama/shopify_sarama.go +++ b/_integration-tests/tests/shopify_sarama/shopify_sarama.go @@ -9,10 +9,10 @@ package shopify_sarama import ( "context" + testcontainersutils "orchestrion/integration/utils/testcontainers" "testing" "time" - "orchestrion/integration/utils" "orchestrion/integration/validator/trace" "github.com/Shopify/sarama" @@ -46,9 +46,9 @@ func (tc *TestCase) Setup(t *testing.T) { "docker.redpanda.com/redpandadata/redpanda:v24.2.1", redpanda.WithAutoCreateTopics(), testcontainers.WithLogger(testcontainers.TestLogger(t)), - utils.WithTestLogConsumer(t), + testcontainersutils.WithTestLogConsumer(t), ) - utils.AssertTestContainersError(t, err) + testcontainersutils.AssertError(t, err) addr, err := tc.server.KafkaSeedBroker(ctx) require.NoError(t, err, "failed to get seed broker address") diff --git a/_integration-tests/tests/vault/vault.go b/_integration-tests/tests/vault/vault.go index 60a6502e..d19f078b 100644 --- a/_integration-tests/tests/vault/vault.go +++ b/_integration-tests/tests/vault/vault.go @@ -12,14 +12,14 @@ import ( "testing" "time" - "orchestrion/integration/utils" - "orchestrion/integration/validator/trace" - "github.com/hashicorp/vault/api" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" testvault "github.com/testcontainers/testcontainers-go/modules/vault" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + + testcontainersutils "orchestrion/integration/utils/testcontainers" + "orchestrion/integration/validator/trace" ) type TestCase struct { @@ -34,10 +34,10 @@ func (tc *TestCase) Setup(t *testing.T) { tc.server, err = testvault.Run(ctx, "vault:1.7.3", testcontainers.WithLogger(testcontainers.TestLogger(t)), - utils.WithTestLogConsumer(t), + testcontainersutils.WithTestLogConsumer(t), testvault.WithToken("root"), ) - utils.AssertTestContainersError(t, err) + testcontainersutils.AssertError(t, err) addr, err := tc.server.HttpHostAddress(ctx) if err != nil { diff --git a/_integration-tests/utils/agent/agent.go b/_integration-tests/utils/agent/agent.go index 24687ca0..ec5c3670 100644 --- a/_integration-tests/utils/agent/agent.go +++ b/_integration-tests/utils/agent/agent.go @@ -7,30 +7,26 @@ package agent import ( "context" - "errors" "fmt" "io" - "net" "net/http" - "os" - "os/exec" - "path/filepath" - "runtime" - "sync/atomic" "testing" "time" + "github.com/docker/go-connections/nat" "github.com/google/uuid" - + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + + testcontainersutils "orchestrion/integration/utils/testcontainers" + "orchestrion/integration/validator/trace" ) type MockAgent struct { - virtualEnv string - process *exec.Cmd - processCancel context.CancelFunc - currentSession atomic.Pointer[Session] - port int + host string + port int } type Session struct { @@ -38,92 +34,69 @@ type Session struct { token uuid.UUID } -func New(t *testing.T) (*MockAgent, error) { - var ( - agent MockAgent - err error - ) - - ddapmTestAgent, _ := exec.LookPath("ddapm-test-agent") - if ddapmTestAgent == "" { - t.Log("No ddapm-test-agent found in $PATH, installing into a python venv...") - if agent.virtualEnv, err = os.MkdirTemp("", "orchestrion-integ-venv-*"); err != nil { - return nil, err - } - t.Logf("Creating Python venv at %q...\n", agent.virtualEnv) - if err = exec.Command("python3", "-m", "venv", agent.virtualEnv).Run(); err != nil { - return nil, err - } - venvBin := filepath.Join(agent.virtualEnv, "bin") - if runtime.GOOS == "windows" { - venvBin = filepath.Join(agent.virtualEnv, "Scripts") - } - - t.Logf("Installing requirements in venv...\n") - _, thisFile, _, _ := runtime.Caller(0) - thisDir := filepath.Dir(thisFile) - if err = exec.Command(filepath.Join(venvBin, "pip"), "install", "-r", filepath.Join(thisDir, "requirements.txt")).Run(); err != nil { - return nil, err - } - - ddapmTestAgent = filepath.Join(venvBin, "ddapm-test-agent") - } - - if agent.port, err = getFreePort(); err != nil { - return nil, err - } - t.Logf("Starting %s on port %d\n", ddapmTestAgent, agent.port) - var ctx context.Context - ctx, agent.processCancel = context.WithCancel(context.Background()) - agent.process = exec.CommandContext( - ctx, - ddapmTestAgent, - fmt.Sprintf("--port=%d", agent.port), - ) - if err = agent.process.Start(); err != nil { - return nil, err +func New(t *testing.T) *MockAgent { + t.Helper() + ctx := context.Background() + exposedPort := "8126/tcp" + + agentContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ContainerRequest: testcontainers.ContainerRequest{ + Name: "orchestrion_integration_tests", + Image: "ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:latest", + ExposedPorts: []string{exposedPort}, + WaitingFor: wait.ForListeningPort(nat.Port(exposedPort)), + LogConsumerCfg: &testcontainers.LogConsumerConfig{ + Consumers: []testcontainers.LogConsumer{testcontainersutils.TestLogConsumer(t)}, + }, + }, + Started: true, + Reuse: true, + Logger: testcontainers.TestLogger(t), + }) + testcontainersutils.AssertError(t, err) + + mappedPort, err := agentContainer.MappedPort(ctx, nat.Port(exposedPort)) + require.NoError(t, err) + + host, err := agentContainer.Host(ctx) + require.NoError(t, err) + + return &MockAgent{ + host: host, + port: mappedPort.Int(), } +} - return &agent, nil +func (a *MockAgent) Addr() string { + return fmt.Sprintf("%s:%d", a.host, a.port) } -func (a *MockAgent) NewSession(t *testing.T) (session *Session, err error) { +func (a *MockAgent) NewSession(t *testing.T) *Session { + t.Helper() token, err := uuid.NewRandom() - if err != nil { - return nil, err - } - session = &Session{agent: a, token: token} - if !a.currentSession.CompareAndSwap(nil, session) { - return nil, errors.New("a test session is already in progress") - } - defer func() { - if err != nil { - a.currentSession.Store(nil) - session = nil - } - }() + require.NoError(t, err) + + session := &Session{agent: a, token: token} ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() - req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("http://127.0.0.1:%d/test/session/start?test_session_token=%s", a.port, session.token.String()), nil) - if err != nil { - return nil, err - } + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("http://%s/test/session/start?test_session_token=%s", a.Addr(), session.token.String()), nil) + require.NoError(t, err) for { resp, err := http.DefaultClient.Do(req) if err != nil { select { case <-ctx.Done(): - return nil, err + require.FailNow(t, "timeout trying to create mock agent test session") default: time.Sleep(100 * time.Millisecond) continue } } if resp.StatusCode != 200 { - return nil, errors.New("test agent returned non-200 status code") + require.FailNow(t, "test agent returned non-200 status code") } break } @@ -131,73 +104,57 @@ func (a *MockAgent) NewSession(t *testing.T) (session *Session, err error) { t.Logf("Started test session with ID %s\n", session.token.String()) tracer.Start( - tracer.WithAgentAddr(fmt.Sprintf("127.0.0.1:%d", a.port)), + tracer.WithAgentAddr(a.Addr()), tracer.WithSampler(tracer.NewAllSampler()), tracer.WithLogStartup(false), tracer.WithLogger(testLogger{t}), + tracer.WithHTTPClient(&http.Client{ + Transport: &sessionTokenTransport{ + rt: http.DefaultTransport, + sessionToken: token.String(), + }, + Timeout: 10 * time.Second, + }), ) + t.Cleanup(tracer.Stop) - return session, nil + return session } -type testLogger struct { - *testing.T -} - -func (l testLogger) Log(msg string) { - l.T.Log(msg) -} - -func (a *MockAgent) Close() error { - if !a.currentSession.CompareAndSwap(nil, nil) { - return errors.New("cannot close agent while a test session is in progress") - } - - a.processCancel() - if err := a.process.Wait(); err != nil { - return err - } - - return os.RemoveAll(a.virtualEnv) -} - -func (s *Session) Port() int { - return s.agent.port -} - -func (s *Session) Close(t *testing.T) ([]byte, error) { - if !s.agent.currentSession.CompareAndSwap(s, nil) { - return nil, errors.New("cannot close session that is not the currently active one") - } - +func (s *Session) Spans(t *testing.T) trace.Spans { + t.Helper() tracer.Flush() tracer.Stop() - t.Logf("Closing test session with ID %s\n", s.token.String()) + t.Logf("Fetching spans from test-agent using session ID %s\n", s.token.String()) resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/test/session/traces?test_session_token=%s", s.agent.port, s.token.String())) - if err != nil { - return nil, err - } + require.NoError(t, err) defer resp.Body.Close() data, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } + require.NoError(t, err) + + var spans trace.Spans + require.NoError(t, trace.ParseRaw(data, &spans)) + t.Logf("Received %d spans", len(spans)) - return data, nil + return spans } -func getFreePort() (int, error) { - addr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0") - if err != nil { - return 0, err - } +type sessionTokenTransport struct { + rt http.RoundTripper + sessionToken string +} - listener, err := net.ListenTCP("tcp", addr) - if err != nil { - return 0, err - } - defer listener.Close() - return listener.Addr().(*net.TCPAddr).Port, nil +func (s *sessionTokenTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req.Header.Add("X-Datadog-Test-Session-Token", s.sessionToken) + return s.rt.RoundTrip(req) +} + +type testLogger struct { + *testing.T +} + +func (l testLogger) Log(msg string) { + l.T.Log(msg) } diff --git a/_integration-tests/utils/agent/requirements.txt b/_integration-tests/utils/agent/requirements.txt deleted file mode 100644 index 91be3473..00000000 --- a/_integration-tests/utils/agent/requirements.txt +++ /dev/null @@ -1,19 +0,0 @@ -ddapm-test-agent==1.18.0 -## The following requirements were added by pip freeze: -aiohappyeyeballs==2.4.0 -aiohttp==3.10.5 -aiosignal==1.3.1 -attrs==24.2.0 -certifi==2024.8.30 -charset-normalizer==3.3.2 -ddsketch==3.0.1 -frozenlist==1.4.1 -idna==3.10 -msgpack==1.1.0 -multidict==6.1.0 -protobuf==5.28.2 -requests==2.32.3 -six==1.16.0 -typing_extensions==4.12.2 -urllib3==2.2.3 -yarl==1.11.1 diff --git a/_integration-tests/utils/suite.go b/_integration-tests/utils/suite.go index a53dde9e..20d26aed 100644 --- a/_integration-tests/utils/suite.go +++ b/_integration-tests/utils/suite.go @@ -54,9 +54,7 @@ func RunTest(t *testing.T, tc TestCase) { t.Helper() require.True(t, orchestrionEnabled, "this test suite must be run with orchestrion enabled") - mockAgent, err := agent.New(t) - require.NoError(t, err) - defer mockAgent.Close() + mockAgent := agent.New(t) t.Log("Running setup") tc.Setup(t) @@ -66,28 +64,13 @@ func RunTest(t *testing.T, tc TestCase) { tc.Teardown(t) }() - sess, err := mockAgent.NewSession(t) - require.NoError(t, err) - - // Defer this, so it runs even if the test panics (e.g, as the result of a failed assertion). - // If this does not happen, the test session will remain open; which is undesirable. - defer checkTrace(t, tc, sess) + sess := mockAgent.NewSession(t) t.Log("Running test") tc.Run(t) -} - -func checkTrace(t *testing.T, tc TestCase, sess *agent.Session) { - t.Helper() - - jsonTraces, err := sess.Close(t) - require.NoError(t, err) - - var traces trace.Spans - require.NoError(t, trace.ParseRaw(jsonTraces, &traces)) - t.Logf("Received %d traces", len(traces)) + spans := sess.Spans(t) for _, expected := range tc.ExpectedTraces() { - expected.RequireAnyMatch(t, traces) + expected.RequireAnyMatch(t, spans) } } diff --git a/_integration-tests/utils/containerlogs.go b/_integration-tests/utils/testcontainers/logs.go similarity index 96% rename from _integration-tests/utils/containerlogs.go rename to _integration-tests/utils/testcontainers/logs.go index 64c1662e..b92938f6 100644 --- a/_integration-tests/utils/containerlogs.go +++ b/_integration-tests/utils/testcontainers/logs.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2023-present Datadog, Inc. -package utils +package testcontainers import ( "testing" diff --git a/_integration-tests/utils/testcontainers.go b/_integration-tests/utils/testcontainers/testcontainers.go similarity index 89% rename from _integration-tests/utils/testcontainers.go rename to _integration-tests/utils/testcontainers/testcontainers.go index 6d5b3c7f..d7ee33c5 100644 --- a/_integration-tests/utils/testcontainers.go +++ b/_integration-tests/utils/testcontainers/testcontainers.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2023-present Datadog, Inc. -package utils +package testcontainers import ( "context" @@ -42,7 +42,7 @@ func StartDynamoDBTestContainer(t *testing.T) (testcontainers.Container, string, ctx := context.Background() server, err := testcontainers.GenericContainer(ctx, req) - AssertTestContainersError(t, err) + AssertError(t, err) mappedPort, err := server.MappedPort(ctx, nat.Port(exposedPort)) require.NoError(t, err) @@ -53,9 +53,9 @@ func StartDynamoDBTestContainer(t *testing.T) (testcontainers.Container, string, return server, host, mappedPort.Port() } -// AssertTestContainersError decides whether the provided testcontainers error should make the test fail or mark it as +// AssertError decides whether the provided testcontainers error should make the test fail or mark it as // skipped, depending on the environment where the test is running. -func AssertTestContainersError(t *testing.T, err error) { +func AssertError(t *testing.T, err error) { if err == nil { return }