@layerzerolabs/common-utils-macros-stellar-contracts 0.2.122
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/Cargo.toml +21 -0
- package/LICENSE +23 -0
- package/clippy.toml +7 -0
- package/package.json +37 -0
- package/rust-toolchain.toml +4 -0
- package/rustfmt.toml +15 -0
- package/src/auth.rs +95 -0
- package/src/contract_ttl.rs +92 -0
- package/src/error.rs +43 -0
- package/src/lib.rs +585 -0
- package/src/lz_contract.rs +105 -0
- package/src/rbac.rs +90 -0
- package/src/storage.rs +522 -0
- package/src/tests/auth.rs +230 -0
- package/src/tests/contract_ttl.rs +695 -0
- package/src/tests/error.rs +156 -0
- package/src/tests/lz_contract.rs +87 -0
- package/src/tests/mod.rs +11 -0
- package/src/tests/rbac.rs +523 -0
- package/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_multisig_code.snap +31 -0
- package/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_ownable_code.snap +39 -0
- package/src/tests/snapshots/common_macros__tests__auth__snapshot_only_auth_preserves_function_signature.snap +19 -0
- package/src/tests/snapshots/common_macros__tests__contract_ttl__snapshot_generated_contractimpl_code.snap +77 -0
- package/src/tests/snapshots/common_macros__tests__contract_ttl__snapshot_generated_contracttrait_code.snap +46 -0
- package/src/tests/snapshots/common_macros__tests__error__snapshot_generated_contract_error_code.snap +20 -0
- package/src/tests/snapshots/common_macros__tests__lz_contract__snapshot_generated_lz_contract_code.snap +51 -0
- package/src/tests/snapshots/common_macros__tests__rbac__snapshot_authorizer_role.snap +21 -0
- package/src/tests/snapshots/common_macros__tests__rbac__snapshot_preserve_function_signature.snap +21 -0
- package/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +10 -0
- package/src/tests/snapshots/common_macros__tests__ttl_extendable__snapshot_generated_ttl_extendable_code.snap +8 -0
- package/src/tests/snapshots/common_macros__tests__upgradeable__snapshot_generated_upgradeable_code.snap +28 -0
- package/src/tests/storage/extract_fields.rs +87 -0
- package/src/tests/storage/gen_accessor_methods.rs +223 -0
- package/src/tests/storage/gen_args.rs +65 -0
- package/src/tests/storage/gen_enum_variant.rs +78 -0
- package/src/tests/storage/gen_key.rs +108 -0
- package/src/tests/storage/gen_params.rs +105 -0
- package/src/tests/storage/generate_storage.rs +410 -0
- package/src/tests/storage/is_primitive_type.rs +48 -0
- package/src/tests/storage/mod.rs +16 -0
- package/src/tests/storage/parse_default.rs +164 -0
- package/src/tests/storage/parse_name.rs +158 -0
- package/src/tests/storage/parse_no_ttl_extension.rs +124 -0
- package/src/tests/storage/parse_storage_type.rs +174 -0
- package/src/tests/storage/snapshots/common_macros__tests__storage__generate_storage__snapshot_generated_storage_code.snap +412 -0
- package/src/tests/storage/storage_kind.rs +39 -0
- package/src/tests/storage/test_setup.rs +25 -0
- package/src/tests/storage/validate_attrs.rs +138 -0
- package/src/tests/storage/variant_config.rs +226 -0
- package/src/tests/test_helpers.rs +87 -0
- package/src/tests/ttl_configurable.rs +34 -0
- package/src/tests/ttl_extendable.rs +32 -0
- package/src/tests/upgradeable.rs +169 -0
- package/src/tests/utils.rs +267 -0
- package/src/ttl_configurable.rs +24 -0
- package/src/ttl_extendable.rs +28 -0
- package/src/upgradeable.rs +136 -0
- package/src/utils.rs +56 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
use quote::quote;
|
|
2
|
+
|
|
3
|
+
use crate::tests::test_helpers::{assert_panics_contains, filter_item_inputs_excluding_labels};
|
|
4
|
+
|
|
5
|
+
// ============================================
|
|
6
|
+
// Error Cases: Invalid Inputs
|
|
7
|
+
// ============================================
|
|
8
|
+
|
|
9
|
+
#[test]
|
|
10
|
+
fn test_contract_error_rejects_non_enum_inputs() {
|
|
11
|
+
for (case, input) in filter_item_inputs_excluding_labels(&["enum"]) {
|
|
12
|
+
assert_panics_contains(case, "failed to parse enum", || {
|
|
13
|
+
crate::error::generate_error(input.clone());
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
#[test]
|
|
19
|
+
fn test_contract_error_requires_unit_variants() {
|
|
20
|
+
let cases = vec![("tuple variant", quote! { A(u32) }), ("struct variant", quote! { A { x: u32 } })];
|
|
21
|
+
|
|
22
|
+
for (case, variant) in cases {
|
|
23
|
+
let input = quote! {
|
|
24
|
+
pub enum MyError {
|
|
25
|
+
#variant,
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
assert_panics_contains(case, "Error enum variants must be unit variants", || {
|
|
29
|
+
crate::error::generate_error(input.clone());
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
#[test]
|
|
35
|
+
fn test_contract_error_discriminant_must_be_integer_literal() {
|
|
36
|
+
let cases = vec![
|
|
37
|
+
("binary expr", quote! { 1 + 1 }),
|
|
38
|
+
("path expr", quote! { SOME_CONST }),
|
|
39
|
+
("negative integer (unary expr)", quote! { -1 }),
|
|
40
|
+
("paren expr", quote! { (1) }),
|
|
41
|
+
("bool literal", quote! { true }),
|
|
42
|
+
("string literal", quote! { "1" }),
|
|
43
|
+
("float literal", quote! { 1.0 }),
|
|
44
|
+
("char literal", quote! { 'a' }),
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
for (case, expr) in cases {
|
|
48
|
+
let input = quote! {
|
|
49
|
+
pub enum MyError {
|
|
50
|
+
A = #expr,
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
assert_panics_contains(case, "Error enum discriminant must be an integer literal", || {
|
|
54
|
+
crate::error::generate_error(input.clone());
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
#[test]
|
|
60
|
+
fn test_contract_error_discriminant_must_fit_u32() {
|
|
61
|
+
let input = quote! {
|
|
62
|
+
pub enum MyError {
|
|
63
|
+
A = 4294967296,
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
assert_panics_contains("u32::MAX + 1", "Error enum discriminant must be a valid u32 integer", || {
|
|
68
|
+
crate::error::generate_error(input);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
#[test]
|
|
73
|
+
fn test_contract_error_discriminants_ordering_rejections_table_driven() {
|
|
74
|
+
let cases = vec![
|
|
75
|
+
(
|
|
76
|
+
"explicit value is less than previous",
|
|
77
|
+
quote! {
|
|
78
|
+
// A is assigned 1 by default; B cannot go backwards.
|
|
79
|
+
A,
|
|
80
|
+
B = 1,
|
|
81
|
+
},
|
|
82
|
+
),
|
|
83
|
+
(
|
|
84
|
+
"explicit zero",
|
|
85
|
+
quote! {
|
|
86
|
+
A = 0,
|
|
87
|
+
},
|
|
88
|
+
),
|
|
89
|
+
(
|
|
90
|
+
"explicit equal to previous explicit",
|
|
91
|
+
quote! {
|
|
92
|
+
A = 1,
|
|
93
|
+
B = 1,
|
|
94
|
+
},
|
|
95
|
+
),
|
|
96
|
+
(
|
|
97
|
+
"explicit decreases after explicit",
|
|
98
|
+
quote! {
|
|
99
|
+
A = 5,
|
|
100
|
+
B = 4,
|
|
101
|
+
},
|
|
102
|
+
),
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
for (case, variants) in cases {
|
|
106
|
+
let input = quote! {
|
|
107
|
+
pub enum MyError {
|
|
108
|
+
#variants
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
assert_panics_contains(case, "Error enum discriminant must be greater than the previous discriminant", || {
|
|
112
|
+
crate::error::generate_error(input.clone());
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
#[test]
|
|
118
|
+
fn test_contract_error_max_not_last_panics_overflow() {
|
|
119
|
+
let input = quote! {
|
|
120
|
+
pub enum MyError {
|
|
121
|
+
A = 4294967295,
|
|
122
|
+
B,
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
assert_panics_contains("max not last overflows", "attempt to add with overflow", || {
|
|
126
|
+
crate::error::generate_error(input);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ============================================
|
|
131
|
+
// Valid Cases: Snapshot Tests for Generated Code
|
|
132
|
+
// ============================================
|
|
133
|
+
|
|
134
|
+
#[test]
|
|
135
|
+
fn snapshot_generated_contract_error_code() {
|
|
136
|
+
let input = quote! {
|
|
137
|
+
/// Example error enum
|
|
138
|
+
pub enum MyError {
|
|
139
|
+
/// Implicit (should start at 1)
|
|
140
|
+
A,
|
|
141
|
+
/// Implicit (should be 2)
|
|
142
|
+
B,
|
|
143
|
+
/// Explicit (must be >= previous + 1)
|
|
144
|
+
C = 10,
|
|
145
|
+
/// Implicit (should be 11)
|
|
146
|
+
D,
|
|
147
|
+
/// Explicit max boundary (u32::MAX)
|
|
148
|
+
E = 4294967295,
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
let result = crate::error::generate_error(input);
|
|
153
|
+
let formatted = prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"));
|
|
154
|
+
|
|
155
|
+
insta::assert_snapshot!(formatted);
|
|
156
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
use proc_macro2::TokenStream;
|
|
2
|
+
use quote::quote;
|
|
3
|
+
|
|
4
|
+
use crate::tests::test_helpers::{assert_panics_contains, filter_item_inputs_excluding_labels};
|
|
5
|
+
|
|
6
|
+
// ============================================
|
|
7
|
+
// Snapshot Tests: lz_contract Code Generation
|
|
8
|
+
// ============================================
|
|
9
|
+
|
|
10
|
+
#[test]
|
|
11
|
+
fn snapshot_generated_lz_contract_code() {
|
|
12
|
+
let input = quote! {
|
|
13
|
+
pub struct MyContract;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
let default_result = crate::lz_contract::generate_lz_contract(TokenStream::new(), input.clone());
|
|
17
|
+
let default_formatted =
|
|
18
|
+
prettyplease::unparse(&syn::parse2::<syn::File>(default_result).expect("failed to parse generated code"));
|
|
19
|
+
|
|
20
|
+
let multisig_upgradeable_result = crate::lz_contract::generate_lz_contract(quote! { multisig, upgradeable }, input);
|
|
21
|
+
let multisig_upgradeable_formatted = prettyplease::unparse(
|
|
22
|
+
&syn::parse2::<syn::File>(multisig_upgradeable_result).expect("failed to parse generated code"),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
let upgradeable_no_migration_result = crate::lz_contract::generate_lz_contract(
|
|
26
|
+
quote! { upgradeable(no_migration) },
|
|
27
|
+
quote! { pub struct MyContract; },
|
|
28
|
+
);
|
|
29
|
+
let upgradeable_no_migration_formatted = prettyplease::unparse(
|
|
30
|
+
&syn::parse2::<syn::File>(upgradeable_no_migration_result).expect("failed to parse generated code"),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
let upgradeable_rbac_result =
|
|
34
|
+
crate::lz_contract::generate_lz_contract(quote! { upgradeable(rbac) }, quote! { pub struct MyContract; });
|
|
35
|
+
let upgradeable_rbac_formatted = prettyplease::unparse(
|
|
36
|
+
&syn::parse2::<syn::File>(upgradeable_rbac_result).expect("failed to parse generated code"),
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// Pass-through: order and content preserved verbatim
|
|
40
|
+
let upgradeable_rbac_no_migration_result = crate::lz_contract::generate_lz_contract(
|
|
41
|
+
quote! { upgradeable(rbac, no_migration) },
|
|
42
|
+
quote! { pub struct MyContract; },
|
|
43
|
+
);
|
|
44
|
+
let upgradeable_rbac_no_migration_formatted = prettyplease::unparse(
|
|
45
|
+
&syn::parse2::<syn::File>(upgradeable_rbac_no_migration_result).expect("failed to parse generated code"),
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
let combined = format!(
|
|
49
|
+
"// === Default (ownable) ===\n\n{}\n\n// === MultiSig + Upgradeable ===\n\n{}\n\n// === Upgradeable (no_migration) ===\n\n{}\n\n// === Upgradeable (rbac) ===\n\n{}\n\n// === Upgradeable (rbac, no_migration) pass-through ===\n\n{}",
|
|
50
|
+
default_formatted, multisig_upgradeable_formatted, upgradeable_no_migration_formatted, upgradeable_rbac_formatted, upgradeable_rbac_no_migration_formatted
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
insta::assert_snapshot!(combined);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ============================================
|
|
57
|
+
// Error Cases: Invalid Config
|
|
58
|
+
// ============================================
|
|
59
|
+
|
|
60
|
+
#[test]
|
|
61
|
+
fn test_lz_contract_invalid_config_table_driven() {
|
|
62
|
+
let input = quote! { pub struct MyContract; };
|
|
63
|
+
|
|
64
|
+
let cases: Vec<(&str, TokenStream, &str)> = vec![
|
|
65
|
+
("unknown option", quote! { not_a_real_option }, "expected one of `upgradeable`, `multisig`"),
|
|
66
|
+
("invalid attr syntax", quote! { 123 }, "failed to parse lz_contract config"),
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
for (case, attr, expected_substring) in cases {
|
|
70
|
+
assert_panics_contains(case, expected_substring, || {
|
|
71
|
+
crate::lz_contract::generate_lz_contract(attr.clone(), input.clone());
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ============================================
|
|
77
|
+
// Error Cases: Non-Struct Input
|
|
78
|
+
// ============================================
|
|
79
|
+
|
|
80
|
+
#[test]
|
|
81
|
+
fn test_lz_contract_rejects_non_struct_inputs() {
|
|
82
|
+
for (case, input) in filter_item_inputs_excluding_labels(&["struct"]) {
|
|
83
|
+
assert_panics_contains(case, "failed to parse struct", || {
|
|
84
|
+
crate::lz_contract::generate_lz_contract(TokenStream::new(), input.clone());
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|