]> pd.if.org Git - nbds/blob - test/map_test2.c
b321a683b1daabee11595940143ec2312f328e0a
[nbds] / test / map_test2.c
1 /* 
2  * Written by Josh Dybnis and released to the public domain, as explained at
3  * http://creativecommons.org/licenses/publicdomain
4  */
5 #include <stdio.h>
6 #include <pthread.h>
7
8 #include "CuTest.h"
9
10 #include "common.h"
11 #include "runtime.h"
12 #include "map.h"
13 #include "lwt.h"
14
15 #define ASSERT_EQUAL(x, y) CuAssertIntEquals(tc, x, y)
16
17 typedef struct worker_data {
18     int id;
19     CuTest *tc;
20     map_t *map;
21     int *wait;
22 } worker_data_t;
23
24 static map_type_t map_type_;
25
26 // Test some basic stuff; add a few keys, remove a few keys
27 void basic_test (CuTest* tc) {
28
29     map_t *map = map_alloc(map_type_);
30
31     ASSERT_EQUAL( 0,              map_count(map)            );
32     ASSERT_EQUAL( DOES_NOT_EXIST, map_add(map,"a",2,10)     );
33     ASSERT_EQUAL( 1,              map_count(map)            );
34     ASSERT_EQUAL( DOES_NOT_EXIST, map_add(map,"b",2,20)     );
35     ASSERT_EQUAL( 2,              map_count(map)            );
36     ASSERT_EQUAL( 20,             map_get(map,"b",2)        );
37     ASSERT_EQUAL( 10,             map_set(map,"a",2,11)     );
38     ASSERT_EQUAL( 20,             map_set(map,"b",2,21)     );
39     ASSERT_EQUAL( 2,              map_count(map)            );
40     ASSERT_EQUAL( 21,             map_add(map,"b",2,22)     );
41     ASSERT_EQUAL( 11,             map_remove(map,"a",2)     );
42     ASSERT_EQUAL( DOES_NOT_EXIST, map_get(map,"a",2)        );
43     ASSERT_EQUAL( 1,              map_count(map)            );
44     ASSERT_EQUAL( DOES_NOT_EXIST, map_remove(map,"a",2)     );
45     ASSERT_EQUAL( 21,             map_remove(map,"b",2)     );
46     ASSERT_EQUAL( 0,              map_count(map)            );
47     ASSERT_EQUAL( DOES_NOT_EXIST, map_remove(map,"b",2)     );
48     ASSERT_EQUAL( DOES_NOT_EXIST, map_remove(map,"c",2)     );
49     ASSERT_EQUAL( 0,              map_count(map)            );
50     
51     ASSERT_EQUAL( DOES_NOT_EXIST, map_add(map,"d",2,40)     );
52     ASSERT_EQUAL( 40,             map_get(map,"d",2)        );
53     ASSERT_EQUAL( 1,              map_count(map)            );
54     ASSERT_EQUAL( 40,             map_remove(map,"d",2)     );
55     ASSERT_EQUAL( DOES_NOT_EXIST, map_get(map,"d",2)        );
56     ASSERT_EQUAL( 0,              map_count(map)            );
57
58     ASSERT_EQUAL( DOES_NOT_EXIST, map_replace(map,"d",2,10) );
59     ASSERT_EQUAL( DOES_NOT_EXIST, map_get(map,"d",2)        );
60     ASSERT_EQUAL( DOES_NOT_EXIST, map_set(map,"d",2,40)     );
61     ASSERT_EQUAL( 40,             map_replace(map,"d",2,41) );
62     ASSERT_EQUAL( 41,             map_get(map,"d",2)        );
63     ASSERT_EQUAL( 41,             map_remove(map,"d",2)     );
64     ASSERT_EQUAL( DOES_NOT_EXIST, map_get(map,"d",2)        );
65     ASSERT_EQUAL( 0,              map_count(map)            );
66
67     ASSERT_EQUAL( DOES_NOT_EXIST, map_replace(map,"b",2,20) );
68     ASSERT_EQUAL( DOES_NOT_EXIST, map_get(map,"b",2)        );
69
70     // In the end, all entries should be removed
71     ASSERT_EQUAL( DOES_NOT_EXIST, map_set(map,"b",2,20)     );
72     ASSERT_EQUAL( 20,             map_replace(map,"b",2,21) );
73     ASSERT_EQUAL( 21,             map_get(map,"b",2)        );
74     ASSERT_EQUAL( 21,             map_remove(map,"b",2)     );
75     ASSERT_EQUAL( DOES_NOT_EXIST, map_get(map,"b",2)        );
76     ASSERT_EQUAL( 0,              map_count(map)            );
77
78     map_free(map);
79
80     // In a quiecent state; it is safe to free.
81     rcu_update();
82 }
83
84 void *simple_worker (void *arg) {
85     worker_data_t *wd = (worker_data_t *)arg;
86     map_t *map = wd->map;
87     CuTest* tc = wd->tc;
88     uint64_t d = wd->id;
89     int iters = map_type_ == MAP_TYPE_LIST ? 100 : 1000000;
90
91     SYNC_ADD(wd->wait, -1);
92     do { } while (*((volatile worker_data_t *)wd)->wait); // wait for all workers to be ready
93
94     for (int j = 0; j < 10; ++j) {
95         for (int i = d; i < iters; i+=2) {
96             char key[10];
97             sprintf(key, "k%u", i); 
98             TRACE("t0", "test map_add() iteration (%llu, %llu)", j, i);
99             CuAssertIntEquals_Msg(tc, key, DOES_NOT_EXIST, map_add(map, key, strlen(key)+1, d+1) );
100             rcu_update();
101         }
102         for (int i = d; i < iters; i+=2) {
103             char key[10];
104             sprintf(key, "k%u", i); 
105             TRACE("t0", "test map_remove() iteration (%llu, %llu)", j, i);
106             CuAssertIntEquals_Msg(tc, key, d+1, map_remove(map, key, strlen(key)+1) );
107             rcu_update();
108         }
109     }
110     return NULL;
111 }
112
113 // Do some simple concurrent testing
114 void simple_add_remove (CuTest* tc) {
115
116     pthread_t thread[2];
117     worker_data_t wd[2];
118     int wait = 2;
119     map_t *map = map_alloc(map_type_);
120
121     // In 2 threads, add & remove even & odd elements concurrently
122     int i;
123     for (i = 0; i < 2; ++i) {
124         wd[i].id = i;
125         wd[i].tc = tc;
126         wd[i].map = map;
127         wd[i].wait = &wait;
128         int rc = nbd_thread_create(thread + i, i, simple_worker, wd + i);
129         if (rc != 0) { perror("nbd_thread_create"); return; }
130     }
131     for (i = 0; i < 2; ++i) {
132         pthread_join(thread[i], NULL);
133     }
134
135     // In the end, all members should be removed
136     ASSERT_EQUAL( 0, map_count(map) );
137
138     // In a quiecent state; it is safe to free.
139     map_free(map);
140 }
141
142
143 void *inserter_worker (void *arg) {
144     //pthread_t thread[NUM_THREADS];
145
146     //map_t *map = map_alloc(map_type_);
147     return NULL;
148 }
149
150 // Concurrent insertion
151 void concurrent_insert (CuTest* tc) {
152 }
153
154 int main (void) {
155
156     nbd_init();
157     //lwt_set_trace_level("h0");
158
159     map_type_t map_types[] = { MAP_TYPE_LIST, MAP_TYPE_SKIPLIST, MAP_TYPE_HASHTABLE };
160     for (int i = 0; i < sizeof(map_types)/sizeof(*map_types); ++i) {
161         map_type_ = map_types[i];
162
163         // Create and run test suite
164         CuString *output = CuStringNew();
165         CuSuite* suite = CuSuiteNew();
166
167         SUITE_ADD_TEST(suite, basic_test);
168         SUITE_ADD_TEST(suite, simple_add_remove);
169
170         CuSuiteRun(suite);
171         CuSuiteDetails(suite, output);
172         printf("%s\n", output->buffer);
173     }
174
175     return 0;
176 }