diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-05-09 17:33:04 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-05-09 17:33:04 +0200 |
commit | 8bb475af99260f1d107dbc8908268ae93960aa83 (patch) | |
tree | 1a7a1fc03424df841a6f977b137482439b09bc9f /src/namestore/test_namestore_api_zone_iteration.c | |
parent | 1f80a11e90ee982bffaae4685e281f75ee1c225d (diff) | |
download | gnunet-8bb475af99260f1d107dbc8908268ae93960aa83.tar.gz gnunet-8bb475af99260f1d107dbc8908268ae93960aa83.zip |
implement new functions in libgnunetsq, clean up sqlite namestore plugin, implement flow control in namestore API and tests
Diffstat (limited to 'src/namestore/test_namestore_api_zone_iteration.c')
-rw-r--r-- | src/namestore/test_namestore_api_zone_iteration.c | 200 |
1 files changed, 89 insertions, 111 deletions
diff --git a/src/namestore/test_namestore_api_zone_iteration.c b/src/namestore/test_namestore_api_zone_iteration.c index 806605d94..68c3de9b8 100644 --- a/src/namestore/test_namestore_api_zone_iteration.c +++ b/src/namestore/test_namestore_api_zone_iteration.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2013 GNUnet e.V. | 3 | Copyright (C) 2013, 2018 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -56,8 +56,6 @@ static char * s_name_3; | |||
56 | 56 | ||
57 | static struct GNUNET_GNSRECORD_Data *s_rd_3; | 57 | static struct GNUNET_GNSRECORD_Data *s_rd_3; |
58 | 58 | ||
59 | static char *directory; | ||
60 | |||
61 | 59 | ||
62 | /** | 60 | /** |
63 | * Re-establish the connection to the service. | 61 | * Re-establish the connection to the service. |
@@ -68,43 +66,8 @@ static char *directory; | |||
68 | static void | 66 | static void |
69 | endbadly (void *cls) | 67 | endbadly (void *cls) |
70 | { | 68 | { |
71 | if (NULL != zi) | 69 | endbadly_task = NULL; |
72 | { | 70 | GNUNET_SCHEDULER_shutdown (); |
73 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | ||
74 | zi = NULL; | ||
75 | } | ||
76 | if (nsh != NULL) | ||
77 | { | ||
78 | GNUNET_NAMESTORE_disconnect (nsh); | ||
79 | nsh = NULL; | ||
80 | } | ||
81 | GNUNET_free_non_null(s_name_1); | ||
82 | GNUNET_free_non_null(s_name_2); | ||
83 | GNUNET_free_non_null(s_name_3); | ||
84 | |||
85 | if (s_rd_1 != NULL) | ||
86 | { | ||
87 | GNUNET_free ((void *)s_rd_1->data); | ||
88 | GNUNET_free (s_rd_1); | ||
89 | } | ||
90 | if (s_rd_2 != NULL) | ||
91 | { | ||
92 | GNUNET_free ((void *)s_rd_2->data); | ||
93 | GNUNET_free (s_rd_2); | ||
94 | } | ||
95 | if (s_rd_3 != NULL) | ||
96 | { | ||
97 | GNUNET_free ((void *)s_rd_3->data); | ||
98 | GNUNET_free (s_rd_3); | ||
99 | } | ||
100 | |||
101 | if (privkey != NULL) | ||
102 | GNUNET_free (privkey); | ||
103 | privkey = NULL; | ||
104 | |||
105 | if (privkey2 != NULL) | ||
106 | GNUNET_free (privkey2); | ||
107 | privkey2 = NULL; | ||
108 | res = 1; | 71 | res = 1; |
109 | } | 72 | } |
110 | 73 | ||
@@ -117,41 +80,44 @@ end (void *cls) | |||
117 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | 80 | GNUNET_NAMESTORE_zone_iteration_stop (zi); |
118 | zi = NULL; | 81 | zi = NULL; |
119 | } | 82 | } |
120 | if (endbadly_task != NULL) | 83 | if (NULL != endbadly_task) |
121 | { | 84 | { |
122 | GNUNET_SCHEDULER_cancel (endbadly_task); | 85 | GNUNET_SCHEDULER_cancel (endbadly_task); |
123 | endbadly_task = NULL; | 86 | endbadly_task = NULL; |
124 | } | 87 | } |
125 | 88 | if (NULL != privkey) | |
126 | if (privkey != NULL) | 89 | { |
127 | GNUNET_free (privkey); | 90 | GNUNET_free (privkey); |
128 | privkey = NULL; | 91 | privkey = NULL; |
129 | 92 | } | |
130 | if (privkey2 != NULL) | 93 | if (NULL != privkey2) |
94 | { | ||
131 | GNUNET_free (privkey2); | 95 | GNUNET_free (privkey2); |
132 | privkey2 = NULL; | 96 | privkey2 = NULL; |
133 | 97 | } | |
134 | GNUNET_free (s_name_1); | 98 | GNUNET_free (s_name_1); |
135 | GNUNET_free (s_name_2); | 99 | GNUNET_free (s_name_2); |
136 | GNUNET_free (s_name_3); | 100 | GNUNET_free (s_name_3); |
137 | if (s_rd_1 != NULL) | 101 | if (NULL != s_rd_1) |
138 | { | 102 | { |
139 | GNUNET_free ((void *)s_rd_1->data); | 103 | GNUNET_free ((void *)s_rd_1->data); |
140 | GNUNET_free (s_rd_1); | 104 | GNUNET_free (s_rd_1); |
141 | } | 105 | } |
142 | if (s_rd_2 != NULL) | 106 | if (NULL != s_rd_2) |
143 | { | 107 | { |
144 | GNUNET_free ((void *)s_rd_2->data); | 108 | GNUNET_free ((void *)s_rd_2->data); |
145 | GNUNET_free (s_rd_2); | 109 | GNUNET_free (s_rd_2); |
146 | } | 110 | } |
147 | if (s_rd_3 != NULL) | 111 | if (NULL != s_rd_3) |
148 | { | 112 | { |
149 | GNUNET_free ((void *)s_rd_3->data); | 113 | GNUNET_free ((void *)s_rd_3->data); |
150 | GNUNET_free (s_rd_3); | 114 | GNUNET_free (s_rd_3); |
151 | } | 115 | } |
152 | if (nsh != NULL) | 116 | if (NULL != nsh) |
117 | { | ||
153 | GNUNET_NAMESTORE_disconnect (nsh); | 118 | GNUNET_NAMESTORE_disconnect (nsh); |
154 | nsh = NULL; | 119 | nsh = NULL; |
120 | } | ||
155 | } | 121 | } |
156 | 122 | ||
157 | 123 | ||
@@ -170,7 +136,7 @@ zone_end (void *cls) | |||
170 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 136 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
171 | "Received last result, iteration done after receing %u results\n", | 137 | "Received last result, iteration done after receing %u results\n", |
172 | returned_records); | 138 | returned_records); |
173 | GNUNET_SCHEDULER_add_now (&end, NULL); | 139 | GNUNET_SCHEDULER_shutdown (); |
174 | } | 140 | } |
175 | 141 | ||
176 | 142 | ||
@@ -191,7 +157,9 @@ zone_proc (void *cls, | |||
191 | int failed = GNUNET_NO; | 157 | int failed = GNUNET_NO; |
192 | 158 | ||
193 | GNUNET_assert (NULL != zone); | 159 | GNUNET_assert (NULL != zone); |
194 | if (0 == memcmp (zone, privkey, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) | 160 | if (0 == memcmp (zone, |
161 | privkey, | ||
162 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) | ||
195 | { | 163 | { |
196 | if (0 == strcmp (label, s_name_1)) | 164 | if (0 == strcmp (label, s_name_1)) |
197 | { | 165 | { |
@@ -230,12 +198,15 @@ zone_proc (void *cls, | |||
230 | else | 198 | else |
231 | { | 199 | { |
232 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 200 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
233 | "Comparing result failed: got name `%s' for first zone\n", label); | 201 | "Comparing result failed: got name `%s' for first zone\n", |
202 | label); | ||
234 | failed = GNUNET_YES; | 203 | failed = GNUNET_YES; |
235 | GNUNET_break (0); | 204 | GNUNET_break (0); |
236 | } | 205 | } |
237 | } | 206 | } |
238 | else if (0 == memcmp (zone, privkey2, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) | 207 | else if (0 == memcmp (zone, |
208 | privkey2, | ||
209 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) | ||
239 | { | 210 | { |
240 | if (0 == strcmp (label, s_name_3)) | 211 | if (0 == strcmp (label, s_name_3)) |
241 | { | 212 | { |
@@ -258,7 +229,8 @@ zone_proc (void *cls, | |||
258 | else | 229 | else |
259 | { | 230 | { |
260 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 231 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
261 | "Comparing result failed: got name `%s' for first zone\n", label); | 232 | "Comparing result failed: got name `%s' for first zone\n", |
233 | label); | ||
262 | failed = GNUNET_YES; | 234 | failed = GNUNET_YES; |
263 | GNUNET_break (0); | 235 | GNUNET_break (0); |
264 | } | 236 | } |
@@ -282,29 +254,34 @@ zone_proc (void *cls, | |||
282 | else | 254 | else |
283 | { | 255 | { |
284 | GNUNET_break (0); | 256 | GNUNET_break (0); |
285 | GNUNET_SCHEDULER_add_now (&end, NULL); | 257 | GNUNET_SCHEDULER_shutdown (); |
258 | res = 1; | ||
286 | } | 259 | } |
287 | } | 260 | } |
288 | 261 | ||
289 | 262 | ||
290 | static void | 263 | static void |
291 | put_cont (void *cls, int32_t success, const char *emsg) | 264 | put_cont (void *cls, |
265 | int32_t success, | ||
266 | const char *emsg) | ||
292 | { | 267 | { |
293 | static int c = 0; | 268 | static int c = 0; |
294 | 269 | ||
295 | if (success == GNUNET_OK) | 270 | if (success == GNUNET_OK) |
296 | { | 271 | { |
297 | c++; | 272 | c++; |
298 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c); | 273 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
274 | "Created record %u \n", | ||
275 | c); | ||
299 | } | 276 | } |
300 | else | 277 | else |
301 | { | 278 | { |
302 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n", | 279 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
280 | "Failed to created records: `%s'\n", | ||
303 | emsg); | 281 | emsg); |
304 | GNUNET_break (0); | 282 | GNUNET_break (0); |
305 | if (NULL != endbadly_task) | 283 | GNUNET_SCHEDULER_shutdown (); |
306 | GNUNET_SCHEDULER_cancel (endbadly_task); | 284 | res = 1; |
307 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
308 | return; | 285 | return; |
309 | } | 286 | } |
310 | 287 | ||
@@ -312,7 +289,8 @@ put_cont (void *cls, int32_t success, const char *emsg) | |||
312 | { | 289 | { |
313 | res = 1; | 290 | res = 1; |
314 | returned_records = 0; | 291 | returned_records = 0; |
315 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All records created, starting iteration over all zones \n"); | 292 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
293 | "All records created, starting iteration over all zones \n"); | ||
316 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | 294 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, |
317 | NULL, | 295 | NULL, |
318 | &fail_cb, | 296 | &fail_cb, |
@@ -323,11 +301,11 @@ put_cont (void *cls, int32_t success, const char *emsg) | |||
323 | NULL); | 301 | NULL); |
324 | if (zi == NULL) | 302 | if (zi == NULL) |
325 | { | 303 | { |
326 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); | 304 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
305 | "Failed to create zone iterator\n"); | ||
327 | GNUNET_break (0); | 306 | GNUNET_break (0); |
328 | if (NULL != endbadly_task) | 307 | GNUNET_SCHEDULER_shutdown (); |
329 | GNUNET_SCHEDULER_cancel (endbadly_task); | 308 | res = 1; |
330 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
331 | return; | 309 | return; |
332 | } | 310 | } |
333 | } | 311 | } |
@@ -337,11 +315,11 @@ put_cont (void *cls, int32_t success, const char *emsg) | |||
337 | static struct GNUNET_GNSRECORD_Data * | 315 | static struct GNUNET_GNSRECORD_Data * |
338 | create_record (unsigned int count) | 316 | create_record (unsigned int count) |
339 | { | 317 | { |
340 | unsigned int c; | ||
341 | struct GNUNET_GNSRECORD_Data * rd; | 318 | struct GNUNET_GNSRECORD_Data * rd; |
342 | 319 | ||
343 | rd = GNUNET_malloc (count * sizeof (struct GNUNET_GNSRECORD_Data)); | 320 | rd = GNUNET_new_array (count, |
344 | for (c = 0; c < count; c++) | 321 | struct GNUNET_GNSRECORD_Data); |
322 | for (unsigned int c = 0; c < count; c++) | ||
345 | { | 323 | { |
346 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS).abs_value_us; | 324 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS).abs_value_us; |
347 | rd[c].record_type = 1111; | 325 | rd[c].record_type = 1111; |
@@ -372,9 +350,8 @@ empty_zone_proc (void *cls, | |||
372 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 350 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
373 | _("Expected empty zone but received zone private key\n")); | 351 | _("Expected empty zone but received zone private key\n")); |
374 | GNUNET_break (0); | 352 | GNUNET_break (0); |
375 | if (endbadly_task != NULL) | 353 | GNUNET_SCHEDULER_shutdown (); |
376 | GNUNET_SCHEDULER_cancel (endbadly_task); | 354 | res = 1; |
377 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
378 | return; | 355 | return; |
379 | } | 356 | } |
380 | if ((NULL != label) || (NULL != rd) || (0 != rd_count)) | 357 | if ((NULL != label) || (NULL != rd) || (0 != rd_count)) |
@@ -382,9 +359,8 @@ empty_zone_proc (void *cls, | |||
382 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 359 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
383 | _("Expected no zone content but received data\n")); | 360 | _("Expected no zone content but received data\n")); |
384 | GNUNET_break (0); | 361 | GNUNET_break (0); |
385 | if (endbadly_task != NULL) | 362 | GNUNET_SCHEDULER_shutdown (); |
386 | GNUNET_SCHEDULER_cancel (endbadly_task); | 363 | res = 1; |
387 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
388 | return; | 364 | return; |
389 | } | 365 | } |
390 | GNUNET_assert (0); | 366 | GNUNET_assert (0); |
@@ -412,7 +388,9 @@ empty_zone_end (void *cls) | |||
412 | "zonefiles%s%s", | 388 | "zonefiles%s%s", |
413 | DIR_SEPARATOR_STR, | 389 | DIR_SEPARATOR_STR, |
414 | "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"); | 390 | "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"); |
415 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); | 391 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
392 | "Using zonekey file `%s' \n", | ||
393 | hostkey_file); | ||
416 | privkey2 = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); | 394 | privkey2 = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); |
417 | GNUNET_free (hostkey_file); | 395 | GNUNET_free (hostkey_file); |
418 | GNUNET_assert (privkey2 != NULL); | 396 | GNUNET_assert (privkey2 != NULL); |
@@ -425,8 +403,8 @@ empty_zone_end (void *cls) | |||
425 | privkey, | 403 | privkey, |
426 | s_name_1, | 404 | s_name_1, |
427 | 1, s_rd_1, | 405 | 1, s_rd_1, |
428 | &put_cont, NULL); | 406 | &put_cont, |
429 | 407 | NULL); | |
430 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 408 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
431 | "Created record 2 \n"); | 409 | "Created record 2 \n"); |
432 | GNUNET_asprintf(&s_name_2, "dummy2"); | 410 | GNUNET_asprintf(&s_name_2, "dummy2"); |
@@ -437,16 +415,18 @@ empty_zone_end (void *cls) | |||
437 | 1, s_rd_2, | 415 | 1, s_rd_2, |
438 | &put_cont, | 416 | &put_cont, |
439 | NULL); | 417 | NULL); |
440 | |||
441 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 418 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
442 | "Created record 3\n"); | 419 | "Created record 3\n"); |
443 | |||
444 | /* name in different zone */ | 420 | /* name in different zone */ |
445 | GNUNET_asprintf(&s_name_3, "dummy3"); | 421 | GNUNET_asprintf(&s_name_3, "dummy3"); |
446 | s_rd_3 = create_record(1); | 422 | s_rd_3 = create_record(1); |
447 | GNUNET_NAMESTORE_records_store (nsh, privkey2, s_name_3, | 423 | GNUNET_NAMESTORE_records_store (nsh, |
448 | 1, s_rd_3, | 424 | privkey2, |
449 | &put_cont, NULL); | 425 | s_name_3, |
426 | 1, | ||
427 | s_rd_3, | ||
428 | &put_cont, | ||
429 | NULL); | ||
450 | } | 430 | } |
451 | 431 | ||
452 | 432 | ||
@@ -455,31 +435,30 @@ run (void *cls, | |||
455 | const struct GNUNET_CONFIGURATION_Handle *cfg, | 435 | const struct GNUNET_CONFIGURATION_Handle *cfg, |
456 | struct GNUNET_TESTING_Peer *peer) | 436 | struct GNUNET_TESTING_Peer *peer) |
457 | { | 437 | { |
458 | directory = NULL; | 438 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, |
459 | GNUNET_assert (GNUNET_OK == | 439 | &endbadly, |
460 | GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", | 440 | NULL); |
461 | "GNUNET_TEST_HOME", | 441 | GNUNET_SCHEDULER_add_shutdown (&end, |
462 | &directory)); | 442 | NULL); |
463 | GNUNET_DISK_directory_remove (directory); | 443 | |
464 | |||
465 | endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT, &endbadly, NULL); | ||
466 | nsh = GNUNET_NAMESTORE_connect (cfg); | 444 | nsh = GNUNET_NAMESTORE_connect (cfg); |
467 | GNUNET_break (NULL != nsh); | 445 | GNUNET_break (NULL != nsh); |
468 | /* first, iterate over empty namestore */ | 446 | /* first, iterate over empty namestore */ |
469 | zi = GNUNET_NAMESTORE_zone_iteration_start(nsh, | 447 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, |
470 | NULL, | 448 | NULL, |
471 | &fail_cb, | 449 | &fail_cb, |
472 | NULL, | 450 | NULL, |
473 | &empty_zone_proc, | 451 | &empty_zone_proc, |
474 | nsh, | 452 | nsh, |
475 | &empty_zone_end, | 453 | &empty_zone_end, |
476 | NULL); | 454 | NULL); |
477 | if (NULL == zi) | 455 | if (NULL == zi) |
478 | { | 456 | { |
479 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); | 457 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
458 | "Failed to create zone iterator\n"); | ||
480 | GNUNET_break (0); | 459 | GNUNET_break (0); |
481 | GNUNET_SCHEDULER_cancel (endbadly_task); | 460 | res = 1; |
482 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | 461 | GNUNET_SCHEDULER_shutdown (); |
483 | } | 462 | } |
484 | } | 463 | } |
485 | 464 | ||
@@ -494,6 +473,8 @@ main (int argc, char *argv[]) | |||
494 | GNUNET_asprintf (&cfg_name, | 473 | GNUNET_asprintf (&cfg_name, |
495 | "test_namestore_api_%s.conf", | 474 | "test_namestore_api_%s.conf", |
496 | plugin_name); | 475 | plugin_name); |
476 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
477 | "GNUNET_TEST_HOME"); | ||
497 | res = 1; | 478 | res = 1; |
498 | if (0 != | 479 | if (0 != |
499 | GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration", | 480 | GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration", |
@@ -503,12 +484,9 @@ main (int argc, char *argv[]) | |||
503 | { | 484 | { |
504 | res = 1; | 485 | res = 1; |
505 | } | 486 | } |
487 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
488 | "GNUNET_TEST_HOME"); | ||
506 | GNUNET_free (cfg_name); | 489 | GNUNET_free (cfg_name); |
507 | if (NULL != directory) | ||
508 | { | ||
509 | GNUNET_DISK_directory_remove (directory); | ||
510 | GNUNET_free (directory); | ||
511 | } | ||
512 | return res; | 490 | return res; |
513 | } | 491 | } |
514 | 492 | ||