#include "UnitTest++.h" #include "test_utils.hh" #include "geners/VarPack.hh" #include "geners/IOPtr.hh" #include "geners/StringArchive.hh" #include "geners/Record.hh" #include "geners/Reference.hh" using namespace gs; using namespace std; #ifdef CPP11_STD_AVAILABLE #define io_ptr(obj) gs::make_IOPtr(obj) namespace { TEST(VarPack) { typedef CPP11_shared_ptr Dptr; StringArchive ar0; // Write a tuple which we will later read as a variable pack int i1 = 15; Dptr dp(new double()); auto agw = make_tuple( &i1, dp, 35 ); i1 = 30; *dp = 345.0; ar0 << Record(agw, "varpack", "top"); const unsigned long len0 = ar0.dataSize(); i1 = 13; *dp = 678.0; std::get<2>(agw) = 64; ar0 << Record(agw, "varpack", "top"); const unsigned long len1 = ar0.dataSize(); // Figure out what kind of record size we are expecting for the // second write operation. The first thing is the class id of // the pack itself. const ClassId& agwid = ClassId::itemId(agw); unsigned idlen = agwid.id().size() + sizeof(unsigned long); // We have a bare int pointer in the pack. The I/O code will switch // to writing out the class id for that pointer. idlen += ClassId::makeId().id().size() + sizeof(unsigned long); // We have a shared double pointer in the pack. The I/O code will // switch to writing out the class id for that pointer. idlen += ClassId::makeId().id().size() + sizeof(unsigned long); // Of course, we also need to take into account the size of // the data itself unsigned long datasize = sizeof(int) + sizeof(double) + sizeof(int); // Make sure the above arguments are correct CHECK_EQUAL(datasize + idlen, len1-len0); // Make a variable pack with IOPtr objects. For them, the I/O // code will not switch to writing out the class ids. long lv = 10; float fv = 5.f; double dv = 1.0; auto pack = make_VarPack( io_ptr(lv), io_ptr(fv), io_ptr(dv) ); ar0 << Record(pack, "pack", "top"); const unsigned long lena = ar0.dataSize(); lv = 11; fv = 6.f; dv = 2.0; ar0 << Record(pack, "pack", "top"); const unsigned long lenb = ar0.dataSize(); const ClassId& packid = ClassId::itemId(pack); idlen = packid.id().size() + sizeof(unsigned long); datasize = sizeof(long) + sizeof(float) + sizeof(double); CHECK_EQUAL(datasize + idlen, lenb - lena); // Make sure we can read varpacks back int ival; Dptr pd(new double()); Dptr pk = pd; auto rag = make_VarPack( &ival, pk, 12 ); Reference ref(ar0, "varpack", "top"); CHECK(ref.size() == 2); ref.restore(0, &rag); CHECK(ival == 30); CHECK(*std::get<1>(rag) == 345.0); CHECK(std::get<2>(rag) == 35); ref.restore(1, &rag); CHECK(ival == 13); CHECK(*std::get<1>(rag) == 678.0); CHECK(std::get<2>(rag) == 64); Reference pref(ar0, "pack", "top"); CHECK(pref.size() == 2); pref.restore(0, &pack); CHECK(lv == 10); CHECK(fv == 5.f); CHECK(dv == 1.0); pref.restore(1, &pack); CHECK(lv == 11); CHECK(fv == 6.f); CHECK(dv == 2.0); } } #else // CPP11_STD_AVAILABLE namespace { TEST(VarPack) { } } #endif // CPP11_STD_AVAILABLE