Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add rstest and fixtures #632

Merged
merged 5 commits into from
Mar 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/monitor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ env_logger = { version = "0.11.0", default-features = false }
test-log = { version = "0.2.12", default-features = false }
wiremock.workspace = true
test-assets = { path = "../test-assets" }
rstest = "0.24.0"
test-with = "0.14.6"
144 changes: 23 additions & 121 deletions crates/monitor/src/client/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,47 +72,14 @@ mod tests {

use super::*;

#[tokio::test]
async fn test_parses_synced_and_healthy_response() {
let mock_server = MockServer::start().await;
let status_url: Url = mock_server
.uri()
.parse::<Url>()
.unwrap()
.join("/status")
.unwrap();
let deployment = deployment_id!("QmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");

Mock::given(method("POST"))
.and(path("/status"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
"data": {
"indexingStatuses": [
{
"synced": true,
"health": "healthy"
}
]
}
})))
.mount(&mock_server)
.await;

let status = monitor_deployment_status(deployment, status_url)
.await
.unwrap();

assert_eq!(
status.borrow().clone(),
DeploymentStatus {
synced: true,
health: "healthy".to_string()
}
);
struct MonitorMock {
mock_server: MockServer,
status_url: Url,
deployment: DeploymentId,
}

#[tokio::test]
async fn test_parses_not_synced_and_healthy_response() {
#[rstest::fixture]
async fn monitor_mock() -> MonitorMock {
let mock_server = MockServer::start().await;
let status_url: Url = mock_server
.uri()
Expand All @@ -121,109 +88,44 @@ mod tests {
.join("/status")
.unwrap();
let deployment = deployment_id!("QmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");

Mock::given(method("POST"))
.and(path("/status"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
"data": {
"indexingStatuses": [
{
"synced": false,
"health": "healthy"
}
]
}
})))
.mount(&mock_server)
.await;

let status = monitor_deployment_status(deployment, status_url)
.await
.unwrap();

assert_eq!(
status.borrow().clone(),
DeploymentStatus {
synced: false,
health: "healthy".to_string()
}
);
}

#[tokio::test]
async fn test_parses_synced_and_unhealthy_response() {
let mock_server = MockServer::start().await;
let status_url: Url = mock_server
.uri()
.parse::<Url>()
.unwrap()
.join("/status")
.unwrap();
let deployment = deployment_id!("QmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");

Mock::given(method("POST"))
.and(path("/status"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
"data": {
"indexingStatuses": [
{
"synced": true,
"health": "unhealthy"
}
]
}
})))
.mount(&mock_server)
.await;

let status = monitor_deployment_status(deployment, status_url)
.await
.unwrap();

assert_eq!(
status.borrow().clone(),
DeploymentStatus {
synced: true,
health: "unhealthy".to_string()
}
);
MonitorMock {
mock_server,
status_url,
deployment,
}
}

#[rstest::rstest]
#[tokio::test]
async fn test_parses_synced_and_failed_response() {
let mock_server = MockServer::start().await;
let status_url: Url = mock_server
.uri()
.parse::<Url>()
.unwrap()
.join("/status")
.unwrap();
let deployment = deployment_id!("QmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");

async fn test_parses_health_and_sync_status_response(
#[future(awt)] monitor_mock: MonitorMock,
#[values(true, false)] synced: bool,
#[values("healthy", "unhealthy", "failed")] health: &str,
) {
Mock::given(method("POST"))
.and(path("/status"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
"data": {
"indexingStatuses": [
{
"synced": true,
"health": "failed"
"synced": synced,
"health": health
}
]
}
})))
.mount(&mock_server)
.mount(&monitor_mock.mock_server)
.await;

let status = monitor_deployment_status(deployment, status_url)
let status = monitor_deployment_status(monitor_mock.deployment, monitor_mock.status_url)
.await
.unwrap();

assert_eq!(
status.borrow().clone(),
DeploymentStatus {
synced: true,
health: "failed".to_string()
synced,
health: health.to_string()
}
);
}
Expand Down
1 change: 1 addition & 0 deletions crates/tap-agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,4 @@ wiremock-grpc = "0.0.3-alpha3"
test-assets = { path = "../test-assets" }
test-log.workspace = true
rstest = "0.24.0"
stdext = "0.3.3"
64 changes: 43 additions & 21 deletions crates/tap-agent/src/agent/sender_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1423,10 +1423,11 @@ pub mod tests {
use serde_json::json;
use sqlx::PgPool;
use test_assets::{
flush_messages, ALLOCATION_ID_0, ALLOCATION_ID_1, TAP_SENDER as SENDER,
flush_messages, pgpool, ALLOCATION_ID_0, ALLOCATION_ID_1, TAP_SENDER as SENDER,
TAP_SIGNER as SIGNER,
};
use thegraph_core::alloy::{hex::ToHexExt, primitives::U256};
use tokio::sync::mpsc;
use wiremock::{
matchers::{body_string_contains, method},
Mock, MockServer, ResponseTemplate,
Expand Down Expand Up @@ -1467,6 +1468,22 @@ pub mod tests {
.await;
mock_escrow_subgraph_server
}
struct TestSenderAccount {
sender_account: ActorRef<SenderAccountMessage>,
msg_receiver: mpsc::Receiver<SenderAccountMessage>,
prefix: String,
}

#[rstest::fixture]
async fn basic_sender_account(#[future(awt)] pgpool: PgPool) -> TestSenderAccount {
let (sender_account, msg_receiver, prefix, _) =
create_sender_account().pgpool(pgpool).call().await;
TestSenderAccount {
sender_account,
msg_receiver,
prefix,
}
}

#[rstest::rstest]
#[sqlx::test(migrations = "../../migrations")]
Expand Down Expand Up @@ -1688,20 +1705,22 @@ pub mod tests {
.as_nanos() as u64
}

#[sqlx::test(migrations = "../../migrations")]
async fn test_update_receipt_fees_no_rav(pgpool: PgPool) {
let (sender_account, _, prefix, _) = create_sender_account().pgpool(pgpool).call().await;

#[rstest::rstest]
#[tokio::test]
async fn test_update_receipt_fees_no_rav(
#[future(awt)] basic_sender_account: TestSenderAccount,
) {
// create a fake sender allocation
let (triggered_rav_request, _, _) = create_mock_sender_allocation(
prefix,
basic_sender_account.prefix,
SENDER.1,
ALLOCATION_ID_0,
sender_account.clone(),
basic_sender_account.sender_account.clone(),
)
.await;

sender_account
basic_sender_account
.sender_account
.cast(SenderAccountMessage::UpdateReceiptFees(
ALLOCATION_ID_0,
ReceiptFees::NewReceipt(TRIGGER_VALUE - 1, get_current_timestamp_u64_ns()),
Expand All @@ -1714,40 +1733,42 @@ pub mod tests {
assert_not_triggered!(&triggered_rav_request);
}

#[sqlx::test(migrations = "../../migrations")]
async fn test_update_receipt_fees_trigger_rav(pgpool: PgPool) {
let (sender_account, mut msg_receiver, prefix, _) =
create_sender_account().pgpool(pgpool).call().await;

#[rstest::rstest]
#[tokio::test]
async fn test_update_receipt_fees_trigger_rav(
#[future(awt)] mut basic_sender_account: TestSenderAccount,
) {
// create a fake sender allocation
let (triggered_rav_request, _, _) = create_mock_sender_allocation(
prefix,
basic_sender_account.prefix,
SENDER.1,
ALLOCATION_ID_0,
sender_account.clone(),
basic_sender_account.sender_account.clone(),
)
.await;

sender_account
basic_sender_account
.sender_account
.cast(SenderAccountMessage::UpdateReceiptFees(
ALLOCATION_ID_0,
ReceiptFees::NewReceipt(TRIGGER_VALUE, get_current_timestamp_u64_ns()),
))
.unwrap();

flush_messages(&mut msg_receiver).await;
flush_messages(&mut basic_sender_account.msg_receiver).await;
assert_not_triggered!(&triggered_rav_request);

// wait for it to be outside buffer
tokio::time::sleep(BUFFER_DURATION).await;

sender_account
basic_sender_account
.sender_account
.cast(SenderAccountMessage::UpdateReceiptFees(
ALLOCATION_ID_0,
ReceiptFees::Retry,
))
.unwrap();
flush_messages(&mut msg_receiver).await;
flush_messages(&mut basic_sender_account.msg_receiver).await;

assert_triggered!(&triggered_rav_request);
}
Expand Down Expand Up @@ -1837,8 +1858,9 @@ pub mod tests {
}

/// Test that the deny status is correctly loaded from the DB at the start of the actor
#[sqlx::test(migrations = "../../migrations")]
async fn test_init_deny(pgpool: PgPool) {
#[rstest::rstest]
#[tokio::test]
async fn test_init_deny(#[future(awt)] pgpool: PgPool) {
sqlx::query!(
r#"
INSERT INTO scalar_tap_denylist (sender_address)
Expand Down
Loading
Loading