tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

tpd.cpp (8749B)


      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    }
     74 }  /* MyAssert */
     75 
     76 #define MY_ASSERT(_expr) \
     77    ((_expr)?((void)0):MyAssert(# _expr,__FILE__,__LINE__))
     78 
     79 int main(PRIntn argc, char *argv[])
     80 {
     81    PRStatus rv;
     82    PRUintn keys;
     83    MyThread *thread;
     84    const RCThreadPrivateData *pd;
     85    PLOptStatus os;
     86    PLOptState *opt = PL_CreateOptState(argc, argv, "d");
     87    RCThread *primordial = RCThread::WrapPrimordialThread();
     88    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
     89    {
     90        if (PL_OPT_BAD == os) {
     91            continue;
     92        }
     93        switch (opt->option)
     94        {
     95            case 'd':  /* debug mode */
     96                debug = PR_TRUE;
     97                break;
     98            default:
     99                break;
    100        }
    101    }
    102    PL_DestroyOptState(opt);
    103 
    104    fout = PR_STDOUT;
    105 
    106    MyPrivateData extension = MyPrivateData("EXTENSION");
    107    MyPrivateData key_string[] = {
    108        "Key #0", "Key #1", "Key #2", "Key #3",
    109        "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"
    110    };
    111 
    112 
    113    did = should = PR_FALSE;
    114    for (keys = 0; keys < 4; ++keys)
    115    {
    116        rv = RCThread::NewPrivateIndex(&key[keys]);
    117        key[keys + 4] = key[keys] + 4;
    118        MY_ASSERT(PR_SUCCESS == rv);
    119    }
    120    PrintProgress(__LINE__);
    121 
    122    /* the first four should be bu null, the last four undefined and null */
    123    did = should = PR_FALSE;
    124    for (keys = 0; keys < 8; ++keys)
    125    {
    126        pd = RCThread::GetPrivateData(key[keys]);
    127        MY_ASSERT(NULL == pd);
    128    }
    129    PrintProgress(__LINE__);
    130 
    131    /* initially set private data for new keys */
    132    did = should = PR_FALSE;
    133    for (keys = 0; keys < 4; ++keys)
    134    {
    135        rv = RCThread::SetPrivateData(key[keys], &key_string[keys]);
    136        MY_ASSERT(PR_SUCCESS == rv);
    137    }
    138    PrintProgress(__LINE__);
    139 
    140    /* re-assign the private data, albeit the same content */
    141    did = PR_FALSE; should = PR_TRUE;
    142    for (keys = 0; keys < 4; ++keys)
    143    {
    144        pd = RCThread::GetPrivateData(key[keys]);
    145        PR_ASSERT(NULL != pd);
    146        rv = RCThread::SetPrivateData(key[keys], &key_string[keys]);
    147        MY_ASSERT(PR_SUCCESS == rv);
    148    }
    149    PrintProgress(__LINE__);
    150 
    151    /* set private to <empty> */
    152    did = PR_FALSE; should = PR_TRUE;
    153    for (keys = 0; keys < 4; ++keys)
    154    {
    155        rv = RCThread::SetPrivateData(key[keys]);
    156        MY_ASSERT(PR_SUCCESS == rv);
    157    }
    158    PrintProgress(__LINE__);
    159 
    160    /* should all be null now */
    161    did = should = PR_FALSE;
    162    for (keys = 0; keys < 4; ++keys)
    163    {
    164        pd = RCThread::GetPrivateData(key[keys]);
    165        PR_ASSERT(NULL == pd);
    166    }
    167    PrintProgress(__LINE__);
    168 
    169    /* allocate another batch of keys and assign data to them */
    170    did = should = PR_FALSE;
    171    for (keys = 8; keys < 127; ++keys)
    172    {
    173        rv = RCThread::NewPrivateIndex(&key[keys]);
    174        MY_ASSERT(PR_SUCCESS == rv);
    175        rv = RCThread::SetPrivateData(key[keys], &extension);
    176        MY_ASSERT(PR_SUCCESS == rv);
    177    }
    178    PrintProgress(__LINE__);
    179 
    180    /* set all the extended slots to <empty> */
    181    did = PR_FALSE; should = PR_TRUE;
    182    for (keys = 8; keys < 127; ++keys)
    183    {
    184        rv = RCThread::SetPrivateData(key[keys]);
    185        MY_ASSERT(PR_SUCCESS == rv);
    186    }
    187    PrintProgress(__LINE__);
    188 
    189    /* set all the extended slots to <empty> again (noop) */
    190    did = should = PR_FALSE;
    191    for (keys = 8; keys < 127; ++keys)
    192    {
    193        rv = RCThread::SetPrivateData(key[keys]);
    194        MY_ASSERT(PR_SUCCESS == rv);
    195    }
    196 
    197    if (debug) {
    198        PR_fprintf(fout, "Creating thread\n");
    199    }
    200    thread = new MyThread();
    201    if (debug) {
    202        PR_fprintf(fout, "Starting thread\n");
    203    }
    204    thread->Start();
    205    if (debug) {
    206        PR_fprintf(fout, "Joining thread\n");
    207    }
    208    (void)thread->Join();
    209    if (debug) {
    210        PR_fprintf(fout, "Joined thread\n");
    211    }
    212 
    213    failed |= (PR_FAILURE == RCPrimordialThread::Cleanup());
    214 
    215    (void)PR_fprintf(
    216        fout, "%s\n",((PR_TRUE == failed) ? "FAILED" : "PASSED"));
    217 
    218    return (failed) ? 1 : 0;
    219 
    220 }  /* main */
    221 
    222 /*
    223 ** class MyPrivateData
    224 */
    225 MyPrivateData::~MyPrivateData()
    226 {
    227    PR_fprintf(
    228        fout, "MyPrivateData::~MyPrivateData[%s]\n",
    229        (NULL != string) ? string : "NULL");
    230 }  /* MyPrivateData::~MyPrivateData */
    231 
    232 MyPrivateData::MyPrivateData(): RCThreadPrivateData()
    233 {
    234    PR_fprintf(fout, "MyPrivateData::MyPrivateData()\n");
    235    string = NULL;
    236 }  /* MyPrivateData::MyPrivateData */
    237 
    238 MyPrivateData::MyPrivateData(char* data): RCThreadPrivateData()
    239 {
    240    PR_fprintf(fout, "MyPrivateData::MyPrivateData(char* data)\n");
    241    string = data;
    242 }  /* MyPrivateData:: MyPrivateData */
    243 
    244 MyPrivateData::MyPrivateData(const MyPrivateData& him): RCThreadPrivateData(him)
    245 {
    246    PR_fprintf(fout, "MyPrivateData::MyPrivateData(const MyPrivateData& him)\n");
    247    string = him.string;
    248 }  /* MyPrivateData:: MyPrivateData */
    249 
    250 void MyPrivateData::Release()
    251 {
    252    if (should) {
    253        did = PR_TRUE;
    254    }
    255    else {
    256        failed = PR_TRUE;
    257    }
    258 }  /* MyPrivateData::operator= */
    259 
    260 /*
    261 ** class MyThread
    262 */
    263 MyThread::~MyThread() { }
    264 MyThread::MyThread(): RCThread(RCThread::global, RCThread::joinable) { }
    265 
    266 
    267 void MyThread::RootFunction()
    268 {
    269    PRStatus rv;
    270    PRUintn keys;
    271    const RCThreadPrivateData *pd;
    272 
    273    MyPrivateData extension = MyPrivateData("EXTENSION");
    274    MyPrivateData key_string[] = {
    275        "Key #0", "Key #1", "Key #2", "Key #3",
    276        "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"
    277    };
    278 
    279    did = should = PR_FALSE;
    280    for (keys = 0; keys < 8; ++keys)
    281    {
    282        pd = GetPrivateData(key[keys]);
    283        MY_ASSERT(NULL == pd);
    284    }
    285    PrintProgress(__LINE__);
    286 
    287    did = should = PR_FALSE;
    288    for (keys = 0; keys < 4; ++keys)
    289    {
    290        rv = SetPrivateData(keys, &key_string[keys]);
    291        MY_ASSERT(PR_SUCCESS == rv);
    292    }
    293    PrintProgress(__LINE__);
    294 
    295 #if !defined(DEBUG)
    296    did = should = PR_FALSE;
    297    for (keys = 4; keys < 8; ++keys)
    298    {
    299        rv = SetPrivateData(keys, &key_string[keys]);
    300        MY_ASSERT(PR_FAILURE == rv);
    301    }
    302    PrintProgress(__LINE__);
    303 #endif
    304 
    305    did = PR_FALSE; should = PR_TRUE;
    306    for (keys = 0; keys < 4; ++keys)
    307    {
    308        rv = SetPrivateData(key[keys], &key_string[keys]);
    309        MY_ASSERT(PR_SUCCESS == rv);
    310    }
    311    PrintProgress(__LINE__);
    312 
    313    did = PR_FALSE; should = PR_TRUE;
    314    for (keys = 0; keys < 4; ++keys)
    315    {
    316        rv = SetPrivateData(key[keys]);
    317        MY_ASSERT(PR_SUCCESS == rv);
    318    }
    319    PrintProgress(__LINE__);
    320 
    321    did = should = PR_FALSE;
    322    for (keys = 0; keys < 4; ++keys)
    323    {
    324        rv = SetPrivateData(key[keys]);
    325        MY_ASSERT(PR_SUCCESS == rv);
    326    }
    327    PrintProgress(__LINE__);
    328 
    329    did = should = PR_FALSE;
    330    for (keys = 8; keys < 127; ++keys)
    331    {
    332        rv = SetPrivateData(key[keys], &extension);
    333        MY_ASSERT(PR_SUCCESS == rv);
    334    }
    335    PrintProgress(__LINE__);
    336 
    337    did = PR_FALSE; should = PR_TRUE;
    338    for (keys = 8; keys < 127; ++keys)
    339    {
    340        rv = SetPrivateData(key[keys]);
    341        MY_ASSERT(PR_SUCCESS == rv);
    342    }
    343    PrintProgress(__LINE__);
    344 
    345    did = should = PR_FALSE;
    346    for (keys = 8; keys < 127; ++keys)
    347    {
    348        rv = SetPrivateData(key[keys]);
    349        MY_ASSERT(PR_SUCCESS == rv);
    350    }
    351 }  /* MyThread::RootFunction */
    352 
    353 /* tpd.c */