mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 20:27:11 +01:00 
			
		
		
		
	Added string classes
This commit is contained in:
		
							
								
								
									
										20
									
								
								projects/SelfTest/String.tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								projects/SelfTest/String.tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| #include "../include/internal/catch_string.h" | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| TEST_CASE( "String", "[Strings]" ) { | ||||
|     using Catch::String; | ||||
|      | ||||
|     SECTION( "empty string" ) { | ||||
|         String empty; | ||||
|         REQUIRE( empty.empty() ); | ||||
|         REQUIRE( empty.size() == 0 ); | ||||
|         REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 ); | ||||
|     } | ||||
|     SECTION( "from literal" ) { | ||||
|         String s = "hello"; | ||||
|         REQUIRE( s.empty() == false ); | ||||
|         REQUIRE( s.size() == 5 ); | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										76
									
								
								projects/SelfTest/StringBuilder.tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								projects/SelfTest/StringBuilder.tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| #include "internal/catch_stringbuilder.h" | ||||
| #include "../include/internal/catch_stringref.h" | ||||
| #include "../include/internal/catch_string.h" | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| TEST_CASE( "StringBuilder", "[Strings]" ) { | ||||
|      | ||||
|     using Catch::StringBuilder; | ||||
|     using Catch::String; | ||||
|      | ||||
|     StringBuilder sb; | ||||
|      | ||||
|     SECTION( "basic" ) { | ||||
|         REQUIRE( sb.capacity() == 0 ); | ||||
|         REQUIRE( sb.size() == 0 ); | ||||
|  | ||||
|         sb.reserve( 32 ); | ||||
|         REQUIRE( sb.capacity() == 32 ); | ||||
|         REQUIRE( sb.size() == 0 ); | ||||
|          | ||||
|         sb.append( "hello" ); | ||||
|         REQUIRE( sb.capacity() == 32 ); | ||||
|         REQUIRE( sb.size() == 5 ); | ||||
|          | ||||
|         String s = std::move( sb ); | ||||
|         REQUIRE( s == "hello" ); | ||||
|         REQUIRE( s.size() == 5 ); | ||||
|     } | ||||
|      | ||||
|     SECTION( "concatenation" ) { | ||||
|         sb << "hello" << " " << "world"; | ||||
|         String s = std::move( sb ); | ||||
|         REQUIRE( s == "hello world" ); | ||||
|     } | ||||
|  | ||||
|     SECTION( "concat & move" ) { | ||||
|         String s = StringBuilder() << "hello" << " " << "world"; | ||||
|         REQUIRE( s == "hello world" ); | ||||
|     } | ||||
|  | ||||
|     SECTION( "reserved" ) { | ||||
|         StringBuilder sb16( 16 ); | ||||
|         REQUIRE( sb16.capacity() == 16 ); | ||||
|         sb16 << "hello" << " " << "world"; | ||||
|         REQUIRE( sb16.capacity() == 16 ); | ||||
|         String s = std::move( sb16 ); | ||||
|         REQUIRE( s == "hello world" ); | ||||
|     } | ||||
|  | ||||
|     SECTION( "from String" ) { | ||||
|         String s = "hello"; | ||||
|  | ||||
|         SECTION( "copy" ) { | ||||
|             StringBuilder sb2 = s; | ||||
|             String s2( std::move(sb2) ); | ||||
|             REQUIRE( s2 == s ); | ||||
|             REQUIRE( s2.c_str() != s.c_str() ); | ||||
|         } | ||||
|         SECTION( "move from uniquely owned string" ) { | ||||
|             auto originalPointer = s.c_str(); | ||||
|             StringBuilder sb2( std::move( s ) ); | ||||
|             String s2( std::move(sb2) ); | ||||
|             REQUIRE( s2 == "hello" ); | ||||
|             REQUIRE( s2.c_str() == originalPointer ); | ||||
|         } | ||||
|         SECTION( "move from shared string (copies)" ) { | ||||
|             auto originalPointer = s.c_str(); | ||||
|             String keepAlive = s; | ||||
|             StringBuilder sb2( std::move( s ) ); | ||||
|             String s2( std::move(sb2) ); | ||||
|             REQUIRE( s2 == "hello" ); | ||||
|             REQUIRE( s2.c_str() != originalPointer ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										151
									
								
								projects/SelfTest/StringRef.tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								projects/SelfTest/StringRef.tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,151 @@ | ||||
| #include "../include/internal/catch_stringref.h" | ||||
| #include "../include/internal/catch_string.h" | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     // Implementation of test accessors | ||||
|     struct StringRefTestAccess { | ||||
|         static auto isOwned( StringRef const& stringRef ) -> bool { | ||||
|             return stringRef.isOwned(); | ||||
|         } | ||||
|         static auto isSubstring( StringRef const& stringRef ) -> bool { | ||||
|             return stringRef.isSubstring(); | ||||
|         } | ||||
|         static auto data( StringRef const& stringRef ) -> char const* { | ||||
|             return stringRef.data(); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     auto isOwned( StringRef const& stringRef ) -> bool { | ||||
|         return StringRefTestAccess::isOwned( stringRef ); | ||||
|     } | ||||
|     auto isSubstring( StringRef const& stringRef ) -> bool { | ||||
|         return StringRefTestAccess::isSubstring( stringRef ); | ||||
|     } | ||||
|     auto data( StringRef const& stringRef ) -> char const* { | ||||
|         return StringRefTestAccess::data( stringRef ); | ||||
|     } | ||||
| } // namespace Catch2 | ||||
|  | ||||
| namespace Catch { | ||||
|     inline auto toString( Catch::StringRef const& stringRef ) -> std::string { | ||||
|         return std::string( data( stringRef ), stringRef.size() ); | ||||
|     } | ||||
| } // namespace Catch | ||||
|  | ||||
| TEST_CASE( "StringRef", "[Strings]" ) { | ||||
|      | ||||
|     using Catch::StringRef; | ||||
|     using Catch::String; | ||||
|      | ||||
|     SECTION( "Empty string" ) { | ||||
|         StringRef empty; | ||||
|         REQUIRE( empty.empty() ); | ||||
|         REQUIRE( empty.size() == 0 ); | ||||
|         REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 ); | ||||
|     } | ||||
|      | ||||
|     SECTION( "From string literal" ) { | ||||
|         StringRef s = "hello"; | ||||
|         REQUIRE( s.empty() == false ); | ||||
|         REQUIRE( s.size() == 5 ); | ||||
|         REQUIRE( isSubstring( s ) == false ); | ||||
|          | ||||
|         auto rawChars = data( s ); | ||||
|         REQUIRE( std::strcmp( rawChars, "hello" ) == 0 ); | ||||
|          | ||||
|         SECTION( "c_str() does not cause copy" ) { | ||||
|             REQUIRE( isOwned( s ) == false ); | ||||
|              | ||||
|             REQUIRE( s.c_str() == rawChars ); | ||||
|              | ||||
|             REQUIRE( isOwned( s ) == false ); | ||||
|         } | ||||
|     } | ||||
|     SECTION( "From sub-string" ) { | ||||
|         StringRef original = StringRef( "original string" ).substr(0, 8); | ||||
|         REQUIRE( original == "original" ); | ||||
|         REQUIRE( isSubstring( original ) ); | ||||
|         REQUIRE( isOwned( original ) == false ); | ||||
|          | ||||
|         original.c_str(); // Forces it to take ownership | ||||
|          | ||||
|         REQUIRE( isSubstring( original ) == false ); | ||||
|         REQUIRE( isOwned( original ) ); | ||||
|          | ||||
|     } | ||||
|      | ||||
|      | ||||
|     SECTION( "Substrings" ) { | ||||
|         StringRef s = "hello world!"; | ||||
|         StringRef ss = s.substr(0, 5); | ||||
|          | ||||
|         SECTION( "zero-based substring" ) { | ||||
|             REQUIRE( ss.empty() == false ); | ||||
|             REQUIRE( ss.size() == 5 ); | ||||
|             REQUIRE( std::strcmp( ss.c_str(), "hello" ) == 0 ); | ||||
|             REQUIRE( ss == "hello" ); | ||||
|         } | ||||
|         SECTION( "c_str() causes copy" ) { | ||||
|             REQUIRE( isSubstring( ss ) ); | ||||
|             REQUIRE( isOwned( ss ) == false ); | ||||
|              | ||||
|             auto rawChars = data( ss ); | ||||
|             REQUIRE( rawChars == data( s ) ); // same pointer value | ||||
|             REQUIRE( ss.c_str() != rawChars ); | ||||
|              | ||||
|             REQUIRE( isSubstring( ss ) == false ); | ||||
|             REQUIRE( isOwned( ss ) ); | ||||
|              | ||||
|             REQUIRE( data( ss ) != data( s ) ); // different pointer value | ||||
|         } | ||||
|          | ||||
|         SECTION( "non-zero-based substring") { | ||||
|             ss = s.substr( 6, 6 ); | ||||
|             REQUIRE( ss.size() == 6 ); | ||||
|             REQUIRE( std::strcmp( ss.c_str(), "world!" ) == 0 ); | ||||
|         } | ||||
|          | ||||
|         SECTION( "Pointer values of full refs should match" ) { | ||||
|             StringRef s2 = s; | ||||
|             REQUIRE( s.c_str() == s2.c_str() ); | ||||
|         } | ||||
|          | ||||
|         SECTION( "Pointer values of substring refs should not match" ) { | ||||
|             REQUIRE( s.c_str() != ss.c_str() ); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     SECTION( "Comparisons" ) { | ||||
|         REQUIRE( StringRef("hello") == StringRef("hello") ); | ||||
|         REQUIRE( StringRef("hello") != StringRef("cello") ); | ||||
|     } | ||||
|      | ||||
|     SECTION( "From string" ) { | ||||
|         String str = "hot potato"; | ||||
|         auto originalPointer = str.c_str(); | ||||
|          | ||||
|         SECTION( "Copied" ) { | ||||
|             // After a String is "copied" to a StringRef | ||||
|             // It has only copied the pointer and size | ||||
|             // - it does not take ownership | ||||
|             StringRef copied = str; | ||||
|             REQUIRE( copied == "hot potato" ); | ||||
|             REQUIRE( str == "hot potato" ); | ||||
|             REQUIRE( isOwned( copied ) == false ); | ||||
|             REQUIRE( data( copied ) == originalPointer ); | ||||
|         } | ||||
|         SECTION( "Moved" ) { | ||||
|             // After a String is *moved* to a StringRef | ||||
|             // The StringRef takes ownership of the underlying data | ||||
|             // and the String is left in an empty state | ||||
|             StringRef copied = std::move( str ); | ||||
|             REQUIRE( copied == "hot potato" ); | ||||
|             REQUIRE( isOwned( copied ) ); | ||||
|             REQUIRE( str.empty() ); | ||||
|             REQUIRE( data( copied ) == originalPointer ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash