testStringAlgorithms.cxx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmConfigure.h" // IWYU pragma: keep
  4. #include <iostream>
  5. #include <sstream>
  6. #include <string>
  7. #include <utility>
  8. #include <vector>
  9. #include <cm/string_view>
  10. #include "cmStringAlgorithms.h"
  11. int testStringAlgorithms(int /*unused*/, char* /*unused*/[])
  12. {
  13. int failed = 0;
  14. auto assert_ok = [&failed](bool test, cm::string_view title) {
  15. if (test) {
  16. std::cout << "Passed: " << title << "\n";
  17. } else {
  18. std::cout << "Failed: " << title << "\n";
  19. ++failed;
  20. }
  21. };
  22. auto assert_string = [&failed](cm::string_view generated,
  23. cm::string_view expected,
  24. cm::string_view title) {
  25. if (generated == expected) {
  26. std::cout << "Passed: " << title << "\n";
  27. } else {
  28. std::cout << "Failed: " << title << "\n";
  29. std::cout << "Expected: " << expected << "\n";
  30. std::cout << "Got: " << generated << "\n";
  31. ++failed;
  32. }
  33. };
  34. // ----------------------------------------------------------------------
  35. // Test cmTrimWhitespace
  36. {
  37. std::string base = "base";
  38. std::string spaces = " \f\f\n\n\r\r\t\t\v\v";
  39. assert_string(cmTrimWhitespace(spaces + base), base,
  40. "cmTrimWhitespace front");
  41. assert_string(cmTrimWhitespace(base + spaces), base,
  42. "cmTrimWhitespace back");
  43. assert_string(cmTrimWhitespace(spaces + base + spaces), base,
  44. "cmTrimWhitespace front and back");
  45. }
  46. // ----------------------------------------------------------------------
  47. // Test cmRemoveQuotes
  48. {
  49. auto test = [&assert_string](cm::string_view source,
  50. cm::string_view expected,
  51. cm::string_view title) {
  52. assert_string(cmRemoveQuotes(source), expected, title);
  53. };
  54. test("", "", "cmRemoveQuotes empty");
  55. test("\"", "\"", "cmRemoveQuotes single quote");
  56. test("\"\"", "", "cmRemoveQuotes double quote");
  57. test("\"a", "\"a", "cmRemoveQuotes quote char");
  58. test("\"ab", "\"ab", "cmRemoveQuotes quote char char");
  59. test("a\"", "a\"", "cmRemoveQuotes char quote");
  60. test("ab\"", "ab\"", "cmRemoveQuotes char char quote");
  61. test("a", "a", "cmRemoveQuotes single char");
  62. test("ab", "ab", "cmRemoveQuotes two chars");
  63. test("abc", "abc", "cmRemoveQuotes three chars");
  64. test("\"abc\"", "abc", "cmRemoveQuotes quoted chars");
  65. test("\"\"abc\"\"", "\"abc\"", "cmRemoveQuotes quoted quoted chars");
  66. }
  67. // ----------------------------------------------------------------------
  68. // Test cmEscapeQuotes
  69. {
  70. assert_string(cmEscapeQuotes("plain"), "plain", "cmEscapeQuotes plain");
  71. std::string base = "\"base\"\"";
  72. std::string result = "\\\"base\\\"\\\"";
  73. assert_string(cmEscapeQuotes(base), result, "cmEscapeQuotes escaped");
  74. }
  75. // ----------------------------------------------------------------------
  76. // Test cmJoin
  77. {
  78. typedef std::string ST;
  79. typedef std::vector<std::string> VT;
  80. assert_string(cmJoin(ST("abc"), ";"), "a;b;c", "cmJoin std::string");
  81. assert_string(cmJoin(VT{}, ";"), "", "cmJoin std::vector empty");
  82. assert_string(cmJoin(VT{ "a" }, ";"), "a", "cmJoin std::vector single");
  83. assert_string(cmJoin(VT{ "a", "b", "c" }, ";"), "a;b;c",
  84. "cmJoin std::vector multiple");
  85. assert_string(cmJoin(VT{ "a", "b", "c" }, "<=>"), "a<=>b<=>c",
  86. "cmJoin std::vector long sep");
  87. }
  88. // ----------------------------------------------------------------------
  89. // Test cmTokenize
  90. {
  91. typedef std::vector<std::string> VT;
  92. assert_ok(cmTokenize("", ";") == VT{ "" }, "cmTokenize empty");
  93. assert_ok(cmTokenize(";", ";") == VT{ "" }, "cmTokenize sep");
  94. assert_ok(cmTokenize("abc", ";") == VT{ "abc" }, "cmTokenize item");
  95. assert_ok(cmTokenize("abc;", ";") == VT{ "abc" }, "cmTokenize item sep");
  96. assert_ok(cmTokenize(";abc", ";") == VT{ "abc" }, "cmTokenize sep item");
  97. assert_ok(cmTokenize("abc;;efg", ";") == VT{ "abc", "efg" },
  98. "cmTokenize item sep sep item");
  99. assert_ok(cmTokenize("a1;a2;a3;a4", ";") == VT{ "a1", "a2", "a3", "a4" },
  100. "cmTokenize multiple items");
  101. }
  102. // ----------------------------------------------------------------------
  103. // Test cmStrCat
  104. {
  105. int ni = -1100;
  106. unsigned int nui = 1100u;
  107. long int nli = -12000l;
  108. unsigned long int nuli = 12000ul;
  109. long long int nlli = -130000ll;
  110. unsigned long long int nulli = 130000ull;
  111. std::string val =
  112. cmStrCat("<test>", ni, ',', nui, ',', nli, ",", nuli, ", ", nlli,
  113. std::string(", "), nulli, cm::string_view("</test>"));
  114. std::string expect =
  115. "<test>-1100,1100,-12000,12000, -130000, 130000</test>";
  116. assert_string(val, expect, "cmStrCat strings and integers");
  117. }
  118. {
  119. float const val = 1.5f;
  120. float const div = 0.00001f;
  121. float f = 0.0f;
  122. std::istringstream(cmStrCat("", val)) >> f;
  123. f -= val;
  124. assert_ok((f < div) && (f > -div), "cmStrCat float");
  125. }
  126. {
  127. double const val = 1.5;
  128. double const div = 0.00001;
  129. double d = 0.0;
  130. std::istringstream(cmStrCat("", val)) >> d;
  131. d -= val;
  132. assert_ok((d < div) && (d > -div), "cmStrCat double");
  133. }
  134. {
  135. std::string val;
  136. std::string expect;
  137. val.reserve(50 * cmStrLen("cmStrCat move ") + 1);
  138. auto data = val.data();
  139. auto capacity = val.capacity();
  140. bool moved = true;
  141. for (int i = 0; i < 100; i++) {
  142. if (i % 2 == 0) {
  143. val = cmStrCat(std::move(val), "move ");
  144. expect += "move ";
  145. } else {
  146. val = cmStrCat("cmStrCat ", std::move(val));
  147. expect = "cmStrCat " + std::move(expect);
  148. }
  149. if (val.data() != data || val.capacity() != capacity) {
  150. moved = false;
  151. }
  152. }
  153. assert_ok(moved, "cmStrCat move");
  154. assert_string(val, expect, "cmStrCat move");
  155. }
  156. // ----------------------------------------------------------------------
  157. // Test cmWrap
  158. {
  159. typedef std::vector<std::string> VT;
  160. assert_string(cmWrap("<", VT{}, ">", "; "), //
  161. "", //
  162. "cmWrap empty, string prefix and suffix");
  163. assert_string(cmWrap("<", VT{ "abc" }, ">", "; "), //
  164. "<abc>", //
  165. "cmWrap single, string prefix and suffix");
  166. assert_string(cmWrap("<", VT{ "a1", "a2", "a3" }, ">", "; "), //
  167. "<a1>; <a2>; <a3>", //
  168. "cmWrap multiple, string prefix and suffix");
  169. assert_string(cmWrap('<', VT{}, '>', "; "), //
  170. "", //
  171. "cmWrap empty, char prefix and suffix");
  172. assert_string(cmWrap('<', VT{ "abc" }, '>', "; "), //
  173. "<abc>", //
  174. "cmWrap single, char prefix and suffix");
  175. assert_string(cmWrap('<', VT{ "a1", "a2", "a3" }, '>', "; "), //
  176. "<a1>; <a2>; <a3>", //
  177. "cmWrap multiple, char prefix and suffix");
  178. }
  179. // ----------------------------------------------------------------------
  180. // Test cmHas(Literal)Prefix and cmHas(Literal)Suffix
  181. {
  182. std::string str("abc");
  183. assert_ok(cmHasPrefix(str, 'a'), "cmHasPrefix char");
  184. assert_ok(!cmHasPrefix(str, 'c'), "cmHasPrefix char not");
  185. assert_ok(cmHasPrefix(str, "ab"), "cmHasPrefix string");
  186. assert_ok(!cmHasPrefix(str, "bc"), "cmHasPrefix string not");
  187. assert_ok(cmHasPrefix(str, str), "cmHasPrefix complete string");
  188. assert_ok(cmHasLiteralPrefix(str, "ab"), "cmHasLiteralPrefix string");
  189. assert_ok(!cmHasLiteralPrefix(str, "bc"), "cmHasLiteralPrefix string not");
  190. assert_ok(cmHasSuffix(str, 'c'), "cmHasSuffix char");
  191. assert_ok(!cmHasSuffix(str, 'a'), "cmHasSuffix char not");
  192. assert_ok(cmHasSuffix(str, "bc"), "cmHasSuffix string");
  193. assert_ok(!cmHasSuffix(str, "ab"), "cmHasSuffix string not");
  194. assert_ok(cmHasSuffix(str, str), "cmHasSuffix complete string");
  195. assert_ok(cmHasLiteralSuffix(str, "bc"), "cmHasLiteralSuffix string");
  196. assert_ok(!cmHasLiteralSuffix(str, "ab"), "cmHasLiteralPrefix string not");
  197. }
  198. // ----------------------------------------------------------------------
  199. // Test cmStrToLong
  200. {
  201. long value;
  202. assert_ok(cmStrToLong("1", &value) && value == 1,
  203. "cmStrToLong parses a positive decimal integer.");
  204. assert_ok(cmStrToLong(" 1", &value) && value == 1,
  205. "cmStrToLong parses a decimal integer after whitespace.");
  206. assert_ok(cmStrToLong("-1", &value) && value == -1,
  207. "cmStrToLong parses a negative decimal integer.");
  208. assert_ok(
  209. cmStrToLong(" -1", &value) && value == -1,
  210. "cmStrToLong parses a negative decimal integer after whitespace.");
  211. assert_ok(!cmStrToLong("1x", &value),
  212. "cmStrToLong rejects trailing content.");
  213. }
  214. // ----------------------------------------------------------------------
  215. // Test cmStrToULong
  216. {
  217. unsigned long value;
  218. assert_ok(cmStrToULong("1", &value) && value == 1,
  219. "cmStrToULong parses a decimal integer.");
  220. assert_ok(cmStrToULong(" 1", &value) && value == 1,
  221. "cmStrToULong parses a decimal integer after whitespace.");
  222. assert_ok(!cmStrToULong("-1", &value),
  223. "cmStrToULong rejects a negative number.");
  224. assert_ok(!cmStrToULong(" -1", &value),
  225. "cmStrToULong rejects a negative number after whitespace.");
  226. assert_ok(!cmStrToULong("1x", &value),
  227. "cmStrToULong rejects trailing content.");
  228. }
  229. // ----------------------------------------------------------------------
  230. // Test cmStrToLongLong
  231. {
  232. long long value;
  233. assert_ok(cmStrToLongLong("1", &value) && value == 1,
  234. "cmStrToLongLong parses a positive decimal integer.");
  235. assert_ok(cmStrToLongLong(" 1", &value) && value == 1,
  236. "cmStrToLongLong parses a decimal integer after whitespace.");
  237. assert_ok(cmStrToLongLong("-1", &value) && value == -1,
  238. "cmStrToLongLong parses a negative decimal integer.");
  239. assert_ok(
  240. cmStrToLongLong(" -1", &value) && value == -1,
  241. "cmStrToLongLong parses a negative decimal integer after whitespace.");
  242. assert_ok(!cmStrToLongLong("1x", &value),
  243. "cmStrToLongLong rejects trailing content.");
  244. }
  245. // ----------------------------------------------------------------------
  246. // Test cmStrToULongLong
  247. {
  248. unsigned long long value;
  249. assert_ok(cmStrToULongLong("1", &value) && value == 1,
  250. "cmStrToULongLong parses a decimal integer.");
  251. assert_ok(cmStrToULongLong(" 1", &value) && value == 1,
  252. "cmStrToULongLong parses a decimal integer after whitespace.");
  253. assert_ok(!cmStrToULongLong("-1", &value),
  254. "cmStrToULongLong rejects a negative number.");
  255. assert_ok(!cmStrToULongLong(" -1", &value),
  256. "cmStrToULongLong rejects a negative number after whitespace.");
  257. assert_ok(!cmStrToULongLong("1x", &value),
  258. "cmStrToULongLong rejects trailing content.");
  259. }
  260. // ----------------------------------------------------------------------
  261. // Test cmStrLen
  262. {
  263. constexpr auto len = cmStrLen("Hello world!");
  264. assert_ok(len == 12,
  265. "cmStrLen returns length of non-empty literal string");
  266. assert_ok(cmStrLen("") == 0,
  267. "cmStrLen returns length of empty literal string");
  268. }
  269. return failed;
  270. }