@@ -128,6 +128,67 @@ template<typename Entity> void testOptionalValues() {
128128 REQUIRE (read->relId .value () == src->relId .value ());
129129}
130130
131+ template <typename Entity> void testOptionalNull () {
132+ static_assert (std::is_same<decltype (Entity::int_), std::optional<int >>::value, " must be std::optional" );
133+
134+ Store store = testStore (true , " c-cpp-tests-db" );
135+ Box<Entity> box (store);
136+
137+ // no values inserted -> no values loaded
138+ obx_id id = box.put (Entity ());
139+
140+ // values inserted
141+ Entity update;
142+ update.int_ = __LINE__;
143+ update.int8 = __LINE__;
144+ update.int16 = __LINE__;
145+ update.int32 = __LINE__;
146+ update.int64 = __LINE__;
147+ update.uint = __LINE__;
148+ update.uint8 = __LINE__;
149+ update.uint16 = __LINE__;
150+ update.uint32 = __LINE__;
151+ update.uint64 = __LINE__;
152+ update.bool_ = __LINE__;
153+ update.string = " foo" ;
154+ update.stringvector = std::vector<std::string>{" foo" , " bar" };
155+ update.byte = __LINE__;
156+ update.ubyte = __LINE__;
157+ update.bytevector = std::vector<int8_t >{-13 , 30 };
158+ update.ubytevector = std::vector<uint8_t >{5 , 6 };
159+ update.float32 = __LINE__;
160+ update.float64 = __LINE__;
161+ update.float_ = __LINE__;
162+ update.double_ = __LINE__;
163+ update.relId = __LINE__;
164+
165+ // overwritten by all fields null
166+ box.get (id, update);
167+
168+ REQUIRE_FALSE (update.int_ .has_value ());
169+ REQUIRE_FALSE (update.int8 .has_value ());
170+ REQUIRE_FALSE (update.int16 .has_value ());
171+ REQUIRE_FALSE (update.int32 .has_value ());
172+ REQUIRE_FALSE (update.int64 .has_value ());
173+ REQUIRE_FALSE (update.uint .has_value ());
174+ REQUIRE_FALSE (update.uint8 .has_value ());
175+ REQUIRE_FALSE (update.uint16 .has_value ());
176+ REQUIRE_FALSE (update.uint32 .has_value ());
177+ REQUIRE_FALSE (update.uint64 .has_value ());
178+ REQUIRE_FALSE (update.bool_ .has_value ());
179+ REQUIRE_FALSE (update.string .has_value ());
180+ REQUIRE_FALSE (update.stringvector .has_value ());
181+ REQUIRE_FALSE (update.byte .has_value ());
182+ REQUIRE_FALSE (update.ubyte .has_value ());
183+ REQUIRE_FALSE (update.bytevector .has_value ());
184+ REQUIRE_FALSE (update.ubytevector .has_value ());
185+ REQUIRE_FALSE (update.float32 .has_value ());
186+ REQUIRE_FALSE (update.float64 .has_value ());
187+ REQUIRE_FALSE (update.float_ .has_value ());
188+ REQUIRE_FALSE (update.double_ .has_value ());
189+ REQUIRE_FALSE (update.relId .has_value ());
190+ }
191+
131192template <typename Entity> void testOptionalEmptyNaN (bool asValue) {
132193
133194 Store store = testStore (true , " c-cpp-tests-db" );
@@ -145,7 +206,7 @@ template<typename Entity> void testOptionalEmptyNaN(bool asValue) {
145206 src->int_ = 23 ;
146207
147208 box.put (*src);
148-
209+
149210 // Update entity by empty-string/NaN
150211 Entity updated;
151212 updated.string = " foo" ;
@@ -182,6 +243,9 @@ TEST_CASE("Optional") {
182243 SECTION (" Values" ) {
183244 testOptionalValues<Optional>();
184245 }
246+ SECTION (" Null" ) {
247+ testOptionalNull<Optional>();
248+ }
185249 SECTION (" Empty/NaN as value" ) {
186250 testOptionalEmptyNaN<Optional>(true );
187251 }
@@ -191,6 +255,9 @@ TEST_CASE("OptionalAsNull") {
191255 SECTION (" Values" ) {
192256 testOptionalValues<OptionalAsNull>();
193257 }
258+ SECTION (" Nulls" ) {
259+ testOptionalNull<OptionalAsNull>();
260+ }
194261 SECTION (" Empty/NaN as null" ) {
195262 testOptionalEmptyNaN<OptionalAsNull>(false );
196263 }
@@ -233,20 +300,20 @@ void testPtrValues() {
233300 // values inserted -> values loaded
234301 std::unique_ptr<Entity> src = std::move (read);
235302 src->int_ .reset (new int32_t (__LINE__));
236- src->int8 .reset (new int8_t (__LINE__ ));
303+ src->int8 .reset (new int8_t (1 ));
237304 src->int16 .reset (new int16_t (__LINE__));
238305 src->int32 .reset (new int32_t (__LINE__));
239306 src->int64 .reset (new int64_t (__LINE__));
240307 src->uint .reset (new uint32_t (__LINE__));
241- src->uint8 .reset (new uint8_t (__LINE__ ));
308+ src->uint8 .reset (new uint8_t (2 ));
242309 src->uint16 .reset (new uint16_t (__LINE__));
243310 src->uint32 .reset (new uint32_t (__LINE__));
244311 src->uint64 .reset (new uint64_t (__LINE__));
245- src->bool_ .reset (new bool (__LINE__ ));
312+ src->bool_ .reset (new bool (true ));
246313 src->string .reset (new std::string (" foo" ));
247314 src->stringvector .reset (new std::vector<std::string>{" foo" , " bar" });
248- src->byte .reset (new int8_t (__LINE__ ));
249- src->ubyte .reset (new uint8_t (__LINE__ ));
315+ src->byte .reset (new int8_t (3 ));
316+ src->ubyte .reset (new uint8_t (4 ));
250317 src->bytevector .reset (new std::vector<int8_t >{-13 , 30 });
251318 src->ubytevector .reset (new std::vector<uint8_t >{5 , 6 });
252319 src->float32 .reset (new float (__LINE__));
@@ -306,6 +373,66 @@ void testPtrValues() {
306373 REQUIRE (*read->relId == *src->relId );
307374}
308375
376+ template <typename Entity> void testPtrNull () {
377+
378+ Store store = testStore (true , " c-cpp-tests-db" );
379+ Box<Entity> box (store);
380+
381+ // no values inserted -> no values loaded
382+ obx_id id = box.put (Entity ());
383+
384+ // Update object populated with value
385+ Entity update;
386+ update.int_ .reset (new int (__LINE__));
387+ update.int8 .reset (new int8_t (1 ));
388+ update.int16 .reset (new int16_t (__LINE__));
389+ update.int32 .reset (new int32_t (__LINE__));
390+ update.int64 .reset (new int64_t (__LINE__));
391+ update.uint .reset (new unsigned int (__LINE__));
392+ update.uint8 .reset (new uint8_t (2 ));
393+ update.uint16 .reset (new uint16_t (__LINE__));
394+ update.uint32 .reset (new uint32_t (__LINE__));
395+ update.uint64 .reset (new uint64_t (__LINE__));
396+ update.bool_ .reset (new bool (true ));
397+ update.string .reset (new std::string (" foo" ));
398+ update.stringvector .reset (new std::vector<std::string>{" foo" , " bar" });
399+ update.byte .reset (new int8_t (3 ));
400+ update.ubyte .reset (new uint8_t (4 ));
401+ update.bytevector .reset (new std::vector<int8_t >{-13 , 30 });
402+ update.ubytevector .reset (new std::vector<uint8_t >{5 , 6 });
403+ update.float32 .reset (new float (__LINE__));
404+ update.float64 .reset (new double (__LINE__));
405+ update.float_ .reset (new float (__LINE__));
406+ update.double_ .reset (new double (__LINE__));
407+ update.relId .reset (new uint64_t (__LINE__));;
408+
409+ // Updated by null values
410+ box.get (id, update);
411+
412+ REQUIRE_FALSE (update.int_ .operator bool ());
413+ REQUIRE_FALSE (update.int8 .operator bool ());
414+ REQUIRE_FALSE (update.int16 .operator bool ());
415+ REQUIRE_FALSE (update.int32 .operator bool ());
416+ REQUIRE_FALSE (update.int64 .operator bool ());
417+ REQUIRE_FALSE (update.uint .operator bool ());
418+ REQUIRE_FALSE (update.uint8 .operator bool ());
419+ REQUIRE_FALSE (update.uint16 .operator bool ());
420+ REQUIRE_FALSE (update.uint32 .operator bool ());
421+ REQUIRE_FALSE (update.uint64 .operator bool ());
422+ REQUIRE_FALSE (update.bool_ .operator bool ());
423+ REQUIRE_FALSE (update.string .operator bool ());
424+ REQUIRE_FALSE (update.stringvector .operator bool ());
425+ REQUIRE_FALSE (update.byte .operator bool ());
426+ REQUIRE_FALSE (update.ubyte .operator bool ());
427+ REQUIRE_FALSE (update.bytevector .operator bool ());
428+ REQUIRE_FALSE (update.ubytevector .operator bool ());
429+ REQUIRE_FALSE (update.float32 .operator bool ());
430+ REQUIRE_FALSE (update.float64 .operator bool ());
431+ REQUIRE_FALSE (update.float_ .operator bool ());
432+ REQUIRE_FALSE (update.double_ .operator bool ());
433+ REQUIRE_FALSE (update.relId .operator bool ());
434+ }
435+
309436template <typename Entity>
310437void testPtrEmptyNaN (bool asValue) {
311438 // Check for optional pointer types with "..-as-null" flag.
@@ -324,20 +451,24 @@ void testPtrEmptyNaN(bool asValue) {
324451 nulled->float64 .reset ( new double ( std::nan (" 2" ) ) );
325452 nulled->double_ .reset ( new double ( std::nan (" -3" ) ) );
326453 nulled->float_ .reset ( new float ( std::nanf (" -4" ) ) );
454+ // Reset one other field
327455 nulled->int_ .reset ( new int (23 ) );
328456
329457 box.put (*nulled);
330458
331459 // Update
332460 Entity update;
333461
334- // Set values
462+ // Set Empty/NaN values
335463 update.string .reset (new std::string (" foo" ));
336464 update.float32 .reset (new float (1 .0f ));
337465 update.float64 .reset (new double (2.0 ));
338466 update.double_ .reset (new double (4.0 ));
339467 update.float_ .reset (new float (4 .0f ));
468+
469+ // Set other and new-field
340470 update.int_ .reset (new int (42 ));
471+ update.uint .reset (new unsigned int (311 ));
341472
342473 // Update
343474 box.get (id,update);
@@ -355,9 +486,11 @@ void testPtrEmptyNaN(bool asValue) {
355486 REQUIRE_FALSE (update.double_ .operator bool ());
356487 REQUIRE_FALSE (update.float_ .operator bool ());
357488 }
358- // Always as Value :
489+ // Updated by optional value :
359490 REQUIRE (update.int_ .operator bool ());
360491 REQUIRE (*update.int_ == 23 );
492+ // Overwritten by optional null value:
493+ REQUIRE_FALSE (update.uint .operator bool ());
361494}
362495} // namespace
363496
@@ -366,6 +499,9 @@ TEST_CASE("UniquePtr") {
366499 static_assert (std::is_same<decltype (UniquePtr::int_), std::unique_ptr<int32_t >>::value, " must be std::unique_ptr" );
367500 testPtrValues<UniquePtr>();
368501 }
502+ SECTION (" Null" ) {
503+ testPtrNull<UniquePtr>();
504+ }
369505 SECTION (" Empty/NaN as value" ) {
370506 testPtrEmptyNaN<UniquePtr>(true );
371507 }
@@ -376,32 +512,36 @@ TEST_CASE("UniquePtrAsNull") {
376512 static_assert (std::is_same<decltype (UniquePtrAsNull::int_), std::unique_ptr<int32_t >>::value, " must be std::unique_ptr" );
377513 testPtrValues<UniquePtrAsNull>();
378514 }
379-
515+ SECTION (" Null" ) {
516+ testPtrNull<UniquePtrAsNull>();
517+ }
380518 SECTION (" Empty/NaN as null" ) {
381519 testPtrEmptyNaN<UniquePtrAsNull>(false );
382520 }
383521}
384522
385523TEST_CASE (" SharedPtr" ) {
386-
387524 SECTION (" Values" ) {
388525 static_assert (std::is_same<decltype (SharedPtr::int_), std::shared_ptr<int32_t >>::value, " must be std::shared_ptr" );
389526 testPtrValues<SharedPtr>();
390527 }
391-
528+ SECTION (" Null" ) {
529+ testPtrNull<SharedPtr>();
530+ }
392531 SECTION (" Empty/NaN as value" ) {
393532 testPtrEmptyNaN<SharedPtr>(true );
394533 }
395534}
396535
397536TEST_CASE (" SharedPtrAsNull" ) {
398-
399537 SECTION (" Values" ) {
400538 static_assert (std::is_same<decltype (SharedPtrAsNull::int_), std::shared_ptr<int32_t >>::value, " must be std::shared_ptr" );
401539 testPtrValues<SharedPtrAsNull>();
402540 }
403-
404- SECTION (" Empty/NaN as null" ) {
541+ SECTION (" Null" ) {
542+ testPtrNull<SharedPtrAsNull>();
543+ }
544+ SECTION (" EmptyNaN as null" ) {
405545 testPtrEmptyNaN<SharedPtrAsNull>(false );
406546 }
407547}
@@ -436,6 +576,7 @@ TEST_CASE("TypefulAsNull") {
436576 updated.double_ = 4.0 ;
437577 updated.float_ = 4 .0f ;
438578 updated.int_ = 42 ;
579+ updated.uint = 311 ;
439580
440581 // Update
441582 box.get (id,updated);
@@ -447,8 +588,9 @@ TEST_CASE("TypefulAsNull") {
447588 REQUIRE (updated.double_ == 0.0 );
448589 REQUIRE (updated.float_ == 0 .0f );
449590
450- // Others are set to value
591+ // Two others are set to value
451592 REQUIRE (updated.int_ == 23 );
593+ REQUIRE (updated.uint == 0 );
452594}
453595
454596namespace {
0 commit comments