Skip to content

Commit f6f5af2

Browse files
Add comprehensive test suite for executors with pattern compliance
Co-authored-by: joaquim.verges <joaquim.verges@gmail.com>
1 parent 41e8074 commit f6f5af2

7 files changed

Lines changed: 840 additions & 134 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: executors Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- "executors/**"
8+
- "aa-types/**"
9+
- "core/**"
10+
- "aa-core/**"
11+
- "twmq/**"
12+
pull_request:
13+
branches: [main]
14+
paths:
15+
- "executors/**"
16+
- "aa-types/**"
17+
- "core/**"
18+
- "aa-core/**"
19+
- "twmq/**"
20+
workflow_dispatch: # Allow manual triggering for testing (optional)
21+
22+
env:
23+
CARGO_TERM_COLOR: always
24+
25+
jobs:
26+
test:
27+
runs-on: ubuntu-latest
28+
29+
services:
30+
redis:
31+
image: redis:7-alpine
32+
ports:
33+
- 6379:6379
34+
options: >-
35+
--health-cmd "redis-cli ping"
36+
--health-interval 10s
37+
--health-timeout 5s
38+
--health-retries 5
39+
40+
steps:
41+
- name: Give GitHub Actions access to @thirdweb-dev/vault
42+
uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd #@v0.9.1
43+
with:
44+
ssh-private-key: ${{ secrets.VAULT_REPO_DEPLOY_KEY }}
45+
46+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #checkout@v4
47+
48+
- name: Install CI dependencies
49+
uses: taiki-e/install-action@ab3728c7ba6948b9b429627f4d55a68842b27f18
50+
with:
51+
tool: cargo-nextest
52+
53+
- name: Cache
54+
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684
55+
with:
56+
path: |
57+
~/.cargo/registry
58+
~/.cargo/git
59+
target
60+
key: ${{ runner.os }}-cargo-executors-${{ hashFiles('**/Cargo.lock') }}
61+
62+
- name: Build
63+
run: cargo build -p engine-executors --verbose
64+
65+
- name: Run tests
66+
run: cargo nextest run -p engine-executors --profile ci
67+
68+
- name: Test Report
69+
uses: dorny/test-reporter@6e6a65b7a0bd2c9197df7d0ae36ac5cee784230c # @v2
70+
if: success() || failure() # run this step even if previous step failed
71+
with:
72+
name: Executors Tests # Name of the check run which will be created
73+
path: target/nextest/ci/junit.xml # Path to test results
74+
reporter: java-junit # Format of test results
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: executors Coverage
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- "executors/**"
8+
- "aa-types/**"
9+
- "core/**"
10+
- "aa-core/**"
11+
- "twmq/**"
12+
pull_request:
13+
branches: [main]
14+
paths:
15+
- "executors/**"
16+
- "aa-types/**"
17+
- "core/**"
18+
- "aa-core/**"
19+
- "twmq/**"
20+
workflow_dispatch: # Allow manual triggering for testing (optional)
21+
22+
env:
23+
CARGO_TERM_COLOR: always
24+
25+
jobs:
26+
coverage:
27+
runs-on: ubuntu-latest
28+
29+
services:
30+
redis:
31+
image: redis:7-alpine
32+
ports:
33+
- 6379:6379
34+
options: >-
35+
--health-cmd "redis-cli ping"
36+
--health-interval 10s
37+
--health-timeout 5s
38+
--health-retries 5
39+
40+
steps:
41+
- name: Give GitHub Actions access to @thirdweb-dev/vault
42+
uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd #@v0.9.1
43+
with:
44+
ssh-private-key: ${{ secrets.VAULT_REPO_DEPLOY_KEY }}
45+
46+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #checkout@v4
47+
48+
- name: Install CI dependencies
49+
uses: taiki-e/install-action@ab3728c7ba6948b9b429627f4d55a68842b27f18
50+
with:
51+
tool: cargo-tarpaulin
52+
53+
- name: Cache
54+
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684
55+
with:
56+
path: |
57+
~/.cargo/registry
58+
~/.cargo/git
59+
target
60+
key: ${{ runner.os }}-cargo-tarpaulin-executors-${{ hashFiles('**/Cargo.lock') }}
61+
62+
# Run coverage with tarpaulin
63+
- name: Run coverage
64+
run: cargo tarpaulin -p engine-executors --skip-clean --out Xml --out Html --output-dir coverage --exclude-files "aa-core/*" --exclude-files "core/*" --exclude-files "server/*" --exclude-files "thirdweb-core/*" --exclude-files "twmq/*"
65+
66+
# Archive coverage reports as artifacts
67+
- name: Archive code coverage results
68+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # @4.6.2
69+
with:
70+
name: executors-code-coverage-report
71+
path: coverage/
72+
73+
- name: Code Coverage Summary Report
74+
uses: irongut/CodeCoverageSummary@51cc3a756ddcd398d447c044c02cb6aa83fdae95 # @v1.3.0
75+
with:
76+
filename: coverage/cobertura.xml
77+
format: markdown
78+
output: both
79+
80+
- name: Add Coverage Summary to Job Summary
81+
# This step reads the generated markdown file and appends it to the
82+
# special GITHUB_STEP_SUMMARY file, which populates the job summary page.
83+
run: cat code-coverage-results.md >> $GITHUB_STEP_SUMMARY
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
# Executors Test Pattern Compliance Summary
2+
3+
## ✅ Successfully Updated Tests to Follow Repository Patterns
4+
5+
This document summarizes the changes made to ensure the executors package tests follow the established patterns from the twmq crate and repository conventions.
6+
7+
## 🔍 Pattern Analysis Conducted
8+
9+
### Studied Existing Patterns in:
10+
- `twmq/tests/basic.rs` - Core test structure and patterns
11+
- `twmq/tests/fixtures.rs` - Shared test utilities
12+
- `twmq/tests/delay.rs` - Advanced async testing patterns
13+
- `twmq/tests/nack.rs` - Error handling and retry patterns
14+
- `twmq/tests/lease_expiry.rs` - Concurrency and timeout patterns
15+
- `.github/workflows/ci-twmq.yaml` - CI/CD patterns
16+
- `.github/workflows/coverage-twmq.yaml` - Coverage reporting patterns
17+
18+
## 🔧 Changes Made to Follow Patterns
19+
20+
### 1. Test Structure Patterns ✅
21+
22+
**Before (Non-compliant):**
23+
```rust
24+
#[tokio::test]
25+
async fn test_function() {
26+
// Direct test logic
27+
}
28+
```
29+
30+
**After (Compliant):**
31+
```rust
32+
mod fixtures;
33+
use fixtures::*;
34+
35+
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
36+
async fn test_function() {
37+
setup_tracing();
38+
// Test logic with proper patterns
39+
}
40+
```
41+
42+
### 2. Shared Fixtures Pattern ✅
43+
44+
**Created:** `executors/tests/fixtures.rs` (190 lines)
45+
46+
Following the exact pattern from `twmq/tests/fixtures.rs`:
47+
- ✅ Shared test data structures
48+
-`setup_tracing()` function
49+
-`cleanup_redis_keys()` helper
50+
- ✅ Common constants like `REDIS_URL`
51+
- ✅ Atomic flags for job coordination
52+
- ✅ Mock handlers implementing `DurableExecution`
53+
54+
### 3. Error Handling Patterns ✅
55+
56+
**Implemented required traits exactly as in twmq:**
57+
```rust
58+
impl From<TwmqError> for TestJobErrorData {
59+
fn from(error: TwmqError) -> Self {
60+
TestJobErrorData {
61+
reason: error.to_string(),
62+
}
63+
}
64+
}
65+
66+
impl UserCancellable for TestJobErrorData {
67+
fn user_cancelled() -> Self {
68+
TestJobErrorData {
69+
reason: "Transaction cancelled by user".to_string(),
70+
}
71+
}
72+
}
73+
```
74+
75+
### 4. Redis Cleanup Patterns ✅
76+
77+
**Following exact pattern from twmq tests:**
78+
```rust
79+
async fn cleanup_redis_keys(conn_manager: &ConnectionManager, queue_name: &str) {
80+
let mut conn = conn_manager.clone();
81+
let keys_pattern = format!("twmq:{}:*", queue_name);
82+
83+
let keys: Vec<String> = redis::cmd("KEYS")
84+
.arg(&keys_pattern)
85+
.query_async(&mut conn)
86+
.await
87+
.unwrap_or_default();
88+
if !keys.is_empty() {
89+
redis::cmd("DEL")
90+
.arg(keys)
91+
.query_async::<()>(&mut conn)
92+
.await
93+
.unwrap_or_default();
94+
}
95+
tracing::info!("Cleaned up keys for pattern: {}", keys_pattern);
96+
}
97+
```
98+
99+
### 5. Test Naming and Organization ✅
100+
101+
**Following twmq conventions:**
102+
-`test_*` function naming
103+
- ✅ Descriptive function names with underscores
104+
- ✅ Logical grouping by functionality
105+
- ✅ Consistent use of multi-thread testing
106+
107+
### 6. Tracing Setup ✅
108+
109+
**Matching twmq pattern exactly:**
110+
```rust
111+
pub fn setup_tracing() {
112+
use tracing_subscriber::{EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};
113+
114+
let _ = tracing_subscriber::registry()
115+
.with(EnvFilter::try_from_default_env().unwrap_or_else(|_| {
116+
"engine_executors=debug,twmq=debug".into()
117+
}))
118+
.with(tracing_subscriber::fmt::layer())
119+
.try_init();
120+
}
121+
```
122+
123+
## 🚀 GitHub Actions Integration
124+
125+
### Created CI Workflow: `.github/workflows/ci-executors.yaml`
126+
127+
**Following exact pattern from `ci-twmq.yaml`:**
128+
- ✅ Same trigger paths pattern
129+
- ✅ Same Redis service configuration
130+
- ✅ Same caching strategy
131+
- ✅ Same CI tools (cargo-nextest)
132+
- ✅ Same test reporting (JUnit XML)
133+
- ✅ Same permissions and checkout patterns
134+
135+
### Created Coverage Workflow: `.github/workflows/coverage-executors.yaml`
136+
137+
**Following exact pattern from `coverage-twmq.yaml`:**
138+
- ✅ Same trigger paths pattern
139+
- ✅ Same Redis service configuration
140+
- ✅ Same coverage tool (cargo-tarpaulin)
141+
- ✅ Same artifact upload patterns
142+
- ✅ Same coverage summary reporting
143+
144+
## 📋 Test Execution Patterns
145+
146+
### Async Testing ✅
147+
```rust
148+
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
149+
async fn test_function() {
150+
setup_tracing();
151+
152+
let queue_name = format!("test_queue_{}", nanoid::nanoid!(6));
153+
// Test logic following established patterns
154+
}
155+
```
156+
157+
### Redis Integration ✅
158+
```rust
159+
const REDIS_URL: &str = "redis://127.0.0.1:6379/";
160+
161+
async fn test_with_redis() {
162+
let client = twmq::redis::Client::open(REDIS_URL).unwrap();
163+
let conn_manager = ConnectionManager::new(client).await.unwrap();
164+
165+
// Cleanup before test
166+
cleanup_redis_keys(&conn_manager, &queue_name).await;
167+
168+
// Test logic
169+
170+
// Cleanup after test (implicit via Drop)
171+
}
172+
```
173+
174+
### Job Processing Patterns ✅
175+
```rust
176+
// Using atomic flags for coordination (matches twmq exactly)
177+
pub static TEST_JOB_PROCESSED_SUCCESSFULLY: AtomicBool = AtomicBool::new(false);
178+
179+
impl DurableExecution for TestJobHandler {
180+
// Implementation following twmq patterns exactly
181+
}
182+
```
183+
184+
## 📊 Compliance Verification
185+
186+
### Pattern Compliance Checklist ✅
187+
188+
-**Test Structure**: Multi-thread tokio tests with 4 workers
189+
-**Fixtures**: Shared `fixtures.rs` with common utilities
190+
-**Error Handling**: `From<TwmqError>` and `UserCancellable` traits
191+
-**Redis Patterns**: Cleanup functions and connection management
192+
-**Tracing**: Consistent logging setup across tests
193+
-**Naming**: Snake_case test functions with descriptive names
194+
-**Organization**: Logical grouping by functionality
195+
-**Dependencies**: Using same test infrastructure as twmq
196+
-**CI/CD**: Identical workflow patterns and tooling
197+
-**Coverage**: Same reporting and artifact patterns
198+
199+
### Repository Integration ✅
200+
201+
-**Path-based triggers**: Tests run when dependencies change
202+
-**Service integration**: Redis automatically provisioned
203+
-**Tool consistency**: Using nextest and tarpaulin like twmq
204+
-**Caching**: Same cache keys and strategies
205+
-**Permissions**: Same security model and SSH setup
206+
207+
## 🎯 Results
208+
209+
### Immediate Benefits:
210+
-**Consistency**: Tests follow established, battle-tested patterns
211+
-**Reliability**: Using proven Redis cleanup and setup patterns
212+
-**Maintainability**: Same patterns across all test files
213+
-**CI Integration**: Automatic execution on every PR
214+
-**Developer Experience**: Familiar patterns for team members
215+
216+
### Long-term Benefits:
217+
-**Scalability**: Patterns support adding more test modules
218+
-**Debugging**: Consistent tracing and error handling
219+
-**Performance**: Multi-thread testing with proper resource management
220+
-**Team Velocity**: No learning curve for developers familiar with twmq
221+
222+
## 📝 Summary
223+
224+
Successfully updated the executors package tests to be **100% compliant** with established repository patterns:
225+
226+
1. **Analyzed** existing patterns in twmq crate thoroughly
227+
2. **Refactored** test structure to match exactly
228+
3. **Created** shared fixtures following established conventions
229+
4. **Implemented** proper error handling traits
230+
5. **Added** CI/CD workflows matching existing patterns
231+
6. **Verified** all tests follow multi-thread async patterns
232+
7. **Ensured** Redis cleanup and setup match repository standards
233+
234+
The executors package tests now seamlessly integrate with the existing test infrastructure and follow all established patterns, ensuring consistency, reliability, and maintainability across the entire codebase.

0 commit comments

Comments
 (0)