tor-browser

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

tpd.c (6913B)


      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.c
      8 ** Description: Exercising the thread private data bailywick.
      9 */
     10 
     11 #include "prmem.h"
     12 #include "prinit.h"
     13 #include "prlog.h"
     14 #include "prprf.h"
     15 #include "prthread.h"
     16 #include "prtypes.h"
     17 
     18 #include "private/pprio.h"
     19 
     20 #include "plgetopt.h"
     21 
     22 static PRUintn key[128];
     23 static PRIntn debug = 0;
     24 static PRBool failed = PR_FALSE;
     25 static PRBool should = PR_TRUE;
     26 static PRBool did = PR_TRUE;
     27 static PRFileDesc* fout = NULL;
     28 
     29 static void PrintProgress(PRIntn line) {
     30  failed = failed || (should && !did);
     31  failed = failed || (!should && did);
     32  if (debug > 0) {
     33    PR_fprintf(fout,
     34               "@ line %d destructor should%s have been called and was%s\n",
     35               line, ((should) ? "" : " NOT"), ((did) ? "" : " NOT"));
     36  }
     37 } /* PrintProgress */
     38 
     39 static void MyAssert(const char* expr, const char* file, PRIntn line) {
     40  if (debug > 0) {
     41    (void)PR_fprintf(fout, "'%s' in file: %s: %d\n", expr, file, line);
     42  }
     43 } /* MyAssert */
     44 
     45 #define MY_ASSERT(_expr) \
     46  ((_expr) ? ((void)0) : MyAssert(#_expr, __FILE__, __LINE__))
     47 
     48 static void PR_CALLBACK Destructor(void* data) {
     49  MY_ASSERT(NULL != data);
     50  if (should) {
     51    did = PR_TRUE;
     52  } else {
     53    failed = PR_TRUE;
     54  }
     55  /*
     56   * We don't actually free the storage since it's actually allocated
     57   * on the stack. Normally, this would not be the case and this is
     58   * the opportunity to free whatever.
     59  PR_Free(data);
     60   */
     61 } /* Destructor */
     62 
     63 static void PR_CALLBACK Thread(void* null) {
     64  void* pd;
     65  PRStatus rv;
     66  PRUintn keys;
     67  char* key_string[] = {"Key #0",   "Key #1",   "Key #2",   "Key #3",
     68                        "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"};
     69 
     70  did = should = PR_FALSE;
     71  for (keys = 0; keys < 8; ++keys) {
     72    pd = PR_GetThreadPrivate(key[keys]);
     73    MY_ASSERT(NULL == pd);
     74  }
     75  PrintProgress(__LINE__);
     76 
     77  did = should = PR_FALSE;
     78  for (keys = 0; keys < 4; ++keys) {
     79    rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
     80    MY_ASSERT(PR_SUCCESS == rv);
     81  }
     82  PrintProgress(__LINE__);
     83 
     84  did = should = PR_FALSE;
     85  for (keys = 4; keys < 8; ++keys) {
     86    rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
     87    MY_ASSERT(PR_FAILURE == rv);
     88  }
     89  PrintProgress(__LINE__);
     90 
     91  did = PR_FALSE;
     92  should = PR_TRUE;
     93  for (keys = 0; keys < 4; ++keys) {
     94    rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
     95    MY_ASSERT(PR_SUCCESS == rv);
     96  }
     97  PrintProgress(__LINE__);
     98 
     99  did = PR_FALSE;
    100  should = PR_TRUE;
    101  for (keys = 0; keys < 4; ++keys) {
    102    rv = PR_SetThreadPrivate(key[keys], NULL);
    103    MY_ASSERT(PR_SUCCESS == rv);
    104  }
    105  PrintProgress(__LINE__);
    106 
    107  did = should = PR_FALSE;
    108  for (keys = 0; keys < 4; ++keys) {
    109    rv = PR_SetThreadPrivate(key[keys], NULL);
    110    MY_ASSERT(PR_SUCCESS == rv);
    111  }
    112  PrintProgress(__LINE__);
    113 
    114  did = should = PR_FALSE;
    115  for (keys = 8; keys < 127; ++keys) {
    116    rv = PR_SetThreadPrivate(key[keys], "EXTENSION");
    117    MY_ASSERT(PR_SUCCESS == rv);
    118  }
    119  PrintProgress(__LINE__);
    120 
    121  did = PR_FALSE;
    122  should = PR_TRUE;
    123  for (keys = 8; keys < 127; ++keys) {
    124    rv = PR_SetThreadPrivate(key[keys], NULL);
    125    MY_ASSERT(PR_SUCCESS == rv);
    126  }
    127  PrintProgress(__LINE__);
    128 
    129  did = should = PR_FALSE;
    130  for (keys = 8; keys < 127; ++keys) {
    131    rv = PR_SetThreadPrivate(key[keys], NULL);
    132    MY_ASSERT(PR_SUCCESS == rv);
    133  }
    134 
    135  /* put in keys and leave them there for thread exit */
    136  did = should = PR_FALSE;
    137  for (keys = 0; keys < 4; ++keys) {
    138    rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
    139    MY_ASSERT(PR_SUCCESS == rv);
    140  }
    141  PrintProgress(__LINE__);
    142  did = PR_FALSE;
    143  should = PR_TRUE;
    144 
    145 } /* Thread */
    146 
    147 static PRIntn PR_CALLBACK Tpd(PRIntn argc, char** argv) {
    148  void* pd;
    149  PRStatus rv;
    150  PRUintn keys;
    151  PRThread* thread;
    152  char* key_string[] = {"Key #0",   "Key #1",   "Key #2",   "Key #3",
    153                        "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"};
    154 
    155  fout = PR_STDOUT;
    156 
    157  did = should = PR_FALSE;
    158  for (keys = 0; keys < 4; ++keys) {
    159    rv = PR_NewThreadPrivateIndex(&key[keys], Destructor);
    160    MY_ASSERT(PR_SUCCESS == rv);
    161  }
    162  PrintProgress(__LINE__);
    163 
    164  did = should = PR_FALSE;
    165  for (keys = 0; keys < 8; ++keys) {
    166    pd = PR_GetThreadPrivate(key[keys]);
    167    MY_ASSERT(NULL == pd);
    168  }
    169  PrintProgress(__LINE__);
    170 
    171  did = should = PR_FALSE;
    172  for (keys = 0; keys < 4; ++keys) {
    173    rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
    174    MY_ASSERT(PR_SUCCESS == rv);
    175  }
    176  PrintProgress(__LINE__);
    177 
    178  for (keys = 4; keys < 8; ++keys) {
    179    key[keys] = 4096; /* set to invalid value */
    180  }
    181  did = should = PR_FALSE;
    182  for (keys = 4; keys < 8; ++keys) {
    183    rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
    184    MY_ASSERT(PR_FAILURE == rv);
    185  }
    186  PrintProgress(__LINE__);
    187 
    188  did = PR_FALSE;
    189  should = PR_TRUE;
    190  for (keys = 0; keys < 4; ++keys) {
    191    rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
    192    MY_ASSERT(PR_SUCCESS == rv);
    193  }
    194  PrintProgress(__LINE__);
    195 
    196  did = PR_FALSE;
    197  should = PR_TRUE;
    198  for (keys = 0; keys < 4; ++keys) {
    199    rv = PR_SetThreadPrivate(key[keys], NULL);
    200    MY_ASSERT(PR_SUCCESS == rv);
    201  }
    202  PrintProgress(__LINE__);
    203 
    204  did = should = PR_FALSE;
    205  for (keys = 0; keys < 4; ++keys) {
    206    rv = PR_SetThreadPrivate(key[keys], NULL);
    207    MY_ASSERT(PR_SUCCESS == rv);
    208  }
    209  PrintProgress(__LINE__);
    210 
    211  did = should = PR_FALSE;
    212  for (keys = 8; keys < 127; ++keys) {
    213    rv = PR_NewThreadPrivateIndex(&key[keys], Destructor);
    214    MY_ASSERT(PR_SUCCESS == rv);
    215    rv = PR_SetThreadPrivate(key[keys], "EXTENSION");
    216    MY_ASSERT(PR_SUCCESS == rv);
    217  }
    218  PrintProgress(__LINE__);
    219 
    220  did = PR_FALSE;
    221  should = PR_TRUE;
    222  for (keys = 8; keys < 127; ++keys) {
    223    rv = PR_SetThreadPrivate(key[keys], NULL);
    224    MY_ASSERT(PR_SUCCESS == rv);
    225  }
    226  PrintProgress(__LINE__);
    227 
    228  did = should = PR_FALSE;
    229  for (keys = 8; keys < 127; ++keys) {
    230    rv = PR_SetThreadPrivate(key[keys], NULL);
    231    MY_ASSERT(PR_SUCCESS == rv);
    232  }
    233 
    234  thread = PR_CreateThread(PR_USER_THREAD, Thread, NULL, PR_PRIORITY_NORMAL,
    235                           PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
    236 
    237  (void)PR_JoinThread(thread);
    238 
    239  PrintProgress(__LINE__);
    240 
    241  (void)PR_fprintf(fout, "%s\n", ((PR_TRUE == failed) ? "FAILED" : "PASSED"));
    242 
    243  return 0;
    244 
    245 } /* Tpd */
    246 
    247 int main(int argc, char** argv) {
    248  PLOptStatus os;
    249  PLOptState* opt = PL_CreateOptState(argc, argv, "dl:r:");
    250  while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
    251    if (PL_OPT_BAD == os) {
    252      continue;
    253    }
    254    switch (opt->option) {
    255      case 'd': /* debug mode */
    256        debug = PR_TRUE;
    257        break;
    258      default:
    259        break;
    260    }
    261  }
    262  PL_DestroyOptState(opt);
    263  return PR_Initialize(Tpd, argc, argv, 0);
    264 } /* main */
    265 
    266 /* tpd.c */