Repository navigation
test(admin): add deterministic failure-boundary coverage for get_role - #1598
Open
opeolarewaju5-glitch wants to merge 2 commits into
Open
opeolarewaju5-glitch wants to merge 2 commits into
opeolarewaju5-glitch wants to merge 2 commits into
Conversation
🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1401
Description
Adds deterministic failure-boundary coverage for the
get_roleread entrypoint incontracts/admin/src/lib.rs, and documents its read-only invariants on the function itself.get_roleis the shared role-resolution primitive behindadd_admin,remove_admin,update_admin_role,deactivate_admin,reactivate_admin, and thepausablepause-authority check. Until now it had no direct test coverage — every assertion reached it indirectly through a caller, so its own boundary contract (what it returns, what it rejects, and what it must never do) was unpinned. Its siblingget_admin_rolealready carried a failure-boundary invariant comment;get_roledid not.Type of Change
No public interface change.
get_role(e: Env, address: Address) -> AdminRolekeeps its exact signature, return values, andContractError::NotAdmin(100) failure mode. No migration path is required.Files changed
contracts/admin/src/test_get_role_failure_boundaries.rscontracts/admin/src/lib.rs#[cfg(test)] modblock; expand theget_roledoc comment with determinism / boundary / error invariants.CHANGELOG.mdUnreleased → Addedentry (repo checklist requires it whencontracts/**is touched).Failure paths traced
get_rolereads exactly one instance-storage key,DataKey::AdminInfo(Address), and returns the storedAdminRole.Some(AdminInfo)SuperAdmin=3,Admin=2,Operator=1)Some(AdminInfo)Some(AdminInfo)activeis not consultedNoneContractError::NotAdmin(100)remove_adminNoneNotAdmin(100)NoneNotAdmin(100)initializeNoneNotAdmin(100) — a per-address read has no init dependencyAdminListentryNoneNotAdmin(100) — never returns stale/garbage datarequire_not_pausedon the read pathInvariants documented in code
ConfigEpochadvance, no events; a pure function ofAdminInfoat the current ledger.is_admin/has_role_at_least.NotAdmin(100) discriminant, never a barepanic!.get_rolereports and never advances the epoch.Test matrix
get_role_returns_exact_role_for_each_hierarchy_levelget_role_is_repeatable_and_leaves_epoch_and_events_untouchedget_role_rejects_unknown_address_with_not_admintry_get_role→Error(Contract, #100), no state changeget_role_rejects_zero_address_sentinel_with_not_adminGAAAA…WHF→#100get_role_before_initialize_rejects_with_not_admin#100get_role_rejects_removed_adminremove_admin→#100get_role_returns_stored_role_while_suspendedhas_role_at_leastisfalseget_role_is_timestamp_independent_across_suspension_expiry_boundaryuntil-1,==until,until+1, whilehas_role_at_leastflips at==until(inclusive expiry)get_role_returns_stored_role_for_deactivated_adminactive=false→ stored role;is_admin→Role::Userget_role_reflects_committed_role_change_and_detects_stale_readget_role_rejects_dangling_admin_list_entryAdminInfogone →#100, never stale datarejected_duplicate_add_admin_leaves_get_role_epoch_and_events_unchangedadd_admin→AlreadyActive(#405) before any epoch bumprejected_unauthorized_mutation_then_successful_retry_is_consistentadd_admin→#100with epoch + events +get_roleunchanged; retry then commits exactly onceget_role_remains_available_while_pausedContractPaused(#106);unpauserestores itunregistered_caller_is_rejected_before_any_state_changeremove_admin(stranger, target)→#100, target/epoch/events untouchedget_role_agrees_with_get_admin_role_across_all_statesRejection paths use
try_*clients so the real transaction boundary is exercised, with relativeget_config_epoch/events().all().len()snapshots for no-op assertions — the same scaffolding astest_pause_failure_boundaries.rs,test_atomic_rollback.rs, andtest_suspension.rs.These 16 tests have not been executed. To honour the issue's scope I did not modify anything outside
get_role, butmainat3beab889does not compile, socargo testcannot run at all. All three blockers below are pre-existing and are not touched by this PR:contracts/credence_errors/src/lib.rs— 40 compile errors onmain. Duplicate enum variants (RoleNotHeldAtLedger = 116at lines 175 and 676,SignatureExpired = 222twice, discriminant232twice) →E0428/E0081;use soroban_sdk::contracterror;is the crate's only import, so#[contracttype],panic_with_error,EnvandAddressare unresolved; and three variants referenced by other crates are absent (BytesTooLarge,MaxPauseSignersExceeded,CrossContractCallerMismatch).Cargo.lockdrift.soroban-env-host 22.1.3declaresed25519-dalek = ">=2.0.0"(open-ended) and the lock resolved it to3.0.0, which is API-incompatible with that crate's owntestutilscode. Verified recoverable withcargo update -p ed25519-dalek@3.0.0 --precise 2.2.0 --dry-run.contracts-tests.yml,contracts-lints.yml(rustfmt + clippy) andcoverage.ymlall declare'pull_request': nulland their jobs onlyechoa "paused — CI stabilization in progress" message, so they compile nothing.What was verified locally with Rust 1.89.0 (per
rust-toolchain.toml): the diff is confined to test code, a doc comment, and a changelog line — no entrypoint body changed, so gas, WASM size, and on-chain behaviour are untouched.Evidence to collect once
mainbuildscargo test -p admin get_role_returns_exact_role_for_each_hierarchy_level1 passed; 0 failedcargo test -p admin test_get_role_failure_boundaries16 passed; 0 failedcargo test -p admin --lockedcargo test --workspace --lockedcargo fmt --all -- --check&&cargo clippy --workspace --all-targets --all-features -- -D warningscargo test -p credence_errors error_codes_wireNotAdminstill100Non-goals
No typo/formatting/documentation-only or cosmetic change; no unrelated refactor, dependency upgrade, or broad rewrite (
get_roleandget_admin_roleremain separate entrypoints — deduplicating them is a behaviour-affecting refactor and is not attempted); no safeguard removed and no validation weakened to make a test pass.Checklist
get_role)CHANGELOG.mdupdated (contracts/**touched)<type>/<short-description>naming conventioncargo test/clippyevidence — blocked by the pre-existing breakage documented above