Back to index

lightning-sunbird  0.9+nobinonly
test_main.cpp
Go to the documentation of this file.
00001 #include <iostream.h>
00002 #include "nsStringIO.h"
00003 
00004 //#define TEST_STD_STRING
00005 
00006 
00007 #include "nsString.h"
00008 #include "nsFragmentedString.h"
00009 #include "nsReadableUtils.h"
00010 #include "nsSlidingString.h"
00011 
00012 #ifdef TEST_STD_STRING
00013 #include "nsStdStringWrapper.h"
00014 #else
00015   typedef nsString nsStdString;
00016   typedef nsCString nsStdCString;
00017 #endif
00018 
00019 template <class CharT>
00020 basic_nsLiteralString<CharT>
00021 literal_hello( CharT* )
00022   {
00023   }
00024 
00025 NS_SPECIALIZE_TEMPLATE
00026 basic_nsLiteralString<char>
00027 literal_hello( char* )
00028   {
00029     return basic_nsLiteralString<char>("Hello");
00030   }
00031 
00032 NS_SPECIALIZE_TEMPLATE
00033 basic_nsLiteralString<PRUnichar>
00034 literal_hello( PRUnichar* )
00035   {
00036 #ifdef HAVE_CPP_2BYTE_WCHAR_T
00037     return basic_nsLiteralString<PRUnichar>(L"Hello");
00038 #else
00039     static PRUnichar constant_unicode[] = { 'H', 'e', 'l', 'l', 'o', PRUnichar() };
00040     return basic_nsLiteralString<PRUnichar>(constant_unicode);
00041 #endif
00042   }
00043 
00044 template <class T>
00045 struct string_class_traits
00046   {
00047   };
00048 
00049 NS_SPECIALIZE_TEMPLATE
00050 struct string_class_traits<PRUnichar>
00051   {
00052     typedef PRUnichar* pointer;
00053     typedef nsString implementation_t;
00054     
00055     static basic_nsLiteralString<PRUnichar> literal_hello() { return ::literal_hello(pointer()); }
00056   };
00057 
00058 NS_SPECIALIZE_TEMPLATE
00059 struct string_class_traits<char>
00060   {
00061     typedef char* pointer;
00062     typedef nsCString implementation_t;
00063     
00064     static basic_nsLiteralString<char> literal_hello() { return ::literal_hello(pointer()); }
00065   };
00066 
00067 
00068 static
00069 void
00070 CallCMid( nsACString& aResult, const nsACString& aSource, PRUint32 aStartPos, PRUint32 aLengthToCopy )
00071   {
00072     aSource.Mid(aResult, aStartPos, aLengthToCopy);
00073   }
00074 
00075 
00076 
00077 template <class CharT>
00078 int
00079 test_multifragment_iterators( const basic_nsAString<CharT>& aString )
00080     /*
00081       ...this tests a problem that was present in |nsPromiseConcatenation| where,
00082       because it originally stored some iteration state in the object itself, rather than
00083       in the fragment, the iterators could get confused if used out of sequence.
00084 
00085       This test should be run on any multi-fragment implementation to verify that it
00086       does not have the same bug.  Make sure the first fragment is only one character long.
00087     */
00088   {
00089     typedef typename basic_nsAString<CharT>::const_iterator ConstIterator;
00090 
00091     int tests_failed = 0;
00092 
00093     ConstIterator iter1 = aString.BeginReading();
00094     ConstIterator iter2 = aString.BeginReading();
00095     ++iter2; ++iter2;
00096 
00097     ConstIterator iter3 = aString.EndReading();
00098     --iter3;
00099     ++iter1; ++iter1;
00100     if ( iter1 != iter2 )
00101       {
00102         cout << "FAILED in |test_multifragment_iterators|" << endl;
00103         ++tests_failed;
00104       }
00105 
00106     return tests_failed;
00107   }
00108 
00109 template <class CharT>
00110 int
00111 test_Vidur_functions( const basic_nsAString<CharT>& aString )
00112   {
00113     char* char_copy = ToNewCString(aString);
00114     PRUnichar* PRUnichar_copy = ToNewUnicode(aString);
00115 
00116     nsMemory::Free(PRUnichar_copy);
00117     nsMemory::Free(char_copy);
00118 
00119     return 0;
00120   }
00121 
00122 template <class CharT>
00123 int
00124 test_readable_hello( const basic_nsAString<CharT>& aReadable )
00125   {
00126     int tests_failed = 0;
00127 
00128     if ( aReadable.Length() != 5 )
00129       {
00130         cout << "FAILED |test_readable_hello|: |Length()| --> " << aReadable.Length() << endl;
00131         ++tests_failed;
00132       }
00133 
00134     if ( aReadable.First() != CharT('H') )
00135       {
00136         cout << "FAILED |test_readable_hello|: |First()| --> '" << aReadable.First() << "'" << endl;
00137         ++tests_failed;
00138       }
00139 
00140     if ( aReadable.Last() != CharT('o') )
00141       {
00142         cout << "FAILED |test_readable_hello|: |Last()| --> '" << aReadable.Last() << "'" << endl;
00143         ++tests_failed;
00144       }
00145 
00146     if ( aReadable[3] != CharT('l') )
00147       {
00148         cout << "FAILED |test_readable_hello|: |operator[]| --> '" << aReadable[3] << "'" << endl;
00149         ++tests_failed;
00150       }
00151 
00152     if ( aReadable.CountChar( CharT('l') ) != 2 )
00153       {
00154         cout << "FAILED |test_readable_hello|: |CountChar('l')| --> " << aReadable.CountChar(CharT('l')) << endl;
00155         ++tests_failed;
00156       }
00157 
00158     basic_nsAString<CharT>::const_iterator iter = aReadable.BeginReading();
00159     if ( *iter != CharT('H') )
00160       {
00161         cout << "FAILED |test_readable_hello|: didn't start out pointing to the right thing, or else couldn't be dereferenced. --> '" << *iter << "'" << endl;
00162         ++tests_failed;
00163       }
00164 
00165     ++iter;
00166 
00167     if ( *iter != CharT('e') )
00168       {
00169         cout << "FAILED |test_readable_hello|: iterator couldn't be incremented, or else couldn't be dereferenced. --> '" << *iter << "'" << endl;
00170         ++tests_failed;
00171       }
00172 
00173     iter = aReadable.EndReading();
00174     --iter;
00175     if ( *iter != CharT('o') )
00176       {
00177         cout << "FAILED |test_readable_hello|: iterator couldn't be set to |EndReading()|, or else couldn't be decremented, or else couldn't be dereferenced. --> '" << *iter << "'" << endl;
00178         ++tests_failed;
00179       }
00180 
00181     basic_nsAString<CharT>::const_iterator iter1 = aReadable.BeginReading().advance(3);
00182     if ( *iter1 != CharT('l') )
00183       {
00184         cout << "FAILED |test_readable_hello|: iterator couldn't be set to |BeginReading()+=n|, or else couldn't be dereferenced. --> '" << *iter1 << "'" << endl;
00185         ++tests_failed;
00186       }
00187 
00188     basic_nsAString<CharT>::const_iterator iter2 = aReadable.EndReading().advance(-2);
00189     if ( *iter2 != CharT('l') )
00190       {
00191         cout << "FAILED |test_readable_hello|: iterator couldn't be set to |EndReading()-=n|, or else couldn't be dereferenced. --> '" << *iter2 << "'" << endl;
00192         ++tests_failed;
00193       }
00194 
00195     if ( iter1 != iter2 )
00196       {
00197         cout << "FAILED |test_readable_hello|: iterator comparison with !=." << endl;
00198         ++tests_failed;
00199       }
00200 
00201     if ( !(iter1 == iter2) )
00202       {
00203         cout << "FAILED |test_readable_hello|: iterator comparison with ==." << endl;
00204         ++tests_failed;
00205       }
00206 
00207     typedef CharT* CharT_ptr;
00208     if ( aReadable != literal_hello(CharT_ptr()) )
00209       {
00210         cout << "FAILED |test_readable_hello|: comparison with \"Hello\"" << endl;
00211         ++tests_failed;
00212       }
00213 
00214     tests_failed += test_multifragment_iterators(aReadable);
00215     // tests_failed += test_deprecated_GetBufferGetUnicode(aReadable);
00216 
00217     test_Vidur_functions(aReadable);
00218 
00219     return tests_failed;
00220   }
00221 
00222 
00223 template <class CharT>
00224 int
00225 test_SetLength( basic_nsAString<CharT>& aWritable )
00226   {
00227     int tests_failed = 0;
00228 
00229     string_class_traits<CharT>::implementation_t oldValue(aWritable);
00230 
00231 
00232     size_t oldLength = aWritable.Length();
00233 
00234     if ( oldValue != Substring(aWritable, 0, oldLength) )
00235       {
00236         cout << "FAILED growing a string in |test_SetLength|, saving the value didn't work." << endl;
00237         ++tests_failed;
00238       }
00239 
00240     size_t newLength = 2*(oldLength+1);
00241 
00242     aWritable.SetLength(newLength);
00243     if ( aWritable.Length() != newLength )
00244       {
00245         cout << "FAILED growing a string in |test_SetLength|, length is wrong." << endl;
00246         ++tests_failed;
00247       }
00248 
00249     if ( oldValue != Substring(aWritable, 0, oldLength) )
00250       {
00251         cout << "FAILED growing a string in |test_SetLength|, contents damaged after growing." << endl;
00252         ++tests_failed;
00253       }
00254 
00255     aWritable.SetLength(oldLength);
00256     if ( aWritable.Length() != oldLength )
00257       {
00258         cout << "FAILED shrinking a string in |test_SetLength|." << endl;
00259         ++tests_failed;
00260       }
00261 
00262     if ( oldValue != Substring(aWritable, 0, oldLength) )
00263       {
00264         cout << "FAILED growing a string in |test_SetLength|, contents damaged after shrinking." << endl;
00265         ++tests_failed;
00266       }
00267 
00268     return tests_failed;
00269   }
00270 
00271 
00272 template <class CharT>
00273 int
00274 test_insert( basic_nsAString<CharT>& aWritable )
00275   {
00276     int tests_failed = 0;
00277 
00278     string_class_traits<CharT>::implementation_t oldValue(aWritable);
00279 
00280     if ( oldValue != aWritable )
00281       {
00282         cout << "FAILED saving the old string value in |test_insert|." << endl;
00283         ++tests_failed;
00284       }
00285 
00286     string_class_traits<CharT>::implementation_t insertable( string_class_traits<CharT>::literal_hello() );
00287 
00288     insertable.SetLength(1);
00289     aWritable.Insert(insertable, 0);
00290 
00291     if ( aWritable != (insertable + oldValue) )
00292       {
00293         cout << "FAILED in |test_insert|." << endl;
00294         ++tests_failed;
00295       }
00296 
00297     aWritable = oldValue;
00298 
00299     return tests_failed;
00300   }
00301 
00302 
00303 template <class CharT>
00304 int
00305 test_cut( basic_nsAString<CharT>& aWritable )
00306   {
00307     int tests_failed = 0;
00308 
00309     aWritable.Cut(0, aWritable.Length()+5);
00310 
00311     return tests_failed;
00312   }
00313 
00314 template <class CharT>
00315 int
00316 test_self_assign( basic_nsAString<CharT>& aWritable )
00317   {
00318     int tests_failed = 0;
00319     string_class_traits<CharT>::implementation_t oldValue(aWritable);
00320 
00321     aWritable = aWritable;
00322     if ( aWritable != oldValue )
00323       {
00324         cout << "FAILED self assignment." << endl;
00325         ++tests_failed;
00326       }
00327 
00328     aWritable = oldValue;
00329     return tests_failed;
00330   }
00331 
00332 template <class CharT>
00333 int
00334 test_self_append( basic_nsAString<CharT>& aWritable )
00335   {
00336     int tests_failed = 0;
00337     string_class_traits<CharT>::implementation_t oldValue(aWritable);
00338 
00339     aWritable += aWritable;
00340     if ( aWritable != oldValue + oldValue )
00341       {
00342         cout << "FAILED self append." << endl;
00343         ++tests_failed;
00344       }
00345 
00346     aWritable = oldValue;
00347     return tests_failed;
00348   }
00349 
00350 template <class CharT>
00351 int
00352 test_self_insert( basic_nsAString<CharT>& aWritable )
00353   {
00354     int tests_failed = 0;
00355     string_class_traits<CharT>::implementation_t oldValue(aWritable);
00356 
00357     aWritable.Insert(aWritable, 0);
00358     if ( aWritable != oldValue + oldValue )
00359       {
00360         cout << "FAILED self insert." << endl;
00361         ++tests_failed;
00362       }
00363 
00364     aWritable = oldValue;
00365     return tests_failed;
00366   }
00367 
00368 template <class CharT>
00369 int
00370 test_self_replace( basic_nsAString<CharT>& aWritable )
00371   {
00372     int tests_failed = 0;
00373     string_class_traits<CharT>::implementation_t oldValue(aWritable);
00374 
00375     aWritable.Replace(0, 0, aWritable);
00376     if ( aWritable != oldValue + oldValue )
00377       {
00378         cout << "FAILED self insert." << endl;
00379         ++tests_failed;
00380       }
00381 
00382     aWritable = oldValue;
00383     return tests_failed;
00384   }
00385 
00386 
00387 
00388 template <class CharT>
00389 int
00390 test_writable( basic_nsAString<CharT>& aWritable )
00391   {
00392     int tests_failed = 0;
00393     // ...
00394 
00395 
00396     {
00397       typedef CharT* CharT_ptr;
00398       aWritable = literal_hello(CharT_ptr());
00399 
00400       if ( aWritable != literal_hello(CharT_ptr()) )
00401         {
00402           cout << "FAILED assignment and/or comparison in |test_writable|." << endl;
00403           ++tests_failed;
00404         }
00405 
00406       tests_failed += test_readable_hello(aWritable);
00407     }
00408 
00409     tests_failed += test_SetLength(aWritable);
00410     tests_failed += test_insert(aWritable);
00411     tests_failed += test_cut(aWritable);
00412     tests_failed += test_self_assign(aWritable);
00413     tests_failed += test_self_append(aWritable);
00414     tests_failed += test_self_insert(aWritable);
00415     tests_failed += test_self_replace(aWritable);
00416 
00417     return tests_failed;
00418   }
00419 
00420 
00421 
00422 typedef void* void_ptr;
00423 
00424 int
00425 main()
00426   {    
00427     int tests_failed = 0;
00428        cout << "String unit tests.  Compiled " __DATE__ " " __TIME__ << endl;
00429 
00430 #if 0
00431     {
00432       nsFragmentedCString fs0;
00433       fs0.Append("Hello");
00434       tests_failed += test_readable_hello(fs0);
00435       tests_failed += test_writable(fs0);
00436     }
00437 #endif
00438 
00439     {
00440       NS_NAMED_LITERAL_STRING(literal, "Hello");
00441       PRUnichar* buffer = ToNewUnicode(literal);
00442 
00443       nsSlidingString ss0(buffer, buffer+5, buffer+6);
00444 //    ss0.AppendBuffer(buffer, buffer+5, buffer+6);
00445       nsReadingIterator<PRUnichar> ri0;
00446       ss0.BeginReading(ri0);
00447 
00448       tests_failed += test_readable_hello(ss0);
00449 
00450       nsSlidingSubstring ss1(ss0);
00451       tests_failed += test_readable_hello(ss1);
00452 
00453       buffer = ToNewUnicode(literal);
00454       ss0.AppendBuffer(buffer, buffer+5, buffer+6);
00455 
00456       ri0.advance(5);
00457       ss0.DiscardPrefix(ri0);
00458 
00459       tests_failed += test_readable_hello(ss0);
00460       tests_failed += test_readable_hello(ss1);
00461 
00462       nsReadingIterator<PRUnichar> ri1;
00463       ss0.EndReading(ri1);
00464 
00465       nsSlidingSubstring ss2(ss0, ri0, ri1);
00466       tests_failed += test_readable_hello(ss2);
00467     }
00468 
00469 
00470     {
00471       nsLiteralCString s0("Patrick Beard made me write this: \"This is just a test\"\n");
00472       print_string(s0);
00473 
00474       const char* raw_string = "He also made me write this.\n";
00475       nsFileCharSink<char> output(stdout);
00476       copy_string(raw_string, raw_string+nsCharTraits<char>::length(raw_string), output);
00477 
00478       nsLiteralCString s1("This ", 5), s2("is ", 3), s3("a ", 2), s4("test\n", 5);
00479       print_string(s1+s2+s3+s4);
00480 
00481       nsLiteralCString s5( "This is " "a " "test" );
00482       print_string(s5+NS_LITERAL_CSTRING("\n"));
00483 
00484       print_string(nsLiteralCString("The value of the string |x| is \"") + Substring(s0, 0, s0.Length()-1) + NS_LITERAL_CSTRING("\".  Hope you liked it."));
00485     }
00486 
00487 
00488     {
00489       tests_failed += test_readable_hello(NS_LITERAL_STRING("Hello"));
00490 
00491       nsLiteralCString s1("Hello");
00492       tests_failed += test_readable_hello(s1);
00493     }
00494 
00495     {
00496 
00497       nsString s3( NS_LITERAL_STRING("Hello") );
00498 
00499       tests_failed += test_readable_hello(s3);
00500       tests_failed += test_writable(s3);
00501 
00502       nsCString s4("Hello");
00503       tests_failed += test_readable_hello(s4);
00504       tests_failed += test_writable(s4);
00505     }
00506 
00507     {
00508       nsStdString s5( NS_LITERAL_STRING("Hello") );
00509 
00510       tests_failed += test_readable_hello(s5);
00511       tests_failed += test_writable(s5);
00512 
00513       nsStdCString s6("Hello");
00514       tests_failed += test_readable_hello(s6);
00515       tests_failed += test_writable(s6);
00516     }
00517 
00518     {
00519       nsLiteralString s7(NS_LITERAL_STRING("He"));
00520       nsString        s8(NS_LITERAL_STRING("l"));
00521       nsStdString     s9(NS_LITERAL_STRING("lo"));
00522 
00523       tests_failed += test_readable_hello(s7+s8+s9);
00524 
00525       nsString s13( s7 + s8 + s9 );
00526       tests_failed += test_readable_hello(s13);
00527 
00528       nsStdString s14( s7 + s8 + s9 );
00529       tests_failed += test_readable_hello(s14);
00530 
00531       nsCString         s10("He");
00532       nsLiteralCString  s11("l");
00533       nsStdCString      s12("lo");
00534       
00535       tests_failed += test_readable_hello(s10+s11+s12);
00536 
00537       
00538     }
00539 
00540     {
00541       const char *foo = "this is a really long string";
00542       nsCString origString;
00543       nsCString string2;
00544       nsCString string3;
00545 
00546       origString = foo;
00547 
00548       string2 = Substring(origString, 0, 5);
00549       string3 = Substring(origString, 6, origString.Length() - 6);
00550     }
00551 
00552     {
00553       nsLiteralCString s13("He");
00554       nsCAutoString    s14("l");
00555       nsLiteralCString s15("lo");
00556 
00557       s14.Assign(s13 + s14 + s15);
00558 
00559       if ( int failures = test_readable_hello(s14) )
00560         {
00561           tests_failed += failures;
00562           cout << "FAILED to keep a promise." << endl;
00563         }
00564     }
00565 
00566 
00567     {
00568       nsLiteralCString str1("Hello");
00569       nsStdCString str2("Hello");
00570 
00571       nsLiteralCString str3("Hello there");
00572 
00573       if ( str1 != str2 )
00574         {
00575           cout << "string comparison using != failed" << endl;
00576           ++tests_failed;
00577         }
00578 
00579       if ( !(str3 > str2) )
00580         {
00581           cout << "string comparison using > failed" << endl;
00582           ++tests_failed;
00583         }
00584 
00585       if ( !(str2 < str3) )
00586         {
00587           cout << "string comparison using < failed" << endl;
00588           ++tests_failed;
00589         }
00590 
00591       if ( str1 != "Hello" )
00592         {
00593           cout << "string comparison using == failed" << endl;
00594           ++tests_failed;
00595         }
00596     }
00597 
00598 #if 0
00599     nsStdCString extracted_middle("XXXXXXXXXX");
00600     CallCMid(extracted_middle, part1+part2a+part2b, 1, 3);
00601     
00602     cout << "The result of mid was \"" << extracted_middle << "\"" << endl;
00603     
00604     nsLiteralCString middle_answer("ell");
00605     if ( middle_answer != extracted_middle )
00606       {
00607         cout << "mid FAILED on nsConcatString" << endl;
00608         ++tests_failed;
00609       }
00610 
00611 
00612 
00613       //
00614       // |nsStdStringWrapper|, i.e., |nsStdCString|
00615       //
00616 
00617     {
00618       nsStdCString extracted_middle;
00619       CallCMid(extracted_middle, part1+part2a+part2b, 1, 3);
00620 
00621      cout << "The result of mid was \"" << extracted_middle << "\"" << endl;
00622 
00623       nsLiteralCString middle_answer("ell");
00624       if ( middle_answer != extracted_middle )
00625         {
00626           cout << "mid FAILED on nsStdCString" << endl;
00627           ++tests_failed;
00628         }
00629     }
00630 
00631 
00632 
00633     nsStdCString leftString;
00634     source.Left(leftString, 9);
00635     // cout << static_cast<const nsACString>(leftString) << endl;
00636 
00637 
00638 
00639     tests_failed += test_multifragment_iterators(part1+part2a+part2b);
00640 #endif
00641 
00642     
00643     
00644     cout << "End of string unit tests." << endl;
00645     if ( !tests_failed )
00646       cout << "OK, all tests passed." << endl;
00647     else
00648       cout << "FAILED one or more tests." << endl;
00649 
00650        return tests_failed;
00651   }