Skip to content

Add comprehensive RAM billing and KV coverage tests#270

Open
heifner wants to merge 2 commits intomasterfrom
feature/ram-billing-tests
Open

Add comprehensive RAM billing and KV coverage tests#270
heifner wants to merge 2 commits intomasterfrom
feature/ram-billing-tests

Conversation

@heifner
Copy link
Copy Markdown
Contributor

@heifner heifner commented Mar 23, 2026

Summary

  • 38 new tests covering all RAM billing code paths, iterator invalidation, cross-contract reads, and key/value boundary enforcement
  • New test contract actions for parameterized billing, notification handlers, and boundary testing
  • ROA limit and privileged contract bypass tests in protocol_feature_tests
  • Uses key_format constexpr consistently instead of raw literals

Test Coverage

Category Tests What it validates
Payer change billing 4 Correct refund/charge on payer change (same size, grow, shrink, back-to-self)
Erase refund 1 Refunds stored payer, not receiver
Secondary index billing 4 Correct amounts for idx store/remove/update
Cross-account idx billing 3 Idx bills payer (not contract), refunds correctly
Read-only rejection 4 erase, idx_store/remove/update blocked (table_operation_not_permitted)
Payer auth edge cases 3 Old payer unauth ok, missing auth fails, active-only (no sysio.payer) fails
Notification billing 2 Self-pay ok, third-party blocked in notify
Mixed-payer 2 Independent deltas, net zero
ROA limit 1 Quota exceeded → ram_usage_exceeded
Privileged bypass 1 sysio.* bypasses payer auth, non-sysio.* does not
Key/value boundaries 6 Max and oversize on both create and update
Iterator invalidation 6 Primary + secondary mutation during iteration
Cross-contract reads 1 Secondary index read across contracts

@heifner heifner force-pushed the feature/db-kv branch 6 times, most recently from 14b9eb6 to f9d1cd5 Compare March 28, 2026 05:22
Base automatically changed from feature/db-kv to master April 1, 2026 01:10
@heifner heifner requested a review from brianjohnson5972 April 1, 2026 13:10
38 new tests covering:
- Payer change billing (create, grow, shrink, back-to-self)
- Erase refunds correct stored payer
- Secondary index billing (store, remove, update amounts)
- Cross-account secondary index billing (payer, not receiver)
- Read-only transaction rejection (erase, idx_store/remove/update)
- Payer authorization edge cases (unauth, active-only, old payer unauth)
- Notification context billing (self-pay, third-party blocked)
- Mixed-payer transactions (independent deltas, net zero)
- ROA limit enforcement on KV operations
- Privileged sysio.* contract payer bypass
- Key/value size boundaries on both create and update
- Iterator invalidation under mutation (primary + secondary)
- Cross-contract secondary index reads

Also use key_format constexpr consistently in test_kv_api contract.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands KV/RAM-related unit coverage by adding new contract actions and host-side tests that exercise RAM billing edge cases (payer changes, secondary index billing), iterator mutation semantics, cross-contract secondary-index reads, ROA quota enforcement, and privileged payer-authorization bypass behavior.

Changes:

  • Added new test_kv_api contract actions to parameterize payer-billing scenarios, read-only rejection paths, notification-context billing, iterator invalidation under mutation, and key/value boundary cases (create + update).
  • Extended kv_api_tests.cpp with comprehensive RAM billing tests (primary + secondary, cross-account), read-only transaction write rejection tests, notification billing tests, iterator mutation tests, and cross-contract read tests.
  • Added protocol feature tests for ROA RAM ceiling enforcement via KV paths and for privileged sysio.* payer-authorization bypass behavior.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.

File Description
unittests/test-contracts/test_kv_api/test_kv_api.cpp Adds new test actions for boundary enforcement, payer-parameterized billing, read-only rejection, notification billing, iterator mutation, and cross-contract reads; updates callers to use key_format.
unittests/test-contracts/test_kv_api/test_kv_api.abi Updates ABI to include the newly added test_kv_api actions/structs used by host-side tests.
unittests/protocol_feature_tests.cpp Adds ROA-limit enforcement test for KV paths and privileged payer-auth bypass tests for sysio.* vs non-sysio.* privileged contracts.
unittests/kv_api_tests.cpp Adds host-side Boost tests covering KV RAM billing, payer changes, secondary index billing, read-only rejection, notification billing, iterator mutation, and cross-contract reads.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

memset(key, 0xB0, 256);
kv_set(key_format, 0, key, 256, "v1", 2); // create
kv_set(key_format, 0, key, 256, "v2", 2); // update — same key, different value
char buf[4]; uint32_t actual = 0;
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tstmaxkeyupd declares uint32_t actual but never uses it, which can trigger -Wunused-variable (and potentially fail builds when warnings are treated as errors). Remove the variable, or use it (e.g., by switching to an API that returns an actual-size outparam if intended).

Suggested change
char buf[4]; uint32_t actual = 0;
char buf[4];

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


// Send notification — receiver's on_notify handler does self-pay kv_set
[[sysio::action]]
void ramnotify(uint32_t key_id, uint32_t val_size) {
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ramnotify doesn't use key_id or val_size, which can trigger -Wunused-parameter warnings in contract builds. Consider marking them [[maybe_unused]] or explicitly casting to void to keep builds warning-clean while still keeping the parameters in the action data for the notification handler.

Suggested change
void ramnotify(uint32_t key_id, uint32_t val_size) {
void ramnotify([[maybe_unused]] uint32_t key_id, [[maybe_unused]] uint32_t val_size) {

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


// Send notification — receiver's handler tries third-party payer
[[sysio::action]]
void ramnotiferr(uint32_t key_id, uint32_t val_size, sysio::name payer) {
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ramnotiferr doesn't use its parameters (key_id, val_size, payer), which can trigger -Wunused-parameter warnings in contract builds. Mark unused parameters [[maybe_unused]] or cast them to void so warnings don’t become errors under stricter build settings.

Suggested change
void ramnotiferr(uint32_t key_id, uint32_t val_size, sysio::name payer) {
void ramnotiferr(uint32_t key_id, uint32_t val_size, sysio::name payer) {
(void)key_id;
(void)val_size;
(void)payer;

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants