/* * Author: Sven Gothel * Copyright (c) 2020 Gothel Software e.K. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include "test_datatype01.hpp" #include "test_datatype02.hpp" #include #include #include #include #include #include /** * Test general use of jau::darray, jau::cow_darray and jau::cow_vector. */ using namespace jau; /**********************************************************************************************************************************************/ /**********************************************************************************************************************************************/ /**********************************************************************************************************************************************/ /**********************************************************************************************************************************************/ /**********************************************************************************************************************************************/ TEST_CASE( "JAU DArray Test 01 - jau::darray initializer list", "[datatype][jau][darray]" ) { int i = 0; jau::for_each(GATT_SERVICES.begin(), GATT_SERVICES.end(), [&i](const GattServiceCharacteristic* ml){ (void)ml; // printf("XX: %s\n\n", ml->toString().c_str()); ++i; }); REQUIRE(3 == i); } static int countGattCharacteristicSpecList01ConstRef(const jau::darray& clist) { int i = 0; jau::for_each(clist.begin(), clist.end(), [&i](const GattCharacteristicSpec& ml){ (void)ml; // printf("XX: %s\n\n", ml->toString().c_str()); ++i; }); return i; } static int countGattCharacteristicSpecList02Copy(jau::darray clist) { int i = 0; jau::for_each(clist.begin(), clist.end(), [&i](const GattCharacteristicSpec& ml){ (void)ml; // printf("XX: %s\n\n", ml->toString().c_str()); ++i; }); return i; } TEST_CASE( "JAU DArray Test 02 - jau::darray immutable type (const)", "[const][jau][darray]" ) { const GattCharacteristicSpec cs1 = { DEVICE_NAME, Mandatory, // GattCharacteristicPropertySpec[9]: { { Read, Mandatory }, { WriteWithAck, Optional }, { WriteNoAck, Excluded }, { AuthSignedWrite, Excluded }, { ReliableWriteExt, Excluded }, { Notify, Excluded }, { Indicate, Excluded }, { AuxWriteExt, Excluded }, { Broadcast, Excluded } }, // GattClientCharacteristicConfigSpec: { Excluded, { Read, Excluded}, { WriteWithAck, Excluded } } }; jau::darray clist = { cs1, { APPEARANCE, Mandatory, // GattCharacteristicPropertySpec[9]: { { Read, Mandatory }, { WriteWithAck, Excluded }, { WriteNoAck, Excluded }, { AuthSignedWrite, Excluded }, { ReliableWriteExt, Excluded }, { Notify, Excluded }, { Indicate, Excluded }, { AuxWriteExt, Excluded }, { Broadcast, Excluded } }, // GattClientCharacteristicConfigSpec: { Excluded, { Read, Excluded}, { WriteWithAck, Excluded } } } }; clist.push_back( cs1 ); int i = 0; jau::for_each(clist.begin(), clist.end(), [&i](const GattCharacteristicSpec& ml){ (void)ml; // printf("XX: %s\n\n", ml->toString().c_str()); ++i; }); REQUIRE(3 == i); REQUIRE(3 == countGattCharacteristicSpecList01ConstRef(clist)); REQUIRE(3 == countGattCharacteristicSpecList02Copy(clist)); } /**********************************************************************************************************************************************/ /**********************************************************************************************************************************************/ /**********************************************************************************************************************************************/ /**********************************************************************************************************************************************/ /**********************************************************************************************************************************************/ template using SharedPayloadListMemMove = jau::darray, jau::nsize_t, jau::callocator>, true /* use_memmove */>; // JAU_TYPENAME_CUE_ALL(SharedPayloadListMemMove) template using SharedPayloadListDefault = jau::darray>; // JAU_TYPENAME_CUE_ALL(SharedPayloadListDefault) template struct NamedSharedPayloadListDefault { int name; SharedPayloadListDefault payload; std::string toString() const noexcept { std::string res = "NSPL-Default-"+std::to_string(name)+"[sz"+std::to_string(payload.size())+": "; int i=0; jau::for_each(payload.cbegin(), payload.cend(), [&](const std::shared_ptr& e) { if(0 struct NamedSharedPayloadListMemMove { int name; SharedPayloadListMemMove payload; std::string toString() const noexcept { std::string res = "NSPL-MemMove-"+std::to_string(name)+"[sz"+std::to_string(payload.size())+": "; int i=0; jau::for_each(payload.cbegin(), payload.cend(), [&](const std::shared_ptr& e) { if(0 using PayloadListMemMove = jau::darray, true /* use_memmove */>; // JAU_TYPENAME_CUE_ALL(PayloadListMemMove) template using PayloadListDefault = jau::darray; // JAU_TYPENAME_CUE_ALL(PayloadListDefault) template struct NamedPayloadListDefault { int name; PayloadListDefault payload; std::string toString() const noexcept { std::string res = "NPL-Default-"+std::to_string(name)+"[sz"+std::to_string(payload.size())+": "; int i=0; jau::for_each(payload.cbegin(), payload.cend(), [&](const typename PayloadListDefault::value_type & e) { if(0 struct NamedPayloadListMemMove { int name; PayloadListMemMove payload; std::string toString() const noexcept { std::string res = "NPL-MemMove-"+std::to_string(name)+"[sz"+std::to_string(payload.size())+": "; int i=0; jau::for_each(payload.cbegin(), payload.cend(), [&](const Payload& e) { if(0 static NamedSharedPayloadListDefault makeNamedSharedPayloadListDefault(int name) { SharedPayloadListDefault data; int i=0; for(i=0; i<2; i++) { std::shared_ptr sp(std::make_shared( name+i )); // copy-elision + make_shared in-place data.push_back( sp ); } for(i=2; i<4; i++) { std::shared_ptr sp(new Payload( name+i )); // double malloc: 1 Payload, 2 shared_ptr data.push_back( std::move( sp ) ); // move the less efficient into } return NamedSharedPayloadListDefault{name, data}; } template static NamedSharedPayloadListDefault modifyCopyOfNamedSharedPayloadListDefault(NamedSharedPayloadListDefault src) { printf("XXX1: %s\n", src.toString().c_str()); src.payload.pop_back(); src.payload.erase(src.payload.cbegin()); printf("XXX2: %s\n", src.toString().c_str()); return src; } template static NamedSharedPayloadListMemMove makeNamedSharedPayloadListMemMove(int name) { SharedPayloadListMemMove data; int i=0; for(i=0; i<2; i++) { std::shared_ptr sp(std::make_shared( name+i )); // copy-elision + make_shared in-place data.push_back( sp ); } for(i=2; i<4; i++) { std::shared_ptr sp(new Payload( name+i )); // double malloc: 1 Payload, 2 shared_ptr data.push_back( std::move( sp ) ); // move the less efficient into } return NamedSharedPayloadListMemMove{name, data}; } template static NamedPayloadListDefault makeNamedPayloadListDefault(int name) { PayloadListDefault data; int i=0; for(i=0; i<2; i++) { Payload sp( name+i ); // copy-elision data.push_back( sp ); } for(i=2; i<4; i++) { Payload sp( name+i ); data.push_back( std::move( sp ) ); // move the less efficient into } return NamedPayloadListDefault{name, data}; } template static NamedPayloadListMemMove makeNamedPayloadListMemMove(int name) { PayloadListMemMove data; int i=0; for(i=0; i<2; i++) { Payload sp( name+i ); // copy-elision data.push_back( sp ); } for(i=2; i<4; i++) { Payload sp( name+i ); data.push_back( std::move( sp ) ); // move the less efficient into } return NamedPayloadListMemMove{name, data}; } JAU_TYPENAME_CUE_ALL(std::shared_ptr) JAU_TYPENAME_CUE_ALL(jau::darray) JAU_TYPENAME_CUE_ALL(jau::darray>) JAU_TYPENAME_CUE_ALL(std::shared_ptr) JAU_TYPENAME_CUE_ALL(jau::darray) JAU_TYPENAME_CUE_ALL(jau::darray>) #define CHECK_TRAITS 0 template< class Cont > static void print_container_info(const std::string& type_id, const Cont &c, std::enable_if_t< jau::is_darray_type::value, bool> = true ) { printf("\nContainer Type %s (a darray, a cow %d):\n - Uses memmove %d (trivially_copyable %d); realloc %d; base_of jau::callocator %d; secmem %d; size %d bytes\n", type_id.c_str(), jau::is_cow_type::value, Cont::uses_memmove, std::is_trivially_copyable::value, Cont::uses_realloc, std::is_base_of, typename Cont::allocator_type>::value, Cont::uses_secmem, (int)sizeof(c)); } template static void print_container_info(const std::string& type_id, const Cont &c, std::enable_if_t< !jau::is_darray_type::value, bool> = true ) { printf("\nContainer Type %s (!darray, a cow %d); size %d bytes\n", type_id.c_str(), jau::is_cow_type::value, (int)sizeof(c)); } template static void testDArrayValueType(const std::string& type_id) { { // jau::type_cue::print(type_id, jau::TypeTraitGroup::ALL); // jau::type_cue>::print("std::shared_ptr<"+type_id+">", jau::TypeTraitGroup::ALL); } { #if CHECK_TRAITS CHECK( true == std::is_base_of, jau::callocator>::value); CHECK( true == PayloadListDefault::uses_realloc); CHECK( true == std::is_trivially_copyable::value); CHECK( true == PayloadListDefault::uses_memmove); #endif NamedPayloadListDefault data = makeNamedPayloadListDefault(1); print_container_info("NamedPayloadListDefault<"+type_id+">", data.payload); NamedPayloadListDefault data2 = data; data2.payload.erase(data2.payload.cbegin()); NamedPayloadListDefault data3(data); data3.payload.erase(data3.payload.begin(), data3.payload.cbegin()+data3.payload.size()/2); NamedPayloadListDefault data8 = makeNamedPayloadListDefault(8); data8.payload.insert(data8.payload.begin(), data.payload.cbegin(), data.payload.cend()); printf("COPY-0: %s\n\n", data.toString().c_str()); printf("COPY-1: %s\n\n", data2.toString().c_str()); printf("COPY-2: %s\n\n", data3.toString().c_str()); printf("COPY+2: %s\n\n", data8.toString().c_str()); } { #if CHECK_TRAITS CHECK( true == std::is_base_of, jau::callocator>::value); CHECK( true == PayloadListMemMove::uses_realloc); CHECK( true == std::is_trivially_copyable::value); CHECK( true == PayloadListMemMove::uses_memmove); #endif NamedPayloadListMemMove data = makeNamedPayloadListMemMove(1); print_container_info("NamedPayloadListMemMove<"+type_id+">", data.payload); NamedPayloadListMemMove data2 = data; data2.payload.erase(data2.payload.cbegin()); NamedPayloadListMemMove data3(data); data3.payload.erase(data3.payload.begin(), data3.payload.cbegin()+data3.payload.size()/2); NamedPayloadListMemMove data8 = makeNamedPayloadListMemMove(8); data8.payload.insert(data8.payload.begin(), data.payload.cbegin(), data.payload.cend()); printf("COPY-0: %s\n\n", data.toString().c_str()); printf("COPY-1: %s\n\n", data2.toString().c_str()); printf("COPY-2: %s\n\n", data3.toString().c_str()); printf("COPY+2: %s\n\n", data8.toString().c_str()); } { #if CHECK_TRAITS CHECK( true == std::is_base_of>, jau::callocator>>::value); CHECK( true == SharedPayloadListDefault::uses_realloc); CHECK( true == std::is_trivially_copyable>::value); CHECK( true == SharedPayloadListDefault::uses_memmove); #endif NamedSharedPayloadListDefault data = makeNamedSharedPayloadListDefault(1); print_container_info("NamedSharedPayloadListDefault<"+type_id+">", data.payload); NamedSharedPayloadListDefault data2 = data; data2.payload.erase(data2.payload.cbegin()); NamedSharedPayloadListDefault data3(data); data3.payload.erase(data3.payload.begin(), data3.payload.cbegin()+data3.payload.size()/2); NamedSharedPayloadListDefault data8 = makeNamedSharedPayloadListDefault(8); data8.payload.insert(data8.payload.begin(), data.payload.cbegin(), data.payload.cend()); printf("COPY-0: %s\n\n", data.toString().c_str()); printf("COPY-1: %s\n\n", data2.toString().c_str()); printf("COPY-2: %s\n\n", data3.toString().c_str()); printf("COPY+2: %s\n\n", data8.toString().c_str()); NamedSharedPayloadListDefault data8_mod(modifyCopyOfNamedSharedPayloadListDefault(data8)); printf("MODI+2-2: %s\n\n", data8_mod.toString().c_str()); struct Holder { NamedSharedPayloadListDefault lala; NamedSharedPayloadListDefault & get_ref() { return lala; } NamedSharedPayloadListDefault & get_ref2() { lala.payload.pop_back(); return lala; } NamedSharedPayloadListDefault get_copy() { return lala; } }; Holder holder{ data }; NamedSharedPayloadListDefault & r1r1 = holder.get_ref(); printf("R1R1: %s\n\n", r1r1.toString().c_str()); NamedSharedPayloadListDefault r2c1 = holder.get_ref(); printf("R1C1: %s\n\n", r2c1.toString().c_str()); NamedSharedPayloadListDefault c1c2 = holder.get_copy(); printf("C1C2: %s\n\n", c1c2.toString().c_str()); r1r1 = holder.get_ref2(); printf("R2R2: %s\n\n", r1r1.toString().c_str()); } { #if CHECK_TRAITS CHECK( true == std::is_base_of>, jau::callocator>>::value); CHECK( true == SharedPayloadListMemMove::uses_realloc); CHECK( true == std::is_trivially_copyable>::value); CHECK( true == SharedPayloadListMemMove::uses_memmove); #endif NamedSharedPayloadListMemMove data = makeNamedSharedPayloadListMemMove(1); print_container_info("NamedSharedPayloadListMemMove<"+type_id+">", data.payload); NamedSharedPayloadListMemMove data2 = data; data2.payload.erase(data2.payload.cbegin()); NamedSharedPayloadListMemMove data3(data); data3.payload.erase(data3.payload.begin(), data3.payload.cbegin()+data3.payload.size()/2); NamedSharedPayloadListMemMove data8 = makeNamedSharedPayloadListMemMove(8); data8.payload.insert(data8.payload.begin(), data.payload.cbegin(), data.payload.cend()); printf("COPY-0: %s\n\n", data.toString().c_str()); printf("COPY-1: %s\n\n", data2.toString().c_str()); printf("COPY-2: %s\n\n", data3.toString().c_str()); printf("COPY+2: %s\n\n", data8.toString().c_str()); } } static GattServiceCharacteristic returnGattSrvcChar(int i) { return *GATT_SERVICES[i]; } static void testDArrayGattServiceCharacteristic() { #if CHECK_TRAITS CHECK( true == std::is_base_of, jau::callocator>::value); CHECK( true == GattCharacteristicSpecList::uses_realloc); CHECK( true == GattCharacteristicSpecList::uses_memmove); CHECK( true == std::is_trivially_copyable::value); #endif GattServiceCharacteristic gatt2 = returnGattSrvcChar(1); print_container_info("darray", gatt2.characteristics); gatt2.characteristics.erase(gatt2.characteristics.cbegin()); GattServiceCharacteristic gatt2b = gatt2; gatt2b.characteristics.erase(gatt2b.characteristics.cbegin()); GattServiceCharacteristic gatt2c(gatt2); gatt2c.characteristics.erase(gatt2c.characteristics.cbegin()); printf("COPY0-1: %s\n\n", gatt2.toString().c_str()); printf("COPY1-2: %s\n\n", gatt2b.toString().c_str()); printf("COPY2-3: %s\n\n", gatt2c.toString().c_str()); } TEST_CASE( "JAU DArray Test 10 - jau::darray value_type behavior (type traits)", "[datatype][jau][darray]" ) { testDArrayValueType("uint64_t"); testDArrayValueType("Addr48Bit"); testDArrayValueType("DataType01"); testDArrayValueType("DataType02"); testDArrayGattServiceCharacteristic(); } /**********************************************************************************************************************************************/ /**********************************************************************************************************************************************/ /**********************************************************************************************************************************************/ /**********************************************************************************************************************************************/ /**********************************************************************************************************************************************/