Comprehensive test suite for validating behavior when approaching and exceeding storage limits in the Hunty contract. All tests are designed to verify constraint enforcement and edge cases.
Test File: contracts/hunty-core/tests/storage_limits.rs
The contract enforces a maximum of 100 clues per hunt (defined as MAX_CLUES_PER_HUNT: u32 = 100 in lib.rs).
test_add_maximum_clues_at_limit- Verifies exactly 100 clues can be added successfullytest_exceed_maximum_clues_fails- Confirms 101st clue is rejected withTooManyClueserrortest_clue_storage_at_boundary- Tests progression through 99→100→101 clues, verifying boundary behavior
The contract enforces a maximum title length of 200 bytes (defined as MAX_TITLE_BYTES: u32 = 200).
test_title_at_maximum_length- Verifies 200-byte title is acceptedtest_title_exceeds_maximum_length- Confirms 201-byte title is rejected withInvalidTitleerrortest_empty_title_fails- Verifies empty titles are rejected
The contract enforces a maximum description length of 2000 bytes (defined as MAX_DESCRIPTION_BYTES: u32 = 2000).
test_description_at_maximum_length- Verifies 2000-byte description is acceptedtest_description_exceeds_maximum_length- Confirms 2001-byte description is rejected withInvalidDescriptionerrortest_empty_description_allowed- Verifies empty descriptions are allowed
Questions within clues enforce a maximum length of 2000 bytes (defined as MAX_QUESTION_LENGTH: u32 = 2000).
test_question_at_maximum_length- Verifies 2000-byte question is acceptedtest_question_exceeds_maximum_length- Confirms 2001-byte question is rejected withInvalidQuestionerror
Answers within clues enforce a maximum length of 256 bytes (defined as MAX_ANSWER_LENGTH: u32 = 256).
test_answer_at_maximum_length- Verifies 256-byte answer is accepted (answer is hashed)test_answer_exceeds_maximum_length- Confirms 257-byte answer is rejected
Tests verify that the contract can handle creation and retrieval of multiple hunts under storage load.
test_create_multiple_hunts_sequential- Creates and verifies 50 hunts sequentiallytest_create_hunts_with_full_clue_set- Creates 10 hunts, each with 100 clues (1000 clues total)test_hunt_storage_pressure_mixed_operations- Creates 5 hunts with varying clue counts (20, 40, 60, 80, 100 clues)test_storage_limits_comprehensive_stress- Single hunt with max title (200B) + max description (2000B) + 100 clues with max questions (2000B) + max answers (256B)test_multiple_hunts_at_maximum_size- Creates 3 hunts at maximum storage capacity
From contracts/hunty-core/src/lib.rs:
const MAX_TITLE_BYTES: u32 = 200; // Hunt title max length
const MAX_DESCRIPTION_BYTES: u32 = 2000; // Hunt description max length
const MAX_QUESTION_LENGTH: u32 = 2000; // Clue question max length
const MAX_ANSWER_LENGTH: u32 = 256; // Clue answer max length
const MAX_CLUES_PER_HUNT: u32 = 100; // Clues per hunt limit
const MAX_LEADERBOARD_SIZE: u32 = 20; // Leaderboard entries returned
const MAX_LEADERBOARD_SCAN_SIZE: u32 = 200; // Max records scanned for leaderboard
const MAX_BATCH_SIZE: u32 = 50; // Paginated query batch size
const DEFAULT_PAGE_SIZE: u32 = 20; // Default page size for paginated queries# Install Rust and Soroban CLI (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
cargo install soroban-clicd contracts/hunty-core
cargo test --test storage_limits# Test maximum clues enforcement
cargo test --test storage_limits clue
# Test title/description constraints
cargo test --test storage_limits title
cargo test --test storage_limits description
# Test answer constraints
cargo test --test storage_limits answer
# Test large number of hunts
cargo test --test storage_limits hunts
# Test comprehensive stress scenarios
cargo test --test storage_limits stresscargo test --test storage_limits test_add_maximum_clues_at_limit -- --nocaptureEach test follows this pattern:
- Setup: Create test environment with timestamps and mocked auth
- Register: Register HuntyCore contract
- Execute: Create hunts/clues with various sizes
- Verify: Assert limits are enforced or accepted appropriately
#[test]
fn test_name() {
let env = Env::default();
env.ledger().set_timestamp(1_700_000_000);
env.mock_all_auths();
let core_id = setup_core_contract(&env);
let creator = Address::generate(&env);
as_core_contract(&env, &core_id, |env| {
// Test operations here
// Assert expectations
});
}InvalidTitle- Title exceeds maximum length or is emptyInvalidDescription- Description exceeds maximum lengthInvalidQuestion- Question exceeds maximum lengthTooManyClues- Attempt to add more than 100 clues- (Answer validation errors when answers exceed 256 bytes)
- 1 hunt with max metadata (200B title + 2000B description)
- 100 clues with max size (2000B questions + 256B answers each)
- Total bytes: ~227KB for metadata + clues
- 10 hunts × 100 clues each = 1,000 total clues
- Each clue stores question, answer hash, points, and flags
- Tests leaderboard scanning limits (MAX_LEADERBOARD_SCAN_SIZE: 200)
- 5 hunts with 20, 40, 60, 80, 100 clues respectively
- Total: 300 clues across hunts
- Verifies hunt counter, clue list storage, and retrieval performance
All tests should PASS when run against the current contract because:
- ✅ Contract enforces all documented limits
- ✅ Storage layer properly persists hunt and clue data
- ✅ Validation functions reject oversized inputs
- ✅ Composite key system prevents collisions
- ✅ TTL policies maintain data across ledger boundaries
- Tests use mocked authentication (
env.mock_all_auths()) to simplify setup - Timestamps are set to consistent values (
1_700_000_000) to avoid time-related failures - Contract registry uses
env.register()to deploy contracts in test environment - No actual token operations - reward testing is separate (see
test.rs)
Potential additional tests to consider:
- Memory profiling to measure actual storage bytes used
- Gas consumption analysis at storage limits
- Concurrent player registrations at hunt limits
- Leaderboard performance with 10,000+ players
- TTL extension behavior under heavy load
- Storage cleanup after hunt completion