2017-11-13 16:38:52 +01:00
# include "internal/catch_stringref.h"
2017-06-29 12:18:14 +02:00
# include "catch.hpp"
2017-06-29 12:43:20 +02:00
# include <cstring>
2017-06-29 12:18:14 +02:00
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 ( ) ;
}
} ;
2018-07-02 11:13:07 +02:00
namespace {
2017-06-29 12:18:14 +02:00
auto isOwned ( StringRef const & stringRef ) - > bool {
return StringRefTestAccess : : isOwned ( stringRef ) ;
}
auto isSubstring ( StringRef const & stringRef ) - > bool {
return StringRefTestAccess : : isSubstring ( stringRef ) ;
}
2018-07-02 11:13:07 +02:00
} // end anonymous namespace
2017-06-29 12:18:14 +02:00
} // namespace Catch
2018-02-08 13:10:12 +01:00
TEST_CASE ( " StringRef " , " [Strings][StringRef] " ) {
2017-06-29 12:18:14 +02:00
using Catch : : StringRef ;
2018-07-02 11:13:07 +02:00
using Catch : : isOwned ; using Catch : : isSubstring ;
2017-08-14 10:04:14 +02:00
2017-06-29 12:18:14 +02:00
SECTION ( " Empty string " ) {
StringRef empty ;
REQUIRE ( empty . empty ( ) ) ;
REQUIRE ( empty . size ( ) = = 0 ) ;
REQUIRE ( std : : strcmp ( empty . c_str ( ) , " " ) = = 0 ) ;
}
2018-02-08 13:10:12 +01:00
2017-06-29 12:18:14 +02:00
SECTION ( " From string literal " ) {
StringRef s = " hello " ;
REQUIRE ( s . empty ( ) = = false ) ;
REQUIRE ( s . size ( ) = = 5 ) ;
REQUIRE ( isSubstring ( s ) = = false ) ;
2018-02-08 13:10:12 +01:00
2018-02-28 22:05:01 +01:00
auto rawChars = s . currentData ( ) ;
2017-06-29 12:18:14 +02:00
REQUIRE ( std : : strcmp ( rawChars , " hello " ) = = 0 ) ;
2018-02-08 13:10:12 +01:00
2017-06-29 12:18:14 +02:00
SECTION ( " c_str() does not cause copy " ) {
REQUIRE ( isOwned ( s ) = = false ) ;
2018-02-08 13:10:12 +01:00
2017-06-29 12:18:14 +02:00
REQUIRE ( s . c_str ( ) = = rawChars ) ;
2018-02-08 13:10:12 +01:00
2017-06-29 12:18:14 +02:00
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 ) ;
2018-02-08 13:10:12 +01:00
2017-06-29 12:18:14 +02:00
original . c_str ( ) ; // Forces it to take ownership
2018-02-08 13:10:12 +01:00
2017-06-29 12:18:14 +02:00
REQUIRE ( isOwned ( original ) ) ;
}
2018-02-08 13:10:12 +01:00
2017-06-29 12:18:14 +02:00
SECTION ( " Substrings " ) {
StringRef s = " hello world! " ;
StringRef ss = s . substr ( 0 , 5 ) ;
2018-02-08 13:10:12 +01:00
2017-06-29 12:18:14 +02:00
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 ) ;
2018-02-08 13:10:12 +01:00
2018-02-28 22:05:01 +01:00
auto rawChars = ss . currentData ( ) ;
REQUIRE ( rawChars = = s . currentData ( ) ) ; // same pointer value
2017-06-29 12:18:14 +02:00
REQUIRE ( ss . c_str ( ) ! = rawChars ) ;
2018-02-08 13:10:12 +01:00
2017-06-29 12:18:14 +02:00
REQUIRE ( isOwned ( ss ) ) ;
2018-02-08 13:10:12 +01:00
2019-05-18 18:54:06 +02:00
SECTION ( " Self-assignment after substring " ) {
2019-05-21 00:56:55 +02:00
ss = * & ss ; // the *& are there to suppress warnings (see: "Improvements to Clang's diagnostics" in https://rev.ng/gitlab/revng-bar-2019/clang/raw/master/docs/ReleaseNotes.rst)
2019-05-21 01:04:19 +02:00
REQUIRE ( isOwned ( ss ) = = false ) ;
REQUIRE ( ss = = " hello " ) ;
REQUIRE ( rawChars = = ss . currentData ( ) ) ; // same pointer value
2019-05-18 18:54:06 +02:00
}
2017-06-29 12:18:14 +02:00
}
2018-02-08 13:10:12 +01:00
2017-06-29 12:18:14 +02:00
SECTION ( " non-zero-based substring " ) {
ss = s . substr ( 6 , 6 ) ;
REQUIRE ( ss . size ( ) = = 6 ) ;
REQUIRE ( std : : strcmp ( ss . c_str ( ) , " world! " ) = = 0 ) ;
}
2018-02-08 13:10:12 +01:00
2017-06-29 12:18:14 +02:00
SECTION ( " Pointer values of full refs should match " ) {
StringRef s2 = s ;
REQUIRE ( s . c_str ( ) = = s2 . c_str ( ) ) ;
}
2018-02-08 13:10:12 +01:00
2017-06-29 12:18:14 +02:00
SECTION ( " Pointer values of substring refs should not match " ) {
REQUIRE ( s . c_str ( ) ! = ss . c_str ( ) ) ;
}
}
2018-02-08 13:10:12 +01:00
2017-06-29 12:18:14 +02:00
SECTION ( " Comparisons " ) {
REQUIRE ( StringRef ( " hello " ) = = StringRef ( " hello " ) ) ;
REQUIRE ( StringRef ( " hello " ) ! = StringRef ( " cello " ) ) ;
}
2017-08-14 09:39:14 +02:00
SECTION ( " from std::string " ) {
std : : string stdStr = " a standard string " ;
SECTION ( " implicitly constructed " ) {
StringRef sr = stdStr ;
REQUIRE ( sr = = " a standard string " ) ;
REQUIRE ( sr . size ( ) = = stdStr . size ( ) ) ;
}
SECTION ( " explicitly constructed " ) {
StringRef sr ( stdStr ) ;
REQUIRE ( sr = = " a standard string " ) ;
REQUIRE ( sr . size ( ) = = stdStr . size ( ) ) ;
}
SECTION ( " assigned " ) {
StringRef sr ;
sr = stdStr ;
REQUIRE ( sr = = " a standard string " ) ;
REQUIRE ( sr . size ( ) = = stdStr . size ( ) ) ;
}
}
SECTION ( " to std::string " ) {
StringRef sr = " a stringref " ;
SECTION ( " implicitly constructed " ) {
std : : string stdStr = sr ;
REQUIRE ( stdStr = = " a stringref " ) ;
REQUIRE ( stdStr . size ( ) = = sr . size ( ) ) ;
}
SECTION ( " explicitly constructed " ) {
std : : string stdStr ( sr ) ;
REQUIRE ( stdStr = = " a stringref " ) ;
REQUIRE ( stdStr . size ( ) = = sr . size ( ) ) ;
}
SECTION ( " assigned " ) {
std : : string stdStr ;
stdStr = sr ;
REQUIRE ( stdStr = = " a stringref " ) ;
REQUIRE ( stdStr . size ( ) = = sr . size ( ) ) ;
}
}
2018-02-08 13:10:12 +01:00
SECTION ( " Counting utf-8 codepoints " ) {
StringRef ascii = " just a plain old boring ascii string... " ;
REQUIRE ( ascii . numberOfCharacters ( ) = = ascii . size ( ) ) ;
StringRef simpleu8 = u8 " Trocha češtiny nikoho nezabila " ;
REQUIRE ( simpleu8 . numberOfCharacters ( ) = = 30 ) ;
StringRef emojis = u8 " Here be 👾 " ;
REQUIRE ( emojis . numberOfCharacters ( ) = = 9 ) ;
}
2017-06-29 12:18:14 +02:00
}
2017-11-13 17:03:27 +01:00
2018-02-08 13:10:12 +01:00
TEST_CASE ( " replaceInPlace " , " [Strings][StringManip] " ) {
2017-11-13 17:03:27 +01:00
std : : string letters = " abcdefcg " ;
SECTION ( " replace single char " ) {
CHECK ( Catch : : replaceInPlace ( letters , " b " , " z " ) ) ;
CHECK ( letters = = " azcdefcg " ) ;
}
SECTION ( " replace two chars " ) {
CHECK ( Catch : : replaceInPlace ( letters , " c " , " z " ) ) ;
CHECK ( letters = = " abzdefzg " ) ;
}
SECTION ( " replace first char " ) {
CHECK ( Catch : : replaceInPlace ( letters , " a " , " z " ) ) ;
CHECK ( letters = = " zbcdefcg " ) ;
}
SECTION ( " replace last char " ) {
CHECK ( Catch : : replaceInPlace ( letters , " g " , " z " ) ) ;
CHECK ( letters = = " abcdefcz " ) ;
}
SECTION ( " replace all chars " ) {
CHECK ( Catch : : replaceInPlace ( letters , letters , " replaced " ) ) ;
CHECK ( letters = = " replaced " ) ;
}
SECTION ( " replace no chars " ) {
CHECK_FALSE ( Catch : : replaceInPlace ( letters , " x " , " z " ) ) ;
CHECK ( letters = = letters ) ;
}
SECTION ( " escape ' " ) {
std : : string s = " didn't " ;
CHECK ( Catch : : replaceInPlace ( s , " ' " , " |' " ) ) ;
CHECK ( s = = " didn|'t " ) ;
}
}
2019-04-04 16:55:46 +02:00
TEST_CASE ( " splitString " , " [Strings] " ) {
using namespace Catch : : Matchers ;
2019-04-21 19:03:44 +02:00
using Catch : : splitStringRef ;
using Catch : : StringRef ;
2019-04-04 16:55:46 +02:00
2019-04-21 19:03:44 +02:00
CHECK_THAT ( splitStringRef ( " " , ' , ' ) , Equals ( std : : vector < StringRef > ( ) ) ) ;
CHECK_THAT ( splitStringRef ( " abc " , ' , ' ) , Equals ( std : : vector < StringRef > { " abc " } ) ) ;
CHECK_THAT ( splitStringRef ( " abc,def " , ' , ' ) , Equals ( std : : vector < StringRef > { " abc " , " def " } ) ) ;
2019-04-04 16:55:46 +02:00
}