Skip to content

Commit 8a04f40

Browse files
committed
chore: PR suggestions and unit tests
1 parent 6066203 commit 8a04f40

File tree

4 files changed

+381
-0
lines changed

4 files changed

+381
-0
lines changed

src/config/server_config.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2063,4 +2063,104 @@ mod tests {
20632063
env::remove_var("API_KEY");
20642064
}
20652065
}
2066+
2067+
mod get_sqs_wait_time_tests {
2068+
use super::*;
2069+
use serial_test::serial;
2070+
2071+
#[test]
2072+
#[serial]
2073+
fn test_returns_default_when_env_not_set() {
2074+
env::remove_var("SQS_TEST_QUEUE_WAIT_TIME_SECONDS");
2075+
let result = ServerConfig::get_sqs_wait_time("TEST_QUEUE", 5);
2076+
assert_eq!(result, 5, "Should return default when env var is not set");
2077+
}
2078+
2079+
#[test]
2080+
#[serial]
2081+
fn test_returns_parsed_value() {
2082+
env::set_var("SQS_TEST_QUEUE_WAIT_TIME_SECONDS", "10");
2083+
let result = ServerConfig::get_sqs_wait_time("TEST_QUEUE", 5);
2084+
assert_eq!(result, 10, "Should return parsed value");
2085+
env::remove_var("SQS_TEST_QUEUE_WAIT_TIME_SECONDS");
2086+
}
2087+
2088+
#[test]
2089+
#[serial]
2090+
fn test_returns_default_when_invalid() {
2091+
env::set_var("SQS_TEST_QUEUE_WAIT_TIME_SECONDS", "not_a_number");
2092+
let result = ServerConfig::get_sqs_wait_time("TEST_QUEUE", 5);
2093+
assert_eq!(result, 5, "Should return default for non-numeric input");
2094+
env::remove_var("SQS_TEST_QUEUE_WAIT_TIME_SECONDS");
2095+
}
2096+
2097+
#[test]
2098+
#[serial]
2099+
fn test_clamps_to_sqs_maximum_of_20() {
2100+
env::set_var("SQS_TEST_QUEUE_WAIT_TIME_SECONDS", "30");
2101+
let result = ServerConfig::get_sqs_wait_time("TEST_QUEUE", 5);
2102+
assert_eq!(result, 20, "Should clamp to SQS maximum of 20 seconds");
2103+
env::remove_var("SQS_TEST_QUEUE_WAIT_TIME_SECONDS");
2104+
}
2105+
2106+
#[test]
2107+
#[serial]
2108+
fn test_allows_zero() {
2109+
env::set_var("SQS_TEST_QUEUE_WAIT_TIME_SECONDS", "0");
2110+
let result = ServerConfig::get_sqs_wait_time("TEST_QUEUE", 5);
2111+
assert_eq!(result, 0, "Should allow zero (short polling)");
2112+
env::remove_var("SQS_TEST_QUEUE_WAIT_TIME_SECONDS");
2113+
}
2114+
}
2115+
2116+
mod get_sqs_poller_count_tests {
2117+
use super::*;
2118+
use serial_test::serial;
2119+
2120+
#[test]
2121+
#[serial]
2122+
fn test_returns_default_when_env_not_set() {
2123+
env::remove_var("SQS_TEST_QUEUE_POLLER_COUNT");
2124+
let result = ServerConfig::get_sqs_poller_count("TEST_QUEUE", 2);
2125+
assert_eq!(result, 2, "Should return default when env var is not set");
2126+
}
2127+
2128+
#[test]
2129+
#[serial]
2130+
fn test_returns_parsed_value() {
2131+
env::set_var("SQS_TEST_QUEUE_POLLER_COUNT", "4");
2132+
let result = ServerConfig::get_sqs_poller_count("TEST_QUEUE", 2);
2133+
assert_eq!(result, 4, "Should return parsed value");
2134+
env::remove_var("SQS_TEST_QUEUE_POLLER_COUNT");
2135+
}
2136+
2137+
#[test]
2138+
#[serial]
2139+
fn test_returns_default_when_invalid() {
2140+
env::set_var("SQS_TEST_QUEUE_POLLER_COUNT", "not_a_number");
2141+
let result = ServerConfig::get_sqs_poller_count("TEST_QUEUE", 2);
2142+
assert_eq!(result, 2, "Should return default for non-numeric input");
2143+
env::remove_var("SQS_TEST_QUEUE_POLLER_COUNT");
2144+
}
2145+
2146+
#[test]
2147+
#[serial]
2148+
fn test_clamps_zero_to_minimum_of_1() {
2149+
env::set_var("SQS_TEST_QUEUE_POLLER_COUNT", "0");
2150+
let result = ServerConfig::get_sqs_poller_count("TEST_QUEUE", 2);
2151+
assert_eq!(result, 1, "Should clamp zero to minimum of 1");
2152+
env::remove_var("SQS_TEST_QUEUE_POLLER_COUNT");
2153+
}
2154+
2155+
#[test]
2156+
#[serial]
2157+
fn test_default_also_clamped_to_minimum_of_1() {
2158+
env::remove_var("SQS_TEST_QUEUE_POLLER_COUNT");
2159+
let result = ServerConfig::get_sqs_poller_count("TEST_QUEUE", 0);
2160+
assert_eq!(
2161+
result, 1,
2162+
"Default of 0 should also be clamped to minimum of 1"
2163+
);
2164+
}
2165+
}
20662166
}

src/metrics/mod.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,3 +734,56 @@ mod property_tests {
734734
}
735735
}
736736
}
737+
738+
#[cfg(test)]
739+
mod processing_time_tests {
740+
use super::*;
741+
742+
#[test]
743+
fn test_observe_processing_time_records_to_histogram() {
744+
let before = TRANSACTION_PROCESSING_TIME
745+
.with_label_values(&["test-relayer", "evm", "request_queue_dwell"])
746+
.get_sample_count();
747+
748+
observe_processing_time("test-relayer", "evm", "request_queue_dwell", 1.5);
749+
750+
let after = TRANSACTION_PROCESSING_TIME
751+
.with_label_values(&["test-relayer", "evm", "request_queue_dwell"])
752+
.get_sample_count();
753+
754+
assert_eq!(after, before + 1, "sample count should increase by 1");
755+
}
756+
757+
#[test]
758+
fn test_observe_processing_time_accumulates_sum() {
759+
let label = "test_sum_stage";
760+
let before_sum = TRANSACTION_PROCESSING_TIME
761+
.with_label_values(&["test-relayer-sum", "stellar", label])
762+
.get_sample_sum();
763+
764+
observe_processing_time("test-relayer-sum", "stellar", label, 2.0);
765+
observe_processing_time("test-relayer-sum", "stellar", label, 3.0);
766+
767+
let after_sum = TRANSACTION_PROCESSING_TIME
768+
.with_label_values(&["test-relayer-sum", "stellar", label])
769+
.get_sample_sum();
770+
771+
let delta = after_sum - before_sum;
772+
assert!(
773+
(delta - 5.0).abs() < 0.001,
774+
"sum should increase by 5.0, got delta {delta}"
775+
);
776+
}
777+
778+
#[test]
779+
fn test_stage_constants_are_distinct() {
780+
let stages = [
781+
STAGE_REQUEST_QUEUE_DWELL,
782+
STAGE_PREPARE_DURATION,
783+
STAGE_SUBMISSION_QUEUE_DWELL,
784+
STAGE_SUBMIT_DURATION,
785+
];
786+
let unique: std::collections::HashSet<&str> = stages.iter().copied().collect();
787+
assert_eq!(stages.len(), unique.len(), "stage constants must be unique");
788+
}
789+
}

src/queues/queue_type.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,4 +313,90 @@ mod tests {
313313
assert!(qt.default_concurrency() > 0, "{qt:?} has zero concurrency");
314314
}
315315
}
316+
317+
#[test]
318+
fn test_sqs_env_key_nonempty_and_uppercase() {
319+
let all = [
320+
QueueType::TransactionRequest,
321+
QueueType::TransactionSubmission,
322+
QueueType::StatusCheck,
323+
QueueType::StatusCheckEvm,
324+
QueueType::StatusCheckStellar,
325+
QueueType::Notification,
326+
QueueType::TokenSwapRequest,
327+
QueueType::RelayerHealthCheck,
328+
];
329+
for qt in &all {
330+
let key = qt.sqs_env_key();
331+
assert!(!key.is_empty(), "{qt:?} has empty sqs_env_key");
332+
assert_eq!(
333+
key,
334+
key.to_uppercase(),
335+
"{qt:?} sqs_env_key should be uppercase"
336+
);
337+
}
338+
}
339+
340+
#[test]
341+
fn test_sqs_env_key_unique_per_variant() {
342+
let all = [
343+
QueueType::TransactionRequest,
344+
QueueType::TransactionSubmission,
345+
QueueType::StatusCheck,
346+
QueueType::StatusCheckEvm,
347+
QueueType::StatusCheckStellar,
348+
QueueType::Notification,
349+
QueueType::TokenSwapRequest,
350+
QueueType::RelayerHealthCheck,
351+
];
352+
let keys: Vec<&str> = all.iter().map(|qt| qt.sqs_env_key()).collect();
353+
let unique: std::collections::HashSet<&str> = keys.iter().copied().collect();
354+
assert_eq!(
355+
keys.len(),
356+
unique.len(),
357+
"sqs_env_key must be unique per QueueType variant"
358+
);
359+
}
360+
361+
#[test]
362+
fn test_default_poller_count_at_least_one() {
363+
let all = [
364+
QueueType::TransactionRequest,
365+
QueueType::TransactionSubmission,
366+
QueueType::StatusCheck,
367+
QueueType::StatusCheckEvm,
368+
QueueType::StatusCheckStellar,
369+
QueueType::Notification,
370+
QueueType::TokenSwapRequest,
371+
QueueType::RelayerHealthCheck,
372+
];
373+
for qt in &all {
374+
assert!(
375+
qt.default_poller_count() >= 1,
376+
"{qt:?} default_poller_count should be >= 1"
377+
);
378+
}
379+
}
380+
381+
#[test]
382+
fn test_default_wait_time_all_variants_covered() {
383+
// Ensure every variant returns a value within SQS bounds [0, 20]
384+
let all = [
385+
QueueType::TransactionRequest,
386+
QueueType::TransactionSubmission,
387+
QueueType::StatusCheck,
388+
QueueType::StatusCheckEvm,
389+
QueueType::StatusCheckStellar,
390+
QueueType::Notification,
391+
QueueType::TokenSwapRequest,
392+
QueueType::RelayerHealthCheck,
393+
];
394+
for qt in &all {
395+
let wt = qt.default_wait_time_secs();
396+
assert!(
397+
wt <= 20,
398+
"{qt:?} default_wait_time_secs {wt} exceeds SQS max 20"
399+
);
400+
}
401+
}
316402
}

src/queues/sqs/worker.rs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,4 +1683,146 @@ mod tests {
16831683
assert!(!is_fifo_queue_url(standard));
16841684
assert!(is_fifo_queue_url(fifo));
16851685
}
1686+
1687+
// ── get_wait_time_for_queue ──────────────────────────────────────────
1688+
1689+
#[test]
1690+
fn test_get_wait_time_for_queue_returns_positive() {
1691+
let all = [
1692+
QueueType::TransactionRequest,
1693+
QueueType::TransactionSubmission,
1694+
QueueType::StatusCheck,
1695+
QueueType::StatusCheckEvm,
1696+
QueueType::StatusCheckStellar,
1697+
QueueType::Notification,
1698+
QueueType::TokenSwapRequest,
1699+
QueueType::RelayerHealthCheck,
1700+
];
1701+
for qt in all {
1702+
let wt = get_wait_time_for_queue(qt);
1703+
assert!(
1704+
wt <= 20,
1705+
"{qt:?}: wait time {wt} exceeds SQS maximum of 20s"
1706+
);
1707+
}
1708+
}
1709+
1710+
#[test]
1711+
fn test_get_wait_time_for_queue_matches_defaults() {
1712+
// Without env overrides the helper should return the queue's default
1713+
assert_eq!(
1714+
get_wait_time_for_queue(QueueType::TransactionRequest),
1715+
QueueType::TransactionRequest.default_wait_time_secs()
1716+
);
1717+
assert_eq!(
1718+
get_wait_time_for_queue(QueueType::StatusCheck),
1719+
QueueType::StatusCheck.default_wait_time_secs()
1720+
);
1721+
}
1722+
1723+
#[test]
1724+
#[serial_test::serial]
1725+
fn test_get_wait_time_for_queue_respects_env_override() {
1726+
// StatusCheck default is 5; override to 12 via the real env var path
1727+
let env_var = format!(
1728+
"SQS_{}_WAIT_TIME_SECONDS",
1729+
QueueType::StatusCheck.sqs_env_key()
1730+
);
1731+
std::env::set_var(&env_var, "12");
1732+
assert_eq!(get_wait_time_for_queue(QueueType::StatusCheck), 12);
1733+
std::env::remove_var(&env_var);
1734+
}
1735+
1736+
#[test]
1737+
#[serial_test::serial]
1738+
fn test_get_wait_time_for_queue_env_override_clamped_to_20() {
1739+
let env_var = format!(
1740+
"SQS_{}_WAIT_TIME_SECONDS",
1741+
QueueType::Notification.sqs_env_key()
1742+
);
1743+
std::env::set_var(&env_var, "99");
1744+
assert_eq!(
1745+
get_wait_time_for_queue(QueueType::Notification),
1746+
20,
1747+
"Should clamp to SQS maximum of 20"
1748+
);
1749+
std::env::remove_var(&env_var);
1750+
}
1751+
1752+
// ── get_poller_count_for_queue ───────────────────────────────────────
1753+
1754+
#[test]
1755+
fn test_get_poller_count_for_queue_all_types_positive() {
1756+
let all = [
1757+
QueueType::TransactionRequest,
1758+
QueueType::TransactionSubmission,
1759+
QueueType::StatusCheck,
1760+
QueueType::StatusCheckEvm,
1761+
QueueType::StatusCheckStellar,
1762+
QueueType::Notification,
1763+
QueueType::TokenSwapRequest,
1764+
QueueType::RelayerHealthCheck,
1765+
];
1766+
for qt in all {
1767+
assert!(
1768+
get_poller_count_for_queue(qt) >= 1,
1769+
"{qt:?}: poller count must be at least 1"
1770+
);
1771+
}
1772+
}
1773+
1774+
#[test]
1775+
fn test_get_poller_count_for_queue_matches_defaults() {
1776+
// Without env overrides the helper should return the queue's default (clamped to >= 1)
1777+
assert_eq!(
1778+
get_poller_count_for_queue(QueueType::TransactionRequest),
1779+
QueueType::TransactionRequest.default_poller_count().max(1)
1780+
);
1781+
assert_eq!(
1782+
get_poller_count_for_queue(QueueType::Notification),
1783+
QueueType::Notification.default_poller_count().max(1)
1784+
);
1785+
}
1786+
1787+
#[test]
1788+
#[serial_test::serial]
1789+
fn test_get_poller_count_for_queue_respects_env_override() {
1790+
let env_var = format!("SQS_{}_POLLER_COUNT", QueueType::Notification.sqs_env_key());
1791+
std::env::set_var(&env_var, "5");
1792+
assert_eq!(get_poller_count_for_queue(QueueType::Notification), 5);
1793+
std::env::remove_var(&env_var);
1794+
}
1795+
1796+
#[test]
1797+
#[serial_test::serial]
1798+
fn test_get_poller_count_for_queue_env_zero_clamped_to_1() {
1799+
let env_var = format!("SQS_{}_POLLER_COUNT", QueueType::StatusCheck.sqs_env_key());
1800+
std::env::set_var(&env_var, "0");
1801+
assert_eq!(
1802+
get_poller_count_for_queue(QueueType::StatusCheck),
1803+
1,
1804+
"Zero poller count from env should be clamped to 1"
1805+
);
1806+
std::env::remove_var(&env_var);
1807+
}
1808+
1809+
// ── PollLoopConfig ──────────────────────────────────────────────────
1810+
1811+
#[test]
1812+
fn test_poll_loop_config_clone() {
1813+
let config = PollLoopConfig {
1814+
queue_type: QueueType::TransactionRequest,
1815+
polling_interval: 15,
1816+
visibility_timeout: 120,
1817+
handler_timeout: Duration::from_secs(120),
1818+
max_retries: 3,
1819+
poller_id: 0,
1820+
poller_count: 2,
1821+
};
1822+
let cloned = config.clone();
1823+
assert_eq!(cloned.polling_interval, 15);
1824+
assert_eq!(cloned.poller_id, 0);
1825+
assert_eq!(cloned.poller_count, 2);
1826+
assert_eq!(cloned.max_retries, 3);
1827+
}
16861828
}

0 commit comments

Comments
 (0)