@layerzerolabs/protocol-stellar-v2 0.2.8 → 0.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +443 -302
- package/.turbo/turbo-lint.log +118 -96
- package/.turbo/turbo-test.log +853 -731
- package/Cargo.lock +120 -37
- package/Cargo.toml +8 -5
- package/contracts/common-macros/src/contract_impl.rs +44 -0
- package/contracts/common-macros/src/lib.rs +86 -40
- package/contracts/common-macros/src/ownable.rs +24 -32
- package/contracts/common-macros/src/storage.rs +95 -120
- package/contracts/common-macros/src/tests/contract_impl.rs +289 -0
- package/contracts/common-macros/src/tests/mod.rs +9 -0
- package/contracts/common-macros/src/tests/ownable.rs +151 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_impl__snapshot_generated_contract_impl_code.snap +85 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_generated_ownable_code.snap +30 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_only_owner_preserves_function_signature.snap +9 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__storage__snapshot_generated_storage_code.snap +1072 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +45 -0
- package/contracts/common-macros/src/tests/storage.rs +485 -0
- package/contracts/common-macros/src/tests/test_helpers.rs +93 -0
- package/contracts/common-macros/src/tests/ttl_configurable.rs +34 -0
- package/contracts/common-macros/src/ttl_configurable.rs +31 -14
- package/contracts/common-macros/src/utils.rs +27 -0
- package/contracts/endpoint-v2/ARCHITECTURE.md +4 -4
- package/contracts/endpoint-v2/src/endpoint_v2.rs +18 -15
- package/contracts/endpoint-v2/src/interfaces/message_lib.rs +2 -3
- package/contracts/endpoint-v2/src/interfaces/message_lib_manager.rs +5 -3
- package/contracts/endpoint-v2/src/interfaces/messaging_channel.rs +2 -2
- package/contracts/endpoint-v2/src/interfaces/messaging_composer.rs +2 -2
- package/contracts/endpoint-v2/src/interfaces/send_lib.rs +4 -4
- package/contracts/endpoint-v2/src/lib.rs +6 -5
- package/contracts/endpoint-v2/src/message_lib_manager.rs +14 -6
- package/contracts/endpoint-v2/src/messaging_channel.rs +6 -2
- package/contracts/endpoint-v2/src/messaging_composer.rs +6 -2
- package/contracts/endpoint-v2/src/storage.rs +10 -7
- package/contracts/endpoint-v2/src/tests/endpoint_v2/pay_messaging_fees.rs +16 -16
- package/contracts/endpoint-v2/src/tests/endpoint_v2/ttl_config.rs +46 -46
- package/contracts/endpoint-v2/src/tests/mock.rs +2 -2
- package/contracts/endpoint-v2/src/util.rs +8 -2
- package/contracts/message-libs/block-message-lib/Cargo.toml +1 -0
- package/contracts/message-libs/block-message-lib/src/lib.rs +5 -5
- package/contracts/message-libs/message-lib-common/src/errors.rs +8 -8
- package/contracts/message-libs/message-lib-common/src/interfaces/dvn.rs +0 -1
- package/contracts/message-libs/message-lib-common/src/interfaces/mod.rs +3 -3
- package/contracts/message-libs/message-lib-common/src/lib.rs +0 -2
- package/contracts/message-libs/message-lib-common/src/packet_codec_v1.rs +4 -6
- package/contracts/message-libs/message-lib-common/src/tests/packet_codec_v1.rs +2 -2
- package/contracts/message-libs/message-lib-common/src/tests/worker_options.rs +11 -11
- package/contracts/message-libs/message-lib-common/src/worker_options.rs +10 -16
- package/contracts/message-libs/simple-message-lib/src/errors.rs +0 -4
- package/contracts/message-libs/simple-message-lib/src/simple_message_lib.rs +49 -34
- package/contracts/message-libs/simple-message-lib/src/storage.rs +3 -7
- package/contracts/message-libs/simple-message-lib/src/test.rs +3 -3
- package/contracts/message-libs/treasury/src/storage.rs +1 -2
- package/contracts/message-libs/treasury/src/tests/setup.rs +3 -2
- package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +0 -13
- package/contracts/message-libs/treasury/src/treasury.rs +18 -21
- package/contracts/message-libs/uln-302/Cargo.toml +1 -0
- package/contracts/message-libs/uln-302/src/interfaces/mod.rs +4 -4
- package/contracts/message-libs/uln-302/src/interfaces/{receive.rs → receive_uln.rs} +3 -3
- package/contracts/message-libs/uln-302/src/interfaces/{send.rs → send_uln.rs} +8 -80
- package/contracts/message-libs/uln-302/src/lib.rs +5 -4
- package/contracts/message-libs/uln-302/src/{receive.rs → receive_uln.rs} +20 -12
- package/contracts/message-libs/uln-302/src/{send.rs → send_uln.rs} +19 -13
- package/contracts/message-libs/uln-302/src/storage.rs +1 -2
- package/contracts/message-libs/uln-302/src/tests/config/uln_config.rs +3 -2
- package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +30 -30
- package/contracts/message-libs/uln-302/src/tests/setup.rs +12 -11
- package/contracts/message-libs/uln-302/src/tests/uln302/set_config.rs +1 -1
- package/contracts/message-libs/uln-302/src/{config_validation.rs → types.rs} +79 -11
- package/contracts/message-libs/uln-302/src/uln302.rs +15 -10
- package/contracts/oapp-macros/Cargo.toml +2 -8
- package/contracts/oapp-macros/src/lib.rs +57 -311
- package/contracts/oapp-macros/src/oapp_core.rs +23 -32
- package/contracts/oapp-macros/src/oapp_full.rs +8 -2
- package/contracts/oapp-macros/src/oapp_options_type3.rs +21 -36
- package/contracts/oapp-macros/src/oapp_receiver.rs +38 -57
- package/contracts/oapp-macros/src/oapp_sender.rs +12 -14
- package/contracts/oapp-macros/src/util.rs +14 -10
- package/contracts/oapps/counter/Cargo.toml +2 -1
- package/contracts/oapps/counter/integration_tests/utils.rs +4 -4
- package/contracts/oapps/counter/src/codec.rs +8 -9
- package/contracts/oapps/counter/src/counter.rs +156 -147
- package/contracts/oapps/counter/src/storage.rs +1 -2
- package/contracts/oapps/counter/src/tests/test_codec.rs +5 -5
- package/contracts/oapps/counter/src/tests/test_counter.rs +11 -13
- package/contracts/oapps/oapp/Cargo.toml +1 -0
- package/contracts/oapps/oapp/src/errors.rs +1 -1
- package/contracts/oapps/oapp/src/lib.rs +3 -0
- package/contracts/oapps/oapp/src/macro_tests/mod.rs +1 -0
- package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +312 -0
- package/contracts/oapps/oapp/src/oapp_core.rs +52 -53
- package/contracts/oapps/oapp/src/oapp_options_type3.rs +18 -28
- package/contracts/oapps/oapp/src/oapp_receiver.rs +82 -31
- package/contracts/oapps/oapp/src/oapp_sender.rs +55 -13
- package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +16 -3
- package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +33 -8
- package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +6 -9
- package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +28 -15
- package/contracts/oapps/oft/Cargo.toml +27 -0
- package/contracts/oapps/oft/integration-tests/mod.rs +3 -0
- package/contracts/oapps/oft/integration-tests/setup.rs +320 -0
- package/contracts/oapps/oft/integration-tests/test_with_sml.rs +155 -0
- package/contracts/oapps/oft/integration-tests/utils.rs +201 -0
- package/contracts/oapps/oft/src/codec/mod.rs +2 -0
- package/contracts/oapps/oft/src/codec/oft_compose_msg_codec.rs +55 -0
- package/contracts/oapps/oft/src/codec/oft_msg_codec.rs +62 -0
- package/contracts/oapps/oft/src/constants.rs +5 -0
- package/contracts/oapps/oft/src/errors.rs +8 -0
- package/contracts/oapps/oft/src/events.rs +19 -0
- package/contracts/oapps/oft/src/interfaces/mint_burn_token.rs +23 -0
- package/contracts/oapps/oft/src/interfaces/mod.rs +3 -0
- package/contracts/oapps/oft/src/lib.rs +22 -0
- package/contracts/oapps/oft/src/macro_tests/mod.rs +2 -0
- package/contracts/oapps/oft/src/macro_tests/test_all_default.rs +41 -0
- package/contracts/oapps/oft/src/macro_tests/test_override.rs +83 -0
- package/contracts/oapps/oft/src/oft.rs +320 -0
- package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +50 -0
- package/contracts/oapps/oft/src/oft_types/mint_burn.rs +50 -0
- package/contracts/oapps/oft/src/oft_types/mod.rs +10 -0
- package/contracts/oapps/oft/src/storage.rs +11 -0
- package/contracts/oapps/oft/src/tests/mod.rs +13 -0
- package/contracts/oapps/oft/src/tests/test_decimals.rs +89 -0
- package/contracts/oapps/oft/src/tests/test_lz_receive.rs +282 -0
- package/contracts/oapps/oft/src/tests/test_oft_compose_msg_codec.rs +68 -0
- package/contracts/oapps/oft/src/tests/test_oft_msg_codec.rs +136 -0
- package/contracts/oapps/oft/src/tests/test_oft_version.rs +13 -0
- package/contracts/oapps/oft/src/tests/test_quote_oft.rs +159 -0
- package/contracts/oapps/oft/src/tests/test_quote_send.rs +195 -0
- package/contracts/oapps/oft/src/tests/test_resolve_address.rs +37 -0
- package/contracts/oapps/oft/src/tests/test_send.rs +915 -0
- package/contracts/oapps/oft/src/tests/test_token.rs +47 -0
- package/contracts/oapps/oft/src/tests/test_utils.rs +789 -0
- package/contracts/oapps/oft/src/types.rs +38 -0
- package/contracts/oapps/oft/src/utils.rs +67 -0
- package/contracts/oapps/oft-mint-burn/Cargo.toml +26 -0
- package/contracts/oapps/oft-mint-burn/src/lib.rs +3 -0
- package/contracts/oapps/oft-mint-burn/src/oft.rs +28 -0
- package/contracts/oapps/oft-mint-burn/src/tests/mod.rs +1 -0
- package/contracts/utils/src/buffer_reader.rs +8 -9
- package/contracts/utils/src/buffer_writer.rs +11 -5
- package/contracts/utils/src/errors.rs +5 -5
- package/contracts/utils/src/ownable.rs +14 -6
- package/contracts/utils/src/testing_utils.rs +11 -1
- package/contracts/utils/src/tests/buffer_reader.rs +491 -730
- package/contracts/utils/src/tests/buffer_writer.rs +336 -148
- package/contracts/utils/src/tests/bytes_ext.rs +125 -40
- package/contracts/utils/src/tests/mod.rs +3 -0
- package/contracts/utils/src/tests/ownable.rs +379 -27
- package/contracts/utils/src/tests/test_helper.rs +47 -0
- package/contracts/utils/src/tests/testing_utils.rs +555 -0
- package/contracts/utils/src/tests/ttl.rs +421 -0
- package/contracts/utils/src/ttl.rs +29 -89
- package/contracts/workers/dvn/Cargo.toml +31 -0
- package/contracts/workers/dvn/src/auth.rs +66 -0
- package/contracts/workers/dvn/src/dvn.rs +143 -0
- package/contracts/workers/dvn/src/errors.rs +21 -0
- package/contracts/workers/dvn/src/events.rs +19 -0
- package/contracts/workers/dvn/src/interfaces/dvn.rs +12 -0
- package/contracts/workers/dvn/src/interfaces/mod.rs +5 -0
- package/contracts/workers/dvn/src/interfaces/multisig.rs +15 -0
- package/contracts/workers/dvn/src/lib.rs +24 -0
- package/contracts/workers/dvn/src/multisig.rs +127 -0
- package/contracts/workers/dvn/src/storage.rs +35 -0
- package/contracts/workers/dvn/src/tests/auth.rs +237 -0
- package/contracts/workers/dvn/src/tests/dvn.rs +349 -0
- package/contracts/workers/dvn/src/tests/key_pair.rs +66 -0
- package/contracts/workers/dvn/src/tests/mod.rs +5 -0
- package/contracts/workers/dvn/src/tests/multisig/mod.rs +3 -0
- package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +133 -0
- package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +108 -0
- package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +109 -0
- package/contracts/workers/dvn/src/tests/setup.rs +109 -0
- package/contracts/workers/dvn/src/types.rs +26 -0
- package/contracts/workers/dvn-fee-lib/Cargo.toml +24 -0
- package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +113 -0
- package/contracts/workers/dvn-fee-lib/src/errors.rs +8 -0
- package/contracts/workers/dvn-fee-lib/src/lib.rs +17 -0
- package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +282 -0
- package/contracts/workers/dvn-fee-lib/src/tests/mod.rs +1 -0
- package/contracts/workers/executor/Cargo.toml +10 -7
- package/contracts/workers/executor/src/errors.rs +8 -0
- package/contracts/workers/executor/src/events.rs +4 -7
- package/contracts/workers/executor/src/interfaces/executor.rs +72 -22
- package/contracts/workers/executor/src/interfaces/mod.rs +0 -2
- package/contracts/workers/executor/src/lib.rs +16 -7
- package/contracts/workers/executor/src/lz_executor.rs +308 -0
- package/contracts/workers/executor/src/storage.rs +24 -16
- package/contracts/workers/executor-fee-lib/Cargo.toml +22 -0
- package/contracts/workers/executor-fee-lib/src/errors.rs +15 -0
- package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +215 -0
- package/contracts/workers/executor-fee-lib/src/executor_option.rs +203 -0
- package/contracts/workers/executor-fee-lib/src/lib.rs +7 -0
- package/contracts/workers/executor-helper/Cargo.toml +29 -0
- package/contracts/workers/executor-helper/src/executor_helper.rs +161 -0
- package/contracts/workers/executor-helper/src/lib.rs +11 -0
- package/contracts/workers/{worker-common → worker}/Cargo.toml +1 -4
- package/contracts/workers/worker/src/errors.rs +24 -0
- package/contracts/workers/worker/src/events.rs +62 -0
- package/contracts/workers/worker/src/interfaces/dvn_fee_lib.rs +75 -0
- package/contracts/workers/worker/src/interfaces/executor_fee_lib.rs +84 -0
- package/contracts/workers/{worker-common → worker}/src/interfaces/mod.rs +2 -2
- package/contracts/workers/worker/src/interfaces/price_feed.rs +85 -0
- package/contracts/workers/worker/src/lib.rs +14 -0
- package/contracts/workers/worker/src/storage.rs +63 -0
- package/contracts/workers/worker/src/worker.rs +459 -0
- package/package.json +3 -3
- package/sdk/dist/generated/bml.d.ts +88 -17
- package/sdk/dist/generated/bml.js +62 -16
- package/sdk/dist/generated/counter.d.ts +281 -102
- package/sdk/dist/generated/counter.js +93 -41
- package/sdk/dist/generated/endpoint.d.ts +128 -105
- package/sdk/dist/generated/endpoint.js +47 -45
- package/sdk/dist/generated/sml.d.ts +212 -69
- package/sdk/dist/generated/sml.js +103 -53
- package/sdk/dist/generated/uln302.d.ts +270 -173
- package/sdk/dist/generated/uln302.js +112 -64
- package/sdk/package.json +11 -11
- package/sdk/test/index.test.ts +147 -42
- package/sdk/test/suites/constants.ts +7 -3
- package/sdk/test/suites/deploy.ts +65 -42
- package/sdk/test/suites/localnet.ts +2 -2
- package/sdk/test/suites/scan.ts +28 -25
- package/sdk/test/utils.ts +199 -0
- package/sdk/tsconfig.json +93 -95
- package/tools/ts-bindings-gen/src/main.rs +2 -0
- package/contracts/common-macros/src/snapshots/common_macros__tests__tests__snapshot_generated_storage_code.snap +0 -310
- package/contracts/common-macros/src/tests.rs +0 -287
- package/contracts/oapp-macros/tests/test_macros.rs +0 -522
- package/contracts/workers/executor/src/executor.rs +0 -347
- package/contracts/workers/executor/src/interfaces/types.rs +0 -51
- package/contracts/workers/worker-common/src/constants.rs +0 -17
- package/contracts/workers/worker-common/src/errors.rs +0 -6
- package/contracts/workers/worker-common/src/events.rs +0 -34
- package/contracts/workers/worker-common/src/interfaces/executor_fee_lib.rs +0 -35
- package/contracts/workers/worker-common/src/interfaces/price_feed.rs +0 -40
- package/contracts/workers/worker-common/src/interfaces/worker.rs +0 -60
- package/contracts/workers/worker-common/src/lib.rs +0 -19
- package/contracts/workers/worker-common/src/storage.rs +0 -32
- package/contracts/workers/worker-common/src/worker_common.rs +0 -166
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
source: contracts/common-macros/src/tests/ttl_configurable.rs
|
|
3
|
+
assertion_line: 20
|
|
4
|
+
expression: formatted
|
|
5
|
+
---
|
|
6
|
+
#[common_macros::ownable]
|
|
7
|
+
pub struct MyContract {
|
|
8
|
+
some_field: u32,
|
|
9
|
+
}
|
|
10
|
+
use utils::ttl::TtlConfigurable as _;
|
|
11
|
+
#[soroban_sdk::contractimpl]
|
|
12
|
+
impl utils::ttl::TtlConfigurable for MyContract {
|
|
13
|
+
#[common_macros::only_owner]
|
|
14
|
+
fn set_ttl_configs(
|
|
15
|
+
env: &soroban_sdk::Env,
|
|
16
|
+
instance: &Option<utils::ttl::TtlConfig>,
|
|
17
|
+
persistent: &Option<utils::ttl::TtlConfig>,
|
|
18
|
+
) {
|
|
19
|
+
utils::ttl::DefaultTtlConfigurable::set_ttl_configs(env, instance, persistent);
|
|
20
|
+
}
|
|
21
|
+
fn ttl_configs(
|
|
22
|
+
env: &soroban_sdk::Env,
|
|
23
|
+
) -> (Option<utils::ttl::TtlConfig>, Option<utils::ttl::TtlConfig>) {
|
|
24
|
+
utils::ttl::DefaultTtlConfigurable::ttl_configs(env)
|
|
25
|
+
}
|
|
26
|
+
#[common_macros::only_owner]
|
|
27
|
+
fn freeze_ttl_configs(env: &soroban_sdk::Env) {
|
|
28
|
+
utils::ttl::DefaultTtlConfigurable::freeze_ttl_configs(env);
|
|
29
|
+
}
|
|
30
|
+
fn is_ttl_configs_frozen(env: &soroban_sdk::Env) -> bool {
|
|
31
|
+
utils::ttl::DefaultTtlConfigurable::is_ttl_configs_frozen(env)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
#[soroban_sdk::contractimpl]
|
|
35
|
+
impl MyContract {
|
|
36
|
+
/// Extends the instance TTL.
|
|
37
|
+
///
|
|
38
|
+
/// # Arguments
|
|
39
|
+
///
|
|
40
|
+
/// * `threshold` - The threshold to extend the TTL.
|
|
41
|
+
/// * `extend_to` - The TTL to extend to.
|
|
42
|
+
pub fn extend_instance_ttl(env: &soroban_sdk::Env, threshold: u32, extend_to: u32) {
|
|
43
|
+
env.storage().instance().extend_ttl(threshold, extend_to);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
use quote::quote;
|
|
2
|
+
|
|
3
|
+
use crate::tests::test_helpers::{assert_panics_contains, non_enum_item_inputs};
|
|
4
|
+
|
|
5
|
+
#[test]
|
|
6
|
+
fn test_non_enum_input() {
|
|
7
|
+
for (case, input) in non_enum_item_inputs() {
|
|
8
|
+
assert_panics_contains(case, "failed to parse enum", || {
|
|
9
|
+
crate::storage::generate_storage(quote! {}, input.clone());
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
#[test]
|
|
15
|
+
fn test_tuple_variant_rejected() {
|
|
16
|
+
let cases = vec![
|
|
17
|
+
(
|
|
18
|
+
"instance tuple variant",
|
|
19
|
+
quote! {
|
|
20
|
+
enum TestEnum {
|
|
21
|
+
#[instance(u32)]
|
|
22
|
+
TupleVariant(String, u32),
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
),
|
|
26
|
+
(
|
|
27
|
+
"persistent tuple variant",
|
|
28
|
+
quote! {
|
|
29
|
+
enum TestEnum {
|
|
30
|
+
#[persistent(u32)]
|
|
31
|
+
TupleVariant(String, u32),
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
),
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
for (case, input) in cases {
|
|
38
|
+
assert_panics_contains(case, "only unit variants or named fields are supported", || {
|
|
39
|
+
crate::storage::generate_storage(quote! {}, input.clone());
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#[test]
|
|
45
|
+
fn test_attribute_errors() {
|
|
46
|
+
let cases_storage_type = vec![
|
|
47
|
+
(
|
|
48
|
+
"missing storage type",
|
|
49
|
+
"storage type must be specified exactly once",
|
|
50
|
+
quote! {
|
|
51
|
+
enum TestEnum { Counter }
|
|
52
|
+
},
|
|
53
|
+
),
|
|
54
|
+
(
|
|
55
|
+
"multiple storage types",
|
|
56
|
+
"storage type must be specified exactly once",
|
|
57
|
+
quote! {
|
|
58
|
+
enum TestEnum {
|
|
59
|
+
#[instance(u32)]
|
|
60
|
+
#[persistent(u32)]
|
|
61
|
+
Counter,
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
),
|
|
65
|
+
(
|
|
66
|
+
"missing type param",
|
|
67
|
+
"failed to parse storage variant for Counter",
|
|
68
|
+
quote! {
|
|
69
|
+
enum TestEnum {
|
|
70
|
+
#[instance]
|
|
71
|
+
Counter,
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
),
|
|
75
|
+
(
|
|
76
|
+
"invalid type param",
|
|
77
|
+
"failed to parse storage variant for",
|
|
78
|
+
quote! {
|
|
79
|
+
enum TestEnum {
|
|
80
|
+
#[persistent(u32, String)]
|
|
81
|
+
Counter,
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
),
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
for (case, expected, input) in cases_storage_type {
|
|
88
|
+
assert_panics_contains(case, expected, || {
|
|
89
|
+
crate::storage::generate_storage(quote! {}, input.clone());
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
let cases_default = vec![
|
|
94
|
+
(
|
|
95
|
+
"multiple defaults",
|
|
96
|
+
"multiple default values specified",
|
|
97
|
+
quote! {
|
|
98
|
+
enum TestEnum {
|
|
99
|
+
#[persistent(u32)]
|
|
100
|
+
#[default(0)]
|
|
101
|
+
#[default(1)]
|
|
102
|
+
Counter,
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
),
|
|
106
|
+
(
|
|
107
|
+
"invalid default value",
|
|
108
|
+
"failed to parse default value",
|
|
109
|
+
quote! {
|
|
110
|
+
enum TestEnum {
|
|
111
|
+
#[persistent(u32)]
|
|
112
|
+
#[default(!@#$%)]
|
|
113
|
+
Counter,
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
),
|
|
117
|
+
(
|
|
118
|
+
"default without parens",
|
|
119
|
+
"failed to parse default value",
|
|
120
|
+
quote! {
|
|
121
|
+
enum TestEnum {
|
|
122
|
+
#[persistent(u32)]
|
|
123
|
+
#[default]
|
|
124
|
+
Counter,
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
),
|
|
128
|
+
(
|
|
129
|
+
"default with empty parens",
|
|
130
|
+
"failed to parse default value",
|
|
131
|
+
quote! {
|
|
132
|
+
enum TestEnum {
|
|
133
|
+
#[persistent(u32)]
|
|
134
|
+
#[default()]
|
|
135
|
+
Counter,
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
),
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
for (case, expected, input) in cases_default {
|
|
142
|
+
assert_panics_contains(case, expected, || {
|
|
143
|
+
crate::storage::generate_storage(quote! {}, input.clone());
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
let cases_name = vec![
|
|
148
|
+
(
|
|
149
|
+
"multiple name attrs",
|
|
150
|
+
"multiple name attributes specified",
|
|
151
|
+
quote! {
|
|
152
|
+
enum TestEnum {
|
|
153
|
+
#[persistent(u32)]
|
|
154
|
+
#[name("foo")]
|
|
155
|
+
#[name("bar")]
|
|
156
|
+
Counter,
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
),
|
|
160
|
+
(
|
|
161
|
+
"invalid name attr",
|
|
162
|
+
"failed to parse name attribute",
|
|
163
|
+
quote! {
|
|
164
|
+
enum TestEnum {
|
|
165
|
+
#[persistent(u32)]
|
|
166
|
+
#[name(123)]
|
|
167
|
+
Counter,
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
),
|
|
171
|
+
(
|
|
172
|
+
"name without parens",
|
|
173
|
+
"failed to parse name attribute",
|
|
174
|
+
quote! {
|
|
175
|
+
enum TestEnum {
|
|
176
|
+
#[persistent(u32)]
|
|
177
|
+
#[name]
|
|
178
|
+
Counter,
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
),
|
|
182
|
+
(
|
|
183
|
+
"name with empty parens",
|
|
184
|
+
"failed to parse name attribute",
|
|
185
|
+
quote! {
|
|
186
|
+
enum TestEnum {
|
|
187
|
+
#[persistent(u32)]
|
|
188
|
+
#[name()]
|
|
189
|
+
Counter,
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
),
|
|
193
|
+
];
|
|
194
|
+
|
|
195
|
+
for (case, expected, input) in cases_name {
|
|
196
|
+
assert_panics_contains(case, expected, || {
|
|
197
|
+
crate::storage::generate_storage(quote! {}, input.clone());
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
assert_panics_contains("unknown attribute", "unknown attribute", || {
|
|
202
|
+
let input = quote! {
|
|
203
|
+
enum TestEnum {
|
|
204
|
+
#[persistent(u32)]
|
|
205
|
+
#[unknown_attr]
|
|
206
|
+
Counter,
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
crate::storage::generate_storage(quote! {}, input);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// Test #[no_ttl_extension] validation
|
|
213
|
+
let cases_no_ttl = vec![
|
|
214
|
+
(
|
|
215
|
+
"multiple no_ttl_extension",
|
|
216
|
+
"multiple #[no_ttl_extension]",
|
|
217
|
+
quote! {
|
|
218
|
+
enum TestEnum {
|
|
219
|
+
#[persistent(u32)]
|
|
220
|
+
#[no_ttl_extension]
|
|
221
|
+
#[no_ttl_extension]
|
|
222
|
+
Counter,
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
),
|
|
226
|
+
(
|
|
227
|
+
"triple no_ttl_extension",
|
|
228
|
+
"multiple #[no_ttl_extension]",
|
|
229
|
+
quote! {
|
|
230
|
+
enum TestEnum {
|
|
231
|
+
#[persistent(u32)]
|
|
232
|
+
#[no_ttl_extension]
|
|
233
|
+
#[no_ttl_extension]
|
|
234
|
+
#[no_ttl_extension]
|
|
235
|
+
Counter,
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
),
|
|
239
|
+
(
|
|
240
|
+
"no_ttl_extension on instance",
|
|
241
|
+
"can only be used with #[persistent",
|
|
242
|
+
quote! {
|
|
243
|
+
enum TestEnum {
|
|
244
|
+
#[instance(u32)]
|
|
245
|
+
#[no_ttl_extension]
|
|
246
|
+
Counter,
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
),
|
|
250
|
+
(
|
|
251
|
+
"no_ttl_extension on instance with default",
|
|
252
|
+
"can only be used with #[persistent",
|
|
253
|
+
quote! {
|
|
254
|
+
enum TestEnum {
|
|
255
|
+
#[instance(u32)]
|
|
256
|
+
#[default(0)]
|
|
257
|
+
#[no_ttl_extension]
|
|
258
|
+
Counter,
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
),
|
|
262
|
+
(
|
|
263
|
+
"no_ttl_extension before instance storage type",
|
|
264
|
+
"can only be used with #[persistent",
|
|
265
|
+
quote! {
|
|
266
|
+
enum TestEnum {
|
|
267
|
+
#[no_ttl_extension]
|
|
268
|
+
#[instance(u32)]
|
|
269
|
+
Counter,
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
),
|
|
273
|
+
(
|
|
274
|
+
"no_ttl_extension on temporary",
|
|
275
|
+
"can only be used with #[persistent",
|
|
276
|
+
quote! {
|
|
277
|
+
enum TestEnum {
|
|
278
|
+
#[temporary(u32)]
|
|
279
|
+
#[no_ttl_extension]
|
|
280
|
+
Counter,
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
),
|
|
284
|
+
(
|
|
285
|
+
"no_ttl_extension before temporary storage type",
|
|
286
|
+
"can only be used with #[persistent",
|
|
287
|
+
quote! {
|
|
288
|
+
enum TestEnum {
|
|
289
|
+
#[no_ttl_extension]
|
|
290
|
+
#[temporary(u32)]
|
|
291
|
+
Counter,
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
),
|
|
295
|
+
(
|
|
296
|
+
"no_ttl_extension on instance in multi-variant enum",
|
|
297
|
+
"can only be used with #[persistent",
|
|
298
|
+
quote! {
|
|
299
|
+
enum TestEnum {
|
|
300
|
+
#[persistent(u32)]
|
|
301
|
+
ValidVariant,
|
|
302
|
+
|
|
303
|
+
#[instance(u32)]
|
|
304
|
+
#[no_ttl_extension]
|
|
305
|
+
InvalidVariant,
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
),
|
|
309
|
+
];
|
|
310
|
+
|
|
311
|
+
for (case, expected, input) in cases_no_ttl {
|
|
312
|
+
assert_panics_contains(case, expected, || {
|
|
313
|
+
crate::storage::generate_storage(quote! {}, input.clone());
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Test that #[storage] does not accept arguments
|
|
318
|
+
let cases_attr = vec![
|
|
319
|
+
("unknown arg", "does not accept arguments", quote! { unknown }),
|
|
320
|
+
("key-value arg", "does not accept arguments", quote! { unknown = SomeType }),
|
|
321
|
+
("function-like arg", "does not accept arguments", quote! { foo(bar) }),
|
|
322
|
+
];
|
|
323
|
+
let input = quote! {
|
|
324
|
+
enum TestEnum {
|
|
325
|
+
#[instance(u32)]
|
|
326
|
+
Counter,
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
for (case, expected, attr) in cases_attr {
|
|
331
|
+
assert_panics_contains(case, expected, || {
|
|
332
|
+
crate::storage::generate_storage(attr.clone(), input.clone());
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// ============================================
|
|
338
|
+
// Valid Cases: Snapshot Tests for Generated Code
|
|
339
|
+
// ============================================
|
|
340
|
+
|
|
341
|
+
/// Comprehensive snapshot test covering all storage macro features:
|
|
342
|
+
/// - All storage types: instance, persistent, temporary
|
|
343
|
+
/// - Unit variants and named field variants
|
|
344
|
+
/// - Default values (with and without)
|
|
345
|
+
/// - TTL extension control (TTL extended by default for persistent storage, opt-out with #[no_ttl_extension])
|
|
346
|
+
/// - Custom name attribute
|
|
347
|
+
/// - Function naming rules: snake_case conversion (UserBalance -> user_balance) and custom name override
|
|
348
|
+
/// - Primitive type detection: u32/i64/bool passed by value, u8/usize/String/Vec/Address passed by reference
|
|
349
|
+
/// - Clone behavior: primitive types not cloned, non-primitive types cloned in key construction
|
|
350
|
+
/// - Field extraction: Unit variants have no fields, Named variants extract fields in order
|
|
351
|
+
/// - Doc comments and visibility
|
|
352
|
+
#[test]
|
|
353
|
+
fn snapshot_generated_storage_code() {
|
|
354
|
+
let input = quote! {
|
|
355
|
+
/// Enum-level doc comment
|
|
356
|
+
pub enum StorageKeys {
|
|
357
|
+
/// Instance storage with default value (no auto TTL for instance)
|
|
358
|
+
#[instance(u32)]
|
|
359
|
+
#[default(0)]
|
|
360
|
+
Counter,
|
|
361
|
+
|
|
362
|
+
/// Persistent storage with named field and default (has auto TTL by default)
|
|
363
|
+
#[persistent(String)]
|
|
364
|
+
#[default("hello".to_string())]
|
|
365
|
+
Message { sender: Address },
|
|
366
|
+
|
|
367
|
+
/// Temporary storage (no auto TTL for temporary)
|
|
368
|
+
#[temporary(bool)]
|
|
369
|
+
Flag { key: String },
|
|
370
|
+
|
|
371
|
+
/// Persistent storage with multiple fields (no default)
|
|
372
|
+
#[persistent(Vec<u8>)]
|
|
373
|
+
Data { id: u64, name: String },
|
|
374
|
+
|
|
375
|
+
/// Persistent storage without fields or default
|
|
376
|
+
#[persistent(Address)]
|
|
377
|
+
Owner,
|
|
378
|
+
|
|
379
|
+
/// Persistent storage with custom name override
|
|
380
|
+
#[persistent(Option<Address>)]
|
|
381
|
+
#[name("custom_key_name")]
|
|
382
|
+
OptionalData { key: BytesN<32> },
|
|
383
|
+
|
|
384
|
+
/// Temporary storage (no auto TTL for temporary)
|
|
385
|
+
#[temporary(u64)]
|
|
386
|
+
TempData,
|
|
387
|
+
|
|
388
|
+
/// Test snake_case naming: UserBalance -> user_balance
|
|
389
|
+
#[persistent(u32)]
|
|
390
|
+
UserBalance { user: Address },
|
|
391
|
+
|
|
392
|
+
/// Test custom name override: #[name("custom")] -> custom
|
|
393
|
+
#[persistent(u32)]
|
|
394
|
+
#[name("custom")]
|
|
395
|
+
AnotherVariant { key: Address },
|
|
396
|
+
|
|
397
|
+
/// Test primitive types: passed by value, not cloned
|
|
398
|
+
#[persistent(u32)]
|
|
399
|
+
U32Value { key: u32 },
|
|
400
|
+
#[persistent(i64)]
|
|
401
|
+
I64Value { key: i64 },
|
|
402
|
+
#[persistent(bool)]
|
|
403
|
+
BoolValue { key: bool },
|
|
404
|
+
|
|
405
|
+
/// Test non-primitive types: passed by reference, cloned
|
|
406
|
+
#[persistent(u32)]
|
|
407
|
+
U8Value { key: u8 },
|
|
408
|
+
#[persistent(u32)]
|
|
409
|
+
UsizeValue { key: usize },
|
|
410
|
+
#[persistent(String)]
|
|
411
|
+
StringValue { key: String },
|
|
412
|
+
#[persistent(Vec<u32>)]
|
|
413
|
+
VecValue { key: Vec<u32> },
|
|
414
|
+
#[persistent(Address)]
|
|
415
|
+
AddressValue { key: Address },
|
|
416
|
+
|
|
417
|
+
/// Test Unit variant: no fields
|
|
418
|
+
#[persistent(u32)]
|
|
419
|
+
UnitVariant,
|
|
420
|
+
|
|
421
|
+
/// Test Named variant: fields extracted in order
|
|
422
|
+
#[persistent(u32)]
|
|
423
|
+
NamedVariant { first: u32, second: String, third: Address },
|
|
424
|
+
|
|
425
|
+
/// Test #[no_ttl_extension] opt-out for persistent storage
|
|
426
|
+
#[persistent(u64)]
|
|
427
|
+
#[no_ttl_extension]
|
|
428
|
+
CachedValue { key: Address },
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
let result = crate::storage::generate_storage(quote! {}, input);
|
|
433
|
+
let formatted = prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"));
|
|
434
|
+
|
|
435
|
+
insta::assert_snapshot!(formatted);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// ============================================
|
|
439
|
+
// is_primitive_type Unit Tests
|
|
440
|
+
// ============================================
|
|
441
|
+
|
|
442
|
+
#[test]
|
|
443
|
+
fn test_is_primitive_type_recognizes_primitive_types() {
|
|
444
|
+
let primitives = ["u32", "i32", "u64", "i64", "u128", "i128", "bool"];
|
|
445
|
+
for ty_str in primitives {
|
|
446
|
+
let ty = syn::parse_str::<syn::Type>(ty_str).expect("failed to parse type");
|
|
447
|
+
assert!(crate::storage::is_primitive_type(&ty), "{ty_str} should be recognized as primitive");
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
#[test]
|
|
452
|
+
fn test_is_primitive_type_rejects_non_primitive_types() {
|
|
453
|
+
let non_primitives = [
|
|
454
|
+
"u8", // not in primitive list
|
|
455
|
+
"usize", // not in primitive list
|
|
456
|
+
"String",
|
|
457
|
+
"Address",
|
|
458
|
+
"Vec<u8>",
|
|
459
|
+
"Option<u32>",
|
|
460
|
+
"std::u32", // multi-segment path
|
|
461
|
+
"soroban_sdk::Address",
|
|
462
|
+
];
|
|
463
|
+
|
|
464
|
+
for ty_str in non_primitives {
|
|
465
|
+
let ty = syn::parse_str::<syn::Type>(ty_str).expect("failed to parse type");
|
|
466
|
+
assert!(!crate::storage::is_primitive_type(&ty), "{ty_str} should NOT be recognized as primitive");
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
#[test]
|
|
471
|
+
fn test_is_primitive_type_rejects_other_type_variants() {
|
|
472
|
+
let other_variants = [
|
|
473
|
+
("&u32", "reference"),
|
|
474
|
+
("&mut u32", "mutable reference"),
|
|
475
|
+
("(u32, i32)", "tuple"),
|
|
476
|
+
("[u32; 4]", "array"),
|
|
477
|
+
("[u32]", "slice"),
|
|
478
|
+
("!", "never"),
|
|
479
|
+
];
|
|
480
|
+
|
|
481
|
+
for (ty_str, label) in other_variants {
|
|
482
|
+
let ty = syn::parse_str::<syn::Type>(ty_str).expect("failed to parse type");
|
|
483
|
+
assert!(!crate::storage::is_primitive_type(&ty), "{label} type {ty_str} should NOT be recognized as primitive");
|
|
484
|
+
}
|
|
485
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#![allow(unused_macros)]
|
|
2
|
+
|
|
3
|
+
pub(in crate::tests) fn assert_panics_contains<F>(case: &str, expected_substring: &str, f: F)
|
|
4
|
+
where
|
|
5
|
+
F: FnOnce() + std::panic::UnwindSafe,
|
|
6
|
+
{
|
|
7
|
+
let result = std::panic::catch_unwind(f);
|
|
8
|
+
assert!(result.is_err(), "{case}: expected panic, but function returned normally");
|
|
9
|
+
|
|
10
|
+
let payload = result.expect_err("checked above");
|
|
11
|
+
let msg = if let Some(s) = payload.downcast_ref::<&str>() {
|
|
12
|
+
(*s).to_string()
|
|
13
|
+
} else if let Some(s) = payload.downcast_ref::<String>() {
|
|
14
|
+
s.clone()
|
|
15
|
+
} else {
|
|
16
|
+
format!("{payload:?}")
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
assert!(
|
|
20
|
+
msg.contains(expected_substring),
|
|
21
|
+
"{case}: expected panic message to contain '{expected_substring}', got '{msg}'"
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
pub(in crate::tests) fn non_struct_item_inputs() -> Vec<(&'static str, proc_macro2::TokenStream)> {
|
|
26
|
+
filter_item_inputs_excluding_labels(&["struct"])
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
pub(in crate::tests) fn non_enum_item_inputs() -> Vec<(&'static str, proc_macro2::TokenStream)> {
|
|
30
|
+
filter_item_inputs_excluding_labels(&["enum"])
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// Canonical list of syntactically-valid `syn::Item` inputs.
|
|
34
|
+
///
|
|
35
|
+
/// Keep this list broad and reusable; other helpers should filter it by AST kind.
|
|
36
|
+
pub(in crate::tests) fn item_inputs() -> Vec<(&'static str, proc_macro2::TokenStream)> {
|
|
37
|
+
vec![
|
|
38
|
+
(
|
|
39
|
+
"struct",
|
|
40
|
+
quote::quote! {
|
|
41
|
+
struct AStruct {
|
|
42
|
+
field: u32,
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
),
|
|
46
|
+
(
|
|
47
|
+
"enum",
|
|
48
|
+
quote::quote! {
|
|
49
|
+
enum AnEnum {
|
|
50
|
+
Variant1,
|
|
51
|
+
Variant2,
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
),
|
|
55
|
+
("function", quote::quote! { fn a_function() {} }),
|
|
56
|
+
("macro invocation", quote::quote! { some_macro!(); }),
|
|
57
|
+
("const item", quote::quote! { const A_CONST: u32 = 1; }),
|
|
58
|
+
("static item", quote::quote! { static A_STATIC: u32 = 1; }),
|
|
59
|
+
("use item", quote::quote! { use core::mem; }),
|
|
60
|
+
("mod item", quote::quote! { mod a_module {} }),
|
|
61
|
+
("extern crate", quote::quote! { extern crate core; }),
|
|
62
|
+
(
|
|
63
|
+
"union",
|
|
64
|
+
quote::quote! {
|
|
65
|
+
union AUnion {
|
|
66
|
+
a: u32,
|
|
67
|
+
b: u32,
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
),
|
|
71
|
+
(
|
|
72
|
+
"impl block",
|
|
73
|
+
quote::quote! {
|
|
74
|
+
impl SomeType {
|
|
75
|
+
fn method(&self) {}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
),
|
|
79
|
+
(
|
|
80
|
+
"trait",
|
|
81
|
+
quote::quote! {
|
|
82
|
+
trait ATrait {
|
|
83
|
+
fn method(&self);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
),
|
|
87
|
+
("type alias", quote::quote! { type AnAlias = u32; }),
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
fn filter_item_inputs_excluding_labels(excluded: &[&str]) -> Vec<(&'static str, proc_macro2::TokenStream)> {
|
|
92
|
+
item_inputs().into_iter().filter(|(label, _)| !excluded.iter().any(|x| x == label)).collect()
|
|
93
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
use quote::quote;
|
|
2
|
+
|
|
3
|
+
use crate::tests::test_helpers::{assert_panics_contains, non_struct_item_inputs};
|
|
4
|
+
|
|
5
|
+
// ============================================
|
|
6
|
+
// Snapshot Test: TtlConfigurable Code Generation
|
|
7
|
+
// ============================================
|
|
8
|
+
|
|
9
|
+
#[test]
|
|
10
|
+
fn snapshot_generated_ttl_configurable_code() {
|
|
11
|
+
// Test with a public unit struct
|
|
12
|
+
let input = quote! {
|
|
13
|
+
pub struct MyContract {
|
|
14
|
+
some_field: u32,
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
let result = crate::ttl_configurable::generate_ttl_configurable_impl(input);
|
|
18
|
+
let formatted = prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"));
|
|
19
|
+
|
|
20
|
+
insta::assert_snapshot!(formatted);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ============================================
|
|
24
|
+
// Error Cases: Non-Struct Input
|
|
25
|
+
// ============================================
|
|
26
|
+
|
|
27
|
+
#[test]
|
|
28
|
+
fn test_ttl_configurable_rejects_non_struct_inputs() {
|
|
29
|
+
for (case, input) in non_struct_item_inputs() {
|
|
30
|
+
assert_panics_contains(case, "failed to parse struct", || {
|
|
31
|
+
crate::ttl_configurable::generate_ttl_configurable_impl(input.clone());
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|