2017-11-13 15:38:52 +00:00
#include "internal/catch_stringref.h"
2017-06-29 11:18:14 +01:00
#include "catch.hpp"
2017-06-29 11:43:20 +01:00
#include <cstring>
2017-06-29 11:18:14 +01: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 11:18:14 +01: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 11:18:14 +01:00
} // namespace Catch
2018-02-08 13:10:12 +01:00
TEST_CASE ( "StringRef" , "[Strings][StringRef]" ) {
2017-06-29 11:18:14 +01:00
using Catch :: StringRef ;
2018-07-02 11:13:07 +02:00
using Catch :: isOwned ; using Catch :: isSubstring ;
2017-08-14 09:04:14 +01:00
2017-06-29 11:18:14 +01: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 11:18:14 +01: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 11:18:14 +01:00
REQUIRE ( std :: strcmp ( rawChars , "hello" ) == 0 );
2018-02-08 13:10:12 +01:00
2017-06-29 11:18:14 +01:00
SECTION ( "c_str() does not cause copy" ) {
REQUIRE ( isOwned ( s ) == false );
2018-02-08 13:10:12 +01:00
2017-06-29 11:18:14 +01:00
REQUIRE ( s . c_str () == rawChars );
2018-02-08 13:10:12 +01:00
2017-06-29 11:18:14 +01: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 11:18:14 +01:00
original . c_str (); // Forces it to take ownership
2018-02-08 13:10:12 +01:00
2017-06-29 11:18:14 +01:00
REQUIRE ( isOwned ( original ) );
}
2018-02-08 13:10:12 +01:00
2017-06-29 11:18:14 +01:00
SECTION ( "Substrings" ) {
StringRef s = "hello world!" ;
StringRef ss = s . substr ( 0 , 5 );
2018-02-08 13:10:12 +01:00
2017-06-29 11:18:14 +01: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 11:18:14 +01:00
REQUIRE ( ss . c_str () != rawChars );
2018-02-08 13:10:12 +01:00
2017-06-29 11:18:14 +01:00
REQUIRE ( isOwned ( ss ) );
2018-02-08 13:10:12 +01:00
2019-05-18 17:54:06 +01:00
SECTION ( "Self-assignment after substring" ) {
2019-05-20 23:56:55 +01: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 00:04:19 +01:00
REQUIRE ( isOwned ( ss ) == false );
REQUIRE ( ss == "hello" );
REQUIRE ( rawChars == ss . currentData () ); // same pointer value
2019-05-18 17:54:06 +01:00
}
2017-06-29 11:18:14 +01:00
}
2018-02-08 13:10:12 +01:00
2017-06-29 11:18:14 +01: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 11:18:14 +01: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 11:18:14 +01: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 11:18:14 +01:00
}
2018-02-08 13:10:12 +01:00
2017-06-29 11:18:14 +01:00
SECTION ( "Comparisons" ) {
REQUIRE ( StringRef ( "hello" ) == StringRef ( "hello" ) );
REQUIRE ( StringRef ( "hello" ) != StringRef ( "cello" ) );
}
2017-08-14 08:39:14 +01: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 08:39:14 +01:00
REQUIRE ( stdStr == "a stringref" );
REQUIRE ( stdStr . size () == sr . size () );
}
}
2017-06-29 11:18:14 +01:00
}