forked from microsoft/GSL
Added operator==
This commit is contained in:
+221
-47
@@ -14,12 +14,10 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <UnitTest++/UnitTest++.h>
|
||||
#include <UnitTest++/UnitTest++.h>
|
||||
#include <string_span.h>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std;
|
||||
using namespace gsl;
|
||||
@@ -76,7 +74,7 @@ SUITE(string_span_tests)
|
||||
wstring_span<> v = stack_string;
|
||||
CHECK(v.length() == 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestConstructFromConstCharPointer)
|
||||
{
|
||||
@@ -89,7 +87,7 @@ SUITE(string_span_tests)
|
||||
{
|
||||
char stack_string[] = "Hello";
|
||||
string_span<> v = ensure_z(stack_string);
|
||||
cstring_span<> v2 = v;
|
||||
cstring_span<> v2 = v;
|
||||
CHECK(v.length() == v2.length());
|
||||
}
|
||||
|
||||
@@ -116,7 +114,7 @@ SUITE(string_span_tests)
|
||||
CHECK(s2.length() == 5);
|
||||
}
|
||||
|
||||
TEST(ComparisonAndImplicitConstructors)
|
||||
TEST(EqualityAndImplicitConstructors)
|
||||
{
|
||||
{
|
||||
cstring_span<> span = "Hello";
|
||||
@@ -132,25 +130,60 @@ SUITE(string_span_tests)
|
||||
CHECK(span == cstring_span<>("Hello"));
|
||||
|
||||
// comparison to static array with no null termination
|
||||
CHECK(span == cstring_span<>(ar));
|
||||
CHECK(span == cstring_span<>(ar));
|
||||
|
||||
// comparison to static array with null at the end
|
||||
CHECK(span == cstring_span<>(ar1));
|
||||
|
||||
// comparison to static array with null in the middle
|
||||
CHECK(span == cstring_span<>(ar2));
|
||||
CHECK(span == cstring_span<>(ar2));
|
||||
|
||||
// comparison to null-terminated c string
|
||||
CHECK(span == cstring_span<>(ptr, 5));
|
||||
CHECK(span == cstring_span<>(ptr, 5));
|
||||
|
||||
// comparison to string
|
||||
CHECK(span == cstring_span<>(str));
|
||||
CHECK(span == cstring_span<>(str));
|
||||
|
||||
// comparison to vector of charaters with no null termination
|
||||
CHECK(span == cstring_span<>(vec));
|
||||
CHECK(span == cstring_span<>(vec));
|
||||
|
||||
// comparison of the original data to string
|
||||
CHECK(span.data() == std::string("Hello"));
|
||||
}
|
||||
|
||||
{
|
||||
char ar[] = { 'H', 'e', 'l', 'l', 'o' };
|
||||
|
||||
string_span<> span = ar;
|
||||
|
||||
char ar1[] = "Hello";
|
||||
char ar2[10] = "Hello";
|
||||
char* ptr = ar;
|
||||
std::string str = "Hello";
|
||||
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
|
||||
|
||||
// comparison to static array with no null termination
|
||||
CHECK(span == string_span<>(ar));
|
||||
|
||||
// comparison to static array with null at the end
|
||||
CHECK(span == string_span<>(ar1));
|
||||
|
||||
// comparison to static array with null in the middle
|
||||
CHECK(span == string_span<>(ar2));
|
||||
|
||||
// comparison to null-terminated c string
|
||||
CHECK(span == string_span<>(ptr, 5));
|
||||
|
||||
// comparison to string
|
||||
CHECK(span == string_span<>(str));
|
||||
|
||||
// comparison to vector of charaters with no null termination
|
||||
CHECK(span == string_span<>(vec));
|
||||
}
|
||||
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
{
|
||||
cstring_span<> span = "Hello";
|
||||
|
||||
CHECK(span == "Hello");
|
||||
CHECK(span == ar);
|
||||
@@ -159,7 +192,7 @@ SUITE(string_span_tests)
|
||||
CHECK(span == ptr);
|
||||
CHECK(span == str);
|
||||
CHECK(span == vec);
|
||||
|
||||
|
||||
char _ar[] = { 'H', 'e', 'l', 'l', 'o' };
|
||||
char _ar1[] = "Hello";
|
||||
char _ar2[10] = "Hello";
|
||||
@@ -191,6 +224,7 @@ SUITE(string_span_tests)
|
||||
CHECK(_span == str);
|
||||
CHECK(_span == vec);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
std::vector<char> str1 = { 'H', 'e', 'l', 'l', 'o' };
|
||||
@@ -203,6 +237,78 @@ SUITE(string_span_tests)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(ComparisonAndImplicitConstructors)
|
||||
{
|
||||
{
|
||||
cstring_span<> span = "Hello";
|
||||
|
||||
const char ar[] = { 'H', 'e', 'l', 'l', 'o' };
|
||||
const char ar1[] = "Hello";
|
||||
const char ar2[10] = "Hello";
|
||||
const char* ptr = "Hello";
|
||||
const std::string str = "Hello";
|
||||
const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
|
||||
|
||||
// comparison to literal
|
||||
CHECK(span < cstring_span<>("Helloo"));
|
||||
CHECK(span > cstring_span<>("Hell"));
|
||||
|
||||
// comparison to static array with no null termination
|
||||
CHECK(span >= cstring_span<>(ar));
|
||||
|
||||
// comparison to static array with null at the end
|
||||
CHECK(span <= cstring_span<>(ar1));
|
||||
|
||||
// comparison to static array with null in the middle
|
||||
CHECK(span >= cstring_span<>(ar2));
|
||||
|
||||
// comparison to null-terminated c string
|
||||
CHECK(span <= cstring_span<>(ptr, 5));
|
||||
|
||||
// comparison to string
|
||||
CHECK(span >= cstring_span<>(str));
|
||||
|
||||
// comparison to vector of charaters with no null termination
|
||||
CHECK(span <= cstring_span<>(vec));
|
||||
}
|
||||
|
||||
{
|
||||
char ar[] = { 'H', 'e', 'l', 'l', 'o' };
|
||||
|
||||
string_span<> span = ar;
|
||||
|
||||
char larr[] = "Hell";
|
||||
char rarr[] = "Helloo";
|
||||
|
||||
char ar1[] = "Hello";
|
||||
char ar2[10] = "Hello";
|
||||
char* ptr = ar;
|
||||
std::string str = "Hello";
|
||||
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
|
||||
|
||||
|
||||
// comparison to static array with no null termination
|
||||
CHECK(span <= string_span<>(ar));
|
||||
CHECK(span < string_span<>(rarr));
|
||||
CHECK(span > string_span<>(larr));
|
||||
|
||||
// comparison to static array with null at the end
|
||||
CHECK(span >= string_span<>(ar1));
|
||||
|
||||
// comparison to static array with null in the middle
|
||||
CHECK(span <= string_span<>(ar2));
|
||||
|
||||
// comparison to null-terminated c string
|
||||
CHECK(span >= string_span<>(ptr, 5));
|
||||
|
||||
// comparison to string
|
||||
CHECK(span <= string_span<>(str));
|
||||
|
||||
// comparison to vector of charaters with no null termination
|
||||
CHECK(span >= string_span<>(vec));
|
||||
}
|
||||
}
|
||||
TEST(EnzureRemoveZ)
|
||||
{
|
||||
// remove z from literals
|
||||
@@ -226,39 +332,17 @@ SUITE(string_span_tests)
|
||||
ptr[1] = 'b';
|
||||
ptr[2] = '\0';
|
||||
|
||||
string_span<> span(ptr);
|
||||
string_span<> span = ensure_z(ptr);
|
||||
CHECK(span.length() == 2);
|
||||
|
||||
delete[] ptr;
|
||||
}
|
||||
|
||||
// ensuze z on c strings
|
||||
{
|
||||
char* ptr = new char[2];
|
||||
|
||||
ptr[0] = 'a';
|
||||
ptr[1] = 'b';
|
||||
|
||||
// do we want to have a constructor from pointer at all?
|
||||
// the behavior is unpredictable if the string is not 0-terminated
|
||||
|
||||
// CHECK_THROW((string_span<>(ptr).length() == 2), fail_fast);
|
||||
|
||||
cstring_span<> sp1{ ptr, 2 }; // good
|
||||
cstring_span<> sp2{ ptr, 3 }; // bad... but can't help there
|
||||
|
||||
CHECK(sp1[1] == 'b');
|
||||
CHECK_THROW((void)(sp1[2] == 'c'), fail_fast);
|
||||
|
||||
CHECK(sp2[1] == 'b');
|
||||
//CHECK_THROW((sp1[2] == 'c'), fail_fast); // buffer overflow
|
||||
|
||||
delete[] ptr;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Constructors)
|
||||
{
|
||||
// creating cstring_span
|
||||
|
||||
// from string temporary
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
{
|
||||
@@ -363,14 +447,12 @@ SUITE(string_span_tests)
|
||||
CHECK(span.length() == 5);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// How string_span should behave with const data
|
||||
// creating string_span
|
||||
|
||||
// from string literal
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
string_span<> span = "Hello";
|
||||
CHECK(span.length() == 5);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -401,12 +483,10 @@ SUITE(string_span_tests)
|
||||
|
||||
// from non-const ptr and length
|
||||
{
|
||||
// does not compile with GCC (ISO standard does not allows converting string literals to char*)
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
char* ptr = "Hello";
|
||||
char ar[] = { 'H', 'e', 'l', 'l', 'o' };
|
||||
char* ptr = ar;
|
||||
string_span<> span{ ptr, 5 };
|
||||
CHECK(span.length() == 5);
|
||||
#endif
|
||||
}
|
||||
|
||||
// from const string
|
||||
@@ -459,11 +539,11 @@ SUITE(string_span_tests)
|
||||
CHECK(span.length() == 5);
|
||||
}
|
||||
|
||||
// from non-const span of non-const data from const vector (looks like a bug)
|
||||
// from non-const span of non-const data from const vector
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
|
||||
const span<char> inner = vec; // fix error (happens inside the constructor)
|
||||
const span<char> inner = vec;
|
||||
string_span<> span = inner;
|
||||
CHECK(span.length() == 5);
|
||||
#endif
|
||||
@@ -500,12 +580,106 @@ SUITE(string_span_tests)
|
||||
// from const string_span of non-const data
|
||||
{
|
||||
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
|
||||
const string_span<> tmp = vec; // what does "const span" mean?
|
||||
const string_span<> tmp = vec;
|
||||
string_span<> span = tmp;
|
||||
CHECK(span.length() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T move_wrapper(T&& t)
|
||||
{
|
||||
return std::move(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T create() { return T{}; }
|
||||
|
||||
template <class T>
|
||||
void use(basic_string_span<T, gsl::dynamic_range> s) {}
|
||||
|
||||
TEST(MoveConstructors)
|
||||
{
|
||||
// move string_span
|
||||
{
|
||||
cstring_span<> span = "Hello";
|
||||
auto span1 = std::move(span);
|
||||
CHECK(span1.length() == 5);
|
||||
}
|
||||
{
|
||||
cstring_span<> span = "Hello";
|
||||
auto span1 = move_wrapper(std::move(span));
|
||||
CHECK(span1.length() == 5);
|
||||
}
|
||||
{
|
||||
cstring_span<> span = "Hello";
|
||||
auto span1 = move_wrapper(std::move(span));
|
||||
CHECK(span1.length() == 5);
|
||||
}
|
||||
|
||||
// move span
|
||||
{
|
||||
span<const char> span = ensure_z("Hello");
|
||||
cstring_span<> span1 = std::move(span);
|
||||
CHECK(span1.length() == 5);
|
||||
}
|
||||
{
|
||||
span<const char> span = ensure_z("Hello");
|
||||
cstring_span<> span2 = move_wrapper(std::move(span));
|
||||
CHECK(span2.length() == 5);
|
||||
}
|
||||
|
||||
// move string
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
std::string str = "Hello";
|
||||
string_span<> span = std::move(str);
|
||||
CHECK(span.length() == 5);
|
||||
#endif
|
||||
}
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
std::string str = "Hello";
|
||||
string_span<> span = move_wrapper<std::string>(std::move(str));
|
||||
CHECK(span.length() == 5);
|
||||
#endif
|
||||
}
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
use<char>(create<string>());
|
||||
#endif
|
||||
}
|
||||
|
||||
// move container
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
|
||||
string_span<> span = std::move(vec);
|
||||
CHECK(span.length() == 5);
|
||||
#endif
|
||||
}
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
|
||||
string_span<> span = move_wrapper<std::vector<char>>(std::move(vec));
|
||||
CHECK(span.length() == 5);
|
||||
#endif
|
||||
}
|
||||
{
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
use<char>(create<std::vector<char>>());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Conversion)
|
||||
{
|
||||
#ifdef CONFIRM_COMPPILATION_ERRORS
|
||||
cstring_span<> span = "Hello";
|
||||
cwstring_span<> wspan{ span };
|
||||
CHECK(wspan.length() == 5);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, const char *[])
|
||||
|
||||
Reference in New Issue
Block a user