LCOV - code coverage report
Current view: top level - tests - catch_structure.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 611 618 98.9 %
Date: 2024-02-03 18:59:18 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2019-2024  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/not_reached.h>
      37             : 
      38             : 
      39             : // C++
      40             : //
      41             : #include    <iomanip>
      42             : 
      43             : 
      44             : // last include
      45             : //
      46             : #include    <snapdev/poison.h>
      47             : 
      48             : 
      49             : 
      50             : namespace
      51             : {
      52             : 
      53             : 
      54             : 
      55             : constexpr prinbee::struct_description_t g_description1[] =
      56             : {
      57             :     prinbee::define_description(
      58             :           prinbee::FieldName("magic")
      59             :         , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
      60             :     ),
      61             :     prinbee::define_description(
      62             :           prinbee::FieldName("count")
      63             :         , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
      64             :     ),
      65             :     prinbee::define_description(
      66             :           prinbee::FieldName("size")
      67             :         , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
      68             :     ),
      69             :     prinbee::define_description(
      70             :           prinbee::FieldName("change")
      71             :         , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT8) // -100 to +100
      72             :     ),
      73             :     prinbee::define_description(
      74             :           prinbee::FieldName("next")
      75             :         , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_REFERENCE)
      76             :     ),
      77             :     prinbee::define_description(
      78             :           prinbee::FieldName("previous")
      79             :         , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_REFERENCE)
      80             :     ),
      81             :     prinbee::end_descriptions()
      82             : };
      83             : 
      84             : 
      85             : 
      86             : constexpr prinbee::struct_description_t g_description2[] =
      87             : {
      88             :     prinbee::define_description(
      89             :           prinbee::FieldName("magic")
      90             :         , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
      91             :     ),
      92             :     prinbee::define_description(
      93             :           prinbee::FieldName("flags")
      94             :         , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT32)
      95             :     ),
      96             :     prinbee::define_description(
      97             :           prinbee::FieldName("name")
      98             :         , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_P8STRING)
      99             :     ),
     100             :     prinbee::define_description(
     101             :           prinbee::FieldName("size")
     102             :         , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT64)
     103             :     ),
     104             :     prinbee::define_description(
     105             :           prinbee::FieldName("model")
     106             :         , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT16)
     107             :     ),
     108             :     prinbee::end_descriptions()
     109             : };
     110             : 
     111             : 
     112             : 
     113             : struct fixed_size_t
     114             : {
     115             :     prinbee::struct_type_t  f_type = prinbee::INVALID_STRUCT_TYPE;
     116             :     bool                    f_fixed = false;
     117             : };
     118             : 
     119             : std::vector<fixed_size_t> const g_fixed_sizes{
     120             :     { prinbee::struct_type_t::STRUCT_TYPE_END, true },
     121             :     { prinbee::struct_type_t::STRUCT_TYPE_VOID, true },
     122             :     { prinbee::struct_type_t::STRUCT_TYPE_BITS8, true },
     123             :     { prinbee::struct_type_t::STRUCT_TYPE_BITS16, true },
     124             :     { prinbee::struct_type_t::STRUCT_TYPE_BITS32, true },
     125             :     { prinbee::struct_type_t::STRUCT_TYPE_BITS64, true },
     126             :     { prinbee::struct_type_t::STRUCT_TYPE_BITS128, true },
     127             :     { prinbee::struct_type_t::STRUCT_TYPE_BITS256, true },
     128             :     { prinbee::struct_type_t::STRUCT_TYPE_BITS512, true },
     129             :     { prinbee::struct_type_t::STRUCT_TYPE_INT8, true },
     130             :     { prinbee::struct_type_t::STRUCT_TYPE_UINT8, true },
     131             :     { prinbee::struct_type_t::STRUCT_TYPE_INT16, true },
     132             :     { prinbee::struct_type_t::STRUCT_TYPE_UINT16, true },
     133             :     { prinbee::struct_type_t::STRUCT_TYPE_INT32, true },
     134             :     { prinbee::struct_type_t::STRUCT_TYPE_UINT32, true },
     135             :     { prinbee::struct_type_t::STRUCT_TYPE_INT64, true },
     136             :     { prinbee::struct_type_t::STRUCT_TYPE_UINT64, true },
     137             :     { prinbee::struct_type_t::STRUCT_TYPE_INT128, true },
     138             :     { prinbee::struct_type_t::STRUCT_TYPE_UINT128, true },
     139             :     { prinbee::struct_type_t::STRUCT_TYPE_INT256, true },
     140             :     { prinbee::struct_type_t::STRUCT_TYPE_UINT256, true },
     141             :     { prinbee::struct_type_t::STRUCT_TYPE_INT512, true },
     142             :     { prinbee::struct_type_t::STRUCT_TYPE_UINT512, true },
     143             :     { prinbee::struct_type_t::STRUCT_TYPE_FLOAT32, true },
     144             :     { prinbee::struct_type_t::STRUCT_TYPE_FLOAT64, true },
     145             :     { prinbee::struct_type_t::STRUCT_TYPE_FLOAT128, true },
     146             :     { prinbee::struct_type_t::STRUCT_TYPE_VERSION, true },
     147             :     { prinbee::struct_type_t::STRUCT_TYPE_TIME, true },
     148             :     { prinbee::struct_type_t::STRUCT_TYPE_MSTIME, true },
     149             :     { prinbee::struct_type_t::STRUCT_TYPE_USTIME, true },
     150             :     { prinbee::struct_type_t::STRUCT_TYPE_P8STRING, false },
     151             :     { prinbee::struct_type_t::STRUCT_TYPE_P16STRING, false },
     152             :     { prinbee::struct_type_t::STRUCT_TYPE_P32STRING, false },
     153             :     { prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE, false },
     154             :     { prinbee::struct_type_t::STRUCT_TYPE_ARRAY8, false },
     155             :     { prinbee::struct_type_t::STRUCT_TYPE_ARRAY16, false },
     156             :     { prinbee::struct_type_t::STRUCT_TYPE_ARRAY32, false },
     157             :     { prinbee::struct_type_t::STRUCT_TYPE_BUFFER8, false },
     158             :     { prinbee::struct_type_t::STRUCT_TYPE_BUFFER16, false },
     159             :     { prinbee::struct_type_t::STRUCT_TYPE_BUFFER32, false },
     160             :     { prinbee::struct_type_t::STRUCT_TYPE_REFERENCE, true },
     161             :     { prinbee::struct_type_t::STRUCT_TYPE_OID, true },
     162             :     { prinbee::struct_type_t::STRUCT_TYPE_RENAMED, true },
     163             : };
     164             : 
     165             : 
     166             : struct field_info_t
     167             : {
     168             :     char const *        f_type_name = nullptr;
     169             :     ssize_t             f_field_size = 0;
     170             :     ssize_t             f_type_field_size = 0;
     171             : };
     172             : 
     173             : std::vector<field_info_t> g_field_info{
     174             :     { "VOID",       0,  0 },
     175             :     { "BITS8",      1,  0 },
     176             :     { "BITS16",     2,  0 },
     177             :     { "BITS32",     4,  0 },
     178             :     { "BITS64",     8,  0 },
     179             :     { "BITS128",   16,  0 },
     180             :     { "BITS256",   32,  0 },
     181             :     { "BITS512",   64,  0 },
     182             :     { "INT8",       1,  0 },
     183             :     { "UINT8",      1,  0 },
     184             :     { "INT16",      2,  0 },
     185             :     { "UINT16",     2,  0 },
     186             :     { "INT32",      4,  0 },
     187             :     { "UINT32",     4,  0 },
     188             :     { "INT64",      8,  0 },
     189             :     { "UINT64",     8,  0 },
     190             :     { "INT128",    16,  0 },
     191             :     { "UINT128",   16,  0 },
     192             :     { "INT256",    32,  0 },
     193             :     { "UINT256",   32,  0 },
     194             :     { "INT512",    64,  0 },
     195             :     { "UINT512",   64,  0 },
     196             :     { "FLOAT32",    4,  0 },
     197             :     { "FLOAT64",    8,  0 },
     198             :     { "FLOAT128",  16,  0 },
     199             :     { "VERSION",    4,  0 },
     200             :     { "TIME",       8,  0 },
     201             :     { "MSTIME",     8,  0 },
     202             :     { "USTIME",     8,  0 },
     203             :     { "P8STRING",  -2,  1 },
     204             :     { "P16STRING", -2,  2 },
     205             :     { "P32STRING", -2,  4 },
     206             :     { "STRUCTURE", -2,  0 },
     207             :     { "ARRAY8",    -2,  1 },
     208             :     { "ARRAY16",   -2,  2 },
     209             :     { "ARRAY32",   -2,  4 },
     210             :     { "BUFFER8",   -2,  1 },
     211             :     { "BUFFER16",  -2,  2 },
     212             :     { "BUFFER32",  -2,  4 },
     213             :     { "REFERENCE",  8,  0 },
     214             :     { "OID",        8,  0 },
     215             :     { "RENAMED",   -1,  0 },
     216             : };
     217             : 
     218             : 
     219         101 : bool is_valid_type(prinbee::struct_type_t type)
     220             : {
     221         101 :     switch(type)
     222             :     {
     223           0 :     case prinbee::struct_type_t::STRUCT_TYPE_END:
     224             :     case prinbee::struct_type_t::STRUCT_TYPE_VOID:
     225             :     case prinbee::struct_type_t::STRUCT_TYPE_BITS8:
     226             :     case prinbee::struct_type_t::STRUCT_TYPE_BITS16:
     227             :     case prinbee::struct_type_t::STRUCT_TYPE_BITS32:
     228             :     case prinbee::struct_type_t::STRUCT_TYPE_BITS64:
     229             :     case prinbee::struct_type_t::STRUCT_TYPE_BITS128:
     230             :     case prinbee::struct_type_t::STRUCT_TYPE_BITS256:
     231             :     case prinbee::struct_type_t::STRUCT_TYPE_BITS512:
     232             :     case prinbee::struct_type_t::STRUCT_TYPE_INT8:
     233             :     case prinbee::struct_type_t::STRUCT_TYPE_UINT8:
     234             :     case prinbee::struct_type_t::STRUCT_TYPE_INT16:
     235             :     case prinbee::struct_type_t::STRUCT_TYPE_UINT16:
     236             :     case prinbee::struct_type_t::STRUCT_TYPE_INT32:
     237             :     case prinbee::struct_type_t::STRUCT_TYPE_UINT32:
     238             :     case prinbee::struct_type_t::STRUCT_TYPE_INT64:
     239             :     case prinbee::struct_type_t::STRUCT_TYPE_UINT64:
     240             :     case prinbee::struct_type_t::STRUCT_TYPE_INT128:
     241             :     case prinbee::struct_type_t::STRUCT_TYPE_UINT128:
     242             :     case prinbee::struct_type_t::STRUCT_TYPE_INT256:
     243             :     case prinbee::struct_type_t::STRUCT_TYPE_UINT256:
     244             :     case prinbee::struct_type_t::STRUCT_TYPE_INT512:
     245             :     case prinbee::struct_type_t::STRUCT_TYPE_UINT512:
     246             :     case prinbee::struct_type_t::STRUCT_TYPE_FLOAT32:
     247             :     case prinbee::struct_type_t::STRUCT_TYPE_FLOAT64:
     248             :     case prinbee::struct_type_t::STRUCT_TYPE_FLOAT128:
     249             :     case prinbee::struct_type_t::STRUCT_TYPE_VERSION:
     250             :     case prinbee::struct_type_t::STRUCT_TYPE_TIME:
     251             :     case prinbee::struct_type_t::STRUCT_TYPE_MSTIME:
     252             :     case prinbee::struct_type_t::STRUCT_TYPE_USTIME:
     253             :     case prinbee::struct_type_t::STRUCT_TYPE_P8STRING:
     254             :     case prinbee::struct_type_t::STRUCT_TYPE_P16STRING:
     255             :     case prinbee::struct_type_t::STRUCT_TYPE_P32STRING:
     256             :     case prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE:
     257             :     case prinbee::struct_type_t::STRUCT_TYPE_ARRAY8:
     258             :     case prinbee::struct_type_t::STRUCT_TYPE_ARRAY16:
     259             :     case prinbee::struct_type_t::STRUCT_TYPE_ARRAY32:
     260             :     case prinbee::struct_type_t::STRUCT_TYPE_BUFFER8:
     261             :     case prinbee::struct_type_t::STRUCT_TYPE_BUFFER16:
     262             :     case prinbee::struct_type_t::STRUCT_TYPE_BUFFER32:
     263             :     case prinbee::struct_type_t::STRUCT_TYPE_REFERENCE:
     264             :     case prinbee::struct_type_t::STRUCT_TYPE_OID:
     265             :     case prinbee::struct_type_t::STRUCT_TYPE_RENAMED:
     266           0 :         return true;
     267             : 
     268         101 :     default:
     269         101 :         return false;
     270             : 
     271             :     }
     272             :     snapdev::NOT_REACHED();
     273             : }
     274             : 
     275             : }
     276             : // no name namespace
     277             : 
     278             : 
     279           2 : CATCH_TEST_CASE("structure_type_name", "[structure] [type] [valid]")
     280             : {
     281           2 :     CATCH_START_SECTION("structure_type_name: name from type")
     282             :     {
     283           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_END) == "END");
     284           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_VOID) == "VOID");
     285           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS8) == "BITS8");
     286           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS16) == "BITS16");
     287           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS32) == "BITS32");
     288           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS64) == "BITS64");
     289           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS128) == "BITS128");
     290           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS256) == "BITS256");
     291           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BITS512) == "BITS512");
     292           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT8) == "INT8");
     293           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT8) == "UINT8");
     294           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT16) == "INT16");
     295           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT16) == "UINT16");
     296           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT32) == "INT32");
     297           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT32) == "UINT32");
     298           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT64) == "INT64");
     299           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT64) == "UINT64");
     300           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT128) == "INT128");
     301           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT128) == "UINT128");
     302           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT256) == "INT256");
     303           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT256) == "UINT256");
     304           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_INT512) == "INT512");
     305           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_UINT512) == "UINT512");
     306           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_FLOAT32) == "FLOAT32");
     307           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_FLOAT64) == "FLOAT64");
     308           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_FLOAT128) == "FLOAT128");
     309           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_VERSION) == "VERSION");
     310           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_TIME) == "TIME");
     311           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_MSTIME) == "MSTIME");
     312           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_USTIME) == "USTIME");
     313           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_P8STRING) == "P8STRING");
     314           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_P16STRING) == "P16STRING");
     315           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_P32STRING) == "P32STRING");
     316           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE) == "STRUCTURE");
     317           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_ARRAY8) == "ARRAY8");
     318           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_ARRAY16) == "ARRAY16");
     319           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_ARRAY32) == "ARRAY32");
     320           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BUFFER8) == "BUFFER8");
     321           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BUFFER16) == "BUFFER16");
     322           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_BUFFER32) == "BUFFER32");
     323           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_REFERENCE) == "REFERENCE");
     324           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_OID) == "OID");
     325           1 :         CATCH_REQUIRE(prinbee::to_string(prinbee::struct_type_t::STRUCT_TYPE_RENAMED) == "RENAMED");
     326             :     }
     327           2 :     CATCH_END_SECTION()
     328             : 
     329           2 :     CATCH_START_SECTION("structure_type_name: type from name")
     330             :     {
     331           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("END") == prinbee::struct_type_t::STRUCT_TYPE_END);
     332           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("VOID") == prinbee::struct_type_t::STRUCT_TYPE_VOID);
     333           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("BITS8") == prinbee::struct_type_t::STRUCT_TYPE_BITS8);
     334           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("BITS16") == prinbee::struct_type_t::STRUCT_TYPE_BITS16);
     335           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("BITS32") == prinbee::struct_type_t::STRUCT_TYPE_BITS32);
     336           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("BITS64") == prinbee::struct_type_t::STRUCT_TYPE_BITS64);
     337           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("BITS128") == prinbee::struct_type_t::STRUCT_TYPE_BITS128);
     338           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("BITS256") == prinbee::struct_type_t::STRUCT_TYPE_BITS256);
     339           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("BITS512") == prinbee::struct_type_t::STRUCT_TYPE_BITS512);
     340           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("INT8") == prinbee::struct_type_t::STRUCT_TYPE_INT8);
     341           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("UINT8") == prinbee::struct_type_t::STRUCT_TYPE_UINT8);
     342           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("INT16") == prinbee::struct_type_t::STRUCT_TYPE_INT16);
     343           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("UINT16") == prinbee::struct_type_t::STRUCT_TYPE_UINT16);
     344           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("INT32") == prinbee::struct_type_t::STRUCT_TYPE_INT32);
     345           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("UINT32") == prinbee::struct_type_t::STRUCT_TYPE_UINT32);
     346           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("INT64") == prinbee::struct_type_t::STRUCT_TYPE_INT64);
     347           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("UINT64") == prinbee::struct_type_t::STRUCT_TYPE_UINT64);
     348           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("INT128") == prinbee::struct_type_t::STRUCT_TYPE_INT128);
     349           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("UINT128") == prinbee::struct_type_t::STRUCT_TYPE_UINT128);
     350           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("INT256") == prinbee::struct_type_t::STRUCT_TYPE_INT256);
     351           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("UINT256") == prinbee::struct_type_t::STRUCT_TYPE_UINT256);
     352           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("INT512") == prinbee::struct_type_t::STRUCT_TYPE_INT512);
     353           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("UINT512") == prinbee::struct_type_t::STRUCT_TYPE_UINT512);
     354           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("FLOAT32") == prinbee::struct_type_t::STRUCT_TYPE_FLOAT32);
     355           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("FLOAT64") == prinbee::struct_type_t::STRUCT_TYPE_FLOAT64);
     356           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("FLOAT128") == prinbee::struct_type_t::STRUCT_TYPE_FLOAT128);
     357           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("VERSION") == prinbee::struct_type_t::STRUCT_TYPE_VERSION);
     358           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("TIME") == prinbee::struct_type_t::STRUCT_TYPE_TIME);
     359           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("MSTIME") == prinbee::struct_type_t::STRUCT_TYPE_MSTIME);
     360           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("USTIME") == prinbee::struct_type_t::STRUCT_TYPE_USTIME);
     361           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("P8STRING") == prinbee::struct_type_t::STRUCT_TYPE_P8STRING);
     362           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("P16STRING") == prinbee::struct_type_t::STRUCT_TYPE_P16STRING);
     363           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("P32STRING") == prinbee::struct_type_t::STRUCT_TYPE_P32STRING);
     364           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("STRUCTURE") == prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE);
     365           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("ARRAY8") == prinbee::struct_type_t::STRUCT_TYPE_ARRAY8);
     366           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("ARRAY16") == prinbee::struct_type_t::STRUCT_TYPE_ARRAY16);
     367           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("ARRAY32") == prinbee::struct_type_t::STRUCT_TYPE_ARRAY32);
     368           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("BUFFER8") == prinbee::struct_type_t::STRUCT_TYPE_BUFFER8);
     369           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("BUFFER16") == prinbee::struct_type_t::STRUCT_TYPE_BUFFER16);
     370           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("BUFFER32") == prinbee::struct_type_t::STRUCT_TYPE_BUFFER32);
     371           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("REFERENCE") == prinbee::struct_type_t::STRUCT_TYPE_REFERENCE);
     372           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("OID") == prinbee::struct_type_t::STRUCT_TYPE_OID);
     373           1 :         CATCH_REQUIRE(prinbee::name_to_struct_type("RENAMED") == prinbee::struct_type_t::STRUCT_TYPE_RENAMED);
     374             :     }
     375           2 :     CATCH_END_SECTION()
     376           2 : }
     377             : 
     378             : 
     379           2 : CATCH_TEST_CASE("structure_type_name_invalid", "[structure] [type] [invalid]")
     380             : {
     381           2 :     CATCH_START_SECTION("structure_type_name: unknown")
     382             :     {
     383         101 :         for(int i(0); i < 100; ++i)
     384             :         {
     385         100 :             prinbee::struct_type_t bad_type(prinbee::struct_type_t::STRUCT_TYPE_END);
     386             :             do
     387             :             {
     388         100 :                 bad_type = static_cast<prinbee::struct_type_t>(SNAP_CATCH2_NAMESPACE::rand32());
     389             :             }
     390         100 :             while(is_valid_type(bad_type));
     391         100 :             std::string const expected(
     392             :                       "*unknown struct type ("
     393         300 :                     + std::to_string(static_cast<int>(bad_type))
     394         200 :                     + ")*");
     395         100 :             CATCH_REQUIRE(expected == prinbee::to_string(bad_type));
     396         100 :         }
     397             :     }
     398           2 :     CATCH_END_SECTION()
     399             : 
     400           2 :     CATCH_START_SECTION("structure_type_name: invalid")
     401             :     {
     402         101 :         for(int i(0); i < 100; ++i)
     403             :         {
     404             :             //prinbee::struct_type_t bad_type(prinbee::struct_type_t::STRUCT_TYPE_END);
     405         100 :             std::string const bad_type_name(SNAP_CATCH2_NAMESPACE::rand_string(rand() % 10 + 1));
     406         100 :             prinbee::struct_type_t type(prinbee::name_to_struct_type(bad_type_name));
     407         100 :             if(type != prinbee::INVALID_STRUCT_TYPE)
     408             :             {
     409             :                 // the rand_string() could return a valid name (very unlikely, though)
     410             :                 //
     411           0 :                 CATCH_REQUIRE(prinbee::to_string(type) == bad_type_name);  // not that bad after all...
     412             :             }
     413             :             else
     414             :             {
     415             :                 // avoid catch2 error "no assertion in section ..."
     416             :                 //
     417         100 :                 CATCH_REQUIRE(prinbee::INVALID_STRUCT_TYPE == type);
     418             :             }
     419         100 :         }
     420             :     }
     421           2 :     CATCH_END_SECTION()
     422           2 : }
     423             : 
     424             : 
     425           1 : CATCH_TEST_CASE("structure_type_metadata", "[structure] [type] [valid]")
     426             : {
     427           1 :     CATCH_START_SECTION("structure_type_metadata: fixed size")
     428             :     {
     429          44 :         for(auto const & f : g_fixed_sizes)
     430             :         {
     431          43 :             CATCH_REQUIRE(f.f_fixed == prinbee::type_with_fixed_size(f.f_type));
     432             :         }
     433             :     }
     434           1 :     CATCH_END_SECTION()
     435           1 : }
     436             : 
     437             : 
     438           2 : CATCH_TEST_CASE("structure_version_basics", "[structure] [version]")
     439             : {
     440           2 :     CATCH_START_SECTION("version: default")
     441             :     {
     442           1 :         prinbee::version_t version;
     443           1 :         CATCH_REQUIRE(version.get_major() == 0);
     444           1 :         CATCH_REQUIRE(version.get_minor() == 0);
     445             :     }
     446           2 :     CATCH_END_SECTION()
     447             : 
     448           2 :     CATCH_START_SECTION("version: conversions")
     449             :     {
     450         101 :         for(int n(0); n < 100; ++n)
     451             :         {
     452         100 :             int const major_version(rand() & 0xFFFF);
     453         100 :             int const minor_version(rand() & 0xFFFF);
     454             : 
     455         100 :             std::uint32_t const binary((major_version << 16) + minor_version);
     456             : 
     457         100 :             prinbee::version_t const v1(major_version, minor_version);
     458         100 :             CATCH_REQUIRE(v1.get_major() == major_version);
     459         100 :             CATCH_REQUIRE(v1.get_minor() == minor_version);
     460         100 :             CATCH_REQUIRE(v1.to_binary() == binary);
     461             : 
     462         100 :             prinbee::version_t v2;
     463         100 :             CATCH_REQUIRE(v2.get_major() == 0);
     464         100 :             CATCH_REQUIRE(v2.get_minor() == 0);
     465         100 :             CATCH_REQUIRE(v2.is_null());
     466         100 :             CATCH_REQUIRE(v2 != v1);
     467         100 :             v2.from_binary(binary);
     468         100 :             CATCH_REQUIRE(v2.get_major() == major_version);
     469         100 :             CATCH_REQUIRE(v2.get_minor() == minor_version);
     470         100 :             CATCH_REQUIRE(v2.to_binary() == binary);
     471         100 :             CATCH_REQUIRE(v2 == v1);
     472             : 
     473         100 :             v2.next_revision();
     474             : 
     475         100 :             if(minor_version == 0xFFFF)
     476             :             {
     477           0 :                 CATCH_REQUIRE(v2.get_major() == major_version + 1);
     478           0 :                 CATCH_REQUIRE(v2.get_minor() == 0);
     479             :             }
     480             :             else
     481             :             {
     482         100 :                 CATCH_REQUIRE(v2.get_major() == major_version);
     483         100 :                 CATCH_REQUIRE(v2.get_minor() == minor_version + 1);
     484             :             }
     485             : 
     486         100 :             v2 = v1;
     487         100 :             int const new_major_version(rand() & 0xFFFF);
     488         100 :             v2.set_major(new_major_version);
     489         100 :             CATCH_REQUIRE(v2.get_major() == new_major_version);
     490         100 :             CATCH_REQUIRE(v2.get_minor() == minor_version);
     491         100 :             CATCH_REQUIRE(v2 != v1);
     492             : 
     493         100 :             int const new_minor_version(rand() & 0xFFFF);
     494         100 :             v2.set_minor(new_minor_version);
     495         100 :             CATCH_REQUIRE(v2.get_major() == new_major_version);
     496         100 :             CATCH_REQUIRE(v2.get_minor() == new_minor_version);
     497         100 :             CATCH_REQUIRE(v2 != v1);
     498             : 
     499         100 :             v2 = v1;
     500         100 :             CATCH_REQUIRE(v2.get_major() == major_version);
     501         100 :             CATCH_REQUIRE(v2.get_minor() == minor_version);
     502         100 :             CATCH_REQUIRE(v2.to_binary() == binary);
     503         100 :             CATCH_REQUIRE(v2 == v1);
     504             : 
     505         100 :             prinbee::version_t v3(v1);
     506         100 :             CATCH_REQUIRE_FALSE(v3.is_null());
     507         100 :             CATCH_REQUIRE(v3.get_major() == major_version);
     508         100 :             CATCH_REQUIRE(v3.get_minor() == minor_version);
     509         100 :             CATCH_REQUIRE(v3.to_binary() == binary);
     510         100 :             CATCH_REQUIRE(v3 == v1);
     511         100 :             CATCH_REQUIRE_FALSE(v3 > v1);
     512         100 :             CATCH_REQUIRE(v3 >= v1);
     513         100 :             CATCH_REQUIRE_FALSE(v3 < v1);
     514         100 :             CATCH_REQUIRE(v3 <= v1);
     515             : 
     516         100 :             std::string v3_str(v3.to_string());
     517         100 :             std::string version_str;
     518         100 :             version_str += std::to_string(major_version);
     519         100 :             version_str += '.';
     520         100 :             version_str += std::to_string(minor_version);
     521         100 :             CATCH_REQUIRE(v3_str == version_str);
     522             : 
     523         100 :             v3.next_branch();
     524         100 :             CATCH_REQUIRE(v3.get_major() == major_version + 1);
     525         100 :             CATCH_REQUIRE(v3.get_minor() == 0);
     526         100 :             CATCH_REQUIRE(v3.to_binary() == static_cast<uint32_t>((major_version + 1) << 16));
     527             : 
     528         100 :             prinbee::version_t v4(binary);
     529         100 :             CATCH_REQUIRE_FALSE(v4.is_null());
     530         100 :             CATCH_REQUIRE(v4.get_major() == major_version);
     531         100 :             CATCH_REQUIRE(v4.get_minor() == minor_version);
     532         100 :             CATCH_REQUIRE(v4.to_binary() == binary);
     533         100 :             CATCH_REQUIRE(v1 == v4);
     534         100 :         }
     535             :     }
     536           2 :     CATCH_END_SECTION()
     537           2 : }
     538             : 
     539             : 
     540           1 : CATCH_TEST_CASE("structure_version_compare", "[structure] [version]")
     541             : {
     542           1 :     CATCH_START_SECTION("version: compare")
     543             :     {
     544         101 :         for(int n(0); n < 100; ++n)
     545             :         {
     546         100 :             int major_version(rand() & 0xFFFF);
     547         100 :             int minor_version(rand() & 0xFFFF);
     548         100 :             int major_version2(rand() & 0xFFFF);
     549         100 :             while(major_version == major_version2)
     550             :             {
     551           0 :                 major_version2 = rand() & 0xFFFF;
     552             :             }
     553             : 
     554         100 :             prinbee::version_t v1(major_version, minor_version);
     555         100 :             prinbee::version_t v2(major_version2, minor_version);
     556         100 :             if(major_version < major_version2)
     557             :             {
     558          47 :                 CATCH_REQUIRE_FALSE(v1 == v2);
     559          47 :                 CATCH_REQUIRE(v1 != v2);
     560          47 :                 CATCH_REQUIRE(v1 < v2);
     561          47 :                 CATCH_REQUIRE(v1 <= v2);
     562          47 :                 CATCH_REQUIRE(v2 > v1);
     563          47 :                 CATCH_REQUIRE(v2 >= v1);
     564             :             }
     565             :             else
     566             :             {
     567          53 :                 CATCH_REQUIRE_FALSE(v1 == v2);
     568          53 :                 CATCH_REQUIRE(v1 != v2);
     569          53 :                 CATCH_REQUIRE(v1 > v2);
     570          53 :                 CATCH_REQUIRE(v1 >= v2);
     571          53 :                 CATCH_REQUIRE(v2 < v1);
     572          53 :                 CATCH_REQUIRE(v2 <= v1);
     573             :             }
     574             :         }
     575             :     }
     576           1 :     CATCH_END_SECTION()
     577           1 : }
     578             : 
     579             : 
     580           1 : CATCH_TEST_CASE("structure_version_overflow", "[structure] [version] [invalid]")
     581             : {
     582           1 :     CATCH_START_SECTION("version overflow")
     583             :     {
     584         101 :         for(int n(0); n < 100; ++n)
     585             :         {
     586         100 :             int major_version(0);
     587         100 :             int minor_version(0);
     588             :             do
     589             :             {
     590         123 :                 major_version = SNAP_CATCH2_NAMESPACE::rand32();
     591         123 :                 minor_version = SNAP_CATCH2_NAMESPACE::rand32();
     592             :             }
     593             :             while(major_version < 65536
     594         123 :                && minor_version < 65536);
     595             : 
     596         100 :             CATCH_REQUIRE_THROWS_MATCHES(
     597             :                       prinbee::version_t(major_version, minor_version)
     598             :                     , prinbee::invalid_parameter
     599             :                     , Catch::Matchers::ExceptionMessage(
     600             :                               "prinbee_exception: major/minor version must be between 0 and 65535 inclusive, "
     601             :                             + std::to_string(major_version)
     602             :                             + "."
     603             :                             + std::to_string(minor_version)
     604             :                             + " is incorrect."));
     605             :         }
     606             :     }
     607           1 :     CATCH_END_SECTION()
     608           1 : }
     609             : 
     610             : 
     611           1 : CATCH_TEST_CASE("structure_min_max_version", "[structure] [version] [valid]")
     612             : {
     613           1 :     CATCH_START_SECTION("min_max_version: default")
     614             :     {
     615           1 :         prinbee::version_t version = prinbee::version_t();
     616           1 :         prinbee::min_max_version_t zero;
     617           1 :         CATCH_REQUIRE(version == zero.min());
     618           1 :         CATCH_REQUIRE(version == zero.max());
     619             :     }
     620           1 :     CATCH_END_SECTION()
     621           1 : }
     622             : 
     623             : 
     624           1 : CATCH_TEST_CASE("structure_flag_definitions", "[structure] [flags] [valid]")
     625             : {
     626           1 :     CATCH_START_SECTION("structure_flag_definitions: all positions")
     627             :     {
     628          65 :         for(std::size_t pos(0); pos < 64; ++pos)
     629             :         {
     630          64 :             std::string const field_name(SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1));
     631          64 :             std::string const flag_name(SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1));
     632             : 
     633          64 :             std::string full_name(field_name);
     634          64 :             full_name += '.';
     635          64 :             full_name += flag_name;
     636             : 
     637          64 :             prinbee::flag_definition const def(field_name, flag_name, pos);
     638          64 :             CATCH_REQUIRE(full_name == def.full_name());
     639          64 :             CATCH_REQUIRE(field_name == def.field_name());
     640          64 :             CATCH_REQUIRE(flag_name == def.flag_name());
     641          64 :             CATCH_REQUIRE(pos == def.pos());
     642          64 :             CATCH_REQUIRE(1ULL == def.size());
     643          64 :             CATCH_REQUIRE((1ULL << pos) == def.mask());
     644          64 :         }
     645             :     }
     646           1 :     CATCH_END_SECTION()
     647           1 : }
     648             : 
     649             : 
     650           2 : CATCH_TEST_CASE("structure_flag_definitions_incorrect_construction", "[structure] [flags] [invalid]")
     651             : {
     652           2 :     CATCH_START_SECTION("structure_flag_definitions: missing name(s)")
     653             :     {
     654             :         // missing flag name
     655           1 :         std::string name(SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1));
     656           3 :         CATCH_REQUIRE_THROWS_MATCHES(
     657             :                   prinbee::flag_definition(name, std::string(), rand(), rand())
     658             :                 , prinbee::invalid_parameter
     659             :                 , Catch::Matchers::ExceptionMessage(
     660             :                           "prinbee_exception: the flag definition must have a non-empty field name and flag name."));
     661             : 
     662             :         // missing field name
     663           1 :         name = SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1);
     664           3 :         CATCH_REQUIRE_THROWS_MATCHES(
     665             :                   prinbee::flag_definition(std::string(), name, rand())
     666             :                 , prinbee::invalid_parameter
     667             :                 , Catch::Matchers::ExceptionMessage(
     668             :                           "prinbee_exception: the flag definition must have a non-empty field name and flag name."));
     669             : 
     670             :         // missing both names
     671           1 :         name = SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1);
     672           5 :         CATCH_REQUIRE_THROWS_MATCHES(
     673             :                   prinbee::flag_definition(std::string(), std::string(), rand() % 64, rand())
     674             :                 , prinbee::invalid_parameter
     675             :                 , Catch::Matchers::ExceptionMessage(
     676             :                           "prinbee_exception: the flag definition must have a non-empty field name and flag name."));
     677           1 :     }
     678           2 :     CATCH_END_SECTION()
     679             : 
     680           2 :     CATCH_START_SECTION("structure_flag_definitions: unsupported sizes / positions")
     681             :     {
     682             :         // zero fails
     683             :         //
     684           1 :         std::string field_name(SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1));
     685           1 :         std::string flag_name(SNAP_CATCH2_NAMESPACE::rand_string(rand() % 100 + 1));
     686           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     687             :                   prinbee::flag_definition(field_name, flag_name, rand(), 0ULL)
     688             :                 , prinbee::invalid_parameter
     689             :                 , Catch::Matchers::ExceptionMessage(
     690             :                           "prinbee_exception: bit field named \""
     691             :                         + field_name
     692             :                         + "."
     693             :                         + flag_name
     694             :                         + "\" can't have a size of 0."));
     695             : 
     696          37 :         for(std::size_t size(64); size < 100; ++size)
     697             :         {
     698          36 :             CATCH_REQUIRE_THROWS_MATCHES(
     699             :                       prinbee::flag_definition(field_name, flag_name, rand(), size)
     700             :                     , prinbee::invalid_parameter
     701             :                     , Catch::Matchers::ExceptionMessage(
     702             :                               "prinbee_exception: bit field named \""
     703             :                             + field_name
     704             :                             + "."
     705             :                             + flag_name
     706             :                             + "\" is too large ("
     707             :                             + std::to_string(size)
     708             :                             + " >= 64)."));
     709             :         }
     710             : 
     711          64 :         for(std::size_t size(1ULL); size < 64ULL; ++size)
     712             :         {
     713        4284 :             for(std::size_t pos(65ULL - size); pos < 100ULL; ++pos)
     714             :             {
     715        4221 :                 CATCH_REQUIRE_THROWS_MATCHES(
     716             :                           prinbee::flag_definition(field_name, flag_name, pos, size)
     717             :                         , prinbee::invalid_parameter
     718             :                         , Catch::Matchers::ExceptionMessage(
     719             :                                   "prinbee_exception: the mask of the bit field named \""
     720             :                                 + field_name
     721             :                                 + "."
     722             :                                 + flag_name
     723             :                                 + "\" does not fit in a uint64_t."));
     724             :             }
     725             :         }
     726             : 
     727             :         // position 65+ is not valid either
     728             :         //
     729           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     730             :                   prinbee::flag_definition(field_name, flag_name, 65ULL)
     731             :                 , prinbee::invalid_parameter
     732             :                 , Catch::Matchers::ExceptionMessage(
     733             :                           "prinbee_exception: the mask of the bit field named \""
     734             :                         + field_name
     735             :                         + "."
     736             :                         + flag_name
     737             :                         + "\" does not fit in a uint64_t."));
     738           1 :     }
     739           2 :     CATCH_END_SECTION()
     740           2 : }
     741             : 
     742             : 
     743           6 : CATCH_TEST_CASE("structure_field", "[structure] [valid]")
     744             : {
     745           6 :     CATCH_START_SECTION("structure_field: check description of all different database types")
     746             :     {
     747          43 :         for(auto const & info : g_field_info)
     748             :         {
     749          42 :             prinbee::field_t::field_flags_t flags((rand() & 1) != 0 ? 0 : prinbee::STRUCT_DESCRIPTION_FLAG_OPTIONAL);
     750          42 :             prinbee::struct_type_t const type(prinbee::name_to_struct_type(info.f_type_name));
     751          42 :             prinbee::struct_description_t description =
     752             :             {
     753             :                 prinbee::define_description(
     754          42 :                       prinbee::FieldName(info.f_type_name)
     755             :                     , prinbee::FieldType(type)
     756             :                     , prinbee::FieldFlags(flags)
     757             :                 ),
     758          42 :             };
     759             : 
     760          84 :             prinbee::field_t::const_pointer_t f(std::make_shared<prinbee::field_t>(&description));
     761             : 
     762          42 :             CATCH_REQUIRE(&description == f->description());
     763          42 :             CATCH_REQUIRE(nullptr == f->next());
     764          42 :             CATCH_REQUIRE(nullptr == f->previous());
     765          42 :             CATCH_REQUIRE(f == f->first());
     766          42 :             CATCH_REQUIRE(f == f->last());
     767          42 :             CATCH_REQUIRE(type == f->type());
     768          42 :             CATCH_REQUIRE(info.f_field_size == f->field_size());
     769          42 :             CATCH_REQUIRE(info.f_type_field_size == f->type_field_size());
     770          42 :             CATCH_REQUIRE(info.f_type_name == f->field_name());
     771          42 :             CATCH_REQUIRE(0 == f->size());
     772             : 
     773          42 :             std::uint32_t const size(SNAP_CATCH2_NAMESPACE::rand32());
     774          42 :             std::const_pointer_cast<prinbee::field_t>(f)->set_size(size);
     775          42 :             CATCH_REQUIRE(size == f->size());
     776             : 
     777             :             // the flag are set by the structure parser, so here it's never set
     778             :             // whether it is defined in the description above
     779             :             //
     780          42 :             CATCH_REQUIRE_FALSE(f->has_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE));
     781          42 :             CATCH_REQUIRE(0 == f->flags());
     782             : 
     783          42 :             std::const_pointer_cast<prinbee::field_t>(f)->set_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE);
     784          42 :             CATCH_REQUIRE(f->has_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE));
     785          42 :             CATCH_REQUIRE(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE == f->flags());
     786             : 
     787          42 :             std::const_pointer_cast<prinbee::field_t>(f)->clear_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE);
     788          42 :             CATCH_REQUIRE_FALSE(f->has_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE));
     789          42 :             CATCH_REQUIRE(0 == f->flags());
     790             : 
     791          42 :             std::const_pointer_cast<prinbee::field_t>(f)->add_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE);
     792          42 :             CATCH_REQUIRE(f->has_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE));
     793          42 :             CATCH_REQUIRE(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE == f->flags());
     794             : 
     795          42 :             CATCH_REQUIRE(0 == f->offset());
     796             : 
     797          42 :             std::uint64_t const offset(SNAP_CATCH2_NAMESPACE::rand64());
     798          42 :             std::const_pointer_cast<prinbee::field_t>(f)->set_offset(offset);
     799          42 :             CATCH_REQUIRE(offset == f->offset());
     800             : 
     801          42 :             std::int64_t const adjust(SNAP_CATCH2_NAMESPACE::rand64());
     802          42 :             std::const_pointer_cast<prinbee::field_t>(f)->adjust_offset(adjust);
     803          42 :             CATCH_REQUIRE(offset + adjust == f->offset());
     804             : 
     805          42 :             CATCH_REQUIRE(f->sub_structures().empty());
     806          42 :             CATCH_REQUIRE(std::const_pointer_cast<prinbee::field_t>(f)->sub_structures().empty());
     807          42 :         }
     808             :     }
     809           6 :     CATCH_END_SECTION()
     810             : 
     811           6 :     CATCH_START_SECTION("structure_field: check flag definitions")
     812             :     {
     813           1 :         prinbee::struct_description_t description =
     814             :         {
     815             :             prinbee::define_description(
     816             :                   prinbee::FieldName("flags")
     817             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS64)
     818             :             ),
     819             :         };
     820             : 
     821           1 :         prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
     822             : 
     823           1 :         CATCH_REQUIRE(&description == f->description());
     824           1 :         CATCH_REQUIRE(nullptr == f->next());
     825           1 :         CATCH_REQUIRE(nullptr == f->previous());
     826           1 :         CATCH_REQUIRE(f == f->first());
     827           1 :         CATCH_REQUIRE(f == f->last());
     828           1 :         CATCH_REQUIRE(prinbee::struct_type_t::STRUCT_TYPE_BITS64 == f->type());
     829           1 :         CATCH_REQUIRE(8 == f->field_size());
     830           1 :         CATCH_REQUIRE(0 == f->type_field_size());
     831           1 :         CATCH_REQUIRE("flags" == f->field_name());
     832           1 :         CATCH_REQUIRE(0 == f->size());
     833           1 :         CATCH_REQUIRE_FALSE(f->has_flags(prinbee::field_t::FIELD_FLAG_VARIABLE_SIZE));
     834           1 :         CATCH_REQUIRE(0 == f->flags());
     835           1 :         CATCH_REQUIRE(0 == f->offset());
     836             : 
     837             : //    flag_definition::pointer_t              find_flag_definition(std::string const & name) const;
     838             : //    void                                    add_flag_definition(flag_definition::pointer_t bits);
     839             : 
     840          11 :         for(int i(1); i <= 10; ++i)
     841             :         {
     842             : #pragma GCC diagnostic push
     843             : #pragma GCC diagnostic ignored "-Wrestrict"
     844          20 :             std::string const name("f" + std::to_string(i));
     845             : #pragma GCC diagnostic pop
     846          10 :             prinbee::flag_definition::pointer_t flag(std::make_shared<prinbee::flag_definition>("flags", name, i * 3, 3));
     847          10 :             CATCH_REQUIRE(flag->full_name() == "flags." + name);
     848          10 :             f->add_flag_definition(flag);
     849          10 :             CATCH_REQUIRE(flag == f->find_flag_definition(name));
     850          10 :         }
     851             : 
     852             :         // make sure they stay around
     853             :         //
     854          11 :         for(int i(1); i <= 10; ++i)
     855             :         {
     856             : #pragma GCC diagnostic push
     857             : #pragma GCC diagnostic ignored "-Wrestrict"
     858          20 :             std::string const name("f" + std::to_string(i));
     859             : #pragma GCC diagnostic pop
     860          10 :             CATCH_REQUIRE(f->find_flag_definition(name)->full_name() == "flags." + name);
     861          10 :         }
     862           1 :     }
     863           6 :     CATCH_END_SECTION()
     864             : 
     865           6 :     CATCH_START_SECTION("structure_field: next/previous (1)")
     866             :     {
     867           1 :         prinbee::struct_description_t description[3] =
     868             :         {
     869             :             prinbee::define_description(
     870             :                   prinbee::FieldName("head")
     871             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT32)
     872             :             ),
     873             :             prinbee::define_description(
     874             :                   prinbee::FieldName("cont")
     875             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT64)
     876             :             ),
     877             :             prinbee::define_description(
     878             :                   prinbee::FieldName("tail")
     879             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS16)
     880             :             ),
     881             :         };
     882             : 
     883           1 :         prinbee::field_t::pointer_t first(std::make_shared<prinbee::field_t>(description + 0));
     884           1 :         prinbee::field_t::pointer_t middle(std::make_shared<prinbee::field_t>(description + 1));
     885           1 :         prinbee::field_t::pointer_t last(std::make_shared<prinbee::field_t>(description + 2));
     886             : 
     887             :         // fields are used internally so the linking requires two calls
     888             :         //
     889           1 :         first->set_next(middle);
     890           1 :         middle->set_previous(first);
     891             : 
     892           1 :         middle->set_next(last);
     893           1 :         last->set_previous(middle);
     894             : 
     895           1 :         CATCH_REQUIRE(nullptr == first->previous());
     896           1 :         CATCH_REQUIRE(middle == first->next());
     897           1 :         CATCH_REQUIRE(first == middle->previous());
     898           1 :         CATCH_REQUIRE(last == middle->next());
     899           1 :         CATCH_REQUIRE(middle == last->previous());
     900           1 :         CATCH_REQUIRE(nullptr == last->next());
     901             : 
     902           1 :         CATCH_REQUIRE(first == first->first());
     903           1 :         CATCH_REQUIRE(first == middle->first());
     904           1 :         CATCH_REQUIRE(first == last->first());
     905           1 :         CATCH_REQUIRE(last == first->last());
     906           1 :         CATCH_REQUIRE(last == middle->last());
     907           1 :         CATCH_REQUIRE(last == last->last());
     908             : 
     909           1 :         CATCH_REQUIRE(first->type() == prinbee::struct_type_t::STRUCT_TYPE_INT32);
     910           1 :         CATCH_REQUIRE(middle->type() == prinbee::struct_type_t::STRUCT_TYPE_UINT64);
     911           1 :         CATCH_REQUIRE(last->type() == prinbee::struct_type_t::STRUCT_TYPE_BITS16);
     912             : 
     913             :         // when last pointer gets reset, it changes a few things
     914             :         //
     915           1 :         last.reset();
     916           1 :         CATCH_REQUIRE(last == nullptr);
     917             : 
     918           1 :         CATCH_REQUIRE(nullptr == first->previous());
     919           1 :         CATCH_REQUIRE(middle == first->next());
     920           1 :         CATCH_REQUIRE(first == first->first());
     921           1 :         CATCH_REQUIRE(middle == first->last());
     922             : 
     923           1 :         CATCH_REQUIRE(first == middle->previous());
     924           1 :         CATCH_REQUIRE(nullptr == middle->next());
     925           1 :         CATCH_REQUIRE(first == middle->first());
     926           1 :         CATCH_REQUIRE(middle == middle->last());
     927           1 :     }
     928           6 :     CATCH_END_SECTION()
     929             : 
     930           6 :     CATCH_START_SECTION("structure_field: next/previous (2)")
     931             :     {
     932           1 :         prinbee::struct_description_t description[5] =
     933             :         {
     934             :             prinbee::define_description(
     935             :                   prinbee::FieldName("head")
     936             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT32)
     937             :             ),
     938             :             prinbee::define_description(
     939             :                   prinbee::FieldName("early")
     940             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_UINT64)
     941             :             ),
     942             :             prinbee::define_description(
     943             :                   prinbee::FieldName("middle")
     944             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT256)
     945             :             ),
     946             :             prinbee::define_description(
     947             :                   prinbee::FieldName("late")
     948             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_REFERENCE)
     949             :             ),
     950             :             prinbee::define_description(
     951             :                   prinbee::FieldName("tail")
     952             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS16)
     953             :             ),
     954             :         };
     955             : 
     956           1 :         prinbee::field_t::pointer_t first(std::make_shared<prinbee::field_t>(description + 0));
     957           1 :         prinbee::field_t::pointer_t early(std::make_shared<prinbee::field_t>(description + 1));
     958           1 :         prinbee::field_t::pointer_t middle(std::make_shared<prinbee::field_t>(description + 2));
     959           1 :         prinbee::field_t::pointer_t late(std::make_shared<prinbee::field_t>(description + 3));
     960           1 :         prinbee::field_t::pointer_t last(std::make_shared<prinbee::field_t>(description + 4));
     961             : 
     962             :         // fields are used internally so the linking requires two calls
     963             :         //
     964           1 :         first->set_next(early);
     965           1 :         early->set_previous(first);
     966             : 
     967           1 :         early->set_next(middle);
     968           1 :         middle->set_previous(early);
     969             : 
     970           1 :         middle->set_next(late);
     971           1 :         late->set_previous(middle);
     972             : 
     973           1 :         late->set_next(last);
     974           1 :         last->set_previous(late);
     975             : 
     976           1 :         CATCH_REQUIRE(nullptr == first->previous());
     977           1 :         CATCH_REQUIRE(early == first->next());
     978           1 :         CATCH_REQUIRE(first == early->previous());
     979           1 :         CATCH_REQUIRE(middle == early->next());
     980           1 :         CATCH_REQUIRE(early == middle->previous());
     981           1 :         CATCH_REQUIRE(late == middle->next());
     982           1 :         CATCH_REQUIRE(middle == late->previous());
     983           1 :         CATCH_REQUIRE(last == late->next());
     984           1 :         CATCH_REQUIRE(late == last->previous());
     985           1 :         CATCH_REQUIRE(nullptr == last->next());
     986             : 
     987           1 :         CATCH_REQUIRE(first == first->first());
     988           1 :         CATCH_REQUIRE(first == early->first());
     989           1 :         CATCH_REQUIRE(first == middle->first());
     990           1 :         CATCH_REQUIRE(first == late->first());
     991           1 :         CATCH_REQUIRE(first == last->first());
     992           1 :         CATCH_REQUIRE(last == first->last());
     993           1 :         CATCH_REQUIRE(last == early->last());
     994           1 :         CATCH_REQUIRE(last == middle->last());
     995           1 :         CATCH_REQUIRE(last == late->last());
     996           1 :         CATCH_REQUIRE(last == last->last());
     997             : 
     998           1 :         CATCH_REQUIRE(first->type() == prinbee::struct_type_t::STRUCT_TYPE_INT32);
     999           1 :         CATCH_REQUIRE(early->type() == prinbee::struct_type_t::STRUCT_TYPE_UINT64);
    1000           1 :         CATCH_REQUIRE(middle->type() == prinbee::struct_type_t::STRUCT_TYPE_INT256);
    1001           1 :         CATCH_REQUIRE(late->type() == prinbee::struct_type_t::STRUCT_TYPE_REFERENCE);
    1002           1 :         CATCH_REQUIRE(last->type() == prinbee::struct_type_t::STRUCT_TYPE_BITS16);
    1003             : 
    1004             :         // when middle pointer gets reset, it changes a few things
    1005             :         //
    1006           1 :         middle.reset();
    1007           1 :         CATCH_REQUIRE(middle == nullptr);
    1008             : 
    1009           1 :         CATCH_REQUIRE(nullptr == first->previous());
    1010           1 :         CATCH_REQUIRE(early == first->next());
    1011           1 :         CATCH_REQUIRE(first == first->first());
    1012           1 :         CATCH_REQUIRE(last == first->last());
    1013             : 
    1014           1 :         CATCH_REQUIRE(first == early->previous());
    1015           1 :         CATCH_REQUIRE(late == early->next());
    1016           1 :         CATCH_REQUIRE(first == early->first());
    1017           1 :         CATCH_REQUIRE(last == early->last());
    1018             : 
    1019           1 :         CATCH_REQUIRE(early == late->previous());
    1020           1 :         CATCH_REQUIRE(last == late->next());
    1021           1 :         CATCH_REQUIRE(first == late->first());
    1022           1 :         CATCH_REQUIRE(last == late->last());
    1023             : 
    1024           1 :         CATCH_REQUIRE(late == last->previous());
    1025           1 :         CATCH_REQUIRE(nullptr == last->next());
    1026           1 :         CATCH_REQUIRE(first == last->first());
    1027           1 :         CATCH_REQUIRE(last == last->last());
    1028           1 :     }
    1029           6 :     CATCH_END_SECTION()
    1030             : 
    1031           6 :     CATCH_START_SECTION("structure_field: new name with a RENAMED but no field name")
    1032             :     {
    1033           1 :         prinbee::struct_description_t rename =
    1034             :         {
    1035             :             prinbee::define_description(
    1036             :                   prinbee::FieldName("true_name")
    1037             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT512)
    1038             :             ),
    1039             :         };
    1040             : 
    1041           1 :         prinbee::struct_description_t description =
    1042             :         {
    1043           3 :             prinbee::define_description(
    1044             :                   prinbee::FieldName("name_missing")
    1045             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_RENAMED)
    1046             :                 , prinbee::FieldSubDescription(&rename)
    1047             :             ),
    1048           4 :         };
    1049             : 
    1050           1 :         prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
    1051             : 
    1052           1 :         CATCH_REQUIRE("true_name" == f->new_name());
    1053           1 :     }
    1054           6 :     CATCH_END_SECTION()
    1055             : 
    1056           6 :     CATCH_START_SECTION("structure_field: sub-structures")
    1057             :     {
    1058           1 :         prinbee::struct_description_t description =
    1059             :         {
    1060             :             prinbee::define_description(
    1061             :                   prinbee::FieldName("structure")
    1062             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE)
    1063             :             ),
    1064             :         };
    1065             : 
    1066           1 :         prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
    1067             : 
    1068           1 :         prinbee::structure::pointer_t s(std::make_shared<prinbee::structure>(g_description1));
    1069           1 :         f->sub_structures().push_back(s);
    1070           1 :         CATCH_REQUIRE((*f)[0] == s);
    1071             : 
    1072           1 :         prinbee::structure::vector_t v;
    1073           1 :         prinbee::structure::pointer_t s1(std::make_shared<prinbee::structure>(g_description1));
    1074           1 :         v.push_back(s1);
    1075           1 :         prinbee::structure::pointer_t s2(std::make_shared<prinbee::structure>(g_description1));
    1076           1 :         v.push_back(s2);
    1077           1 :         prinbee::structure::pointer_t s3(std::make_shared<prinbee::structure>(g_description1));
    1078           1 :         v.push_back(s3);
    1079           1 :         f->set_sub_structures(v);
    1080           1 :         CATCH_REQUIRE((*f)[0] == s1);
    1081           1 :         CATCH_REQUIRE((*f)[1] == s2);
    1082           1 :         CATCH_REQUIRE((*f)[2] == s3);
    1083           1 :     }
    1084           6 :     CATCH_END_SECTION()
    1085           6 : }
    1086             : 
    1087             : 
    1088           7 : CATCH_TEST_CASE("structure_invalid_field", "[structure] [valid]")
    1089             : {
    1090           7 :     CATCH_START_SECTION("structure_invalid_field: check description of all different database types")
    1091             :     {
    1092             :         // generate an invalid type and then try a field description
    1093             :         // with such, we should get errors in various places
    1094             :         //
    1095           1 :         prinbee::struct_type_t bad_type(static_cast<prinbee::struct_type_t>(rand()));
    1096           1 :         while(is_valid_type(bad_type))
    1097             :         {
    1098           0 :             bad_type = static_cast<prinbee::struct_type_t>(rand());
    1099             :         }
    1100           1 :         prinbee::struct_description_t description =
    1101             :         {
    1102           1 :             prinbee::define_description(
    1103             :                   prinbee::FieldName("INVALID")
    1104             :                 , prinbee::FieldType(bad_type)
    1105             :             ),
    1106           2 :         };
    1107             : 
    1108           2 :         prinbee::field_t::const_pointer_t f(std::make_shared<prinbee::field_t>(&description));
    1109             : 
    1110           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1111             :                   f->field_size()
    1112             :                 , prinbee::out_of_range
    1113             :                 , Catch::Matchers::ExceptionMessage(
    1114             :                           "out_of_range: type out of range for converting it to a field size ("
    1115             :                           "*unknown struct type ("
    1116             :                         + std::to_string(static_cast<int>(bad_type))
    1117             :                         + ")*"
    1118             :                           ", max: 43).")); // this number is not defined otherwise...
    1119             : 
    1120           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1121             :                   f->type_field_size()
    1122             :                 , prinbee::out_of_range
    1123             :                 , Catch::Matchers::ExceptionMessage(
    1124             :                           "out_of_range: type out of range for converting it to a type field size ("
    1125             :                           "*unknown struct type ("
    1126             :                         + std::to_string(static_cast<int>(bad_type))
    1127             :                         + ")*"
    1128             :                           ", max: 43).")); // this number is not defined otherwise...
    1129           1 :     }
    1130           7 :     CATCH_END_SECTION()
    1131             : 
    1132           7 :     CATCH_START_SECTION("structure_invalid_field: new name without a RENAMED")
    1133             :     {
    1134           1 :         prinbee::struct_description_t description =
    1135             :         {
    1136             :             prinbee::define_description(
    1137             :                   prinbee::FieldName("not_renamed")
    1138             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_ARRAY8) // <- wrong type
    1139             :             ),
    1140             :         };
    1141             : 
    1142           1 :         prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
    1143             : 
    1144           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1145             :                   f->new_name()
    1146             :                 , prinbee::type_mismatch
    1147             :                 , Catch::Matchers::ExceptionMessage(
    1148             :                           "prinbee_exception: field \"not_renamed\" is not a RENAMED field, it has no new name."));
    1149           1 :     }
    1150           7 :     CATCH_END_SECTION()
    1151             : 
    1152           7 :     CATCH_START_SECTION("structure_invalid_field: new name without a sub-description")
    1153             :     {
    1154           1 :         prinbee::struct_description_t description =
    1155             :         {
    1156             :             prinbee::define_description(
    1157             :                   prinbee::FieldName("no_link")
    1158             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_RENAMED)
    1159             :             ),
    1160             :         };
    1161             : 
    1162           1 :         prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
    1163             : 
    1164           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1165             :                   f->new_name()
    1166             :                 , prinbee::logic_error
    1167             :                 , Catch::Matchers::ExceptionMessage(
    1168             :                           "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."));
    1169           1 :     }
    1170           7 :     CATCH_END_SECTION()
    1171             : 
    1172           7 :     CATCH_START_SECTION("structure_invalid_field: new name with a RENAMED but no field name")
    1173             :     {
    1174           1 :         prinbee::struct_description_t rename =
    1175             :         {
    1176             :             prinbee::define_description(
    1177             :                   prinbee::FieldName(nullptr)
    1178             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT512)
    1179             :             ),
    1180             :         };
    1181             : 
    1182           1 :         prinbee::struct_description_t description =
    1183             :         {
    1184           3 :             prinbee::define_description(
    1185             :                   prinbee::FieldName("name_missing")
    1186             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_RENAMED)
    1187             :                 , prinbee::FieldSubDescription(&rename)
    1188             :             ),
    1189           4 :         };
    1190             : 
    1191           1 :         prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
    1192             : 
    1193           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1194             :                   f->new_name()
    1195             :                 , prinbee::logic_error
    1196             :                 , Catch::Matchers::ExceptionMessage(
    1197             :                           "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."));
    1198           1 :     }
    1199           7 :     CATCH_END_SECTION()
    1200             : 
    1201           7 :     CATCH_START_SECTION("structure_invalid_field: unknown flag")
    1202             :     {
    1203           1 :         prinbee::struct_description_t description =
    1204             :         {
    1205             :             prinbee::define_description(
    1206             :                   prinbee::FieldName("flags")
    1207             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_BITS16)
    1208             :             ),
    1209             :         };
    1210             : 
    1211           1 :         prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
    1212             : 
    1213           5 :         CATCH_REQUIRE_THROWS_MATCHES(
    1214             :                   f->find_flag_definition("unknown")
    1215             :                 , prinbee::field_not_found
    1216             :                 , Catch::Matchers::ExceptionMessage(
    1217             :                           "prinbee_exception: flag named \"unknown\" not found."));
    1218           1 :     }
    1219           7 :     CATCH_END_SECTION()
    1220             : 
    1221           7 :     CATCH_START_SECTION("structure_invalid_field: sub-structure indexing out of range")
    1222             :     {
    1223           1 :         prinbee::struct_description_t description =
    1224             :         {
    1225             :             prinbee::define_description(
    1226             :                   prinbee::FieldName("structure")
    1227             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_STRUCTURE)
    1228             :             ),
    1229             :         };
    1230             : 
    1231           1 :         prinbee::field_t::pointer_t f(std::make_shared<prinbee::field_t>(&description));
    1232             : 
    1233           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1234             :                   (*f)[0]
    1235             :                 , prinbee::out_of_bounds
    1236             :                 , Catch::Matchers::ExceptionMessage(
    1237             :                           "prinbee_exception: index (0) is out of bounds since there are no sub-structures."));
    1238             : 
    1239           1 :         prinbee::structure::pointer_t s;
    1240           1 :         f->sub_structures().push_back(s);
    1241             : 
    1242           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1243             :                   (*f)[1]
    1244             :                 , prinbee::out_of_bounds
    1245             :                 , Catch::Matchers::ExceptionMessage(
    1246             :                           "prinbee_exception: index (1) is out of bounds (0..0)"));
    1247           1 :     }
    1248           7 :     CATCH_END_SECTION()
    1249             : 
    1250             : #ifdef _DEBUG
    1251             :     // these throw ... only happen when debug is turned on
    1252             :     //
    1253             :     // i.e. with `mk -t -r` command line option (Release mode),
    1254             :     // it does not include debug core
    1255             :     //
    1256           7 :     CATCH_START_SECTION("structure_invalid_field: validity verifications in contructor")
    1257             :     {
    1258           1 :         prinbee::struct_description_t name_missing =
    1259             :         {
    1260             :             prinbee::define_description(
    1261             :                   prinbee::FieldName(nullptr)
    1262             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT512)
    1263             :             ),
    1264             :         };
    1265             : 
    1266           2 :         CATCH_REQUIRE_THROWS_MATCHES(
    1267             :                   std::make_shared<prinbee::field_t>(&name_missing)
    1268             :                 , prinbee::logic_error
    1269             :                 , Catch::Matchers::ExceptionMessage(
    1270             :                           "logic_error: a field must have a name, `nullptr` is not valid."));
    1271             : 
    1272           1 :         prinbee::struct_description_t name_empty =
    1273             :         {
    1274             :             prinbee::define_description(
    1275             :                   prinbee::FieldName("")
    1276             :                 , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT512)
    1277             :             ),
    1278             :         };
    1279             : 
    1280           2 :         CATCH_REQUIRE_THROWS_MATCHES(
    1281             :                   std::make_shared<prinbee::field_t>(&name_empty)
    1282             :                 , prinbee::logic_error
    1283             :                 , Catch::Matchers::ExceptionMessage(
    1284             :                           "logic_error: a field must have a name, an empty string (\"\") is not valid."));
    1285             : 
    1286         101 :         for(int i(0); i < 100; ++i)
    1287             :         {
    1288         100 :             char name[10];
    1289         100 :             name[sizeof(name) - 1] = '\0';
    1290        1000 :             for(std::size_t j(0); j < sizeof(name) - 1; ++j)
    1291             :             {
    1292         900 :                 switch(rand() % 4)
    1293             :                 {
    1294         223 :                 case 0:
    1295         223 :                     name[j] = rand() % 26 + 'A';
    1296         223 :                     break;
    1297             : 
    1298         218 :                 case 1:
    1299         218 :                     name[j] = rand() % 26 + 'a';
    1300         218 :                     break;
    1301             : 
    1302         239 :                 case 2:
    1303         239 :                     if(j == 0)
    1304             :                     {
    1305             :                         // avoid digits as the first character
    1306             :                         //
    1307          23 :                         name[j] = rand() % 26 + 'a';
    1308             :                     }
    1309             :                     else
    1310             :                     {
    1311         216 :                         name[j] = rand() % 10 + '0';
    1312             :                     }
    1313         239 :                     break;
    1314             : 
    1315         220 :                 case 3:
    1316         220 :                     name[j] = '_';
    1317         220 :                     break;
    1318             : 
    1319             :                 }
    1320             :             }
    1321         100 :             int k(-1);
    1322         100 :             if(i == 0)
    1323             :             {
    1324           1 :                 name[0] = rand() % 10 + '0';
    1325             :             }
    1326             :             else
    1327             :             {
    1328          99 :                 k = rand() % (sizeof(name) - 1);
    1329             :                 for(;;)
    1330             :                 {
    1331         120 :                     name[k] = rand() % 255;
    1332         120 :                     if((name[k] < 'A' || name[k] > 'Z')
    1333         111 :                     && (name[k] < 'a' || name[k] > 'z')
    1334         103 :                     && (name[k] < '0' || name[k] > '9')
    1335         100 :                     && name[k] != '_'
    1336         100 :                     && name[k] != '\0')
    1337             :                     {
    1338          99 :                         break;
    1339             :                     }
    1340             :                 }
    1341             :             }
    1342             : 
    1343         100 :             prinbee::struct_description_t name_invalid =
    1344             :             {
    1345         200 :                 prinbee::define_description(
    1346             :                       prinbee::FieldName(name)
    1347             :                     , prinbee::FieldType(prinbee::struct_type_t::STRUCT_TYPE_INT512)
    1348             :                 ),
    1349         300 :             };
    1350             : 
    1351         200 :             CATCH_REQUIRE_THROWS_MATCHES(
    1352             :                       std::make_shared<prinbee::field_t>(&name_invalid)
    1353             :                     , prinbee::logic_error
    1354             :                     , Catch::Matchers::ExceptionMessage(
    1355             :                               std::string("logic_error: field name \"")
    1356             :                             + name
    1357             :                             + "\" is not valid (unsupported characters)."));
    1358             :         }
    1359             :     }
    1360           7 :     CATCH_END_SECTION()
    1361             : #endif
    1362           7 : }
    1363             : 
    1364             : 
    1365             : 
    1366             : 
    1367           2 : CATCH_TEST_CASE("structure", "[structure] [valid]")
    1368             : {
    1369           2 :     CATCH_START_SECTION("structure: simple structure (fixed size)")
    1370             :     {
    1371           1 :         prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description1));
    1372             : 
    1373           1 :         description->init_buffer();
    1374             : 
    1375           1 :         description->set_uinteger("magic", static_cast<uint32_t>(prinbee::dbtype_t::BLOCK_TYPE_BLOB));
    1376             : 
    1377           1 :         std::uint32_t const count(123);
    1378           1 :         description->set_uinteger("count", count);
    1379             : 
    1380           1 :         std::uint32_t const size(900000);
    1381           1 :         description->set_uinteger("size", size);
    1382             : 
    1383           1 :         std::int32_t const change(-55);
    1384           1 :         description->set_integer("change", change);
    1385             : 
    1386           1 :         prinbee::reference_t const next(0xff00ff00ff00);
    1387           1 :         description->set_uinteger("next", next);
    1388             : 
    1389           1 :         prinbee::reference_t const previous(0xff11ff11ff11);
    1390           1 :         description->set_uinteger("previous", previous);
    1391             : 
    1392           1 :         CATCH_REQUIRE(description->get_uinteger("magic") == static_cast<uint32_t>(prinbee::dbtype_t::BLOCK_TYPE_BLOB));
    1393           1 :         CATCH_REQUIRE(description->get_uinteger("count") == count);
    1394           1 :         CATCH_REQUIRE(description->get_uinteger("size") == size);
    1395           1 :         CATCH_REQUIRE(description->get_integer("change") == change);
    1396           1 :         CATCH_REQUIRE(description->get_uinteger("next") == next);
    1397           1 :         CATCH_REQUIRE(description->get_uinteger("previous") == previous);
    1398           1 :     }
    1399           2 :     CATCH_END_SECTION()
    1400             : 
    1401           2 :     CATCH_START_SECTION("structure with a string")
    1402             :     {
    1403           1 :         prinbee::structure::pointer_t description(std::make_shared<prinbee::structure>(g_description2));
    1404             : 
    1405           1 :         description->init_buffer();
    1406             : 
    1407           1 :         description->set_uinteger("magic", static_cast<uint32_t>(prinbee::dbtype_t::BLOCK_TYPE_DATA));
    1408             : 
    1409           1 :         std::uint32_t flags(0x100105);
    1410           1 :         description->set_uinteger("flags", flags);
    1411             : 
    1412           2 :         std::string const name("this is the name we want to include here");
    1413           1 :         description->set_string("name", name);
    1414             : 
    1415           1 :         uint64_t size(1LL << 53);
    1416           1 :         description->set_uinteger("size", size);
    1417             : 
    1418           1 :         uint16_t model(33);
    1419           1 :         description->set_uinteger("model", model);
    1420             : 
    1421           1 :         CATCH_REQUIRE(description->get_uinteger("magic") == static_cast<uint32_t>(prinbee::dbtype_t::BLOCK_TYPE_DATA));
    1422           1 :         CATCH_REQUIRE(description->get_uinteger("flags") == flags);
    1423           1 :         CATCH_REQUIRE(description->get_string("name") == name);
    1424           1 :         CATCH_REQUIRE(description->get_uinteger("size") == size);
    1425           1 :         CATCH_REQUIRE(description->get_uinteger("model") == model);
    1426           1 :     }
    1427           2 :     CATCH_END_SECTION()
    1428           2 : }
    1429             : 
    1430             : 
    1431             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14

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