diff options
Diffstat (limited to 'src/libs/xpcom18a4/xpcom/tests/StringFactoringTests')
12 files changed, 1528 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/Makefile.in b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/Makefile.in new file mode 100644 index 00000000..1ced5d3e --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/Makefile.in @@ -0,0 +1,76 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = xpcom +PROGRAM = profile_strings +#PROGRAM = test_main + +CPPSRCS = \ + $(topsrcdir)/xpcom/ds/nsString2.cpp \ + $(topsrcdir)/xpcom/ds/nsStr.cpp \ + $(topsrcdir)/xpcom/ds/nsString.cpp \ + $(topsrcdir)/xpcom/ds/nsCRT.cpp \ + $(topsrcdir)/xpcom/base/nsAllocator.cpp \ + $(topsrcdir)/xpcom/ds/nsDeque.cpp \ + profile_main.cpp \ + $(NULL) +# test_main.cpp \ + + +LIBS += \ + $(NSPR_LIBS) \ + $(NULL) + +include $(topsrcdir)/config/rules.mk + +DEFINES += -DNEW_STRING_APIS -DSTANDALONE_STRING_TESTS -UDEBUG -DNDEBUG +#DEFINES += -DSTANDALONE_STRING_TESTS -UDEBUG -DNDEBUG +INCLUDES += -I$(srcdir)/../public -I$(srcdir)/services + +libs:: + $(INSTALL) $(srcdir)/test.properties $(DIST)/bin/res + +install:: + $(SYSINSTALL) $(IFLAGS1) $(srcdir)/test.properties $(DESTDIR)$(mozappdir)/res + diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.Prefix new file mode 100644 index 00000000..b9580e49 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.Prefix @@ -0,0 +1,4 @@ +// StringTest.Prefix + +#define STANDALONE_STRING_TESTS +#define HAVE_CPP_2BYTE_WCHAR_T diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.mcp b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.mcp Binary files differnew file mode 100644 index 00000000..12b125ed --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.mcp diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestDebug.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestDebug.Prefix new file mode 100644 index 00000000..3724af94 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestDebug.Prefix @@ -0,0 +1,4 @@ +#include "StringTest.Prefix" + +#define DEBUG 1 +#undef NDEBUG diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestNo_wchar_t.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestNo_wchar_t.Prefix new file mode 100644 index 00000000..dddf8450 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestNo_wchar_t.Prefix @@ -0,0 +1,5 @@ +// StringTestNo_wchar_t.Prefix + +#include "StringTest.Prefix" + +#undef HAVE_CPP_2BYTE_WCHAR_T diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileNew.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileNew.Prefix new file mode 100644 index 00000000..b6ca50d3 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileNew.Prefix @@ -0,0 +1,3 @@ +// StringTestProfileNew.Prefix + +#include "StringTest.Prefix" diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileOld.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileOld.Prefix new file mode 100644 index 00000000..d23e3ea9 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileOld.Prefix @@ -0,0 +1,6 @@ +// StringTestProfileOld.Prefix + +#include "StringTest.Prefix" + +#define OLD_STRING_APIS +#undef HAVE_CPP_2BYTE_WCHAR_T
\ No newline at end of file diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileStd.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileStd.Prefix new file mode 100644 index 00000000..eb8a7a85 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileStd.Prefix @@ -0,0 +1,7 @@ +// StringTestProfileOld.Prefix + +#include "StringTest.Prefix" + +#define OLD_STRING_APIS +#define TEST_STD_STRING +#undef HAVE_CPP_2BYTE_WCHAR_T
\ No newline at end of file diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/ToDo.doc b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/ToDo.doc new file mode 100644 index 00000000..da114471 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/ToDo.doc @@ -0,0 +1,41 @@ +// To Do... + + - Decide: do I really want to define |Equals| (i.e., so many extra signatures) + + . Make |ns[C]String| rename its converting operations to, e.g., |EqualsWithConversion|, + |AssignWithConversion|, |CompareWithConversion|, |AppendWithConversion|, etc. + + . Bring |Equals| and |Compare| into scope + + . Implement chunky iterators + + . Get "nsAReadableString.h" and "nsAWritableString.h" to added to the MANIFEST, etc. + + - Get "nsAReadableString.h" and "nsAWritableString.h" to compile everywhere + + - Add test for |Replace|... + + - Add tests for Find and RFind + + - Implement the Find and RFind signatures + + . Fix Truncate / SetLength confusion (make SetLength the real function in |nsString|) + + . Chop out conflicting |ns[C]String| operators + + . Figure out how if we can make PRUnichar be wchar_t, so we get the cheap constructors, + ...and ensure the cheap constructors can be made to work everywhere + + x Try the |static const unsigned long kLeftString = 1 - 1; /* because VC++ doesn't like =0 */| hack + + . Add tests for |nsShared[C]String| + + . Implement |nsShared[C]String| + + - Add tests for the shared string smart pointer + + . Implement the shared string smart pointer + + . Figure out why StdStringWrapper isn't as good as raw std::string + + - Implement a smart allocator for StdStringWrapper diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/nsStdStringWrapper.h b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/nsStdStringWrapper.h new file mode 100644 index 00000000..6e43b528 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/nsStdStringWrapper.h @@ -0,0 +1,234 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott Collins <scc@mozilla.org> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsStdStringWrapper_h___ +#define nsStdStringWrapper_h___ + +#include <string> + +#ifndef nsAString_h___ +#include "nsAString.h" +#endif + + +template <class T> +class nsStringAllocator + : public std::allocator<T> // temporarily + { + // ... + }; + + +template < class CharT, class TraitsT = nsCharTraits<CharT>, class AllocatorT = nsStringAllocator<CharT> > +class basic_nsStdStringWrapper + : public basic_nsAString<CharT> + /* + ... + */ + { + protected: + std::basic_string<CharT, TraitsT, AllocatorT> mRawString; + + typedef std::basic_string<CharT, TraitsT, AllocatorT> basic_string_t; + + using typename basic_string_t::traits_type; + using typename basic_string_t::value_type; + using typename basic_string_t::allocator_type; + using typename basic_string_t::size_type; + using typename basic_string_t::difference_type; + using typename basic_string_t::reference; + using typename basic_string_t::const_reference; + using typename basic_string_t::pointer; + using typename basic_string_t::const_pointer; + using typename basic_string_t::iterator; + using typename basic_string_t::const_iterator; + using typename basic_string_t::reverse_iterator; + using typename basic_string_t::const_reverse_iterator; + + static const size_type npos = size_type(-1); + + protected: + virtual const void* Implementation() const; + + virtual const CharT* GetReadableFragment( nsReadableFragment<CharT>&, nsFragmentRequest, PRUint32 ) const; + virtual CharT* GetWritableFragment( nsWritableFragment<CharT>&, nsFragmentRequest, PRUint32 ); + + public: + basic_nsStdStringWrapper() { } + +#if 0 + explicit + basic_nsStdStringWrapper( const AllocatorT& a = AllocatorT() ) + : mRawString(a) + { + } +#endif + + explicit + basic_nsStdStringWrapper( const basic_nsAString<CharT>& str ) + { + Assign(str); + } + +#if 0 + explicit + basic_nsStdStringWrapper( const basic_string_t& str, size_type pos = 0, size_type n = npos ) + : mRawString(str, pos, n) + { + } + + basic_nsStdStringWrapper( const basic_string_t& str, size_type pos, size_type n, const AllocatorT& a ) + : mRawString(str, pos, n, a) + { + } +#endif + + basic_nsStdStringWrapper( const CharT* s, size_type n, const AllocatorT& a = AllocatorT() ) + : mRawString(s, n, a) + { + } + + explicit + basic_nsStdStringWrapper( const CharT* s, const AllocatorT& a = AllocatorT() ) + : mRawString(s, a) + { + } + +#if 0 + basic_nsStdStringWrapper( size_type n, CharT c, const AllocatorT& a = AllocatorT() ) + : mRawString(n, c, a) + { + } +#endif + + virtual + PRUint32 + Length() const + { + return mRawString.length(); + } + + virtual + void + SetCapacity( PRUint32 aNewCapacity ) + { + mRawString.reserve(aNewCapacity); + } + + virtual + void + SetLength( PRUint32 aNewLength ) + { + mRawString.resize(aNewLength); + } + + protected: + virtual void do_AssignFromReadable( const basic_nsAString<CharT>& ); + + // ... + }; + +NS_DEF_TEMPLATE_STRING_COMPARISON_OPERATORS(basic_nsStdStringWrapper<CharT>, CharT) + + + +template <class CharT, class TraitsT, class AllocatorT> +const void* +basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT>::Implementation() const + { + static const char* implementation = "nsStdStringWrapper"; + return implementation; + } + + +template <class CharT, class TraitsT, class AllocatorT> +const CharT* +basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT>::GetReadableFragment( nsReadableFragment<CharT>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const + { + switch ( aRequest ) + { + case kFirstFragment: + case kLastFragment: + case kFragmentAt: + aFragment.mEnd = (aFragment.mStart = mRawString.data()) + mRawString.length(); + return aFragment.mStart + aOffset; + + case kPrevFragment: + case kNextFragment: + default: + return 0; + } + } + +template <class CharT, class TraitsT, class AllocatorT> +CharT* +basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT>::GetWritableFragment( nsWritableFragment<CharT>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) + { + switch ( aRequest ) + { + case kFirstFragment: + case kLastFragment: + case kFragmentAt: + aFragment.mEnd = (aFragment.mStart = NS_CONST_CAST(CharT*, mRawString.data())) + mRawString.length(); + return aFragment.mStart + aOffset; + + case kPrevFragment: + case kNextFragment: + default: + return 0; + } + } + +template <class CharT, class TraitsT, class AllocatorT> +void +basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT>::do_AssignFromReadable( const basic_nsAString<CharT>& rhs ) + { + typedef basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT> this_t; + + if ( SameImplementation(*this, rhs) ) + mRawString = NS_STATIC_CAST(this_t, rhs).mRawString; + else + basic_nsAString<CharT>::do_AssignFromReadable(rhs); + } + + +typedef basic_nsStdStringWrapper<PRUnichar> nsStdString; +typedef basic_nsStdStringWrapper<char> nsStdCString; + + +#endif // !defined(nsStdStringWrapper_h___) diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/profile_main.cpp b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/profile_main.cpp new file mode 100644 index 00000000..d7c14621 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/profile_main.cpp @@ -0,0 +1,497 @@ +// profile_main.cpp + +#include "nscore.h" +#include <iostream.h> +#include <string> +#include <iomanip> + +#include "nsInt64.h" + +#ifdef XP_MAC +#include <Timer.h> +#include "Profiler.h" +#else +#include "prtime.h" +#endif + +#ifndef TEST_STD_STRING +#include "nsString.h" +#else +#include "nsStdStringWrapper.h" +typedef nsStdCString nsCString; +#endif + +static const int kTestSucceeded = 0; +static const int kTestFailed = 1; + +static const size_t N = 100000; + + +template <class T> +inline +PRUint32 +TotalLength( const T& s ) + { + return s.Length(); + } + +NS_SPECIALIZE_TEMPLATE +inline +PRUint32 +TotalLength( const string& s ) + { + return s.length(); + } + +template <class T> +inline +PRUint32 +Find( const T& text, const T& pattern ) + { + return text.Find(pattern); + } + +NS_SPECIALIZE_TEMPLATE +inline +PRUint32 +Find( const string& text, const string& pattern ) + { + return text.find(pattern); + } + +inline +nsInt64 +GetTime() + { +#ifdef XP_MAC + UnsignedWide time; + Microseconds(&time); + return nsInt64( *reinterpret_cast<PRInt64*>(&time) ); +#else + return nsInt64( PR_Now() ); +#endif + } + +class TestTimer + { + public: + TestTimer() : mStartTime(GetTime()) { } + + ~TestTimer() + { + nsInt64 stopTime = GetTime(); + nsInt64 totalTime = stopTime - mStartTime; +#ifdef HAVE_LONG_LONG + cout << setw(10) << NS_STATIC_CAST(PRInt64, totalTime) << " µs : "; +#else + cout << setw(10) << NS_STATIC_CAST(PRInt32, totalTime) << "µs : "; +#endif + } + + private: + nsInt64 mStartTime; + }; + +inline +int +foo( const nsCString& ) + { + return 1; + } + +static +int +test_construction() + { + cout << endl; + + { + nsCString someCString; + int total = 0; + TestTimer timer; + for ( int i=0; i<N; ++i ) + { + total += foo( someCString ); + } + } + cout << "null loop time for constructor" << endl; + + + { + int total = 0; + TestTimer timer; + for ( int i=0; i<N; ++i ) + { + total += foo( nsCString() ); + } + } + cout << "nsCString()" << endl; + + + { + int total = 0; + TestTimer timer; + for ( int i=0; i<N; ++i ) + { + total += foo( nsCString("This is a reasonable length string with some text in it and it is good.") ); + } + } + cout << "nsCString(\"abc\")" << endl; + + return kTestSucceeded; + } + +static +int +test_concat() + { + cout << endl; + + //---------|---------|---------|---------|---------|---------|---------| + nsCString s1("This is a reasonable length string with some text in it and it is good."); + nsCString s2("This is another string that I will use in the concatenation test."); + nsCString s3("This is yet a third string that I will use in the concatenation test."); + + PRUint32 len = TotalLength( s1 + s2 + s3 + s1 + s2 + s3 ); + if ( len != (71 + 65 + 69 + 71 + 65 + 69) ) + { + cout << "|test_concat()| FAILED" << endl; + return kTestFailed; + } + + + { + nsCString anEmptyCString; + TestTimer timer; + for ( int i=0; i<N; ++i ) + { + len += TotalLength( anEmptyCString ); + } + } + cout << "null loop time for concat" << endl; + + + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + len += TotalLength( s1 + s2 + s3 + s1 + s2 + s3 ); + } + cout << "TotalLength( s1 + s2 + s3 + s1 + s2 + s3 )" << endl; + + + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + len += TotalLength( s1 + s2 ); + } + cout << "TotalLength( s1 + s2 )" << endl; + + return kTestSucceeded; + } + +static +int +test_concat_and_assign() + { + //---------|---------|---------|---------|---------|---------|---------| + nsCString s1("This is a reasonable length string with some text in it and it is good."); + nsCString s2("This is another string that I will use in the concatenation test."); + nsCString s3("This is yet a third string that I will use in the concatenation test."); + + nsCString s4( s1 + s2 + s3 + s1 + s2 + s3 ); + if ( TotalLength(s4) != (71 + 65 + 69 + 71 + 65 + 69) ) + { + cout << "|test_concat()| FAILED" << endl; + return kTestFailed; + } + + + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + s4 = s1 + s2 + s3 + s1 + s2 + s3; + } + cout << "s4 = s1 + s2 + s3 + s1 + s2 + s3" << endl; + + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + s4 = s1 + s2; + } + cout << "s4 = s1 + s2" << endl; + + return kTestSucceeded; + } + +static +int +test_compare() + { + nsCString s1("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxThis is a reasonable length string with some text in it and it is good."); + nsCString s2("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxThis is a reasonable length string with some text in it and it is bad."); + + int count = 0; + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + if ( s1 > s2 ) + ++count; + } + cout << "s1 > s2" << endl; + + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + if ( s1 == s1 ) + ++count; + } + cout << "s1 == s1" << endl; + + return kTestSucceeded; + } + +static +int +test_countchar() + { + nsCString s1("This is a reasonable length string with some text in it and it is good."); + + if ( s1.CountChar('e') != 5 ) + { + cout << "|test_countchar()| FAILED: found a count of " << s1.CountChar('e') << endl; + return kTestFailed; + } + + PRUint32 total = 0; + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + total += s1.CountChar('e'); + } + cout << "s1.CountChar('e')" << endl; + + return kTestSucceeded; + } + +static +int +test_append_string() + { + nsCString s1("This is a reasonable length string with some text in it and it is good."); + nsCString s2("This is another string that I will use in the concatenation test."); + + PRUint32 len = 0; + + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + { + nsCString s3; + s3.Append(s1); + s3.Append(s2); + len += TotalLength(s3); + } + } + cout << "s3.Append(s1); s3.Append(s2)" << endl; + + return kTestSucceeded; + } + +static +int +test_repeated_append_string() + { + nsCString s1("This is a reasonable length string with some text in it and it is good."); + nsCString s2("This is another string that I will use in the concatenation test."); + + PRUint32 len = 0; + + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + { + nsCString s3; + for ( int j=0; j<100; ++j ) + { + s3.Append(s1); + s3.Append(s2); + len += TotalLength(s3); + } + } + } + cout << "repeated s3.Append(s1); s3.Append(s2)" << endl; + + return kTestSucceeded; + } + +static +int +test_append_char() + { + cout << endl; + + PRUint32 len = 0; + + nsCString s1("hello"); + PRUint32 oldLength = s1.Length(); + + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + { + s1.SetLength(oldLength); + } + } + cout << "null loop time for append char" << endl; + + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + { + s1.Append('e'); + s1.SetLength(oldLength); + } + } + cout << "s1.Append('e')" << endl; + + return kTestSucceeded; + } + +static +int +test_repeated_append_char() + { + PRUint32 len = 0; + + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + { + nsCString s1; + for ( int j=0; j<1000; ++j ) + { + s1.Append('e'); + len += TotalLength(s1); + } + } + } + cout << "repeated s1.Append('e')" << endl; + + return kTestSucceeded; + } + +static +int +test_insert_string() + { + nsCString s1("This is a reasonable length string with some text in it and it is good."); + + PRUint32 len = 0; + + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + { + nsCString s2("This is another string that I will use in the concatenation test."); + s2.Insert(s1, 3); + len += TotalLength(s2); + } + } + cout << "s2.Insert(s1, 3)" << endl; + + return kTestSucceeded; + } + +#ifndef TEST_STD_STRING +static +int +test_find_string() + { + nsCString text("aaaaaaaaaab"); + nsCString pattern("aab"); + + PRUint32 position = 0; + { + TestTimer timer; + for ( int i=0; i<N; ++i ) + position = Find(text, pattern); + } + cout << "text.Find(pattern)" << endl; + + return kTestSucceeded; + } +#endif + +class Profiler + { + public: + Profiler() + { +#if 0 + ProfilerInit(collectDetailed, bestTimeBase, 100, 32); +#endif + } + + void + Dump( const char* output_name ) + { + } + + void + Dump( const unsigned char* output_name ) + { +#if 0 + ProfilerDump(output_name); +#endif + } + + ~Profiler() + { +#if 0 + ProfilerDump(mOutputName); + ProfilerTerm(); +#endif + } + }; + +int +main() + { + + cout << "String performance profiling. Compiled " __DATE__ " " __TIME__ << endl; +#ifdef TEST_STD_STRING + cout << "Testing std::string." << endl; +#else + cout << "Testing factored nsString." << endl; +#endif + + int tests_failed = 0; + + Profiler profiler; + + tests_failed += test_construction(); + tests_failed += test_concat(); + tests_failed += test_concat_and_assign(); + tests_failed += test_compare(); + tests_failed += test_countchar(); + tests_failed += test_append_string(); + tests_failed += test_repeated_append_string(); + tests_failed += test_append_char(); + tests_failed += test_repeated_append_char(); + tests_failed += test_insert_string(); +#ifndef TEST_STD_STRING + tests_failed += test_find_string(); +#endif + +#ifdef TEST_STD_STRING + profiler.Dump("\pStandard String.prof"); +#else + profiler.Dump("\pFactored String.prof"); +#endif + + if ( tests_failed ) + cout << "One or more tests FAILED. Measurements may be invalid." << endl; + + cout << "End of string performance profiling." << endl; + return 0; + } diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/test_main.cpp b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/test_main.cpp new file mode 100644 index 00000000..b8365dac --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/test_main.cpp @@ -0,0 +1,651 @@ +#include <iostream.h> +#include "nsStringIO.h" + +//#define TEST_STD_STRING + + +#include "nsString.h" +#include "nsFragmentedString.h" +#include "nsReadableUtils.h" +#include "nsSlidingString.h" + +#ifdef TEST_STD_STRING +#include "nsStdStringWrapper.h" +#else + typedef nsString nsStdString; + typedef nsCString nsStdCString; +#endif + +template <class CharT> +basic_nsLiteralString<CharT> +literal_hello( CharT* ) + { + } + +NS_SPECIALIZE_TEMPLATE +basic_nsLiteralString<char> +literal_hello( char* ) + { + return basic_nsLiteralString<char>("Hello"); + } + +NS_SPECIALIZE_TEMPLATE +basic_nsLiteralString<PRUnichar> +literal_hello( PRUnichar* ) + { +#ifdef HAVE_CPP_2BYTE_WCHAR_T + return basic_nsLiteralString<PRUnichar>(L"Hello"); +#else + static PRUnichar constant_unicode[] = { 'H', 'e', 'l', 'l', 'o', PRUnichar() }; + return basic_nsLiteralString<PRUnichar>(constant_unicode); +#endif + } + +template <class T> +struct string_class_traits + { + }; + +NS_SPECIALIZE_TEMPLATE +struct string_class_traits<PRUnichar> + { + typedef PRUnichar* pointer; + typedef nsString implementation_t; + + static basic_nsLiteralString<PRUnichar> literal_hello() { return ::literal_hello(pointer()); } + }; + +NS_SPECIALIZE_TEMPLATE +struct string_class_traits<char> + { + typedef char* pointer; + typedef nsCString implementation_t; + + static basic_nsLiteralString<char> literal_hello() { return ::literal_hello(pointer()); } + }; + + +static +void +CallCMid( nsACString& aResult, const nsACString& aSource, PRUint32 aStartPos, PRUint32 aLengthToCopy ) + { + aSource.Mid(aResult, aStartPos, aLengthToCopy); + } + + + +template <class CharT> +int +test_multifragment_iterators( const basic_nsAString<CharT>& aString ) + /* + ...this tests a problem that was present in |nsPromiseConcatenation| where, + because it originally stored some iteration state in the object itself, rather than + in the fragment, the iterators could get confused if used out of sequence. + + This test should be run on any multi-fragment implementation to verify that it + does not have the same bug. Make sure the first fragment is only one character long. + */ + { + typedef typename basic_nsAString<CharT>::const_iterator ConstIterator; + + int tests_failed = 0; + + ConstIterator iter1 = aString.BeginReading(); + ConstIterator iter2 = aString.BeginReading(); + ++iter2; ++iter2; + + ConstIterator iter3 = aString.EndReading(); + --iter3; + ++iter1; ++iter1; + if ( iter1 != iter2 ) + { + cout << "FAILED in |test_multifragment_iterators|" << endl; + ++tests_failed; + } + + return tests_failed; + } + +template <class CharT> +int +test_Vidur_functions( const basic_nsAString<CharT>& aString ) + { + char* char_copy = ToNewCString(aString); + PRUnichar* PRUnichar_copy = ToNewUnicode(aString); + + nsMemory::Free(PRUnichar_copy); + nsMemory::Free(char_copy); + + return 0; + } + +template <class CharT> +int +test_readable_hello( const basic_nsAString<CharT>& aReadable ) + { + int tests_failed = 0; + + if ( aReadable.Length() != 5 ) + { + cout << "FAILED |test_readable_hello|: |Length()| --> " << aReadable.Length() << endl; + ++tests_failed; + } + + if ( aReadable.First() != CharT('H') ) + { + cout << "FAILED |test_readable_hello|: |First()| --> '" << aReadable.First() << "'" << endl; + ++tests_failed; + } + + if ( aReadable.Last() != CharT('o') ) + { + cout << "FAILED |test_readable_hello|: |Last()| --> '" << aReadable.Last() << "'" << endl; + ++tests_failed; + } + + if ( aReadable[3] != CharT('l') ) + { + cout << "FAILED |test_readable_hello|: |operator[]| --> '" << aReadable[3] << "'" << endl; + ++tests_failed; + } + + if ( aReadable.CountChar( CharT('l') ) != 2 ) + { + cout << "FAILED |test_readable_hello|: |CountChar('l')| --> " << aReadable.CountChar(CharT('l')) << endl; + ++tests_failed; + } + + basic_nsAString<CharT>::const_iterator iter = aReadable.BeginReading(); + if ( *iter != CharT('H') ) + { + cout << "FAILED |test_readable_hello|: didn't start out pointing to the right thing, or else couldn't be dereferenced. --> '" << *iter << "'" << endl; + ++tests_failed; + } + + ++iter; + + if ( *iter != CharT('e') ) + { + cout << "FAILED |test_readable_hello|: iterator couldn't be incremented, or else couldn't be dereferenced. --> '" << *iter << "'" << endl; + ++tests_failed; + } + + iter = aReadable.EndReading(); + --iter; + if ( *iter != CharT('o') ) + { + 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; + ++tests_failed; + } + + basic_nsAString<CharT>::const_iterator iter1 = aReadable.BeginReading().advance(3); + if ( *iter1 != CharT('l') ) + { + cout << "FAILED |test_readable_hello|: iterator couldn't be set to |BeginReading()+=n|, or else couldn't be dereferenced. --> '" << *iter1 << "'" << endl; + ++tests_failed; + } + + basic_nsAString<CharT>::const_iterator iter2 = aReadable.EndReading().advance(-2); + if ( *iter2 != CharT('l') ) + { + cout << "FAILED |test_readable_hello|: iterator couldn't be set to |EndReading()-=n|, or else couldn't be dereferenced. --> '" << *iter2 << "'" << endl; + ++tests_failed; + } + + if ( iter1 != iter2 ) + { + cout << "FAILED |test_readable_hello|: iterator comparison with !=." << endl; + ++tests_failed; + } + + if ( !(iter1 == iter2) ) + { + cout << "FAILED |test_readable_hello|: iterator comparison with ==." << endl; + ++tests_failed; + } + + typedef CharT* CharT_ptr; + if ( aReadable != literal_hello(CharT_ptr()) ) + { + cout << "FAILED |test_readable_hello|: comparison with \"Hello\"" << endl; + ++tests_failed; + } + + tests_failed += test_multifragment_iterators(aReadable); + // tests_failed += test_deprecated_GetBufferGetUnicode(aReadable); + + test_Vidur_functions(aReadable); + + return tests_failed; + } + + +template <class CharT> +int +test_SetLength( basic_nsAString<CharT>& aWritable ) + { + int tests_failed = 0; + + string_class_traits<CharT>::implementation_t oldValue(aWritable); + + + size_t oldLength = aWritable.Length(); + + if ( oldValue != Substring(aWritable, 0, oldLength) ) + { + cout << "FAILED growing a string in |test_SetLength|, saving the value didn't work." << endl; + ++tests_failed; + } + + size_t newLength = 2*(oldLength+1); + + aWritable.SetLength(newLength); + if ( aWritable.Length() != newLength ) + { + cout << "FAILED growing a string in |test_SetLength|, length is wrong." << endl; + ++tests_failed; + } + + if ( oldValue != Substring(aWritable, 0, oldLength) ) + { + cout << "FAILED growing a string in |test_SetLength|, contents damaged after growing." << endl; + ++tests_failed; + } + + aWritable.SetLength(oldLength); + if ( aWritable.Length() != oldLength ) + { + cout << "FAILED shrinking a string in |test_SetLength|." << endl; + ++tests_failed; + } + + if ( oldValue != Substring(aWritable, 0, oldLength) ) + { + cout << "FAILED growing a string in |test_SetLength|, contents damaged after shrinking." << endl; + ++tests_failed; + } + + return tests_failed; + } + + +template <class CharT> +int +test_insert( basic_nsAString<CharT>& aWritable ) + { + int tests_failed = 0; + + string_class_traits<CharT>::implementation_t oldValue(aWritable); + + if ( oldValue != aWritable ) + { + cout << "FAILED saving the old string value in |test_insert|." << endl; + ++tests_failed; + } + + string_class_traits<CharT>::implementation_t insertable( string_class_traits<CharT>::literal_hello() ); + + insertable.SetLength(1); + aWritable.Insert(insertable, 0); + + if ( aWritable != (insertable + oldValue) ) + { + cout << "FAILED in |test_insert|." << endl; + ++tests_failed; + } + + aWritable = oldValue; + + return tests_failed; + } + + +template <class CharT> +int +test_cut( basic_nsAString<CharT>& aWritable ) + { + int tests_failed = 0; + + aWritable.Cut(0, aWritable.Length()+5); + + return tests_failed; + } + +template <class CharT> +int +test_self_assign( basic_nsAString<CharT>& aWritable ) + { + int tests_failed = 0; + string_class_traits<CharT>::implementation_t oldValue(aWritable); + + aWritable = aWritable; + if ( aWritable != oldValue ) + { + cout << "FAILED self assignment." << endl; + ++tests_failed; + } + + aWritable = oldValue; + return tests_failed; + } + +template <class CharT> +int +test_self_append( basic_nsAString<CharT>& aWritable ) + { + int tests_failed = 0; + string_class_traits<CharT>::implementation_t oldValue(aWritable); + + aWritable += aWritable; + if ( aWritable != oldValue + oldValue ) + { + cout << "FAILED self append." << endl; + ++tests_failed; + } + + aWritable = oldValue; + return tests_failed; + } + +template <class CharT> +int +test_self_insert( basic_nsAString<CharT>& aWritable ) + { + int tests_failed = 0; + string_class_traits<CharT>::implementation_t oldValue(aWritable); + + aWritable.Insert(aWritable, 0); + if ( aWritable != oldValue + oldValue ) + { + cout << "FAILED self insert." << endl; + ++tests_failed; + } + + aWritable = oldValue; + return tests_failed; + } + +template <class CharT> +int +test_self_replace( basic_nsAString<CharT>& aWritable ) + { + int tests_failed = 0; + string_class_traits<CharT>::implementation_t oldValue(aWritable); + + aWritable.Replace(0, 0, aWritable); + if ( aWritable != oldValue + oldValue ) + { + cout << "FAILED self insert." << endl; + ++tests_failed; + } + + aWritable = oldValue; + return tests_failed; + } + + + +template <class CharT> +int +test_writable( basic_nsAString<CharT>& aWritable ) + { + int tests_failed = 0; + // ... + + + { + typedef CharT* CharT_ptr; + aWritable = literal_hello(CharT_ptr()); + + if ( aWritable != literal_hello(CharT_ptr()) ) + { + cout << "FAILED assignment and/or comparison in |test_writable|." << endl; + ++tests_failed; + } + + tests_failed += test_readable_hello(aWritable); + } + + tests_failed += test_SetLength(aWritable); + tests_failed += test_insert(aWritable); + tests_failed += test_cut(aWritable); + tests_failed += test_self_assign(aWritable); + tests_failed += test_self_append(aWritable); + tests_failed += test_self_insert(aWritable); + tests_failed += test_self_replace(aWritable); + + return tests_failed; + } + + + +typedef void* void_ptr; + +int +main() + { + int tests_failed = 0; + cout << "String unit tests. Compiled " __DATE__ " " __TIME__ << endl; + +#if 0 + { + nsFragmentedCString fs0; + fs0.Append("Hello"); + tests_failed += test_readable_hello(fs0); + tests_failed += test_writable(fs0); + } +#endif + + { + NS_NAMED_LITERAL_STRING(literal, "Hello"); + PRUnichar* buffer = ToNewUnicode(literal); + + nsSlidingString ss0(buffer, buffer+5, buffer+6); +// ss0.AppendBuffer(buffer, buffer+5, buffer+6); + nsReadingIterator<PRUnichar> ri0; + ss0.BeginReading(ri0); + + tests_failed += test_readable_hello(ss0); + + nsSlidingSubstring ss1(ss0); + tests_failed += test_readable_hello(ss1); + + buffer = ToNewUnicode(literal); + ss0.AppendBuffer(buffer, buffer+5, buffer+6); + + ri0.advance(5); + ss0.DiscardPrefix(ri0); + + tests_failed += test_readable_hello(ss0); + tests_failed += test_readable_hello(ss1); + + nsReadingIterator<PRUnichar> ri1; + ss0.EndReading(ri1); + + nsSlidingSubstring ss2(ss0, ri0, ri1); + tests_failed += test_readable_hello(ss2); + } + + + { + nsLiteralCString s0("Patrick Beard made me write this: \"This is just a test\"\n"); + print_string(s0); + + const char* raw_string = "He also made me write this.\n"; + nsFileCharSink<char> output(stdout); + copy_string(raw_string, raw_string+nsCharTraits<char>::length(raw_string), output); + + nsLiteralCString s1("This ", 5), s2("is ", 3), s3("a ", 2), s4("test\n", 5); + print_string(s1+s2+s3+s4); + + nsLiteralCString s5( "This is " "a " "test" ); + print_string(s5+NS_LITERAL_CSTRING("\n")); + + print_string(nsLiteralCString("The value of the string |x| is \"") + Substring(s0, 0, s0.Length()-1) + NS_LITERAL_CSTRING("\". Hope you liked it.")); + } + + + { + tests_failed += test_readable_hello(NS_LITERAL_STRING("Hello")); + + nsLiteralCString s1("Hello"); + tests_failed += test_readable_hello(s1); + } + + { + + nsString s3( NS_LITERAL_STRING("Hello") ); + + tests_failed += test_readable_hello(s3); + tests_failed += test_writable(s3); + + nsCString s4("Hello"); + tests_failed += test_readable_hello(s4); + tests_failed += test_writable(s4); + } + + { + nsStdString s5( NS_LITERAL_STRING("Hello") ); + + tests_failed += test_readable_hello(s5); + tests_failed += test_writable(s5); + + nsStdCString s6("Hello"); + tests_failed += test_readable_hello(s6); + tests_failed += test_writable(s6); + } + + { + nsLiteralString s7(NS_LITERAL_STRING("He")); + nsString s8(NS_LITERAL_STRING("l")); + nsStdString s9(NS_LITERAL_STRING("lo")); + + tests_failed += test_readable_hello(s7+s8+s9); + + nsString s13( s7 + s8 + s9 ); + tests_failed += test_readable_hello(s13); + + nsStdString s14( s7 + s8 + s9 ); + tests_failed += test_readable_hello(s14); + + nsCString s10("He"); + nsLiteralCString s11("l"); + nsStdCString s12("lo"); + + tests_failed += test_readable_hello(s10+s11+s12); + + + } + + { + const char *foo = "this is a really long string"; + nsCString origString; + nsCString string2; + nsCString string3; + + origString = foo; + + string2 = Substring(origString, 0, 5); + string3 = Substring(origString, 6, origString.Length() - 6); + } + + { + nsLiteralCString s13("He"); + nsCAutoString s14("l"); + nsLiteralCString s15("lo"); + + s14.Assign(s13 + s14 + s15); + + if ( int failures = test_readable_hello(s14) ) + { + tests_failed += failures; + cout << "FAILED to keep a promise." << endl; + } + } + + + { + nsLiteralCString str1("Hello"); + nsStdCString str2("Hello"); + + nsLiteralCString str3("Hello there"); + + if ( str1 != str2 ) + { + cout << "string comparison using != failed" << endl; + ++tests_failed; + } + + if ( !(str3 > str2) ) + { + cout << "string comparison using > failed" << endl; + ++tests_failed; + } + + if ( !(str2 < str3) ) + { + cout << "string comparison using < failed" << endl; + ++tests_failed; + } + + if ( str1 != "Hello" ) + { + cout << "string comparison using == failed" << endl; + ++tests_failed; + } + } + +#if 0 + nsStdCString extracted_middle("XXXXXXXXXX"); + CallCMid(extracted_middle, part1+part2a+part2b, 1, 3); + + cout << "The result of mid was \"" << extracted_middle << "\"" << endl; + + nsLiteralCString middle_answer("ell"); + if ( middle_answer != extracted_middle ) + { + cout << "mid FAILED on nsConcatString" << endl; + ++tests_failed; + } + + + + // + // |nsStdStringWrapper|, i.e., |nsStdCString| + // + + { + nsStdCString extracted_middle; + CallCMid(extracted_middle, part1+part2a+part2b, 1, 3); + + cout << "The result of mid was \"" << extracted_middle << "\"" << endl; + + nsLiteralCString middle_answer("ell"); + if ( middle_answer != extracted_middle ) + { + cout << "mid FAILED on nsStdCString" << endl; + ++tests_failed; + } + } + + + + nsStdCString leftString; + source.Left(leftString, 9); + // cout << static_cast<const nsACString>(leftString) << endl; + + + + tests_failed += test_multifragment_iterators(part1+part2a+part2b); +#endif + + + + cout << "End of string unit tests." << endl; + if ( !tests_failed ) + cout << "OK, all tests passed." << endl; + else + cout << "FAILED one or more tests." << endl; + + return tests_failed; + } |