f4e68bd32b1212bdfa6eff1e48729ba64969860b
[invirt/third/libt4.git] / lock_tester.cc
1 //
2 // Lock server tester
3 //
4
5 #include "lock_protocol.h"
6 #include "lock_client.h"
7 #include "rpc/rpc.h"
8 #include <arpa/inet.h>
9 #include <vector>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include "lang/verify.h"
13 #include "tprintf.h"
14 #include <sys/types.h>
15 #include <unistd.h>
16 #include "lock.h"
17
18 char tprintf_thread_prefix = 'c';
19
20 // must be >= 2
21 const int nt = 6; //XXX: lab1's rpc handlers are blocking. Since rpcs uses a thread pool of 10 threads, we cannot test more than 10 blocking rpc.
22 std::string dst;
23 lock_client **lc = new lock_client * [nt];
24 lock_protocol::lockid_t a = "1";
25 lock_protocol::lockid_t b = "2";
26 lock_protocol::lockid_t c = "3";
27
28 // check_grant() and check_release() check that the lock server
29 // doesn't grant the same lock to both clients.
30 // it assumes that lock names are distinct in the first byte.
31 int ct[256];
32 std::mutex count_mutex;
33
34 void
35 check_grant(lock_protocol::lockid_t lid)
36 {
37     lock ml(count_mutex);
38     int x = lid[0] & 0x0f;
39     if(ct[x] != 0){
40         fprintf(stderr, "error: server granted %s twice\n", lid.c_str());
41         fprintf(stdout, "error: server granted %s twice\n", lid.c_str());
42         exit(1);
43     }
44     ct[x] += 1;
45 }
46
47 void
48 check_release(lock_protocol::lockid_t lid)
49 {
50     lock ml(count_mutex);
51     int x = lid[0] & 0x0f;
52     if(ct[x] != 1){
53         fprintf(stderr, "error: client released un-held lock %s\n",  lid.c_str());
54         exit(1);
55     }
56     ct[x] -= 1;
57 }
58
59 void
60 test1(void)
61 {
62     tprintf ("acquire a release a acquire a release a\n");
63     lc[0]->acquire(a);
64     check_grant(a);
65     lc[0]->release(a);
66     check_release(a);
67     lc[0]->acquire(a);
68     check_grant(a);
69     lc[0]->release(a);
70     check_release(a);
71
72     tprintf ("acquire a acquire b release b release a\n");
73     lc[0]->acquire(a);
74     check_grant(a);
75     lc[0]->acquire(b);
76     check_grant(b);
77     lc[0]->release(b);
78     check_release(b);
79     lc[0]->release(a);
80     check_release(a);
81 }
82
83 void *
84 test2(int i) 
85 {
86     tprintf ("test2: client %d acquire a release a\n", i);
87     lc[i]->acquire(a);
88     tprintf ("test2: client %d acquire done\n", i);
89     check_grant(a);
90     sleep(1);
91     tprintf ("test2: client %d release\n", i);
92     check_release(a);
93     lc[i]->release(a);
94     tprintf ("test2: client %d release done\n", i);
95     return 0;
96 }
97
98 void *
99 test3(int i)
100 {
101     tprintf ("test3: client %d acquire a release a concurrent\n", i);
102     for (int j = 0; j < 10; j++) {
103         lc[i]->acquire(a);
104         check_grant(a);
105         tprintf ("test3: client %d got lock\n", i);
106         check_release(a);
107         lc[i]->release(a);
108     }
109     return 0;
110 }
111
112 void *
113 test4(int i)
114 {
115     tprintf ("test4: thread %d acquire a release a concurrent; same clnt\n", i);
116     for (int j = 0; j < 10; j++) {
117         lc[0]->acquire(a);
118         check_grant(a);
119         tprintf ("test4: thread %d on client 0 got lock\n", i);
120         check_release(a);
121         lc[0]->release(a);
122     }
123     return 0;
124 }
125
126 void *
127 test5(int i)
128 {
129     tprintf ("test5: client %d acquire a release a concurrent; same and diff clnt\n", i);
130     for (int j = 0; j < 10; j++) {
131         if (i < 5)  lc[0]->acquire(a);
132         else  lc[1]->acquire(a);
133         check_grant(a);
134         tprintf ("test5: client %d got lock\n", i);
135         check_release(a);
136         if (i < 5) lc[0]->release(a);
137         else lc[1]->release(a);
138     }
139     return 0;
140 }
141
142 int
143 main(int argc, char *argv[])
144 {
145     std::thread th[nt];
146     int test = 0;
147
148     setvbuf(stdout, NULL, _IONBF, 0);
149     setvbuf(stderr, NULL, _IONBF, 0);
150     srandom((uint32_t)getpid());
151
152     if(argc < 2) {
153         fprintf(stderr, "Usage: %s [host:]port [test]\n", argv[0]);
154         exit(1);
155     }
156
157     dst = argv[1]; 
158
159     if (argc > 2) {
160         test = atoi(argv[2]);
161         if(test < 1 || test > 5){
162             tprintf("Test number must be between 1 and 5\n");
163             exit(1);
164         }
165     }
166
167     tprintf("cache lock client\n");
168     for (int i = 0; i < nt; i++) lc[i] = new lock_client(dst);
169
170     if(!test || test == 1){
171         test1();
172     }
173
174     if(!test || test == 2){
175         // test2
176         for (int i = 0; i < nt; i++)
177             th[i] = std::thread(test2, i);
178         for (int i = 0; i < nt; i++)
179             th[i].join();
180     }
181
182     if(!test || test == 3){
183         tprintf("test 3\n");
184
185         // test3
186         for (int i = 0; i < nt; i++)
187             th[i] = std::thread(test3, i);
188         for (int i = 0; i < nt; i++)
189             th[i].join();
190     }
191
192     if(!test || test == 4){
193         tprintf("test 4\n");
194
195         // test 4
196         for (int i = 0; i < 2; i++)
197             th[i] = std::thread(test4, i);
198         for (int i = 0; i < 2; i++)
199             th[i].join();
200     }
201
202     if(!test || test == 5){
203         tprintf("test 5\n");
204
205         // test 5
206         for (int i = 0; i < nt; i++)
207             th[i] = std::thread(test5, i);
208         for (int i = 0; i < nt; i++)
209             th[i].join();
210     }
211
212     tprintf ("%s: passed all tests successfully\n", argv[0]);
213
214 }