Skip to content

Commit 6feefbc

Browse files
BigtoCchipshort
authored andcommitted
feat(metadata): Add test
1 parent ad98e4b commit 6feefbc

File tree

4 files changed

+269
-1
lines changed

4 files changed

+269
-1
lines changed

contracts/cyberpunk/Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contracts/cyberpunk/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ cosmwasm-std = { path = "../../packages/std", default-features = false, features
2828
] }
2929
rust-argon2 = "2.1"
3030
thiserror = "1.0.26"
31+
serde_json = "1.0.117"
3132

3233
[dev-dependencies]
3334
cosmwasm-vm = { path = "../../packages/vm", default-features = false }

contracts/cyberpunk/src/contract.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ mod tests {
225225
message_info, mock_dependencies, mock_env, MockApi, MockQuerier, MockStorage,
226226
};
227227
use cosmwasm_std::{from_json, DenomMetadata, DenomUnit, OwnedDeps};
228+
use serde_json::{json, Error};
228229

229230
fn setup() -> OwnedDeps<MockStorage, MockApi, MockQuerier> {
230231
let mut deps = mock_dependencies();
@@ -292,4 +293,161 @@ mod tests {
292293

293294
assert_eq!(denom.symbol, "FOO0");
294295
}
296+
297+
#[test]
298+
fn query_denom_metadata_with_null_denom_units_works() {
299+
// Test case with null denom_units - should deserialize as empty vec
300+
let json_with_null_denom_units = json!({
301+
"description": "Test Token",
302+
"denom_units": null,
303+
"base": "utest",
304+
"display": "TEST",
305+
"name": "Test Token",
306+
"symbol": "TEST",
307+
"uri": "https://test.com",
308+
"uri_hash": "hash"
309+
});
310+
311+
let metadata_with_null_denom_units: DenomMetadata =
312+
serde_json::from_value(json_with_null_denom_units).unwrap();
313+
assert_eq!(
314+
metadata_with_null_denom_units.denom_units,
315+
Vec::<DenomUnit>::default()
316+
);
317+
assert!(metadata_with_null_denom_units.denom_units.is_empty());
318+
319+
// Test normal case with provided denom_units
320+
let json_with_units = json!({
321+
"description": "Test Token",
322+
"denom_units": [
323+
{
324+
"denom": "utest",
325+
"exponent": 6,
326+
"aliases": ["microtest"]
327+
}
328+
],
329+
"base": "utest",
330+
"display": "TEST",
331+
"name": "Test Token",
332+
"symbol": "TEST",
333+
"uri": "https://test.com",
334+
"uri_hash": "hash"
335+
});
336+
337+
let metadata_with_units: DenomMetadata = serde_json::from_value(json_with_units).unwrap();
338+
assert_eq!(metadata_with_units.denom_units.len(), 1);
339+
assert_eq!(metadata_with_units.denom_units[0].denom, "utest");
340+
assert_eq!(metadata_with_units.denom_units[0].aliases.len(), 1);
341+
assert_eq!(metadata_with_units.denom_units[0].aliases[0], "microtest");
342+
343+
// Test with null aliases inside denom_units - should deserialize as empty vec
344+
let json_with_null_aliases = json!({
345+
"description": "Test Token",
346+
"denom_units": [
347+
{
348+
"denom": "utest",
349+
"exponent": 6,
350+
"aliases": null
351+
}
352+
],
353+
"base": "utest",
354+
"display": "TEST",
355+
"name": "Test Token",
356+
"symbol": "TEST",
357+
"uri": "https://test.com",
358+
"uri_hash": "hash"
359+
});
360+
361+
let metadata_with_null_aliases: DenomMetadata =
362+
serde_json::from_value(json_with_null_aliases).unwrap();
363+
assert_eq!(metadata_with_null_aliases.denom_units.len(), 1);
364+
assert_eq!(
365+
metadata_with_null_aliases.denom_units[0].aliases,
366+
Vec::<String>::default()
367+
);
368+
assert!(metadata_with_null_aliases.denom_units[0].aliases.is_empty());
369+
}
370+
371+
#[test]
372+
fn query_denom_metadata_with_missing_fields_fails() {
373+
// Missing denom_units should be treated as default value (empty vec)
374+
let json_missing_denom_units = json!({
375+
"description": "Test Token",
376+
"base": "utest",
377+
"display": "TEST",
378+
"name": "Test Token",
379+
"symbol": "TEST",
380+
"uri": "https://test.com",
381+
"uri_hash": "hash"
382+
});
383+
384+
let json_missing_denom_units_metadata: Result<DenomMetadata, Error> =
385+
serde_json::from_value(json_missing_denom_units);
386+
assert!(json_missing_denom_units_metadata.is_err());
387+
388+
// Missing aliases field should be treated as default (empty vec)
389+
let json_missing_aliases = json!({
390+
"description": "Test Token",
391+
"denom_units": [
392+
{
393+
"denom": "utest",
394+
"exponent": 6
395+
}
396+
],
397+
"base": "utest",
398+
"display": "TEST",
399+
"name": "Test Token",
400+
"symbol": "TEST",
401+
"uri": "https://test.com",
402+
"uri_hash": "hash"
403+
});
404+
405+
let missing_aliases_metadata: Result<DenomMetadata, Error> =
406+
serde_json::from_value(json_missing_aliases);
407+
assert!(missing_aliases_metadata.is_err());
408+
}
409+
410+
#[test]
411+
fn query_denom_metadata_with_mixed_null_and_value_works() {
412+
// Test with multiple denom units, some with null aliases and some with values
413+
let mixed_json = json!({
414+
"description": "Mixed Token",
415+
"denom_units": [
416+
{
417+
"denom": "unit1",
418+
"exponent": 0,
419+
"aliases": null
420+
},
421+
{
422+
"denom": "unit2",
423+
"exponent": 6,
424+
"aliases": ["microunit", "u"]
425+
},
426+
{
427+
"denom": "unit3",
428+
"exponent": 9,
429+
"aliases": []
430+
}
431+
],
432+
"base": "unit1",
433+
"display": "MIXED",
434+
"name": "Mixed Token",
435+
"symbol": "MIX",
436+
"uri": "https://mixed.token",
437+
"uri_hash": "hash123"
438+
});
439+
440+
let metadata: DenomMetadata = serde_json::from_value(mixed_json).unwrap();
441+
442+
// First denom unit has null aliases, should be empty vec
443+
assert!(metadata.denom_units[0].aliases.is_empty());
444+
445+
// Second has two aliases
446+
assert_eq!(metadata.denom_units[1].aliases.len(), 2);
447+
assert_eq!(metadata.denom_units[1].aliases[0], "microunit");
448+
assert_eq!(metadata.denom_units[1].aliases[1], "u");
449+
450+
// Third has explicitly empty aliases
451+
assert!(metadata.denom_units[2].aliases.is_empty());
452+
}
295453
}

packages/std/src/metadata.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ pub struct DenomUnit {
2626
pub aliases: Vec<String>,
2727
}
2828

29+
// Deserialize a field that is null, defaulting to the type's default value.
30+
// Panic if the field is missing.
2931
fn deserialize_null_default<'de, D, T>(deserializer: D) -> Result<T, D::Error>
3032
where
3133
T: Default + Deserialize<'de>,
@@ -34,3 +36,109 @@ where
3436
let opt = Option::deserialize(deserializer)?;
3537
Ok(opt.unwrap_or_default())
3638
}
39+
40+
#[cfg(test)]
41+
mod tests {
42+
use super::*;
43+
use serde_json::{json, Error};
44+
45+
#[test]
46+
fn deserialize_denom_metadata_with_null_fields_works() {
47+
// Test case with null denom_units - should deserialize as empty vec
48+
let json_with_null_denom_units = json!({
49+
"description": "Test Token",
50+
"denom_units": null,
51+
"base": "utest",
52+
"display": "TEST",
53+
"name": "Test Token",
54+
"symbol": "TEST",
55+
"uri": "https://test.com",
56+
"uri_hash": "hash"
57+
});
58+
59+
let metadata_null_denom_units: DenomMetadata = serde_json::from_value(json_with_null_denom_units).unwrap();
60+
assert_eq!(metadata_null_denom_units.denom_units, Vec::<DenomUnit>::default());
61+
assert!(metadata_null_denom_units.denom_units.is_empty());
62+
63+
// Test normal case with provided denom_units
64+
let json_with_units = json!({
65+
"description": "Test Token",
66+
"denom_units": [
67+
{
68+
"denom": "utest",
69+
"exponent": 6,
70+
"aliases": ["microtest"]
71+
}
72+
],
73+
"base": "utest",
74+
"display": "TEST",
75+
"name": "Test Token",
76+
"symbol": "TEST",
77+
"uri": "https://test.com",
78+
"uri_hash": "hash"
79+
});
80+
81+
let metadata_with_units: DenomMetadata = serde_json::from_value(json_with_units).unwrap();
82+
assert_eq!(metadata_with_units.denom_units.len(), 1);
83+
assert_eq!(metadata_with_units.denom_units[0].denom, "utest");
84+
85+
// Test with null aliases inside denom_units - should deserialize as empty vec
86+
let json_with_null_aliases = json!({
87+
"description": "Test Token",
88+
"denom_units": [
89+
{
90+
"denom": "utest",
91+
"exponent": 6,
92+
"aliases": null
93+
}
94+
],
95+
"base": "utest",
96+
"display": "TEST",
97+
"name": "Test Token",
98+
"symbol": "TEST",
99+
"uri": "https://test.com",
100+
"uri_hash": "hash"
101+
});
102+
103+
let metadata_with_null_aliases: DenomMetadata = serde_json::from_value(json_with_null_aliases).unwrap();
104+
assert_eq!(metadata_with_null_aliases.denom_units.len(), 1);
105+
assert_eq!(metadata_with_null_aliases.denom_units[0].aliases, Vec::<String>::default());
106+
assert!(metadata_with_null_aliases.denom_units[0].aliases.is_empty());
107+
}
108+
109+
#[test]
110+
fn deserialize_denom_metadata_with_missing_fields_fails() {
111+
// Missing denom_units should be treated like null
112+
let json_missing_denom_units = json!({
113+
"description": "Test Token",
114+
"base": "utest",
115+
"display": "TEST",
116+
"name": "Test Token",
117+
"symbol": "TEST",
118+
"uri": "https://test.com",
119+
"uri_hash": "hash"
120+
});
121+
122+
let metadata: Result<DenomMetadata, Error> = serde_json::from_value(json_missing_denom_units);
123+
assert!(metadata.is_err());
124+
125+
let json_missing_alias = json!({
126+
"description": "Test Token",
127+
"base": "utest",
128+
"denom_units": [
129+
{
130+
"denom": "utest",
131+
"exponent": 6,
132+
}
133+
],
134+
"display": "TEST",
135+
"name": "Test Token",
136+
"symbol": "TEST",
137+
"uri": "https://test.com",
138+
"uri_hash": "hash"
139+
});
140+
141+
let metadata_missing_alias: Result<DenomMetadata, Error> = serde_json::from_value(json_missing_alias);
142+
assert!(metadata_missing_alias.is_err());
143+
}
144+
}

0 commit comments

Comments
 (0)