LCOV - code coverage report
Current view: top level - tests - catch_structure.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 99.1 % 2403 2381
Test Date: 2025-06-19 11:28:46 Functions: 100.0 % 16 16
Legend: Lines: hit not hit

            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
        

Generated by: LCOV version 2.0-1

Snap C++ | List of projects | List of versions