squall/test/String.cpp

673 lines
19 KiB
C++
Raw Normal View History

2020-11-14 17:18:49 -06:00
#include "storm/String.hpp"
2020-11-15 13:09:14 -06:00
#include "storm/Memory.hpp"
2020-11-14 17:18:49 -06:00
#include "test/Test.hpp"
#include <type_traits>
TEST_CASE("SStrChr const", "[string]") {
const char* string = "foobar";
static_assert(std::is_same<decltype(SStrChr(string, 'f')), const char*>::value, "Expect result to be const char*");
SECTION("finds first character when it exists at start of string") {
const char* result = SStrChr(string, 'f');
REQUIRE(result == string);
}
SECTION("finds first character when it exists in middle of string") {
const char* result = SStrChr(string, 'b');
REQUIRE(result == string + 3);
}
SECTION("finds first character when it exists at end of string") {
const char* result = SStrChr(string, 'r');
REQUIRE(result == string + 5);
}
SECTION("returns nullptr when character does not exist in string") {
const char* result = SStrChr(string, 'z');
REQUIRE(result == nullptr);
}
SECTION("returns nullptr when string is empty") {
const char* result = SStrChr("", 'z');
REQUIRE(result == nullptr);
}
SECTION("returns nullptr when character is 0") {
const char* result = SStrChr(string, '\0');
REQUIRE(result == nullptr);
}
}
2020-11-21 12:11:01 -06:00
TEST_CASE("SStrChr", "[string]") {
char* string = "foobar";
static_assert(std::is_same<decltype(SStrChr(string, 'f')), char*>::value, "Expect result to be char*");
2020-11-21 12:11:01 -06:00
SECTION("finds first character when it exists at start of string") {
char* result = SStrChr(string, 'f');
2020-11-21 12:11:01 -06:00
REQUIRE(result == string);
}
SECTION("finds first character when it exists in middle of string") {
char* result = SStrChr(string, 'b');
2020-11-21 12:11:01 -06:00
REQUIRE(result == string + 3);
}
SECTION("finds first character when it exists at end of string") {
char* result = SStrChr(string, 'r');
REQUIRE(result == string + 5);
}
SECTION("returns nullptr when character does not exist in string") {
char* result = SStrChr(string, 'z');
REQUIRE(result == nullptr);
}
SECTION("returns nullptr when string is empty") {
char* string = "";
char* result = SStrChr(string, 'z');
REQUIRE(result == nullptr);
}
SECTION("returns nullptr when character is 0") {
char* result = SStrChr(string, '\0');
REQUIRE(result == nullptr);
}
}
TEST_CASE("SStrChrR const", "[string]") {
const char* string = "ffoobbaarr";
static_assert(std::is_same<decltype(SStrChrR(string, 'f')), const char*>::value, "Expect result to be const char*");
SECTION("finds last character when it exists at start of string") {
const char* result = SStrChrR(string, 'f');
REQUIRE(result == string + 1);
}
SECTION("finds last character when it exists in middle of string") {
const char* result = SStrChrR(string, 'b');
2020-11-21 12:11:01 -06:00
REQUIRE(result == string + 5);
}
SECTION("finds last character when it exists at end of string") {
const char* result = SStrChrR(string, 'r');
REQUIRE(result == string + 9);
}
SECTION("finds last character when it exists at start and end of string") {
const char* string = "ffoobbaarrff";
const char* result = SStrChrR(string, 'f');
REQUIRE(result == string + 11);
}
2020-11-21 12:11:01 -06:00
SECTION("returns nullptr when character does not exist in string") {
const char* result = SStrChrR(string, 'z');
2020-11-21 12:11:01 -06:00
REQUIRE(result == nullptr);
}
SECTION("returns nullptr when string is empty") {
const char* result = SStrChrR("", 'z');
REQUIRE(result == nullptr);
}
SECTION("returns nullptr when character is 0") {
const char* result = SStrChrR(string, '\0');
2020-11-21 12:11:01 -06:00
REQUIRE(result == nullptr);
}
}
2020-11-21 12:49:47 -06:00
TEST_CASE("SStrChrR", "[string]") {
char* string = "ffoobbaarr";
static_assert(std::is_same<decltype(SStrChrR(string, 'f')), char*>::value, "Expect result to be char*");
2020-11-21 12:49:47 -06:00
SECTION("finds last character when it exists at start of string") {
char* result = SStrChrR(string, 'f');
2020-11-21 12:49:47 -06:00
REQUIRE(result == string + 1);
}
SECTION("finds last character when it exists in middle of string") {
char* result = SStrChrR(string, 'b');
2020-11-21 12:49:47 -06:00
REQUIRE(result == string + 5);
}
SECTION("finds last character when it exists at end of string") {
char* result = SStrChrR(string, 'r');
2020-11-21 12:49:47 -06:00
REQUIRE(result == string + 9);
}
SECTION("finds last character when it exists at start and end of string") {
char* string = "ffoobbaarrff";
char* result = SStrChrR(string, 'f');
2020-11-21 12:49:47 -06:00
REQUIRE(result == string + 11);
}
SECTION("returns nullptr when character does not exist in string") {
char* result = SStrChrR(string, 'z');
2020-11-21 12:49:47 -06:00
REQUIRE(result == nullptr);
}
SECTION("returns nullptr when string is empty") {
char* string = "";
char* result = SStrChrR(string, 'z');
REQUIRE(result == nullptr);
}
SECTION("returns nullptr when character is 0") {
char* result = SStrChrR(string, '\0');
2020-11-21 12:49:47 -06:00
REQUIRE(result == nullptr);
}
}
2020-11-14 17:58:34 -06:00
TEST_CASE("SStrCmp", "[string]") {
SECTION("compares two strings that exactly match correctly") {
auto compare = SStrCmp("foo", "foo");
2020-11-14 17:58:34 -06:00
REQUIRE(compare == 0);
}
SECTION("compares two strings that partially match correctly") {
auto compare1 = SStrCmp("bar", "foobar");
auto compare2 = SStrCmp("foobar", "bar");
2020-11-14 17:58:34 -06:00
REQUIRE(compare1 < 0);
REQUIRE(compare2 > 0);
}
SECTION("compares two strings that do not match correctly") {
auto compare = SStrCmp("bar", "xyzzy");
2020-11-14 17:58:34 -06:00
REQUIRE(compare < 0);
}
SECTION("only compares up to maxchars") {
auto compare = SStrCmp("donkeykong", "donkeypinnochio", 6);
REQUIRE(compare == 0);
}
SECTION("compare is case sensitive") {
auto compare = SStrCmp("dingdong", "dInGdOnG");
REQUIRE(compare != 0);
}
2020-11-14 17:58:34 -06:00
}
2020-11-15 12:47:41 -06:00
TEST_CASE("SStrCmpI", "[string]") {
SECTION("compares two strings that exactly match correctly") {
auto compare = SStrCmpI("foo", "foo");
2020-11-15 12:47:41 -06:00
REQUIRE(compare == 0);
}
SECTION("compares two strings that match with differing case correctly") {
auto compare = SStrCmpI("foo", "FoO");
2020-11-15 12:47:41 -06:00
REQUIRE(compare == 0);
}
SECTION("compares two strings that partially match correctly") {
auto compare1 = SStrCmpI("bar", "foobar");
auto compare2 = SStrCmpI("foobar", "bar");
REQUIRE(compare1 < 0);
REQUIRE(compare2 > 0);
}
2020-11-15 12:47:41 -06:00
SECTION("compares two strings that do not match correctly") {
auto compare = SStrCmpI("bar", "xyzzy");
2020-11-15 12:47:41 -06:00
REQUIRE(compare < 0);
}
SECTION("only compares up to maxchars") {
auto compare = SStrCmpI("donkeykong", "donkeypinnochio", 6);
REQUIRE(compare == 0);
}
2020-11-15 12:47:41 -06:00
}
2020-11-15 13:09:14 -06:00
TEST_CASE("SStrDupA", "[string]") {
SECTION("duplicates string correctly") {
auto string1 = "foo bar";
auto string2 = SStrDupA(string1, __FILE__, __LINE__);
auto compare = SStrCmp(string1, string2);
auto newPtr = string1 != string2;
SMemFree(string2);
REQUIRE(compare == 0);
REQUIRE(newPtr == true);
}
SECTION("duplicates empty string correctly") {
auto string1 = "";
auto string2 = SStrDupA(string1, __FILE__, __LINE__);
auto compare = SStrCmp(string1, string2);
2020-11-15 13:09:14 -06:00
auto newPtr = string1 != string2;
SMemFree(string2);
REQUIRE(compare == 0);
REQUIRE(newPtr == true);
}
}
2020-11-14 17:18:49 -06:00
TEST_CASE("SStrHashHT", "[string]") {
SECTION("hashes simple string correctly") {
auto hash = SStrHashHT("foo");
REQUIRE(hash == 1371562358u);
}
SECTION("hashes string with forward slash correctly") {
auto hash = SStrHashHT("foo/bar");
REQUIRE(hash == 2270424393u);
}
SECTION("hashes string with forward slash equivalent to back slash") {
auto hashForwardSlash = SStrHashHT("foo/bar");
auto hashBackSlash = SStrHashHT("foo\\bar");
REQUIRE(hashForwardSlash == hashBackSlash);
}
}
2020-11-15 12:57:32 -06:00
TEST_CASE("SStrLen", "[string]") {
SECTION("calculates string length correctly") {
REQUIRE(SStrLen("foo") == 3);
}
SECTION("calculates empty string length correctly") {
REQUIRE(SStrLen("") == 0);
2020-11-15 12:57:32 -06:00
}
}
2020-11-16 17:44:08 -06:00
2020-11-16 18:41:53 -06:00
TEST_CASE("SStrLower", "[string]") {
SECTION("rewrites uppercase string to lowercase correctly") {
char string[] = "FOOBAR";
SStrLower(string);
2020-11-16 18:41:53 -06:00
REQUIRE(!SStrCmp(string, "foobar"));
2020-11-16 18:41:53 -06:00
}
SECTION("rewrites lowercase string to lowercase correctly") {
char string[] = "foobar";
SStrLower(string);
REQUIRE(!SStrCmp(string, "foobar"));
}
SECTION("does nothing on empty string") {
char string[] = "";
SStrLower(string);
2020-11-16 18:41:53 -06:00
REQUIRE(!SStrCmp(string, ""));
2020-11-16 18:41:53 -06:00
}
}
2020-11-21 15:03:44 -06:00
TEST_CASE("SStrPack", "[string]") {
SECTION("truncates dest correctly when first byte in source is null") {
char dest[10] = {};
2020-11-21 15:03:44 -06:00
auto source = "\0foobar";
auto length = SStrPack(dest, source, sizeof(dest));
2020-11-21 15:03:44 -06:00
REQUIRE(length == 0);
REQUIRE(!SStrCmp(dest, ""));
2020-11-21 15:03:44 -06:00
}
SECTION("truncates dest correctly when middle byte in source is null") {
char dest[10] = {};
2020-11-21 15:03:44 -06:00
auto source = "foo\0bar";
auto length = SStrPack(dest, source, sizeof(dest));
2020-11-21 15:03:44 -06:00
REQUIRE(length == 3);
REQUIRE(!SStrCmp(dest, "foo"));
2020-11-21 15:03:44 -06:00
}
SECTION("does not truncate dest when source has no early null byte") {
char dest[10] = {};
2020-11-21 15:03:44 -06:00
auto source = "foobar";
auto length = SStrPack(dest, source, sizeof(dest));
REQUIRE(length == 6);
REQUIRE(!SStrCmp(dest, "foobar"));
}
SECTION("appends to target string") {
char dest[10] = "who";
auto length = SStrPack(dest, "dis", sizeof(dest));
2020-11-21 15:03:44 -06:00
REQUIRE(length == 6);
REQUIRE(!SStrCmp(dest, "whodis"));
}
SECTION("truncates when dest size is not large enough") {
char dest[5] = "who";
auto length = SStrPack(dest, "dis", sizeof(dest));
REQUIRE(length == 4);
REQUIRE(!SStrCmp(dest, "whod"));
2020-11-21 15:03:44 -06:00
}
}
2020-11-21 21:02:01 -06:00
TEST_CASE("SStrPrintf", "[string]") {
SECTION("fills dest with formatted string") {
char dest[100] = {};
auto length = SStrPrintf(dest, sizeof(dest), "%s - %s", "foo", "bar");
2020-11-21 21:02:01 -06:00
REQUIRE(length == 9);
REQUIRE(!SStrCmp(dest, "foo - bar"));
}
SECTION("fills dest with int") {
char dest[100] = {};
auto length = SStrPrintf(dest, sizeof(dest), "%d", 69);
REQUIRE(length == 2);
REQUIRE(!SStrCmp(dest, "69"));
2020-11-21 21:02:01 -06:00
}
SECTION("fills dest with empty string") {
char dest[100] = {};
auto length = SStrPrintf(dest, sizeof(dest), "");
2020-11-21 21:02:01 -06:00
REQUIRE(length == 0);
REQUIRE(!SStrCmp(dest, ""));
2020-11-21 21:02:01 -06:00
}
SECTION("truncates when dest size is not large enough") {
char dest[4] = {};
auto length = SStrPrintf(dest, sizeof(dest), "%s", "wowzers");
REQUIRE(length == 3);
REQUIRE(!SStrCmp(dest, "wow"));
}
2025-08-31 16:28:04 -07:00
SECTION("does nothing if maxchars is 0") {
char dest[10] = {};
auto length = SStrPrintf(dest, 0, "%d", 69);
REQUIRE(length == 0);
REQUIRE(!SStrCmp(dest, ""));
}
2020-11-21 21:02:01 -06:00
}
2020-11-16 17:44:08 -06:00
TEST_CASE("SStrStr", "[string]") {
auto string = "foobar";
2020-11-16 17:44:08 -06:00
SECTION("finds substring when it exists at end of string") {
auto search = "bar";
auto substring = SStrStr(string, search);
REQUIRE(substring == string + 3);
2020-11-16 17:44:08 -06:00
}
SECTION("finds substring when it exists at start of string") {
auto search = "foo";
auto substring = SStrStr(string, search);
REQUIRE(substring == string);
2020-11-16 17:44:08 -06:00
}
SECTION("finds substring when search is empty") {
auto substring = SStrStr(string, "");
REQUIRE(substring == string);
}
SECTION("returns nullptr when search does not exist in string") {
auto substring = SStrStr(string, "xyzzy");
REQUIRE(substring == nullptr);
}
2020-11-16 17:44:08 -06:00
SECTION("returns nullptr when given empty string") {
auto substring = SStrStr("", "bar");
2020-11-16 17:44:08 -06:00
REQUIRE(substring == nullptr);
}
}
2020-11-21 13:14:15 -06:00
2020-11-21 20:44:37 -06:00
TEST_CASE("SStrTokenize", "[string]") {
SECTION("finds all tokens in comma-delimited string") {
auto string = "foo,bar,baz";
char buffer[100] = {};
2020-11-21 20:44:37 -06:00
const char* tokens[] = { "foo", "bar", "baz" };
for (auto& token : tokens) {
SStrTokenize(&string, buffer, sizeof(buffer), " ,", nullptr);
REQUIRE(!SStrCmp(buffer, token));
2020-11-21 20:44:37 -06:00
}
}
SECTION("finds all tokens in comma-and-whitespace-delimited string") {
auto string = "foo , bar , baz";
char buffer[100] = {};
2020-11-21 20:44:37 -06:00
const char* tokens[] = { "foo", "bar", "baz" };
for (auto& token : tokens) {
SStrTokenize(&string, buffer, sizeof(buffer), " ,", nullptr);
REQUIRE(!SStrCmp(buffer, token));
2020-11-21 20:44:37 -06:00
}
}
SECTION("finds no tokens empty string") {
auto string = "";
char buffer[100] = {};
SStrTokenize(&string, buffer, sizeof(buffer), " ,", nullptr);
REQUIRE(!SStrCmp(buffer, ""));
2020-11-21 20:44:37 -06:00
}
SECTION("identifies quoted tokens") {
auto string = "foo bar \"baz bazinga\" bodonkers \"donga dongs\"";
char buffer[100] = {};
std::pair<const char*, int> tokens[] = {
std::make_pair("foo", 0),
std::make_pair("bar", 0),
std::make_pair("baz bazinga", 1),
std::make_pair("bodonkers", 0),
std::make_pair("donga dongs", 1)
};
for (auto& token : tokens) {
int quoted = 0;
SStrTokenize(&string, buffer, sizeof(buffer), " \"", &quoted);
std::string result = buffer;
REQUIRE(result == token.first);
REQUIRE(quoted == token.second);
}
}
SECTION("doesn't identify quoted tokens if excluded from whitespace") {
auto string = "foo bar \"baz bazinga\" bodonkers \"donga dongs\"";
char buffer[100] = {};
std::pair<const char*, int> tokens[] = {
std::make_pair("foo", 0),
std::make_pair("bar", 0),
std::make_pair("\"baz", 0),
std::make_pair("bazinga\"", 0),
std::make_pair("bodonkers", 0),
std::make_pair("\"donga", 0),
std::make_pair("dongs\"", 0)
};
for (auto& token : tokens) {
int quoted = 0;
SStrTokenize(&string, buffer, sizeof(buffer), " ", &quoted);
std::string result = buffer;
REQUIRE(result == token.first);
REQUIRE(quoted == token.second);
}
}
2020-11-21 20:44:37 -06:00
}
2020-11-21 14:05:13 -06:00
TEST_CASE("SStrToFloat", "[string]") {
SECTION("converts empty string to float") {
auto result = SStrToFloat("");
2020-11-21 14:05:13 -06:00
REQUIRE(result == 0.0f);
}
SECTION("converts whitespace string to float") {
auto result = SStrToFloat(" \t\r\n");
REQUIRE(result == 0.0f);
}
SECTION("converts random characters to float") {
auto result = SStrToFloat("abcd");
2020-11-21 14:05:13 -06:00
REQUIRE(result == 0.0f);
}
SECTION("converts string with positive int to float") {
auto result = SStrToFloat("123");
2020-11-21 14:05:13 -06:00
REQUIRE(result == 123.0f);
}
SECTION("converts string with negative int to float") {
auto result = SStrToFloat("-123");
2020-11-21 14:05:13 -06:00
REQUIRE(result == -123.0f);
}
SECTION("converts string with positive float to float") {
auto result = SStrToFloat("1.5");
2020-11-21 14:05:13 -06:00
REQUIRE(result == 1.5f);
}
SECTION("converts string with negative float to float") {
auto result = SStrToFloat("-1.5");
2020-11-21 14:05:13 -06:00
REQUIRE(result == -1.5f);
}
SECTION("converts string with float and positive exponent to float") {
auto result = SStrToFloat("1.5e3");
2020-11-21 14:05:13 -06:00
REQUIRE(result == 1500.0f);
}
SECTION("converts string with float and positive full form exponent to float") {
auto result = SStrToFloat("1.5e+3");
REQUIRE(result == 1500.0f);
}
SECTION("converts string with capital exponent to float") {
auto result = SStrToFloat("1.5E+3");
REQUIRE(result == 1500.0f);
}
SECTION("converts string with random added letter to float") {
auto result = SStrToFloat("1.5g3");
REQUIRE(result == 1.5f);
}
2020-11-21 14:05:13 -06:00
SECTION("converts string with float and negative exponent to float") {
auto result = SStrToFloat("1500.0e-3");
2020-11-21 14:05:13 -06:00
REQUIRE(result == 1.5f);
}
SECTION("converts string with zero to float") {
auto result = SStrToFloat("0");
2020-11-21 14:05:13 -06:00
REQUIRE(result == 0.0f);
}
SECTION("converts string with leading zero to float") {
auto result = SStrToFloat("01");
2020-11-21 14:05:13 -06:00
REQUIRE(result == 1.0f);
}
}
2020-11-21 13:14:15 -06:00
TEST_CASE("SStrToInt", "[string]") {
SECTION("converts empty string to int") {
auto result = SStrToInt("");
2020-11-21 13:14:15 -06:00
REQUIRE(result == 0);
}
SECTION("converts whitespace string to int") {
auto result = SStrToInt(" ");
REQUIRE(result == 0);
}
SECTION("converts random characters to int") {
auto result = SStrToInt("abcd");
2020-11-21 13:14:15 -06:00
REQUIRE(result == 0);
}
SECTION("converts string with positive number to int") {
auto result = SStrToInt("123");
2020-11-21 13:14:15 -06:00
REQUIRE(result == 123);
}
SECTION("converts string with negative number to int") {
auto result = SStrToInt("-123");
2020-11-21 13:14:15 -06:00
REQUIRE(result == -123);
}
SECTION("converts string with zero to int") {
auto result = SStrToInt("0");
2020-11-21 13:14:15 -06:00
REQUIRE(result == 0);
}
SECTION("converts string with leading zero to int") {
auto result = SStrToInt("01");
2020-11-21 13:14:15 -06:00
REQUIRE(result == 1);
}
SECTION("converts string with two whitespace-separated numbers to int") {
auto result = SStrToInt("123 456");
2020-11-21 13:14:15 -06:00
REQUIRE(result == 123);
}
}
2021-02-13 18:51:47 -06:00
2025-08-31 16:28:04 -07:00
TEST_CASE("SStrToUnsigned", "[string]") {
SECTION("converts empty string to int") {
auto result = SStrToUnsigned("");
REQUIRE(result == 0);
}
SECTION("converts whitespace string to int") {
auto result = SStrToUnsigned(" ");
REQUIRE(result == 0);
}
SECTION("converts random characters to int") {
auto result = SStrToUnsigned("abcd");
REQUIRE(result == 0);
}
SECTION("converts string with positive number to int") {
auto result = SStrToUnsigned("123");
REQUIRE(result == 123);
}
SECTION("returns 0 if number is negative") {
auto result = SStrToUnsigned("-123");
REQUIRE(result == 0);
}
SECTION("converts string with zero to int") {
auto result = SStrToUnsigned("0");
REQUIRE(result == 0);
}
SECTION("converts string with leading zero to int") {
auto result = SStrToUnsigned("01");
REQUIRE(result == 1);
}
SECTION("converts string with two whitespace-separated numbers to int") {
auto result = SStrToUnsigned("123 456");
REQUIRE(result == 123);
}
SECTION("converts max unsigned int") {
auto result = SStrToUnsigned("4294967295");
REQUIRE(result == 4294967295u);
}
}
2021-02-13 18:51:47 -06:00
TEST_CASE("SStrUpper", "[string]") {
SECTION("rewrites lowercase string to uppercase correctly") {
char string[] = "foobar";
SStrUpper(string);
2021-02-13 18:51:47 -06:00
REQUIRE(!SStrCmp(string, "FOOBAR"));
2021-02-13 18:51:47 -06:00
}
SECTION("rewrites uppercase string to uppercase correctly") {
char string[] = "FOOBAR";
SStrUpper(string);
REQUIRE(!SStrCmp(string, "FOOBAR"));
}
SECTION("does nothing on empty string") {
char string[] = "";
SStrUpper(string);
REQUIRE(!SStrCmp(string, ""));
2021-02-13 18:51:47 -06:00
}
}