Imported Upstream version 4.10.6
[platform/upstream/nspr.git] / pr / src / cplus / tests / tpd.cpp
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 /*
7 ** File:        tpd.cpp
8 ** Description: Exercising the thread private data bailywick.
9 */
10
11 #include "prlog.h"
12 #include "prprf.h"
13 #include "rcthread.h"
14
15 #include <string.h>
16
17 #include "plgetopt.h"
18
19 /*
20 ** class MyThread
21 */
22 class MyThread: public RCThread
23 {
24 public:
25     MyThread();
26
27 private:
28     ~MyThread();
29     void RootFunction();
30 };  /* MyThread */
31
32 /*
33 ** class MyPrivateData
34 */
35 class MyPrivateData: public RCThreadPrivateData
36 {
37 public:
38     virtual ~MyPrivateData();
39
40     MyPrivateData();
41     MyPrivateData(char*);
42     MyPrivateData(const MyPrivateData&);
43
44     void Release();
45
46 private:
47     char *string;
48 };  /* MyPrivateData */
49
50 static PRUintn key[128];
51 static PRIntn debug = 0;
52 static PRBool failed = PR_FALSE;
53 static PRBool should = PR_TRUE;
54 static PRBool did = PR_TRUE;
55 static PRFileDesc *fout = NULL;
56
57 static void PrintProgress(PRIntn line)
58 {
59     failed = failed || (should && !did);
60     failed = failed || (!should && did);
61     if (debug > 0)
62     {
63         PR_fprintf(
64             fout, "@ line %d destructor should %shave been called and was%s\n",
65             line, ((should) ? "" : "NOT "), ((did) ? "" : " NOT"));
66     }
67 }  /* PrintProgress */
68
69 static void MyAssert(const char *expr, const char *file, PRIntn line)
70 {
71     if (debug > 0)
72         (void)PR_fprintf(fout, "'%s' in file: %s: %d\n", expr, file, line);
73 }  /* MyAssert */
74
75 #define MY_ASSERT(_expr) \
76     ((_expr)?((void)0):MyAssert(# _expr,__FILE__,__LINE__))
77
78 int main(PRIntn argc, char *argv[])
79 {
80     PRStatus rv;
81     PRUintn keys;
82     MyThread *thread;
83     const RCThreadPrivateData *pd;
84     PLOptStatus os;
85     PLOptState *opt = PL_CreateOptState(argc, argv, "d");
86     RCThread *primordial = RCThread::WrapPrimordialThread();
87     while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
88     {
89         if (PL_OPT_BAD == os) continue;
90         switch (opt->option)
91         {
92         case 'd':  /* debug mode */
93             debug = PR_TRUE;
94             break;
95          default:
96             break;
97         }
98     }
99     PL_DestroyOptState(opt);
100
101     fout = PR_STDOUT;
102
103     MyPrivateData extension = MyPrivateData("EXTENSION");
104     MyPrivateData key_string[] = {
105         "Key #0", "Key #1", "Key #2", "Key #3",
106         "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"};
107     
108
109     did = should = PR_FALSE;
110     for (keys = 0; keys < 4; ++keys)
111     {
112         rv = RCThread::NewPrivateIndex(&key[keys]);
113         key[keys + 4] = key[keys] + 4;
114         MY_ASSERT(PR_SUCCESS == rv);
115     }
116     PrintProgress(__LINE__);
117
118     /* the first four should be bu null, the last four undefined and null */
119     did = should = PR_FALSE;
120     for (keys = 0; keys < 8; ++keys)
121     {
122         pd = RCThread::GetPrivateData(key[keys]);
123         MY_ASSERT(NULL == pd);
124     }
125     PrintProgress(__LINE__);
126
127     /* initially set private data for new keys */
128     did = should = PR_FALSE;
129     for (keys = 0; keys < 4; ++keys)
130     {
131         rv = RCThread::SetPrivateData(key[keys], &key_string[keys]);
132         MY_ASSERT(PR_SUCCESS == rv);
133     }
134     PrintProgress(__LINE__);
135
136     /* re-assign the private data, albeit the same content */    
137     did = PR_FALSE; should = PR_TRUE;
138     for (keys = 0; keys < 4; ++keys)
139     {
140         pd = RCThread::GetPrivateData(key[keys]);
141         PR_ASSERT(NULL != pd);
142         rv = RCThread::SetPrivateData(key[keys], &key_string[keys]);
143         MY_ASSERT(PR_SUCCESS == rv);
144     }
145     PrintProgress(__LINE__);
146
147     /* set private to <empty> */
148     did = PR_FALSE; should = PR_TRUE;
149     for (keys = 0; keys < 4; ++keys)
150     {
151         rv = RCThread::SetPrivateData(key[keys]);
152         MY_ASSERT(PR_SUCCESS == rv);
153     }
154     PrintProgress(__LINE__);
155
156     /* should all be null now */
157     did = should = PR_FALSE;
158     for (keys = 0; keys < 4; ++keys)
159     {
160         pd = RCThread::GetPrivateData(key[keys]);
161         PR_ASSERT(NULL == pd);
162     }
163     PrintProgress(__LINE__);
164
165     /* allocate another batch of keys and assign data to them */
166     did = should = PR_FALSE;
167     for (keys = 8; keys < 127; ++keys)
168     {
169         rv = RCThread::NewPrivateIndex(&key[keys]);
170         MY_ASSERT(PR_SUCCESS == rv);
171         rv = RCThread::SetPrivateData(key[keys], &extension);
172         MY_ASSERT(PR_SUCCESS == rv);
173     }
174     PrintProgress(__LINE__);
175
176     /* set all the extended slots to <empty> */
177     did = PR_FALSE; should = PR_TRUE;
178     for (keys = 8; keys < 127; ++keys)
179     {
180         rv = RCThread::SetPrivateData(key[keys]);
181         MY_ASSERT(PR_SUCCESS == rv);
182     }
183     PrintProgress(__LINE__);
184
185     /* set all the extended slots to <empty> again (noop) */
186     did = should = PR_FALSE;
187     for (keys = 8; keys < 127; ++keys)
188     {
189         rv = RCThread::SetPrivateData(key[keys]);
190         MY_ASSERT(PR_SUCCESS == rv);
191     }
192
193     if (debug) PR_fprintf(fout, "Creating thread\n");
194     thread = new MyThread();
195     if (debug) PR_fprintf(fout, "Starting thread\n");
196     thread->Start();
197     if (debug) PR_fprintf(fout, "Joining thread\n");
198     (void)thread->Join();
199     if (debug) PR_fprintf(fout, "Joined thread\n");
200
201     failed |= (PR_FAILURE == RCPrimordialThread::Cleanup());
202
203     (void)PR_fprintf(
204         fout, "%s\n",((PR_TRUE == failed) ? "FAILED" : "PASSED"));
205
206     return (failed) ? 1 : 0;
207
208 }  /* main */
209
210 /*
211 ** class MyPrivateData
212 */
213 MyPrivateData::~MyPrivateData()
214 {
215     PR_fprintf(
216         fout, "MyPrivateData::~MyPrivateData[%s]\n",
217         (NULL != string) ? string : "NULL");
218 }  /* MyPrivateData::~MyPrivateData */
219
220 MyPrivateData::MyPrivateData(): RCThreadPrivateData()
221 {
222     PR_fprintf(fout, "MyPrivateData::MyPrivateData()\n");
223     string = NULL;
224 }  /* MyPrivateData::MyPrivateData */
225
226 MyPrivateData::MyPrivateData(char* data): RCThreadPrivateData()
227 {
228     PR_fprintf(fout, "MyPrivateData::MyPrivateData(char* data)\n");
229     string = data;
230 }  /* MyPrivateData:: MyPrivateData */
231
232 MyPrivateData::MyPrivateData(const MyPrivateData& him): RCThreadPrivateData(him)
233 {
234     PR_fprintf(fout, "MyPrivateData::MyPrivateData(const MyPrivateData& him)\n");
235     string = him.string;
236 }  /* MyPrivateData:: MyPrivateData */
237
238 void MyPrivateData::Release()
239 {
240     if (should) did = PR_TRUE;
241     else failed = PR_TRUE;
242 }  /* MyPrivateData::operator= */
243
244 /*
245 ** class MyThread
246 */
247 MyThread::~MyThread() { }
248 MyThread::MyThread(): RCThread(RCThread::global, RCThread::joinable) { }
249
250
251 void MyThread::RootFunction()
252 {
253     PRStatus rv;
254     PRUintn keys;
255     const RCThreadPrivateData *pd;
256     
257     MyPrivateData extension = MyPrivateData("EXTENSION");
258     MyPrivateData key_string[] = {
259         "Key #0", "Key #1", "Key #2", "Key #3",
260         "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"};
261     
262     did = should = PR_FALSE;
263     for (keys = 0; keys < 8; ++keys)
264     {
265         pd = GetPrivateData(key[keys]);
266         MY_ASSERT(NULL == pd);
267     }
268     PrintProgress(__LINE__);
269
270     did = should = PR_FALSE;
271     for (keys = 0; keys < 4; ++keys)
272     {
273         rv = SetPrivateData(keys, &key_string[keys]);
274         MY_ASSERT(PR_SUCCESS == rv);
275     }
276     PrintProgress(__LINE__);
277
278 #if !defined(DEBUG)
279     did = should = PR_FALSE;
280     for (keys = 4; keys < 8; ++keys)
281     {
282         rv = SetPrivateData(keys, &key_string[keys]);
283         MY_ASSERT(PR_FAILURE == rv);
284     }
285     PrintProgress(__LINE__);
286 #endif
287     
288     did = PR_FALSE; should = PR_TRUE;
289     for (keys = 0; keys < 4; ++keys)
290     {
291         rv = SetPrivateData(key[keys], &key_string[keys]);
292         MY_ASSERT(PR_SUCCESS == rv);
293     }
294     PrintProgress(__LINE__);
295
296     did = PR_FALSE; should = PR_TRUE;
297     for (keys = 0; keys < 4; ++keys)
298     {
299         rv = SetPrivateData(key[keys]);
300         MY_ASSERT(PR_SUCCESS == rv);
301     }
302     PrintProgress(__LINE__);
303
304     did = should = PR_FALSE;
305     for (keys = 0; keys < 4; ++keys)
306     {
307         rv = SetPrivateData(key[keys]);
308         MY_ASSERT(PR_SUCCESS == rv);
309     }
310     PrintProgress(__LINE__);
311
312     did = should = PR_FALSE;
313     for (keys = 8; keys < 127; ++keys)
314     {
315         rv = SetPrivateData(key[keys], &extension);
316         MY_ASSERT(PR_SUCCESS == rv);
317     }
318     PrintProgress(__LINE__);
319
320     did = PR_FALSE; should = PR_TRUE;
321     for (keys = 8; keys < 127; ++keys)
322     {
323         rv = SetPrivateData(key[keys]);
324         MY_ASSERT(PR_SUCCESS == rv);
325     }
326     PrintProgress(__LINE__);
327
328     did = should = PR_FALSE;
329     for (keys = 8; keys < 127; ++keys)
330     {
331         rv = SetPrivateData(key[keys]);
332         MY_ASSERT(PR_SUCCESS == rv);
333     }
334 }  /* MyThread::RootFunction */
335
336 /* tpd.c */