133 cfg.
pathname =
"data/kv_container_all_types";
141 std::cout <<
"[case] int8 -> int8\n";
148 std::cout <<
"[case] int8 -> int64\n";
155 std::cout <<
"[case] int32 -> string\n";
162 std::cout <<
"[case] string -> string\n";
166 ASSERT_FOUND(kv, std::string(
"key"), std::string(
"value"));
169 std::cout <<
"[case] string -> POD(SimpleStruct)\n";
177 std::cout <<
"[case] string -> set<int>\n";
180 std::set<int> s{1, 2, 3};
185#if __cplusplus >= 201703L
186 std::cout <<
"[case] int64 -> vector<uint8_t>\n";
189 std::vector<uint8_t> data{1, 2, 3, 4};
194 std::cout <<
"[case] string -> vector<SimpleStruct>\n";
197 std::vector<SimpleStruct> vec{{1, 1.0f}, {2, 2.0f}};
202 std::cout <<
"[case] string -> list<string>\n";
205 std::list<std::string> lst{
"a",
"b",
"c"};
210 std::cout <<
"[case] string -> vector<string>\n";
213 std::vector<std::string> lst{
"a",
"b",
"c"};
218 std::cout <<
"[case] string -> set<string>\n";
221 std::set<std::string> s{
"a",
"b",
"c"};
227 std::cout <<
"[case] string -> self-serializable struct\n";
229 struct Serializable {
234 Serializable(
int a_,
const std::string& b_) : a(a_), b(b_) {}
236 std::vector<uint8_t> to_bytes()
const {
237 std::vector<uint8_t> result(
sizeof(
int) + b.size());
238 std::memcpy(result.data(), &a,
sizeof(
int));
239 std::memcpy(result.data() +
sizeof(
int), b.data(), b.size());
242 static Serializable from_bytes(
const void* data,
size_t size) {
243 if (size <
sizeof(
int))
244 throw std::runtime_error(
"Invalid data size for Serializable");
245 const uint8_t* ptr =
static_cast<const uint8_t*
>(data);
247 std::memcpy(&s.a, ptr,
sizeof(
int));
248 s.b = std::string(
reinterpret_cast<const char*
>(ptr +
sizeof(
int)), size -
sizeof(
int));
251 bool operator==(
const Serializable& other)
const {
252 return a == other.a && b == other.b;
257 Serializable s{7,
"seven"};
263 std::cout <<
"[case] std::bitset<32> -> int\n";
265 using Bits = std::bitset<32>;
267 Bits key(std::string(
"10101010101010101010101010101010"));
273 std::cout <<
"[concurrency] start\n";
278 std::condition_variable cv;
279 std::size_t epoch = 0;
280 std::size_t last_seen = 0;
281 std::atomic<bool> failed(
false);
282 std::atomic<bool> done(
false);
284 std::exception_ptr w_ex, r_ex;
288 for (
int i = 0; i < 1000; ++i) {
292 std::lock_guard<std::mutex> lock(mtx);
298 std::this_thread::sleep_for(std::chrono::milliseconds(1));
300 done.store(
true, std::memory_order_release);
303 }
catch (
const std::exception& ex) {
304 sync_cerr() <<
"[error] writer: " << ex.what() <<
"\n";
306 done.store(
true, std::memory_order_release);
309 sync_cerr() <<
"[error] writer: unknown\n";
311 done.store(
true, std::memory_order_release);
319 std::unique_lock<std::mutex> lock(mtx);
320 bool ok = cv.wait_for(lock, std::chrono::seconds(2), [&] {
321 return epoch > last_seen || done.load(std::memory_order_acquire);
324 sync_cerr() <<
"[error] reader timeout (epoch=" << epoch
325 <<
", last_seen=" << last_seen <<
")\n";
329 if (done.load(std::memory_order_acquire) && epoch == last_seen) {
336# if __cplusplus >= 201703L
337 auto val = kv.
find(1);
338 if (!val || *val != expected) {
340 << (val ? val->value : -1)
341 <<
", expected " << expected.
value <<
"\n";
347 if (!val.first || val.second != expected) {
350 <<
", expected " << expected.
value <<
"\n";
357 }
catch (
const std::exception& ex) {
358 sync_cerr() <<
"[error] reader: " << ex.what() <<
"\n";
361 sync_cerr() <<
"[error] reader: unknown\n";
370 try { std::rethrow_exception(w_ex); }
371 catch (
const std::exception& e) {
sync_cerr() <<
"[error] writer rethrow: " << e.what() <<
"\n"; }
372 catch (...) {
sync_cerr() <<
"[error] writer rethrow: unknown\n"; }
375 try { std::rethrow_exception(r_ex); }
376 catch (
const std::exception& e) {
sync_cerr() <<
"[error] reader rethrow: " << e.what() <<
"\n"; }
377 catch (...) {
sync_cerr() <<
"[error] reader rethrow: unknown\n"; }
381 sync_cerr() <<
"[concurrency] failed: thread exception\n";
385 std::cerr <<
"[concurrency] failed\n";
389 std::cout <<
"[concurrency] ok\n";
392 std::cout <<
"[result] all tests passed\n";