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 ( ) ) ;
}
2019-09-08 21:04:23 +02:00
SECTION ( " Past the end substring " ) {
REQUIRE ( s . substr ( s . size ( ) + 1 , 123 ) . empty ( ) ) ;
}
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 ( " 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 ( " explicitly constructed " ) {
std : : string stdStr ( sr ) ;
REQUIRE ( stdStr = = " a stringref " ) ;
REQUIRE ( stdStr . size ( ) = = sr . size ( ) ) ;
}
SECTION ( " assigned " ) {
std : : string stdStr ;
2019-09-08 14:49:40 +02:00
stdStr = static_cast < std : : string > ( sr ) ;
2017-08-14 09:39:14 +02:00
REQUIRE ( stdStr = = " a stringref " ) ;
REQUIRE ( stdStr . size ( ) = = sr . size ( ) ) ;
}
}
2017-06-29 12:18:14 +02:00
}