update readme
[c11concurrency-benchmarks.git] / silo / test.cc
1 #include <iostream>
2 #include <functional>
3 #include <unordered_map>
4 #include <tuple>
5 #include <set>
6 #include <unistd.h>
7
8 #include "circbuf.h"
9 #include "pxqueue.h"
10 #include "core.h"
11 #include "thread.h"
12 #include "txn.h"
13 #include "txn_btree.h"
14 #include "varint.h"
15 #include "small_vector.h"
16 #include "static_vector.h"
17 #include "small_unordered_map.h"
18 #include "static_unordered_map.h"
19 #include "counter.h"
20 #include "record/encoder.h"
21 #include "record/inline_str.h"
22 #include "record/cursor.h"
23
24 #ifdef PROTO2_CAN_DISABLE_GC
25 #include "txn_proto2_impl.h"
26 #endif
27
28 #define MYREC_KEY_FIELDS(x, y) \
29   x(int32_t,k0) \
30   y(int32_t,k1)
31 #define MYREC_VALUE_FIELDS(x, y) \
32   x(int32_t,v0) \
33   y(int16_t,v1)
34 DO_STRUCT(myrec, MYREC_KEY_FIELDS, MYREC_VALUE_FIELDS)
35
36 #define CURSORREC_KEY_FIELDS(x, y) \
37   x(int32_t,k0) \
38   y(int32_t,k1)
39 #define CURSORREC_VALUE_FIELDS(x, y) \
40   x(int32_t,v0) \
41   y(int16_t,v1) \
42   y(int32_t,v2) \
43   y(inline_str_8<25>,v3) \
44   y(inline_str_fixed<25>,v4) \
45   y(int32_t,v5) \
46   y(int8_t,v6)
47 DO_STRUCT(cursorrec, CURSORREC_KEY_FIELDS, CURSORREC_VALUE_FIELDS)
48
49 using namespace std;
50 using namespace util;
51
52 static event_counter evt_test("test");
53 static event_counter evt_test1("test1");
54 static event_avg_counter evt_test_avg("test_avg");
55
56 namespace varkeytest {
57   void
58   Test()
59   {
60     const string s0 = u64_varkey(1).str();
61     ALWAYS_ASSERT(s0.size() == 8);
62     const char e0[] = { 0, 0, 0, 0, 0, 0, 0, 1 };
63     ALWAYS_ASSERT(memcmp(s0.data(), &e0[0], 8) == 0);
64     cout << "varkey test passed" << endl;
65   }
66 }
67
68 namespace pxqueuetest {
69
70   static inline void *
71   N2P(uint64_t n)
72   {
73     return (void *) n;
74   }
75
76   static inline rcu::deleter_t
77   N2D(uint64_t n)
78   {
79     return (rcu::deleter_t) n;
80   }
81
82   struct sorter {
83     bool
84     operator()(const rcu::delete_entry &a,
85                const rcu::delete_entry &b) const
86     {
87       return (a.ptr < b.ptr) || (a.ptr == b.ptr && a.action < b.action);
88     }
89   };
90
91   void
92   Test()
93   {
94     typedef basic_px_queue<rcu::delete_entry, 8> px_queue;
95
96     {
97       px_queue q0;
98       for (size_t i = 0; i < 14; i++)
99         q0.enqueue(rcu::delete_entry(N2P(i), N2D(i)), 1);
100       ALWAYS_ASSERT(!q0.empty());
101       q0.sanity_check();
102
103       uint64_t i = 0;
104       for (auto &p : q0) {
105         ALWAYS_ASSERT(p.ptr == N2P(i));
106         ALWAYS_ASSERT((rcu::deleter_t) p.action == N2D(i));
107         i++;
108       }
109       ALWAYS_ASSERT(i == 14);
110
111       px_queue q1;
112       q1.enqueue(rcu::delete_entry(N2P(123), N2D(543)), 1);
113       q1.enqueue(rcu::delete_entry(N2P(12345), N2D(54321)), 1);
114       q1.sanity_check();
115       auto q1_it = q1.begin();
116       ALWAYS_ASSERT(q1_it != q1.end());
117       ALWAYS_ASSERT(q1_it->ptr == N2P(123));
118       ALWAYS_ASSERT((rcu::deleter_t) q1_it->action == N2D(543));
119       ++q1_it;
120       ALWAYS_ASSERT(q1_it != q1.end());
121       ALWAYS_ASSERT(q1_it->ptr == N2P(12345));
122       ALWAYS_ASSERT((rcu::deleter_t) q1_it->action == N2D(54321));
123       ++q1_it;
124       ALWAYS_ASSERT(q1_it == q1.end());
125     }
126
127     {
128       px_queue q0, q1;
129       q1.enqueue(rcu::delete_entry(N2P(1), N2D(1)), 1);
130       q1.enqueue(rcu::delete_entry(N2P(2), N2D(2)), 2);
131
132       q0.sanity_check();
133       q1.sanity_check();
134
135       q0.empty_accept_from(q1, 1);
136       ALWAYS_ASSERT(q0.get_ngroups() == 1);
137       ALWAYS_ASSERT(q1.get_ngroups() == 1);
138
139       vector<rcu::delete_entry> v0(q0.begin(), q0.end());
140       vector<rcu::delete_entry> v0test = {{N2P(1), N2D(1)}};
141
142       vector<rcu::delete_entry> v1(q1.begin(), q1.end());
143       vector<rcu::delete_entry> v1test = {{N2P(2), N2D(2)}};
144
145       sort(v0.begin(), v0.end(), sorter());
146       sort(v0test.begin(), v0test.end(), sorter());
147       sort(v1.begin(), v1.end(), sorter());
148       sort(v1test.begin(), v1test.end(), sorter());
149
150       ALWAYS_ASSERT(v0 == v0test);
151       ALWAYS_ASSERT(v1 == v1test);
152
153       q0.clear();
154       ALWAYS_ASSERT(q0.empty());
155       q0.sanity_check();
156
157       q1.clear();
158       ALWAYS_ASSERT(q1.empty());
159       q1.sanity_check();
160     }
161
162     {
163       px_queue q0, q1;
164       q0.enqueue(rcu::delete_entry(N2P(1), N2D(1)), 1);
165       q0.enqueue(rcu::delete_entry(N2P(3), N2D(3)), 1);
166
167       q1.enqueue(rcu::delete_entry(N2P(2), N2D(2)), 1);
168       q1.enqueue(rcu::delete_entry(N2P(4), N2D(4)), 1);
169       q1.enqueue(rcu::delete_entry(N2P(6), N2D(6)), 2);
170
171       q0.sanity_check();
172       q1.sanity_check();
173
174       q0.transfer_freelist(q1);
175       q0.sanity_check();
176       q1.sanity_check();
177
178       q1.transfer_freelist(q0);
179       q0.sanity_check();
180       q1.sanity_check();
181
182       q0.clear();
183       ALWAYS_ASSERT(q0.empty());
184       q1.clear();
185       ALWAYS_ASSERT(q1.empty());
186       q0.sanity_check();
187       q1.sanity_check();
188     }
189
190     cout << "pxqueue test passed" << endl;
191   }
192 }
193
194 void
195 CircbufTest()
196 {
197   // test circbuf
198   int values[] = {0, 1, 2, 3, 4};
199   circbuf<int, ARRAY_NELEMS(values)> b;
200   ALWAYS_ASSERT(b.empty());
201   for (size_t i = 0; i < ARRAY_NELEMS(values); i++) {
202     b.enq(&values[i]);
203   }
204   vector<int *> pxs;
205   b.peekall(pxs);
206   ALWAYS_ASSERT(pxs.size() == ARRAY_NELEMS(values));
207   ALWAYS_ASSERT(set<int *>(pxs.begin(), pxs.end()).size() == pxs.size());
208   for (size_t i = 0; i < ARRAY_NELEMS(values); i++)
209     ALWAYS_ASSERT(pxs[i] == &values[i]);
210   for (size_t i = 0; i < ARRAY_NELEMS(values); i++) {
211     ALWAYS_ASSERT(!b.empty());
212     ALWAYS_ASSERT(b.peek() == &values[i]);
213     ALWAYS_ASSERT(*b.peek() == values[i]);
214     ALWAYS_ASSERT(b.deq() == &values[i]);
215   }
216   ALWAYS_ASSERT(b.empty());
217
218   b.enq(&values[0]);
219   b.enq(&values[1]);
220   b.enq(&values[2]);
221   b.peekall(pxs);
222   auto testlist = vector<int *>({&values[0], &values[1], &values[2]});
223   ALWAYS_ASSERT(pxs == testlist);
224
225   ALWAYS_ASSERT(b.deq() == &values[0]);
226   ALWAYS_ASSERT(b.deq() == &values[1]);
227   ALWAYS_ASSERT(b.deq() == &values[2]);
228
229   cout << "circbuf test passed" << endl;
230 }
231
232 void
233 CounterTest()
234 {
235 #ifdef ENABLE_EVENT_COUNTERS
236   ++evt_test;
237   ++evt_test;
238   evt_test_avg.offer(1);
239   evt_test_avg.offer(2);
240   evt_test_avg.offer(3);
241   map<string, counter_data> m = event_counter::get_all_counters();
242   ALWAYS_ASSERT(m.find("test") != m.end());
243   ALWAYS_ASSERT(m.find("test1") != m.end());
244   ALWAYS_ASSERT(m.find("test_avg") != m.end());
245
246   ALWAYS_ASSERT(m["test"].count_ == 2);
247   ALWAYS_ASSERT(m["test1"].count_ == 0);
248   ALWAYS_ASSERT(m["test_avg"].count_ == 3);
249   ALWAYS_ASSERT(m["test_avg"].sum_ == 6);
250   ALWAYS_ASSERT(m["test_avg"].max_ == 3);
251
252   cout << "event counters test passed" << endl;
253 #endif
254 }
255
256 void
257 UtilTest()
258 {
259   static_assert(CACHELINE_SIZE == 64, "xx");
260   static_assert(LG_CACHELINE_SIZE == 6, "xx");
261
262   const bool e0 = round_up<size_t, 1>(3) == 4;
263   ALWAYS_ASSERT(e0);
264   const bool e1 = round_down<size_t, 1>(3) == 2;
265   ALWAYS_ASSERT(e1);
266   const bool e2 = round_up<size_t, 1>(2) == 2;
267   ALWAYS_ASSERT(e2);
268   const bool e3 = round_down<size_t, 1>(2) == 2;
269   ALWAYS_ASSERT(e3);
270   const bool e4 = round_down<size_t, LG_CACHELINE_SIZE>(2) == 0;
271   ALWAYS_ASSERT(e4);
272   const bool e5 = round_down<size_t, LG_CACHELINE_SIZE>(CACHELINE_SIZE) == CACHELINE_SIZE;
273   ALWAYS_ASSERT(e5);
274   const bool e6 = round_down<size_t, LG_CACHELINE_SIZE>(CACHELINE_SIZE + 10) == CACHELINE_SIZE;
275   ALWAYS_ASSERT(e6);
276
277   cout << "util test passed" << endl;
278 }
279
280 namespace small_vector_ns {
281
282 typedef small_vector<string, 4> vec_type;
283 typedef static_vector<string, 4> static_vec_type;
284 typedef vector<string> stl_vec_type;
285
286 template <typename VecType>
287 static void
288 init_vec0(VecType &v)
289 {
290   ALWAYS_ASSERT(v.empty());
291   ALWAYS_ASSERT(v.size() == 0);
292
293   v.push_back("a");
294   ALWAYS_ASSERT(!v.empty());
295   ALWAYS_ASSERT(v.size() == 1);
296   ALWAYS_ASSERT(v.front() == "a");
297   ALWAYS_ASSERT(v.back() == "a");
298
299   v.push_back("b");
300   ALWAYS_ASSERT(v.size() == 2);
301   ALWAYS_ASSERT(v.front() == "a");
302   ALWAYS_ASSERT(v.back() == "b");
303
304   v.push_back("c");
305   ALWAYS_ASSERT(v.size() == 3);
306   ALWAYS_ASSERT(v.front() == "a");
307   ALWAYS_ASSERT(v.back() == "c");
308
309   v.push_back("d");
310   ALWAYS_ASSERT(v.size() == 4);
311   ALWAYS_ASSERT(v.front() == "a");
312   ALWAYS_ASSERT(v.back() == "d");
313 }
314
315 template <typename VecType>
316 static void
317 init_vec1(VecType &v)
318 {
319   ALWAYS_ASSERT(v.empty());
320   ALWAYS_ASSERT(v.size() == 0);
321
322   v.push_back("a");
323   ALWAYS_ASSERT(!v.empty());
324   ALWAYS_ASSERT(v.size() == 1);
325   ALWAYS_ASSERT(v.front() == "a");
326   ALWAYS_ASSERT(v.back() == "a");
327
328   v.push_back("b");
329   ALWAYS_ASSERT(v.size() == 2);
330   ALWAYS_ASSERT(v.front() == "a");
331   ALWAYS_ASSERT(v.back() == "b");
332
333   v.push_back("c");
334   ALWAYS_ASSERT(v.size() == 3);
335   ALWAYS_ASSERT(v.front() == "a");
336   ALWAYS_ASSERT(v.back() == "c");
337
338   v.push_back("d");
339   ALWAYS_ASSERT(v.size() == 4);
340   ALWAYS_ASSERT(v.front() == "a");
341   ALWAYS_ASSERT(v.back() == "d");
342
343   v.push_back("e");
344   ALWAYS_ASSERT(v.size() == 5);
345   ALWAYS_ASSERT(v.front() == "a");
346   ALWAYS_ASSERT(v.back() == "e");
347
348   v.push_back("f");
349   ALWAYS_ASSERT(v.size() == 6);
350   ALWAYS_ASSERT(v.front() == "a");
351   ALWAYS_ASSERT(v.back() == "f");
352 }
353
354 template <typename VecA, typename VecB>
355 static void
356 assert_vecs_equal(VecA &v, const VecB &stl_v)
357 {
358   ALWAYS_ASSERT(v.size() == stl_v.size());
359   VecB tmp(v.begin(), v.end());
360   ALWAYS_ASSERT(tmp == stl_v);
361   const VecA &cv = v;
362   VecB tmp1(cv.begin(), cv.end());
363   ALWAYS_ASSERT(tmp1 == stl_v);
364 }
365
366 struct foo {
367   int a;
368   int b;
369   int c;
370   int d;
371
372   foo()
373     : a(), b(), c(), d()
374   {}
375
376   foo(int a, int b, int c, int d)
377     : a(a), b(b), c(c), d(d)
378   {}
379 };
380
381 struct PComp {
382   inline bool
383   operator()(const pair<uint32_t, uint32_t> &a,
384              const pair<uint32_t, uint32_t> &b) const
385   {
386     return a.first < b.first;
387   }
388 };
389
390 void
391 Test()
392 {
393   {
394     vec_type v;
395     static_vec_type static_v;
396     stl_vec_type stl_v;
397     init_vec0(v);
398     init_vec0(static_v);
399     init_vec0(stl_v);
400
401     vec_type v_copy(v);
402     vec_type v_assign;
403     ALWAYS_ASSERT(v_assign.empty());
404     v_assign = v;
405
406     static_vec_type static_v_copy(static_v);
407     static_vec_type static_v_assign;
408     ALWAYS_ASSERT(static_v_assign.empty());
409     static_v_assign = static_v;
410
411     assert_vecs_equal(v, stl_v);
412     assert_vecs_equal(v_copy, stl_v);
413     assert_vecs_equal(v_assign, stl_v);
414
415     assert_vecs_equal(static_v, stl_v);
416     assert_vecs_equal(static_v_copy, stl_v);
417     assert_vecs_equal(static_v_assign, stl_v);
418
419     v.clear();
420     assert_vecs_equal(v, stl_vec_type());
421
422     static_v.clear();
423     assert_vecs_equal(static_v, stl_vec_type());
424   }
425
426   {
427     vec_type v;
428     stl_vec_type stl_v;
429     init_vec1(v);
430     init_vec1(stl_v);
431     vec_type v_copy(v);
432     vec_type v_assign;
433     ALWAYS_ASSERT(v_assign.empty());
434     v_assign = v;
435     assert_vecs_equal(v, stl_v);
436     assert_vecs_equal(v_copy, stl_v);
437     assert_vecs_equal(v_assign, stl_v);
438     v.clear();
439     assert_vecs_equal(v, stl_vec_type());
440   }
441
442   {
443     for (int iter = 0; iter < 10; iter++) {
444       small_vector<foo> v;
445       for (int i = 0; i < 20; i++) {
446         v.push_back(foo(i, i + 1, i + 2, i + 3));
447         ALWAYS_ASSERT(v.back().a == i);
448         ALWAYS_ASSERT(v.back().b == (i + 1));
449         ALWAYS_ASSERT(v.back().c == (i + 2));
450         ALWAYS_ASSERT(v.back().d == (i + 3));
451         ALWAYS_ASSERT(v[i].a == i);
452         ALWAYS_ASSERT(v[i].b == (i + 1));
453         ALWAYS_ASSERT(v[i].c == (i + 2));
454         ALWAYS_ASSERT(v[i].d == (i + 3));
455       }
456       for (int i = 0; i < 20; i++) {
457         ALWAYS_ASSERT(v[i].a == i);
458         ALWAYS_ASSERT(v[i].b == (i + 1));
459         ALWAYS_ASSERT(v[i].c == (i + 2));
460         ALWAYS_ASSERT(v[i].d == (i + 3));
461       }
462     }
463   }
464
465   {
466     small_vector<int> v;
467     v.push_back(10);
468     v.push_back(2);
469     v.push_back(5);
470     v.push_back(7);
471     v.push_back(3);
472     v.push_back(100);
473     sort(v.begin(), v.end());
474
475     small_vector<int> v1;
476     v1.push_back(10);
477     v1.push_back(2);
478     v1.push_back(5);
479     v1.push_back(7);
480     v1.push_back(3);
481     v1.push_back(100);
482     v1.sort();
483
484     vector<int> stl_v;
485     stl_v.push_back(10);
486     stl_v.push_back(2);
487     stl_v.push_back(5);
488     stl_v.push_back(7);
489     stl_v.push_back(3);
490     stl_v.push_back(100);
491     sort(stl_v.begin(), stl_v.end());
492
493     assert_vecs_equal(v, stl_v);
494     assert_vecs_equal(v1, stl_v);
495   }
496
497   {
498     small_vector<int, 3> v;
499     v.push_back(10);
500     v.push_back(2);
501     v.push_back(5);
502     v.push_back(7);
503     v.push_back(3);
504     v.push_back(100);
505     sort(v.begin(), v.end());
506
507     small_vector<int, 3> v1;
508     v1.push_back(10);
509     v1.push_back(2);
510     v1.push_back(5);
511     v1.push_back(7);
512     v1.push_back(3);
513     v1.push_back(100);
514     v1.sort();
515
516     vector<int> stl_v;
517     stl_v.push_back(10);
518     stl_v.push_back(2);
519     stl_v.push_back(5);
520     stl_v.push_back(7);
521     stl_v.push_back(3);
522     stl_v.push_back(100);
523     sort(stl_v.begin(), stl_v.end());
524
525     assert_vecs_equal(v, stl_v);
526     assert_vecs_equal(v1, stl_v);
527   }
528
529   {
530     fast_random r(29395);
531     small_vector< pair<uint32_t, uint32_t> > v;
532     vector< pair<uint32_t, uint32_t> > stl_v;
533     for (size_t i = 0; i < 48; i++) {
534       uint32_t x = r.next();
535       v.push_back(make_pair(x, x + 1));
536       stl_v.push_back(make_pair(x, x + 1));
537     }
538     sort(v.begin(), v.end(), PComp());
539     sort(stl_v.begin(), stl_v.end(), PComp());
540     assert_vecs_equal(v, stl_v);
541     for (size_t i = 0; i < 48; i++)
542       ALWAYS_ASSERT(v[i].first + 1 == v[i].second);
543   }
544
545   {
546     // test C++11 features
547     small_vector<string, 4> v;
548     v.emplace_back("hello");
549     string world = "world";
550     v.push_back(move(world));
551     //ALWAYS_ASSERT(world.empty());
552     ALWAYS_ASSERT(v.size() == 2);
553     ALWAYS_ASSERT(v[0] == "hello");
554     ALWAYS_ASSERT(v[1] == "world");
555   }
556
557   {
558     // reverse iterators
559     vec_type v0;
560     v0.emplace_back("a");
561     v0.emplace_back("b");
562     v0.emplace_back("c");
563     v0.emplace_back("d");
564
565     stl_vec_type sv0;
566     sv0.emplace_back("a");
567     sv0.emplace_back("b");
568     sv0.emplace_back("c");
569     sv0.emplace_back("d");
570
571     stl_vec_type test(v0.rbegin(), v0.rend());
572     stl_vec_type svtest(sv0.rbegin(), sv0.rend());
573     ALWAYS_ASSERT(test == svtest);
574
575     v0.emplace_back("e");
576     sv0.emplace_back("e");
577
578     stl_vec_type test1(v0.rbegin(), v0.rend());
579     stl_vec_type svtest1(sv0.rbegin(), sv0.rend());
580     ALWAYS_ASSERT(test1 == svtest1);
581   }
582
583   cout << "vec test passed" << endl;
584 }
585
586 }
587
588 namespace small_map_ns {
589
590 typedef small_unordered_map<string, string, 4> map_type;
591 typedef static_unordered_map<string, string, 4> static_map_type;
592 typedef map<string, string> stl_map_type;
593
594 template <typename MapType>
595 static void
596 assert_map_contains(MapType &m, const string &k, const string &v)
597 {
598   ALWAYS_ASSERT(!m.empty());
599   ALWAYS_ASSERT(m[k] == v);
600   {
601     typename MapType::iterator it = m.find(k);
602     ALWAYS_ASSERT(it != m.end());
603     ALWAYS_ASSERT(it->first == k);
604     ALWAYS_ASSERT(it->second == v);
605   }
606   const MapType &const_m = m;
607   {
608     typename MapType::const_iterator it = const_m.find(k);
609     ALWAYS_ASSERT(it != const_m.end());
610     ALWAYS_ASSERT(it->first == k);
611     ALWAYS_ASSERT(it->second == v);
612   }
613 }
614
615 template <typename MapType>
616 static void
617 assert_map_equals(MapType &m, const stl_map_type &stl_m)
618 {
619   ALWAYS_ASSERT(m.size() == stl_m.size());
620
621   // reg version prefix
622   {
623     stl_map_type test;
624     for (typename MapType::iterator it = m.begin();
625          it != m.end(); ++it) {
626       ALWAYS_ASSERT(test.find(it->first) == test.end());
627       test[it->first] = it->second;
628     }
629     ALWAYS_ASSERT(test == stl_m);
630   }
631
632   // reg version postfix
633   {
634     stl_map_type test;
635     for (typename MapType::iterator it = m.begin();
636          it != m.end(); it++) {
637       ALWAYS_ASSERT(test.find(it->first) == test.end());
638       test[it->first] = it->second;
639     }
640     ALWAYS_ASSERT(test == stl_m);
641   }
642
643   // const version prefix
644   {
645     const MapType &const_m = m;
646     stl_map_type test;
647     for (typename MapType::const_iterator it = const_m.begin();
648          it != const_m.end(); ++it) {
649       ALWAYS_ASSERT(test.find(it->first) == test.end());
650       test[it->first] = it->second;
651     }
652     ALWAYS_ASSERT(test == stl_m);
653   }
654
655   // const version postfix
656   {
657     const MapType &const_m = m;
658     stl_map_type test;
659     for (typename MapType::const_iterator it = const_m.begin();
660          it != const_m.end(); it++) {
661       ALWAYS_ASSERT(test.find(it->first) == test.end());
662       test[it->first] = it->second;
663     }
664     ALWAYS_ASSERT(test == stl_m);
665   }
666 }
667
668 template <typename T>
669 static void
670 init_map(T& m)
671 {
672   m["a"] = "1";
673   m["b"] = "2";
674   m["c"] = "3";
675   m["d"] = "4";
676 }
677
678 template <typename T>
679 static void
680 init_map1(T& m)
681 {
682   m["a"] = "1";
683   m["b"] = "2";
684   m["c"] = "3";
685   m["d"] = "4";
686   m["e"] = "5";
687   m["f"] = "6";
688 }
689
690 void
691 Test()
692 {
693   {
694     map_type m, m_copy;
695     static_map_type static_m, static_m_copy;
696     stl_map_type stl_m;
697
698     init_map(m);
699     init_map(static_m);
700
701     ALWAYS_ASSERT(m.is_small_type());
702     ALWAYS_ASSERT(static_m.is_small_type());
703     INVARIANT(m.size() == 4);
704     INVARIANT(static_m.size() == 4);
705
706     init_map(stl_m);
707
708     ALWAYS_ASSERT(m_copy.is_small_type());
709     m_copy = m;
710     ALWAYS_ASSERT(m_copy.is_small_type());
711     INVARIANT(m_copy.size() == 4);
712
713     static_m_copy = static_m;
714     INVARIANT(static_m_copy.size() == 4);
715
716     map_type m_construct(m);
717     INVARIANT(m_construct.size() == 4);
718     for (stl_map_type::iterator it = stl_m.begin();
719          it != stl_m.end(); ++it) {
720       assert_map_contains(m, it->first, it->second);
721       assert_map_contains(m_copy, it->first, it->second);
722       assert_map_contains(m_construct, it->first, it->second);
723     }
724     assert_map_equals(m, stl_m);
725     assert_map_equals(m_copy, stl_m);
726     assert_map_equals(m_construct, stl_m);
727     ALWAYS_ASSERT(m.is_small_type());
728     ALWAYS_ASSERT(m_copy.is_small_type());
729     ALWAYS_ASSERT(m_construct.is_small_type());
730
731     static_map_type static_m_construct(static_m);
732     INVARIANT(static_m_construct.size() == 4);
733     for (stl_map_type::iterator it = stl_m.begin();
734          it != stl_m.end(); ++it) {
735       assert_map_contains(static_m, it->first, it->second);
736       assert_map_contains(static_m_copy, it->first, it->second);
737       assert_map_contains(static_m_construct, it->first, it->second);
738     }
739     assert_map_equals(static_m, stl_m);
740     assert_map_equals(static_m_copy, stl_m);
741     assert_map_equals(static_m_construct, stl_m);
742     ALWAYS_ASSERT(static_m.is_small_type());
743     ALWAYS_ASSERT(static_m_copy.is_small_type());
744     ALWAYS_ASSERT(static_m_construct.is_small_type());
745   }
746
747   {
748     map_type m, m_copy;
749     stl_map_type stl_m;
750     init_map1(m);
751     init_map1(stl_m);
752     m_copy = m;
753     map_type m_construct(m);
754     for (stl_map_type::iterator it = stl_m.begin();
755          it != stl_m.end(); ++it) {
756       assert_map_contains(m, it->first, it->second);
757       assert_map_contains(m_copy, it->first, it->second);
758     }
759     assert_map_equals(m, stl_m);
760     assert_map_equals(m_copy, stl_m);
761     assert_map_equals(m_construct, stl_m);
762   }
763
764   {
765     map_type m;
766     ALWAYS_ASSERT(m.empty());
767     ALWAYS_ASSERT(m.size() == 0);
768     m["a"] = "1";
769     ALWAYS_ASSERT(!m.empty());
770     ALWAYS_ASSERT(m.size() == 1);
771     m["b"] = "2";
772     ALWAYS_ASSERT(!m.empty());
773     ALWAYS_ASSERT(m.size() == 2);
774     m["b"] = "2";
775     ALWAYS_ASSERT(!m.empty());
776     ALWAYS_ASSERT(m.size() == 2);
777     m["c"] = "3";
778     ALWAYS_ASSERT(!m.empty());
779     ALWAYS_ASSERT(m.size() == 3);
780     m["d"] = "4";
781     ALWAYS_ASSERT(!m.empty());
782     ALWAYS_ASSERT(m.size() == 4);
783
784     m.clear();
785     ALWAYS_ASSERT(m.empty());
786     ALWAYS_ASSERT(m.size() == 0);
787     m["a"] = "1";
788     m["b"] = "2";
789     m["c"] = "3";
790     m["d"] = "4";
791     m["d"] = "4";
792     m["d"] = "4";
793     m["e"] = "5";
794     ALWAYS_ASSERT(!m.empty());
795     ALWAYS_ASSERT(m.size() == 5);
796   }
797
798   { // check primitive key type maps
799     small_unordered_map<int, int> m;
800     m[0] = 1;
801     m[1] = 2;
802     m[2] = 3;
803     ALWAYS_ASSERT(m.find(0) != m.end());
804     ALWAYS_ASSERT(m.find(1) != m.end());
805     ALWAYS_ASSERT(m.find(2) != m.end());
806     ALWAYS_ASSERT(m.find(0)->first == 0 && m.find(0)->second == 1);
807     ALWAYS_ASSERT(m.find(1)->first == 1 && m.find(1)->second == 2);
808     ALWAYS_ASSERT(m.find(2)->first == 2 && m.find(2)->second == 3);
809   }
810
811   cout << "map test passed" << endl;
812 }
813 }
814
815 namespace recordtest {
816
817 ostream &
818 operator<<(ostream &o, const myrec::key &k)
819 {
820   o << "[k0=" << k.k0 << ", k1=" << k.k1 << "]" << endl;
821   return o;
822 }
823
824 ostream &
825 operator<<(ostream &o, const myrec::value &v)
826 {
827   o << "[v0=" << v.v0 << ", v1=" << v.v1 << "]" << endl;
828   return o;
829 }
830
831 void
832 TestCursor()
833 {
834   const cursorrec::value v(12345, 1, 54321, "foo", "bar", 98765, 2);
835   const string enc_v = Encode(v);
836   cursorrec::value v0;
837   read_record_cursor<cursorrec> rc((const uint8_t *) enc_v.data(), enc_v.size());
838   for (size_t i = rc.field();
839        i < cursorrec::value_descriptor::nfields();
840        i = rc.field())
841     rc.read_current_and_advance(&v0);
842   ALWAYS_ASSERT(v == v0);
843
844   // mutate v2 => 98765432, v4 => "asdfasdfasdf"
845   v0.v2 = 98765432;
846   v0.v4.assign("asdfasdfasdf");
847
848   rc.reset();
849   rc.skip_to(2);
850   const size_t v2_oldsz = rc.read_current_raw_size_and_advance();
851   rc.skip_to(4);
852   const size_t v4_oldsz = rc.read_current_raw_size_and_advance();
853
854   typedef serializer<int32_t, true> si32;
855   typedef serializer<inline_str_fixed<25>, true> sistr25;
856   ALWAYS_ASSERT(si32::nbytes(&v.v2) == v2_oldsz);
857   ALWAYS_ASSERT(sistr25::nbytes(&v.v4) == v4_oldsz);
858   ALWAYS_ASSERT(cursorrec::value_descriptor::nbytes_fn(2)((const uint8_t *) &v.v2) == v2_oldsz);
859   ALWAYS_ASSERT(cursorrec::value_descriptor::nbytes_fn(4)((const uint8_t *) &v.v4) == v4_oldsz);
860
861   const size_t v2_newsz =
862     cursorrec::value_descriptor::nbytes_fn(2)((const uint8_t *) &v0.v2);
863   const size_t v4_newsz =
864     cursorrec::value_descriptor::nbytes_fn(4)((const uint8_t *) &v0.v4);
865
866   uint8_t v2_oldraw_v[cursorrec::value_descriptor::max_nbytes(2)];
867   uint8_t v4_oldraw_v[cursorrec::value_descriptor::max_nbytes(4)];
868
869   string enc_v0 = enc_v;
870   if ((v2_oldsz + v4_oldsz) < (v2_newsz + v4_newsz))
871     // grow buffer
872     enc_v0.resize(enc_v0.size() + (v2_newsz + v4_newsz) - (v2_oldsz + v4_oldsz));
873   write_record_cursor<cursorrec> wc((uint8_t *) enc_v0.data());
874   wc.skip_to(2);
875   wc.write_current_and_advance(&v0, &v2_oldraw_v[0]);
876   wc.skip_to(4);
877   wc.write_current_and_advance(&v0, &v4_oldraw_v[0]);
878
879   read_record_cursor<cursorrec> rc1((const uint8_t *) enc_v0.data(), enc_v0.size());
880   cursorrec::value v2;
881   for (size_t i = rc1.field();
882        i < cursorrec::value_descriptor::nfields();
883        i = rc1.field())
884     rc1.read_current_and_advance(&v2);
885   ALWAYS_ASSERT(v2 == v0);
886   cerr << "v2: " << v2 << endl;
887   cerr << "v0: " << v2 << endl;
888 }
889
890 void
891 Test()
892 {
893   const myrec::key k0(123, 456);
894   const myrec::key k1(999, 123);
895   const myrec::key k2(123, 457);
896   myrec::key k0_temp, k1_temp, k2_temp;
897
898   ALWAYS_ASSERT(Size(k0) == sizeof(k0));
899   ALWAYS_ASSERT(Size(k1) == sizeof(k1));
900   ALWAYS_ASSERT(Size(k2) == sizeof(k2));
901
902   {
903     const string s0 = Encode(k0);
904     const string s1 = Encode(k1);
905     const string s2 = Encode(k2);
906     ALWAYS_ASSERT(s0 < s1);
907     ALWAYS_ASSERT(s0 < s2);
908     Decode(s0, k0_temp);
909     Decode(s1, k1_temp);
910     Decode(s2, k2_temp);
911     ALWAYS_ASSERT(k0 == k0_temp);
912     ALWAYS_ASSERT(k1 == k1_temp);
913     ALWAYS_ASSERT(k2 == k2_temp);
914
915     string t0, t1, t2;
916     const myrec::key *p0 = Decode(Encode(k0), k0_temp);
917     const myrec::key *p1 = Decode(Encode(k1), k1_temp);
918     const myrec::key *p2 = Decode(Encode(k2), k2_temp);
919     ALWAYS_ASSERT(*p0 == k0);
920     ALWAYS_ASSERT(*p1 == k1);
921     ALWAYS_ASSERT(*p2 == k2);
922   }
923
924   const myrec::value v0(859435, 2834);
925   const myrec::value v1(0, 73);
926   const myrec::value v2(654, 8);
927   myrec::value v0_temp, v1_temp, v2_temp;
928
929   {
930     const size_t sz0 = Size(v0);
931     const size_t sz1 = Size(v1);
932     const size_t sz2 = Size(v2);
933     uint8_t buf0[sz0], buf1[sz1], buf2[sz2];
934     Encode(buf0, v0);
935     Encode(buf1, v1);
936     Encode(buf2, v2);
937
938     const string s0((const char *) buf0, sz0);
939     const string s1((const char *) buf1, sz1);
940     const string s2((const char *) buf2, sz2);
941
942     Decode(s0, v0_temp);
943     Decode(s1, v1_temp);
944     Decode(s2, v2_temp);
945     ALWAYS_ASSERT(v0 == v0_temp);
946     ALWAYS_ASSERT(v1 == v1_temp);
947     ALWAYS_ASSERT(v2 == v2_temp);
948   }
949
950   TestCursor();
951
952   cout << "encoder test passed" << endl;
953 }
954
955 }
956
957 class main_thread : public ndb_thread {
958 public:
959   main_thread(int argc, char **argv)
960     : ndb_thread(false, string("main")),
961       argc(argc), argv(argv), ret(0)
962   {}
963
964   virtual void
965   run()
966   {
967 #ifndef CHECK_INVARIANTS
968     cerr << "WARNING: tests are running without invariant checking" << endl;
969 #endif
970     cerr << "PID: " << getpid() << endl;
971
972     CircbufTest();
973
974     // initialize the numa allocator subsystem with the number of CPUs running
975     // + reasonable size per core
976     ::allocator::Initialize(coreid::num_cpus_online(), size_t(128 * (1<<20)));
977 #ifdef PROTO2_CAN_DISABLE_GC
978     transaction_proto2_static::InitGC();
979 #endif
980     //varkeytest::Test();
981     //pxqueuetest::Test();
982     //CounterTest();
983     //UtilTest();
984     //varint::Test();
985     //small_vector_ns::Test();
986     //small_map_ns::Test();
987     //recordtest::Test();
988     //rcu::Test();
989     extern void TestConcurrentBtreeFast();
990     extern void TestConcurrentBtreeSlow();
991     // either tests Masstree or Silotree, depending on NDB_MASSTREE
992     TestConcurrentBtreeFast();
993     TestConcurrentBtreeSlow();
994     txn_btree_test();
995     ret = 0;
996   }
997
998   inline int
999   retval() const
1000   {
1001     return ret;
1002   }
1003 private:
1004   const int argc;
1005   char **const argv;
1006   volatile int ret;
1007 };
1008
1009 int
1010 main(int argc, char **argv)
1011 {
1012   main_thread t(argc, argv);
1013   t.start();
1014   t.join();
1015   return t.retval();
1016 }