// Last parameter exists to keep everything hidden in options template <class IArchive, class OArchive> inline void test_endian_serialization( typename IArchive::Options const & iOptions, typename OArchive::Options const & oOptions, const std::uint8_t inputLittleEndian ) { std::random_device rd; std::mt19937 gen(rd()); for(size_t i=0; i<100; ++i) { bool o_bool = random_value<uint8_t>(gen) % 2 ? true : false; uint8_t o_uint8 = random_value<uint8_t>(gen); int8_t o_int8 = random_value<int8_t>(gen); uint16_t o_uint16 = random_value<uint16_t>(gen); int16_t o_int16 = random_value<int16_t>(gen); uint32_t o_uint32 = random_value<uint32_t>(gen); int32_t o_int32 = random_value<int32_t>(gen); uint64_t o_uint64 = random_value<uint64_t>(gen); int64_t o_int64 = random_value<int64_t>(gen); float o_float = random_value<float>(gen); double o_double = random_value<double>(gen); std::vector<int32_t> o_vector(100); for(auto & elem : o_vector) elem = random_value<uint32_t>(gen); std::ostringstream os; { OArchive oar(os, oOptions); oar(o_bool); oar(o_uint8); oar(o_int8); oar(o_uint16); oar(o_int16); oar(o_uint32); oar(o_int32); oar(o_uint64); oar(o_int64); oar(o_float); oar(o_double); // We can't test vector directly here since we are artificially interfering with the endianness, // which can result in the size being incorrect oar(cereal::binary_data( o_vector.data(), static_cast<std::size_t>( o_vector.size() * sizeof(int32_t) ) )); } bool i_bool = false; uint8_t i_uint8 = 0; int8_t i_int8 = 0; uint16_t i_uint16 = 0; int16_t i_int16 = 0; uint32_t i_uint32 = 0; int32_t i_int32 = 0; uint64_t i_uint64 = 0; int64_t i_int64 = 0; float i_float = 0; double i_double = 0; std::vector<int32_t> i_vector(100); std::istringstream is(os.str()); { IArchive iar(is, iOptions); iar(i_bool); iar(i_uint8); iar(i_int8); iar(i_uint16); iar(i_int16); iar(i_uint32); iar(i_int32); iar(i_uint64); iar(i_int64); iar(i_float); iar(i_double); iar(cereal::binary_data( i_vector.data(), static_cast<std::size_t>( i_vector.size() * sizeof(int32_t) ) )); } // Convert to big endian if we expect to read big and didn't start big if( cereal::portable_binary_detail::is_little_endian() ^ inputLittleEndian ) // Convert to little endian if { CEREAL_TEST_SWAP_OUTPUT for( auto & val : o_vector ) swapBytes(val); } CEREAL_TEST_CHECK_EQUAL check_collection(i_vector, o_vector); }
template <class IArchive, class OArchive> inline void test_map() { std::random_device rd; std::mt19937 gen(rd()); for(int ii=0; ii<100; ++ii) { std::map<size_t, std::vector<StructInternalSerialize>> o_vectormap; for(int j=0; j<10; ++j) { size_t id = random_value<size_t>(gen); for(int k=0; k<100; ++k) o_vectormap[id].emplace_back(random_value<int>(gen), random_value<int>(gen)); } std::map<std::string, int> o_podmap; for(int j=0; j<100; ++j) o_podmap.insert({random_value<std::string>(gen), random_value<int>(gen)}); std::map<int, StructInternalSerialize> o_isermap; for(int j=0; j<100; ++j) o_isermap.insert({random_value<int>(gen), { random_value<int>(gen), random_value<int>(gen) }}); std::map<int, StructInternalSplit> o_isplmap; for(int j=0; j<100; ++j) o_isplmap.insert({random_value<int>(gen), { random_value<int>(gen), random_value<int>(gen) }}); std::map<uint32_t, StructExternalSerialize> o_esermap; for(int j=0; j<100; ++j) o_esermap.insert({random_value<uint32_t>(gen), { random_value<int>(gen), random_value<int>(gen) }}); std::map<int8_t, StructExternalSplit> o_esplmap; for(int j=0; j<100; ++j) o_esplmap.insert({random_value<char>(gen), { random_value<int>(gen), random_value<int>(gen) }}); std::ostringstream os; { OArchive oar(os); oar(o_vectormap); oar(o_podmap); oar(o_isermap); oar(o_isplmap); oar(o_esermap); oar(o_esplmap); } std::map<size_t, std::vector<StructInternalSerialize>> i_vectormap; std::map<std::string, int> i_podmap; std::map<int, StructInternalSerialize> i_isermap; std::map<int, StructInternalSplit> i_isplmap; std::map<uint32_t, StructExternalSerialize> i_esermap; std::map<int8_t, StructExternalSplit> i_esplmap; std::istringstream is(os.str()); { IArchive iar(is); iar(i_vectormap); iar(i_podmap); iar(i_isermap); iar(i_isplmap); iar(i_esermap); iar(i_esplmap); } CHECK_EQ(i_vectormap.size(), o_vectormap.size()); auto o_v_it = o_vectormap.begin(); auto i_v_it = i_vectormap.begin(); for(;o_v_it != o_vectormap.end(); ++o_v_it, ++i_v_it) { CHECK_EQ(i_v_it->second.size(), o_v_it->second.size()); check_collection(i_v_it->second, o_v_it->second); } check_collection(i_podmap, o_podmap); check_collection(i_isermap, o_isermap); check_collection(i_isplmap, o_isplmap); check_collection(i_esermap, o_esermap); check_collection(i_esplmap, o_esplmap); } }
template <class IArchive, class OArchive> inline void test_valarray() { std::random_device rd; std::mt19937 gen(rd()); for (int ii = 0; ii<100; ++ii) { std::valarray<int> o_podvalarray(100); for (auto & elem : o_podvalarray) elem = random_value<int>(gen); std::valarray<StructInternalSerialize> o_iservalarray(100); for (auto & elem : o_iservalarray) elem = StructInternalSerialize(random_value<int>(gen), random_value<int>(gen)); std::valarray<StructInternalSplit> o_isplvalarray(100); for (auto & elem : o_isplvalarray) elem = StructInternalSplit(random_value<int>(gen), random_value<int>(gen)); std::valarray<StructExternalSerialize> o_eservalarray(100); for (auto & elem : o_eservalarray) elem = StructExternalSerialize(random_value<int>(gen), random_value<int>(gen)); std::valarray<StructExternalSplit> o_esplvalarray(100); for (auto & elem : o_esplvalarray) elem = StructExternalSplit(random_value<int>(gen), random_value<int>(gen)); std::ostringstream os; { OArchive oar(os); oar(o_podvalarray); oar(o_iservalarray); oar(o_isplvalarray); oar(o_eservalarray); oar(o_esplvalarray); } std::valarray<int> i_podvalarray; std::valarray<StructInternalSerialize> i_iservalarray; std::valarray<StructInternalSplit> i_isplvalarray; std::valarray<StructExternalSerialize> i_eservalarray; std::valarray<StructExternalSplit> i_esplvalarray; std::istringstream is(os.str()); { IArchive iar(is); iar(i_podvalarray); iar(i_iservalarray); iar(i_isplvalarray); iar(i_eservalarray); iar(i_esplvalarray); } CHECK_EQ(i_podvalarray.size(), o_podvalarray.size()); CHECK_EQ(i_iservalarray.size(), o_iservalarray.size()); CHECK_EQ(i_isplvalarray.size(), o_isplvalarray.size()); CHECK_EQ(i_eservalarray.size(), o_eservalarray.size()); CHECK_EQ(i_esplvalarray.size(), o_esplvalarray.size()); check_collection(i_podvalarray , o_podvalarray ); check_collection(i_iservalarray, o_iservalarray); check_collection(i_isplvalarray, o_isplvalarray); check_collection(i_eservalarray, o_eservalarray); check_collection(i_esplvalarray, o_esplvalarray); } }
void test_deque() { std::random_device rd; std::mt19937 gen(rd()); for(int ii=0; ii<100; ++ii) { std::deque<int> o_poddeque(100); for(auto & elem : o_poddeque) elem = random_value<int>(gen); std::deque<StructInternalSerialize> o_iserdeque(100); for(auto & elem : o_iserdeque) elem = StructInternalSerialize( random_value<int>(gen), random_value<int>(gen) ); std::deque<StructInternalSplit> o_ispldeque(100); for(auto & elem : o_ispldeque) elem = StructInternalSplit( random_value<int>(gen), random_value<int>(gen) ); std::deque<StructExternalSerialize> o_eserdeque(100); for(auto & elem : o_eserdeque) elem = StructExternalSerialize( random_value<int>(gen), random_value<int>(gen) ); std::deque<StructExternalSplit> o_espldeque(100); for(auto & elem : o_espldeque) elem = StructExternalSplit( random_value<int>(gen), random_value<int>(gen) ); std::ostringstream os; { OArchive oar(os); oar(o_poddeque); oar(o_iserdeque); oar(o_ispldeque); oar(o_eserdeque); oar(o_espldeque); } std::deque<int> i_poddeque; std::deque<StructInternalSerialize> i_iserdeque; std::deque<StructInternalSplit> i_ispldeque; std::deque<StructExternalSerialize> i_eserdeque; std::deque<StructExternalSplit> i_espldeque; std::istringstream is(os.str()); { IArchive iar(is); iar(i_poddeque); iar(i_iserdeque); iar(i_ispldeque); iar(i_eserdeque); iar(i_espldeque); } CHECK_EQ(i_poddeque.size(), o_poddeque.size()); CHECK_EQ(i_iserdeque.size(), o_iserdeque.size()); CHECK_EQ(i_ispldeque.size(), o_ispldeque.size()); CHECK_EQ(i_eserdeque.size(), o_eserdeque.size()); CHECK_EQ(i_espldeque.size(), o_espldeque.size()); check_collection(i_poddeque, o_poddeque ); check_collection(i_iserdeque, o_iserdeque); check_collection(i_ispldeque, o_ispldeque); check_collection(i_eserdeque, o_eserdeque); check_collection(i_espldeque, o_espldeque); } }
int main(int argc, char **argv) { krb5_ccache ccinitial, ccu1, ccu2; krb5_principal princ1, princ2, princ3; const char *collection_name, *typename; char *initial_primary_name, *unique1_name, *unique2_name; /* * Get the collection name from the command line. This is a ccache name * with collection semantics, like DIR:/path/to/directory. This test * program assumes that the collection is empty to start with. */ assert(argc == 2); collection_name = argv[1]; /* * Set the default ccache for the context to be the collection name, so the * library can find the collection. */ check(krb5_init_context(&ctx)); check(krb5_cc_set_default_name(ctx, collection_name)); /* * Resolve the collection name. Since the collection is empty, this should * generate a subsidiary name of an uninitialized cache. Getting the name * of the resulting cache should give us the subsidiary name, not the * collection name. This resulting subsidiary name should be consistent if * we resolve the collection name again, and the collection should still be * empty since we haven't initialized the cache. */ check(krb5_cc_resolve(ctx, collection_name, &ccinitial)); check(krb5_cc_get_full_name(ctx, ccinitial, &initial_primary_name)); assert(strcmp(initial_primary_name, collection_name) != 0); check_primary_name(collection_name, initial_primary_name); check_collection(NULL, 0); check_princ(collection_name, NULL); check_princ(initial_primary_name, NULL); /* * Before initializing the primary ccache, generate and initialize two * unique caches of the collection's type. Check that the cache names * resolve to the generated caches and appear in the collection. (They * might appear before being initialized; that's not currently considered * important). The primary cache for the collection should remain as the * unitialized cache from the previous step. */ typename = krb5_cc_get_type(ctx, ccinitial); check(krb5_cc_new_unique(ctx, typename, NULL, &ccu1)); check(krb5_cc_get_full_name(ctx, ccu1, &unique1_name)); check(krb5_parse_name(ctx, "princ1@X", &princ1)); check(krb5_cc_initialize(ctx, ccu1, princ1)); check_princ(unique1_name, princ1); check_match(princ1, unique1_name); check_collection(NULL, 1, unique1_name); check(krb5_cc_new_unique(ctx, typename, NULL, &ccu2)); check(krb5_cc_get_full_name(ctx, ccu2, &unique2_name)); check(krb5_parse_name(ctx, "princ2@X", &princ2)); check(krb5_cc_initialize(ctx, ccu2, princ2)); check_princ(unique2_name, princ2); check_match(princ1, unique1_name); check_match(princ2, unique2_name); check_collection(NULL, 2, unique1_name, unique2_name); assert(strcmp(unique1_name, initial_primary_name) != 0); assert(strcmp(unique1_name, collection_name) != 0); assert(strcmp(unique2_name, initial_primary_name) != 0); assert(strcmp(unique2_name, collection_name) != 0); assert(strcmp(unique2_name, unique1_name) != 0); check_primary_name(collection_name, initial_primary_name); /* * Initialize the initial primary cache. Make sure it didn't change names, * that the previously retrieved name and the collection name both resolve * to the initialized cache, and that it now appears first in the * collection. */ check(krb5_parse_name(ctx, "princ3@X", &princ3)); check(krb5_cc_initialize(ctx, ccinitial, princ3)); check_name(ccinitial, initial_primary_name); check_princ(initial_primary_name, princ3); check_princ(collection_name, princ3); check_match(princ3, initial_primary_name); check_collection(initial_primary_name, 2, unique1_name, unique2_name); /* * Switch the primary cache to each cache we have open. One each switch, * check the primary name, check that the collection resolves to the * expected cache, and check that the new primary name appears first in the * collection. */ check(krb5_cc_switch(ctx, ccu1)); check_primary_name(collection_name, unique1_name); check_princ(collection_name, princ1); check_collection(unique1_name, 2, initial_primary_name, unique2_name); check(krb5_cc_switch(ctx, ccu2)); check_primary_name(collection_name, unique2_name); check_princ(collection_name, princ2); check_collection(unique2_name, 2, initial_primary_name, unique1_name); check(krb5_cc_switch(ctx, ccinitial)); check_primary_name(collection_name, initial_primary_name); check_princ(collection_name, princ3); check_collection(initial_primary_name, 2, unique1_name, unique2_name); /* * Temporarily set the context default ccache to a subsidiary name, and * check that iterating over the collection yields that subsidiary cache * and no others. */ check(krb5_cc_set_default_name(ctx, unique1_name)); check_collection(unique1_name, 0); check(krb5_cc_set_default_name(ctx, collection_name)); /* * Destroy the primary cache. Make sure this causes both the initial * primary name and the collection name to resolve to an uninitialized * cache. Make sure the primary name doesn't change and doesn't appear in * the collection any more. */ check(krb5_cc_destroy(ctx, ccinitial)); check_princ(initial_primary_name, NULL); check_princ(collection_name, NULL); check_primary_name(collection_name, initial_primary_name); check_match(princ1, unique1_name); check_match(princ2, unique2_name); check_match(princ3, NULL); check_collection(NULL, 2, unique1_name, unique2_name); /* * Switch to the first unique cache after destroying the primary cache. * Check that the collection name resolves to this cache and that the new * primary name appears first in the collection. */ check(krb5_cc_switch(ctx, ccu1)); check_primary_name(collection_name, unique1_name); check_princ(collection_name, princ1); check_collection(unique1_name, 1, unique2_name); /* * Destroy the second unique cache (which is not the current primary), * check that it is on longer initialized, and check that it no longer * appears in the collection. Check that destroying the non-primary cache * doesn't affect the primary name. */ check(krb5_cc_destroy(ctx, ccu2)); check_princ(unique2_name, NULL); check_match(princ2, NULL); check_collection(unique1_name, 0); check_primary_name(collection_name, unique1_name); check_match(princ1, unique1_name); check_princ(collection_name, princ1); /* * Destroy the first unique cache. Check that the collection is empty and * still has the same primary name. */ check(krb5_cc_destroy(ctx, ccu1)); check_princ(unique1_name, NULL); check_princ(collection_name, NULL); check_primary_name(collection_name, unique1_name); check_match(princ1, NULL); check_collection(NULL, 0); krb5_free_string(ctx, initial_primary_name); krb5_free_string(ctx, unique1_name); krb5_free_string(ctx, unique2_name); krb5_free_principal(ctx, princ1); krb5_free_principal(ctx, princ2); krb5_free_principal(ctx, princ3); krb5_free_context(ctx); return 0; }