Skip to content

Commit dd1ba28

Browse files
Adapt unit tests
1 parent cf4cb1e commit dd1ba28

3 files changed

Lines changed: 363 additions & 0 deletions

File tree

tests/unit/CMakeLists.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,48 @@ target_link_libraries(test_param_trusted_name PUBLIC
169169
gcov
170170
${LIBBSD_LIBRARIES}
171171
-Wl,--wrap=get_trusted_name
172+
-Wl,--wrap=get_address_display_name
172173
-Wl,--wrap=get_public_key
173174
-Wl,--wrap=get_current_tx_chain_id
174175
-Wl,--wrap=add_to_field_table
175176
)
176177

177178
add_test(test_param_trusted_name test_param_trusted_name)
178179

180+
# Address name lookup test (get_address_display_name: Address Book→Trusted Name→RAW resolution + conflict detection)
181+
add_executable(test_address_name_lookup
182+
${SRC_DIR}/test_address_name_lookup.c
183+
${APP_DIR}/address_name_lookup.c
184+
${PLUGIN_DIR}/common_utils.c
185+
${MOCK_DIR}/mock.c
186+
${BOLOS_SDK}/lib_standard_app/format.c
187+
${BOLOS_SDK}/lib_standard_app/read.c
188+
)
189+
190+
target_include_directories(test_address_name_lookup PRIVATE
191+
${APP_DIR}/features/address_book
192+
${BOLOS_SDK}/address_book/include
193+
)
194+
195+
target_compile_definitions(test_address_name_lookup PRIVATE
196+
HAVE_ADDRESS_BOOK
197+
HAVE_ECDSA
198+
HAVE_HASH
199+
HAVE_SHA256
200+
HAVE_SHA3
201+
HAVE_ECC
202+
)
203+
204+
target_link_libraries(test_address_name_lookup PUBLIC
205+
cmocka
206+
gcov
207+
${LIBBSD_LIBRARIES}
208+
-Wl,--wrap=get_trusted_name
209+
-Wl,--wrap=get_address_book_contact
210+
)
211+
212+
add_test(test_address_name_lookup test_address_name_lookup)
213+
179214
# Raw parameter test
180215
add_executable(test_param_raw
181216
${SRC_DIR}/test_param_raw.c
Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
/**
2+
* @file test_address_name_lookup.c
3+
* @brief Unit tests for get_address_display_name (Address Book→Trusted Name→RAW resolution)
4+
*/
5+
6+
#include <stdarg.h>
7+
#include <stddef.h>
8+
#include <setjmp.h>
9+
#include <cmocka.h>
10+
#include <string.h>
11+
#include <stdint.h>
12+
#include <stdbool.h>
13+
14+
#include "address_name_lookup.h"
15+
#include "handle_provide_contact.h"
16+
#include "shared_context.h"
17+
18+
#include "os.h"
19+
20+
strings_t strings;
21+
22+
static chain_config_t chainConfig_storage = {.ticker = "ETH", .chain_id = 1, .coin_type = 60};
23+
const chain_config_t *g_chain_config = &chainConfig_storage;
24+
25+
// =============================================================================
26+
// Controllable mocks
27+
// =============================================================================
28+
29+
const s_trusted_name *__wrap_get_trusted_name(uint8_t type_count,
30+
const e_name_type *types,
31+
uint8_t source_count,
32+
const e_name_source *sources,
33+
const uint64_t *chain_id,
34+
const uint8_t *addr) {
35+
(void) type_count;
36+
(void) types;
37+
(void) source_count;
38+
(void) sources;
39+
(void) chain_id;
40+
(void) addr;
41+
return (const s_trusted_name *) mock();
42+
}
43+
44+
const s_ab_contact *__wrap_get_address_book_contact(uint64_t chain_id, const uint8_t *addr) {
45+
(void) chain_id;
46+
(void) addr;
47+
return (const s_ab_contact *) mock();
48+
}
49+
50+
// =============================================================================
51+
// Test helpers
52+
// =============================================================================
53+
54+
// clang-format off
55+
static const uint8_t TEST_ADDR[ADDRESS_LENGTH] = {
56+
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00,
57+
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22, 0x33, 0x44
58+
};
59+
// clang-format on
60+
61+
static const e_name_type TYPES_ACCOUNT[] = {TN_TYPE_ACCOUNT};
62+
static const e_name_source SOURCES_ENS[] = {TN_SOURCE_ENS};
63+
static const uint64_t CHAIN_ID = 1;
64+
65+
// =============================================================================
66+
// Test cases
67+
// =============================================================================
68+
69+
/**
70+
* Both Address Book and Trusted Name exist for the same address → Address Book wins, rendering
71+
* handles Trusted Name separately
72+
*/
73+
static void test_conflict_ab_and_tn(void **state) {
74+
(void) state;
75+
76+
static s_ab_contact ab = {.contact_name = "Alice"};
77+
static s_trusted_name tn = {.name = "alice.eth"};
78+
char buf[64];
79+
e_addr_name_source name_source;
80+
const void *extra_data = NULL;
81+
82+
will_return(__wrap_get_trusted_name, &tn);
83+
will_return(__wrap_get_address_book_contact, &ab);
84+
85+
assert_true(get_address_display_name(TEST_ADDR,
86+
CHAIN_ID,
87+
1,
88+
TYPES_ACCOUNT,
89+
1,
90+
SOURCES_ENS,
91+
buf,
92+
sizeof(buf),
93+
&name_source,
94+
&extra_data));
95+
96+
assert_int_equal(name_source, ADDR_NAME_FROM_ADDRESS_BOOK);
97+
assert_string_equal(buf, "Alice");
98+
assert_ptr_equal(extra_data, &ab);
99+
}
100+
101+
/**
102+
* Address Book contact found, no Trusted Name → ADDR_NAME_FROM_ADDRESS_BOOK, contact name in buf
103+
*/
104+
static void test_ab_only(void **state) {
105+
(void) state;
106+
107+
static s_ab_contact ab = {.contact_name = "Alice"};
108+
char buf[64];
109+
e_addr_name_source name_source;
110+
const void *extra_data = NULL;
111+
112+
will_return(__wrap_get_trusted_name, NULL);
113+
will_return(__wrap_get_address_book_contact, &ab);
114+
115+
assert_true(get_address_display_name(TEST_ADDR,
116+
CHAIN_ID,
117+
1,
118+
TYPES_ACCOUNT,
119+
1,
120+
SOURCES_ENS,
121+
buf,
122+
sizeof(buf),
123+
&name_source,
124+
&extra_data));
125+
126+
assert_int_equal(name_source, ADDR_NAME_FROM_ADDRESS_BOOK);
127+
assert_string_equal(buf, "Alice");
128+
assert_ptr_equal(extra_data, &ab);
129+
}
130+
131+
/**
132+
* No Address Book contact, Trusted Name found → ADDR_NAME_FROM_TRUSTED_NAME, tn name in buf
133+
*/
134+
static void test_tn_only(void **state) {
135+
(void) state;
136+
137+
static s_trusted_name tn = {.name = "alice.eth"};
138+
char buf[64];
139+
e_addr_name_source name_source;
140+
const void *extra_data = NULL;
141+
142+
will_return(__wrap_get_trusted_name, &tn);
143+
will_return(__wrap_get_address_book_contact, NULL);
144+
145+
assert_true(get_address_display_name(TEST_ADDR,
146+
CHAIN_ID,
147+
1,
148+
TYPES_ACCOUNT,
149+
1,
150+
SOURCES_ENS,
151+
buf,
152+
sizeof(buf),
153+
&name_source,
154+
&extra_data));
155+
156+
assert_int_equal(name_source, ADDR_NAME_FROM_TRUSTED_NAME);
157+
assert_string_equal(buf, "alice.eth");
158+
assert_ptr_equal(extra_data, &tn);
159+
}
160+
161+
/**
162+
* Neither Address Book nor Trusted Name found → ADDR_NAME_FROM_RAW, formatted address in buf
163+
*/
164+
static void test_raw_fallback(void **state) {
165+
(void) state;
166+
167+
char buf[64];
168+
e_addr_name_source name_source;
169+
170+
will_return(__wrap_get_trusted_name, NULL);
171+
will_return(__wrap_get_address_book_contact, NULL);
172+
173+
assert_true(get_address_display_name(TEST_ADDR,
174+
CHAIN_ID,
175+
1,
176+
TYPES_ACCOUNT,
177+
1,
178+
SOURCES_ENS,
179+
buf,
180+
sizeof(buf),
181+
&name_source,
182+
NULL));
183+
184+
assert_int_equal(name_source, ADDR_NAME_FROM_RAW);
185+
assert_string_equal(buf, "0x11223344556677889900aabbccddeEfF11223344");
186+
}
187+
188+
/**
189+
* TN_TYPE_ACCOUNT not in types → Address Book is not checked; Trusted Name found →
190+
* ADDR_NAME_FROM_TRUSTED_NAME
191+
*/
192+
static void test_non_account_type_skips_ab(void **state) {
193+
(void) state;
194+
195+
static const e_name_type types_contract[] = {TN_TYPE_CONTRACT};
196+
static s_trusted_name tn = {.name = "MyContract"};
197+
char buf[64];
198+
e_addr_name_source name_source;
199+
200+
will_return(__wrap_get_trusted_name, &tn);
201+
// get_address_book_contact must NOT be called (no will_return set for it)
202+
203+
assert_true(get_address_display_name(TEST_ADDR,
204+
CHAIN_ID,
205+
1,
206+
types_contract,
207+
1,
208+
SOURCES_ENS,
209+
buf,
210+
sizeof(buf),
211+
&name_source,
212+
NULL));
213+
214+
assert_int_equal(name_source, ADDR_NAME_FROM_TRUSTED_NAME);
215+
assert_string_equal(buf, "MyContract");
216+
}
217+
218+
/**
219+
* Wrong chain_id (e.g. Polygon 137 instead of Ethereum 1): neither Address Book nor Trusted Name
220+
* resolves the address for a chain the entries were not registered on → RAW
221+
*/
222+
static void test_wrong_chain_id(void **state) {
223+
(void) state;
224+
225+
const uint64_t polygon_chain_id = 137;
226+
char buf[64];
227+
e_addr_name_source name_source;
228+
229+
// In the real implementation, get_trusted_name checks chain_id equality
230+
// and get_address_book_contact checks the contact's chain scope.
231+
// Both return NULL when the chain doesn't match.
232+
will_return(__wrap_get_trusted_name, NULL);
233+
will_return(__wrap_get_address_book_contact, NULL);
234+
235+
assert_true(get_address_display_name(TEST_ADDR,
236+
polygon_chain_id,
237+
1,
238+
TYPES_ACCOUNT,
239+
1,
240+
SOURCES_ENS,
241+
buf,
242+
sizeof(buf),
243+
&name_source,
244+
NULL));
245+
246+
assert_int_equal(name_source, ADDR_NAME_FROM_RAW);
247+
assert_string_equal(buf, "0x11223344556677889900aabbccddeEfF11223344");
248+
}
249+
250+
/**
251+
* Non-Ethereum blockchain family (chain_id=0): chain_is_ethereum_compatible
252+
* returns false inside get_trusted_name, so neither Address Book nor Trusted Name resolves → RAW
253+
*/
254+
static void test_non_ethereum_chain(void **state) {
255+
(void) state;
256+
257+
const uint64_t non_eth_chain_id = 0;
258+
char buf[64];
259+
e_addr_name_source name_source;
260+
261+
// In the real implementation, get_trusted_name rejects non-Ethereum-compatible
262+
// chains (chain_is_ethereum_compatible == false) and returns NULL.
263+
will_return(__wrap_get_trusted_name, NULL);
264+
will_return(__wrap_get_address_book_contact, NULL);
265+
266+
assert_true(get_address_display_name(TEST_ADDR,
267+
non_eth_chain_id,
268+
1,
269+
TYPES_ACCOUNT,
270+
1,
271+
SOURCES_ENS,
272+
buf,
273+
sizeof(buf),
274+
&name_source,
275+
NULL));
276+
277+
assert_int_equal(name_source, ADDR_NAME_FROM_RAW);
278+
assert_string_equal(buf, "0x11223344556677889900aabbccddeEfF11223344");
279+
}
280+
281+
// =============================================================================
282+
// Test runner
283+
// =============================================================================
284+
285+
int main(void) {
286+
const struct CMUnitTest tests[] = {
287+
cmocka_unit_test(test_conflict_ab_and_tn),
288+
cmocka_unit_test(test_ab_only),
289+
cmocka_unit_test(test_tn_only),
290+
cmocka_unit_test(test_raw_fallback),
291+
cmocka_unit_test(test_non_account_type_skips_ab),
292+
cmocka_unit_test(test_wrong_chain_id),
293+
cmocka_unit_test(test_non_ethereum_chain),
294+
};
295+
296+
return cmocka_run_group_tests(tests, NULL, NULL);
297+
}

tests/unit/src/test_param_trusted_name.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
// Headers for mocked functions
2424
#include "trusted_name.h"
25+
#include "address_name_lookup.h"
2526
#include "utils.h"
2627
#include "get_public_key.h"
2728
#include "tx_ctx.h"
@@ -88,6 +89,36 @@ const s_trusted_name *__wrap_get_trusted_name(uint8_t type_count,
8889
return (const s_trusted_name *) mock();
8990
}
9091

92+
/**
93+
* @brief Mock implementation of get_address_display_name
94+
*
95+
* Delegates to the existing get_trusted_name mock so that the 8 existing tests
96+
* that set expectations on __wrap_get_trusted_name continue to work unchanged.
97+
*/
98+
bool __wrap_get_address_display_name(const uint8_t *addr,
99+
uint64_t chain_id,
100+
uint8_t type_count,
101+
const e_name_type *types,
102+
uint8_t source_count,
103+
const e_name_source *sources,
104+
char *buf,
105+
size_t buf_size,
106+
e_addr_name_source *name_source_out,
107+
const void **extra_data_out) {
108+
const s_trusted_name *tname =
109+
__wrap_get_trusted_name(type_count, types, source_count, sources, &chain_id, addr);
110+
if (tname != NULL) {
111+
strlcpy(buf, tname->name, buf_size);
112+
if (name_source_out != NULL) *name_source_out = ADDR_NAME_FROM_TRUSTED_NAME;
113+
if (extra_data_out != NULL) *extra_data_out = tname;
114+
} else {
115+
getEthDisplayableAddress(addr, buf, buf_size, chain_id);
116+
if (name_source_out != NULL) *name_source_out = ADDR_NAME_FROM_RAW;
117+
if (extra_data_out != NULL) *extra_data_out = NULL;
118+
}
119+
return true;
120+
}
121+
91122
/**
92123
* @brief Mock implementation of get_public_key
93124
*/

0 commit comments

Comments
 (0)