Skip to content

Commit 716818c

Browse files
committed
test: replace sqlx::test with postgres testcontainers
Signed-off-by: Joseph Livesey <[email protected]>
1 parent c3a4f1c commit 716818c

File tree

22 files changed

+1193
-384
lines changed

22 files changed

+1193
-384
lines changed

Cargo.lock

Lines changed: 261 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ tap_core = { version = "4.1.4", default-features = false }
8888
tap_graph = { version = "0.3.4", features = ["v2"] }
8989
tempfile = "3.8.0"
9090
test-log = { version = "0.2.12", default-features = false }
91+
testcontainers-modules = { version = "0.12.1", features = ["postgres"] }
9192
test-with = "0.14.6"
9293
thegraph-core = { version = "0.15.1", features = [
9394
"attestation",

crates/dips/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ serde_json.workspace = true
3939
[dev-dependencies]
4040
rand.workspace = true
4141
indexer-watcher = { path = "../watcher" }
42+
testcontainers-modules = { workspace = true, features = ["postgres"] }
43+
test-assets = { path = "../test-assets" }
4244

4345
[build-dependencies]
4446
tonic-build = { workspace = true, optional = true }

crates/dips/src/database.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ pub(crate) mod test {
135135
use std::sync::Arc;
136136

137137
use build_info::chrono::Duration;
138-
use sqlx::PgPool;
139138
use thegraph_core::alloy::{
140139
primitives::{ruint::aliases::U256, Address},
141140
sol_types::SolValue,
@@ -145,9 +144,10 @@ pub(crate) mod test {
145144
use super::*;
146145
use crate::{CancellationRequest, IndexingAgreementVoucher};
147146

148-
#[sqlx::test(migrations = "../../migrations")]
149-
async fn test_store_agreement(pool: PgPool) {
150-
let store = Arc::new(PsqlAgreementStore { pool });
147+
#[tokio::test]
148+
async fn test_store_agreement() {
149+
let test_db = test_assets::setup_shared_test_db().await;
150+
let store = Arc::new(PsqlAgreementStore { pool: test_db.pool });
151151
let id = Uuid::now_v7();
152152

153153
// Create metadata first
@@ -196,9 +196,10 @@ pub(crate) mod test {
196196
assert_eq!(row.subgraph_deployment_id, "Qm123");
197197
}
198198

199-
#[sqlx::test(migrations = "../../migrations")]
200-
async fn test_get_agreement_by_id(pool: PgPool) {
201-
let store = Arc::new(PsqlAgreementStore { pool });
199+
#[tokio::test]
200+
async fn test_get_agreement_by_id() {
201+
let test_db = test_assets::setup_shared_test_db().await;
202+
let store = Arc::new(PsqlAgreementStore { pool: test_db.pool });
202203
let id = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d9").unwrap();
203204

204205
// Create metadata first
@@ -277,9 +278,10 @@ pub(crate) mod test {
277278
assert!(!stored_agreement.cancelled);
278279
}
279280

280-
#[sqlx::test(migrations = "../../migrations")]
281-
async fn test_cancel_agreement(pool: PgPool) {
282-
let store = Arc::new(PsqlAgreementStore { pool });
281+
#[tokio::test]
282+
async fn test_cancel_agreement() {
283+
let test_db = test_assets::setup_shared_test_db().await;
284+
let store = Arc::new(PsqlAgreementStore { pool: test_db.pool });
283285
let id = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7e9").unwrap();
284286

285287
// Create metadata first

crates/service/src/database/cost_model.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,10 @@ pub(crate) mod test {
251251
]
252252
}
253253

254-
#[sqlx::test(migrations = "../../migrations")]
255-
async fn success_cost_models(pool: PgPool) {
254+
#[tokio::test]
255+
async fn success_cost_models() {
256+
let test_db = test_assets::setup_shared_test_db().await;
257+
let pool = test_db.pool;
256258
let test_models = test_data();
257259
let test_deployments = test_models
258260
.iter()
@@ -313,8 +315,10 @@ pub(crate) mod test {
313315
}
314316
}
315317

316-
#[sqlx::test(migrations = "../../migrations")]
317-
async fn global_fallback_cost_models(pool: PgPool) {
318+
#[tokio::test]
319+
async fn global_fallback_cost_models() {
320+
let test_db = test_assets::setup_shared_test_db().await;
321+
let pool = test_db.pool;
318322
let test_models = test_data();
319323
let test_deployments = test_models
320324
.iter()
@@ -403,8 +407,10 @@ pub(crate) mod test {
403407
assert_eq!(missing_model.model, global_model.model);
404408
}
405409

406-
#[sqlx::test(migrations = "../../migrations")]
407-
async fn success_cost_model(pool: PgPool) {
410+
#[tokio::test]
411+
async fn success_cost_model() {
412+
let test_db = test_assets::setup_shared_test_db().await;
413+
let pool = test_db.pool;
408414
add_cost_models(&pool, to_db_models(test_data())).await;
409415

410416
let deployment_id_from_bytes = DeploymentId::from_str(
@@ -425,8 +431,10 @@ pub(crate) mod test {
425431
assert_eq!(model.model, Some("default => 0.00025;".to_string()));
426432
}
427433

428-
#[sqlx::test(migrations = "../../migrations")]
429-
async fn global_fallback_cost_model(pool: PgPool) {
434+
#[tokio::test]
435+
async fn global_fallback_cost_model() {
436+
let test_db = test_assets::setup_shared_test_db().await;
437+
let pool = test_db.pool;
430438
let test_models = test_data();
431439
let global_model = global_cost_model();
432440

crates/service/src/middleware/auth.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@ mod tests {
6969
service
7070
}
7171

72-
#[sqlx::test(migrations = "../../migrations")]
73-
async fn test_composition_header_valid(pgpool: PgPool) {
74-
let mut service = service(pgpool.clone()).await;
72+
#[tokio::test]
73+
async fn test_composition_header_valid() {
74+
let test_db = test_assets::setup_shared_test_db().await;
75+
let mut service = service(test_db.pool.clone()).await;
7576
// should allow queries that contains the free token
7677
// if the token does not match, return payment required
7778
let mut req = Request::new(Default::default());
@@ -83,9 +84,10 @@ mod tests {
8384
assert_eq!(res.status(), StatusCode::OK);
8485
}
8586

86-
#[sqlx::test(migrations = "../../migrations")]
87-
async fn test_composition_header_invalid(pgpool: PgPool) {
88-
let mut service = service(pgpool.clone()).await;
87+
#[tokio::test]
88+
async fn test_composition_header_invalid() {
89+
let test_db = test_assets::setup_shared_test_db().await;
90+
let mut service = service(test_db.pool.clone()).await;
8991

9092
// if the token exists but is wrong, try the receipt
9193
let mut req = Request::new(Default::default());
@@ -96,9 +98,10 @@ mod tests {
9698
assert_eq!(res.status(), StatusCode::PAYMENT_REQUIRED);
9799
}
98100

99-
#[sqlx::test(migrations = "../../migrations")]
100-
async fn test_composition_with_receipt(pgpool: PgPool) {
101-
let mut service = service(pgpool.clone()).await;
101+
#[tokio::test]
102+
async fn test_composition_with_receipt() {
103+
let test_db = test_assets::setup_shared_test_db().await;
104+
let mut service = service(test_db.pool.clone()).await;
102105

103106
let receipt = create_signed_receipt(SignedReceiptRequest::builder().build()).await;
104107

@@ -111,16 +114,17 @@ mod tests {
111114
// verify receipts
112115
assert_while_retry!({
113116
let result = sqlx::query!("SELECT * FROM scalar_tap_receipts")
114-
.fetch_all(&pgpool)
117+
.fetch_all(&test_db.pool)
115118
.await
116119
.unwrap();
117120
result.is_empty()
118121
});
119122
}
120123

121-
#[sqlx::test(migrations = "../../migrations")]
122-
async fn test_composition_without_header_or_receipt(pgpool: PgPool) {
123-
let mut service = service(pgpool.clone()).await;
124+
#[tokio::test]
125+
async fn test_composition_without_header_or_receipt() {
126+
let test_db = test_assets::setup_shared_test_db().await;
127+
let mut service = service(test_db.pool.clone()).await;
124128
// if it has neither, should return payment required
125129
let req = Request::new(Default::default());
126130
let res = service.call(req).await.unwrap();

crates/service/src/middleware/auth/tap.rs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,10 @@ mod tests {
164164
}
165165

166166
#[rstest]
167-
#[sqlx::test(migrations = "../../migrations")]
168-
async fn test_tap_valid_receipt(
169-
metric: &'static prometheus::CounterVec,
170-
#[ignore] pgpool: PgPool,
171-
) {
172-
let mut service = service(metric, pgpool.clone()).await;
167+
#[tokio::test]
168+
async fn test_tap_valid_receipt(metric: &'static prometheus::CounterVec) {
169+
let test_db = test_assets::setup_shared_test_db().await;
170+
let mut service = service(metric, test_db.pool.clone()).await;
173171

174172
let receipt = create_signed_receipt(SignedReceiptRequest::builder().build()).await;
175173

@@ -182,20 +180,18 @@ mod tests {
182180
// verify receipts
183181
assert_while_retry!({
184182
sqlx::query!("SELECT * FROM scalar_tap_receipts")
185-
.fetch_all(&pgpool)
183+
.fetch_all(&test_db.pool)
186184
.await
187185
.unwrap()
188186
.is_empty()
189187
})
190188
}
191189

192190
#[rstest]
193-
#[sqlx::test(migrations = "../../migrations")]
194-
async fn test_invalid_receipt_with_failed_metric(
195-
metric: &'static prometheus::CounterVec,
196-
#[ignore] pgpool: PgPool,
197-
) {
198-
let mut service = service(metric, pgpool.clone()).await;
191+
#[tokio::test]
192+
async fn test_invalid_receipt_with_failed_metric(metric: &'static prometheus::CounterVec) {
193+
let test_db = test_assets::setup_shared_test_db().await;
194+
let mut service = service(metric, test_db.pool.clone()).await;
199195
// if it fails tap receipt, should return failed to process payment + tap message
200196

201197
assert_eq!(metric.collect().first().unwrap().get_metric().len(), 0);
@@ -224,12 +220,10 @@ mod tests {
224220
}
225221

226222
#[rstest]
227-
#[sqlx::test(migrations = "../../migrations")]
228-
async fn test_tap_missing_signed_receipt(
229-
metric: &'static prometheus::CounterVec,
230-
#[ignore] pgpool: PgPool,
231-
) {
232-
let mut service = service(metric, pgpool.clone()).await;
223+
#[tokio::test]
224+
async fn test_tap_missing_signed_receipt(metric: &'static prometheus::CounterVec) {
225+
let test_db = test_assets::setup_shared_test_db().await;
226+
let mut service = service(metric, test_db.pool.clone()).await;
233227
// if it doesnt contain the signed receipt
234228
// should return payment required
235229
let req = Request::new(Body::default());

crates/service/src/tap/checks/deny_list_check.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,10 @@ mod tests {
262262
DenyListCheck::new(pgpool).await
263263
}
264264

265-
#[sqlx::test(migrations = "../../migrations")]
266-
async fn test_sender_denylist(pgpool: PgPool) {
265+
#[tokio::test]
266+
async fn test_sender_denylist() {
267+
let test_db = test_assets::setup_shared_test_db().await;
268+
let pgpool = test_db.pool;
267269
// Add the sender to the denylist
268270
sqlx::query!(
269271
r#"
@@ -292,8 +294,10 @@ mod tests {
292294
.is_err());
293295
}
294296

295-
#[sqlx::test(migrations = "../../migrations")]
296-
async fn test_sender_denylist_updates(pgpool: PgPool) {
297+
#[tokio::test]
298+
async fn test_sender_denylist_updates() {
299+
let test_db = test_assets::setup_shared_test_db().await;
300+
let pgpool = test_db.pool;
297301
let signed_receipt = create_signed_receipt(SignedReceiptRequest::builder().build()).await;
298302

299303
let deny_list_check = new_deny_list_check(pgpool.clone()).await;

crates/service/src/tap/checks/value_check.rs

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,6 @@ enum CostModelNotification {
368368
mod tests {
369369
use std::time::Duration;
370370

371-
use sqlx::PgPool;
372371
use tap_core::receipt::{checks::Check, Context};
373372
use test_assets::{create_signed_receipt, flush_messages, SignedReceiptRequest};
374373
use tokio::time::sleep;
@@ -379,14 +378,18 @@ mod tests {
379378
tap::{CheckingReceipt, TapReceipt},
380379
};
381380

382-
#[sqlx::test(migrations = "../../migrations")]
383-
async fn initialize_check(pgpool: PgPool) {
381+
#[tokio::test]
382+
async fn initialize_check() {
383+
let test_db = test_assets::setup_shared_test_db().await;
384+
let pgpool = test_db.pool;
384385
let check = MinimumValue::new(pgpool, Duration::from_secs(0)).await;
385386
assert_eq!(check.cost_model_map.read().unwrap().len(), 0);
386387
}
387388

388-
#[sqlx::test(migrations = "../../migrations")]
389-
async fn should_initialize_check_with_models(pgpool: PgPool) {
389+
#[tokio::test]
390+
async fn should_initialize_check_with_models() {
391+
let test_db = test_assets::setup_shared_test_db().await;
392+
let pgpool = test_db.pool;
390393
// insert 2 cost models for different deployment_id
391394
let test_models = test::test_data();
392395

@@ -399,8 +402,10 @@ mod tests {
399402
assert!(check.global_model.read().unwrap().is_none());
400403
}
401404

402-
#[sqlx::test(migrations = "../../migrations")]
403-
async fn should_watch_model_insert(pgpool: PgPool) {
405+
#[tokio::test]
406+
async fn should_watch_model_insert() {
407+
let test_db = test_assets::setup_shared_test_db().await;
408+
let pgpool = test_db.pool;
404409
let mut check = MinimumValue::new(pgpool.clone(), Duration::from_secs(0)).await;
405410
assert_eq!(check.cost_model_map.read().unwrap().len(), 0);
406411

@@ -416,8 +421,10 @@ mod tests {
416421
);
417422
}
418423

419-
#[sqlx::test(migrations = "../../migrations")]
420-
async fn should_watch_model_remove(pgpool: PgPool) {
424+
#[tokio::test]
425+
async fn should_watch_model_remove() {
426+
let test_db = test_assets::setup_shared_test_db().await;
427+
let pgpool = test_db.pool;
421428
// insert 2 cost models for different deployment_id
422429
let test_models = test::test_data();
423430
add_cost_models(&pgpool, to_db_models(test_models.clone())).await;
@@ -436,17 +443,21 @@ mod tests {
436443
assert_eq!(check.cost_model_map.read().unwrap().len(), 0);
437444
}
438445

439-
#[sqlx::test(migrations = "../../migrations")]
440-
async fn should_start_global_model(pgpool: PgPool) {
446+
#[tokio::test]
447+
async fn should_start_global_model() {
448+
let test_db = test_assets::setup_shared_test_db().await;
449+
let pgpool = test_db.pool;
441450
let global_model = global_cost_model();
442451
add_cost_models(&pgpool, vec![global_model.clone()]).await;
443452

444453
let check = MinimumValue::new(pgpool.clone(), Duration::from_secs(0)).await;
445454
assert!(check.global_model.read().unwrap().is_some());
446455
}
447456

448-
#[sqlx::test(migrations = "../../migrations")]
449-
async fn should_watch_global_model(pgpool: PgPool) {
457+
#[tokio::test]
458+
async fn should_watch_global_model() {
459+
let test_db = test_assets::setup_shared_test_db().await;
460+
let pgpool = test_db.pool;
450461
let mut check = MinimumValue::new(pgpool.clone(), Duration::from_secs(0)).await;
451462

452463
let global_model = global_cost_model();
@@ -457,8 +468,10 @@ mod tests {
457468
assert!(check.global_model.read().unwrap().is_some());
458469
}
459470

460-
#[sqlx::test(migrations = "../../migrations")]
461-
async fn should_remove_global_model(pgpool: PgPool) {
471+
#[tokio::test]
472+
async fn should_remove_global_model() {
473+
let test_db = test_assets::setup_shared_test_db().await;
474+
let pgpool = test_db.pool;
462475
let global_model = global_cost_model();
463476
add_cost_models(&pgpool, vec![global_model.clone()]).await;
464477

@@ -475,8 +488,10 @@ mod tests {
475488
assert_eq!(check.cost_model_map.read().unwrap().len(), 0);
476489
}
477490

478-
#[sqlx::test(migrations = "../../migrations")]
479-
async fn should_check_minimal_value(pgpool: PgPool) {
491+
#[tokio::test]
492+
async fn should_check_minimal_value() {
493+
let test_db = test_assets::setup_shared_test_db().await;
494+
let pgpool = test_db.pool;
480495
// insert cost models for different deployment_id
481496
let test_models = test::test_data();
482497

@@ -565,8 +580,10 @@ mod tests {
565580
.expect("should accept more than minimal");
566581
}
567582

568-
#[sqlx::test(migrations = "../../migrations")]
569-
async fn should_check_using_global(pgpool: PgPool) {
583+
#[tokio::test]
584+
async fn should_check_using_global() {
585+
let test_db = test_assets::setup_shared_test_db().await;
586+
let pgpool = test_db.pool;
570587
// insert cost models for different deployment_id
571588
let test_models = test::test_data();
572589
let global_model = global_cost_model();

0 commit comments

Comments
 (0)