Line data Source code
1 : // Copyright (c) 2019-2025 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/prinbee
4 : // contact@m2osw.com
5 : //
6 : // This program is free software: you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation, either version 3 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 :
19 : // self
20 : //
21 : #include "catch_main.h"
22 :
23 :
24 : // prinbee
25 : //
26 : #include <prinbee/data/structure.h>
27 :
28 :
29 : // advgetopt
30 : //
31 : #include <advgetopt/options.h>
32 :
33 :
34 : // snapdev
35 : //
36 : #include <snapdev/enum_class_math.h>
37 : #include <snapdev/not_reached.h>
38 :
39 :
40 : // C++
41 : //
42 : #include <iomanip>
43 :
44 :
45 : // last include
46 : //
47 : #include <snapdev/poison.h>
48 :
49 :
50 :
51 : namespace
52 : {
53 :
54 :
55 :
56 : constexpr prinbee::struct_description_t g_description1_buffer_size_renamed[] =
57 : {
58 : prinbee::define_description(
59 : prinbee::FieldName("size")
60 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
61 : ),
62 : };
63 :
64 :
65 : // static size is:
66 : // 0 + 4 + 4 + 4 + 1 + 8 + 8 = 29
67 : //
68 : constexpr prinbee::struct_description_t g_description1[] =
69 : {
70 : prinbee::define_description(
71 : prinbee::FieldName("_magic")
72 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
73 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_BLOB))
74 : ),
75 : prinbee::define_description(
76 : prinbee::FieldName("_structure_version")
77 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
78 : , prinbee::FieldVersion(0, 1)
79 : ),
80 : prinbee::define_description(
81 : prinbee::FieldName("count")
82 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
83 : ),
84 : prinbee::define_description(
85 : prinbee::FieldName("buffer_size")
86 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_RENAMED)
87 : , prinbee::FieldSubDescription(g_description1_buffer_size_renamed)
88 : ),
89 : prinbee::define_description(
90 : prinbee::FieldName("size")
91 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
92 : ),
93 : prinbee::define_description(
94 : prinbee::FieldName("change")
95 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT8) // -100 to +100
96 : , prinbee::FieldVersion(3, 2, 11, 24)
97 : ),
98 : prinbee::define_description(
99 : prinbee::FieldName("next")
100 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_REFERENCE)
101 : ),
102 : prinbee::define_description(
103 : prinbee::FieldName("previous")
104 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_REFERENCE)
105 : ),
106 : prinbee::end_descriptions()
107 : };
108 :
109 :
110 :
111 : // static size is 0 (at least because of the name which is a P8STRING)
112 : //
113 : constexpr prinbee::struct_description_t g_description2[] =
114 : {
115 : prinbee::define_description(
116 : prinbee::FieldName("_magic")
117 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
118 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::FILE_TYPE_BLOOM_FILTER))
119 : ),
120 : prinbee::define_description(
121 : prinbee::FieldName("_structure_version")
122 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
123 : , prinbee::FieldVersion(15, 10231)
124 : ),
125 : prinbee::define_description(
126 : prinbee::FieldName("flags")
127 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
128 : ),
129 : prinbee::define_description(
130 : prinbee::FieldName("name")
131 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P8STRING)
132 : ),
133 : prinbee::define_description(
134 : prinbee::FieldName("size")
135 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT64)
136 : ),
137 : prinbee::define_description(
138 : prinbee::FieldName("model")
139 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT16)
140 : ),
141 : prinbee::end_descriptions()
142 : };
143 :
144 :
145 :
146 : constexpr prinbee::struct_description_t g_description3_sub1[] =
147 : {
148 : prinbee::define_description(
149 : prinbee::FieldName("major")
150 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
151 : ),
152 : prinbee::define_description(
153 : prinbee::FieldName("minor")
154 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
155 : ),
156 : prinbee::define_description(
157 : prinbee::FieldName("release")
158 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
159 : ),
160 : prinbee::define_description(
161 : prinbee::FieldName("build")
162 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
163 : ),
164 : prinbee::end_descriptions()
165 : };
166 :
167 :
168 : // static size is:
169 : // 0 + 4 + 4 + 64 + 16 + 1 = 89
170 : // ^--- sub-structure
171 : //
172 : constexpr prinbee::struct_description_t g_description3[] =
173 : {
174 : prinbee::define_description(
175 : prinbee::FieldName("_magic")
176 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
177 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_FREE_SPACE))
178 : ),
179 : prinbee::define_description(
180 : prinbee::FieldName("_structure_version")
181 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
182 : , prinbee::FieldVersion(25, 312)
183 : ),
184 : prinbee::define_description(
185 : prinbee::FieldName("sub_field")
186 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
187 : ),
188 : prinbee::define_description(
189 : prinbee::FieldName("data")
190 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT512)
191 : ),
192 : prinbee::define_description(
193 : prinbee::FieldName("software_version")
194 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE)
195 : , prinbee::FieldSubDescription(g_description3_sub1)
196 : ),
197 : prinbee::define_description(
198 : prinbee::FieldName("javascript_version")
199 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_VERSION)
200 : , prinbee::FieldDefaultValue("7.3")
201 : ),
202 : prinbee::define_description(
203 : prinbee::FieldName("eight_bits=null/advance:4/efficient:2/sign")
204 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS8)
205 : ),
206 : prinbee::end_descriptions()
207 : };
208 :
209 :
210 :
211 : constexpr prinbee::struct_description_t g_description4a[] =
212 : {
213 : prinbee::define_description(
214 : prinbee::FieldName("_magic")
215 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
216 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::FILE_TYPE_PRIMARY_INDEX))
217 : ),
218 : prinbee::define_description(
219 : prinbee::FieldName("missing_structure_version")
220 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_NSTIME)
221 : ),
222 : prinbee::end_descriptions()
223 : };
224 :
225 :
226 :
227 : constexpr prinbee::struct_description_t g_description4b[] =
228 : {
229 : prinbee::define_description(
230 : prinbee::FieldName("_structure_version")
231 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
232 : , prinbee::FieldVersion(45, 12'231)
233 : ),
234 : prinbee::define_description(
235 : prinbee::FieldName("missing_magic=16")
236 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_CHAR)
237 : ),
238 : prinbee::end_descriptions()
239 : };
240 :
241 :
242 :
243 : constexpr prinbee::struct_description_t g_description5_sub1[] =
244 : {
245 : prinbee::define_description(
246 : prinbee::FieldName("size")
247 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT8)
248 : ),
249 : prinbee::define_description(
250 : prinbee::FieldName("parts")
251 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BUFFER8)
252 : ),
253 : prinbee::end_descriptions()
254 : };
255 :
256 :
257 : // not static (but static up to the sub-structure so that is the one
258 : // that breaks the static-ness)
259 : //
260 : // dynamic size on initialization:
261 : // _magic 4
262 : // _structure_version 4
263 : // sub_field 8
264 : // data 16
265 : // early_version.size 1
266 : // early_version.parts 1 + 0
267 : // sixteen_bits 2
268 : // tag 15 (the current value does not chnage this size)
269 : // name 1
270 : // ---------
271 : // total 52
272 : //
273 : constexpr prinbee::struct_description_t g_description5[] =
274 : {
275 : prinbee::define_description(
276 : prinbee::FieldName("_magic")
277 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
278 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS))
279 : ),
280 : prinbee::define_description(
281 : prinbee::FieldName("_structure_version")
282 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
283 : , prinbee::FieldVersion(405, 119)
284 : ),
285 : prinbee::define_description(
286 : prinbee::FieldName("sub_field")
287 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT64)
288 : ),
289 : prinbee::define_description(
290 : prinbee::FieldName("data")
291 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT128)
292 : ),
293 : // WARNING: the order here is ignored when computing the static size,
294 : // instead it goes through the sorted field names, so we
295 : // make sure that this one (early_version) is before any other
296 : // variable field
297 : //
298 : prinbee::define_description(
299 : prinbee::FieldName("early_version")
300 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE)
301 : , prinbee::FieldSubDescription(g_description5_sub1)
302 : ),
303 : prinbee::define_description(
304 : prinbee::FieldName("sixteen_bits=bulk:4/more:4/raise/signal:7")
305 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS16)
306 : ),
307 : prinbee::define_description(
308 : prinbee::FieldName("tag=15")
309 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_CHAR)
310 : , prinbee::FieldDefaultValue("image")
311 : ),
312 : prinbee::define_description(
313 : prinbee::FieldName("name")
314 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P8STRING)
315 : ),
316 : prinbee::end_descriptions()
317 : };
318 :
319 :
320 : constexpr prinbee::struct_description_t g_description6_rename[] =
321 : {
322 : prinbee::define_description(
323 : prinbee::FieldName("essay")
324 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_VOID)
325 : ),
326 : };
327 :
328 :
329 : // the structure is dynamic since it includes P-strings
330 : //
331 : // the default size, because it has default strings is a little more
332 : // complicated than the simple size of each field
333 : // _magic 4
334 : // _structure_version 4
335 : // name 1 + 5
336 : // description 2 + 62
337 : // essay 4 + 98
338 : // tag 15
339 : // renamed 0
340 : // ----------
341 : // total 197
342 : //
343 : constexpr prinbee::struct_description_t g_description6[] =
344 : {
345 : prinbee::define_description(
346 : prinbee::FieldName("_magic")
347 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
348 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS))
349 : ),
350 : prinbee::define_description(
351 : prinbee::FieldName("_structure_version")
352 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
353 : , prinbee::FieldVersion(15'345, 2'341)
354 : ),
355 : prinbee::define_description(
356 : prinbee::FieldName("name")
357 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P8STRING)
358 : , prinbee::FieldDefaultValue("Henri")
359 : ),
360 : prinbee::define_description(
361 : prinbee::FieldName("description")
362 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P16STRING)
363 : , prinbee::FieldDefaultValue("King who fell from a horse and had a rotting foot as a result.")
364 : ),
365 : prinbee::define_description(
366 : prinbee::FieldName("essay")
367 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P32STRING)
368 : , prinbee::FieldDefaultValue("King who killed his wife to marry another. Later wives were lucky that the divorce was \"invented\".")
369 : ),
370 : prinbee::define_description(
371 : prinbee::FieldName("tag=15")
372 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_CHAR)
373 : , prinbee::FieldDefaultValue("king")
374 : ),
375 : prinbee::define_description(
376 : prinbee::FieldName("dissertation")
377 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_RENAMED)
378 : , prinbee::FieldSubDescription(g_description6_rename)
379 : ),
380 : prinbee::end_descriptions()
381 : };
382 :
383 :
384 :
385 :
386 :
387 : constexpr prinbee::struct_description_t g_description7_column[] =
388 : {
389 : prinbee::define_description(
390 : prinbee::FieldName("colname")
391 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P8STRING)
392 : , prinbee::FieldDefaultValue("_undefined")
393 : ),
394 : prinbee::define_description(
395 : prinbee::FieldName("max_size")
396 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT16)
397 : , prinbee::FieldDefaultValue("256")
398 : ),
399 : prinbee::define_description(
400 : prinbee::FieldName("type")
401 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT16)
402 : , prinbee::FieldDefaultValue("14")
403 : ),
404 : prinbee::end_descriptions()
405 : };
406 :
407 :
408 : // the structure is dynamic (P-strings + arrays)
409 : //
410 : // _magic 4
411 : // _structure_version 4
412 : // name 32
413 : // columns 1
414 : // comment 4 + 43
415 : // ----------
416 : // total 45 + 88
417 : //
418 : constexpr prinbee::struct_description_t g_description7[] =
419 : {
420 : prinbee::define_description(
421 : prinbee::FieldName("_magic")
422 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
423 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS))
424 : ),
425 : prinbee::define_description(
426 : prinbee::FieldName("_structure_version")
427 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
428 : , prinbee::FieldVersion(1, 2)
429 : ),
430 : prinbee::define_description(
431 : prinbee::FieldName("name=32")
432 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_CHAR)
433 : , prinbee::FieldDefaultValue("users")
434 : ),
435 : prinbee::define_description(
436 : prinbee::FieldName("columns")
437 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_ARRAY8)
438 : , prinbee::FieldSubDescription(g_description7_column)
439 : ),
440 : prinbee::define_description(
441 : prinbee::FieldName("comment")
442 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P32STRING)
443 : , prinbee::FieldDefaultValue("This represents a form of table definition.")
444 : ),
445 : prinbee::end_descriptions()
446 : };
447 :
448 :
449 :
450 : constexpr prinbee::struct_description_t g_description8_column[] =
451 : {
452 : prinbee::define_description(
453 : prinbee::FieldName("colname")
454 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P8STRING)
455 : , prinbee::FieldDefaultValue("_undefined")
456 : ),
457 : prinbee::define_description(
458 : prinbee::FieldName("max_size")
459 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT16)
460 : , prinbee::FieldDefaultValue("256")
461 : ),
462 : prinbee::define_description(
463 : prinbee::FieldName("type")
464 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT16)
465 : , prinbee::FieldDefaultValue("14")
466 : ),
467 : prinbee::end_descriptions()
468 : };
469 :
470 :
471 : // the structure is dynamic (P-strings + arrays)
472 : //
473 : // _magic 4
474 : // _structure_version 4
475 : // name 4 + 5
476 : // columns 2
477 : // comment 4 + 33
478 : // ----------
479 : // total 18 + 56
480 : //
481 : constexpr prinbee::struct_description_t g_description8[] =
482 : {
483 : prinbee::define_description(
484 : prinbee::FieldName("_magic")
485 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
486 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS))
487 : ),
488 : prinbee::define_description(
489 : prinbee::FieldName("_structure_version")
490 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
491 : , prinbee::FieldVersion(1, 2)
492 : ),
493 : prinbee::define_description(
494 : prinbee::FieldName("name")
495 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P32STRING)
496 : , prinbee::FieldDefaultValue("users")
497 : ),
498 : prinbee::define_description(
499 : prinbee::FieldName("columns")
500 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_ARRAY16)
501 : , prinbee::FieldSubDescription(g_description7_column)
502 : ),
503 : prinbee::define_description(
504 : prinbee::FieldName("comment")
505 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P32STRING)
506 : , prinbee::FieldDefaultValue("Another form of table definition.")
507 : ),
508 : prinbee::end_descriptions()
509 : };
510 :
511 :
512 :
513 :
514 :
515 : constexpr prinbee::struct_description_t g_description9_column[] =
516 : {
517 : prinbee::define_description(
518 : prinbee::FieldName("colname")
519 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P16STRING)
520 : , prinbee::FieldDefaultValue("_undefined")
521 : ),
522 : prinbee::define_description(
523 : prinbee::FieldName("max_size")
524 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT16)
525 : , prinbee::FieldDefaultValue("256")
526 : ),
527 : prinbee::define_description(
528 : prinbee::FieldName("type")
529 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT16)
530 : , prinbee::FieldDefaultValue("14")
531 : ),
532 : prinbee::end_descriptions()
533 : };
534 :
535 :
536 : // the structure is dynamic (P-strings + arrays)
537 : //
538 : // _magic 4
539 : // _structure_version 4
540 : // name 1 + 4
541 : // columns 4
542 : // comment 2 + 56
543 : // ----------
544 : // total 15 + 75
545 : //
546 : constexpr prinbee::struct_description_t g_description9[] =
547 : {
548 : prinbee::define_description(
549 : prinbee::FieldName("_magic")
550 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
551 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS))
552 : ),
553 : prinbee::define_description(
554 : prinbee::FieldName("_structure_version")
555 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
556 : , prinbee::FieldVersion(1, 2)
557 : ),
558 : prinbee::define_description(
559 : prinbee::FieldName("name")
560 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P8STRING)
561 : , prinbee::FieldDefaultValue("page")
562 : ),
563 : prinbee::define_description(
564 : prinbee::FieldName("columns")
565 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_ARRAY32)
566 : , prinbee::FieldSubDescription(g_description7_column)
567 : ),
568 : prinbee::define_description(
569 : prinbee::FieldName("comment")
570 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P16STRING)
571 : , prinbee::FieldDefaultValue("Table with a number of columns that can go to 4 billion.")
572 : ),
573 : prinbee::end_descriptions()
574 : };
575 :
576 :
577 :
578 : constexpr prinbee::struct_description_t g_description10_buffer_size_renamed[] =
579 : {
580 : prinbee::define_description(
581 : prinbee::FieldName("unknown")
582 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
583 : ),
584 : };
585 :
586 :
587 : // rename has "unknown" field
588 : //
589 : constexpr prinbee::struct_description_t g_description10[] =
590 : {
591 : prinbee::define_description(
592 : prinbee::FieldName("_magic")
593 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
594 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_BLOB))
595 : ),
596 : prinbee::define_description(
597 : prinbee::FieldName("_structure_version")
598 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
599 : , prinbee::FieldVersion(0, 1)
600 : ),
601 : prinbee::define_description(
602 : prinbee::FieldName("buffer_size")
603 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_RENAMED)
604 : , prinbee::FieldSubDescription(g_description10_buffer_size_renamed)
605 : ),
606 : prinbee::end_descriptions()
607 : };
608 :
609 :
610 :
611 :
612 :
613 :
614 :
615 :
616 : constexpr prinbee::struct_description_t g_description11_column[] =
617 : {
618 : prinbee::define_description(
619 : prinbee::FieldName("name")
620 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P8STRING)
621 : , prinbee::FieldDefaultValue("_undefined")
622 : ),
623 : prinbee::define_description(
624 : prinbee::FieldName("type")
625 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT16)
626 : , prinbee::FieldDefaultValue("14")
627 : ),
628 : prinbee::define_description(
629 : prinbee::FieldName("flags=null/blob")
630 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS8)
631 : , prinbee::FieldDefaultValue("2")
632 : ),
633 : prinbee::end_descriptions()
634 : };
635 :
636 :
637 : constexpr prinbee::struct_description_t g_description11[] =
638 : {
639 : prinbee::define_description(
640 : prinbee::FieldName("_magic")
641 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
642 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_SCHEMA_LIST))
643 : ),
644 : prinbee::define_description(
645 : prinbee::FieldName("_structure_version")
646 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
647 : , prinbee::FieldVersion(5, 29)
648 : ),
649 : prinbee::define_description(
650 : prinbee::FieldName("name=32")
651 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_CHAR)
652 : , prinbee::FieldDefaultValue("passwords")
653 : ),
654 : prinbee::define_description(
655 : prinbee::FieldName("columns")
656 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_ARRAY8)
657 : , prinbee::FieldSubDescription(g_description11_column)
658 : ),
659 : prinbee::end_descriptions()
660 : };
661 :
662 :
663 :
664 :
665 :
666 :
667 :
668 :
669 :
670 :
671 :
672 : struct fixed_size_t
673 : {
674 : prinbee::struct_type_t f_type = prinbee::INVALID_STRUCT_TYPE;
675 : bool f_fixed = false;
676 : };
677 :
678 : std::vector<fixed_size_t> const g_fixed_sizes{
679 : { prinbee::struct_type_t::STRUCT_TYPE_END, true },
680 : { prinbee::struct_type_t::STRUCT_TYPE_VOID, true },
681 : { prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION, true },
682 : { prinbee::struct_type_t::STRUCT_TYPE_BITS8, true },
683 : { prinbee::struct_type_t::STRUCT_TYPE_BITS16, true },
684 : { prinbee::struct_type_t::STRUCT_TYPE_BITS32, true },
685 : { prinbee::struct_type_t::STRUCT_TYPE_BITS64, true },
686 : { prinbee::struct_type_t::STRUCT_TYPE_BITS128, true },
687 : { prinbee::struct_type_t::STRUCT_TYPE_BITS256, true },
688 : { prinbee::struct_type_t::STRUCT_TYPE_BITS512, true },
689 : { prinbee::struct_type_t::STRUCT_TYPE_INT8, true },
690 : { prinbee::struct_type_t::STRUCT_TYPE_UINT8, true },
691 : { prinbee::struct_type_t::STRUCT_TYPE_INT16, true },
692 : { prinbee::struct_type_t::STRUCT_TYPE_UINT16, true },
693 : { prinbee::struct_type_t::STRUCT_TYPE_INT32, true },
694 : { prinbee::struct_type_t::STRUCT_TYPE_UINT32, true },
695 : { prinbee::struct_type_t::STRUCT_TYPE_INT64, true },
696 : { prinbee::struct_type_t::STRUCT_TYPE_UINT64, true },
697 : { prinbee::struct_type_t::STRUCT_TYPE_INT128, true },
698 : { prinbee::struct_type_t::STRUCT_TYPE_UINT128, true },
699 : { prinbee::struct_type_t::STRUCT_TYPE_INT256, true },
700 : { prinbee::struct_type_t::STRUCT_TYPE_UINT256, true },
701 : { prinbee::struct_type_t::STRUCT_TYPE_INT512, true },
702 : { prinbee::struct_type_t::STRUCT_TYPE_UINT512, true },
703 : { prinbee::struct_type_t::STRUCT_TYPE_FLOAT32, true },
704 : { prinbee::struct_type_t::STRUCT_TYPE_FLOAT64, true },
705 : { prinbee::struct_type_t::STRUCT_TYPE_FLOAT128, true },
706 : { prinbee::struct_type_t::STRUCT_TYPE_VERSION, true },
707 : { prinbee::struct_type_t::STRUCT_TYPE_TIME, true },
708 : { prinbee::struct_type_t::STRUCT_TYPE_MSTIME, true },
709 : { prinbee::struct_type_t::STRUCT_TYPE_USTIME, true },
710 : { prinbee::struct_type_t::STRUCT_TYPE_NSTIME, true },
711 : { prinbee::struct_type_t::STRUCT_TYPE_P8STRING, false },
712 : { prinbee::struct_type_t::STRUCT_TYPE_P16STRING, false },
713 : { prinbee::struct_type_t::STRUCT_TYPE_P32STRING, false },
714 : { prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE, false },
715 : { prinbee::struct_type_t::STRUCT_TYPE_ARRAY8, false },
716 : { prinbee::struct_type_t::STRUCT_TYPE_ARRAY16, false },
717 : { prinbee::struct_type_t::STRUCT_TYPE_ARRAY32, false },
718 : { prinbee::struct_type_t::STRUCT_TYPE_BUFFER8, false },
719 : { prinbee::struct_type_t::STRUCT_TYPE_BUFFER16, false },
720 : { prinbee::struct_type_t::STRUCT_TYPE_BUFFER32, false },
721 : { prinbee::struct_type_t::STRUCT_TYPE_REFERENCE, true },
722 : { prinbee::struct_type_t::STRUCT_TYPE_OID, true },
723 : { prinbee::struct_type_t::STRUCT_TYPE_RENAMED, true },
724 : };
725 :
726 :
727 : struct field_info_t
728 : {
729 : char const * f_type_name = nullptr;
730 : ssize_t f_field_size = 0;
731 : ssize_t f_type_field_size = 0;
732 : };
733 :
734 : std::vector<field_info_t> g_field_info{
735 : { "VOID", 0, 0 },
736 : { "BITS8", 1, 0 },
737 : { "BITS16", 2, 0 },
738 : { "BITS32", 4, 0 },
739 : { "BITS64", 8, 0 },
740 : { "BITS128", 16, 0 },
741 : { "BITS256", 32, 0 },
742 : { "BITS512", 64, 0 },
743 : { "INT8", 1, 0 },
744 : { "UINT8", 1, 0 },
745 : { "INT16", 2, 0 },
746 : { "UINT16", 2, 0 },
747 : { "INT32", 4, 0 },
748 : { "UINT32", 4, 0 },
749 : { "INT64", 8, 0 },
750 : { "UINT64", 8, 0 },
751 : { "INT128", 16, 0 },
752 : { "UINT128", 16, 0 },
753 : { "INT256", 32, 0 },
754 : { "UINT256", 32, 0 },
755 : { "INT512", 64, 0 },
756 : { "UINT512", 64, 0 },
757 : { "FLOAT32", 4, 0 },
758 : { "FLOAT64", 8, 0 },
759 : { "FLOAT128", 16, 0 },
760 : { "VERSION", 4, 0 },
761 : { "TIME", 8, 0 },
762 : { "MSTIME", 8, 0 },
763 : { "USTIME", 8, 0 },
764 : { "NSTIME", 16, 0 },
765 : { "CHAR", -1, 0 },
766 : { "P8STRING", -2, 1 },
767 : { "P16STRING", -2, 2 },
768 : { "P32STRING", -2, 4 },
769 : { "STRUCTURE", -2, 0 },
770 : { "ARRAY8", -2, 1 },
771 : { "ARRAY16", -2, 2 },
772 : { "ARRAY32", -2, 4 },
773 : { "BUFFER8", -2, 1 },
774 : { "BUFFER16", -2, 2 },
775 : { "BUFFER32", -2, 4 },
776 : { "REFERENCE", 8, 0 },
777 : { "OID", 8, 0 },
778 : { "RENAMED", -1, 0 },
779 : };
780 :
781 :
782 101 : bool is_valid_type(prinbee::struct_type_t type)
783 : {
784 101 : switch(type)
785 : {
786 0 : case prinbee::struct_type_t::STRUCT_TYPE_END:
787 : case prinbee::struct_type_t::STRUCT_TYPE_VOID:
788 : case prinbee::struct_type_t::STRUCT_TYPE_BITS8:
789 : case prinbee::struct_type_t::STRUCT_TYPE_BITS16:
790 : case prinbee::struct_type_t::STRUCT_TYPE_BITS32:
791 : case prinbee::struct_type_t::STRUCT_TYPE_BITS64:
792 : case prinbee::struct_type_t::STRUCT_TYPE_BITS128:
793 : case prinbee::struct_type_t::STRUCT_TYPE_BITS256:
794 : case prinbee::struct_type_t::STRUCT_TYPE_BITS512:
795 : case prinbee::struct_type_t::STRUCT_TYPE_INT8:
796 : case prinbee::struct_type_t::STRUCT_TYPE_UINT8:
797 : case prinbee::struct_type_t::STRUCT_TYPE_INT16:
798 : case prinbee::struct_type_t::STRUCT_TYPE_UINT16:
799 : case prinbee::struct_type_t::STRUCT_TYPE_INT32:
800 : case prinbee::struct_type_t::STRUCT_TYPE_UINT32:
801 : case prinbee::struct_type_t::STRUCT_TYPE_INT64:
802 : case prinbee::struct_type_t::STRUCT_TYPE_UINT64:
803 : case prinbee::struct_type_t::STRUCT_TYPE_INT128:
804 : case prinbee::struct_type_t::STRUCT_TYPE_UINT128:
805 : case prinbee::struct_type_t::STRUCT_TYPE_INT256:
806 : case prinbee::struct_type_t::STRUCT_TYPE_UINT256:
807 : case prinbee::struct_type_t::STRUCT_TYPE_INT512:
808 : case prinbee::struct_type_t::STRUCT_TYPE_UINT512:
809 : case prinbee::struct_type_t::STRUCT_TYPE_FLOAT32:
810 : case prinbee::struct_type_t::STRUCT_TYPE_FLOAT64:
811 : case prinbee::struct_type_t::STRUCT_TYPE_FLOAT128:
812 : case prinbee::struct_type_t::STRUCT_TYPE_VERSION:
813 : case prinbee::struct_type_t::STRUCT_TYPE_TIME:
814 : case prinbee::struct_type_t::STRUCT_TYPE_MSTIME:
815 : case prinbee::struct_type_t::STRUCT_TYPE_USTIME:
816 : case prinbee::struct_type_t::STRUCT_TYPE_P8STRING:
817 : case prinbee::struct_type_t::STRUCT_TYPE_P16STRING:
818 : case prinbee::struct_type_t::STRUCT_TYPE_P32STRING:
819 : case prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE:
820 : case prinbee::struct_type_t::STRUCT_TYPE_ARRAY8:
821 : case prinbee::struct_type_t::STRUCT_TYPE_ARRAY16:
822 : case prinbee::struct_type_t::STRUCT_TYPE_ARRAY32:
823 : case prinbee::struct_type_t::STRUCT_TYPE_BUFFER8:
824 : case prinbee::struct_type_t::STRUCT_TYPE_BUFFER16:
825 : case prinbee::struct_type_t::STRUCT_TYPE_BUFFER32:
826 : case prinbee::struct_type_t::STRUCT_TYPE_REFERENCE:
827 : case prinbee::struct_type_t::STRUCT_TYPE_OID:
828 : case prinbee::struct_type_t::STRUCT_TYPE_RENAMED:
829 0 : return true;
830 :
831 101 : default:
832 101 : return false;
833 :
834 : }
835 : snapdev::NOT_REACHED();
836 : }
837 :
838 : }
839 : // no name namespace
840 :
841 :
842 2 : CATCH_TEST_CASE("structure_type_name", "[structure][type][valid]")
843 : {
844 4 : CATCH_START_SECTION("structure_type_name: name from type")
845 : {
846 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_END) == "END");
847 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_VOID) == "VOID");
848 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION) == "STRUCTURE_VERSION");
849 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS8) == "BITS8");
850 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS16) == "BITS16");
851 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS32) == "BITS32");
852 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS64) == "BITS64");
853 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS128) == "BITS128");
854 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS256) == "BITS256");
855 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS512) == "BITS512");
856 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT8) == "INT8");
857 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT8) == "UINT8");
858 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT16) == "INT16");
859 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT16) == "UINT16");
860 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT32) == "INT32");
861 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT32) == "UINT32");
862 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT64) == "INT64");
863 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT64) == "UINT64");
864 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT128) == "INT128");
865 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT128) == "UINT128");
866 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT256) == "INT256");
867 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT256) == "UINT256");
868 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT512) == "INT512");
869 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT512) == "UINT512");
870 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_FLOAT32) == "FLOAT32");
871 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_FLOAT64) == "FLOAT64");
872 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_FLOAT128) == "FLOAT128");
873 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_VERSION) == "VERSION");
874 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_TIME) == "TIME");
875 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_MSTIME) == "MSTIME");
876 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_USTIME) == "USTIME");
877 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_NSTIME) == "NSTIME");
878 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_P8STRING) == "P8STRING");
879 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_P16STRING) == "P16STRING");
880 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_P32STRING) == "P32STRING");
881 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE) == "STRUCTURE");
882 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_ARRAY8) == "ARRAY8");
883 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_ARRAY16) == "ARRAY16");
884 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_ARRAY32) == "ARRAY32");
885 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BUFFER8) == "BUFFER8");
886 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BUFFER16) == "BUFFER16");
887 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BUFFER32) == "BUFFER32");
888 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_REFERENCE) == "REFERENCE");
889 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_OID) == "OID");
890 1 : CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_RENAMED) == "RENAMED");
891 : }
892 3 : CATCH_END_SECTION()
893 :
894 4 : CATCH_START_SECTION("structure_type_name: type from name")
895 : {
896 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("END") == prinbee::struct_type_t::STRUCT_TYPE_END);
897 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("VOID") == prinbee::struct_type_t::STRUCT_TYPE_VOID);
898 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("STRUCTURE_VERSION") == prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION);
899 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("BITS8") == prinbee::struct_type_t::STRUCT_TYPE_BITS8);
900 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("BITS16") == prinbee::struct_type_t::STRUCT_TYPE_BITS16);
901 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("BITS32") == prinbee::struct_type_t::STRUCT_TYPE_BITS32);
902 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("BITS64") == prinbee::struct_type_t::STRUCT_TYPE_BITS64);
903 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("BITS128") == prinbee::struct_type_t::STRUCT_TYPE_BITS128);
904 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("BITS256") == prinbee::struct_type_t::STRUCT_TYPE_BITS256);
905 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("BITS512") == prinbee::struct_type_t::STRUCT_TYPE_BITS512);
906 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("INT8") == prinbee::struct_type_t::STRUCT_TYPE_INT8);
907 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("UINT8") == prinbee::struct_type_t::STRUCT_TYPE_UINT8);
908 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("INT16") == prinbee::struct_type_t::STRUCT_TYPE_INT16);
909 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("UINT16") == prinbee::struct_type_t::STRUCT_TYPE_UINT16);
910 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("INT32") == prinbee::struct_type_t::STRUCT_TYPE_INT32);
911 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("UINT32") == prinbee::struct_type_t::STRUCT_TYPE_UINT32);
912 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("INT64") == prinbee::struct_type_t::STRUCT_TYPE_INT64);
913 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("UINT64") == prinbee::struct_type_t::STRUCT_TYPE_UINT64);
914 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("INT128") == prinbee::struct_type_t::STRUCT_TYPE_INT128);
915 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("UINT128") == prinbee::struct_type_t::STRUCT_TYPE_UINT128);
916 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("INT256") == prinbee::struct_type_t::STRUCT_TYPE_INT256);
917 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("UINT256") == prinbee::struct_type_t::STRUCT_TYPE_UINT256);
918 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("INT512") == prinbee::struct_type_t::STRUCT_TYPE_INT512);
919 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("UINT512") == prinbee::struct_type_t::STRUCT_TYPE_UINT512);
920 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("FLOAT32") == prinbee::struct_type_t::STRUCT_TYPE_FLOAT32);
921 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("FLOAT64") == prinbee::struct_type_t::STRUCT_TYPE_FLOAT64);
922 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("FLOAT128") == prinbee::struct_type_t::STRUCT_TYPE_FLOAT128);
923 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("VERSION") == prinbee::struct_type_t::STRUCT_TYPE_VERSION);
924 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("TIME") == prinbee::struct_type_t::STRUCT_TYPE_TIME);
925 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("MSTIME") == prinbee::struct_type_t::STRUCT_TYPE_MSTIME);
926 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("USTIME") == prinbee::struct_type_t::STRUCT_TYPE_USTIME);
927 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("NSTIME") == prinbee::struct_type_t::STRUCT_TYPE_NSTIME);
928 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("P8STRING") == prinbee::struct_type_t::STRUCT_TYPE_P8STRING);
929 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("P16STRING") == prinbee::struct_type_t::STRUCT_TYPE_P16STRING);
930 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("P32STRING") == prinbee::struct_type_t::STRUCT_TYPE_P32STRING);
931 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("STRUCTURE") == prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE);
932 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("ARRAY8") == prinbee::struct_type_t::STRUCT_TYPE_ARRAY8);
933 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("ARRAY16") == prinbee::struct_type_t::STRUCT_TYPE_ARRAY16);
934 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("ARRAY32") == prinbee::struct_type_t::STRUCT_TYPE_ARRAY32);
935 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("BUFFER8") == prinbee::struct_type_t::STRUCT_TYPE_BUFFER8);
936 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("BUFFER16") == prinbee::struct_type_t::STRUCT_TYPE_BUFFER16);
937 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("BUFFER32") == prinbee::struct_type_t::STRUCT_TYPE_BUFFER32);
938 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("REFERENCE") == prinbee::struct_type_t::STRUCT_TYPE_REFERENCE);
939 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("OID") == prinbee::struct_type_t::STRUCT_TYPE_OID);
940 3 : CATCH_REQUIRE(prinbee::name_to_struct_type("RENAMED") == prinbee::struct_type_t::STRUCT_TYPE_RENAMED);
941 : }
942 3 : CATCH_END_SECTION()
943 2 : }
944 :
945 :
946 2 : CATCH_TEST_CASE("structure_type_name_invalid", "[structure][type][invalid]")
947 : {
948 4 : CATCH_START_SECTION("structure_type_name_invalid: unknown")
949 : {
950 101 : for(int i(0); i < 100; ++i)
951 : {
952 100 : prinbee::struct_type_t bad_type(prinbee::struct_type_t::STRUCT_TYPE_END);
953 : do
954 : {
955 100 : bad_type = static_cast<prinbee::struct_type_t>(SNAP_CATCH2_NAMESPACE::rand32());
956 : }
957 100 : while(is_valid_type(bad_type));
958 100 : std::string const expected(
959 : "*unknown struct type ("
960 200 : + std::to_string(static_cast<int>(bad_type))
961 200 : + ")*");
962 100 : CATCH_REQUIRE(expected == prinbee::to_string(bad_type));
963 100 : }
964 : }
965 3 : CATCH_END_SECTION()
966 :
967 4 : CATCH_START_SECTION("structure_type_name_invalid: invalid")
968 : {
969 101 : for(int i(0); i < 100; ++i)
970 : {
971 : //prinbee::struct_type_t bad_type(prinbee::struct_type_t::STRUCT_TYPE_END);
972 100 : std::string const bad_type_name(SNAP_CATCH2_NAMESPACE::rand_string(rand() % 10 + 1));
973 100 : prinbee::struct_type_t type(prinbee::name_to_struct_type(bad_type_name));
974 100 : if(type != prinbee::INVALID_STRUCT_TYPE)
975 : {
976 : // the rand_string() could return a valid name (very unlikely, though)
977 : //
978 0 : CATCH_REQUIRE(prinbee::to_string(type) == bad_type_name); // not that bad after all...
979 : }
980 : else
981 : {
982 : // avoid catch2 error "no assertion in section ..."
983 : //
984 100 : CATCH_REQUIRE(prinbee::INVALID_STRUCT_TYPE == type);
985 : }
986 100 : }
987 : }
988 3 : CATCH_END_SECTION()
989 2 : }
990 :
991 :
992 1 : CATCH_TEST_CASE("structure_type_metadata", "[structure][type][valid]")
993 : {
994 3 : CATCH_START_SECTION("structure_type_metadata: fixed size")
995 : {
996 46 : for(auto const & f : g_fixed_sizes)
997 : {
998 45 : if(f.f_fixed != prinbee::type_with_fixed_size(f.f_type))
999 : {
1000 0 : SNAP_LOG_FATAL
1001 : << "type "
1002 0 : << prinbee::to_string(f.f_type)
1003 0 : << (f.f_fixed ? " was" : " is not")
1004 : << " expected to be fixed."
1005 : << SNAP_LOG_SEND;
1006 : }
1007 45 : CATCH_REQUIRE(f.f_fixed == prinbee::type_with_fixed_size(f.f_type));
1008 : }
1009 : }
1010 2 : CATCH_END_SECTION()
1011 1 : }
1012 :
1013 :
1014 2 : CATCH_TEST_CASE("structure_version_basics", "[structure][version]")
1015 : {
1016 4 : CATCH_START_SECTION("structure_version_basics: default version")
1017 : {
1018 1 : prinbee::version_t version;
1019 1 : CATCH_REQUIRE(version.get_major() == 0);
1020 1 : CATCH_REQUIRE(version.get_minor() == 0);
1021 : }
1022 3 : CATCH_END_SECTION()
1023 :
1024 4 : CATCH_START_SECTION("structure_version_basics: version conversions")
1025 : {
1026 101 : for(int n(0); n < 100; ++n)
1027 : {
1028 100 : int const major_version(rand() & 0xFFFF);
1029 100 : int const minor_version(rand() & 0xFFFF);
1030 :
1031 100 : std::uint32_t const binary((major_version << 16) + minor_version);
1032 :
1033 100 : prinbee::version_t const v1(major_version, minor_version);
1034 100 : CATCH_REQUIRE(v1.get_major() == major_version);
1035 100 : CATCH_REQUIRE(v1.get_minor() == minor_version);
1036 100 : CATCH_REQUIRE(v1.to_binary() == binary);
1037 :
1038 100 : prinbee::version_t v2;
1039 100 : CATCH_REQUIRE(v2.get_major() == 0);
1040 100 : CATCH_REQUIRE(v2.get_minor() == 0);
1041 100 : CATCH_REQUIRE(v2.is_null());
1042 100 : CATCH_REQUIRE(v2 != v1);
1043 100 : v2.from_binary(binary);
1044 100 : CATCH_REQUIRE(v2.get_major() == major_version);
1045 100 : CATCH_REQUIRE(v2.get_minor() == minor_version);
1046 100 : CATCH_REQUIRE(v2.to_binary() == binary);
1047 100 : CATCH_REQUIRE(v2 == v1);
1048 :
1049 100 : v2.next_revision();
1050 :
1051 100 : if(minor_version == 0xFFFF)
1052 : {
1053 0 : CATCH_REQUIRE(v2.get_major() == major_version + 1);
1054 0 : CATCH_REQUIRE(v2.get_minor() == 0);
1055 : }
1056 : else
1057 : {
1058 100 : CATCH_REQUIRE(v2.get_major() == major_version);
1059 100 : CATCH_REQUIRE(v2.get_minor() == minor_version + 1);
1060 : }
1061 :
1062 100 : v2 = v1;
1063 100 : int const new_major_version(rand() & 0xFFFF);
1064 100 : v2.set_major(new_major_version);
1065 100 : CATCH_REQUIRE(v2.get_major() == new_major_version);
1066 100 : CATCH_REQUIRE(v2.get_minor() == minor_version);
1067 100 : CATCH_REQUIRE(v2 != v1);
1068 :
1069 100 : int const new_minor_version(rand() & 0xFFFF);
1070 100 : v2.set_minor(new_minor_version);
1071 100 : CATCH_REQUIRE(v2.get_major() == new_major_version);
1072 100 : CATCH_REQUIRE(v2.get_minor() == new_minor_version);
1073 100 : CATCH_REQUIRE(v2 != v1);
1074 :
1075 100 : v2 = v1;
1076 100 : CATCH_REQUIRE(v2.get_major() == major_version);
1077 100 : CATCH_REQUIRE(v2.get_minor() == minor_version);
1078 100 : CATCH_REQUIRE(v2.to_binary() == binary);
1079 100 : CATCH_REQUIRE(v2 == v1);
1080 :
1081 100 : prinbee::version_t v3(v1);
1082 100 : CATCH_REQUIRE_FALSE(v3.is_null());
1083 100 : CATCH_REQUIRE(v3.get_major() == major_version);
1084 100 : CATCH_REQUIRE(v3.get_minor() == minor_version);
1085 100 : CATCH_REQUIRE(v3.to_binary() == binary);
1086 100 : CATCH_REQUIRE(v3 == v1);
1087 100 : CATCH_REQUIRE_FALSE(v3 > v1);
1088 100 : CATCH_REQUIRE(v3 >= v1);
1089 100 : CATCH_REQUIRE_FALSE(v3 < v1);
1090 100 : CATCH_REQUIRE(v3 <= v1);
1091 :
1092 100 : std::string v3_str(v3.to_string());
1093 100 : std::string version_str;
1094 100 : version_str += std::to_string(major_version);
1095 100 : version_str += '.';
1096 100 : version_str += std::to_string(minor_version);
1097 100 : CATCH_REQUIRE(v3_str == version_str);
1098 100 : std::stringstream ss;
1099 100 : ss << v3;
1100 100 : CATCH_REQUIRE(ss.str() == version_str);
1101 :
1102 100 : v3.next_branch();
1103 100 : CATCH_REQUIRE(v3.get_major() == major_version + 1);
1104 100 : CATCH_REQUIRE(v3.get_minor() == 0);
1105 100 : CATCH_REQUIRE(v3.to_binary() == static_cast<uint32_t>((major_version + 1) << 16));
1106 :
1107 100 : prinbee::version_t v4(binary);
1108 100 : CATCH_REQUIRE_FALSE(v4.is_null());
1109 100 : CATCH_REQUIRE(v4.get_major() == major_version);
1110 100 : CATCH_REQUIRE(v4.get_minor() == minor_version);
1111 100 : CATCH_REQUIRE(v4.to_binary() == binary);
1112 100 : CATCH_REQUIRE(v1 == v4);
1113 100 : }
1114 : }
1115 3 : CATCH_END_SECTION()
1116 2 : }
1117 :
1118 :
1119 1 : CATCH_TEST_CASE("structure_version_compare", "[structure][version]")
1120 : {
1121 3 : CATCH_START_SECTION("structure_version_compare: compare")
1122 : {
1123 101 : for(int n(0); n < 100; ++n)
1124 : {
1125 100 : int major_version(rand() & 0xFFFF);
1126 100 : int minor_version(rand() & 0xFFFF);
1127 100 : int major_version2(rand() & 0xFFFF);
1128 100 : while(major_version == major_version2)
1129 : {
1130 0 : major_version2 = rand() & 0xFFFF;
1131 : }
1132 :
1133 100 : prinbee::version_t v1(major_version, minor_version);
1134 100 : prinbee::version_t v2(major_version2, minor_version);
1135 100 : if(major_version < major_version2)
1136 : {
1137 51 : CATCH_REQUIRE_FALSE(v1 == v2);
1138 51 : CATCH_REQUIRE(v1 != v2);
1139 51 : CATCH_REQUIRE(v1 < v2);
1140 51 : CATCH_REQUIRE(v1 <= v2);
1141 51 : CATCH_REQUIRE(v2 > v1);
1142 51 : CATCH_REQUIRE(v2 >= v1);
1143 : }
1144 : else
1145 : {
1146 49 : CATCH_REQUIRE_FALSE(v1 == v2);
1147 49 : CATCH_REQUIRE(v1 != v2);
1148 49 : CATCH_REQUIRE(v1 > v2);
1149 49 : CATCH_REQUIRE(v1 >= v2);
1150 49 : CATCH_REQUIRE(v2 < v1);
1151 49 : CATCH_REQUIRE(v2 <= v1);
1152 : }
1153 : }
1154 : }
1155 2 : CATCH_END_SECTION()
1156 1 : }
1157 :
1158 :
1159 1 : CATCH_TEST_CASE("structure_version_overflow", "[structure][version][invalid]")
1160 : {
1161 3 : CATCH_START_SECTION("structure_version_overflow: version overflow")
1162 : {
1163 101 : for(int n(0); n < 100; ++n)
1164 : {
1165 100 : int major_version(0);
1166 100 : int minor_version(0);
1167 : do
1168 : {
1169 126 : major_version = SNAP_CATCH2_NAMESPACE::rand32();
1170 126 : minor_version = SNAP_CATCH2_NAMESPACE::rand32();
1171 : }
1172 : while(major_version < 65536
1173 126 : && minor_version < 65536);
1174 :
1175 200 : CATCH_REQUIRE_THROWS_MATCHES(
1176 : prinbee::version_t(major_version, minor_version)
1177 : , prinbee::invalid_parameter
1178 : , Catch::Matchers::ExceptionMessage(
1179 : "prinbee_exception: major/minor version must be between 0 and 65535 inclusive, "
1180 : + std::to_string(major_version)
1181 : + "."
1182 : + std::to_string(minor_version)
1183 : + " is incorrect."));
1184 : }
1185 : }
1186 2 : CATCH_END_SECTION()
1187 1 : }
1188 :
1189 :
1190 1 : CATCH_TEST_CASE("structure_min_max_version", "[structure][version][valid]")
1191 : {
1192 3 : CATCH_START_SECTION("structure_min_max_version: default")
1193 : {
1194 1 : prinbee::version_t version = prinbee::version_t();
1195 1 : prinbee::min_max_version_t full_range;
1196 1 : CATCH_REQUIRE(version == full_range.min());
1197 1 : CATCH_REQUIRE(prinbee::max_version() == full_range.max());
1198 : }
1199 2 : CATCH_END_SECTION()
1200 1 : }
1201 :
1202 :
1203 1 : CATCH_TEST_CASE("structure_flag_definitions", "[structure][flags][valid]")
1204 : {
1205 3 : CATCH_START_SECTION("structure_flag_definitions: all positions")
1206 : {
1207 65 : for(std::size_t pos(0); pos < 64; ++pos)
1208 : {
1209 64 : std::string const field_name(SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1));
1210 64 : std::string const flag_name(SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1));
1211 :
1212 64 : std::string full_name(field_name);
1213 64 : full_name += '.';
1214 64 : full_name += flag_name;
1215 :
1216 64 : prinbee::flag_definition const def(field_name, flag_name, pos);
1217 64 : CATCH_REQUIRE(full_name == def.full_name());
1218 64 : CATCH_REQUIRE(field_name == def.field_name());
1219 64 : CATCH_REQUIRE(flag_name == def.flag_name());
1220 64 : CATCH_REQUIRE(pos == def.pos());
1221 64 : CATCH_REQUIRE(1ULL == def.size());
1222 64 : CATCH_REQUIRE((1ULL << pos) == def.mask());
1223 64 : }
1224 : }
1225 2 : CATCH_END_SECTION()
1226 1 : }
1227 :
1228 :
1229 2 : CATCH_TEST_CASE("structure_flag_definitions_incorrect_construction", "[structure][flags][invalid]")
1230 : {
1231 4 : CATCH_START_SECTION("structure_flag_definitions_incorrect_construction: missing name(s)")
1232 : {
1233 : // missing flag name
1234 1 : std::string name(SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1));
1235 6 : CATCH_REQUIRE_THROWS_MATCHES(
1236 : prinbee::flag_definition(name, std::string(), rand(), rand())
1237 : , prinbee::invalid_parameter
1238 : , Catch::Matchers::ExceptionMessage(
1239 : "prinbee_exception: the flag definition must have a non-empty field name and flag name."));
1240 :
1241 : // missing field name
1242 1 : name = SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1);
1243 6 : CATCH_REQUIRE_THROWS_MATCHES(
1244 : prinbee::flag_definition(std::string(), name, rand())
1245 : , prinbee::invalid_parameter
1246 : , Catch::Matchers::ExceptionMessage(
1247 : "prinbee_exception: the flag definition must have a non-empty field name and flag name."));
1248 :
1249 : // missing both names
1250 1 : name = SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1);
1251 8 : CATCH_REQUIRE_THROWS_MATCHES(
1252 : prinbee::flag_definition(std::string(), std::string(), rand() % 64, rand())
1253 : , prinbee::invalid_parameter
1254 : , Catch::Matchers::ExceptionMessage(
1255 : "prinbee_exception: the flag definition must have a non-empty field name and flag name."));
1256 1 : }
1257 3 : CATCH_END_SECTION()
1258 :
1259 4 : CATCH_START_SECTION("structure_flag_definitions_incorrect_construction: unsupported sizes / positions")
1260 : {
1261 : // zero fails
1262 : //
1263 1 : std::string field_name(SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1));
1264 1 : std::string flag_name(SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1));
1265 2 : CATCH_REQUIRE_THROWS_MATCHES(
1266 : prinbee::flag_definition(field_name, flag_name, rand(), 0ULL)
1267 : , prinbee::invalid_parameter
1268 : , Catch::Matchers::ExceptionMessage(
1269 : "prinbee_exception: bit field named \""
1270 : + field_name
1271 : + "."
1272 : + flag_name
1273 : + "\" cannot have a size of 0."));
1274 :
1275 37 : for(std::size_t size(64); size < 100; ++size)
1276 : {
1277 72 : CATCH_REQUIRE_THROWS_MATCHES(
1278 : prinbee::flag_definition(field_name, flag_name, rand(), size)
1279 : , prinbee::invalid_parameter
1280 : , Catch::Matchers::ExceptionMessage(
1281 : "prinbee_exception: bit field named \""
1282 : + field_name
1283 : + "."
1284 : + flag_name
1285 : + "\" is too large ("
1286 : + std::to_string(size)
1287 : + " >= 64)."));
1288 : }
1289 :
1290 64 : for(std::size_t size(1ULL); size < 64ULL; ++size)
1291 : {
1292 4284 : for(std::size_t pos(65ULL - size); pos < 100ULL; ++pos)
1293 : {
1294 8442 : CATCH_REQUIRE_THROWS_MATCHES(
1295 : prinbee::flag_definition(field_name, flag_name, pos, size)
1296 : , prinbee::invalid_parameter
1297 : , Catch::Matchers::ExceptionMessage(
1298 : "prinbee_exception: the mask of the bit field named \""
1299 : + field_name
1300 : + "."
1301 : + flag_name
1302 : + "\" does not fit in a uint64_t."));
1303 : }
1304 : }
1305 :
1306 : // position 65+ is not valid either
1307 : //
1308 2 : CATCH_REQUIRE_THROWS_MATCHES(
1309 : prinbee::flag_definition(field_name, flag_name, 65ULL)
1310 : , prinbee::invalid_parameter
1311 : , Catch::Matchers::ExceptionMessage(
1312 : "prinbee_exception: the mask of the bit field named \""
1313 : + field_name
1314 : + "."
1315 : + flag_name
1316 : + "\" does not fit in a uint64_t."));
1317 1 : }
1318 3 : CATCH_END_SECTION()
1319 2 : }
1320 :
1321 :
1322 6 : CATCH_TEST_CASE("structure_field", "[structure][valid]")
1323 : {
1324 8 : CATCH_START_SECTION("structure_field: check description of all different database types")
1325 : {
1326 45 : for(auto const & info : g_field_info)
1327 : {
1328 44 : prinbee::field_t::field_flags_t flags((rand() & 1) != 0 ? 0 : prinbee::STRUCT_DESCRIPTION_FLAG_OPTIONAL);
1329 132 : prinbee::struct_type_t const type(prinbee::name_to_struct_type(info.f_type_name));
1330 44 : std::shared_ptr<prinbee::struct_description_t> description;
1331 132 : std::string name(info.f_type_name);
1332 44 : ssize_t expected_type_field_size(info.f_type_field_size);
1333 44 : switch(type)
1334 : {
1335 5 : case prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE:
1336 : case prinbee::struct_type_t::STRUCT_TYPE_ARRAY8:
1337 : case prinbee::struct_type_t::STRUCT_TYPE_ARRAY16:
1338 : case prinbee::struct_type_t::STRUCT_TYPE_ARRAY32:
1339 : case prinbee::struct_type_t::STRUCT_TYPE_RENAMED:
1340 5 : description.reset(new prinbee::struct_description_t{
1341 5 : prinbee::define_description(
1342 : prinbee::FieldName(name.c_str())
1343 : , prinbee::FieldType(type)
1344 : , prinbee::FieldFlags(flags)
1345 : , prinbee::FieldSubDescription(g_description3)
1346 : ),
1347 15 : });
1348 5 : break;
1349 :
1350 7 : case prinbee::struct_type_t::STRUCT_TYPE_BITS8:
1351 : case prinbee::struct_type_t::STRUCT_TYPE_BITS16:
1352 : case prinbee::struct_type_t::STRUCT_TYPE_BITS32:
1353 : case prinbee::struct_type_t::STRUCT_TYPE_BITS64:
1354 : case prinbee::struct_type_t::STRUCT_TYPE_BITS128:
1355 : case prinbee::struct_type_t::STRUCT_TYPE_BITS256:
1356 : case prinbee::struct_type_t::STRUCT_TYPE_BITS512:
1357 7 : name += "=flag";
1358 7 : description.reset(new prinbee::struct_description_t{
1359 : prinbee::define_description(
1360 : prinbee::FieldName(name.c_str())
1361 : , prinbee::FieldType(type)
1362 : , prinbee::FieldFlags(flags)
1363 : ),
1364 14 : });
1365 7 : break;
1366 :
1367 1 : case prinbee::struct_type_t::STRUCT_TYPE_CHAR:
1368 1 : expected_type_field_size = 40;
1369 1 : name += "=40";
1370 1 : description.reset(new prinbee::struct_description_t{
1371 : prinbee::define_description(
1372 : prinbee::FieldName(name.c_str())
1373 : , prinbee::FieldType(type)
1374 : , prinbee::FieldFlags(flags)
1375 : ),
1376 2 : });
1377 1 : break;
1378 :
1379 31 : default:
1380 31 : description.reset(new prinbee::struct_description_t{
1381 : prinbee::define_description(
1382 : prinbee::FieldName(name.c_str())
1383 : , prinbee::FieldType(type)
1384 : , prinbee::FieldFlags(flags)
1385 : ),
1386 62 : });
1387 31 : break;
1388 :
1389 : }
1390 :
1391 88 : prinbee::field_t::const_pointer_t f(std::make_shared<prinbee::field_t>(description.get()));
1392 :
1393 44 : CATCH_REQUIRE(description.get() == f->description());
1394 44 : CATCH_REQUIRE(nullptr == f->next());
1395 44 : CATCH_REQUIRE(nullptr == f->previous());
1396 44 : CATCH_REQUIRE(f == f->first());
1397 44 : CATCH_REQUIRE(f == f->last());
1398 44 : CATCH_REQUIRE(type == f->type());
1399 44 : CATCH_REQUIRE(info.f_field_size == f->field_size());
1400 44 : CATCH_REQUIRE(expected_type_field_size == f->type_field_size());
1401 44 : CATCH_REQUIRE(info.f_type_name == f->field_name());
1402 44 : if(type == prinbee::struct_type_t::STRUCT_TYPE_CHAR)
1403 : {
1404 : // CHAR is peculiar about its size which is hard coded in
1405 : // the field name so it is predefined and not zero here
1406 : //
1407 1 : CATCH_REQUIRE(expected_type_field_size == f->size());
1408 : }
1409 : else
1410 : {
1411 43 : CATCH_REQUIRE(0 == f->size());
1412 : }
1413 :
1414 44 : std::uint32_t const size(SNAP_CATCH2_NAMESPACE::rand32());
1415 44 : std::const_pointer_cast<prinbee::field_t>(f)->set_size(size);
1416 44 : CATCH_REQUIRE(size == f->size());
1417 :
1418 : // the flags are set by the structure parser, so here it's never set
1419 : // whether it is defined in the description above
1420 : //
1421 44 : CATCH_REQUIRE_FALSE(f->has_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE));
1422 44 : CATCH_REQUIRE(0 == f->flags());
1423 :
1424 44 : std::const_pointer_cast<prinbee::field_t>(f)->set_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE);
1425 44 : CATCH_REQUIRE(f->has_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE));
1426 44 : CATCH_REQUIRE(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE == f->flags());
1427 :
1428 44 : std::const_pointer_cast<prinbee::field_t>(f)->clear_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE);
1429 44 : CATCH_REQUIRE_FALSE(f->has_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE));
1430 44 : CATCH_REQUIRE(0 == f->flags());
1431 :
1432 44 : std::const_pointer_cast<prinbee::field_t>(f)->add_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE);
1433 44 : CATCH_REQUIRE(f->has_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE));
1434 44 : CATCH_REQUIRE(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE == f->flags());
1435 :
1436 44 : CATCH_REQUIRE(0 == f->offset());
1437 :
1438 44 : std::uint64_t const offset(SNAP_CATCH2_NAMESPACE::rand64());
1439 44 : std::const_pointer_cast<prinbee::field_t>(f)->set_offset(offset);
1440 44 : CATCH_REQUIRE(offset == f->offset());
1441 :
1442 44 : std::int64_t const adjust(SNAP_CATCH2_NAMESPACE::rand64());
1443 44 : std::const_pointer_cast<prinbee::field_t>(f)->adjust_offset(adjust);
1444 44 : CATCH_REQUIRE(offset + adjust == f->offset());
1445 :
1446 44 : CATCH_REQUIRE(f->sub_structures().empty());
1447 44 : CATCH_REQUIRE(std::const_pointer_cast<prinbee::field_t>(f)->sub_structures().empty());
1448 44 : }
1449 : }
1450 7 : CATCH_END_SECTION()
1451 :
1452 8 : CATCH_START_SECTION("structure_field: check flag definitions")
1453 : {
1454 1 : prinbee::struct_description_t description =
1455 : {
1456 : prinbee::define_description(
1457 : prinbee::FieldName("flags=big:60/small:3/tiny")
1458 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS64)
1459 : ),
1460 : };
1461 :
1462 1 : prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
1463 :
1464 1 : CATCH_REQUIRE(&description == f->description());
1465 1 : CATCH_REQUIRE(nullptr == f->next());
1466 1 : CATCH_REQUIRE(nullptr == f->previous());
1467 1 : CATCH_REQUIRE(f == f->first());
1468 1 : CATCH_REQUIRE(f == f->last());
1469 1 : CATCH_REQUIRE(prinbee::struct_type_t::STRUCT_TYPE_BITS64 == f->type());
1470 1 : CATCH_REQUIRE(8 == f->field_size());
1471 1 : CATCH_REQUIRE(0 == f->type_field_size());
1472 1 : CATCH_REQUIRE("flags" == f->field_name());
1473 1 : CATCH_REQUIRE(0 == f->size());
1474 1 : CATCH_REQUIRE_FALSE(f->has_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE));
1475 1 : CATCH_REQUIRE(0 == f->flags());
1476 1 : CATCH_REQUIRE(0 == f->offset());
1477 :
1478 : // flag_definition::pointer_t find_flag_definition(std::string const & name) const;
1479 : // void add_flag_definition(flag_definition::pointer_t bits);
1480 :
1481 11 : for(int i(1); i <= 10; ++i)
1482 : {
1483 : #pragma GCC diagnostic push
1484 : #pragma GCC diagnostic ignored "-Wrestrict"
1485 10 : std::string const name("f" + std::to_string(i));
1486 : #pragma GCC diagnostic pop
1487 10 : prinbee::flag_definition::pointer_t flag(std::make_shared<prinbee::flag_definition>("flags", name, i * 3, 3));
1488 10 : CATCH_REQUIRE(flag->full_name() == "flags." + name);
1489 10 : f->add_flag_definition(flag);
1490 10 : CATCH_REQUIRE(flag == f->find_flag_definition(name));
1491 10 : }
1492 :
1493 : // make sure they stay around
1494 : //
1495 11 : for(int i(1); i <= 10; ++i)
1496 : {
1497 : #pragma GCC diagnostic push
1498 : #pragma GCC diagnostic ignored "-Wrestrict"
1499 10 : std::string const name("f" + std::to_string(i));
1500 : #pragma GCC diagnostic pop
1501 10 : CATCH_REQUIRE(f->find_flag_definition(name)->full_name() == "flags." + name);
1502 10 : }
1503 1 : }
1504 7 : CATCH_END_SECTION()
1505 :
1506 8 : CATCH_START_SECTION("structure_field: next/previous (1)")
1507 : {
1508 1 : prinbee::struct_description_t description[3] =
1509 : {
1510 : prinbee::define_description(
1511 : prinbee::FieldName("head")
1512 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT32)
1513 : ),
1514 : prinbee::define_description(
1515 : prinbee::FieldName("cont")
1516 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT64)
1517 : ),
1518 : prinbee::define_description(
1519 : prinbee::FieldName("tail=fish:10/fin:2/gill/bones:3")
1520 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS16)
1521 : ),
1522 : };
1523 :
1524 1 : prinbee::field_t::pointer_t first(std::make_shared<prinbee::field_t>(description + 0));
1525 1 : prinbee::field_t::pointer_t middle(std::make_shared<prinbee::field_t>(description + 1));
1526 1 : prinbee::field_t::pointer_t last(std::make_shared<prinbee::field_t>(description + 2));
1527 :
1528 : // fields are used internally so the linking requires two calls
1529 : //
1530 1 : first->set_next(middle);
1531 1 : middle->set_previous(first);
1532 :
1533 1 : middle->set_next(last);
1534 1 : last->set_previous(middle);
1535 :
1536 1 : CATCH_REQUIRE(nullptr == first->previous());
1537 1 : CATCH_REQUIRE(middle == first->next());
1538 1 : CATCH_REQUIRE(first == middle->previous());
1539 1 : CATCH_REQUIRE(last == middle->next());
1540 1 : CATCH_REQUIRE(middle == last->previous());
1541 1 : CATCH_REQUIRE(nullptr == last->next());
1542 :
1543 1 : CATCH_REQUIRE(first == first->first());
1544 1 : CATCH_REQUIRE(first == middle->first());
1545 1 : CATCH_REQUIRE(first == last->first());
1546 1 : CATCH_REQUIRE(last == first->last());
1547 1 : CATCH_REQUIRE(last == middle->last());
1548 1 : CATCH_REQUIRE(last == last->last());
1549 :
1550 1 : CATCH_REQUIRE(first->type() == prinbee::struct_type_t::STRUCT_TYPE_INT32);
1551 1 : CATCH_REQUIRE(middle->type() == prinbee::struct_type_t::STRUCT_TYPE_UINT64);
1552 1 : CATCH_REQUIRE(last->type() == prinbee::struct_type_t::STRUCT_TYPE_BITS16);
1553 :
1554 : // when last pointer gets reset, it changes a few things
1555 : //
1556 1 : last.reset();
1557 1 : CATCH_REQUIRE(last == nullptr);
1558 :
1559 1 : CATCH_REQUIRE(nullptr == first->previous());
1560 1 : CATCH_REQUIRE(middle == first->next());
1561 1 : CATCH_REQUIRE(first == first->first());
1562 1 : CATCH_REQUIRE(middle == first->last());
1563 :
1564 1 : CATCH_REQUIRE(first == middle->previous());
1565 1 : CATCH_REQUIRE(nullptr == middle->next());
1566 1 : CATCH_REQUIRE(first == middle->first());
1567 1 : CATCH_REQUIRE(middle == middle->last());
1568 1 : }
1569 7 : CATCH_END_SECTION()
1570 :
1571 8 : CATCH_START_SECTION("structure_field: next/previous (2)")
1572 : {
1573 1 : prinbee::struct_description_t description[5] =
1574 : {
1575 : prinbee::define_description(
1576 : prinbee::FieldName("head")
1577 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT32)
1578 : ),
1579 : prinbee::define_description(
1580 : prinbee::FieldName("early")
1581 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT64)
1582 : ),
1583 : prinbee::define_description(
1584 : prinbee::FieldName("middle")
1585 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT256)
1586 : ),
1587 : prinbee::define_description(
1588 : prinbee::FieldName("late")
1589 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_REFERENCE)
1590 : ),
1591 : prinbee::define_description(
1592 : prinbee::FieldName("tail=mask:13/size:3")
1593 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS16)
1594 : ),
1595 : };
1596 :
1597 1 : prinbee::field_t::pointer_t first(std::make_shared<prinbee::field_t>(description + 0));
1598 1 : prinbee::field_t::pointer_t early(std::make_shared<prinbee::field_t>(description + 1));
1599 1 : prinbee::field_t::pointer_t middle(std::make_shared<prinbee::field_t>(description + 2));
1600 1 : prinbee::field_t::pointer_t late(std::make_shared<prinbee::field_t>(description + 3));
1601 1 : prinbee::field_t::pointer_t last(std::make_shared<prinbee::field_t>(description + 4));
1602 :
1603 : // fields are used internally so the linking requires two calls
1604 : //
1605 1 : first->set_next(early);
1606 1 : early->set_previous(first);
1607 :
1608 1 : early->set_next(middle);
1609 1 : middle->set_previous(early);
1610 :
1611 1 : middle->set_next(late);
1612 1 : late->set_previous(middle);
1613 :
1614 1 : late->set_next(last);
1615 1 : last->set_previous(late);
1616 :
1617 1 : CATCH_REQUIRE(nullptr == first->previous());
1618 1 : CATCH_REQUIRE(early == first->next());
1619 1 : CATCH_REQUIRE(first == early->previous());
1620 1 : CATCH_REQUIRE(middle == early->next());
1621 1 : CATCH_REQUIRE(early == middle->previous());
1622 1 : CATCH_REQUIRE(late == middle->next());
1623 1 : CATCH_REQUIRE(middle == late->previous());
1624 1 : CATCH_REQUIRE(last == late->next());
1625 1 : CATCH_REQUIRE(late == last->previous());
1626 1 : CATCH_REQUIRE(nullptr == last->next());
1627 :
1628 1 : CATCH_REQUIRE(first == first->first());
1629 1 : CATCH_REQUIRE(first == early->first());
1630 1 : CATCH_REQUIRE(first == middle->first());
1631 1 : CATCH_REQUIRE(first == late->first());
1632 1 : CATCH_REQUIRE(first == last->first());
1633 1 : CATCH_REQUIRE(last == first->last());
1634 1 : CATCH_REQUIRE(last == early->last());
1635 1 : CATCH_REQUIRE(last == middle->last());
1636 1 : CATCH_REQUIRE(last == late->last());
1637 1 : CATCH_REQUIRE(last == last->last());
1638 :
1639 1 : CATCH_REQUIRE(first->type() == prinbee::struct_type_t::STRUCT_TYPE_INT32);
1640 1 : CATCH_REQUIRE(early->type() == prinbee::struct_type_t::STRUCT_TYPE_UINT64);
1641 1 : CATCH_REQUIRE(middle->type() == prinbee::struct_type_t::STRUCT_TYPE_INT256);
1642 1 : CATCH_REQUIRE(late->type() == prinbee::struct_type_t::STRUCT_TYPE_REFERENCE);
1643 1 : CATCH_REQUIRE(last->type() == prinbee::struct_type_t::STRUCT_TYPE_BITS16);
1644 :
1645 : // when middle pointer gets reset, it changes a few things
1646 : //
1647 1 : middle.reset();
1648 1 : CATCH_REQUIRE(middle == nullptr);
1649 :
1650 1 : CATCH_REQUIRE(nullptr == first->previous());
1651 1 : CATCH_REQUIRE(early == first->next());
1652 1 : CATCH_REQUIRE(first == first->first());
1653 1 : CATCH_REQUIRE(last == first->last());
1654 :
1655 1 : CATCH_REQUIRE(first == early->previous());
1656 1 : CATCH_REQUIRE(late == early->next());
1657 1 : CATCH_REQUIRE(first == early->first());
1658 1 : CATCH_REQUIRE(last == early->last());
1659 :
1660 1 : CATCH_REQUIRE(early == late->previous());
1661 1 : CATCH_REQUIRE(last == late->next());
1662 1 : CATCH_REQUIRE(first == late->first());
1663 1 : CATCH_REQUIRE(last == late->last());
1664 :
1665 1 : CATCH_REQUIRE(late == last->previous());
1666 1 : CATCH_REQUIRE(nullptr == last->next());
1667 1 : CATCH_REQUIRE(first == last->first());
1668 1 : CATCH_REQUIRE(last == last->last());
1669 1 : }
1670 7 : CATCH_END_SECTION()
1671 :
1672 8 : CATCH_START_SECTION("structure_field: new name with a RENAMED but no field name")
1673 : {
1674 1 : prinbee::struct_description_t rename =
1675 : {
1676 : prinbee::define_description(
1677 : prinbee::FieldName("true_name")
1678 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT512)
1679 : ),
1680 : };
1681 :
1682 1 : prinbee::struct_description_t description =
1683 : {
1684 3 : prinbee::define_description(
1685 : prinbee::FieldName("name_missing")
1686 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_RENAMED)
1687 : , prinbee::FieldSubDescription(&rename)
1688 : ),
1689 4 : };
1690 :
1691 1 : prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
1692 :
1693 1 : CATCH_REQUIRE("true_name" == f->new_name());
1694 1 : }
1695 7 : CATCH_END_SECTION()
1696 :
1697 8 : CATCH_START_SECTION("structure_field: sub-structures")
1698 : {
1699 1 : prinbee::struct_description_t description[] =
1700 : {
1701 : prinbee::define_description(
1702 : prinbee::FieldName("structure")
1703 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE)
1704 : , prinbee::FieldSubDescription(g_description1)
1705 : ),
1706 : };
1707 :
1708 1 : prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(description));
1709 :
1710 1 : prinbee::structure::pointer_t s(std::make_shared<prinbee::structure>(g_description1));
1711 1 : CATCH_REQUIRE(s->get_static_size() == 33);
1712 1 : f->sub_structures().push_back(s);
1713 1 : CATCH_REQUIRE((*f)[0] == s);
1714 1 : }
1715 7 : CATCH_END_SECTION()
1716 6 : }
1717 :
1718 :
1719 12 : CATCH_TEST_CASE("structure_invalid_field", "[structure][valid]")
1720 : {
1721 14 : CATCH_START_SECTION("structure_invalid_field: check description of all different database types")
1722 : {
1723 : // generate an invalid type and then try a field description
1724 : // with such, we should get errors in various places
1725 : //
1726 1 : prinbee::struct_type_t bad_type(static_cast<prinbee::struct_type_t>(rand()));
1727 1 : while(is_valid_type(bad_type))
1728 : {
1729 0 : bad_type = static_cast<prinbee::struct_type_t>(rand());
1730 : }
1731 :
1732 6 : CATCH_REQUIRE_THROWS_MATCHES(
1733 : prinbee::define_description(
1734 : prinbee::FieldName("INVALID")
1735 : , prinbee::FieldType(bad_type)
1736 : )
1737 : , prinbee::invalid_parameter
1738 : , Catch::Matchers::ExceptionMessage("prinbee_exception: the specified structure field type was not recognized."));
1739 :
1740 1 : prinbee::struct_description_t description =
1741 : {
1742 : .f_field_name = "INVALID",
1743 : .f_type = bad_type,
1744 : .f_flags = 0,
1745 : .f_default_value = nullptr,
1746 : .f_min_version = prinbee::version_t(),
1747 : .f_max_version = prinbee::version_t(),
1748 : .f_sub_description = nullptr,
1749 1 : };
1750 :
1751 1 : prinbee::field_t::const_pointer_t f(std::make_shared<prinbee::field_t>(&description));
1752 :
1753 1 : CATCH_REQUIRE_THROWS_MATCHES(
1754 : f->field_size()
1755 : , prinbee::out_of_range
1756 : , Catch::Matchers::ExceptionMessage(
1757 : "out_of_range: type out of range for converting it to a field size ("
1758 : "*unknown struct type ("
1759 : + std::to_string(static_cast<int>(bad_type))
1760 : + ")*"
1761 : ", max: 47).")); // this number is not defined otherwise...
1762 :
1763 1 : CATCH_REQUIRE_THROWS_MATCHES(
1764 : f->type_field_size()
1765 : , prinbee::out_of_range
1766 : , Catch::Matchers::ExceptionMessage(
1767 : "out_of_range: type out of range for converting it to a type field size ("
1768 : "*unknown struct type ("
1769 : + std::to_string(static_cast<int>(bad_type))
1770 : + ")*"
1771 : ", max: 47).")); // this number is not defined otherwise...
1772 1 : }
1773 13 : CATCH_END_SECTION()
1774 :
1775 14 : CATCH_START_SECTION("structure_invalid_field: new name without a RENAMED")
1776 : {
1777 1 : prinbee::struct_description_t description =
1778 : {
1779 : prinbee::define_description(
1780 : prinbee::FieldName("not_renamed")
1781 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BUFFER8) // <- wrong type
1782 : ),
1783 : };
1784 :
1785 1 : prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
1786 :
1787 4 : CATCH_REQUIRE_THROWS_MATCHES(
1788 : f->new_name()
1789 : , prinbee::type_mismatch
1790 : , Catch::Matchers::ExceptionMessage(
1791 : "prinbee_exception: field \"not_renamed\" is not a RENAMED field, it has no new name."));
1792 1 : }
1793 13 : CATCH_END_SECTION()
1794 :
1795 14 : CATCH_START_SECTION("structure_invalid_field: new name without a sub-description")
1796 : {
1797 6 : CATCH_REQUIRE_THROWS_MATCHES(
1798 : prinbee::define_description(
1799 : prinbee::FieldName("no_link")
1800 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_RENAMED)
1801 : )
1802 : , prinbee::invalid_parameter
1803 : , Catch::Matchers::ExceptionMessage(
1804 : "prinbee_exception: this structure field must have a sub-description field."));
1805 :
1806 : // in case someone creates a description manually, make sure we also
1807 : // catch that error
1808 : //
1809 1 : prinbee::struct_description_t description =
1810 : {
1811 : .f_field_name = "no_link",
1812 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_RENAMED,
1813 : .f_flags = 0,
1814 : .f_default_value = nullptr,
1815 : .f_min_version = prinbee::version_t(),
1816 : .f_max_version = prinbee::version_t(),
1817 : .f_sub_description = nullptr,
1818 : };
1819 1 : prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
1820 4 : CATCH_REQUIRE_THROWS_MATCHES(
1821 : f->new_name()
1822 : , prinbee::logic_error
1823 : , Catch::Matchers::ExceptionMessage(
1824 : "logic_error: field \"no_link\" is marked as having a new name (RENAMED) but it has no f_sub_description to define the new name."));
1825 1 : }
1826 13 : CATCH_END_SECTION()
1827 :
1828 14 : CATCH_START_SECTION("structure_invalid_field: new name with a RENAMED but no field name")
1829 : {
1830 1 : prinbee::struct_description_t rename =
1831 : {
1832 : prinbee::define_description(
1833 : prinbee::FieldName(nullptr)
1834 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_END) // the type is not checked with the RENAMED although it probably should be!
1835 : ),
1836 : };
1837 :
1838 1 : prinbee::struct_description_t description =
1839 : {
1840 3 : prinbee::define_description(
1841 : prinbee::FieldName("name_missing")
1842 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_RENAMED)
1843 : , prinbee::FieldSubDescription(&rename)
1844 : ),
1845 4 : };
1846 :
1847 1 : prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
1848 :
1849 4 : CATCH_REQUIRE_THROWS_MATCHES(
1850 : f->new_name()
1851 : , prinbee::logic_error
1852 : , Catch::Matchers::ExceptionMessage(
1853 : "logic_error: field \"name_missing\" is marked as having a new name (RENAMED) but it has no entries in its f_sub_description defining the new name."));
1854 1 : }
1855 13 : CATCH_END_SECTION()
1856 :
1857 14 : CATCH_START_SECTION("structure_invalid_field: unknown flag")
1858 : {
1859 1 : prinbee::struct_description_t description =
1860 : {
1861 : prinbee::define_description(
1862 : prinbee::FieldName("flags=some_flag/another/foo/bar")
1863 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS16)
1864 : ),
1865 : };
1866 :
1867 1 : prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
1868 :
1869 8 : CATCH_REQUIRE_THROWS_MATCHES(
1870 : f->find_flag_definition("unknown")
1871 : , prinbee::field_not_found
1872 : , Catch::Matchers::ExceptionMessage(
1873 : "prinbee_exception: flag named \"unknown\" not found."));
1874 1 : }
1875 13 : CATCH_END_SECTION()
1876 :
1877 14 : CATCH_START_SECTION("structure_invalid_field: sub-structure indexing out of range")
1878 : {
1879 6 : CATCH_REQUIRE_THROWS_MATCHES(
1880 : prinbee::define_description(
1881 : prinbee::FieldName("structure")
1882 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE)
1883 : )
1884 : , prinbee::invalid_parameter
1885 : , Catch::Matchers::ExceptionMessage(
1886 : "prinbee_exception: this structure field must have a sub-description field."));
1887 :
1888 1 : prinbee::struct_description_t description =
1889 : {
1890 : .f_field_name = "structure",
1891 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE,
1892 : .f_flags = 0,
1893 : .f_default_value = nullptr,
1894 : .f_min_version = prinbee::version_t(),
1895 : .f_max_version = prinbee::version_t(),
1896 : .f_sub_description = nullptr,
1897 : };
1898 :
1899 1 : prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
1900 :
1901 4 : CATCH_REQUIRE_THROWS_MATCHES(
1902 : (*f)[0]
1903 : , prinbee::out_of_bounds
1904 : , Catch::Matchers::ExceptionMessage(
1905 : "prinbee_exception: index (0) is out of bounds since there are no sub-structures."));
1906 :
1907 1 : prinbee::structure::pointer_t s;
1908 1 : f->sub_structures().push_back(s);
1909 :
1910 4 : CATCH_REQUIRE_THROWS_MATCHES(
1911 : (*f)[1]
1912 : , prinbee::out_of_bounds
1913 : , Catch::Matchers::ExceptionMessage(
1914 : "prinbee_exception: index (1) is out of bounds (0..0)"));
1915 1 : }
1916 13 : CATCH_END_SECTION()
1917 :
1918 14 : CATCH_START_SECTION("structure_invalid_field: field does not support a sub-structure")
1919 : {
1920 1 : for(prinbee::struct_type_t type(prinbee::struct_type_t::STRUCT_TYPE_END);
1921 48 : type <= prinbee::struct_type_t::STRUCT_TYPE_RENAMED;
1922 47 : ++type)
1923 : {
1924 47 : switch(type)
1925 : {
1926 1 : case prinbee::struct_type_t::STRUCT_TYPE_MAGIC:
1927 7 : CATCH_REQUIRE_THROWS_MATCHES(
1928 : prinbee::define_description(
1929 : prinbee::FieldName("_magic")
1930 : , prinbee::FieldType(type)
1931 : , prinbee::FieldSubDescription(g_description1)
1932 : )
1933 : , prinbee::invalid_parameter
1934 : , Catch::Matchers::ExceptionMessage(
1935 : "prinbee_exception: this structure field cannot have a sub-description field."));
1936 : break;
1937 :
1938 1 : case prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION:
1939 7 : CATCH_REQUIRE_THROWS_MATCHES(
1940 : prinbee::define_description(
1941 : prinbee::FieldName("_structure_version")
1942 : , prinbee::FieldType(type)
1943 : , prinbee::FieldSubDescription(g_description1)
1944 : )
1945 : , prinbee::invalid_parameter
1946 : , Catch::Matchers::ExceptionMessage(
1947 : "prinbee_exception: this structure field cannot have a sub-description field."));
1948 : break;
1949 :
1950 5 : case prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE:
1951 : case prinbee::struct_type_t::STRUCT_TYPE_ARRAY8:
1952 : case prinbee::struct_type_t::STRUCT_TYPE_ARRAY16:
1953 : case prinbee::struct_type_t::STRUCT_TYPE_ARRAY32:
1954 : case prinbee::struct_type_t::STRUCT_TYPE_RENAMED:
1955 5 : break;
1956 :
1957 7 : case prinbee::struct_type_t::STRUCT_TYPE_BITS8:
1958 : case prinbee::struct_type_t::STRUCT_TYPE_BITS16:
1959 : case prinbee::struct_type_t::STRUCT_TYPE_BITS32:
1960 : case prinbee::struct_type_t::STRUCT_TYPE_BITS64:
1961 : case prinbee::struct_type_t::STRUCT_TYPE_BITS128:
1962 : case prinbee::struct_type_t::STRUCT_TYPE_BITS256:
1963 : case prinbee::struct_type_t::STRUCT_TYPE_BITS512:
1964 49 : CATCH_REQUIRE_THROWS_MATCHES(
1965 : prinbee::define_description(
1966 : prinbee::FieldName("field=bits:3")
1967 : , prinbee::FieldType(type)
1968 : , prinbee::FieldSubDescription(g_description1)
1969 : )
1970 : , prinbee::invalid_parameter
1971 : , Catch::Matchers::ExceptionMessage(
1972 : "prinbee_exception: this structure field cannot have a sub-description field."));
1973 : break;
1974 :
1975 1 : case prinbee::struct_type_t::STRUCT_TYPE_CHAR:
1976 7 : CATCH_REQUIRE_THROWS_MATCHES(
1977 : prinbee::define_description(
1978 : prinbee::FieldName("field=1001")
1979 : , prinbee::FieldType(type)
1980 : , prinbee::FieldSubDescription(g_description1)
1981 : )
1982 : , prinbee::invalid_parameter
1983 : , Catch::Matchers::ExceptionMessage(
1984 : "prinbee_exception: this structure field cannot have a sub-description field."));
1985 : break;
1986 :
1987 32 : default:
1988 224 : CATCH_REQUIRE_THROWS_MATCHES(
1989 : prinbee::define_description(
1990 : prinbee::FieldName(type == prinbee::struct_type_t::STRUCT_TYPE_END ? nullptr : "field")
1991 : , prinbee::FieldType(type)
1992 : , prinbee::FieldSubDescription(g_description1)
1993 : )
1994 : , prinbee::invalid_parameter
1995 : , Catch::Matchers::ExceptionMessage(
1996 : "prinbee_exception: this structure field cannot have a sub-description field."));
1997 : break;
1998 :
1999 : }
2000 : }
2001 : }
2002 13 : CATCH_END_SECTION()
2003 :
2004 14 : CATCH_START_SECTION("structure_invalid_field: name field")
2005 : {
2006 6 : CATCH_REQUIRE_THROWS_MATCHES(
2007 : prinbee::define_description(
2008 : prinbee::FieldName("unwanted_name")
2009 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_END)
2010 : )
2011 : , prinbee::invalid_parameter
2012 : , Catch::Matchers::ExceptionMessage(
2013 : "prinbee_exception: the END structure field cannot have a field name."));
2014 : }
2015 13 : CATCH_END_SECTION()
2016 :
2017 14 : CATCH_START_SECTION("structure_invalid_field: name field")
2018 : {
2019 7 : CATCH_REQUIRE_THROWS_MATCHES(
2020 : prinbee::define_description(
2021 : prinbee::FieldName("inverted_version")
2022 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT32)
2023 : , prinbee::FieldVersion(15, 255, 15, 254)
2024 : )
2025 : , prinbee::invalid_parameter
2026 : , Catch::Matchers::ExceptionMessage(
2027 : "prinbee_exception: this structure field must have a minimum version which is smaller or equal to the maximum version."));
2028 : }
2029 13 : CATCH_END_SECTION()
2030 :
2031 14 : CATCH_START_SECTION("structure_invalid_field: structure version missing or invalid")
2032 : {
2033 6 : CATCH_REQUIRE_THROWS_MATCHES(
2034 : prinbee::define_description(
2035 : prinbee::FieldName("_structure_version")
2036 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
2037 : )
2038 : , prinbee::invalid_parameter
2039 : , Catch::Matchers::ExceptionMessage(
2040 : "prinbee_exception: this structure field must have a version."));
2041 :
2042 7 : CATCH_REQUIRE_THROWS_MATCHES(
2043 : prinbee::define_description(
2044 : prinbee::FieldName("_structure_version")
2045 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
2046 : , prinbee::FieldVersion(0, 0, 65535, 65535) // explicit (same as unspecified); invalid min.
2047 : )
2048 : , prinbee::invalid_parameter
2049 : , Catch::Matchers::ExceptionMessage(
2050 : "prinbee_exception: this structure field must have a version."));
2051 :
2052 7 : CATCH_REQUIRE_THROWS_MATCHES(
2053 : prinbee::define_description(
2054 : prinbee::FieldName("_structure_version")
2055 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
2056 : , prinbee::FieldVersion(3, 7, 123, 456) // invalid max.
2057 : )
2058 : , prinbee::invalid_parameter
2059 : , Catch::Matchers::ExceptionMessage(
2060 : "prinbee_exception: this structure field must have a version."));
2061 :
2062 7 : CATCH_REQUIRE_THROWS_MATCHES(
2063 : prinbee::define_description(
2064 : prinbee::FieldName("_structure_version")
2065 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
2066 : , prinbee::FieldVersion(0, 0, 123, 456) // invalid min. & max.
2067 : )
2068 : , prinbee::invalid_parameter
2069 : , Catch::Matchers::ExceptionMessage(
2070 : "prinbee_exception: this structure field must have a version."));
2071 : }
2072 13 : CATCH_END_SECTION()
2073 :
2074 14 : CATCH_START_SECTION("structure_invalid_field: field validity verifications in define_description() [compile time if defined constexpr]")
2075 : {
2076 6 : CATCH_REQUIRE_THROWS_MATCHES(
2077 : prinbee::define_description(
2078 : prinbee::FieldName(nullptr)
2079 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT512)
2080 : )
2081 : , prinbee::invalid_parameter
2082 : , Catch::Matchers::ExceptionMessage(
2083 : "prinbee_exception: this structure field must have a field name."));
2084 :
2085 6 : CATCH_REQUIRE_THROWS_MATCHES(
2086 : prinbee::define_description(
2087 : prinbee::FieldName("")
2088 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT512)
2089 : )
2090 : , prinbee::invalid_parameter
2091 : , Catch::Matchers::ExceptionMessage(
2092 : "prinbee_exception: this structure field name, \"\" is not considered valid."));
2093 :
2094 101 : for(int i(0); i < 100; ++i)
2095 : {
2096 100 : char name[10];
2097 100 : name[sizeof(name) - 1] = '\0';
2098 1000 : for(std::size_t j(0); j < sizeof(name) - 1; ++j)
2099 : {
2100 900 : switch(rand() % 4)
2101 : {
2102 224 : case 0:
2103 224 : name[j] = rand() % 26 + 'A';
2104 224 : break;
2105 :
2106 233 : case 1:
2107 233 : name[j] = rand() % 26 + 'a';
2108 233 : break;
2109 :
2110 238 : case 2:
2111 238 : if(j == 0)
2112 : {
2113 : // avoid digits as the first character
2114 : //
2115 28 : name[j] = rand() % 26 + 'a';
2116 : }
2117 : else
2118 : {
2119 210 : name[j] = rand() % 10 + '0';
2120 : }
2121 238 : break;
2122 :
2123 205 : case 3:
2124 205 : name[j] = '_';
2125 205 : break;
2126 :
2127 : }
2128 : }
2129 100 : int k(-1);
2130 100 : if(i == 0)
2131 : {
2132 1 : name[0] = rand() % 10 + '0';
2133 : }
2134 : else
2135 : {
2136 99 : k = rand() % (sizeof(name) - 1);
2137 : for(;;)
2138 : {
2139 135 : name[k] = rand() % 255;
2140 135 : if((name[k] < 'A' || name[k] > 'Z')
2141 123 : && (name[k] < 'a' || name[k] > 'z')
2142 112 : && (name[k] < '0' || name[k] > '9')
2143 100 : && name[k] != '_'
2144 100 : && name[k] != '\0')
2145 : {
2146 99 : break;
2147 : }
2148 : }
2149 : }
2150 :
2151 600 : CATCH_REQUIRE_THROWS_MATCHES(
2152 : prinbee::define_description(
2153 : prinbee::FieldName(name)
2154 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT512)
2155 : )
2156 : , prinbee::invalid_parameter
2157 : , Catch::Matchers::ExceptionMessage(
2158 : std::string("prinbee_exception: this structure field name, \"")
2159 : + name
2160 : + "\" is not considered valid."));
2161 : }
2162 : }
2163 13 : CATCH_END_SECTION()
2164 :
2165 : #ifdef _DEBUG
2166 : // these throw ... only happen when debug is turned on
2167 : //
2168 : // i.e. with `mk -t -r` command line option (Release mode),
2169 : // it does not include debug core
2170 : //
2171 14 : CATCH_START_SECTION("structure_invalid_field: validity verifications in contructor")
2172 : {
2173 : {
2174 1 : prinbee::struct_description_t name_missing =
2175 : {
2176 : .f_field_name = nullptr,
2177 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_INT512,
2178 : .f_flags = 0,
2179 : .f_default_value = nullptr,
2180 : .f_min_version = prinbee::version_t(),
2181 : .f_max_version = prinbee::version_t(),
2182 : .f_sub_description = nullptr,
2183 : };
2184 :
2185 5 : CATCH_REQUIRE_THROWS_MATCHES(
2186 : std::make_shared<prinbee::field_t>(&name_missing)
2187 : , prinbee::logic_error
2188 : , Catch::Matchers::ExceptionMessage(
2189 : "logic_error: a field must have a name, null is not valid."));
2190 : }
2191 :
2192 : {
2193 1 : prinbee::struct_description_t empty_name =
2194 : {
2195 : .f_field_name = "",
2196 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_INT512,
2197 : .f_flags = 0,
2198 : .f_default_value = nullptr,
2199 : .f_min_version = prinbee::version_t(),
2200 : .f_max_version = prinbee::version_t(),
2201 : .f_sub_description = nullptr,
2202 : };
2203 :
2204 5 : CATCH_REQUIRE_THROWS_MATCHES(
2205 : std::make_shared<prinbee::field_t>(&empty_name)
2206 : , prinbee::logic_error
2207 : , Catch::Matchers::ExceptionMessage(
2208 : "logic_error: a field must have a name, an empty string (\"\") is not valid."));
2209 : }
2210 :
2211 : {
2212 1 : prinbee::struct_description_t missing_flags =
2213 : {
2214 : .f_field_name = "foo",
2215 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_BITS8,
2216 : .f_flags = 0,
2217 : .f_default_value = nullptr,
2218 : .f_min_version = prinbee::version_t(),
2219 : .f_max_version = prinbee::version_t(),
2220 : .f_sub_description = nullptr,
2221 : };
2222 :
2223 5 : CATCH_REQUIRE_THROWS_MATCHES(
2224 : std::make_shared<prinbee::field_t>(&missing_flags)
2225 : , prinbee::logic_error
2226 : , Catch::Matchers::ExceptionMessage(
2227 : "logic_error: bit field name & definition \"foo\" are not valid."));
2228 : }
2229 :
2230 : {
2231 1 : prinbee::struct_description_t bad_name =
2232 : {
2233 : .f_field_name = "3_bad_names",
2234 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_INT32,
2235 : .f_flags = 0,
2236 : .f_default_value = nullptr,
2237 : .f_min_version = prinbee::version_t(),
2238 : .f_max_version = prinbee::version_t(),
2239 : .f_sub_description = nullptr,
2240 : };
2241 :
2242 5 : CATCH_REQUIRE_THROWS_MATCHES(
2243 : std::make_shared<prinbee::field_t>(&bad_name)
2244 : , prinbee::logic_error
2245 : , Catch::Matchers::ExceptionMessage(
2246 : "logic_error: field name \"3_bad_names\" is not valid (unsupported characters)."));
2247 : }
2248 : }
2249 13 : CATCH_END_SECTION()
2250 : #endif
2251 12 : }
2252 :
2253 :
2254 5 : CATCH_TEST_CASE("structure", "[structure][valid]")
2255 : {
2256 7 : CATCH_START_SECTION("structure: simple structure (fixed size)")
2257 : {
2258 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description1));
2259 :
2260 1 : description->init_buffer();
2261 :
2262 1 : std::uint32_t const count(123);
2263 3 : description->set_uinteger("count", count);
2264 :
2265 1 : std::uint32_t const size(900'000);
2266 3 : description->set_uinteger("size", size);
2267 :
2268 1 : std::int32_t const change(-55);
2269 3 : description->set_integer("change", change);
2270 :
2271 1 : prinbee::reference_t const next(0xff00ff00ff00);
2272 3 : description->set_uinteger("next", next);
2273 :
2274 1 : prinbee::reference_t const previous(0xff11ff11ff11);
2275 3 : description->set_uinteger("previous", previous);
2276 :
2277 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_BLOB);
2278 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(0, 1));
2279 3 : CATCH_REQUIRE(description->get_uinteger("count") == count);
2280 3 : CATCH_REQUIRE(description->get_uinteger("size") == size);
2281 3 : CATCH_REQUIRE(description->get_integer("change") == change);
2282 3 : CATCH_REQUIRE(description->get_uinteger("next") == next);
2283 3 : CATCH_REQUIRE(description->get_uinteger("previous") == previous);
2284 1 : }
2285 6 : CATCH_END_SECTION()
2286 :
2287 7 : CATCH_START_SECTION("structure: structure with a string")
2288 : {
2289 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description2));
2290 :
2291 1 : CATCH_REQUIRE(description->get_static_size() == 0);
2292 :
2293 1 : description->init_buffer();
2294 :
2295 : //description->set_uinteger("_magic", static_cast<uint32_t>(prinbee::dbtype_t::BLOCK_TYPE_DATA));
2296 :
2297 1 : std::uint32_t flags(0x100105);
2298 3 : description->set_uinteger("flags", flags);
2299 :
2300 3 : std::string const name("this is the name we want to include here");
2301 3 : description->set_string("name", name);
2302 :
2303 1 : uint64_t size(1LL << 53);
2304 3 : description->set_uinteger("size", size);
2305 :
2306 1 : uint16_t model(33);
2307 3 : description->set_uinteger("model", model);
2308 :
2309 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::FILE_TYPE_BLOOM_FILTER);
2310 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(15, 10231));
2311 3 : CATCH_REQUIRE(description->get_uinteger("flags") == flags);
2312 3 : CATCH_REQUIRE(description->get_string("name") == name);
2313 3 : CATCH_REQUIRE(description->get_uinteger("size") == size);
2314 3 : CATCH_REQUIRE(description->get_uinteger("model") == model);
2315 1 : }
2316 6 : CATCH_END_SECTION()
2317 :
2318 7 : CATCH_START_SECTION("structure: structure with a bit field")
2319 : {
2320 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description3));
2321 :
2322 1 : CATCH_REQUIRE(description->get_static_size() == 97);
2323 :
2324 1 : description->init_buffer();
2325 :
2326 3 : CATCH_REQUIRE(description->get_version("javascript_version") == prinbee::version_t(7, 3));
2327 :
2328 : //description->set_uinteger("_magic", static_cast<std::uint32_t>(prinbee::dbtype_t::BLOCK_TYPE_DATA));
2329 :
2330 1 : std::uint32_t sub_field(SNAP_CATCH2_NAMESPACE::rand32());
2331 3 : description->set_uinteger("sub_field", sub_field);
2332 :
2333 1 : prinbee::int512_t large_number;
2334 1 : SNAP_CATCH2_NAMESPACE::rand512(large_number);
2335 3 : description->set_large_integer("data", large_number);
2336 :
2337 1 : std::uint32_t major(SNAP_CATCH2_NAMESPACE::rand32());
2338 1 : std::uint32_t minor(SNAP_CATCH2_NAMESPACE::rand32());
2339 1 : std::uint32_t release(SNAP_CATCH2_NAMESPACE::rand32());
2340 1 : std::uint32_t build(SNAP_CATCH2_NAMESPACE::rand32());
2341 3 : description->set_uinteger("software_version.major", major);
2342 3 : description->set_uinteger("software_version.minor", minor);
2343 3 : description->set_uinteger("software_version.release", release);
2344 3 : description->set_uinteger("software_version.build", build);
2345 :
2346 3 : description->set_version("javascript_version", prinbee::version_t(12, 8));
2347 :
2348 1 : std::uint32_t const null_value(rand() & 1);
2349 3 : description->set_bits("eight_bits.null", null_value);
2350 :
2351 1 : std::uint32_t const advance_value(rand() & 15);
2352 3 : description->set_bits("eight_bits.advance", advance_value);
2353 :
2354 1 : std::uint32_t const efficient_value(rand() & 3);
2355 3 : description->set_bits("eight_bits.efficient", efficient_value);
2356 :
2357 1 : std::uint32_t const sign_value(rand() & 1);
2358 3 : description->set_bits("eight_bits.sign", sign_value);
2359 :
2360 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_FREE_SPACE);
2361 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(25, 312));
2362 3 : CATCH_REQUIRE(description->get_uinteger("_structure_version") == prinbee::version_t(25, 312).to_binary());
2363 3 : CATCH_REQUIRE(description->get_uinteger("sub_field") == sub_field);
2364 3 : CATCH_REQUIRE(description->get_large_integer("data") == large_number);
2365 3 : CATCH_REQUIRE(description->get_uinteger("software_version.major") == major);
2366 3 : CATCH_REQUIRE(description->get_uinteger("software_version.minor") == minor);
2367 3 : CATCH_REQUIRE(description->get_uinteger("software_version.release") == release);
2368 3 : CATCH_REQUIRE(description->get_uinteger("software_version.build") == build);
2369 3 : CATCH_REQUIRE(description->get_structure("software_version") != nullptr); // we do not have the pointer, but it cannot be nullptr
2370 3 : CATCH_REQUIRE(description->get_version("javascript_version") == prinbee::version_t(12, 8));
2371 3 : CATCH_REQUIRE(description->get_bits("eight_bits.null") == null_value);
2372 3 : CATCH_REQUIRE(description->get_bits("eight_bits.advance") == advance_value);
2373 3 : CATCH_REQUIRE(description->get_bits("eight_bits.efficient") == efficient_value);
2374 3 : CATCH_REQUIRE(description->get_bits("eight_bits.sign") == sign_value);
2375 :
2376 : // the get_field() allows you to search for a specific flag in a field and
2377 : // you get the field pointer--not too sure that makes sense, but it works...
2378 : //
2379 3 : prinbee::field_t::pointer_t eight_bits(description->get_field("eight_bits"));
2380 3 : CATCH_REQUIRE(description->get_field("eight_bits.null") == eight_bits);
2381 3 : CATCH_REQUIRE(description->get_field("eight_bits.advance") == eight_bits);
2382 3 : CATCH_REQUIRE(description->get_field("eight_bits.efficient") == eight_bits);
2383 3 : CATCH_REQUIRE(description->get_field("eight_bits.sign") == eight_bits);
2384 1 : }
2385 6 : CATCH_END_SECTION()
2386 :
2387 7 : CATCH_START_SECTION("structure: structure with a variable sub-structure")
2388 : {
2389 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description5));
2390 :
2391 : // uninitialized structures have no buffer
2392 : //
2393 8 : CATCH_REQUIRE_THROWS_MATCHES(
2394 : description->get_field("name")
2395 : , prinbee::logic_error
2396 : , Catch::Matchers::ExceptionMessage(
2397 : "logic_error: trying to access a structure field when the f_buffer pointer is still null."));
2398 :
2399 : // the BUFFER8 in the sub-structure makes this structure dynamic
2400 : // (and later the P8STRING too)
2401 : //
2402 1 : CATCH_REQUIRE(description->get_static_size() == 0UL);
2403 1 : CATCH_REQUIRE(description->get_current_size() == 52UL);
2404 :
2405 1 : description->init_buffer();
2406 :
2407 : // to change a VERSION type, we use the set_uinteger() function
2408 : // but we must make sure that the structure version cannot be
2409 : // updated (this is a read-only field)
2410 : //
2411 7 : CATCH_REQUIRE_THROWS_MATCHES(
2412 : description->set_uinteger("_structure_version", SNAP_CATCH2_NAMESPACE::rand32())
2413 : , prinbee::type_mismatch
2414 : , Catch::Matchers::ExceptionMessage(
2415 : "prinbee_exception: this field type is \"STRUCTURE_VERSION\""
2416 : " but we expected one of \"BITS8, BITS16, BITS32, BITS64, OID, REFERENCE, UINT8, UINT16, UINT32, UINT64, VERSION\"."));
2417 :
2418 1 : std::int64_t const sub_field(SNAP_CATCH2_NAMESPACE::rand64());
2419 3 : description->set_integer("sub_field", sub_field);
2420 1 : CATCH_REQUIRE(description->get_current_size() == 52UL);
2421 :
2422 1 : prinbee::int512_t large_number;
2423 1 : SNAP_CATCH2_NAMESPACE::rand512(large_number);
2424 1 : if((large_number.f_value[1] & (1UL << 63)) == 0)
2425 : {
2426 1 : large_number.f_value[2] = 0;
2427 1 : large_number.f_value[3] = 0;
2428 1 : large_number.f_value[4] = 0;
2429 1 : large_number.f_value[5] = 0;
2430 1 : large_number.f_value[6] = 0;
2431 1 : large_number.f_high_value = 0;
2432 : }
2433 : else
2434 : {
2435 0 : large_number.f_value[2] = -1;
2436 0 : large_number.f_value[3] = -1;
2437 0 : large_number.f_value[4] = -1;
2438 0 : large_number.f_value[5] = -1;
2439 0 : large_number.f_value[6] = -1;
2440 0 : large_number.f_high_value = -1;
2441 : }
2442 3 : description->set_large_integer("data", large_number);
2443 1 : CATCH_REQUIRE(description->get_current_size() == 52UL);
2444 :
2445 1 : std::uint8_t const version_size((rand() & 7) + 1);
2446 3 : prinbee::buffer_t version_parts(version_size);
2447 8 : for(std::uint8_t idx(0); idx < version_size; ++idx)
2448 : {
2449 7 : version_parts[idx] = rand();
2450 : }
2451 3 : description->set_uinteger("early_version.size", version_size);
2452 1 : CATCH_REQUIRE(description->get_current_size() == 52UL);
2453 3 : description->set_buffer("early_version.parts", version_parts);
2454 1 : CATCH_REQUIRE(description->get_current_size() == 52UL + version_size);
2455 :
2456 1 : std::uint32_t const bulk_value(rand() & 15);
2457 3 : description->set_bits("sixteen_bits.bulk", bulk_value);
2458 1 : CATCH_REQUIRE(description->get_current_size() == 52UL + version_size);
2459 :
2460 1 : std::uint32_t const more_value(rand() & 15);
2461 3 : description->set_bits("sixteen_bits.more", more_value);
2462 1 : CATCH_REQUIRE(description->get_current_size() == 52UL + version_size);
2463 :
2464 1 : std::uint32_t const raise_value(rand() & 1);
2465 3 : description->set_bits("sixteen_bits.raise", raise_value);
2466 1 : CATCH_REQUIRE(description->get_current_size() == 52UL + version_size);
2467 :
2468 1 : std::uint32_t const signal_value(rand() & 127);
2469 3 : description->set_bits("sixteen_bits.signal", signal_value);
2470 1 : CATCH_REQUIRE(description->get_current_size() == 52UL + version_size);
2471 :
2472 : //description->set_string("tag", ...); -- keep the default value instead
2473 :
2474 1 : std::string const name(SNAP_CATCH2_NAMESPACE::random_string(1, 255));
2475 3 : description->set_string("name", name);
2476 1 : CATCH_REQUIRE(description->get_current_size() == 52UL + version_size + name.length());
2477 :
2478 : // field must be given a name
2479 : //
2480 5 : CATCH_REQUIRE_THROWS_MATCHES(
2481 : description->get_uinteger(std::string())
2482 : , prinbee::logic_error
2483 : , Catch::Matchers::ExceptionMessage(
2484 : "logic_error: called structure::get_field() with an empty field name."));
2485 :
2486 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
2487 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(405, 119));
2488 3 : CATCH_REQUIRE(description->get_integer("sub_field") == sub_field);
2489 3 : CATCH_REQUIRE(description->get_large_integer("data") == large_number);
2490 3 : CATCH_REQUIRE(description->get_uinteger("early_version.size") == version_size);
2491 3 : CATCH_REQUIRE(description->get_buffer("early_version.parts") == version_parts);
2492 3 : CATCH_REQUIRE(description->get_bits("sixteen_bits.bulk") == bulk_value);
2493 3 : CATCH_REQUIRE(description->get_bits("sixteen_bits.more") == more_value);
2494 3 : CATCH_REQUIRE(description->get_bits("sixteen_bits.raise") == raise_value);
2495 3 : CATCH_REQUIRE(description->get_bits("sixteen_bits.signal") == signal_value);
2496 3 : CATCH_REQUIRE(description->get_string("tag") == "image"); // from the default value
2497 3 : CATCH_REQUIRE(description->get_string("name") == name);
2498 :
2499 : // the version_parts buffer change:
2500 : // 1. same size
2501 : // 2. grow
2502 : // 3. shrink back
2503 : //
2504 11 : for(int count(0); count < 10; ++count)
2505 : {
2506 80 : for(std::uint8_t idx(0); idx < version_size; ++idx)
2507 : {
2508 70 : version_parts[idx] = rand();
2509 : }
2510 : //description->set_uinteger("early_version.size", version_size);
2511 30 : description->set_buffer("early_version.parts", version_parts);
2512 30 : CATCH_REQUIRE(description->get_uinteger("early_version.size") == version_size);
2513 30 : CATCH_REQUIRE(description->get_buffer("early_version.parts") == version_parts);
2514 : }
2515 1 : std::size_t buffer_size(version_size);
2516 11 : for(int count(0); count < 10; ++count)
2517 : {
2518 10 : buffer_size += rand() % 10 + 1;
2519 10 : version_parts.resize(buffer_size);
2520 418 : for(std::uint8_t idx(0); idx < buffer_size; ++idx)
2521 : {
2522 408 : version_parts[idx] = rand();
2523 : }
2524 30 : description->set_uinteger("early_version.size", buffer_size);
2525 30 : description->set_buffer("early_version.parts", version_parts);
2526 30 : CATCH_REQUIRE(description->get_uinteger("early_version.size") == buffer_size);
2527 30 : CATCH_REQUIRE(description->get_buffer("early_version.parts") == version_parts);
2528 : }
2529 11 : for(int count(0); count < 10; ++count)
2530 : {
2531 10 : buffer_size -= rand() % 10 + 1;
2532 10 : if(static_cast<ssize_t>(buffer_size) <= 0)
2533 : {
2534 0 : break;
2535 : }
2536 10 : version_parts.resize(buffer_size);
2537 368 : for(std::uint8_t idx(0); idx < buffer_size; ++idx)
2538 : {
2539 358 : version_parts[idx] = rand();
2540 : }
2541 30 : description->set_uinteger("early_version.size", buffer_size);
2542 30 : description->set_buffer("early_version.parts", version_parts);
2543 30 : CATCH_REQUIRE(description->get_uinteger("early_version.size") == buffer_size);
2544 30 : CATCH_REQUIRE(description->get_buffer("early_version.parts") == version_parts);
2545 : }
2546 1 : }
2547 6 : CATCH_END_SECTION()
2548 :
2549 7 : CATCH_START_SECTION("structure: structure with four types of strings")
2550 : {
2551 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description6));
2552 :
2553 : // the strings make this structure dynamic
2554 : //
2555 1 : CATCH_REQUIRE(description->get_static_size() == 0UL);
2556 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 1UL + 0UL + 2UL + 0UL + 4UL + 0UL + 15UL);
2557 :
2558 1 : description->init_buffer();
2559 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 1UL + 5UL + 2UL + 62UL + 4UL + 98UL + 15UL);
2560 :
2561 7 : CATCH_REQUIRE_THROWS_MATCHES(
2562 : description->set_uinteger("_magic", SNAP_CATCH2_NAMESPACE::rand32())
2563 : , prinbee::type_mismatch
2564 : , Catch::Matchers::ExceptionMessage(
2565 : "prinbee_exception: this field type is \"MAGIC\""
2566 : " but we expected one of \"BITS8, BITS16, BITS32, BITS64, OID, REFERENCE, UINT8, UINT16, UINT32, UINT64, VERSION\"."));
2567 :
2568 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
2569 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(15'345, 2'341));
2570 :
2571 3 : CATCH_REQUIRE(description->get_string("name") == "Henri");
2572 1 : std::string const name(SNAP_CATCH2_NAMESPACE::random_string(1, 255));
2573 3 : description->set_string("name", name);
2574 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 1UL + name.length() + 2UL + 62UL + 4UL + 98UL + 15UL);
2575 3 : CATCH_REQUIRE(description->get_string("name") == name);
2576 :
2577 3 : CATCH_REQUIRE(description->get_string("description") == "King who fell from a horse and had a rotting foot as a result.");
2578 1 : std::string const description_field(SNAP_CATCH2_NAMESPACE::random_string(256, 3'000));
2579 3 : description->set_string("description", description_field);
2580 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 1UL + name.length() + 2UL + description_field.length() + 4UL + 98UL + 15UL);
2581 3 : CATCH_REQUIRE(description->get_string("description") == description_field);
2582 :
2583 3 : CATCH_REQUIRE(description->get_string("essay") == "King who killed his wife to marry another. Later wives were lucky that the divorce was \"invented\".");
2584 3 : CATCH_REQUIRE(description->get_string("dissertation") == "King who killed his wife to marry another. Later wives were lucky that the divorce was \"invented\".");
2585 1 : std::string const essay(SNAP_CATCH2_NAMESPACE::random_string(1'000, 250'000));
2586 3 : description->set_string("essay", essay);
2587 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 1UL + name.length() + 2UL + description_field.length() + 4UL + essay.length() + 15UL);
2588 3 : CATCH_REQUIRE(description->get_string("essay") == essay);
2589 3 : CATCH_REQUIRE(description->get_string("dissertation") == essay);
2590 :
2591 1 : std::string const dissertation(SNAP_CATCH2_NAMESPACE::random_string(1'000, 250'000));
2592 3 : description->set_string("dissertation", dissertation);
2593 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 1UL + name.length() + 2UL + description_field.length() + 4UL + dissertation.length() + 15UL);
2594 3 : CATCH_REQUIRE(description->get_string("dissertation") == dissertation);
2595 3 : CATCH_REQUIRE(description->get_string("essay") == dissertation);
2596 :
2597 5 : description->set_string("tag", "kingdom");
2598 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 1UL + name.length() + 2UL + description_field.length() + 4UL + dissertation.length() + 15UL);
2599 3 : CATCH_REQUIRE(description->get_string("tag") == "kingdom");
2600 1 : }
2601 6 : CATCH_END_SECTION()
2602 5 : }
2603 :
2604 :
2605 1 : CATCH_TEST_CASE("structure_get_set", "[structure][valid]")
2606 : {
2607 3 : CATCH_START_SECTION("structure: structure get/set functions")
2608 : {
2609 : typedef std::uint32_t valid_func_t;
2610 :
2611 1 : constexpr valid_func_t VALID_FUNC_FLAG = 0x0001;
2612 1 : constexpr valid_func_t VALID_FUNC_BITS = 0x0002;
2613 1 : constexpr valid_func_t VALID_FUNC_INTEGER = 0x0004;
2614 1 : constexpr valid_func_t VALID_FUNC_UINTEGER = 0x0008;
2615 1 : constexpr valid_func_t VALID_FUNC_LARGE_INTEGER = 0x0010;
2616 1 : constexpr valid_func_t VALID_FUNC_LARGE_UINTEGER = 0x0020;
2617 1 : constexpr valid_func_t VALID_FUNC_FLOAT32 = 0x0040;
2618 1 : constexpr valid_func_t VALID_FUNC_FLOAT64 = 0x0080;
2619 1 : constexpr valid_func_t VALID_FUNC_FLOAT128 = 0x0100;
2620 1 : constexpr valid_func_t VALID_FUNC_VARIABLE_SIZE = 0x0200;
2621 :
2622 : struct type_to_test_t
2623 : {
2624 : valid_func_t f_valid_func = 0;
2625 : prinbee::struct_type_t f_type = prinbee::struct_type_t::STRUCT_TYPE_VOID;
2626 : std::uint16_t f_mask_size = 512;
2627 : };
2628 :
2629 1 : type_to_test_t const type_to_test[] =
2630 : {
2631 : {
2632 : .f_valid_func = 0,
2633 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_VOID,
2634 : .f_mask_size = 512,
2635 : },
2636 : {
2637 : .f_valid_func = VALID_FUNC_FLAG | VALID_FUNC_BITS | VALID_FUNC_UINTEGER | VALID_FUNC_LARGE_UINTEGER,
2638 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_BITS8,
2639 : .f_mask_size = 8,
2640 : },
2641 : {
2642 : .f_valid_func = VALID_FUNC_FLAG | VALID_FUNC_BITS | VALID_FUNC_UINTEGER | VALID_FUNC_LARGE_UINTEGER,
2643 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_BITS16,
2644 : .f_mask_size = 16,
2645 : },
2646 : {
2647 : .f_valid_func = VALID_FUNC_FLAG | VALID_FUNC_BITS | VALID_FUNC_UINTEGER | VALID_FUNC_LARGE_UINTEGER,
2648 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_BITS32,
2649 : .f_mask_size = 32,
2650 : },
2651 : {
2652 : .f_valid_func = VALID_FUNC_FLAG | VALID_FUNC_BITS | VALID_FUNC_UINTEGER | VALID_FUNC_LARGE_UINTEGER,
2653 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_BITS64,
2654 : .f_mask_size = 64,
2655 : },
2656 : {
2657 : .f_valid_func = VALID_FUNC_FLAG | VALID_FUNC_LARGE_UINTEGER,
2658 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_BITS128,
2659 : .f_mask_size = 128,
2660 : },
2661 : {
2662 : .f_valid_func = VALID_FUNC_FLAG | VALID_FUNC_LARGE_UINTEGER,
2663 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_BITS256,
2664 : .f_mask_size = 256,
2665 : },
2666 : {
2667 : .f_valid_func = VALID_FUNC_FLAG | VALID_FUNC_LARGE_UINTEGER,
2668 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_BITS512,
2669 : .f_mask_size = 512,
2670 : },
2671 : {
2672 : .f_valid_func = VALID_FUNC_INTEGER | VALID_FUNC_LARGE_INTEGER,
2673 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_INT8,
2674 : .f_mask_size = 8,
2675 : },
2676 : {
2677 : .f_valid_func = VALID_FUNC_UINTEGER | VALID_FUNC_LARGE_UINTEGER,
2678 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_UINT8,
2679 : .f_mask_size = 8,
2680 : },
2681 : {
2682 : .f_valid_func = VALID_FUNC_INTEGER | VALID_FUNC_LARGE_INTEGER,
2683 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_INT16,
2684 : .f_mask_size = 16,
2685 : },
2686 : {
2687 : .f_valid_func = VALID_FUNC_UINTEGER | VALID_FUNC_LARGE_UINTEGER,
2688 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_UINT16,
2689 : .f_mask_size = 16,
2690 : },
2691 : {
2692 : .f_valid_func = VALID_FUNC_INTEGER | VALID_FUNC_LARGE_INTEGER,
2693 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_INT32,
2694 : .f_mask_size = 32,
2695 : },
2696 : {
2697 : .f_valid_func = VALID_FUNC_UINTEGER | VALID_FUNC_LARGE_UINTEGER,
2698 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_UINT32,
2699 : .f_mask_size = 32,
2700 : },
2701 : {
2702 : .f_valid_func = VALID_FUNC_INTEGER | VALID_FUNC_LARGE_INTEGER,
2703 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_INT64,
2704 : .f_mask_size = 64,
2705 : },
2706 : {
2707 : .f_valid_func = VALID_FUNC_UINTEGER | VALID_FUNC_LARGE_UINTEGER,
2708 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_UINT64,
2709 : .f_mask_size = 64,
2710 : },
2711 : {
2712 : .f_valid_func = VALID_FUNC_LARGE_INTEGER,
2713 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_INT128,
2714 : .f_mask_size = 128,
2715 : },
2716 : {
2717 : .f_valid_func = VALID_FUNC_LARGE_UINTEGER,
2718 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_UINT128,
2719 : .f_mask_size = 128,
2720 : },
2721 : {
2722 : .f_valid_func = VALID_FUNC_LARGE_INTEGER,
2723 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_INT256,
2724 : .f_mask_size = 256,
2725 : },
2726 : {
2727 : .f_valid_func = VALID_FUNC_LARGE_UINTEGER,
2728 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_UINT256,
2729 : .f_mask_size = 256,
2730 : },
2731 : {
2732 : .f_valid_func = VALID_FUNC_LARGE_INTEGER,
2733 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_INT512,
2734 : .f_mask_size = 512,
2735 : },
2736 : {
2737 : .f_valid_func = VALID_FUNC_LARGE_UINTEGER,
2738 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_UINT512,
2739 : .f_mask_size = 512,
2740 : },
2741 : {
2742 : .f_valid_func = VALID_FUNC_FLOAT32,
2743 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_FLOAT32,
2744 : .f_mask_size = 32,
2745 : },
2746 : {
2747 : .f_valid_func = VALID_FUNC_FLOAT64,
2748 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_FLOAT64,
2749 : .f_mask_size = 64,
2750 : },
2751 : {
2752 : .f_valid_func = VALID_FUNC_FLOAT128,
2753 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_FLOAT128,
2754 : .f_mask_size = 128,
2755 : },
2756 : {
2757 : .f_valid_func = VALID_FUNC_VARIABLE_SIZE,
2758 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_CHAR,
2759 : .f_mask_size = 512,
2760 : },
2761 : {
2762 : .f_valid_func = VALID_FUNC_VARIABLE_SIZE,
2763 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_P8STRING,
2764 : .f_mask_size = 512,
2765 : },
2766 : {
2767 : .f_valid_func = VALID_FUNC_VARIABLE_SIZE,
2768 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_P16STRING,
2769 : .f_mask_size = 512,
2770 : },
2771 : {
2772 : .f_valid_func = VALID_FUNC_VARIABLE_SIZE,
2773 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_P32STRING,
2774 : .f_mask_size = 512,
2775 : },
2776 : };
2777 : // STRUCT_TYPE_MAGIC, // CHAR=4
2778 : // STRUCT_TYPE_STRUCTURE_VERSION, // UINT16:UINT16 (Major:Minor) -- version of the structure.cpp/h description
2779 : // STRUCT_TYPE_VERSION, // UINT16:UINT16 (Major:Minor)
2780 : //
2781 : // STRUCT_TYPE_REFERENCE, // UINT64 to another location in the file (offset 0 is start of file)
2782 : // STRUCT_TYPE_OID, // UINT64 similar to a REFERENCE, but points to the TIND/INDR blocks (sizeof(OID) == sizeof(REFERENCE) must be true)
2783 :
2784 30 : for(auto const & t : type_to_test)
2785 : {
2786 : //prinbee::int512_t integer;
2787 : //SNAP_CATCH2_NAMESPACE::rand512(integer);
2788 : //std::string string(SNAP_CATCH2_NAMESPACE::random_string(1, 255));
2789 : //long double floating_point(drand48() * 1000.0L);
2790 :
2791 29 : char const * field_name = "test_field";
2792 29 : if((t.f_valid_func & VALID_FUNC_FLAG) != 0)
2793 : {
2794 7 : field_name = "test_field=on/color:3/valid/side:2";
2795 : }
2796 22 : else if(t.f_type == prinbee::struct_type_t::STRUCT_TYPE_CHAR)
2797 : {
2798 1 : field_name = "test_field=32";
2799 : }
2800 :
2801 29 : prinbee::struct_description_t field_descriptions[] =
2802 : {
2803 : {
2804 : .f_field_name = "_magic",
2805 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_MAGIC,
2806 : .f_flags = 0,
2807 : .f_default_value = prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_BLOB),
2808 : .f_min_version = prinbee::version_t(),
2809 : .f_max_version = prinbee::max_version(),
2810 : .f_sub_description = nullptr,
2811 : },
2812 : {
2813 : .f_field_name = "_structure_version",
2814 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION,
2815 : .f_flags = 0,
2816 : .f_default_value = nullptr,
2817 : .f_min_version = prinbee::version_t(3, 7),
2818 : .f_max_version = prinbee::max_version(),
2819 : .f_sub_description = nullptr,
2820 : },
2821 : {
2822 : .f_field_name = field_name,
2823 29 : .f_type = t.f_type,
2824 : .f_flags = 0,
2825 : .f_default_value = nullptr,
2826 : .f_min_version = prinbee::version_t(),
2827 : .f_max_version = prinbee::max_version(),
2828 : .f_sub_description = nullptr,
2829 : },
2830 : {
2831 : .f_field_name = nullptr,
2832 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_END,
2833 : .f_flags = 0,
2834 : .f_default_value = nullptr,
2835 : .f_min_version = prinbee::version_t(),
2836 : .f_max_version = prinbee::version_t(),
2837 : .f_sub_description = nullptr,
2838 : },
2839 29 : };
2840 :
2841 29 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(field_descriptions));
2842 29 : description->init_buffer();
2843 :
2844 29 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_BLOB);
2845 87 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(3, 7));
2846 :
2847 : // the integer functions below check the size and throw a different
2848 : // out_of_range error for parameters with a variable size such as
2849 : // CHAR and P8STRING
2850 : //
2851 29 : std::string variable_size_errmsg;
2852 29 : if((t.f_valid_func & VALID_FUNC_VARIABLE_SIZE) != 0)
2853 : {
2854 4 : std::string const field_type(prinbee::to_string(t.f_type));
2855 4 : int size(-10);
2856 130 : for(auto const & fi : g_field_info)
2857 : {
2858 130 : if(fi.f_type_name == field_type)
2859 : {
2860 4 : size = fi.f_field_size;
2861 4 : break;
2862 : }
2863 : }
2864 4 : variable_size_errmsg = "out_of_range: value ("
2865 8 : + std::to_string(t.f_type == prinbee::struct_type_t::STRUCT_TYPE_CHAR ? 32 : 0)
2866 16 : + ") and type ("
2867 16 : + prinbee::to_string(t.f_type)
2868 16 : + ") sizes do not correspond (expected size: "
2869 16 : + std::to_string(size)
2870 12 : + ").";
2871 4 : }
2872 :
2873 : // get_flag() function
2874 : //
2875 29 : prinbee::field_t::pointer_t f;
2876 29 : if((t.f_valid_func & VALID_FUNC_FLAG) != 0)
2877 : {
2878 21 : prinbee::flag_definition::pointer_t flag(description->get_flag("test_field.on", f));
2879 7 : CATCH_REQUIRE(flag->full_name() == "test_field.on");
2880 7 : CATCH_REQUIRE(flag->field_name() == "test_field");
2881 7 : CATCH_REQUIRE(flag->flag_name() == "on");
2882 7 : CATCH_REQUIRE(flag->pos() == 0);
2883 7 : CATCH_REQUIRE(flag->size() == 1);
2884 7 : CATCH_REQUIRE(flag->mask() == 1);
2885 :
2886 21 : flag = description->get_flag("test_field.color", f);
2887 7 : CATCH_REQUIRE(flag->full_name() == "test_field.color");
2888 7 : CATCH_REQUIRE(flag->field_name() == "test_field");
2889 7 : CATCH_REQUIRE(flag->flag_name() == "color");
2890 7 : CATCH_REQUIRE(flag->pos() == 1);
2891 7 : CATCH_REQUIRE(flag->size() == 3);
2892 7 : CATCH_REQUIRE(flag->mask() == 0xe);
2893 :
2894 21 : flag = description->get_flag("test_field.valid", f);
2895 7 : CATCH_REQUIRE(flag->full_name() == "test_field.valid");
2896 7 : CATCH_REQUIRE(flag->field_name() == "test_field");
2897 7 : CATCH_REQUIRE(flag->flag_name() == "valid");
2898 7 : CATCH_REQUIRE(flag->pos() == 4);
2899 7 : CATCH_REQUIRE(flag->size() == 1);
2900 7 : CATCH_REQUIRE(flag->mask() == 0x10);
2901 :
2902 21 : flag = description->get_flag("test_field.side", f);
2903 7 : CATCH_REQUIRE(flag->full_name() == "test_field.side");
2904 7 : CATCH_REQUIRE(flag->field_name() == "test_field");
2905 7 : CATCH_REQUIRE(flag->flag_name() == "side");
2906 7 : CATCH_REQUIRE(flag->pos() == 5);
2907 7 : CATCH_REQUIRE(flag->size() == 2);
2908 7 : CATCH_REQUIRE(flag->mask() == 0x60);
2909 7 : }
2910 : else
2911 : {
2912 176 : CATCH_REQUIRE_THROWS_MATCHES(
2913 : description->get_flag(field_name, f)
2914 : , prinbee::field_not_found
2915 : , Catch::Matchers::ExceptionMessage(
2916 : "prinbee_exception: flag named \""
2917 : + std::string(field_name)
2918 : + "\" must at least include a field name and a flag name."));
2919 : }
2920 :
2921 : // get_bits()/set_bits() functions
2922 : //
2923 29 : if((t.f_valid_func & VALID_FUNC_FLAG) != 0)
2924 : {
2925 7 : if((t.f_valid_func & VALID_FUNC_BITS) != 0)
2926 : {
2927 36 : for(int v(0); v < 8; ++v)
2928 : {
2929 96 : description->set_bits("test_field.on", v & 1);
2930 96 : CATCH_REQUIRE(description->get_bits("test_field.on") == (v & 1));
2931 :
2932 96 : description->set_bits("test_field.color", v & 7);
2933 96 : CATCH_REQUIRE(description->get_bits("test_field.color") == (v & 7));
2934 :
2935 96 : description->set_bits("test_field.valid", v & 1);
2936 96 : CATCH_REQUIRE(description->get_bits("test_field.valid") == (v & 1));
2937 :
2938 96 : description->set_bits("test_field.side", v & 3);
2939 96 : CATCH_REQUIRE(description->get_bits("test_field.side") == (v & 3));
2940 : }
2941 : }
2942 : else
2943 : {
2944 : // these BITSxxx are not yet fully implemented
2945 : // (i.e. bits in large integers)
2946 : //
2947 15 : CATCH_REQUIRE_THROWS_MATCHES(
2948 : description->set_bits("test_field.on", rand() & 1)
2949 : , prinbee::type_mismatch
2950 : , Catch::Matchers::ExceptionMessage(
2951 : "prinbee_exception: this field type is \""
2952 : + prinbee::to_string(t.f_type)
2953 : + "\" but we expected one of"
2954 : " \"BITS8, BITS16, BITS32, BITS64\"."));
2955 :
2956 15 : CATCH_REQUIRE_THROWS_MATCHES(
2957 : description->get_bits("test_field.on")
2958 : , prinbee::type_mismatch
2959 : , Catch::Matchers::ExceptionMessage(
2960 : "prinbee_exception: this field type is \""
2961 : + prinbee::to_string(t.f_type)
2962 : + "\" but we expected one of"
2963 : " \"BITS8, BITS16, BITS32, BITS64\"."));
2964 : }
2965 : }
2966 : else
2967 : {
2968 154 : CATCH_REQUIRE_THROWS_MATCHES(
2969 : description->set_bits("test_field", rand())
2970 : , prinbee::field_not_found
2971 : , Catch::Matchers::ExceptionMessage(
2972 : "prinbee_exception: flag named \"test_field\" must at least include a field name and a flag name."));
2973 :
2974 154 : CATCH_REQUIRE_THROWS_MATCHES(
2975 : description->get_bits("test_field")
2976 : , prinbee::field_not_found
2977 : , Catch::Matchers::ExceptionMessage(
2978 : "prinbee_exception: flag named \"test_field\" must at least include a field name and a flag name."));
2979 : }
2980 :
2981 : // get_uinteger()/set_uinteger()
2982 : //
2983 29 : if((t.f_valid_func & VALID_FUNC_UINTEGER) != 0)
2984 : {
2985 88 : for(int count(0); count < 10; ++count)
2986 : {
2987 80 : std::uint64_t v(0);
2988 80 : SNAP_CATCH2_NAMESPACE::random(v);
2989 240 : description->set_uinteger(field_name, v);
2990 80 : std::uint64_t const r(v & (((static_cast<std::uint64_t>(1) << (t.f_mask_size - 1)) << 1) - 1));
2991 240 : CATCH_REQUIRE(description->get_uinteger(field_name) == r);
2992 : }
2993 : }
2994 21 : else if((t.f_valid_func & VALID_FUNC_VARIABLE_SIZE) != 0)
2995 : {
2996 4 : std::uint64_t v(0);
2997 4 : SNAP_CATCH2_NAMESPACE::random(v);
2998 20 : CATCH_REQUIRE_THROWS_MATCHES(
2999 : description->set_uinteger("test_field", v)
3000 : , prinbee::out_of_range
3001 : , Catch::Matchers::ExceptionMessage(variable_size_errmsg));
3002 :
3003 20 : CATCH_REQUIRE_THROWS_MATCHES(
3004 : description->get_uinteger("test_field")
3005 : , prinbee::out_of_range
3006 : , Catch::Matchers::ExceptionMessage(variable_size_errmsg));
3007 : }
3008 : else
3009 : {
3010 17 : std::uint64_t v(0);
3011 17 : SNAP_CATCH2_NAMESPACE::random(v);
3012 85 : CATCH_REQUIRE_THROWS_MATCHES(
3013 : description->set_uinteger("test_field", v)
3014 : , prinbee::type_mismatch
3015 : , Catch::Matchers::ExceptionMessage(
3016 : "prinbee_exception: this field type is \""
3017 : + prinbee::to_string(t.f_type)
3018 : + "\""
3019 : " but we expected one of \"BITS8, BITS16, BITS32, BITS64, OID, REFERENCE, UINT8, UINT16, UINT32, UINT64, VERSION\"."));
3020 :
3021 85 : CATCH_REQUIRE_THROWS_MATCHES(
3022 : description->get_uinteger("test_field")
3023 : , prinbee::type_mismatch
3024 : , Catch::Matchers::ExceptionMessage(
3025 : "prinbee_exception: this field type is \""
3026 : + prinbee::to_string(t.f_type)
3027 : + "\""
3028 : " but we expected one of \"BITS8, BITS16, BITS32, BITS64, MAGIC, OID, REFERENCE, STRUCTURE_VERSION, UINT8, UINT16, UINT32, UINT64, VERSION\"."));
3029 : }
3030 :
3031 : // get_integer()/set_integer()
3032 : //
3033 29 : if((t.f_valid_func & VALID_FUNC_INTEGER) != 0)
3034 : {
3035 44 : for(int count(0); count < 10; ++count)
3036 : {
3037 40 : std::int64_t v(0);
3038 40 : SNAP_CATCH2_NAMESPACE::random(v);
3039 120 : description->set_integer(field_name, v);
3040 40 : std::int64_t r(v & (((static_cast<std::uint64_t>(1) << (t.f_mask_size - 1)) << 1) - 1));
3041 40 : if(t.f_mask_size != 64
3042 30 : && (r & (static_cast<std::uint64_t>(1) << (t.f_mask_size - 1))) != 0)
3043 : {
3044 : // sign extend the value if less than 64 bits
3045 : //
3046 11 : r |= static_cast<std::int64_t>(-1) << t.f_mask_size;
3047 : }
3048 120 : CATCH_REQUIRE(description->get_integer(field_name) == r);
3049 : }
3050 : }
3051 25 : else if((t.f_valid_func & VALID_FUNC_VARIABLE_SIZE) != 0)
3052 : {
3053 4 : std::uint64_t v(0);
3054 4 : SNAP_CATCH2_NAMESPACE::random(v);
3055 20 : CATCH_REQUIRE_THROWS_MATCHES(
3056 : description->set_integer("test_field", v)
3057 : , prinbee::out_of_range
3058 : , Catch::Matchers::ExceptionMessage(variable_size_errmsg));
3059 :
3060 20 : CATCH_REQUIRE_THROWS_MATCHES(
3061 : description->get_integer("test_field")
3062 : , prinbee::out_of_range
3063 : , Catch::Matchers::ExceptionMessage(variable_size_errmsg));
3064 : }
3065 : else
3066 : {
3067 21 : std::int64_t v(0);
3068 21 : SNAP_CATCH2_NAMESPACE::random(v);
3069 105 : CATCH_REQUIRE_THROWS_MATCHES(
3070 : description->set_integer(field_name, v)
3071 : , prinbee::type_mismatch
3072 : , Catch::Matchers::ExceptionMessage(
3073 : "prinbee_exception: this field type is \""
3074 : + prinbee::to_string(t.f_type)
3075 : + "\""
3076 : " but we expected one of \"INT8, INT16, INT32, INT64, MSTIME, TIME, USTIME\"."));
3077 :
3078 105 : CATCH_REQUIRE_THROWS_MATCHES(
3079 : description->get_integer(field_name)
3080 : , prinbee::type_mismatch
3081 : , Catch::Matchers::ExceptionMessage(
3082 : "prinbee_exception: this field type is \""
3083 : + prinbee::to_string(t.f_type)
3084 : + "\""
3085 : " but we expected one of \"INT8, INT16, INT32, INT64, MSTIME, TIME, USTIME\"."));
3086 : }
3087 :
3088 : // get_large_uinteger()/set_large_uinteger()
3089 : //
3090 29 : if((t.f_valid_func & VALID_FUNC_LARGE_UINTEGER) != 0)
3091 : {
3092 154 : for(int count(0); count < 10; ++count)
3093 : {
3094 140 : prinbee::uint512_t v(0);
3095 140 : SNAP_CATCH2_NAMESPACE::rand512(v);
3096 420 : description->set_large_uinteger(field_name, v);
3097 140 : prinbee::uint512_t r(v);
3098 140 : if(t.f_mask_size != 512)
3099 : {
3100 120 : prinbee::uint512_t mask(0);
3101 120 : prinbee::uint512_t one(1);
3102 120 : mask -= one;
3103 120 : mask >>= 512 - t.f_mask_size;
3104 120 : r &= mask;
3105 : }
3106 420 : CATCH_REQUIRE(description->get_large_uinteger(field_name) == r);
3107 : }
3108 : }
3109 15 : else if((t.f_valid_func & VALID_FUNC_VARIABLE_SIZE) != 0)
3110 : {
3111 4 : std::uint64_t v(0);
3112 4 : SNAP_CATCH2_NAMESPACE::random(v);
3113 24 : CATCH_REQUIRE_THROWS_MATCHES(
3114 : description->set_large_uinteger("test_field", v)
3115 : , prinbee::out_of_range
3116 : , Catch::Matchers::ExceptionMessage(variable_size_errmsg));
3117 :
3118 24 : CATCH_REQUIRE_THROWS_MATCHES(
3119 : description->get_large_uinteger("test_field")
3120 : , prinbee::out_of_range
3121 : , Catch::Matchers::ExceptionMessage(variable_size_errmsg));
3122 : }
3123 : else
3124 : {
3125 11 : prinbee::uint512_t v(0);
3126 11 : SNAP_CATCH2_NAMESPACE::rand512(v);
3127 55 : CATCH_REQUIRE_THROWS_MATCHES(
3128 : description->set_large_uinteger(field_name, v)
3129 : , prinbee::type_mismatch
3130 : , Catch::Matchers::ExceptionMessage(
3131 : "prinbee_exception: this field type is \""
3132 : + prinbee::to_string(t.f_type)
3133 : + "\""
3134 : " but we expected one of \"BITS8, BITS16, BITS32, BITS64, OID, REFERENCE, UINT8, UINT16, UINT32, UINT64, UINT128, UINT256, UINT512, VERSION\"."));
3135 :
3136 66 : CATCH_REQUIRE_THROWS_MATCHES(
3137 : description->get_large_uinteger(field_name)
3138 : , prinbee::type_mismatch
3139 : , Catch::Matchers::ExceptionMessage(
3140 : "prinbee_exception: this field type is \""
3141 : + prinbee::to_string(t.f_type)
3142 : + "\""
3143 : " but we expected one of \"BITS8, BITS16, BITS32, BITS64, MAGIC, OID, REFERENCE, STRUCTURE_VERSION, UINT8, UINT16, UINT32, UINT64, UINT128, UINT256, UINT512, VERSION\"."));
3144 : }
3145 :
3146 : // get_integer()/set_integer()
3147 : //
3148 29 : if((t.f_valid_func & VALID_FUNC_LARGE_INTEGER) != 0)
3149 : {
3150 77 : for(int count(0); count < 10; ++count)
3151 : {
3152 70 : prinbee::int512_t v(0);
3153 70 : SNAP_CATCH2_NAMESPACE::rand512(v);
3154 210 : description->set_large_integer(field_name, v);
3155 :
3156 70 : prinbee::int512_t r(v);
3157 70 : if(t.f_mask_size != 512)
3158 : {
3159 60 : prinbee::int512_t const one(1);
3160 60 : prinbee::int512_t const sign(one << (t.f_mask_size - 1));
3161 60 : if((r & sign) == 0)
3162 : {
3163 : // positive number, clear upper bits
3164 : //
3165 33 : prinbee::uint512_t mask(0);
3166 33 : mask -= one;
3167 33 : mask >>= 512 - t.f_mask_size;
3168 33 : r &= mask;
3169 : }
3170 : else
3171 : {
3172 : // negative number, set upper bits to all ones
3173 : //
3174 27 : prinbee::int512_t mask(0);
3175 27 : mask -= one;
3176 27 : mask <<= t.f_mask_size;
3177 27 : r |= mask;
3178 : }
3179 : }
3180 210 : CATCH_REQUIRE(description->get_large_integer(field_name) == r);
3181 : }
3182 : }
3183 22 : else if((t.f_valid_func & VALID_FUNC_VARIABLE_SIZE) != 0)
3184 : {
3185 4 : std::uint64_t v(0);
3186 4 : SNAP_CATCH2_NAMESPACE::random(v);
3187 24 : CATCH_REQUIRE_THROWS_MATCHES(
3188 : description->set_large_integer("test_field", v)
3189 : , prinbee::out_of_range
3190 : , Catch::Matchers::ExceptionMessage(variable_size_errmsg));
3191 :
3192 24 : CATCH_REQUIRE_THROWS_MATCHES(
3193 : description->get_large_integer("test_field")
3194 : , prinbee::out_of_range
3195 : , Catch::Matchers::ExceptionMessage(variable_size_errmsg));
3196 : }
3197 : else
3198 : {
3199 18 : prinbee::int512_t v(0);
3200 18 : SNAP_CATCH2_NAMESPACE::rand512(v);
3201 90 : CATCH_REQUIRE_THROWS_MATCHES(
3202 : description->set_large_integer(field_name, v)
3203 : , prinbee::type_mismatch
3204 : , Catch::Matchers::ExceptionMessage(
3205 : "prinbee_exception: this field type is \""
3206 : + prinbee::to_string(t.f_type)
3207 : + "\""
3208 : " but we expected one of \"INT8, INT16, INT32, INT64, INT128, INT256, INT512, MSTIME, NSTIME, TIME, USTIME\"."));
3209 :
3210 108 : CATCH_REQUIRE_THROWS_MATCHES(
3211 : description->get_large_integer(field_name)
3212 : , prinbee::type_mismatch
3213 : , Catch::Matchers::ExceptionMessage(
3214 : "prinbee_exception: this field type is \""
3215 : + prinbee::to_string(t.f_type)
3216 : + "\""
3217 : " but we expected one of \"INT8, INT16, INT32, INT64, INT128, INT256, INT512, MSTIME, NSTIME, TIME, USTIME\"."));
3218 : }
3219 :
3220 : // get_float32()/set_float32()
3221 : //
3222 29 : if((t.f_valid_func & VALID_FUNC_FLOAT32) != 0)
3223 : {
3224 11 : for(int count(0); count < 10; ++count)
3225 : {
3226 10 : float v(drand48() * 1000.0L);
3227 30 : description->set_float32(field_name, v);
3228 :
3229 30 : CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(description->get_float32(field_name), v, 0.0f));
3230 : }
3231 : }
3232 28 : else if((t.f_valid_func & VALID_FUNC_VARIABLE_SIZE) != 0)
3233 : {
3234 4 : float v(drand48() * 1000.0L);
3235 20 : CATCH_REQUIRE_THROWS_MATCHES(
3236 : description->set_float32("test_field", v)
3237 : , prinbee::type_mismatch
3238 : , Catch::Matchers::ExceptionMessage(
3239 : "prinbee_exception: this field type is \""
3240 : + prinbee::to_string(t.f_type)
3241 : + "\" but we expected \"FLOAT32\"."));
3242 :
3243 20 : CATCH_REQUIRE_THROWS_MATCHES(
3244 : description->get_float32("test_field")
3245 : , prinbee::type_mismatch
3246 : , Catch::Matchers::ExceptionMessage(
3247 : "prinbee_exception: this field type is \""
3248 : + prinbee::to_string(t.f_type)
3249 : + "\" but we expected \"FLOAT32\"."));
3250 : }
3251 : else
3252 : {
3253 24 : float v(drand48() * 1000.0L);
3254 120 : CATCH_REQUIRE_THROWS_MATCHES(
3255 : description->set_float32(field_name, v)
3256 : , prinbee::type_mismatch
3257 : , Catch::Matchers::ExceptionMessage(
3258 : "prinbee_exception: this field type is \""
3259 : + prinbee::to_string(t.f_type)
3260 : + "\" but we expected \"FLOAT32\"."));
3261 :
3262 120 : CATCH_REQUIRE_THROWS_MATCHES(
3263 : description->get_float32(field_name)
3264 : , prinbee::type_mismatch
3265 : , Catch::Matchers::ExceptionMessage(
3266 : "prinbee_exception: this field type is \""
3267 : + prinbee::to_string(t.f_type)
3268 : + "\" but we expected \"FLOAT32\"."));
3269 : }
3270 :
3271 : // get_float64()/set_float64()
3272 : //
3273 29 : if((t.f_valid_func & VALID_FUNC_FLOAT64) != 0)
3274 : {
3275 11 : for(int count(0); count < 10; ++count)
3276 : {
3277 10 : double v(drand48() * 1000.0L);
3278 30 : description->set_float64(field_name, v);
3279 :
3280 30 : CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(description->get_float64(field_name), v, 0.0));
3281 : }
3282 : }
3283 28 : else if((t.f_valid_func & VALID_FUNC_VARIABLE_SIZE) != 0)
3284 : {
3285 4 : double v(drand48() * 1000.0L);
3286 20 : CATCH_REQUIRE_THROWS_MATCHES(
3287 : description->set_float64("test_field", v)
3288 : , prinbee::type_mismatch
3289 : , Catch::Matchers::ExceptionMessage(
3290 : "prinbee_exception: this field type is \""
3291 : + prinbee::to_string(t.f_type)
3292 : + "\" but we expected \"FLOAT64\"."));
3293 :
3294 20 : CATCH_REQUIRE_THROWS_MATCHES(
3295 : description->get_float64("test_field")
3296 : , prinbee::type_mismatch
3297 : , Catch::Matchers::ExceptionMessage(
3298 : "prinbee_exception: this field type is \""
3299 : + prinbee::to_string(t.f_type)
3300 : + "\" but we expected \"FLOAT64\"."));
3301 : }
3302 : else
3303 : {
3304 24 : double v(drand48() * 1000.0L);
3305 120 : CATCH_REQUIRE_THROWS_MATCHES(
3306 : description->set_float64(field_name, v)
3307 : , prinbee::type_mismatch
3308 : , Catch::Matchers::ExceptionMessage(
3309 : "prinbee_exception: this field type is \""
3310 : + prinbee::to_string(t.f_type)
3311 : + "\" but we expected \"FLOAT64\"."));
3312 :
3313 120 : CATCH_REQUIRE_THROWS_MATCHES(
3314 : description->get_float64(field_name)
3315 : , prinbee::type_mismatch
3316 : , Catch::Matchers::ExceptionMessage(
3317 : "prinbee_exception: this field type is \""
3318 : + prinbee::to_string(t.f_type)
3319 : + "\" but we expected \"FLOAT64\"."));
3320 : }
3321 :
3322 : // get_float128()/set_float128()
3323 : //
3324 29 : if((t.f_valid_func & VALID_FUNC_FLOAT128) != 0)
3325 : {
3326 11 : for(int count(0); count < 10; ++count)
3327 : {
3328 10 : long double v(drand48() * 1000.0L);
3329 30 : description->set_float128(field_name, v);
3330 :
3331 30 : CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(description->get_float128(field_name), v, 0.0l));
3332 : }
3333 : }
3334 28 : else if((t.f_valid_func & VALID_FUNC_VARIABLE_SIZE) != 0)
3335 : {
3336 4 : long double v(drand48() * 1000.0L);
3337 20 : CATCH_REQUIRE_THROWS_MATCHES(
3338 : description->set_float128("test_field", v)
3339 : , prinbee::type_mismatch
3340 : , Catch::Matchers::ExceptionMessage(
3341 : "prinbee_exception: this field type is \""
3342 : + prinbee::to_string(t.f_type)
3343 : + "\" but we expected \"FLOAT128\"."));
3344 :
3345 20 : CATCH_REQUIRE_THROWS_MATCHES(
3346 : description->get_float128("test_field")
3347 : , prinbee::type_mismatch
3348 : , Catch::Matchers::ExceptionMessage(
3349 : "prinbee_exception: this field type is \""
3350 : + prinbee::to_string(t.f_type)
3351 : + "\" but we expected \"FLOAT128\"."));
3352 : }
3353 : else
3354 : {
3355 24 : long double v(drand48() * 1000.0L);
3356 120 : CATCH_REQUIRE_THROWS_MATCHES(
3357 : description->set_float128(field_name, v)
3358 : , prinbee::type_mismatch
3359 : , Catch::Matchers::ExceptionMessage(
3360 : "prinbee_exception: this field type is \""
3361 : + prinbee::to_string(t.f_type)
3362 : + "\" but we expected \"FLOAT128\"."));
3363 :
3364 120 : CATCH_REQUIRE_THROWS_MATCHES(
3365 : description->get_float128(field_name)
3366 : , prinbee::type_mismatch
3367 : , Catch::Matchers::ExceptionMessage(
3368 : "prinbee_exception: this field type is \""
3369 : + prinbee::to_string(t.f_type)
3370 : + "\" but we expected \"FLOAT128\"."));
3371 : }
3372 :
3373 : // buffers are not checked here, but we can still attempt the
3374 : // get/set functions with all the other types which must all fail
3375 : {
3376 29 : prinbee::buffer_t v;
3377 29 : std::uint64_t l(rand() % 300);
3378 3677 : for(std::uint64_t i(0); i < l; ++i)
3379 : {
3380 3648 : v.push_back(rand());
3381 : }
3382 145 : CATCH_REQUIRE_THROWS_MATCHES(
3383 : description->set_buffer(field_name, v)
3384 : , prinbee::type_mismatch
3385 : , Catch::Matchers::ExceptionMessage(
3386 : "prinbee_exception: this field type is \""
3387 : + prinbee::to_string(t.f_type)
3388 : + "\" but we expected one of \"BUFFER8, BUFFER16, BUFFER32\"."));
3389 :
3390 174 : CATCH_REQUIRE_THROWS_MATCHES(
3391 : description->get_buffer(field_name)
3392 : , prinbee::type_mismatch
3393 : , Catch::Matchers::ExceptionMessage(
3394 : "prinbee_exception: this field type is \""
3395 : + prinbee::to_string(t.f_type)
3396 : + "\" but we expected one of \"BUFFER8, BUFFER16, BUFFER32\"."));
3397 29 : }
3398 :
3399 : // arrays are not checked here, but we can still attempt the
3400 : // get function with all the other types which must all fail
3401 : {
3402 145 : CATCH_REQUIRE_THROWS_MATCHES(
3403 : description->get_array(field_name)
3404 : , prinbee::type_mismatch
3405 : , Catch::Matchers::ExceptionMessage(
3406 : "prinbee_exception: this field type is \""
3407 : + prinbee::to_string(t.f_type)
3408 : + "\" but we expected one of \"ARRAY8, ARRAY16, ARRAY32\"."));
3409 :
3410 203 : CATCH_REQUIRE_THROWS_MATCHES(
3411 : std::const_pointer_cast<prinbee::structure const>(description)->get_array(field_name)
3412 : , prinbee::type_mismatch
3413 : , Catch::Matchers::ExceptionMessage(
3414 : "prinbee_exception: this field type is \""
3415 : + prinbee::to_string(t.f_type)
3416 : + "\" but we expected one of \"ARRAY8, ARRAY16, ARRAY32\"."));
3417 : }
3418 29 : }
3419 : }
3420 2 : CATCH_END_SECTION()
3421 1 : }
3422 :
3423 :
3424 :
3425 4 : CATCH_TEST_CASE("structure_array", "[structure][array][valid]")
3426 : {
3427 6 : CATCH_START_SECTION("structure_array: structure with an ARRAY8")
3428 : {
3429 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description7));
3430 :
3431 : // the strings make this structure dynamic
3432 : //
3433 1 : CATCH_REQUIRE(description->get_static_size() == 0UL);
3434 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 32UL + 1UL + 4UL);
3435 :
3436 1 : description->init_buffer();
3437 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 32UL + 1UL + 4UL + 43UL);
3438 :
3439 7 : CATCH_REQUIRE_THROWS_MATCHES(
3440 : description->set_uinteger("_magic", SNAP_CATCH2_NAMESPACE::rand32())
3441 : , prinbee::type_mismatch
3442 : , Catch::Matchers::ExceptionMessage(
3443 : "prinbee_exception: this field type is \"MAGIC\""
3444 : " but we expected one of \"BITS8, BITS16, BITS32, BITS64, OID, REFERENCE, UINT8, UINT16, UINT32, UINT64, VERSION\"."));
3445 :
3446 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3447 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3448 :
3449 3 : CATCH_REQUIRE(description->get_string("name") == "users");
3450 3 : std::string const name("different_name");
3451 3 : description->set_string("name", name);
3452 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 32UL + 1UL + 4UL + 43UL);
3453 3 : CATCH_REQUIRE(description->get_string("name") == name);
3454 :
3455 3 : CATCH_REQUIRE(description->get_string("comment") == "This represents a form of table definition.");
3456 3 : std::string const comment_field(rand() % 1 == 0 ? "Short comment." : "This is a longer comment so we may test the pinsert() as well once in a while, but random is complicated to view the data.");
3457 3 : description->set_string("comment", comment_field);
3458 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 32UL + 1UL + 4UL + comment_field.length());
3459 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3460 :
3461 : // now create column definitions, one at a time and add them to
3462 : // the array
3463 : //
3464 3 : prinbee::structure::pointer_t column1(description->new_array_item("columns"));
3465 :
3466 3 : CATCH_REQUIRE(column1->get_string("colname") == "_undefined");
3467 3 : std::string const column1_name("col1");
3468 3 : column1->set_string("colname", column1_name);
3469 3 : CATCH_REQUIRE(column1->get_string("colname") == column1_name);
3470 :
3471 3 : CATCH_REQUIRE(column1->get_uinteger("max_size") == 256);
3472 1 : std::uint16_t column1_max_size(0);
3473 1 : SNAP_CATCH2_NAMESPACE::random(column1_max_size);
3474 3 : column1->set_uinteger("max_size", column1_max_size);
3475 3 : CATCH_REQUIRE(column1->get_uinteger("max_size") == column1_max_size);
3476 :
3477 3 : CATCH_REQUIRE(column1->get_uinteger("type") == 14);
3478 1 : std::uint16_t column1_type(0);
3479 1 : SNAP_CATCH2_NAMESPACE::random(column1_type);
3480 3 : column1->set_uinteger("type", column1_type);
3481 3 : CATCH_REQUIRE(column1->get_uinteger("type") == column1_type);
3482 :
3483 : // make sure the root was not affected
3484 : //
3485 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3486 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3487 3 : CATCH_REQUIRE(description->get_string("name") == name);
3488 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3489 :
3490 3 : prinbee::structure::vector_t array(description->get_array("columns"));
3491 1 : CATCH_REQUIRE(array.size() == 1);
3492 1 : CATCH_REQUIRE(array[0] == column1);
3493 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
3494 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
3495 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
3496 :
3497 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 32UL
3498 : + 1UL + 1UL + column1_name.length() + 2UL + 2UL
3499 : + 4UL + comment_field.length());
3500 :
3501 : // column #2
3502 : //
3503 3 : prinbee::structure::pointer_t column2(description->new_array_item("columns"));
3504 :
3505 3 : CATCH_REQUIRE(column2->get_string("colname") == "_undefined");
3506 3 : std::string const column2_name("col2_long_name_here");
3507 3 : column2->set_string("colname", column2_name);
3508 3 : CATCH_REQUIRE(column2->get_string("colname") == column2_name);
3509 :
3510 3 : CATCH_REQUIRE(column2->get_uinteger("max_size") == 256);
3511 1 : std::uint16_t column2_max_size(0);
3512 1 : SNAP_CATCH2_NAMESPACE::random(column2_max_size);
3513 3 : column2->set_uinteger("max_size", column2_max_size);
3514 3 : CATCH_REQUIRE(column2->get_uinteger("max_size") == column2_max_size);
3515 :
3516 3 : CATCH_REQUIRE(column2->get_uinteger("type") == 14);
3517 1 : std::uint16_t column2_type(0);
3518 1 : SNAP_CATCH2_NAMESPACE::random(column2_type);
3519 3 : column2->set_uinteger("type", column2_type);
3520 3 : CATCH_REQUIRE(column2->get_uinteger("type") == column2_type);
3521 :
3522 : // make sure the root & column1 were not affected
3523 : //
3524 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3525 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3526 3 : CATCH_REQUIRE(description->get_string("name") == name);
3527 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3528 :
3529 3 : array = description->get_array("columns");
3530 1 : CATCH_REQUIRE(array.size() == 2);
3531 1 : CATCH_REQUIRE(array[0] == column1);
3532 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
3533 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
3534 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
3535 1 : CATCH_REQUIRE(array[1] == column2);
3536 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
3537 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
3538 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
3539 :
3540 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 32UL
3541 : + 1UL + 1UL + column1_name.length() + 2UL + 2UL
3542 : + 1UL + column2_name.length() + 2UL + 2UL
3543 : + 4UL + comment_field.length());
3544 :
3545 : // column #3
3546 : //
3547 3 : prinbee::structure::pointer_t column3(description->new_array_item("columns"));
3548 :
3549 3 : CATCH_REQUIRE(column3->get_string("colname") == "_undefined");
3550 3 : std::string const column3_name("col3__here");
3551 3 : column3->set_string("colname", column3_name);
3552 3 : CATCH_REQUIRE(column3->get_string("colname") == column3_name);
3553 :
3554 3 : CATCH_REQUIRE(column3->get_uinteger("max_size") == 256);
3555 1 : std::uint16_t column3_max_size(0);
3556 1 : SNAP_CATCH2_NAMESPACE::random(column3_max_size);
3557 3 : column3->set_uinteger("max_size", column3_max_size);
3558 3 : CATCH_REQUIRE(column3->get_uinteger("max_size") == column3_max_size);
3559 :
3560 3 : CATCH_REQUIRE(column3->get_uinteger("type") == 14);
3561 1 : std::uint16_t column3_type(0);
3562 1 : SNAP_CATCH2_NAMESPACE::random(column3_type);
3563 3 : column3->set_uinteger("type", column3_type);
3564 3 : CATCH_REQUIRE(column3->get_uinteger("type") == column3_type);
3565 :
3566 : // make sure the root & column 1/2 are not affected
3567 : //
3568 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3569 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3570 3 : CATCH_REQUIRE(description->get_string("name") == name);
3571 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3572 :
3573 3 : array = description->get_array("columns");
3574 1 : CATCH_REQUIRE(array.size() == 3);
3575 1 : CATCH_REQUIRE(array[0] == column1);
3576 3 : CATCH_REQUIRE(column1->get_string("colname") == column1_name);
3577 3 : CATCH_REQUIRE(column1->get_uinteger("max_size") == column1_max_size);
3578 3 : CATCH_REQUIRE(column1->get_uinteger("type") == column1_type);
3579 1 : CATCH_REQUIRE(array[1] == column2);
3580 3 : CATCH_REQUIRE(column2->get_string("colname") == column2_name);
3581 3 : CATCH_REQUIRE(column2->get_uinteger("max_size") == column2_max_size);
3582 3 : CATCH_REQUIRE(column2->get_uinteger("type") == column2_type);
3583 1 : CATCH_REQUIRE(array[2] == column3);
3584 3 : CATCH_REQUIRE(column3->get_string("colname") == column3_name);
3585 3 : CATCH_REQUIRE(column3->get_uinteger("max_size") == column3_max_size);
3586 3 : CATCH_REQUIRE(column3->get_uinteger("type") == column3_type);
3587 :
3588 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 32UL
3589 : + 1UL + 1UL + column1_name.length() + 2UL + 2UL
3590 : + 1UL + column2_name.length() + 2UL + 2UL
3591 : + 1UL + column3_name.length() + 2UL + 2UL
3592 : + 4UL + comment_field.length());
3593 : //{
3594 : //prinbee::reference_t start_offset(0);
3595 : //prinbee::virtual_buffer::pointer_t buffer(description->get_virtual_buffer(start_offset));
3596 : //std::cout << std::flush << "column3 at the end -- buffer start offset: " << start_offset << "\n" << *buffer << std::endl;
3597 : //description->display_offsets();
3598 : //}
3599 : // column #4 and beyond (we want to test an overflow, see after loop)
3600 : //
3601 : // WARNING: the following adds column #4 to column #255--we cannot
3602 : // have 256 columns since the 8 bit counters can be 0 to
3603 : // 255 with 0 representing an empty array
3604 : //
3605 253 : for(int count(4); count < 256; ++count)
3606 : {
3607 756 : description->new_array_item("columns");
3608 : }
3609 :
3610 : // further attempts to add array items fail
3611 : //
3612 11 : for(int count(0); count < 10; ++ count)
3613 : {
3614 80 : CATCH_REQUIRE_THROWS_MATCHES(
3615 : description->new_array_item("columns")
3616 : , prinbee::out_of_range
3617 : , Catch::Matchers::ExceptionMessage(
3618 : "out_of_range: the new_array_item() function cannot be"
3619 : " used because the array is already full with 256 items."));
3620 : }
3621 :
3622 : {
3623 1 : prinbee::reference_t start_offset(0);
3624 1 : prinbee::virtual_buffer::pointer_t b(description->get_virtual_buffer(start_offset));
3625 1 : CATCH_REQUIRE(b != nullptr);
3626 1 : CATCH_REQUIRE(b->size() == description->get_current_size());
3627 :
3628 3 : prinbee::buffer_t buffer(b->size());
3629 1 : CATCH_REQUIRE(b->pread(buffer.data(), buffer.size(), 0) == static_cast<int>(buffer.size()));
3630 :
3631 1 : prinbee::virtual_buffer::pointer_t n(std::make_shared<prinbee::virtual_buffer>());
3632 1 : n->pwrite(buffer.data(), buffer.size(), 0, true);
3633 :
3634 1 : prinbee::structure::pointer_t d(std::make_shared<prinbee::structure>(g_description7));
3635 1 : d->set_virtual_buffer(n, 0);
3636 :
3637 1 : CATCH_REQUIRE(d->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3638 3 : CATCH_REQUIRE(d->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3639 3 : CATCH_REQUIRE(d->get_string("name") == name);
3640 3 : CATCH_REQUIRE(d->get_string("comment") == comment_field);
3641 :
3642 3 : array = d->get_array("columns");
3643 1 : CATCH_REQUIRE(array.size() == 255);
3644 :
3645 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
3646 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
3647 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
3648 :
3649 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
3650 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
3651 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
3652 :
3653 3 : CATCH_REQUIRE(array[2]->get_string("colname") == column3_name);
3654 3 : CATCH_REQUIRE(array[2]->get_uinteger("max_size") == column3_max_size);
3655 3 : CATCH_REQUIRE(array[2]->get_uinteger("type") == column3_type);
3656 :
3657 253 : for(std::size_t idx(3); idx < 255; ++idx)
3658 : {
3659 756 : CATCH_REQUIRE(array[idx]->get_string("colname") == "_undefined");
3660 756 : CATCH_REQUIRE(array[idx]->get_uinteger("max_size") == 256);
3661 756 : CATCH_REQUIRE(array[idx]->get_uinteger("type") == 14);
3662 : }
3663 1 : }
3664 :
3665 : // now randomly remove columns one by one
3666 : //
3667 : // Remember we only have 255 entries, not 256, since the size has to
3668 : // fit in 8 bits and 0 does represent "no items"
3669 : //
3670 256 : for(int count(0); count < 255; ++count)
3671 : {
3672 255 : std::size_t max(0);
3673 255 : if((rand() & 1) != 0)
3674 : {
3675 339 : max = std::const_pointer_cast<prinbee::structure const>(description)->get_array("columns").size();
3676 : }
3677 : else
3678 : {
3679 426 : max = description->get_array("columns").size();
3680 : }
3681 255 : int const idx(rand() % max);
3682 765 : description->delete_array_item("columns", idx);
3683 :
3684 : // attempts to delete a non-existent item fails
3685 : //
3686 255 : int index(max + rand());
3687 1275 : CATCH_REQUIRE_THROWS_MATCHES(
3688 : description->delete_array_item("columns", index)
3689 : , prinbee::out_of_range
3690 : , Catch::Matchers::ExceptionMessage(
3691 : "out_of_range: the index ("
3692 : + std::to_string(index)
3693 : + ") in delete_array_item() function is out of range (larger or equal to the size: "
3694 : + std::to_string(max - 1) // -1 because we deleted one item above
3695 : + ")."));
3696 : }
3697 :
3698 : // further attempts to delete any array item fail
3699 : //
3700 11 : for(int count(0); count < 10; ++ count)
3701 : {
3702 50 : CATCH_REQUIRE_THROWS_MATCHES(
3703 : description->delete_array_item("columns", count)
3704 : , prinbee::out_of_range
3705 : , Catch::Matchers::ExceptionMessage(
3706 : "out_of_range: the index ("
3707 : + std::to_string(count)
3708 : + ") in delete_array_item() function is out of range (larger or equal to the size: 0)."));
3709 : }
3710 :
3711 3 : CATCH_REQUIRE(description->get_array("columns").empty());
3712 1 : }
3713 5 : CATCH_END_SECTION()
3714 :
3715 6 : CATCH_START_SECTION("structure_array: structure with an ARRAY16")
3716 : {
3717 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description8));
3718 :
3719 : // the strings make this structure dynamic
3720 : //
3721 1 : CATCH_REQUIRE(description->get_static_size() == 0UL);
3722 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + 2UL + 4UL);
3723 :
3724 1 : description->init_buffer();
3725 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + 5UL + 2UL + 4UL + 33UL);
3726 :
3727 7 : CATCH_REQUIRE_THROWS_MATCHES(
3728 : description->set_uinteger("_magic", SNAP_CATCH2_NAMESPACE::rand32())
3729 : , prinbee::type_mismatch
3730 : , Catch::Matchers::ExceptionMessage(
3731 : "prinbee_exception: this field type is \"MAGIC\""
3732 : " but we expected one of \"BITS8, BITS16, BITS32, BITS64, OID, REFERENCE, UINT8, UINT16, UINT32, UINT64, VERSION\"."));
3733 :
3734 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3735 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3736 :
3737 3 : CATCH_REQUIRE(description->get_string("name") == "users");
3738 3 : std::string name("different_name");
3739 3 : description->set_string("name", name);
3740 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length() + 2UL + 4UL + 33UL);
3741 3 : CATCH_REQUIRE(description->get_string("name") == name);
3742 :
3743 3 : CATCH_REQUIRE(description->get_string("comment") == "Another form of table definition.");
3744 3 : std::string comment_field(rand() % 1 == 0 ? "Perfect table." : "This is a longer comment so we may test the pinsert() as well once in a while, but random is complicated to view the data.");
3745 3 : description->set_string("comment", comment_field);
3746 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length() + 2UL + 4UL + comment_field.length());
3747 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3748 :
3749 : // now create column definitions, one at a time and add them to
3750 : // the array
3751 : //
3752 3 : prinbee::structure::pointer_t column1(description->new_array_item("columns"));
3753 :
3754 3 : CATCH_REQUIRE(column1->get_string("colname") == "_undefined");
3755 3 : std::string column1_name("wide_col1");
3756 3 : column1->set_string("colname", column1_name);
3757 3 : CATCH_REQUIRE(column1->get_string("colname") == column1_name);
3758 :
3759 3 : CATCH_REQUIRE(column1->get_uinteger("max_size") == 256);
3760 1 : std::uint16_t column1_max_size(0);
3761 1 : SNAP_CATCH2_NAMESPACE::random(column1_max_size);
3762 3 : column1->set_uinteger("max_size", column1_max_size);
3763 3 : CATCH_REQUIRE(column1->get_uinteger("max_size") == column1_max_size);
3764 :
3765 3 : CATCH_REQUIRE(column1->get_uinteger("type") == 14);
3766 1 : std::uint16_t column1_type(0);
3767 1 : SNAP_CATCH2_NAMESPACE::random(column1_type);
3768 3 : column1->set_uinteger("type", column1_type);
3769 3 : CATCH_REQUIRE(column1->get_uinteger("type") == column1_type);
3770 :
3771 : // make sure the root was not affected
3772 : //
3773 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3774 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3775 3 : CATCH_REQUIRE(description->get_string("name") == name);
3776 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3777 :
3778 3 : prinbee::structure::vector_t array(description->get_array("columns"));
3779 1 : CATCH_REQUIRE(array.size() == 1);
3780 1 : CATCH_REQUIRE(array[0] == column1);
3781 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
3782 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
3783 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
3784 :
3785 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length()
3786 : + 2UL + 1UL + column1_name.length() + 2UL + 2UL
3787 : + 4UL + comment_field.length());
3788 :
3789 : // now change the root structure (name) and make sure that column #1 is still fine
3790 : //
3791 1 : name = "change_the_name_to_a_longer_one";
3792 3 : description->set_string("name", name);
3793 :
3794 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3795 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3796 3 : CATCH_REQUIRE(description->get_string("name") == name);
3797 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3798 :
3799 3 : array = description->get_array("columns");
3800 1 : CATCH_REQUIRE(array.size() == 1);
3801 1 : CATCH_REQUIRE(array[0] == column1);
3802 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
3803 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
3804 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
3805 :
3806 : // change the root structure again (comment) and make sure that column #1 is still fine
3807 : //
3808 1 : comment_field = "Just another comment to stick at the end.";
3809 3 : description->set_string("comment", comment_field);
3810 :
3811 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3812 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3813 3 : CATCH_REQUIRE(description->get_string("name") == name);
3814 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3815 :
3816 3 : array = description->get_array("columns");
3817 1 : CATCH_REQUIRE(array.size() == 1);
3818 1 : CATCH_REQUIRE(array[0] == column1);
3819 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
3820 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
3821 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
3822 :
3823 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length()
3824 : + 2UL + 1UL + column1_name.length() + 2UL + 2UL
3825 : + 4UL + comment_field.length());
3826 :
3827 : // also test changing the 1st column name
3828 : //
3829 1 : column1_name = "renamed_column1_to_make_sure_we_can_do_that";
3830 3 : column1->set_string("colname", column1_name);
3831 :
3832 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3833 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3834 3 : CATCH_REQUIRE(description->get_string("name") == name);
3835 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3836 :
3837 3 : array = description->get_array("columns");
3838 1 : CATCH_REQUIRE(array.size() == 1);
3839 1 : CATCH_REQUIRE(array[0] == column1);
3840 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
3841 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
3842 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
3843 :
3844 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length()
3845 : + 2UL + 1UL + column1_name.length() + 2UL + 2UL
3846 : + 4UL + comment_field.length());
3847 :
3848 : // column #2
3849 : //
3850 3 : prinbee::structure::pointer_t column2(description->new_array_item("columns"));
3851 :
3852 3 : CATCH_REQUIRE(column2->get_string("colname") == "_undefined");
3853 3 : std::string column2_name("wide_col2_long_name_here");
3854 3 : column2->set_string("colname", column2_name);
3855 3 : CATCH_REQUIRE(column2->get_string("colname") == column2_name);
3856 :
3857 3 : CATCH_REQUIRE(column2->get_uinteger("max_size") == 256);
3858 1 : std::uint16_t column2_max_size(0);
3859 1 : SNAP_CATCH2_NAMESPACE::random(column2_max_size);
3860 3 : column2->set_uinteger("max_size", column2_max_size);
3861 3 : CATCH_REQUIRE(column2->get_uinteger("max_size") == column2_max_size);
3862 :
3863 3 : CATCH_REQUIRE(column2->get_uinteger("type") == 14);
3864 1 : std::uint16_t column2_type(0);
3865 1 : SNAP_CATCH2_NAMESPACE::random(column2_type);
3866 3 : column2->set_uinteger("type", column2_type);
3867 3 : CATCH_REQUIRE(column2->get_uinteger("type") == column2_type);
3868 :
3869 : // make sure the root & column1 were not affected
3870 : //
3871 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3872 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3873 3 : CATCH_REQUIRE(description->get_string("name") == name);
3874 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3875 :
3876 3 : array = description->get_array("columns");
3877 1 : CATCH_REQUIRE(array.size() == 2);
3878 1 : CATCH_REQUIRE(array[0] == column1);
3879 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
3880 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
3881 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
3882 1 : CATCH_REQUIRE(array[1] == column2);
3883 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
3884 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
3885 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
3886 :
3887 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length()
3888 : + 2UL + 1UL + column1_name.length() + 2UL + 2UL
3889 : + 1UL + column2_name.length() + 2UL + 2UL
3890 : + 4UL + comment_field.length());
3891 :
3892 : // now change the root structure (name) and make sure that column #1 is still fine
3893 : //
3894 1 : name = "smaller_name_this_time";
3895 3 : description->set_string("name", name);
3896 :
3897 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3898 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3899 3 : CATCH_REQUIRE(description->get_string("name") == name);
3900 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3901 :
3902 3 : array = description->get_array("columns");
3903 1 : CATCH_REQUIRE(array.size() == 2);
3904 1 : CATCH_REQUIRE(array[0] == column1);
3905 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
3906 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
3907 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
3908 1 : CATCH_REQUIRE(array[1] == column2);
3909 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
3910 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
3911 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
3912 :
3913 : // change the root structure again (comment) and make sure that column #1 is still fine
3914 : //
3915 1 : comment_field = "So many ALTER happening here!";
3916 3 : description->set_string("comment", comment_field);
3917 :
3918 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3919 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3920 3 : CATCH_REQUIRE(description->get_string("name") == name);
3921 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3922 :
3923 3 : array = description->get_array("columns");
3924 1 : CATCH_REQUIRE(array.size() == 2);
3925 1 : CATCH_REQUIRE(array[0] == column1);
3926 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
3927 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
3928 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
3929 1 : CATCH_REQUIRE(array[1] == column2);
3930 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
3931 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
3932 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
3933 :
3934 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length()
3935 : + 2UL + 1UL + column1_name.length() + 2UL + 2UL
3936 : + 1UL + column2_name.length() + 2UL + 2UL
3937 : + 4UL + comment_field.length());
3938 :
3939 : // also test changing the 1st & 2nd column names
3940 : //
3941 1 : column1_name = "renamed_column1_to_make_sure_we_can_do_that";
3942 3 : column1->set_string("colname", column1_name);
3943 1 : column2_name = "col2";
3944 3 : column2->set_string("colname", column2_name);
3945 :
3946 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3947 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3948 3 : CATCH_REQUIRE(description->get_string("name") == name);
3949 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3950 :
3951 3 : array = description->get_array("columns");
3952 1 : CATCH_REQUIRE(array.size() == 2);
3953 1 : CATCH_REQUIRE(array[0] == column1);
3954 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
3955 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
3956 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
3957 1 : CATCH_REQUIRE(array[1] == column2);
3958 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
3959 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
3960 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
3961 :
3962 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length()
3963 : + 2UL + 1UL + column1_name.length() + 2UL + 2UL
3964 : + 1UL + column2_name.length() + 2UL + 2UL
3965 : + 4UL + comment_field.length());
3966 :
3967 : // column #3
3968 : //
3969 3 : prinbee::structure::pointer_t column3(description->new_array_item("columns"));
3970 :
3971 3 : CATCH_REQUIRE(column3->get_string("colname") == "_undefined");
3972 3 : std::string column3_name("col3__here");
3973 3 : column3->set_string("colname", column3_name);
3974 3 : CATCH_REQUIRE(column3->get_string("colname") == column3_name);
3975 :
3976 3 : CATCH_REQUIRE(column3->get_uinteger("max_size") == 256);
3977 1 : std::uint16_t column3_max_size(0);
3978 1 : SNAP_CATCH2_NAMESPACE::random(column3_max_size);
3979 3 : column3->set_uinteger("max_size", column3_max_size);
3980 3 : CATCH_REQUIRE(column3->get_uinteger("max_size") == column3_max_size);
3981 :
3982 3 : CATCH_REQUIRE(column3->get_uinteger("type") == 14);
3983 1 : std::uint16_t column3_type(0);
3984 1 : SNAP_CATCH2_NAMESPACE::random(column3_type);
3985 3 : column3->set_uinteger("type", column3_type);
3986 3 : CATCH_REQUIRE(column3->get_uinteger("type") == column3_type);
3987 :
3988 : // make sure the root & column 1/2 are not affected
3989 : //
3990 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
3991 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
3992 3 : CATCH_REQUIRE(description->get_string("name") == name);
3993 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
3994 :
3995 3 : array = description->get_array("columns");
3996 1 : CATCH_REQUIRE(array.size() == 3);
3997 1 : CATCH_REQUIRE(array[0] == column1);
3998 3 : CATCH_REQUIRE(column1->get_string("colname") == column1_name);
3999 3 : CATCH_REQUIRE(column1->get_uinteger("max_size") == column1_max_size);
4000 3 : CATCH_REQUIRE(column1->get_uinteger("type") == column1_type);
4001 1 : CATCH_REQUIRE(array[1] == column2);
4002 3 : CATCH_REQUIRE(column2->get_string("colname") == column2_name);
4003 3 : CATCH_REQUIRE(column2->get_uinteger("max_size") == column2_max_size);
4004 3 : CATCH_REQUIRE(column2->get_uinteger("type") == column2_type);
4005 1 : CATCH_REQUIRE(array[2] == column3);
4006 3 : CATCH_REQUIRE(column3->get_string("colname") == column3_name);
4007 3 : CATCH_REQUIRE(column3->get_uinteger("max_size") == column3_max_size);
4008 3 : CATCH_REQUIRE(column3->get_uinteger("type") == column3_type);
4009 :
4010 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length()
4011 : + 2UL + 1UL + column1_name.length() + 2UL + 2UL
4012 : + 1UL + column2_name.length() + 2UL + 2UL
4013 : + 1UL + column3_name.length() + 2UL + 2UL
4014 : + 4UL + comment_field.length());
4015 :
4016 : // now change the root structure (name) and make sure that column #1 is still fine
4017 : //
4018 1 : name = "final_name";
4019 3 : description->set_string("name", name);
4020 :
4021 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4022 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4023 3 : CATCH_REQUIRE(description->get_string("name") == name);
4024 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4025 :
4026 3 : array = description->get_array("columns");
4027 1 : CATCH_REQUIRE(array.size() == 3);
4028 1 : CATCH_REQUIRE(array[0] == column1);
4029 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4030 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4031 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4032 1 : CATCH_REQUIRE(array[1] == column2);
4033 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
4034 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
4035 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4036 1 : CATCH_REQUIRE(array[2] == column3);
4037 3 : CATCH_REQUIRE(array[2]->get_string("colname") == column3_name);
4038 3 : CATCH_REQUIRE(array[2]->get_uinteger("max_size") == column3_max_size);
4039 3 : CATCH_REQUIRE(array[2]->get_uinteger("type") == column3_type);
4040 :
4041 : // change the root structure again (comment) and make sure that column #1 is still fine
4042 : //
4043 1 : comment_field = "Final comment.";
4044 3 : description->set_string("comment", comment_field);
4045 :
4046 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4047 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4048 3 : CATCH_REQUIRE(description->get_string("name") == name);
4049 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4050 :
4051 3 : array = description->get_array("columns");
4052 1 : CATCH_REQUIRE(array.size() == 3);
4053 1 : CATCH_REQUIRE(array[0] == column1);
4054 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4055 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4056 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4057 1 : CATCH_REQUIRE(array[1] == column2);
4058 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
4059 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
4060 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4061 1 : CATCH_REQUIRE(array[2] == column3);
4062 3 : CATCH_REQUIRE(array[2]->get_string("colname") == column3_name);
4063 3 : CATCH_REQUIRE(array[2]->get_uinteger("max_size") == column3_max_size);
4064 3 : CATCH_REQUIRE(array[2]->get_uinteger("type") == column3_type);
4065 :
4066 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length()
4067 : + 2UL + 1UL + column1_name.length() + 2UL + 2UL
4068 : + 1UL + column2_name.length() + 2UL + 2UL
4069 : + 1UL + column3_name.length() + 2UL + 2UL
4070 : + 4UL + comment_field.length());
4071 :
4072 : // also test changing the 1st & 2nd column names
4073 : //
4074 1 : column1_name = "changing_again";
4075 3 : column1->set_string("colname", column1_name);
4076 1 : column2_name = "col2_final_name";
4077 3 : column2->set_string("colname", column2_name);
4078 1 : column3_name = "col3_new_name";
4079 3 : column3->set_string("colname", column3_name);
4080 :
4081 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4082 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4083 3 : CATCH_REQUIRE(description->get_string("name") == name);
4084 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4085 :
4086 3 : array = description->get_array("columns");
4087 1 : CATCH_REQUIRE(array.size() == 3);
4088 1 : CATCH_REQUIRE(array[0] == column1);
4089 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4090 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4091 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4092 1 : CATCH_REQUIRE(array[1] == column2);
4093 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
4094 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
4095 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4096 1 : CATCH_REQUIRE(array[2] == column3);
4097 3 : CATCH_REQUIRE(array[2]->get_string("colname") == column3_name);
4098 3 : CATCH_REQUIRE(array[2]->get_uinteger("max_size") == column3_max_size);
4099 3 : CATCH_REQUIRE(array[2]->get_uinteger("type") == column3_type);
4100 :
4101 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length()
4102 : + 2UL + 1UL + column1_name.length() + 2UL + 2UL
4103 : + 1UL + column2_name.length() + 2UL + 2UL
4104 : + 1UL + column3_name.length() + 2UL + 2UL
4105 : + 4UL + comment_field.length());
4106 :
4107 : {
4108 1 : prinbee::reference_t start_offset(0);
4109 1 : prinbee::virtual_buffer::pointer_t b(description->get_virtual_buffer(start_offset));
4110 1 : CATCH_REQUIRE(b != nullptr);
4111 1 : CATCH_REQUIRE(b->size() == description->get_current_size());
4112 :
4113 3 : prinbee::buffer_t buffer(b->size());
4114 1 : CATCH_REQUIRE(b->pread(buffer.data(), buffer.size(), 0) == static_cast<int>(buffer.size()));
4115 :
4116 1 : prinbee::virtual_buffer::pointer_t n(std::make_shared<prinbee::virtual_buffer>());
4117 1 : n->pwrite(buffer.data(), buffer.size(), 0, true);
4118 :
4119 1 : prinbee::structure::pointer_t d(std::make_shared<prinbee::structure>(g_description8));
4120 1 : d->set_virtual_buffer(n, 0);
4121 :
4122 1 : CATCH_REQUIRE(d->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4123 3 : CATCH_REQUIRE(d->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4124 3 : CATCH_REQUIRE(d->get_string("name") == name);
4125 3 : CATCH_REQUIRE(d->get_string("comment") == comment_field);
4126 :
4127 3 : array = d->get_array("columns");
4128 1 : CATCH_REQUIRE(array.size() == 3);
4129 :
4130 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4131 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4132 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4133 :
4134 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
4135 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
4136 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4137 :
4138 3 : CATCH_REQUIRE(array[2]->get_string("colname") == column3_name);
4139 3 : CATCH_REQUIRE(array[2]->get_uinteger("max_size") == column3_max_size);
4140 3 : CATCH_REQUIRE(array[2]->get_uinteger("type") == column3_type);
4141 1 : }
4142 :
4143 : //{
4144 : //prinbee::reference_t start_offset(0);
4145 : //prinbee::virtual_buffer::pointer_t buffer(description->get_virtual_buffer(start_offset));
4146 : //std::cout << std::flush << "column3 at the end -- buffer start offset: " << start_offset << "\n" << *buffer << std::endl;
4147 : //description->display_offsets();
4148 : //}
4149 : // delete column 2 (index of 1)
4150 3 : description->delete_array_item("columns", 1);
4151 :
4152 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4153 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4154 3 : CATCH_REQUIRE(description->get_string("name") == name);
4155 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4156 :
4157 3 : array = description->get_array("columns");
4158 1 : CATCH_REQUIRE(array.size() == 2);
4159 1 : CATCH_REQUIRE(array[0] == column1);
4160 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4161 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4162 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4163 : // column 2 was deleted
4164 1 : CATCH_REQUIRE(array[1] == column3);
4165 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column3_name);
4166 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column3_max_size);
4167 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column3_type);
4168 :
4169 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length()
4170 : + 2UL + 1UL + column1_name.length() + 2UL + 2UL
4171 : + 1UL + column3_name.length() + 2UL + 2UL
4172 : + 4UL + comment_field.length());
4173 :
4174 : // delete column 1 (index of 0)
4175 3 : description->delete_array_item("columns", 0);
4176 :
4177 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4178 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4179 3 : CATCH_REQUIRE(description->get_string("name") == name);
4180 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4181 :
4182 3 : array = description->get_array("columns");
4183 1 : CATCH_REQUIRE(array.size() == 1);
4184 : // column 1 & 2 were deleted
4185 1 : CATCH_REQUIRE(array[0] == column3);
4186 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column3_name);
4187 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column3_max_size);
4188 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column3_type);
4189 :
4190 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length()
4191 : + 2UL + 1UL + column3_name.length() + 2UL + 2UL
4192 : + 4UL + comment_field.length());
4193 :
4194 : // delete column 3 (index of 0 since 1 & 2 are gone)
4195 : //
4196 3 : description->delete_array_item("columns", 0);
4197 :
4198 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4199 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4200 3 : CATCH_REQUIRE(description->get_string("name") == name);
4201 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4202 :
4203 3 : array = description->get_array("columns");
4204 1 : CATCH_REQUIRE(array.size() == 0);
4205 :
4206 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 4UL + name.length()
4207 : + 2UL
4208 : + 4UL + comment_field.length());
4209 1 : }
4210 5 : CATCH_END_SECTION()
4211 :
4212 6 : CATCH_START_SECTION("structure_array: structure with an ARRAY32")
4213 : {
4214 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description9));
4215 :
4216 : // the strings make this structure dynamic
4217 : //
4218 1 : CATCH_REQUIRE(description->get_static_size() == 0UL);
4219 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 1UL + 4UL + 2UL);
4220 :
4221 1 : description->init_buffer();
4222 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 1UL + 4UL + 4UL + 2UL + 56UL);
4223 :
4224 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4225 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4226 :
4227 3 : CATCH_REQUIRE(description->get_string("name") == "page");
4228 3 : std::string name("thirty_two_bits");
4229 3 : description->set_string("name", name);
4230 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 1UL + name.length() + 4UL + 2UL + 56UL);
4231 3 : CATCH_REQUIRE(description->get_string("name") == name);
4232 :
4233 3 : CATCH_REQUIRE(description->get_string("comment") == "Table with a number of columns that can go to 4 billion.");
4234 3 : std::string comment_field(rand() % 1 == 0 ? "Randomly small comment." : "This one's small too...");
4235 3 : description->set_string("comment", comment_field);
4236 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 1UL + name.length() + 4UL + 2UL + comment_field.length());
4237 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4238 :
4239 : // now create column definitions, one at a time and add them to
4240 : // the array
4241 : //
4242 3 : prinbee::structure::pointer_t column1(description->new_array_item("columns"));
4243 :
4244 3 : CATCH_REQUIRE(column1->get_string("colname") == "_undefined");
4245 3 : std::string const column1_name("wide_col1");
4246 3 : column1->set_string("colname", column1_name);
4247 3 : CATCH_REQUIRE(column1->get_string("colname") == column1_name);
4248 :
4249 3 : CATCH_REQUIRE(column1->get_uinteger("max_size") == 256);
4250 1 : std::uint16_t column1_max_size(0);
4251 1 : SNAP_CATCH2_NAMESPACE::random(column1_max_size);
4252 3 : column1->set_uinteger("max_size", column1_max_size);
4253 3 : CATCH_REQUIRE(column1->get_uinteger("max_size") == column1_max_size);
4254 :
4255 3 : CATCH_REQUIRE(column1->get_uinteger("type") == 14);
4256 1 : std::uint16_t column1_type(0);
4257 1 : SNAP_CATCH2_NAMESPACE::random(column1_type);
4258 3 : column1->set_uinteger("type", column1_type);
4259 3 : CATCH_REQUIRE(column1->get_uinteger("type") == column1_type);
4260 :
4261 : // make sure the root was not affected
4262 : //
4263 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4264 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4265 3 : CATCH_REQUIRE(description->get_string("name") == name);
4266 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4267 :
4268 3 : prinbee::structure::vector_t array(description->get_array("columns"));
4269 1 : CATCH_REQUIRE(array.size() == 1);
4270 1 : CATCH_REQUIRE(array[0] == column1);
4271 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4272 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4273 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4274 :
4275 : // now change the root structure (name) and make sure that column #1 is still fine
4276 : //
4277 1 : name = "we_want_to_test_with_a_very_long_name";
4278 3 : description->set_string("name", name);
4279 :
4280 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4281 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4282 3 : CATCH_REQUIRE(description->get_string("name") == name);
4283 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4284 :
4285 3 : array = description->get_array("columns");
4286 1 : CATCH_REQUIRE(array.size() == 1);
4287 1 : CATCH_REQUIRE(array[0] == column1);
4288 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4289 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4290 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4291 :
4292 : // change the root structure again (comment) and make sure that column #1 is still fine
4293 : //
4294 1 : comment_field = "Just another comment to stick at the end.";
4295 3 : description->set_string("comment", comment_field);
4296 :
4297 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4298 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4299 3 : CATCH_REQUIRE(description->get_string("name") == name);
4300 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4301 :
4302 3 : array = description->get_array("columns");
4303 1 : CATCH_REQUIRE(array.size() == 1);
4304 1 : CATCH_REQUIRE(array[0] == column1);
4305 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4306 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4307 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4308 :
4309 : {
4310 1 : prinbee::reference_t start_offset(0);
4311 1 : prinbee::virtual_buffer::pointer_t b(description->get_virtual_buffer(start_offset));
4312 1 : CATCH_REQUIRE(b != nullptr);
4313 1 : CATCH_REQUIRE(b->size() == description->get_current_size());
4314 :
4315 3 : prinbee::buffer_t buffer(b->size());
4316 1 : CATCH_REQUIRE(b->pread(buffer.data(), buffer.size(), 0) == static_cast<int>(buffer.size()));
4317 :
4318 1 : prinbee::virtual_buffer::pointer_t n(std::make_shared<prinbee::virtual_buffer>());
4319 1 : n->pwrite(buffer.data(), buffer.size(), 0, true);
4320 :
4321 1 : prinbee::structure::pointer_t d(std::make_shared<prinbee::structure>(g_description9));
4322 1 : d->set_virtual_buffer(n, 0);
4323 :
4324 1 : CATCH_REQUIRE(d->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4325 3 : CATCH_REQUIRE(d->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4326 3 : CATCH_REQUIRE(d->get_string("name") == name);
4327 3 : CATCH_REQUIRE(d->get_string("comment") == comment_field);
4328 :
4329 3 : array = d->get_array("columns");
4330 1 : CATCH_REQUIRE(array.size() == 1);
4331 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4332 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4333 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4334 1 : }
4335 :
4336 : // column #2
4337 : //
4338 3 : prinbee::structure::pointer_t column2(description->new_array_item("columns"));
4339 :
4340 3 : CATCH_REQUIRE(column2->get_string("colname") == "_undefined");
4341 3 : std::string const column2_name("wide_col2_long_name_here");
4342 3 : column2->set_string("colname", column2_name);
4343 3 : CATCH_REQUIRE(column2->get_string("colname") == column2_name);
4344 :
4345 3 : CATCH_REQUIRE(column2->get_uinteger("max_size") == 256);
4346 1 : std::uint16_t column2_max_size(0);
4347 1 : SNAP_CATCH2_NAMESPACE::random(column2_max_size);
4348 3 : column2->set_uinteger("max_size", column2_max_size);
4349 3 : CATCH_REQUIRE(column2->get_uinteger("max_size") == column2_max_size);
4350 :
4351 3 : CATCH_REQUIRE(column2->get_uinteger("type") == 14);
4352 1 : std::uint16_t column2_type(0);
4353 1 : SNAP_CATCH2_NAMESPACE::random(column2_type);
4354 3 : column2->set_uinteger("type", column2_type);
4355 3 : CATCH_REQUIRE(column2->get_uinteger("type") == column2_type);
4356 :
4357 : // make sure the root & column1 were not affected
4358 : //
4359 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4360 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4361 3 : CATCH_REQUIRE(description->get_string("name") == name);
4362 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4363 :
4364 3 : array = description->get_array("columns");
4365 1 : CATCH_REQUIRE(array.size() == 2);
4366 1 : CATCH_REQUIRE(array[0] == column1);
4367 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4368 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4369 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4370 1 : CATCH_REQUIRE(array[1] == column2);
4371 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
4372 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
4373 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4374 :
4375 : // now change the root structure (name) and make sure that column #1 is still fine
4376 : //
4377 1 : name = "smaller_name_this_time";
4378 3 : description->set_string("name", name);
4379 :
4380 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4381 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4382 3 : CATCH_REQUIRE(description->get_string("name") == name);
4383 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4384 :
4385 3 : array = description->get_array("columns");
4386 1 : CATCH_REQUIRE(array.size() == 2);
4387 1 : CATCH_REQUIRE(array[0] == column1);
4388 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4389 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4390 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4391 1 : CATCH_REQUIRE(array[1] == column2);
4392 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
4393 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
4394 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4395 :
4396 : // change the root structure again (comment) and make sure that column #1 is still fine
4397 : //
4398 1 : comment_field = "So many ALTER happening here! I just can't believe it's all working.";
4399 3 : description->set_string("comment", comment_field);
4400 :
4401 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4402 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4403 3 : CATCH_REQUIRE(description->get_string("name") == name);
4404 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4405 :
4406 3 : array = description->get_array("columns");
4407 1 : CATCH_REQUIRE(array.size() == 2);
4408 1 : CATCH_REQUIRE(array[0] == column1);
4409 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4410 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4411 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4412 1 : CATCH_REQUIRE(array[1] == column2);
4413 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
4414 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
4415 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4416 :
4417 : {
4418 1 : prinbee::reference_t start_offset(0);
4419 1 : prinbee::virtual_buffer::pointer_t b(description->get_virtual_buffer(start_offset));
4420 1 : CATCH_REQUIRE(b != nullptr);
4421 1 : CATCH_REQUIRE(b->size() == description->get_current_size());
4422 :
4423 3 : prinbee::buffer_t buffer(b->size());
4424 1 : CATCH_REQUIRE(b->pread(buffer.data(), buffer.size(), 0) == static_cast<int>(buffer.size()));
4425 :
4426 1 : prinbee::virtual_buffer::pointer_t n(std::make_shared<prinbee::virtual_buffer>());
4427 1 : n->pwrite(buffer.data(), buffer.size(), 0, true);
4428 :
4429 1 : prinbee::structure::pointer_t d(std::make_shared<prinbee::structure>(g_description9));
4430 1 : d->set_virtual_buffer(n, 0);
4431 :
4432 1 : CATCH_REQUIRE(d->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4433 3 : CATCH_REQUIRE(d->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4434 3 : CATCH_REQUIRE(d->get_string("name") == name);
4435 3 : CATCH_REQUIRE(d->get_string("comment") == comment_field);
4436 :
4437 3 : array = d->get_array("columns");
4438 1 : CATCH_REQUIRE(array.size() == 2);
4439 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4440 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4441 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4442 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
4443 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
4444 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4445 1 : }
4446 :
4447 : // column #3
4448 : //
4449 3 : prinbee::structure::pointer_t column3(description->new_array_item("columns"));
4450 :
4451 3 : CATCH_REQUIRE(column3->get_string("colname") == "_undefined");
4452 3 : std::string const column3_name("col3__here");
4453 3 : column3->set_string("colname", column3_name);
4454 3 : CATCH_REQUIRE(column3->get_string("colname") == column3_name);
4455 :
4456 3 : CATCH_REQUIRE(column3->get_uinteger("max_size") == 256);
4457 1 : std::uint16_t column3_max_size(0);
4458 1 : SNAP_CATCH2_NAMESPACE::random(column3_max_size);
4459 3 : column3->set_uinteger("max_size", column3_max_size);
4460 3 : CATCH_REQUIRE(column3->get_uinteger("max_size") == column3_max_size);
4461 :
4462 3 : CATCH_REQUIRE(column3->get_uinteger("type") == 14);
4463 1 : std::uint16_t column3_type(0);
4464 1 : SNAP_CATCH2_NAMESPACE::random(column3_type);
4465 3 : column3->set_uinteger("type", column3_type);
4466 3 : CATCH_REQUIRE(column3->get_uinteger("type") == column3_type);
4467 :
4468 : // make sure the root & column 1/2 are not affected
4469 : //
4470 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4471 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4472 3 : CATCH_REQUIRE(description->get_string("name") == name);
4473 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4474 :
4475 3 : array = description->get_array("columns");
4476 1 : CATCH_REQUIRE(array.size() == 3);
4477 1 : CATCH_REQUIRE(array[0] == column1);
4478 3 : CATCH_REQUIRE(column1->get_string("colname") == column1_name);
4479 3 : CATCH_REQUIRE(column1->get_uinteger("max_size") == column1_max_size);
4480 3 : CATCH_REQUIRE(column1->get_uinteger("type") == column1_type);
4481 1 : CATCH_REQUIRE(array[1] == column2);
4482 3 : CATCH_REQUIRE(column2->get_string("colname") == column2_name);
4483 3 : CATCH_REQUIRE(column2->get_uinteger("max_size") == column2_max_size);
4484 3 : CATCH_REQUIRE(column2->get_uinteger("type") == column2_type);
4485 1 : CATCH_REQUIRE(array[2] == column3);
4486 3 : CATCH_REQUIRE(column3->get_string("colname") == column3_name);
4487 3 : CATCH_REQUIRE(column3->get_uinteger("max_size") == column3_max_size);
4488 3 : CATCH_REQUIRE(column3->get_uinteger("type") == column3_type);
4489 :
4490 : // now change the root structure (name) and make sure that column #1 is still fine
4491 : //
4492 1 : name = "pretty_much_final_name";
4493 3 : description->set_string("name", name);
4494 :
4495 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4496 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4497 3 : CATCH_REQUIRE(description->get_string("name") == name);
4498 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4499 :
4500 3 : array = description->get_array("columns");
4501 1 : CATCH_REQUIRE(array.size() == 3);
4502 1 : CATCH_REQUIRE(array[0] == column1);
4503 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4504 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4505 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4506 1 : CATCH_REQUIRE(array[1] == column2);
4507 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
4508 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
4509 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4510 1 : CATCH_REQUIRE(array[2] == column3);
4511 3 : CATCH_REQUIRE(array[2]->get_string("colname") == column3_name);
4512 3 : CATCH_REQUIRE(array[2]->get_uinteger("max_size") == column3_max_size);
4513 3 : CATCH_REQUIRE(array[2]->get_uinteger("type") == column3_type);
4514 :
4515 : // change the root structure again (comment) and make sure that column #1 is still fine
4516 : //
4517 1 : comment_field = "Final comment.";
4518 3 : description->set_string("comment", comment_field);
4519 :
4520 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4521 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4522 3 : CATCH_REQUIRE(description->get_string("name") == name);
4523 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4524 :
4525 3 : array = description->get_array("columns");
4526 1 : CATCH_REQUIRE(array.size() == 3);
4527 1 : CATCH_REQUIRE(array[0] == column1);
4528 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4529 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4530 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4531 1 : CATCH_REQUIRE(array[1] == column2);
4532 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
4533 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
4534 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4535 1 : CATCH_REQUIRE(array[2] == column3);
4536 3 : CATCH_REQUIRE(array[2]->get_string("colname") == column3_name);
4537 3 : CATCH_REQUIRE(array[2]->get_uinteger("max_size") == column3_max_size);
4538 3 : CATCH_REQUIRE(array[2]->get_uinteger("type") == column3_type);
4539 : //{
4540 : //prinbee::reference_t start_offset(0);
4541 : //prinbee::virtual_buffer::pointer_t buffer(description->get_virtual_buffer(start_offset));
4542 : //std::cout << std::flush << "column3 at the end -- buffer start offset: " << start_offset << "\n" << *buffer << std::endl;
4543 : //description->display_offsets();
4544 : //}
4545 : {
4546 1 : prinbee::reference_t start_offset(0);
4547 1 : prinbee::virtual_buffer::pointer_t b(description->get_virtual_buffer(start_offset));
4548 1 : CATCH_REQUIRE(b != nullptr);
4549 1 : CATCH_REQUIRE(b->size() == description->get_current_size());
4550 :
4551 3 : prinbee::buffer_t buffer(b->size());
4552 1 : CATCH_REQUIRE(b->pread(buffer.data(), buffer.size(), 0) == static_cast<int>(buffer.size()));
4553 :
4554 1 : prinbee::virtual_buffer::pointer_t n(std::make_shared<prinbee::virtual_buffer>());
4555 1 : n->pwrite(buffer.data(), buffer.size(), 0, true);
4556 :
4557 1 : prinbee::structure::pointer_t d(std::make_shared<prinbee::structure>(g_description9));
4558 1 : d->set_virtual_buffer(n, 0);
4559 :
4560 1 : CATCH_REQUIRE(d->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4561 3 : CATCH_REQUIRE(d->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4562 3 : CATCH_REQUIRE(d->get_string("name") == name);
4563 3 : CATCH_REQUIRE(d->get_string("comment") == comment_field);
4564 :
4565 3 : array = d->get_array("columns");
4566 1 : CATCH_REQUIRE(array.size() == 3);
4567 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4568 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4569 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4570 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
4571 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
4572 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4573 3 : CATCH_REQUIRE(array[2]->get_string("colname") == column3_name);
4574 3 : CATCH_REQUIRE(array[2]->get_uinteger("max_size") == column3_max_size);
4575 3 : CATCH_REQUIRE(array[2]->get_uinteger("type") == column3_type);
4576 1 : }
4577 :
4578 : // delete column 3
4579 : //
4580 3 : description->delete_array_item("columns", 2);
4581 :
4582 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4583 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4584 3 : CATCH_REQUIRE(description->get_string("name") == name);
4585 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4586 :
4587 3 : array = description->get_array("columns");
4588 1 : CATCH_REQUIRE(array.size() == 2);
4589 1 : CATCH_REQUIRE(array[0] == column1);
4590 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4591 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4592 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4593 1 : CATCH_REQUIRE(array[1] == column2);
4594 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
4595 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
4596 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4597 : //{
4598 : //prinbee::reference_t start_offset(0);
4599 : //prinbee::virtual_buffer::pointer_t buffer(description->get_virtual_buffer(start_offset));
4600 : //std::cout << std::flush << "column3 at the end -- buffer start offset: " << start_offset << "\n" << *buffer << std::endl;
4601 : //description->display_offsets();
4602 : //}
4603 : {
4604 1 : prinbee::reference_t start_offset(0);
4605 1 : prinbee::virtual_buffer::pointer_t b(description->get_virtual_buffer(start_offset));
4606 1 : CATCH_REQUIRE(b != nullptr);
4607 1 : CATCH_REQUIRE(b->size() == description->get_current_size());
4608 :
4609 3 : prinbee::buffer_t buffer(b->size());
4610 1 : CATCH_REQUIRE(b->pread(buffer.data(), buffer.size(), 0) == static_cast<int>(buffer.size()));
4611 :
4612 1 : prinbee::virtual_buffer::pointer_t n(std::make_shared<prinbee::virtual_buffer>());
4613 1 : n->pwrite(buffer.data(), buffer.size(), 0, true);
4614 :
4615 1 : prinbee::structure::pointer_t d(std::make_shared<prinbee::structure>(g_description9));
4616 1 : d->set_virtual_buffer(n, 0);
4617 :
4618 1 : CATCH_REQUIRE(d->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4619 3 : CATCH_REQUIRE(d->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4620 3 : CATCH_REQUIRE(d->get_string("name") == name);
4621 3 : CATCH_REQUIRE(d->get_string("comment") == comment_field);
4622 :
4623 3 : array = d->get_array("columns");
4624 1 : CATCH_REQUIRE(array.size() == 2);
4625 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column1_name);
4626 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column1_max_size);
4627 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4628 3 : CATCH_REQUIRE(array[1]->get_string("colname") == column2_name);
4629 3 : CATCH_REQUIRE(array[1]->get_uinteger("max_size") == column2_max_size);
4630 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4631 1 : }
4632 :
4633 : // delete column 1
4634 : //
4635 3 : description->delete_array_item("columns", 0);
4636 :
4637 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4638 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4639 3 : CATCH_REQUIRE(description->get_string("name") == name);
4640 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4641 :
4642 3 : array = description->get_array("columns");
4643 1 : CATCH_REQUIRE(array.size() == 1);
4644 1 : CATCH_REQUIRE(array[0] == column2);
4645 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column2_name);
4646 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column2_max_size);
4647 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column2_type);
4648 : //{
4649 : //prinbee::reference_t start_offset(0);
4650 : //prinbee::virtual_buffer::pointer_t buffer(description->get_virtual_buffer(start_offset));
4651 : //std::cout << std::flush << "column3 at the end -- buffer start offset: " << start_offset << "\n" << *buffer << std::endl;
4652 : //description->display_offsets();
4653 : //}
4654 : {
4655 1 : prinbee::reference_t start_offset(0);
4656 1 : prinbee::virtual_buffer::pointer_t b(description->get_virtual_buffer(start_offset));
4657 1 : CATCH_REQUIRE(b != nullptr);
4658 1 : CATCH_REQUIRE(b->size() == description->get_current_size());
4659 :
4660 3 : prinbee::buffer_t buffer(b->size());
4661 1 : CATCH_REQUIRE(b->pread(buffer.data(), buffer.size(), 0) == static_cast<int>(buffer.size()));
4662 :
4663 1 : prinbee::virtual_buffer::pointer_t n(std::make_shared<prinbee::virtual_buffer>());
4664 1 : n->pwrite(buffer.data(), buffer.size(), 0, true);
4665 :
4666 1 : prinbee::structure::pointer_t d(std::make_shared<prinbee::structure>(g_description9));
4667 1 : d->set_virtual_buffer(n, 0);
4668 :
4669 1 : CATCH_REQUIRE(d->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4670 3 : CATCH_REQUIRE(d->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4671 3 : CATCH_REQUIRE(d->get_string("name") == name);
4672 3 : CATCH_REQUIRE(d->get_string("comment") == comment_field);
4673 :
4674 3 : array = d->get_array("columns");
4675 1 : CATCH_REQUIRE(array.size() == 1);
4676 3 : CATCH_REQUIRE(array[0]->get_string("colname") == column2_name);
4677 3 : CATCH_REQUIRE(array[0]->get_uinteger("max_size") == column2_max_size);
4678 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column2_type);
4679 1 : }
4680 :
4681 : // delete column 2 (which is now at offset 0)
4682 : //
4683 3 : description->delete_array_item("columns", 0);
4684 :
4685 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4686 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4687 3 : CATCH_REQUIRE(description->get_string("name") == name);
4688 3 : CATCH_REQUIRE(description->get_string("comment") == comment_field);
4689 :
4690 3 : array = description->get_array("columns");
4691 1 : CATCH_REQUIRE(array.size() == 0);
4692 : //{
4693 : //prinbee::reference_t start_offset(0);
4694 : //prinbee::virtual_buffer::pointer_t buffer(description->get_virtual_buffer(start_offset));
4695 : //std::cout << std::flush << "column3 at the end -- buffer start offset: " << start_offset << "\n" << *buffer << std::endl;
4696 : //description->display_offsets();
4697 : //}
4698 : {
4699 1 : prinbee::reference_t start_offset(0);
4700 1 : prinbee::virtual_buffer::pointer_t b(description->get_virtual_buffer(start_offset));
4701 1 : CATCH_REQUIRE(b != nullptr);
4702 1 : CATCH_REQUIRE(b->size() == description->get_current_size());
4703 :
4704 3 : prinbee::buffer_t buffer(b->size());
4705 1 : CATCH_REQUIRE(b->pread(buffer.data(), buffer.size(), 0) == static_cast<int>(buffer.size()));
4706 :
4707 1 : prinbee::virtual_buffer::pointer_t n(std::make_shared<prinbee::virtual_buffer>());
4708 1 : n->pwrite(buffer.data(), buffer.size(), 0, true);
4709 :
4710 1 : prinbee::structure::pointer_t d(std::make_shared<prinbee::structure>(g_description9));
4711 1 : d->set_virtual_buffer(n, 0);
4712 :
4713 1 : CATCH_REQUIRE(d->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS);
4714 3 : CATCH_REQUIRE(d->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(1, 2));
4715 3 : CATCH_REQUIRE(d->get_string("name") == name);
4716 3 : CATCH_REQUIRE(d->get_string("comment") == comment_field);
4717 :
4718 3 : array = d->get_array("columns");
4719 1 : CATCH_REQUIRE(array.size() == 0);
4720 1 : }
4721 1 : }
4722 5 : CATCH_END_SECTION()
4723 :
4724 6 : CATCH_START_SECTION("structure_array: structure with an ARRAY8 at the end of the structure")
4725 : {
4726 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description11));
4727 :
4728 : // the array make this structure dynamic
4729 : //
4730 1 : CATCH_REQUIRE(description->get_static_size() == 0UL);
4731 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 32UL + 1UL);
4732 :
4733 1 : description->init_buffer();
4734 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 32UL + 1UL);
4735 :
4736 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_SCHEMA_LIST);
4737 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(5, 29));
4738 :
4739 : // changing the CHAR data does not change the size
4740 : //
4741 3 : CATCH_REQUIRE(description->get_string("name") == "passwords");
4742 3 : std::string const name("different_name");
4743 3 : description->set_string("name", name);
4744 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 32UL + 1UL);
4745 3 : CATCH_REQUIRE(description->get_string("name") == name);
4746 :
4747 : // now create column definitions
4748 : //
4749 3 : prinbee::structure::pointer_t column1(description->new_array_item("columns"));
4750 :
4751 3 : CATCH_REQUIRE(column1->get_string("name") == "_undefined");
4752 3 : std::string const column1_name("col1");
4753 3 : column1->set_string("name", column1_name);
4754 3 : CATCH_REQUIRE(column1->get_string("name") == column1_name);
4755 :
4756 3 : CATCH_REQUIRE(column1->get_uinteger("type") == 14);
4757 1 : std::uint16_t column1_type(0);
4758 1 : SNAP_CATCH2_NAMESPACE::random(column1_type);
4759 3 : column1->set_uinteger("type", column1_type);
4760 3 : CATCH_REQUIRE(column1->get_uinteger("type") == column1_type);
4761 :
4762 3 : CATCH_REQUIRE(column1->get_uinteger("flags") == 2);
4763 1 : std::uint16_t column1_flags(0);
4764 1 : SNAP_CATCH2_NAMESPACE::random(column1_flags);
4765 1 : column1_flags &= 3;
4766 3 : column1->set_uinteger("flags", column1_flags);
4767 3 : CATCH_REQUIRE(column1->get_uinteger("flags") == column1_flags);
4768 :
4769 : // make sure the root was not affected
4770 : //
4771 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_SCHEMA_LIST);
4772 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(5, 29));
4773 3 : CATCH_REQUIRE(description->get_string("name") == name);
4774 :
4775 3 : prinbee::structure::vector_t array(description->get_array("columns"));
4776 1 : CATCH_REQUIRE(array.size() == 1);
4777 1 : CATCH_REQUIRE(array[0] == column1);
4778 3 : CATCH_REQUIRE(array[0]->get_string("name") == column1_name);
4779 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4780 3 : CATCH_REQUIRE(array[0]->get_uinteger("flags") == column1_flags);
4781 :
4782 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 32UL
4783 : + 1UL + 1UL + column1_name.length() + 2UL + 1UL);
4784 :
4785 : // column #2
4786 : //
4787 3 : prinbee::structure::pointer_t column2(description->new_array_item("columns"));
4788 :
4789 3 : CATCH_REQUIRE(column2->get_string("name") == "_undefined");
4790 3 : std::string const column2_name("col2_long_name_here");
4791 3 : column2->set_string("name", column2_name);
4792 3 : CATCH_REQUIRE(column2->get_string("name") == column2_name);
4793 :
4794 3 : CATCH_REQUIRE(column2->get_uinteger("type") == 14);
4795 1 : std::uint16_t column2_type(0);
4796 1 : SNAP_CATCH2_NAMESPACE::random(column2_type);
4797 3 : column2->set_uinteger("type", column2_type);
4798 3 : CATCH_REQUIRE(column2->get_uinteger("type") == column2_type);
4799 :
4800 3 : CATCH_REQUIRE(column2->get_uinteger("flags") == 2);
4801 1 : std::uint16_t column2_flags(0);
4802 1 : SNAP_CATCH2_NAMESPACE::random(column2_flags);
4803 1 : column2_flags &= 3;
4804 3 : column2->set_uinteger("flags", column2_flags);
4805 3 : CATCH_REQUIRE(column2->get_uinteger("flags") == column2_flags);
4806 :
4807 : // make sure the root & column1 were not affected
4808 : //
4809 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_SCHEMA_LIST);
4810 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(5, 29));
4811 3 : CATCH_REQUIRE(description->get_string("name") == name);
4812 :
4813 3 : array = description->get_array("columns");
4814 1 : CATCH_REQUIRE(array.size() == 2);
4815 1 : CATCH_REQUIRE(array[0] == column1);
4816 3 : CATCH_REQUIRE(array[0]->get_string("name") == column1_name);
4817 3 : CATCH_REQUIRE(array[0]->get_uinteger("type") == column1_type);
4818 3 : CATCH_REQUIRE(array[0]->get_uinteger("flags") == column1_flags);
4819 1 : CATCH_REQUIRE(array[1] == column2);
4820 3 : CATCH_REQUIRE(array[1]->get_string("name") == column2_name);
4821 3 : CATCH_REQUIRE(array[1]->get_uinteger("type") == column2_type);
4822 3 : CATCH_REQUIRE(array[1]->get_uinteger("flags") == column2_flags);
4823 :
4824 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 32UL
4825 : + 1UL + 1UL + column1_name.length() + 2UL + 1UL
4826 : + 1UL + column2_name.length() + 2UL + 1UL);
4827 :
4828 : // column #3
4829 : //
4830 3 : prinbee::structure::pointer_t column3(description->new_array_item("columns"));
4831 :
4832 3 : CATCH_REQUIRE(column3->get_string("name") == "_undefined");
4833 3 : std::string const column3_name("col3__here");
4834 3 : column3->set_string("name", column3_name);
4835 3 : CATCH_REQUIRE(column3->get_string("name") == column3_name);
4836 :
4837 3 : CATCH_REQUIRE(column3->get_uinteger("type") == 14);
4838 1 : std::uint16_t column3_type(0);
4839 1 : SNAP_CATCH2_NAMESPACE::random(column3_type);
4840 3 : column3->set_uinteger("type", column3_type);
4841 3 : CATCH_REQUIRE(column3->get_uinteger("type") == column3_type);
4842 :
4843 3 : CATCH_REQUIRE(column3->get_uinteger("flags") == 2);
4844 1 : std::uint16_t column3_flags(0);
4845 1 : SNAP_CATCH2_NAMESPACE::random(column3_flags);
4846 1 : column3_flags &= 3;
4847 3 : column3->set_uinteger("flags", column3_flags);
4848 3 : CATCH_REQUIRE(column3->get_uinteger("flags") == column3_flags);
4849 :
4850 : // make sure the root & column 1/2 are not affected
4851 : //
4852 1 : CATCH_REQUIRE(description->get_magic() == prinbee::dbtype_t::BLOCK_TYPE_SCHEMA_LIST);
4853 3 : CATCH_REQUIRE(description->get_version(prinbee::g_system_field_name_structure_version) == prinbee::version_t(5, 29));
4854 3 : CATCH_REQUIRE(description->get_string("name") == name);
4855 :
4856 3 : array = description->get_array("columns");
4857 1 : CATCH_REQUIRE(array.size() == 3);
4858 1 : CATCH_REQUIRE(array[0] == column1);
4859 3 : CATCH_REQUIRE(column1->get_string("name") == column1_name);
4860 3 : CATCH_REQUIRE(column1->get_uinteger("type") == column1_type);
4861 3 : CATCH_REQUIRE(column1->get_uinteger("flags") == column1_flags);
4862 1 : CATCH_REQUIRE(array[1] == column2);
4863 3 : CATCH_REQUIRE(column2->get_string("name") == column2_name);
4864 3 : CATCH_REQUIRE(column2->get_uinteger("type") == column2_type);
4865 3 : CATCH_REQUIRE(column2->get_uinteger("flags") == column2_flags);
4866 1 : CATCH_REQUIRE(array[2] == column3);
4867 3 : CATCH_REQUIRE(column3->get_string("name") == column3_name);
4868 3 : CATCH_REQUIRE(column3->get_uinteger("type") == column3_type);
4869 3 : CATCH_REQUIRE(column3->get_uinteger("flags") == column3_flags);
4870 :
4871 1 : CATCH_REQUIRE(description->get_current_size() == 4UL + 4UL + 32UL
4872 : + 1UL + 1UL + column1_name.length() + 2UL + 1UL
4873 : + 1UL + column2_name.length() + 2UL + 1UL
4874 : + 1UL + column3_name.length() + 2UL + 1UL);
4875 : //{
4876 : //prinbee::reference_t start_offset(0);
4877 : //prinbee::virtual_buffer::pointer_t buffer(description->get_virtual_buffer(start_offset));
4878 : //std::cout << std::flush << "column3 at the end -- buffer start offset: " << start_offset << "\n" << *buffer << std::endl;
4879 : //description->display_offsets();
4880 : //}
4881 :
4882 : // another way to setup an array is to create items in a vector
4883 : // and then save that vector in our structure
4884 : //
4885 :
4886 : //prinbee::structure::vector_t v;
4887 : //prinbee::structure::pointer_t s1(std::make_shared<prinbee::structure>(g_description11_column));
4888 : //v.push_back(s1);
4889 : //prinbee::structure::pointer_t s2(std::make_shared<prinbee::structure>(g_description11_column));
4890 : //v.push_back(s2);
4891 : //prinbee::structure::pointer_t s3(std::make_shared<prinbee::structure>(g_description11_column));
4892 : //v.push_back(s3);
4893 : //f->set_sub_structures(v);
4894 : //CATCH_REQUIRE((*f)[0] == s1);
4895 : //CATCH_REQUIRE((*f)[1] == s2);
4896 : //CATCH_REQUIRE((*f)[2] == s3);
4897 :
4898 : // column #4 and beyond (we want to test an overflow, see after loop)
4899 : //
4900 : // WARNING: the following adds column #4 to column #255--we cannot
4901 : // have 256 columns since the 8 bit counters can be 0 to
4902 : // 255 with 0 representing an empty array
4903 : //
4904 253 : for(int count(4); count < 256; ++count)
4905 : {
4906 756 : description->new_array_item("columns");
4907 : }
4908 :
4909 : // further attempts to add array items fail
4910 : //
4911 11 : for(int count(0); count < 10; ++ count)
4912 : {
4913 80 : CATCH_REQUIRE_THROWS_MATCHES(
4914 : description->new_array_item("columns")
4915 : , prinbee::out_of_range
4916 : , Catch::Matchers::ExceptionMessage(
4917 : "out_of_range: the new_array_item() function cannot be"
4918 : " used because the array is already full with 256 items."));
4919 : }
4920 :
4921 : // now randomly remove columns one by one
4922 : //
4923 : // Remember we only have 255 entries, not 256, since the size has to
4924 : // fit in 8 bits and 0 does represent "no items"
4925 : //
4926 256 : for(int count(0); count < 255; ++count)
4927 : {
4928 255 : std::size_t max(0);
4929 255 : if((rand() & 1) != 0)
4930 : {
4931 414 : max = std::const_pointer_cast<prinbee::structure const>(description)->get_array("columns").size();
4932 : }
4933 : else
4934 : {
4935 351 : max = description->get_array("columns").size();
4936 : }
4937 255 : int const idx(rand() % max);
4938 765 : description->delete_array_item("columns", idx);
4939 :
4940 : // attempts to delete a non-existent item fails
4941 : //
4942 255 : int index(max + rand());
4943 1275 : CATCH_REQUIRE_THROWS_MATCHES(
4944 : description->delete_array_item("columns", index)
4945 : , prinbee::out_of_range
4946 : , Catch::Matchers::ExceptionMessage(
4947 : "out_of_range: the index ("
4948 : + std::to_string(index)
4949 : + ") in delete_array_item() function is out of range (larger or equal to the size: "
4950 : + std::to_string(max - 1) // -1 because we deleted one item above
4951 : + ")."));
4952 : }
4953 :
4954 : // further attempts to delete any array item fail
4955 : //
4956 11 : for(int count(0); count < 10; ++ count)
4957 : {
4958 50 : CATCH_REQUIRE_THROWS_MATCHES(
4959 : description->delete_array_item("columns", count)
4960 : , prinbee::out_of_range
4961 : , Catch::Matchers::ExceptionMessage(
4962 : "out_of_range: the index ("
4963 : + std::to_string(count)
4964 : + ") in delete_array_item() function is out of range (larger or equal to the size: 0)."));
4965 : }
4966 :
4967 3 : CATCH_REQUIRE(description->get_array("columns").empty());
4968 1 : }
4969 5 : CATCH_END_SECTION()
4970 4 : }
4971 :
4972 :
4973 41 : CATCH_TEST_CASE("structure_invalid", "[structure][invalid]")
4974 : {
4975 43 : CATCH_START_SECTION("structure_invalid: missing description (nullptr)")
4976 : {
4977 6 : CATCH_REQUIRE_THROWS_MATCHES(
4978 : new prinbee::structure(nullptr)
4979 : , prinbee::logic_error
4980 : , Catch::Matchers::ExceptionMessage("logic_error: the description parameter of a structure object cannot be null."));
4981 : }
4982 42 : CATCH_END_SECTION()
4983 :
4984 43 : CATCH_START_SECTION("structure_invalid: missing description (empty)")
4985 : {
4986 1 : prinbee::struct_description_t description[] =
4987 : {
4988 : prinbee::end_descriptions()
4989 : };
4990 6 : CATCH_REQUIRE_THROWS_MATCHES(
4991 : new prinbee::structure(description)
4992 : , prinbee::logic_error
4993 : , Catch::Matchers::ExceptionMessage("logic_error: the root description of a structure must start with a magic field followed by a structure version."));
4994 : }
4995 42 : CATCH_END_SECTION()
4996 :
4997 43 : CATCH_START_SECTION("structure_invalid: structure version missing in description")
4998 : {
4999 4 : CATCH_REQUIRE_THROWS_MATCHES(
5000 : std::make_shared<prinbee::structure>(g_description4a)
5001 : , prinbee::logic_error
5002 : , Catch::Matchers::ExceptionMessage("logic_error: the root description of a structure must start with a magic field followed by a structure version."));
5003 : }
5004 42 : CATCH_END_SECTION()
5005 :
5006 43 : CATCH_START_SECTION("structure_invalid: magic missing in description")
5007 : {
5008 4 : CATCH_REQUIRE_THROWS_MATCHES(
5009 : std::make_shared<prinbee::structure>(g_description4b)
5010 : , prinbee::logic_error
5011 : , Catch::Matchers::ExceptionMessage("logic_error: the root description of a structure must start with a magic field followed by a structure version."));
5012 : }
5013 42 : CATCH_END_SECTION()
5014 :
5015 43 : CATCH_START_SECTION("structure_invalid: get/set string against a different type")
5016 : {
5017 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description9));
5018 1 : description->init_buffer();
5019 :
5020 8 : CATCH_REQUIRE_THROWS_MATCHES(
5021 : description->get_string("columns")
5022 : , prinbee::type_mismatch
5023 : , Catch::Matchers::ExceptionMessage(
5024 : "prinbee_exception: this field type is \"ARRAY32\" but we expected one of \"CHAR, P8STRING, P16STRING, P32STRING\"."));
5025 :
5026 11 : CATCH_REQUIRE_THROWS_MATCHES(
5027 : description->set_string("columns", "anything")
5028 : , prinbee::type_mismatch
5029 : , Catch::Matchers::ExceptionMessage(
5030 : "prinbee_exception: this field type is \"ARRAY32\" but we expected one of \"CHAR, P8STRING, P16STRING, P32STRING\"."));
5031 1 : }
5032 42 : CATCH_END_SECTION()
5033 :
5034 43 : CATCH_START_SECTION("structure_invalid: get/new array against a different type")
5035 : {
5036 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description9));
5037 1 : description->init_buffer();
5038 :
5039 7 : CATCH_REQUIRE_THROWS_MATCHES(
5040 : description->get_array("name")
5041 : , prinbee::type_mismatch
5042 : , Catch::Matchers::ExceptionMessage(
5043 : "prinbee_exception: this field type is \"P8STRING\" but we expected one of \"ARRAY8, ARRAY16, ARRAY32\"."));
5044 :
5045 8 : CATCH_REQUIRE_THROWS_MATCHES(
5046 : description->new_array_item("name")
5047 : , prinbee::type_mismatch
5048 : , Catch::Matchers::ExceptionMessage(
5049 : "prinbee_exception: this field type is \"P8STRING\" but we expected one of \"ARRAY8, ARRAY16, ARRAY32\"."));
5050 :
5051 7 : CATCH_REQUIRE_THROWS_MATCHES(
5052 : description->delete_array_item("name", 0)
5053 : , prinbee::type_mismatch
5054 : , Catch::Matchers::ExceptionMessage(
5055 : "prinbee_exception: this field type is \"P8STRING\" but we expected one of \"ARRAY8, ARRAY16, ARRAY32\"."));
5056 1 : }
5057 42 : CATCH_END_SECTION()
5058 :
5059 43 : CATCH_START_SECTION("structure_invalid: get/set string with damaged buffer")
5060 : {
5061 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description9));
5062 1 : description->init_buffer();
5063 :
5064 : // at the moment, everything is fine
5065 : //
5066 3 : CATCH_REQUIRE(description->get_string("name") == "page");
5067 :
5068 1 : prinbee::reference_t start_offset(0);
5069 1 : prinbee::virtual_buffer::pointer_t buffer(description->get_virtual_buffer(start_offset));
5070 1 : std::uint8_t size(9);
5071 1 : buffer->pwrite(
5072 : &size
5073 : , sizeof(size)
5074 : , 4 + 4); // skip magic & structure version
5075 :
5076 8 : CATCH_REQUIRE_THROWS_MATCHES(
5077 : description->get_string("name")
5078 : , prinbee::corrupted_data
5079 : , Catch::Matchers::ExceptionMessage(
5080 : "prinbee_exception: the size of string field \"name\" (4) is"
5081 : " different from the size found in the file (9 found at"
5082 : " offset 8 over 1 bytes)."));
5083 :
5084 11 : CATCH_REQUIRE_THROWS_MATCHES(
5085 : description->set_string("name", "new name")
5086 : , prinbee::corrupted_data
5087 : , Catch::Matchers::ExceptionMessage(
5088 : "prinbee_exception: the size of string field \"name\" (4) is"
5089 : " different from the size found in the file (9 found at"
5090 : " offset 8 over 1 bytes)."));
5091 1 : }
5092 42 : CATCH_END_SECTION()
5093 :
5094 43 : CATCH_START_SECTION("structure_invalid: get/set ARRAY8 with damaged size (a.k.a. number of items)")
5095 : {
5096 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description7));
5097 1 : description->init_buffer();
5098 :
5099 : // create a few columns
5100 : //
5101 1 : std::size_t const max(rand() % 96 + 5);
5102 96 : for(std::size_t idx(0); idx < max; ++idx)
5103 : {
5104 285 : prinbee::structure::pointer_t column(description->new_array_item("columns"));
5105 285 : std::string name("col");
5106 95 : name += std::to_string(idx);
5107 285 : column->set_string("colname", name);
5108 285 : CATCH_REQUIRE(column->get_string("colname") == name);
5109 95 : }
5110 :
5111 1 : prinbee::reference_t start_offset(0);
5112 1 : prinbee::virtual_buffer::pointer_t buffer(description->get_virtual_buffer(start_offset));
5113 1 : std::uint8_t const size(200);
5114 1 : buffer->pwrite(
5115 : &size
5116 : , sizeof(size)
5117 : , 4 + 4 + 32); // skip magic & structure version & name (a CHAR(32))
5118 :
5119 1 : int const to_delete(rand() & 255);
5120 5 : CATCH_REQUIRE_THROWS_MATCHES(
5121 : description->delete_array_item("columns", to_delete)
5122 : , prinbee::corrupted_data
5123 : , Catch::Matchers::ExceptionMessage(
5124 : "prinbee_exception: the number of array items is"
5125 : " different in our buffer and our field (read "
5126 : + std::to_string(static_cast<int>(size))
5127 : + " from the buffer, found "
5128 : + std::to_string(max)
5129 : + " in our in memory array)."));
5130 1 : }
5131 42 : CATCH_END_SECTION()
5132 :
5133 43 : CATCH_START_SECTION("structure_invalid: get BUFFER8 with damaged size")
5134 : {
5135 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description5));
5136 1 : description->init_buffer();
5137 :
5138 : // create a buffer
5139 : //
5140 1 : std::size_t const max(rand() % 96 + 5);
5141 3 : prinbee::buffer_t value(max);
5142 65 : for(std::size_t idx(0); idx < max; ++idx)
5143 : {
5144 64 : value[idx] = rand();
5145 : }
5146 3 : description->set_buffer("early_version.parts", value);
5147 :
5148 1 : prinbee::reference_t start_offset(0);
5149 1 : prinbee::virtual_buffer::pointer_t buffer(description->get_virtual_buffer(start_offset));
5150 1 : std::uint8_t const size(max + rand() % 50 + 1); // a different size
5151 1 : buffer->pwrite(
5152 : &size
5153 : , sizeof(size)
5154 : , 4 + 4 // skip magic & structure version
5155 : + 8 + 16 // sub-field & data
5156 : + 1); // early_version.size
5157 :
5158 6 : CATCH_REQUIRE_THROWS_MATCHES(
5159 : description->get_buffer("early_version.parts")
5160 : , prinbee::corrupted_data
5161 : , Catch::Matchers::ExceptionMessage(
5162 : "prinbee_exception: the existing buffer size ("
5163 : + std::to_string(static_cast<int>(size))
5164 : + ") and field size ("
5165 : + std::to_string(max)
5166 : + ") do not match."));
5167 1 : }
5168 42 : CATCH_END_SECTION()
5169 :
5170 43 : CATCH_START_SECTION("structure_invalid: string too long for this P8STRING")
5171 : {
5172 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description9));
5173 1 : description->init_buffer();
5174 3 : CATCH_REQUIRE(description->get_string("name") == "page");
5175 :
5176 258 : for(std::size_t size(256); size <= 512; ++size)
5177 : {
5178 257 : std::string const name(SNAP_CATCH2_NAMESPACE::random_string(size, size));
5179 1285 : CATCH_REQUIRE_THROWS_MATCHES(
5180 : description->set_string("name", name)
5181 : , prinbee::out_of_range
5182 : , Catch::Matchers::ExceptionMessage(
5183 : "out_of_range: the input string is too large for this string field ("
5184 : + std::to_string(size)
5185 : + " >= 256)."));
5186 257 : }
5187 :
5188 3 : CATCH_REQUIRE(description->get_string("name") == "page");
5189 1 : }
5190 42 : CATCH_END_SECTION()
5191 :
5192 43 : CATCH_START_SECTION("structure_invalid: string too long for this CHAR")
5193 : {
5194 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description7));
5195 1 : description->init_buffer();
5196 3 : CATCH_REQUIRE(description->get_string("name") == "users");
5197 :
5198 225 : for(std::size_t size(33); size <= 256; ++size)
5199 : {
5200 224 : std::string const name(SNAP_CATCH2_NAMESPACE::random_string(size, size));
5201 1120 : CATCH_REQUIRE_THROWS_MATCHES(
5202 : description->set_string("name", name)
5203 : , prinbee::out_of_range
5204 : , Catch::Matchers::ExceptionMessage(
5205 : "out_of_range: the CHAR field is limited to 32 characters. The input string is "
5206 : + std::to_string(size)
5207 : + " characters. It does not fit this field."));
5208 224 : }
5209 :
5210 3 : CATCH_REQUIRE(description->get_string("name") == "users");
5211 1 : }
5212 42 : CATCH_END_SECTION()
5213 :
5214 43 : CATCH_START_SECTION("structure_invalid: invalid CHAR size (missing equal)")
5215 : {
5216 1 : prinbee::struct_description_t description = {
5217 : .f_field_name = "char123",
5218 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_CHAR,
5219 : };
5220 :
5221 : #ifdef _DEBUG
5222 5 : CATCH_REQUIRE_THROWS_MATCHES(
5223 : std::make_shared<prinbee::field_t>(&description)
5224 : , prinbee::logic_error
5225 : , Catch::Matchers::ExceptionMessage("logic_error: char field name & length \"char123\" are not valid."));
5226 : #else
5227 : CATCH_REQUIRE_THROWS_MATCHES(
5228 : std::make_shared<prinbee::field_t>(&description)
5229 : , prinbee::invalid_parameter
5230 : , Catch::Matchers::ExceptionMessage(
5231 : "prinbee_exception: the name of a field of type CHAR must have a size"
5232 : " defined as in \"foo=123\"; \"char123\" is missing an equal (=) character."));
5233 : #endif
5234 : }
5235 42 : CATCH_END_SECTION()
5236 :
5237 43 : CATCH_START_SECTION("structure_invalid: invalid CHAR size (negative size)")
5238 : {
5239 1 : prinbee::struct_description_t description = {
5240 : .f_field_name = "char=-123",
5241 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_CHAR,
5242 : };
5243 :
5244 : #ifdef _DEBUG
5245 5 : CATCH_REQUIRE_THROWS_MATCHES(
5246 : std::make_shared<prinbee::field_t>(&description)
5247 : , prinbee::logic_error
5248 : , Catch::Matchers::ExceptionMessage("logic_error: char field name & length \"char=-123\" are not valid."));
5249 : #else
5250 : CATCH_REQUIRE_THROWS_MATCHES(
5251 : std::make_shared<prinbee::field_t>(&description)
5252 : , prinbee::out_of_range
5253 : , Catch::Matchers::ExceptionMessage(
5254 : "out_of_range: the size in field \"char=-123\" must be at least 1 and no more then 2^32 - 1."));
5255 : #endif
5256 : }
5257 42 : CATCH_END_SECTION()
5258 :
5259 43 : CATCH_START_SECTION("structure_invalid: invalid CHAR size (size too large for 64 bits)")
5260 : {
5261 1 : prinbee::struct_description_t description = {
5262 : .f_field_name = "char=9999999999999999999",
5263 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_CHAR,
5264 : };
5265 :
5266 5 : CATCH_REQUIRE_THROWS_MATCHES(
5267 : std::make_shared<prinbee::field_t>(&description)
5268 : , prinbee::invalid_parameter
5269 : , Catch::Matchers::ExceptionMessage(
5270 : "prinbee_exception: the size in field"
5271 : " \"char=9999999999999999999\" must be a valid decimal number."));
5272 : }
5273 42 : CATCH_END_SECTION()
5274 :
5275 43 : CATCH_START_SECTION("structure_invalid: invalid CHAR size (size of zero)")
5276 : {
5277 1 : prinbee::struct_description_t description = {
5278 : .f_field_name = "char=0",
5279 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_CHAR,
5280 : };
5281 :
5282 5 : CATCH_REQUIRE_THROWS_MATCHES(
5283 : std::make_shared<prinbee::field_t>(&description)
5284 : , prinbee::out_of_range
5285 : , Catch::Matchers::ExceptionMessage(
5286 : "out_of_range: the size in field \"char=0\" must be at least 1 and no more then 2^32 - 1."));
5287 : }
5288 42 : CATCH_END_SECTION()
5289 :
5290 43 : CATCH_START_SECTION("structure_invalid: invalid CHAR size (size too large for 32 bits)")
5291 : {
5292 3 : std::string char_size("char=");
5293 1 : std::uint64_t const size((1ULL << 32) + rand());
5294 1 : char_size += std::to_string(size);
5295 1 : prinbee::struct_description_t description = {
5296 1 : .f_field_name = char_size.c_str(),
5297 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_CHAR,
5298 1 : };
5299 :
5300 3 : CATCH_REQUIRE_THROWS_MATCHES(
5301 : std::make_shared<prinbee::field_t>(&description)
5302 : , prinbee::out_of_range
5303 : , Catch::Matchers::ExceptionMessage(
5304 : "out_of_range: the size in field \""
5305 : + char_size
5306 : + "\" must be at least 1 and no more then 2^32 - 1."));
5307 1 : }
5308 42 : CATCH_END_SECTION()
5309 :
5310 43 : CATCH_START_SECTION("structure_invalid: invalid bit field size (size too large for 8 bits)")
5311 : {
5312 1 : constexpr prinbee::struct_description_t description_definition[] =
5313 : {
5314 : prinbee::define_description(
5315 : prinbee::FieldName("_magic")
5316 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
5317 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS))
5318 : ),
5319 : prinbee::define_description(
5320 : prinbee::FieldName("_structure_version")
5321 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
5322 : , prinbee::FieldVersion(405, 119)
5323 : ),
5324 : prinbee::define_description(
5325 : prinbee::FieldName("bad_bits=large:9")
5326 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS8)
5327 : ),
5328 : prinbee::end_descriptions()
5329 : };
5330 :
5331 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(description_definition));
5332 3 : CATCH_REQUIRE_THROWS_MATCHES(
5333 : description->init_buffer()
5334 : , prinbee::invalid_size
5335 : , Catch::Matchers::ExceptionMessage(
5336 : "prinbee_exception: the total number of bits used by"
5337 : " bit field \"large\" overflows the maximum"
5338 : " allowed of 8."));
5339 1 : }
5340 42 : CATCH_END_SECTION()
5341 :
5342 43 : CATCH_START_SECTION("structure_invalid: invalid bit field size (size is zero)")
5343 : {
5344 1 : constexpr prinbee::struct_description_t description_definition[] =
5345 : {
5346 : prinbee::define_description(
5347 : prinbee::FieldName("_magic")
5348 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
5349 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS))
5350 : ),
5351 : prinbee::define_description(
5352 : prinbee::FieldName("_structure_version")
5353 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
5354 : , prinbee::FieldVersion(405, 119)
5355 : ),
5356 : prinbee::define_description(
5357 : prinbee::FieldName("bad_bits=zero:0")
5358 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS8)
5359 : ),
5360 : prinbee::end_descriptions()
5361 : };
5362 :
5363 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(description_definition));
5364 3 : CATCH_REQUIRE_THROWS_MATCHES(
5365 : description->init_buffer()
5366 : , prinbee::invalid_size
5367 : , Catch::Matchers::ExceptionMessage(
5368 : "prinbee_exception: the size of a bit field must be"
5369 : " positive. \"zero\" was given 0 instead."));
5370 1 : }
5371 42 : CATCH_END_SECTION()
5372 :
5373 43 : CATCH_START_SECTION("structure_invalid: invalid bit field size (size does not fit 64 bits)")
5374 : {
5375 1 : constexpr prinbee::struct_description_t description_definition[] =
5376 : {
5377 : prinbee::define_description(
5378 : prinbee::FieldName("_magic")
5379 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
5380 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS))
5381 : ),
5382 : prinbee::define_description(
5383 : prinbee::FieldName("_structure_version")
5384 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
5385 : , prinbee::FieldVersion(405, 119)
5386 : ),
5387 : prinbee::define_description(
5388 : prinbee::FieldName("bad_bits=giant:9999999999999999999")
5389 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS8)
5390 : ),
5391 : prinbee::end_descriptions()
5392 : };
5393 :
5394 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(description_definition));
5395 3 : CATCH_REQUIRE_THROWS_MATCHES(
5396 : description->init_buffer()
5397 : , prinbee::invalid_size
5398 : , Catch::Matchers::ExceptionMessage(
5399 : "prinbee_exception: the size (9999999999999999999) of bit field \"giant\" is invalid."));
5400 1 : }
5401 42 : CATCH_END_SECTION()
5402 :
5403 43 : CATCH_START_SECTION("structure_invalid: get unknown field")
5404 : {
5405 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description9));
5406 1 : description->init_buffer();
5407 :
5408 : try
5409 : {
5410 5 : description->get_field("unknown.field.name");
5411 0 : throw prinbee::logic_error("the expected exception did not occur.");
5412 : }
5413 1 : catch(prinbee::field_not_found const & e)
5414 : {
5415 3 : CATCH_REQUIRE(e.what() == std::string("prinbee_exception: this description does not include a field named \"unknown\"."));
5416 3 : CATCH_REQUIRE(e.get_parameter("field_name") == "unknown");
5417 3 : CATCH_REQUIRE(e.get_parameter("full_field_name") == "unknown.field.name");
5418 1 : }
5419 :
5420 : //CATCH_REQUIRE_THROWS_MATCHES(
5421 : // description->get_field("unknown.field.name")
5422 : // , prinbee::field_not_found
5423 : // , Catch::Matchers::ExceptionMessage(
5424 : // "prinbee_exception: this description does not include a field named \"unknown\"."));
5425 1 : }
5426 42 : CATCH_END_SECTION()
5427 :
5428 43 : CATCH_START_SECTION("structure_invalid: get unknown field with a sub-name")
5429 : {
5430 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description5));
5431 1 : description->init_buffer();
5432 :
5433 : try
5434 : {
5435 5 : description->get_field("early_version.field");
5436 0 : throw prinbee::logic_error("the expected exception did not occur.");
5437 : }
5438 1 : catch(prinbee::field_not_found const & e)
5439 : {
5440 3 : CATCH_REQUIRE(e.what() == std::string("prinbee_exception: this description does not include a field named \"field\"."));
5441 3 : CATCH_REQUIRE(e.get_parameter("field_name") == "field");
5442 3 : CATCH_REQUIRE(e.get_parameter("full_field_name") == "early_version.field");
5443 1 : }
5444 :
5445 : //CATCH_REQUIRE_THROWS_MATCHES(
5446 : // description->get_field("early_version.field")
5447 : // , prinbee::field_not_found
5448 : // , Catch::Matchers::ExceptionMessage(
5449 : // "prinbee_exception: this description does not include a field named \"field\"."));
5450 1 : }
5451 42 : CATCH_END_SECTION()
5452 :
5453 43 : CATCH_START_SECTION("structure_invalid: get field with wrong type")
5454 : {
5455 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description5));
5456 1 : description->init_buffer();
5457 :
5458 6 : CATCH_REQUIRE_THROWS_MATCHES(
5459 : description->get_field("early_version.size", prinbee::struct_type_t::STRUCT_TYPE_UINT16)
5460 : , prinbee::type_mismatch
5461 : , Catch::Matchers::ExceptionMessage(
5462 : "prinbee_exception: this field type is \""
5463 : + prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT8)
5464 : + "\" but we expected \""
5465 : + prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT16)
5466 : + "\"."));
5467 1 : }
5468 42 : CATCH_END_SECTION()
5469 :
5470 43 : CATCH_START_SECTION("structure_invalid: get field with wrong type")
5471 : {
5472 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description5));
5473 1 : description->init_buffer();
5474 :
5475 8 : CATCH_REQUIRE_THROWS_MATCHES(
5476 : description->get_field("data.bad_type", prinbee::struct_type_t::STRUCT_TYPE_UINT16)
5477 : , prinbee::type_mismatch
5478 : , Catch::Matchers::ExceptionMessage(
5479 : "prinbee_exception: field \"data\" is not of"
5480 : " type structure or bit field so you can't get a"
5481 : " sub-field (i.e. have a period in the name)."));
5482 1 : }
5483 42 : CATCH_END_SECTION()
5484 :
5485 43 : CATCH_START_SECTION("structure_invalid: get field.flag with wrong flag name")
5486 : {
5487 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description3));
5488 1 : description->init_buffer();
5489 :
5490 : try
5491 : {
5492 5 : description->get_field("eight_bits.unknown_flag");
5493 0 : throw prinbee::logic_error("the expected exception did not occur.");
5494 : }
5495 1 : catch(prinbee::field_not_found const & e)
5496 : {
5497 3 : CATCH_REQUIRE(e.what() == std::string("prinbee_exception: flag named \"unknown_flag\" not found."));
5498 3 : CATCH_REQUIRE(e.get_parameter("flag_name") == "unknown_flag");
5499 1 : }
5500 :
5501 : //CATCH_REQUIRE_THROWS_MATCHES(
5502 : // description->get_field("eight_bits.unknown_flag")
5503 : // , prinbee::field_not_found
5504 : // , Catch::Matchers::ExceptionMessage(
5505 : // "prinbee_exception: flag named \"unknown_flag\" not found."));
5506 1 : }
5507 42 : CATCH_END_SECTION()
5508 :
5509 43 : CATCH_START_SECTION("structure_invalid: get field.flag with wrong type")
5510 : {
5511 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description3));
5512 1 : description->init_buffer();
5513 :
5514 8 : CATCH_REQUIRE_THROWS_MATCHES(
5515 : description->get_field("eight_bits.efficient", prinbee::struct_type_t::STRUCT_TYPE_BITS16)
5516 : , prinbee::type_mismatch
5517 : , Catch::Matchers::ExceptionMessage(
5518 : "prinbee_exception: this field type is \"BITS8\" but"
5519 : " we expected \"BITS16\"."));
5520 1 : }
5521 42 : CATCH_END_SECTION()
5522 :
5523 43 : CATCH_START_SECTION("structure_invalid: get flag with flag name missing")
5524 : {
5525 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description3));
5526 1 : description->init_buffer();
5527 :
5528 1 : prinbee::field_t::pointer_t f;
5529 : try
5530 : {
5531 5 : description->get_flag("eight_bits", f);
5532 0 : throw prinbee::logic_error("the expected exception did not occur.");
5533 : }
5534 1 : catch(prinbee::field_not_found const & e)
5535 : {
5536 3 : CATCH_REQUIRE(e.what() == std::string(
5537 : "prinbee_exception: flag named \"eight_bits\" must"
5538 : " at least include a field name and a flag name."));
5539 3 : CATCH_REQUIRE(e.get_parameter("flag_name") == "eight_bits");
5540 1 : }
5541 :
5542 : //CATCH_REQUIRE_THROWS_MATCHES(
5543 : // description->get_flag("eight_bits", f)
5544 : // , prinbee::field_not_found
5545 : // , Catch::Matchers::ExceptionMessage(
5546 : // "prinbee_exception: flag named \"eight_bits\" must"
5547 : // " at least include a field name and a flag name."));
5548 1 : }
5549 42 : CATCH_END_SECTION()
5550 :
5551 43 : CATCH_START_SECTION("structure_invalid: get flag with UINT32 type")
5552 : {
5553 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description3));
5554 1 : description->init_buffer();
5555 :
5556 1 : prinbee::field_t::pointer_t f;
5557 8 : CATCH_REQUIRE_THROWS_MATCHES(
5558 : description->get_flag("sub_field.efficient", f)
5559 : , prinbee::type_mismatch
5560 : , Catch::Matchers::ExceptionMessage(
5561 : "prinbee_exception: expected a field of type"
5562 : " BITS<size> for flag named \"sub_field.efficient\"."
5563 : " Got a UINT32 instead."));
5564 1 : }
5565 42 : CATCH_END_SECTION()
5566 :
5567 43 : CATCH_START_SECTION("structure_invalid: get field which is RENAMED with an invalid destination name")
5568 : {
5569 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description10));
5570 1 : description->init_buffer();
5571 :
5572 1 : prinbee::field_t::pointer_t f;
5573 : try
5574 : {
5575 5 : description->get_field("buffer_size");
5576 0 : throw prinbee::logic_error("the expected exception did not occur.");
5577 : }
5578 1 : catch(prinbee::field_not_found const & e)
5579 : {
5580 3 : CATCH_REQUIRE(e.what() == std::string("prinbee_exception: this description renames field"
5581 : " \"buffer_size\" to \"unknown\" but we could not"
5582 : " find the latter field."));
5583 3 : CATCH_REQUIRE(e.get_parameter("field_name") == "buffer_size");
5584 3 : CATCH_REQUIRE(e.get_parameter("new_name") == "unknown");
5585 3 : CATCH_REQUIRE(e.get_parameter("full_field_name") == "buffer_size");
5586 1 : }
5587 :
5588 : //CATCH_REQUIRE_THROWS_MATCHES(
5589 : // description->get_field("buffer_size")
5590 : // , prinbee::field_not_found
5591 : // , Catch::Matchers::ExceptionMessage(
5592 : // "prinbee_exception: this description renames field"
5593 : // " \"buffer_size\" to \"unknown\" but we could not"
5594 : // " find the latter field."));
5595 1 : }
5596 42 : CATCH_END_SECTION()
5597 :
5598 43 : CATCH_START_SECTION("structure_invalid: structure version cannot be updated")
5599 : {
5600 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description3));
5601 1 : description->init_buffer();
5602 :
5603 8 : CATCH_REQUIRE_THROWS_MATCHES(
5604 : description->set_version(prinbee::g_system_field_name_structure_version, prinbee::version_t(rand() & 0xFFFF, rand() & 0xFFFF))
5605 : , prinbee::type_mismatch
5606 : , Catch::Matchers::ExceptionMessage(
5607 : "prinbee_exception: this field type is \"STRUCTURE_VERSION\""
5608 : " but we expected one of \"BITS8, BITS16, BITS32, BITS64, OID, REFERENCE, UINT8, UINT16, UINT32, UINT64, VERSION\"."));
5609 1 : }
5610 42 : CATCH_END_SECTION()
5611 :
5612 43 : CATCH_START_SECTION("structure_invalid: set bit field with out of range values")
5613 : {
5614 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description3));
5615 1 : description->init_buffer();
5616 :
5617 3 : CATCH_REQUIRE(description->get_bits("eight_bits.null") == 0);
5618 3 : CATCH_REQUIRE(description->get_bits("eight_bits.advance") == 0);
5619 3 : CATCH_REQUIRE(description->get_bits("eight_bits.efficient") == 0);
5620 3 : CATCH_REQUIRE(description->get_bits("eight_bits.sign") == 0);
5621 :
5622 : // change the value to add some spice to this test
5623 : //
5624 1 : std::uint32_t const valid_null_value(rand() & 1);
5625 3 : description->set_bits("eight_bits.null", valid_null_value);
5626 :
5627 1 : std::uint32_t const valid_advance_value(rand() & 15);
5628 3 : description->set_bits("eight_bits.advance", valid_advance_value);
5629 :
5630 1 : std::uint32_t const valid_efficient_value(rand() & 3);
5631 3 : description->set_bits("eight_bits.efficient", valid_efficient_value);
5632 :
5633 1 : std::uint32_t const valid_sign_value(rand() & 1);
5634 3 : description->set_bits("eight_bits.sign", valid_sign_value);
5635 :
5636 11 : for(int count(0); count < 10; ++count)
5637 : {
5638 : {
5639 10 : std::uint64_t null_value(0);
5640 20 : while(null_value < 2)
5641 : {
5642 10 : SNAP_CATCH2_NAMESPACE::random(null_value);
5643 : }
5644 50 : CATCH_REQUIRE_THROWS_MATCHES(
5645 : description->set_bits("eight_bits.null", null_value)
5646 : , prinbee::invalid_number
5647 : , Catch::Matchers::ExceptionMessage(
5648 : "prinbee_exception: value \""
5649 : + std::to_string(null_value)
5650 : + "\" does not fit in flag field \"eight_bits.null\"."));
5651 :
5652 30 : CATCH_REQUIRE(description->get_bits("eight_bits.null") == valid_null_value);
5653 : }
5654 :
5655 : {
5656 10 : std::uint64_t advance_value(0);
5657 20 : while(advance_value < 16)
5658 : {
5659 10 : SNAP_CATCH2_NAMESPACE::random(advance_value);
5660 : }
5661 50 : CATCH_REQUIRE_THROWS_MATCHES(
5662 : description->set_bits("eight_bits.advance", advance_value)
5663 : , prinbee::invalid_number
5664 : , Catch::Matchers::ExceptionMessage(
5665 : "prinbee_exception: value \""
5666 : + std::to_string(advance_value)
5667 : + "\" does not fit in flag field \"eight_bits.advance\"."));
5668 :
5669 30 : CATCH_REQUIRE(description->get_bits("eight_bits.advance") == valid_advance_value);
5670 : }
5671 :
5672 : {
5673 10 : std::uint64_t efficient_value(0);
5674 20 : while(efficient_value < 8)
5675 : {
5676 10 : SNAP_CATCH2_NAMESPACE::random(efficient_value);
5677 : }
5678 50 : CATCH_REQUIRE_THROWS_MATCHES(
5679 : description->set_bits("eight_bits.efficient", efficient_value)
5680 : , prinbee::invalid_number
5681 : , Catch::Matchers::ExceptionMessage(
5682 : "prinbee_exception: value \""
5683 : + std::to_string(efficient_value)
5684 : + "\" does not fit in flag field \"eight_bits.efficient\"."));
5685 :
5686 30 : CATCH_REQUIRE(description->get_bits("eight_bits.efficient") == valid_efficient_value);
5687 : }
5688 :
5689 : {
5690 10 : std::uint64_t sign_value(0);
5691 20 : while(sign_value < 8)
5692 : {
5693 10 : SNAP_CATCH2_NAMESPACE::random(sign_value);
5694 : }
5695 50 : CATCH_REQUIRE_THROWS_MATCHES(
5696 : description->set_bits("eight_bits.sign", sign_value)
5697 : , prinbee::invalid_number
5698 : , Catch::Matchers::ExceptionMessage(
5699 : "prinbee_exception: value \""
5700 : + std::to_string(sign_value)
5701 : + "\" does not fit in flag field \"eight_bits.sign\"."));
5702 :
5703 30 : CATCH_REQUIRE(description->get_bits("eight_bits.sign") == valid_sign_value);
5704 : }
5705 : }
5706 1 : }
5707 42 : CATCH_END_SECTION()
5708 :
5709 43 : CATCH_START_SECTION("structure_invalid: set buffer with too large a size")
5710 : {
5711 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description5));
5712 1 : description->init_buffer();
5713 :
5714 1 : std::size_t const max(rand() % 100 + 256);
5715 3 : prinbee::buffer_t v(max);
5716 336 : for(std::size_t idx(0); idx < max; ++idx)
5717 : {
5718 335 : v[idx] = rand();
5719 : }
5720 5 : CATCH_REQUIRE_THROWS_MATCHES(
5721 : description->set_buffer("early_version.parts", v)
5722 : , prinbee::out_of_range
5723 : , Catch::Matchers::ExceptionMessage(
5724 : "out_of_range: size of input buffer ("
5725 : + std::to_string(max)
5726 : + ") too large to send it to the buffer; the maximum permitted by this field is 255."));
5727 1 : }
5728 42 : CATCH_END_SECTION()
5729 :
5730 43 : CATCH_START_SECTION("structure_invalid: field \"_magic\" wrong name")
5731 : {
5732 : //prinbee::define_description(
5733 : // prinbee::FieldName("_structure_version")
5734 : // , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
5735 : // , prinbee::FieldVersion(405, 119)
5736 : //),
5737 :
5738 7 : CATCH_REQUIRE_THROWS_MATCHES(
5739 : prinbee::define_description(
5740 : prinbee::FieldName("wrong_name")
5741 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
5742 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS))
5743 : )
5744 : , prinbee::invalid_parameter
5745 : , Catch::Matchers::ExceptionMessage(
5746 : "prinbee_exception: the MAGIC field must be named \"_magic\"."));
5747 : }
5748 42 : CATCH_END_SECTION()
5749 :
5750 43 : CATCH_START_SECTION("structure_invalid: field \"_structure_version\" wrong name")
5751 : {
5752 7 : CATCH_REQUIRE_THROWS_MATCHES(
5753 : prinbee::define_description(
5754 : prinbee::FieldName("wrong_name")
5755 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
5756 : , prinbee::FieldVersion(405, 119)
5757 : )
5758 : , prinbee::invalid_parameter
5759 : , Catch::Matchers::ExceptionMessage(
5760 : "prinbee_exception: the STRUCTURE_VERSION field must be named \"_structure_version\"."));
5761 : }
5762 42 : CATCH_END_SECTION()
5763 :
5764 43 : CATCH_START_SECTION("structure_invalid: bit field with invalid names")
5765 : {
5766 1 : for(prinbee::struct_type_t type(prinbee::struct_type_t::STRUCT_TYPE_BITS8);
5767 8 : type <= prinbee::struct_type_t::STRUCT_TYPE_BITS512;
5768 7 : ++type)
5769 : {
5770 42 : CATCH_REQUIRE_THROWS_MATCHES(
5771 : prinbee::define_description(
5772 : prinbee::FieldName("missing_flag_definitions")
5773 : , prinbee::FieldType(type)
5774 : )
5775 : , prinbee::invalid_parameter
5776 : , Catch::Matchers::ExceptionMessage(
5777 : "prinbee_exception: this structure bit field name or definition is not considered valid."));
5778 :
5779 42 : CATCH_REQUIRE_THROWS_MATCHES(
5780 : prinbee::define_description(
5781 : prinbee::FieldName("two_equal=flag=wrong")
5782 : , prinbee::FieldType(type)
5783 : )
5784 : , prinbee::invalid_parameter
5785 : , Catch::Matchers::ExceptionMessage(
5786 : "prinbee_exception: this structure bit field name or definition is not considered valid."));
5787 :
5788 42 : CATCH_REQUIRE_THROWS_MATCHES(
5789 : prinbee::define_description(
5790 : prinbee::FieldName("expect_number=flag:number")
5791 : , prinbee::FieldType(type)
5792 : )
5793 : , prinbee::invalid_parameter
5794 : , Catch::Matchers::ExceptionMessage(
5795 : "prinbee_exception: this structure bit field name or definition is not considered valid."));
5796 :
5797 42 : CATCH_REQUIRE_THROWS_MATCHES(
5798 : prinbee::define_description(
5799 : prinbee::FieldName("wrong_character=no/question/mark?")
5800 : , prinbee::FieldType(type)
5801 : )
5802 : , prinbee::invalid_parameter
5803 : , Catch::Matchers::ExceptionMessage(
5804 : "prinbee_exception: this structure bit field name or definition is not considered valid."));
5805 : }
5806 : }
5807 42 : CATCH_END_SECTION()
5808 :
5809 43 : CATCH_START_SECTION("structure_invalid: CHAR field with invalid names")
5810 : {
5811 6 : CATCH_REQUIRE_THROWS_MATCHES(
5812 : prinbee::define_description(
5813 : prinbee::FieldName("missing_size")
5814 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_CHAR)
5815 : )
5816 : , prinbee::invalid_parameter
5817 : , Catch::Matchers::ExceptionMessage(
5818 : "prinbee_exception: this structure char field name is not considered valid."));
5819 :
5820 6 : CATCH_REQUIRE_THROWS_MATCHES(
5821 : prinbee::define_description(
5822 : prinbee::FieldName("expect_number=expect_number")
5823 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_CHAR)
5824 : )
5825 : , prinbee::invalid_parameter
5826 : , Catch::Matchers::ExceptionMessage(
5827 : "prinbee_exception: this structure char field name is not considered valid."));
5828 :
5829 6 : CATCH_REQUIRE_THROWS_MATCHES(
5830 : prinbee::define_description(
5831 : prinbee::FieldName("bad?char=123")
5832 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_CHAR)
5833 : )
5834 : , prinbee::invalid_parameter
5835 : , Catch::Matchers::ExceptionMessage(
5836 : "prinbee_exception: this structure char field name is not considered valid."));
5837 :
5838 6 : CATCH_REQUIRE_THROWS_MATCHES(
5839 : prinbee::define_description(
5840 : prinbee::FieldName("bad_char=123!")
5841 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_CHAR)
5842 : )
5843 : , prinbee::invalid_parameter
5844 : , Catch::Matchers::ExceptionMessage(
5845 : "prinbee_exception: this structure char field name is not considered valid."));
5846 :
5847 6 : CATCH_REQUIRE_THROWS_MATCHES(
5848 : prinbee::define_description(
5849 : prinbee::FieldName("no_number=")
5850 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_CHAR)
5851 : )
5852 : , prinbee::invalid_parameter
5853 : , Catch::Matchers::ExceptionMessage(
5854 : "prinbee_exception: this structure char field name is not considered valid."));
5855 : }
5856 42 : CATCH_END_SECTION()
5857 :
5858 43 : CATCH_START_SECTION("structure_invalid: catch bit field ending with lone '/'")
5859 : {
5860 1 : constexpr prinbee::struct_description_t description_definition[] =
5861 : {
5862 : prinbee::define_description(
5863 : prinbee::FieldName("_magic")
5864 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
5865 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS))
5866 : ),
5867 : prinbee::define_description(
5868 : prinbee::FieldName("_structure_version")
5869 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
5870 : , prinbee::FieldVersion(405, 119)
5871 : ),
5872 : //prinbee::define_description(...) -- this detects the "issue" and fails at compile time...
5873 : {
5874 : .f_field_name = "bad_bits=small/medium:3/giant:9/",
5875 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_BITS32,
5876 : //.f_flags =
5877 : //.f_default_value =
5878 : //.f_min_version =
5879 : //.f_max_version =
5880 : //.f_sub_description =
5881 : },
5882 : prinbee::end_descriptions()
5883 : };
5884 :
5885 : // the problem is caught by the verification function early on
5886 : // and the parser never sees it
5887 : //
5888 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(description_definition));
5889 3 : CATCH_REQUIRE_THROWS_MATCHES(
5890 : description->init_buffer()
5891 : , prinbee::logic_error
5892 : , Catch::Matchers::ExceptionMessage(
5893 : "logic_error: bit field name & definition \"bad_bits=small/medium:3/giant:9/\" are not valid."));
5894 1 : }
5895 42 : CATCH_END_SECTION()
5896 :
5897 43 : CATCH_START_SECTION("structure_invalid: bits field with a sub-description")
5898 : {
5899 1 : constexpr prinbee::struct_description_t description_definition[] =
5900 : {
5901 : prinbee::define_description(
5902 : prinbee::FieldName("_magic")
5903 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
5904 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS))
5905 : ),
5906 : prinbee::define_description(
5907 : prinbee::FieldName("_structure_version")
5908 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
5909 : , prinbee::FieldVersion(405, 119)
5910 : ),
5911 : //prinbee::define_description(...) -- this detects the "issue" and fails at compile time...
5912 : {
5913 : .f_field_name = "foo=flag:3",
5914 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_BITS8,
5915 : .f_sub_description = g_description3_sub1,
5916 : },
5917 : prinbee::end_descriptions()
5918 : };
5919 :
5920 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(description_definition));
5921 3 : CATCH_REQUIRE_THROWS_MATCHES(
5922 : description->init_buffer()
5923 : , prinbee::logic_error
5924 : , Catch::Matchers::ExceptionMessage(
5925 : "logic_error: field \"foo=flag:3\" has its "
5926 : "\"f_sub_description\" field set to a pointer"
5927 : " when its type does not allow it."));
5928 1 : }
5929 42 : CATCH_END_SECTION()
5930 :
5931 43 : CATCH_START_SECTION("structure_invalid: structure field without a sub-description")
5932 : {
5933 1 : constexpr prinbee::struct_description_t description_definition[] =
5934 : {
5935 : prinbee::define_description(
5936 : prinbee::FieldName("_magic")
5937 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
5938 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS))
5939 : ),
5940 : prinbee::define_description(
5941 : prinbee::FieldName("_structure_version")
5942 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
5943 : , prinbee::FieldVersion(405, 119)
5944 : ),
5945 : //prinbee::define_description(...) -- this detects the "issue" and fails at compile time...
5946 : {
5947 : .f_field_name = "sub_struct",
5948 : .f_type = prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE,
5949 : },
5950 : prinbee::end_descriptions()
5951 : };
5952 :
5953 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(description_definition));
5954 :
5955 3 : CATCH_REQUIRE_THROWS_MATCHES(
5956 : description->init_buffer()
5957 : , prinbee::logic_error
5958 : , Catch::Matchers::ExceptionMessage(
5959 : "logic_error: field \"sub_struct\""
5960 : " is expected to have its \"f_sub_description\""
5961 : " field set to a pointer but it is null right now."));
5962 1 : }
5963 42 : CATCH_END_SECTION()
5964 :
5965 43 : CATCH_START_SECTION("structure_invalid: reload large number from too small a buffer")
5966 : {
5967 1 : constexpr prinbee::struct_description_t description_definition[] =
5968 : {
5969 : prinbee::define_description(
5970 : prinbee::FieldName("_magic")
5971 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_MAGIC)
5972 : , prinbee::FieldDefaultValue(prinbee::to_string(prinbee::dbtype_t::BLOCK_TYPE_INDEX_POINTERS))
5973 : ),
5974 : prinbee::define_description(
5975 : prinbee::FieldName("_structure_version")
5976 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE_VERSION)
5977 : , prinbee::FieldVersion(405, 119)
5978 : ),
5979 : prinbee::define_description(
5980 : prinbee::FieldName("large_number")
5981 : , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT512)
5982 : ),
5983 : prinbee::end_descriptions()
5984 : };
5985 :
5986 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(description_definition));
5987 1 : description->init_buffer();
5988 :
5989 : // get a copy of the buffer
5990 : //
5991 1 : prinbee::reference_t start_offset(0);
5992 1 : prinbee::virtual_buffer::pointer_t b(description->get_virtual_buffer(start_offset));
5993 1 : CATCH_REQUIRE(b != nullptr);
5994 1 : CATCH_REQUIRE(b->size() == description->get_current_size());
5995 :
5996 : // create a copy but skip the last 32 bytes to generate an invalid
5997 : // buffer
5998 : //
5999 3 : prinbee::buffer_t buffer(b->size() - 32ULL);
6000 1 : CATCH_REQUIRE(b->pread(buffer.data(), buffer.size(), 0) == static_cast<int>(buffer.size()));
6001 :
6002 1 : prinbee::virtual_buffer::pointer_t n(std::make_shared<prinbee::virtual_buffer>());
6003 1 : n->pwrite(buffer.data(), buffer.size(), 0, true);
6004 :
6005 1 : prinbee::structure::pointer_t d(std::make_shared<prinbee::structure>(description_definition));
6006 1 : d->set_virtual_buffer(n, 0);
6007 :
6008 8 : CATCH_REQUIRE_THROWS_MATCHES(
6009 : d->get_large_integer("large_number")
6010 : , prinbee::corrupted_data
6011 : , Catch::Matchers::ExceptionMessage(
6012 : "prinbee_exception: field \"large_number\" is too"
6013 : " large for the specified data buffer."));
6014 1 : }
6015 42 : CATCH_END_SECTION()
6016 :
6017 43 : CATCH_START_SECTION("structure_invalid: attempt sub-structure GET before initialization sub-structure is empty")
6018 : {
6019 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description3));
6020 : //description->init_buffer();
6021 :
6022 8 : CATCH_REQUIRE_THROWS_MATCHES(
6023 : description->get_structure("structure_version")
6024 : , prinbee::logic_error
6025 : , Catch::Matchers::ExceptionMessage(
6026 : "logic_error: trying to access a structure field when the f_buffer pointer is still null."));
6027 1 : }
6028 42 : CATCH_END_SECTION()
6029 :
6030 43 : CATCH_START_SECTION("structure_invalid: attempt sub-structure GET of wrong field")
6031 : {
6032 1 : prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description3));
6033 1 : description->init_buffer();
6034 :
6035 8 : CATCH_REQUIRE_THROWS_MATCHES(
6036 : description->get_structure("javascript_version")
6037 : , prinbee::type_mismatch
6038 : , Catch::Matchers::ExceptionMessage(
6039 : "prinbee_exception: this field type is \"VERSION\" but we expected \"STRUCTURE\"."));
6040 1 : }
6041 42 : CATCH_END_SECTION()
6042 41 : }
6043 :
6044 :
6045 :
6046 : // vim: ts=4 sw=4 et
|