home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / test / intltest / restest.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-19  |  19.5 KB  |  650 lines

  1. /*
  2. *****************************************************************************************
  3. *                                                                                       *
  4. * COPYRIGHT:                                                                            *
  5. *   (C) Copyright Taligent, Inc.,  1997                                                 *
  6. *   (C) Copyright International Business Machines Corporation,  1997-1998               *
  7. *   Licensed Material - Program-Property of IBM - All Rights Reserved.                  *
  8. *   US Government Users Restricted Rights - Use, duplication, or disclosure             *
  9. *   restricted by GSA ADP Schedule Contract with IBM Corp.                              *
  10. *                                                                                       *
  11. *****************************************************************************************
  12. */
  13.  
  14. #include "restest.h"
  15.  
  16. #include "resbund.h"
  17. #include "unistr.h"
  18.  
  19. #include <time.h>
  20. #include <string.h>
  21. #include <limits.h>
  22.  
  23. #define RESTEST_HEAP_CHECK 0
  24.  
  25. #if defined(_WIN32) && !defined(__WINDOWS__)
  26. #define _CRTDBG_MAP_ALLOC
  27. #include <crtdbg.h>
  28. #endif
  29.  
  30. //***************************************************************************************
  31.  
  32. const UnicodeString kERROR = "ERROR";
  33. const int32_t kERROR_COUNT = -1234567;
  34.  
  35. //***************************************************************************************
  36.  
  37. enum E_Where
  38. {
  39.     e_Default,
  40.     e_te,
  41.     e_te_IN,
  42.     e_Where_count
  43. };
  44.  
  45. //***************************************************************************************
  46.  
  47. #define CONFIRM_EQ(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); OUT << action << " returned " << (actual) << " instead of " << (expected) << endl; pass=FALSE; }
  48. #define CONFIRM_GE(actual,expected) if ((actual)>=(expected)) { record_pass(); } else { record_fail(); OUT << action << " returned " << (actual) << " instead of x >= " << (expected) << endl; pass=FALSE; }
  49. #define CONFIRM_NE(actual,expected) if ((expected)!=(actual)) { record_pass(); } else { record_fail(); OUT << action << " returned " << (actual) << " instead of x != " << (expected) << endl; pass=FALSE; }
  50.  
  51. #ifdef _DEBUG
  52. #define CONFIRM_UErrorCode(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); OUT << action << " returned " << errorName(actual) << " instead of " << errorName(expected) << endl; pass=FALSE; }
  53. #else
  54. #define CONFIRM_UErrorCode(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); OUT << action << " returned " << actual << " instead of " << expected << endl; pass=FALSE; }
  55. #endif
  56. //***************************************************************************************
  57.  
  58. /**
  59.  * Convert an integer, positive or negative, to a character string radix 10.
  60.  */
  61. char*
  62. itoa(int32_t i, char* buf)
  63. {
  64.     char* result = buf;
  65.  
  66.     // Handle negative
  67.     if (i < 0)
  68.     {
  69.         *buf++ = '-';
  70.         i = -i;
  71.     }
  72.  
  73.     // Output digits in reverse order
  74.     char* p = buf;
  75.     do
  76.     {
  77.         *p++ = '0' + (i % 10);
  78.         i /= 10;
  79.     }
  80.     while (i);
  81.     *p-- = 0;
  82.  
  83.     // Reverse the string
  84.     while (buf < p)
  85.     {
  86.         char c = *buf;
  87.         *buf++ = *p;
  88.         *p-- = c;
  89.     }
  90.  
  91.     return result;
  92. }
  93.  
  94.  
  95.  
  96. //***************************************************************************************
  97.  
  98. // Array of our test objects
  99.  
  100. struct
  101. {
  102.     const char* name;
  103.     Locale *locale;
  104.     UErrorCode expected_constructor_status;
  105.     E_Where where;
  106.     bool_t like[e_Where_count];
  107.     bool_t inherits[e_Where_count];
  108. }
  109. param[] =
  110. {
  111.     // "te" means test
  112.     // "IN" means inherits
  113.     // "NE" or "ne" means "does not exist"
  114.  
  115.     { "default",       0,      U_ZERO_ERROR,             e_Default,      { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } },
  116.     { "te",            0,      U_ZERO_ERROR,             e_te,           { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE } },
  117.     { "te_IN",         0,      U_ZERO_ERROR,             e_te_IN,        { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE } },
  118.     { "te_NE",         0,      U_USING_FALLBACK_ERROR,   e_te,           { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE } },
  119.     { "te_IN_NE",      0,      U_USING_FALLBACK_ERROR,   e_te_IN,        { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE } },
  120.     { "ne",            0,      U_USING_DEFAULT_ERROR,    e_Default,      { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } }
  121. };
  122.  
  123. int32_t bundles_count = sizeof(param) / sizeof(param[0]);
  124.  
  125. //***************************************************************************************
  126.  
  127. /**
  128.  * Return a random unsigned long l where 0N <= l <= ULONG_MAX.
  129.  */
  130.  
  131. uint32_t
  132. randul()
  133. {
  134.     static bool_t initialized = FALSE;
  135.     if (!initialized)
  136.     {
  137.         srand((unsigned)time(NULL));
  138.         initialized = TRUE;
  139.     }
  140.     // Assume rand has at least 12 bits of precision
  141.     uint32_t l;
  142.     for (int32_t i=0; i<sizeof(l); ++i) ((char*)&l)[i] = (rand() & 0x0FF0) >> 4;
  143.     return l;
  144. }
  145.  
  146. /**
  147.  * Return a random double x where 0.0 <= x < 1.0.
  148.  */
  149. double
  150. randd()
  151. {
  152.     return ((double)randul()) / ULONG_MAX;
  153. }
  154.  
  155. /**
  156.  * Return a random integer i where 0 <= i < n.
  157.  */
  158. int32_t randi(int32_t n)
  159. {
  160.     return (int32_t)(randd() * n);
  161. }
  162.  
  163. //***************************************************************************************
  164.  
  165. ResourceBundleTest::ResourceBundleTest()
  166. : pass(0),
  167.   fail(0),
  168.   OUT(it_out)
  169. {
  170.     param[0].locale = new Locale("default");
  171.     param[1].locale = new Locale("te");
  172.     param[2].locale = new Locale("te", "IN");
  173.     param[3].locale = new Locale("te", "NE");
  174.     param[4].locale = new Locale("te", "IN", "NE");
  175.     param[5].locale = new Locale("ne");
  176. }
  177.  
  178. ResourceBundleTest::~ResourceBundleTest()
  179. {
  180. }
  181.  
  182. void ResourceBundleTest::runIndexedTest( int32_t index, bool_t exec, char* &name, char* par )
  183. {
  184.     if (exec) logln("TestSuite ResourceBundleTest: ");
  185.     switch (index) {
  186.     case 0: name = "TestResourceBundles"; if (exec) TestResourceBundles(); break;
  187.     case 1: name = "TestConstruction"; if (exec) TestConstruction(); break;
  188.  
  189.         default: name = ""; break; //needed to end loop
  190.     }
  191. }
  192.  
  193. //***************************************************************************************
  194.  
  195. void
  196. ResourceBundleTest::TestResourceBundles()
  197. {
  198. #if defined(_WIN32) && !defined(__WINDOWS__)
  199. #if defined(_DEBUG) && RESTEST_HEAP_CHECK
  200.     /*
  201.      * Set the debug-heap flag to keep freed blocks in the
  202.      * heap's linked list - This will allow us to catch any
  203.      * inadvertent use of freed memory
  204.      */
  205.     int tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
  206.     tmpDbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
  207.     tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF;
  208.     tmpDbgFlag |= _CRTDBG_CHECK_ALWAYS_DF;
  209.     _CrtSetDbgFlag(tmpDbgFlag);
  210.  
  211.     _CrtMemState memstate;
  212.     _CrtMemCheckpoint(&memstate);
  213.     {
  214. #endif
  215. #endif
  216.  
  217.     testTag("only_in_Default", TRUE, FALSE, FALSE);
  218.     testTag("only_in_te", FALSE, TRUE, FALSE);
  219.     testTag("only_in_te_IN", FALSE, FALSE, TRUE);
  220.     testTag("in_Default_te", TRUE, TRUE, FALSE);
  221.     testTag("in_Default_te_te_IN", TRUE, TRUE, TRUE);
  222.     testTag("in_Default_te_IN", TRUE, FALSE, TRUE);
  223.     testTag("in_te_te_IN", FALSE, TRUE, TRUE);
  224.     testTag("nonexistent", FALSE, FALSE, FALSE);
  225.     OUT << "Passed: " << pass << "\nFailed: " << fail << endl;
  226.  
  227. #if defined(_WIN32) && !defined(__WINDOWS__)
  228. #if defined(_DEBUG) && RESTEST_HEAP_CHECK
  229.     }
  230.     _CrtMemDumpAllObjectsSince(&memstate);
  231.  
  232.     /*
  233.      * Set the debug-heap flag to keep freed blocks in the
  234.      * heap's linked list - This will allow us to catch any
  235.      * inadvertent use of freed memory
  236.      */
  237.     tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
  238.     tmpDbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
  239.     tmpDbgFlag &= ~_CRTDBG_LEAK_CHECK_DF;
  240.     tmpDbgFlag &= ~_CRTDBG_CHECK_ALWAYS_DF;
  241.     _CrtSetDbgFlag(tmpDbgFlag);
  242. #endif
  243. #endif
  244. }
  245.  
  246. void
  247. ResourceBundleTest::TestConstruction()
  248. {
  249.     {
  250.         UErrorCode   err = U_ZERO_ERROR;
  251.         const char   *directory;
  252.         Locale       locale("te", "IN");
  253.  
  254.         directory=IntlTest::getTestDirectory();
  255.  
  256.         ResourceBundle  test1(directory, err);
  257.         ResourceBundle  test2(directory, locale, err);
  258.  
  259.         UnicodeString   result1;
  260.         UnicodeString   result2;
  261.  
  262.         test1.getString("string_in_Default_te_te_IN", result1, err);
  263.         test2.getString("string_in_Default_te_te_IN", result2, err);
  264.  
  265.         if (U_FAILURE(err)) {
  266.             errln("Something threw an error in TestConstruction()");
  267.             return;
  268.         }
  269.  
  270.         logln("for string_in_Default_te_te_IN, default.txt had " + result1);
  271.         logln("for string_in_Default_te_te_IN, te_IN.txt had " + result2);
  272.  
  273.         if (result1 != "DEFAULT" || result2 != "TE_IN")
  274.             errln("Construction test failed; run verbose for more information");
  275.  
  276.         const char* version1;
  277.         const char* version2;
  278.  
  279.         version1 = test1.getVersionNumber();
  280.         version2 = test2.getVersionNumber();
  281.  
  282.         char *versionID1 = new char[1 + strlen(ICU_VERSION) + strlen(version1)]; // + 1 for zero byte
  283.         char *versionID2 = new char[1 + strlen(ICU_VERSION) + strlen(version2)]; // + 1 for zero byte
  284.  
  285.         strcpy(versionID1, ICU_VERSION);
  286.         strcat(versionID1, ".44");  // hardcoded, please change if the default.txt file or ResourceBundle::kVersionSeparater is changed.
  287.  
  288.         strcpy(versionID2, ICU_VERSION);
  289.         strcat(versionID2, ".55");  // hardcoded, please change if the te_IN.txt file or ResourceBundle::kVersionSeparater is changed.
  290.  
  291.         logln(UnicodeString("getVersionNumber on default.txt returned ") + version1);
  292.         logln(UnicodeString("getVersionNumber on te_IN.txt returned ") + version2);
  293.  
  294.         if (strcmp(version1, versionID1) != 0 || strcmp(version2, versionID2) != 0)
  295.             errln("getVersionNumber() failed");
  296.     }
  297.     {
  298.         UErrorCode   err = U_ZERO_ERROR;
  299.         const char   *directory;
  300.         Locale       locale("te", "IN");
  301.  
  302.         directory=IntlTest::getTestDirectory();
  303.  
  304.  
  305.         wchar_t* wideDirectory = new wchar_t[256];
  306.         mbstowcs(wideDirectory, directory, 256);
  307.  
  308.         ResourceBundle  test2(wideDirectory, locale, err);
  309.  
  310.         UnicodeString   result2;
  311.  
  312.         test2.getString("string_in_Default_te_te_IN", result2, err);
  313.  
  314.         if (U_FAILURE(err)) {
  315.             errln("Something threw an error in TestConstruction()");
  316.             return;
  317.         }
  318.  
  319.         logln("for string_in_Default_te_te_IN, te_IN.txt had " + result2);
  320.  
  321.         if (result2 != "TE_IN")
  322.             errln("Construction test failed; run verbose for more information");
  323.     }
  324. }
  325.  
  326. //***************************************************************************************
  327.  
  328. bool_t
  329. ResourceBundleTest::testTag(const char* frag,
  330.                             bool_t in_Default,
  331.                             bool_t in_te,
  332.                             bool_t in_te_IN)
  333. {
  334.     bool_t pass=TRUE;
  335.  
  336.     // Make array from input params
  337.  
  338.     bool_t is_in[] = { in_Default, in_te, in_te_IN };
  339.  
  340.     const char* NAME[] = { "DEFAULT", "TE", "TE_IN" };
  341.  
  342.     // Now try to load the desired items
  343.  
  344.     UnicodeString tag;
  345.     UnicodeString action;
  346.  
  347.     int32_t i,j,row,col, actual_bundle;
  348.     int32_t index;
  349.     const char *directory;
  350.  
  351.     directory=IntlTest::getTestDirectory();
  352.  
  353.         for (i=0; i<bundles_count; ++i)
  354.     {
  355.         action = "Constructor for ";
  356.         action += param[i].name;
  357.  
  358.         UErrorCode status = U_ZERO_ERROR;
  359.         ResourceBundle theBundle( directory, *param[i].locale, status);
  360.         CONFIRM_UErrorCode(status,param[i].expected_constructor_status);
  361.  
  362.     if(i == 5)
  363.       actual_bundle = 0; /* ne -> default */
  364.     else if(i == 3)
  365.       actual_bundle = 1; /* te_NE -> te */
  366.     else if(i == 4)
  367.       actual_bundle = 2; /* te_IN_NE -> te_IN */
  368.     else
  369.       actual_bundle = i;
  370.  
  371.  
  372.         UErrorCode expected_resource_status = U_MISSING_RESOURCE_ERROR;
  373.         for (j=e_te_IN; j>=e_Default; --j)
  374.         {
  375.             if (is_in[j] && param[i].inherits[j])
  376.           {
  377.         if(j == actual_bundle) /* it's in the same bundle OR it's a nonexistent=default bundle (5) */
  378.           expected_resource_status = U_ZERO_ERROR;
  379.         else if(j == 0)
  380.           expected_resource_status = U_USING_DEFAULT_ERROR;
  381.         else
  382.           expected_resource_status = U_USING_FALLBACK_ERROR;
  383.         
  384.                 break;
  385.             }
  386.         }
  387.  
  388.         UErrorCode expected_status;
  389.  
  390.         UnicodeString base;
  391.         for (j=param[i].where; j>=0; --j)
  392.         {
  393.             if (is_in[j])
  394.             {
  395.                 base = NAME[j];
  396.                 break;
  397.             }
  398.         }
  399.  
  400.         //--------------------------------------------------------------------------
  401.         // string
  402.  
  403.         action = param[i].name;
  404.         action += ".getString(";
  405.         action += tag;
  406.         action += ")";
  407.  
  408.         tag = "string_";
  409.         tag += frag;
  410.  
  411.         UnicodeString string(kERROR);
  412.         status = U_ZERO_ERROR;
  413.         theBundle.getString(tag, string, status);
  414.  
  415.         CONFIRM_UErrorCode(status, expected_resource_status);
  416.  
  417.         UnicodeString expected_string;
  418.         expected_string = U_SUCCESS(status) ? base : kERROR;
  419.  
  420.         CONFIRM_EQ(string, expected_string);
  421.  
  422.         //--------------------------------------------------------------------------
  423.         // array
  424.  
  425.         action = param[i].name;
  426.         action += ".getStringArray(";
  427.         action += tag;
  428.         action += ")";
  429.  
  430.         tag = "array_";
  431.         tag += frag;
  432.  
  433.         int32_t count = kERROR_COUNT;
  434.         status = U_ZERO_ERROR;
  435.         const UnicodeString* array = theBundle.getStringArray(tag, count, status);
  436.         CONFIRM_UErrorCode(status,expected_resource_status);
  437.  
  438.         if (U_SUCCESS(status))
  439.         {
  440.             CONFIRM_GE(count,1);
  441.             CONFIRM_NE((int32_t)array,(int32_t)0);
  442.  
  443.             for (j=0; j<count; ++j)
  444.             {
  445.                 char buf[32];
  446.                 expected_string = base;
  447.                 expected_string += itoa(j,buf);
  448.                 CONFIRM_EQ(array[j],expected_string);
  449.             }
  450.         }
  451.         else
  452.         {
  453.             CONFIRM_EQ(count,kERROR_COUNT);
  454.             CONFIRM_EQ((int32_t)array,(int32_t)0);
  455.             count = 0;
  456.         }
  457.  
  458.         //--------------------------------------------------------------------------
  459.         // arrayItem
  460.  
  461.         action = param[i].name;
  462.         action += ".getArrayItem(";
  463.         action += tag;
  464.         action += ")";
  465.  
  466.         for (j=0; j<100; ++j)
  467.         {
  468.             index = count ? (randi(count * 3) - count) : (randi(200) - 100);
  469.             status = U_ZERO_ERROR;
  470.             string = kERROR;
  471.             theBundle.getArrayItem(tag, index, string, status);
  472.             expected_status = (index >= 0 && index < count) ? expected_resource_status : U_MISSING_RESOURCE_ERROR;
  473.             CONFIRM_UErrorCode(status,expected_status);
  474.  
  475.             if (U_SUCCESS(status))
  476.             {
  477.                 char buf[32];
  478.                 expected_string = base;
  479.                 expected_string += itoa(index,buf);
  480.             }
  481.             else
  482.             {
  483.                 expected_string = kERROR;
  484.             }
  485.             CONFIRM_EQ(string,expected_string);
  486.         }
  487.  
  488.         //--------------------------------------------------------------------------
  489.         // 2dArray
  490.  
  491.         action = param[i].name;
  492.         action += ".get2dArray(";
  493.         action += tag;
  494.         action += ")";
  495.  
  496.         tag = "array_2d_";
  497.         tag += frag;
  498.  
  499.         int32_t row_count = kERROR_COUNT, column_count = kERROR_COUNT;
  500.         status = U_ZERO_ERROR;
  501.         const UnicodeString** array2d = theBundle.get2dArray(tag, row_count, column_count, status);
  502.         CONFIRM_UErrorCode(status,expected_resource_status);
  503.  
  504.         if (U_SUCCESS(status))
  505.         {
  506.             CONFIRM_GE(row_count,1);
  507.             CONFIRM_GE(column_count,(int32_t)0);
  508.             CONFIRM_NE((int32_t)array,(int32_t)0);
  509.  
  510.             for (row=0; row<row_count; ++row)
  511.             {
  512.                 for (col=0; col<column_count; ++col)
  513.                 {
  514.                     char buf[32];
  515.                     expected_string = base;
  516.                     expected_string += itoa(row,buf);
  517.                     expected_string += itoa(col,buf);
  518.                     CONFIRM_EQ(array2d[row][col],expected_string);
  519.                 }
  520.             }
  521.         }
  522.         else
  523.         {
  524.             CONFIRM_EQ(row_count,kERROR_COUNT);
  525.             CONFIRM_EQ(column_count,kERROR_COUNT);
  526.             CONFIRM_EQ((int32_t)array,(int32_t)0);
  527.             row_count = column_count = 0;
  528.         }
  529.  
  530.         //--------------------------------------------------------------------------
  531.         // 2dArrayItem
  532.  
  533.         action = param[i].name;
  534.         action += ".get2dArrayItem(";
  535.         action += tag;
  536.         action += ")";
  537.  
  538.         for (j=0; j<200; ++j)
  539.         {
  540.             row = row_count ? (randi(row_count * 3) - row_count) : (randi(200) - 100);
  541.             col = column_count ? (randi(column_count * 3) - column_count) : (randi(200) - 100);
  542.             status = U_ZERO_ERROR;
  543.             string = kERROR;
  544.             theBundle.get2dArrayItem(tag, row, col, string, status);
  545.             expected_status = (row >= 0 && row < row_count && col >= 0 && col < column_count) ?
  546.           expected_resource_status: U_MISSING_RESOURCE_ERROR;
  547.             CONFIRM_UErrorCode(status,expected_status);
  548.  
  549.             if (U_SUCCESS(status))
  550.             {
  551.                 char buf[32];
  552.                 expected_string = base;
  553.                 expected_string += itoa(row,buf);
  554.                 expected_string += itoa(col,buf);
  555.             }
  556.             else
  557.             {
  558.                 expected_string = kERROR;
  559.             }
  560.             CONFIRM_EQ(string,expected_string);
  561.         }
  562.  
  563.         //--------------------------------------------------------------------------
  564.         // taggedArrayItem
  565.  
  566.         tag = "tagged_array_";
  567.         tag += frag;
  568.  
  569.         action = param[i].name;
  570.         action += ".getTaggedArray(";
  571.         action += tag;
  572.         action += ")";
  573.  
  574.         UnicodeString*  tags = 0;
  575.         UnicodeString*  items = 0;
  576.         int32_t         expected_count;
  577.  
  578.         status = U_ZERO_ERROR;
  579.  
  580.         theBundle.getTaggedArray(tag, tags, items, expected_count, status);
  581.         CONFIRM_UErrorCode(status, expected_resource_status);
  582.  
  583.         if (U_SUCCESS(status)) {
  584.             CONFIRM_GE((int32_t)expected_count, (int32_t)0);
  585.             CONFIRM_NE((int32_t)tags, (int32_t)0);
  586.             CONFIRM_NE((int32_t)items, (int32_t)0);
  587.  
  588.             for (index = 0; index < expected_count; index++) {
  589.                 logln("tag = " + tags[index] + ", value = " + items[index]);
  590.                 if (tags[index].startsWith("tag") && items[index].startsWith(base))
  591.                     record_pass();
  592.                 else
  593.                     record_fail();
  594.             }
  595.         }
  596.         else
  597.             expected_count = 0;
  598.         delete [] tags;
  599.         delete [] items;
  600.  
  601.         //--------------------------------------------------------------------------
  602.         // taggedArrayItem
  603.  
  604.         action = param[i].name;
  605.         action += ".getTaggedArrayItem(";
  606.         action += tag;
  607.         action += ")";
  608.  
  609.         count = 0;
  610.         for (index=-20; index<20; ++index)
  611.         {
  612.             char buf[32];
  613.             UnicodeString item_tag("tag");
  614.             item_tag += itoa(index,buf);
  615.  
  616.             status = U_ZERO_ERROR;
  617.             string = kERROR;
  618.             theBundle.getTaggedArrayItem(tag,item_tag,string,status);
  619.             if (index < 0)
  620.             {
  621.                 CONFIRM_UErrorCode(status,U_MISSING_RESOURCE_ERROR);
  622.             }
  623.             else
  624.             {
  625.                 if (status != U_MISSING_RESOURCE_ERROR) {
  626.                     count++;
  627.                     expected_string = base;
  628.                     expected_string += buf;
  629.                     CONFIRM_EQ(string,expected_string);
  630.                 }
  631.             }
  632.         }
  633.         CONFIRM_EQ(count, expected_count);
  634.     }
  635.     return pass;
  636. }
  637.  
  638. void
  639. ResourceBundleTest::record_pass()
  640. {
  641.   ++pass;
  642. }
  643. void
  644. ResourceBundleTest::record_fail()
  645. {
  646.   err();
  647.   ++fail;
  648. }
  649. //eof
  650.