StringOp_test.cc 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #include "catch.hpp"
  2. #include "StringOp.hh"
  3. #include <type_traits>
  4. using namespace StringOp;
  5. using std::string;
  6. using std::string_view;
  7. using std::vector;
  8. static void testStringToInt(const string& s, bool ok, int expected)
  9. {
  10. int result;
  11. bool success = stringToInt(s, result);
  12. REQUIRE(success == ok);
  13. if (ok) {
  14. CHECK(result == expected);
  15. CHECK(stringToInt(s) == expected);
  16. }
  17. }
  18. static void checkTrimRight(const string& s, char c, const string& expected)
  19. {
  20. string test = s;
  21. trimRight(test, c);
  22. CHECK(test == expected);
  23. string_view ref = s;
  24. trimRight(ref, c);
  25. CHECK(ref == expected);
  26. }
  27. static void checkTrimRight(const string& s, const char* chars, const string& expected)
  28. {
  29. string test = s;
  30. trimRight(test, chars);
  31. CHECK(test == expected);
  32. string_view ref = s;
  33. trimRight(ref, chars);
  34. CHECK(ref == expected);
  35. }
  36. static void checkTrimLeft(const string& s, char c, const string& expected)
  37. {
  38. string test = s;
  39. trimLeft(test, c);
  40. CHECK(test == expected);
  41. string_view ref = s;
  42. trimLeft(ref, c);
  43. CHECK(ref == expected);
  44. }
  45. static void checkTrimLeft(const string& s, const char* chars, const string& expected)
  46. {
  47. string test = s;
  48. trimLeft(test, chars);
  49. CHECK(test == expected);
  50. string_view ref = s;
  51. trimLeft(ref, chars);
  52. CHECK(ref == expected);
  53. }
  54. static void checkSplitOnFirst(const string& s, const string& first, const string& last)
  55. {
  56. auto [f1, l1] = splitOnFirst(s, '-');
  57. auto [f2, l2] = splitOnFirst(s, " -+");
  58. static_assert(std::is_same_v<decltype(f1), std::string_view>);
  59. static_assert(std::is_same_v<decltype(f2), std::string_view>);
  60. static_assert(std::is_same_v<decltype(l1), std::string_view>);
  61. static_assert(std::is_same_v<decltype(l2), std::string_view>);
  62. CHECK(f1 == first);
  63. CHECK(f2 == first);
  64. CHECK(l1 == last);
  65. CHECK(l2 == last);
  66. }
  67. static void checkSplitOnLast(const string& s, const string& first, const string& last)
  68. {
  69. auto [f1, l1] = splitOnLast(s, '-');
  70. auto [f2, l2] = splitOnLast(s, " -+");
  71. static_assert(std::is_same_v<decltype(f1), std::string_view>);
  72. static_assert(std::is_same_v<decltype(f2), std::string_view>);
  73. static_assert(std::is_same_v<decltype(l1), std::string_view>);
  74. static_assert(std::is_same_v<decltype(l2), std::string_view>);
  75. CHECK(f1 == first);
  76. CHECK(f2 == first);
  77. CHECK(l1 == last);
  78. CHECK(l2 == last);
  79. }
  80. static void checkSplit(const string& s, const vector<string_view> expected)
  81. {
  82. CHECK(split(s, '-') == expected);
  83. }
  84. static void checkParseRange(const string& s, const vector<unsigned>& expected)
  85. {
  86. CHECK(parseRange(s, 0, 99) == expected);
  87. }
  88. TEST_CASE("StringOp")
  89. {
  90. SECTION("stringToXXX") {
  91. testStringToInt("", true, 0);
  92. testStringToInt("0", true, 0);
  93. testStringToInt("1234", true, 1234);
  94. testStringToInt("-1234", true, -1234);
  95. testStringToInt("0xabcd", true, 43981);
  96. testStringToInt("0x7fffffff", true, 2147483647);
  97. testStringToInt("-0x80000000", true, -2147483648);
  98. testStringToInt("bla", false, 0);
  99. //testStringToInt("0x80000000", true, 0); not detected correctly
  100. // TODO stringToUint
  101. // TODO stringToUint64
  102. CHECK(stringToBool("0") == false);
  103. CHECK(stringToBool("1") == true);
  104. CHECK(stringToBool("Yes") == true);
  105. CHECK(stringToBool("yes") == true);
  106. CHECK(stringToBool("YES") == true);
  107. CHECK(stringToBool("No") == false);
  108. CHECK(stringToBool("no") == false);
  109. CHECK(stringToBool("NO") == false);
  110. CHECK(stringToBool("True") == true);
  111. CHECK(stringToBool("true") == true);
  112. CHECK(stringToBool("TRUE") == true);
  113. CHECK(stringToBool("False") == false);
  114. CHECK(stringToBool("false") == false);
  115. CHECK(stringToBool("FALSE") == false);
  116. // These two behave different as Tcl
  117. CHECK(stringToBool("2") == false); // is true in Tcl
  118. CHECK(stringToBool("foobar") == false); // is error in Tcl
  119. // TODO stringToDouble
  120. }
  121. SECTION("toLower") {
  122. CHECK(toLower("") == "");
  123. CHECK(toLower("foo") == "foo");
  124. CHECK(toLower("FOO") == "foo");
  125. CHECK(toLower("fOo") == "foo");
  126. CHECK(toLower(string("FoO")) == "foo");
  127. }
  128. SECTION("startsWith") {
  129. CHECK (startsWith("foobar", "foo"));
  130. CHECK_FALSE(startsWith("foobar", "bar"));
  131. CHECK_FALSE(startsWith("ba", "bar"));
  132. CHECK (startsWith("", ""));
  133. CHECK_FALSE(startsWith("", "bar"));
  134. CHECK (startsWith("foobar", ""));
  135. CHECK (startsWith("foobar", 'f'));
  136. CHECK_FALSE(startsWith("foobar", 'b'));
  137. CHECK_FALSE(startsWith("", 'b'));
  138. }
  139. SECTION("endsWith") {
  140. CHECK (endsWith("foobar", "bar"));
  141. CHECK_FALSE(endsWith("foobar", "foo"));
  142. CHECK_FALSE(endsWith("ba", "bar"));
  143. CHECK_FALSE(endsWith("ba", "baba"));
  144. CHECK (endsWith("", ""));
  145. CHECK_FALSE(endsWith("", "bar"));
  146. CHECK (endsWith("foobar", ""));
  147. CHECK (endsWith("foobar", 'r'));
  148. CHECK_FALSE(endsWith("foobar", 'o'));
  149. CHECK_FALSE(endsWith("", 'b'));
  150. }
  151. SECTION("trimRight") {
  152. checkTrimRight("", ' ', "");
  153. checkTrimRight(" ", ' ', "");
  154. checkTrimRight("foo", ' ', "foo");
  155. checkTrimRight(" foo", ' ', " foo");
  156. checkTrimRight("foo ", ' ', "foo");
  157. checkTrimRight("", "o ", "");
  158. checkTrimRight(" o ", "o ", "");
  159. checkTrimRight("foobar", "o ", "foobar");
  160. checkTrimRight(" foobar", "o ", " foobar");
  161. checkTrimRight("foo ", "o ", "f");
  162. }
  163. SECTION("trimLeft") {
  164. checkTrimLeft("", ' ', "");
  165. checkTrimLeft(" ", ' ', "");
  166. checkTrimLeft("foo", ' ', "foo");
  167. checkTrimLeft("foo ", ' ', "foo ");
  168. checkTrimLeft(" foo", ' ', "foo");
  169. checkTrimLeft("", "f ", "");
  170. checkTrimLeft(" f ", "f ", "");
  171. checkTrimLeft("foo", "f ", "oo");
  172. checkTrimLeft("barfoo ", "f ", "barfoo ");
  173. checkTrimLeft(" foo", "f ", "oo");
  174. }
  175. SECTION("splitOnFirst") {
  176. checkSplitOnFirst("", "", "");
  177. checkSplitOnFirst("-", "", "");
  178. checkSplitOnFirst("foo-", "foo", "");
  179. checkSplitOnFirst("-foo", "", "foo");
  180. checkSplitOnFirst("foo-bar", "foo", "bar");
  181. checkSplitOnFirst("foo-bar-qux", "foo", "bar-qux");
  182. checkSplitOnFirst("-bar-qux", "", "bar-qux");
  183. checkSplitOnFirst("foo-bar-", "foo", "bar-");
  184. }
  185. SECTION("splitOnLast") {
  186. checkSplitOnLast("", "", "");
  187. checkSplitOnLast("-", "", "");
  188. checkSplitOnLast("foo-", "foo", "");
  189. checkSplitOnLast("-foo", "", "foo");
  190. checkSplitOnLast("foo-bar", "foo", "bar");
  191. checkSplitOnLast("foo-bar-qux", "foo-bar", "qux");
  192. checkSplitOnLast("-bar-qux", "-bar", "qux");
  193. checkSplitOnLast("foo-bar-", "foo-bar", "");
  194. }
  195. SECTION("split") {
  196. checkSplit("", {});
  197. checkSplit("-", {""});
  198. checkSplit("foo-", {"foo"});
  199. checkSplit("-foo", {"", "foo"});
  200. checkSplit("foo-bar", {"foo", "bar"});
  201. checkSplit("foo-bar-qux", {"foo", "bar", "qux"});
  202. checkSplit("-bar-qux", {"", "bar", "qux"});
  203. checkSplit("foo-bar-", {"foo", "bar"});
  204. }
  205. SECTION("parseRange") {
  206. checkParseRange("", {});
  207. checkParseRange("5", {5});
  208. checkParseRange("5,8", {5,8});
  209. checkParseRange("5,5", {5});
  210. checkParseRange("5-7", {5,6,7});
  211. checkParseRange("7-5", {5,6,7});
  212. checkParseRange("5-7,19", {5,6,7,19});
  213. checkParseRange("15,5-7", {5,6,7,15});
  214. checkParseRange("6,5-7", {5,6,7});
  215. checkParseRange("5-8,10-12", {5,6,7,8,10,11,12});
  216. checkParseRange("5-9,6-10", {5,6,7,8,9,10});
  217. CHECK_THROWS (parseRange( "4", 5, 10));
  218. CHECK_NOTHROW(parseRange( "5", 5, 10));
  219. CHECK_NOTHROW(parseRange("10", 5, 10));
  220. CHECK_THROWS (parseRange("11", 5, 10));
  221. }
  222. SECTION("caseless") {
  223. caseless op;
  224. CHECK( op("abc", "xyz"));
  225. CHECK(!op("xyz", "abc"));
  226. CHECK(!op("abc", "abc"));
  227. CHECK( op("ABC", "xyz"));
  228. CHECK(!op("xyz", "ABC"));
  229. CHECK(!op("ABC", "abc"));
  230. CHECK( op("aBC", "Xyz"));
  231. CHECK(!op("xYz", "AbC"));
  232. CHECK(!op("ABc", "abC"));
  233. CHECK( op("abc", "ABCdef"));
  234. CHECK(!op("AbcDef", "AbC"));
  235. }
  236. SECTION("casecmp") {
  237. casecmp op;
  238. CHECK( op("abc", "abc"));
  239. CHECK( op("abc", "ABC"));
  240. CHECK(!op("abc", "xyz"));
  241. CHECK(!op("ab", "abc"));
  242. CHECK(!op("ab", "ABC"));
  243. CHECK(!op("abc", "ab"));
  244. CHECK(!op("abc", "AB"));
  245. }
  246. }