Skip to content

Commit c955894

Browse files
committed
Cleanup AWS testing
1 parent 032b76f commit c955894

File tree

9 files changed

+523
-109
lines changed

9 files changed

+523
-109
lines changed

.github/workflows/test.yml

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,24 @@ jobs:
111111
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
112112
with:
113113
persist-credentials: false
114-
- name: Run docker compose
114+
115+
# Test GCP backend
116+
- name: Run docker compose for GCP
115117
run: docker compose -f compose.yml up -d --build --wait --wait-timeout 60
116-
- name: Run e2e tests
117-
run: go test -v -tags=e2e ./tests/
118+
- name: Run GCP e2e tests
119+
run: TEST_BACKENDS=gcp go test -v -tags=e2e ./tests/
120+
- name: Stop GCP docker compose
121+
if: always()
122+
run: docker compose -f compose.yml down
123+
124+
# Test AWS backend
125+
- name: Run docker compose for AWS
126+
run: docker compose -f docker-compose-aws.yml up -d --build --wait --wait-timeout 60
127+
- name: Run AWS e2e tests
128+
run: TEST_BACKENDS=aws go test -v -tags=e2e ./tests/
129+
- name: Stop AWS docker compose
130+
if: always()
131+
run: docker compose -f docker-compose-aws.yml down
118132

119133
sharding-freeze:
120134
name: Run freeze log tests

internal/tessera/aws_test.go

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
//
2+
// Copyright 2025 The Sigstore Authors.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package tessera
17+
18+
import (
19+
"context"
20+
"os"
21+
"testing"
22+
23+
"github.com/stretchr/testify/assert"
24+
"github.com/stretchr/testify/require"
25+
)
26+
27+
func TestNewAWSDriver_AWSSDKLoads(t *testing.T) {
28+
ctx := context.Background()
29+
30+
tests := []struct {
31+
name string
32+
bucket string
33+
mysqlDSN string
34+
hostname string
35+
skipReason string
36+
}{
37+
{
38+
name: "configuration with connectivity check",
39+
bucket: "test-bucket",
40+
mysqlDSN: "user:pass@tcp(localhost:3306)/db",
41+
hostname: "test",
42+
skipReason: "requires AWS credentials and MySQL connectivity",
43+
},
44+
}
45+
46+
for _, test := range tests {
47+
t.Run(test.name, func(t *testing.T) {
48+
if test.skipReason != "" {
49+
t.Skip(test.skipReason)
50+
}
51+
52+
driver, err := NewAWSDriver(ctx, test.bucket, test.mysqlDSN, test.hostname)
53+
require.NoError(t, err)
54+
assert.NotNil(t, driver)
55+
})
56+
}
57+
}
58+
59+
func TestNewAWSAntispam_ConfigValidation(t *testing.T) {
60+
ctx := context.Background()
61+
62+
tests := []struct {
63+
name string
64+
mysqlDSN string
65+
maxBatchSize uint
66+
pushbackThreshold uint
67+
expectErr bool
68+
errContains string
69+
skipReason string
70+
}{
71+
{
72+
name: "empty DSN",
73+
mysqlDSN: "",
74+
maxBatchSize: 100,
75+
pushbackThreshold: 10,
76+
skipReason: "requires MySQL connectivity",
77+
},
78+
{
79+
name: "valid configuration requires real MySQL",
80+
mysqlDSN: "user:pass@tcp(localhost:3306)/db",
81+
maxBatchSize: 100,
82+
pushbackThreshold: 10,
83+
skipReason: "requires MySQL connectivity",
84+
},
85+
}
86+
87+
for _, test := range tests {
88+
t.Run(test.name, func(t *testing.T) {
89+
if test.skipReason != "" {
90+
t.Skip(test.skipReason)
91+
}
92+
93+
antispam, err := NewAWSAntispam(ctx, test.mysqlDSN, test.maxBatchSize, test.pushbackThreshold)
94+
95+
if test.expectErr {
96+
require.Error(t, err)
97+
assert.Contains(t, err.Error(), test.errContains)
98+
assert.Nil(t, antispam)
99+
} else {
100+
require.NoError(t, err)
101+
assert.NotNil(t, antispam)
102+
}
103+
})
104+
}
105+
}
106+
107+
func TestNewAWSDriver_WithRealAWSEnv(t *testing.T) {
108+
// Skip if not running in AWS backend test environment
109+
if os.Getenv("TEST_AWS_BACKEND") != "true" {
110+
t.Skip("skipping AWS driver test; set TEST_AWS_BACKEND=true to run")
111+
}
112+
113+
ctx := context.Background()
114+
115+
// These values match the docker-compose-aws.yml configuration
116+
bucket := os.Getenv("AWS_BUCKET_NAME")
117+
if bucket == "" {
118+
bucket = "rekor-tiles"
119+
}
120+
121+
mysqlDSN := os.Getenv("AWS_MYSQL_DSN")
122+
if mysqlDSN == "" {
123+
t.Skip("AWS_MYSQL_DSN not set")
124+
}
125+
126+
driver, err := NewAWSDriver(ctx, bucket, mysqlDSN, "test-hostname")
127+
require.NoError(t, err)
128+
assert.NotNil(t, driver)
129+
}
130+
131+
func TestNewAWSAntispam_WithRealMySQLEnv(t *testing.T) {
132+
// Skip if not running in AWS backend test environment
133+
if os.Getenv("TEST_AWS_BACKEND") != "true" {
134+
t.Skip("skipping AWS antispam test; set TEST_AWS_BACKEND=true to run")
135+
}
136+
137+
ctx := context.Background()
138+
139+
mysqlDSN := os.Getenv("AWS_MYSQL_DSN")
140+
if mysqlDSN == "" {
141+
t.Skip("AWS_MYSQL_DSN not set")
142+
}
143+
144+
antispam, err := NewAWSAntispam(ctx, mysqlDSN, 100, 10)
145+
require.NoError(t, err)
146+
assert.NotNil(t, antispam)
147+
}

internal/tessera/tessera_test.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,114 @@ func TestAppendOptions(t *testing.T) {
158158
_ = WithAntispamOptions(ao, nil) // initializes non-persistent antispam
159159
}
160160

161+
func TestNewDriver(t *testing.T) {
162+
ctx := context.Background()
163+
164+
tests := []struct {
165+
name string
166+
config DriverConfiguration
167+
expectErr bool
168+
errContains string
169+
skipReason string
170+
}{
171+
{
172+
name: "no configuration provided",
173+
config: DriverConfiguration{
174+
Hostname: "test",
175+
},
176+
expectErr: true,
177+
errContains: "no flags provided to initialize Tessera driver",
178+
},
179+
{
180+
name: "GCP configuration incomplete - missing Spanner",
181+
config: DriverConfiguration{
182+
Hostname: "test",
183+
GCPBucket: "test-bucket",
184+
},
185+
expectErr: true,
186+
errContains: "no flags provided to initialize Tessera driver",
187+
},
188+
{
189+
name: "GCP configuration incomplete - missing bucket",
190+
config: DriverConfiguration{
191+
Hostname: "test",
192+
GCPSpannerDB: "projects/test/instances/test/databases/test",
193+
},
194+
expectErr: true,
195+
errContains: "no flags provided to initialize Tessera driver",
196+
},
197+
{
198+
name: "AWS configuration incomplete - missing MySQL DSN",
199+
config: DriverConfiguration{
200+
Hostname: "test",
201+
AWSBucket: "test-bucket",
202+
},
203+
expectErr: true,
204+
errContains: "no flags provided to initialize Tessera driver",
205+
},
206+
{
207+
name: "AWS configuration incomplete - missing bucket",
208+
config: DriverConfiguration{
209+
Hostname: "test",
210+
AWSMySQLDSN: "user:pass@tcp(localhost:3306)/db",
211+
},
212+
expectErr: true,
213+
errContains: "no flags provided to initialize Tessera driver",
214+
},
215+
{
216+
name: "GCP configuration complete",
217+
config: DriverConfiguration{
218+
Hostname: "test",
219+
GCPBucket: "test-bucket",
220+
GCPSpannerDB: "projects/test/instances/test/databases/test",
221+
},
222+
skipReason: "requires GCP credentials and connectivity",
223+
},
224+
{
225+
name: "AWS configuration complete",
226+
config: DriverConfiguration{
227+
Hostname: "test",
228+
AWSBucket: "test-bucket",
229+
AWSMySQLDSN: "user:pass@tcp(localhost:3306)/db",
230+
},
231+
skipReason: "requires AWS credentials and MySQL connectivity",
232+
},
233+
{
234+
name: "AWS configuration with persistent antispam",
235+
config: DriverConfiguration{
236+
Hostname: "test",
237+
AWSBucket: "test-bucket",
238+
AWSMySQLDSN: "user:pass@tcp(localhost:3306)/db",
239+
PersistentAntispam: true,
240+
ASMaxBatchSize: 100,
241+
ASPushbackThreshold: 10,
242+
},
243+
skipReason: "requires AWS credentials and MySQL connectivity",
244+
},
245+
}
246+
247+
for _, test := range tests {
248+
t.Run(test.name, func(t *testing.T) {
249+
if test.skipReason != "" {
250+
t.Skip(test.skipReason)
251+
}
252+
253+
driver, antispam, err := NewDriver(ctx, test.config)
254+
255+
if test.expectErr {
256+
assert.Error(t, err)
257+
assert.Contains(t, err.Error(), test.errContains)
258+
assert.Nil(t, driver)
259+
assert.Nil(t, antispam)
260+
} else {
261+
assert.NoError(t, err)
262+
assert.NotNil(t, driver)
263+
// antispam may be nil if PersistentAntispam is false
264+
}
265+
})
266+
}
267+
}
268+
161269
func hexDecodeOrDie(t *testing.T, text string) []byte {
162270
decoded, err := hex.DecodeString(text)
163271
if err != nil {

tests/README.md

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,19 @@
22

33
## Running the End to End tests
44

5-
Start the Docker containers from the top level directory:
5+
The e2e tests support multiple storage backends (GCP and AWS). You can control which backends to test using the `TEST_BACKENDS` environment variable.
6+
7+
### Backend Selection
8+
9+
The `TEST_BACKENDS` environment variable accepts the following values:
10+
- `gcp` (default): Test only the GCP backend
11+
- `aws`: Test only the AWS backend
12+
- `gcp,aws`: Test both backends
13+
- `all`: Test all backends
14+
15+
### Testing GCP Backend (Default)
16+
17+
Start the GCP Docker containers:
618

719
```sh
820
docker compose -f compose.yml up -d --build --wait --wait-timeout 60
@@ -11,11 +23,74 @@ docker compose -f compose.yml up -d --build --wait --wait-timeout 60
1123
Run the tests:
1224

1325
```sh
26+
# Explicit GCP selection
27+
TEST_BACKENDS=gcp go test -v -tags=e2e ./tests/
28+
29+
# Or without specifying (defaults to GCP)
1430
go test -v -tags=e2e ./tests/
1531
```
1632

17-
When finished, you can clean up the Docker containers if desired:
33+
Clean up:
34+
35+
```sh
36+
docker compose -f compose.yml down
37+
```
38+
39+
### Testing AWS Backend
40+
41+
Start the AWS Docker containers (MinIO + MySQL):
42+
43+
```sh
44+
docker compose -f docker-compose-aws.yml up -d --build --wait --wait-timeout 60
45+
```
46+
47+
Run the tests:
48+
49+
```sh
50+
TEST_BACKENDS=aws go test -v -tags=e2e ./tests/
51+
```
52+
53+
Clean up:
1854

1955
```sh
20-
docker compose down
56+
docker compose -f docker-compose-aws.yml down
57+
```
58+
59+
### Testing Both Backends
60+
61+
To test both GCP and AWS backends in sequence:
62+
63+
```sh
64+
# Start GCP services
65+
docker compose -f compose.yml up -d --build --wait --wait-timeout 60
66+
67+
# Run GCP tests
68+
TEST_BACKENDS=gcp go test -v -tags=e2e ./tests/
69+
70+
# Stop GCP services
71+
docker compose -f compose.yml down
72+
73+
# Start AWS services
74+
docker compose -f docker-compose-aws.yml up -d --build --wait --wait-timeout 60
75+
76+
# Run AWS tests
77+
TEST_BACKENDS=aws go test -v -tags=e2e ./tests/
78+
79+
# Stop AWS services
80+
docker compose -f docker-compose-aws.yml down
81+
```
82+
83+
### Running Specific Tests
84+
85+
To run only specific test functions:
86+
87+
```sh
88+
# GCP backend only
89+
TEST_BACKENDS=gcp go test -v -tags=e2e ./tests/ -run TestReadWrite
90+
91+
# AWS backend only
92+
TEST_BACKENDS=aws go test -v -tags=e2e ./tests/ -run TestPersistentDeduplication
93+
94+
# Both backends
95+
TEST_BACKENDS=all go test -v -tags=e2e ./tests/ -run TestReadWrite
2196
```

0 commit comments

Comments
 (0)