1 #include "maxminddb_test_helper.h"
2
test_metadata(MMDB_s * mmdb,const char * mode_desc)3 void test_metadata(MMDB_s *mmdb, const char *mode_desc) {
4 cmp_ok(mmdb->metadata.node_count,
5 "==",
6 37,
7 "node_count is 37 - %s",
8 mode_desc);
9 cmp_ok(mmdb->metadata.record_size,
10 "==",
11 24,
12 "record_size is 24 - %s",
13 mode_desc);
14 cmp_ok(
15 mmdb->metadata.ip_version, "==", 4, "ip_version is 4 - %s", mode_desc);
16 is(mmdb->metadata.database_type,
17 "Test",
18 "database_type is Test - %s",
19 mode_desc);
20 // 2013-07-01T00:00:00Z
21 uint64_t expect_epoch = 1372636800;
22 int is_ok = cmp_ok(mmdb->metadata.build_epoch,
23 ">=",
24 expect_epoch,
25 "build_epoch > %lli",
26 expect_epoch);
27 if (!is_ok) {
28 diag(" epoch is %lli", mmdb->metadata.build_epoch);
29 }
30
31 cmp_ok(mmdb->metadata.binary_format_major_version,
32 "==",
33 2,
34 "binary_format_major_version is 2 - %s",
35 mode_desc);
36 cmp_ok(mmdb->metadata.binary_format_minor_version,
37 "==",
38 0,
39 "binary_format_minor_version is 0 - %s",
40 mode_desc);
41
42 cmp_ok(mmdb->metadata.languages.count,
43 "==",
44 2,
45 "found 2 languages - %s",
46 mode_desc);
47 is(mmdb->metadata.languages.names[0],
48 "en",
49 "first language is en - %s",
50 mode_desc);
51 is(mmdb->metadata.languages.names[1],
52 "zh",
53 "second language is zh - %s",
54 mode_desc);
55
56 cmp_ok(mmdb->metadata.description.count,
57 "==",
58 2,
59 "found 2 descriptions - %s",
60 mode_desc);
61 for (uint16_t i = 0; i < mmdb->metadata.description.count; i++) {
62 const char *language =
63 mmdb->metadata.description.descriptions[i]->language;
64 const char *description =
65 mmdb->metadata.description.descriptions[i]->description;
66 if (strncmp(language, "en", 2) == 0) {
67 ok(1, "found en description");
68 is(description, "Test Database", "en description");
69 } else if (strncmp(language, "zh", 2) == 0) {
70 ok(1, "found zh description");
71 is(description, "Test Database Chinese", "zh description");
72 } else {
73 ok(0,
74 "found unknown description in unexpected language - %s",
75 language);
76 }
77 }
78
79 cmp_ok(mmdb->full_record_byte_size,
80 "==",
81 6,
82 "full_record_byte_size is 6 - %s",
83 mode_desc);
84 }
85
86 MMDB_entry_data_list_s *
test_languages_value(MMDB_entry_data_list_s * entry_data_list)87 test_languages_value(MMDB_entry_data_list_s *entry_data_list) {
88 MMDB_entry_data_list_s *languages = entry_data_list = entry_data_list->next;
89
90 cmp_ok(languages->entry_data.type,
91 "==",
92 MMDB_DATA_TYPE_ARRAY,
93 "'languages' key's value is an array");
94 cmp_ok(languages->entry_data.data_size,
95 "==",
96 2,
97 "'languages' key's value has 2 elements");
98
99 MMDB_entry_data_list_s *idx0 = entry_data_list = entry_data_list->next;
100 cmp_ok(idx0->entry_data.type,
101 "==",
102 MMDB_DATA_TYPE_UTF8_STRING,
103 "first array entry is a UTF8_STRING");
104 const char *lang0 = dup_entry_string_or_bail(idx0->entry_data);
105 is(lang0, "en", "first language is en");
106 free((void *)lang0);
107
108 MMDB_entry_data_list_s *idx1 = entry_data_list = entry_data_list->next;
109 cmp_ok(idx1->entry_data.type,
110 "==",
111 MMDB_DATA_TYPE_UTF8_STRING,
112 "second array entry is a UTF8_STRING");
113 const char *lang1 = dup_entry_string_or_bail(idx1->entry_data);
114 is(lang1, "zh", "second language is zh");
115 free((void *)lang1);
116
117 return entry_data_list;
118 }
119
120 MMDB_entry_data_list_s *
test_description_value(MMDB_entry_data_list_s * entry_data_list)121 test_description_value(MMDB_entry_data_list_s *entry_data_list) {
122 MMDB_entry_data_list_s *description = entry_data_list =
123 entry_data_list->next;
124 cmp_ok(description->entry_data.type,
125 "==",
126 MMDB_DATA_TYPE_MAP,
127 "'description' key's value is a map");
128 cmp_ok(description->entry_data.data_size,
129 "==",
130 2,
131 "'description' key's value has 2 key/value pairs");
132
133 for (int i = 0; i < 2; i++) {
134 MMDB_entry_data_list_s *key = entry_data_list = entry_data_list->next;
135 cmp_ok(key->entry_data.type,
136 "==",
137 MMDB_DATA_TYPE_UTF8_STRING,
138 "found a map key in 'map'");
139 const char *key_name = dup_entry_string_or_bail(key->entry_data);
140
141 MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next;
142 cmp_ok(value->entry_data.type,
143 "==",
144 MMDB_DATA_TYPE_UTF8_STRING,
145 "map value is a UTF8_STRING");
146 const char *description = dup_entry_string_or_bail(value->entry_data);
147
148 if (strcmp(key_name, "en") == 0) {
149 is(description,
150 "Test Database",
151 "en description == 'Test Database'");
152 } else if (strcmp(key_name, "zh") == 0) {
153 is(description,
154 "Test Database Chinese",
155 "zh description == 'Test Database Chinese'");
156 } else {
157 ok(0, "unknown key found in description map - %s", key_name);
158 }
159
160 free((void *)key_name);
161 free((void *)description);
162 }
163
164 return entry_data_list;
165 }
166
test_metadata_as_data_entry_list(MMDB_s * mmdb,const char * mode_desc)167 void test_metadata_as_data_entry_list(MMDB_s *mmdb, const char *mode_desc) {
168 MMDB_entry_data_list_s *entry_data_list, *first;
169 int status = MMDB_get_metadata_as_entry_data_list(mmdb, &entry_data_list);
170
171 first = entry_data_list;
172
173 cmp_ok(status,
174 "==",
175 MMDB_SUCCESS,
176 "get metadata as data_entry_list - %s",
177 mode_desc);
178
179 cmp_ok(first->entry_data.data_size,
180 "==",
181 9,
182 "metadata map has 9 key/value pairs");
183
184 while (1) {
185 MMDB_entry_data_list_s *key = entry_data_list = entry_data_list->next;
186
187 if (!key) {
188 break;
189 }
190
191 cmp_ok(key->entry_data.type,
192 "==",
193 MMDB_DATA_TYPE_UTF8_STRING,
194 "found a map key");
195
196 const char *key_name = dup_entry_string_or_bail(key->entry_data);
197 if (strcmp(key_name, "node_count") == 0) {
198 MMDB_entry_data_list_s *value = entry_data_list =
199 entry_data_list->next;
200 cmp_ok(value->entry_data.uint32, "==", 37, "node_count == 37");
201 } else if (strcmp(key_name, "record_size") == 0) {
202 MMDB_entry_data_list_s *value = entry_data_list =
203 entry_data_list->next;
204 cmp_ok(value->entry_data.uint16, "==", 24, "record_size == 24");
205 } else if (strcmp(key_name, "ip_version") == 0) {
206 MMDB_entry_data_list_s *value = entry_data_list =
207 entry_data_list->next;
208 cmp_ok(value->entry_data.uint16, "==", 4, "ip_version == 4");
209 } else if (strcmp(key_name, "binary_format_major_version") == 0) {
210 MMDB_entry_data_list_s *value = entry_data_list =
211 entry_data_list->next;
212 cmp_ok(value->entry_data.uint16,
213 "==",
214 2,
215 "binary_format_major_version == 2");
216 } else if (strcmp(key_name, "binary_format_minor_version") == 0) {
217 MMDB_entry_data_list_s *value = entry_data_list =
218 entry_data_list->next;
219 cmp_ok(value->entry_data.uint16,
220 "==",
221 0,
222 "binary_format_minor_version == 0");
223 } else if (strcmp(key_name, "build_epoch") == 0) {
224 MMDB_entry_data_list_s *value = entry_data_list =
225 entry_data_list->next;
226 ok(value->entry_data.uint64 > 1373571901,
227 "build_epoch > 1373571901");
228 } else if (strcmp(key_name, "database_type") == 0) {
229 MMDB_entry_data_list_s *value = entry_data_list =
230 entry_data_list->next;
231 const char *type = dup_entry_string_or_bail(value->entry_data);
232 is(type, "Test", "type == Test");
233 free((void *)type);
234 } else if (strcmp(key_name, "languages") == 0) {
235 entry_data_list = test_languages_value(entry_data_list);
236 } else if (strcmp(key_name, "description") == 0) {
237 entry_data_list = test_description_value(entry_data_list);
238 } else {
239 ok(0, "unknown key found in metadata map - %s", key_name);
240 }
241
242 free((void *)key_name);
243 }
244
245 MMDB_free_entry_data_list(first);
246 }
247
run_tests(int mode,const char * mode_desc)248 void run_tests(int mode, const char *mode_desc) {
249 const char *file = "MaxMind-DB-test-ipv4-24.mmdb";
250 const char *path = test_database_path(file);
251 MMDB_s *mmdb = open_ok(path, mode, mode_desc);
252
253 // All of the remaining tests require an open mmdb
254 if (NULL == mmdb) {
255 diag("could not open %s - skipping remaining tests", path);
256 return;
257 }
258 free((void *)path);
259
260 test_metadata(mmdb, mode_desc);
261 test_metadata_as_data_entry_list(mmdb, mode_desc);
262
263 MMDB_close(mmdb);
264 free(mmdb);
265 }
266
main(void)267 int main(void) {
268 plan(NO_PLAN);
269 for_all_modes(&run_tests);
270 done_testing();
271 }
272