string_helpers_test.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "common/string_helpers.h"
  5. #include <gmock/gmock.h>
  6. #include <gtest/gtest.h>
  7. #include <string>
  8. #include "llvm/Support/Error.h"
  9. using ::testing::Eq;
  10. using ::testing::Optional;
  11. namespace Carbon::Testing {
  12. namespace {
  13. TEST(UnescapeStringLiteral, Valid) {
  14. EXPECT_THAT(UnescapeStringLiteral("test"), Optional(Eq("test")));
  15. EXPECT_THAT(UnescapeStringLiteral("okay whitespace"),
  16. Optional(Eq("okay whitespace")));
  17. EXPECT_THAT(UnescapeStringLiteral("test\n"), Optional(Eq("test\n")));
  18. EXPECT_THAT(UnescapeStringLiteral("test\\n"), Optional(Eq("test\n")));
  19. EXPECT_THAT(UnescapeStringLiteral("abc\\ndef"), Optional(Eq("abc\ndef")));
  20. EXPECT_THAT(UnescapeStringLiteral("test\\\\n"), Optional(Eq("test\\n")));
  21. EXPECT_THAT(UnescapeStringLiteral("\\xAA"), Optional(Eq("\xAA")));
  22. EXPECT_THAT(UnescapeStringLiteral("\\x12"), Optional(Eq("\x12")));
  23. EXPECT_THAT(UnescapeStringLiteral("test", 1), Optional(Eq("test")));
  24. EXPECT_THAT(UnescapeStringLiteral("test\\#n", 1), Optional(Eq("test\n")));
  25. EXPECT_THAT(UnescapeStringLiteral(
  26. "r\\u{000000E9}al \\u{2764}\\u{FE0F}\\u{1F50A}!\\u{10FFFF}"),
  27. Optional(Eq("réal ❤️🔊!􏿿")));
  28. }
  29. TEST(UnescapeStringLiteral, Invalid) {
  30. // Missing char after `\`.
  31. EXPECT_THAT(UnescapeStringLiteral("a\\"), Eq(std::nullopt));
  32. // Not a supported escape.
  33. EXPECT_THAT(UnescapeStringLiteral("\\e"), Eq(std::nullopt));
  34. // Needs 2 hex chars.
  35. EXPECT_THAT(UnescapeStringLiteral("\\x"), Eq(std::nullopt));
  36. // Needs 2 hex chars.
  37. EXPECT_THAT(UnescapeStringLiteral("\\xA"), Eq(std::nullopt));
  38. // Needs uppercase hex.
  39. EXPECT_THAT(UnescapeStringLiteral("\\xaa"), Eq(std::nullopt));
  40. // Reserved.
  41. EXPECT_THAT(UnescapeStringLiteral("\\00"), Eq(std::nullopt));
  42. EXPECT_THAT(UnescapeStringLiteral("\\#00", 1), Eq(std::nullopt));
  43. }
  44. TEST(UnescapeStringLiteral, InvalidUnicodes) {
  45. // Various incomplete Unicode specifiers
  46. EXPECT_THAT(UnescapeStringLiteral("\\u"), Eq(std::nullopt));
  47. EXPECT_THAT(UnescapeStringLiteral("\\u1"), Eq(std::nullopt));
  48. EXPECT_THAT(UnescapeStringLiteral("\\uz"), Eq(std::nullopt));
  49. EXPECT_THAT(UnescapeStringLiteral("\\u{"), Eq(std::nullopt));
  50. EXPECT_THAT(UnescapeStringLiteral("\\u{z"), Eq(std::nullopt));
  51. EXPECT_THAT(UnescapeStringLiteral("\\u{E9"), Eq(std::nullopt));
  52. EXPECT_THAT(UnescapeStringLiteral("\\u{E9z"), Eq(std::nullopt));
  53. EXPECT_THAT(UnescapeStringLiteral("\\u{}"), Eq(std::nullopt));
  54. // invalid characters in unicode
  55. EXPECT_THAT(UnescapeStringLiteral("\\u{z}"), Eq(std::nullopt));
  56. // lowercase hexadecimal
  57. EXPECT_THAT(UnescapeStringLiteral("\\u{e9}"), Eq(std::nullopt));
  58. // Codepoint number too high
  59. EXPECT_THAT(UnescapeStringLiteral("\\u{110000}"), Eq(std::nullopt));
  60. // codepoint more than 8 hex digits
  61. EXPECT_THAT(UnescapeStringLiteral("\\u{FF000000E9}"), Eq(std::nullopt));
  62. }
  63. TEST(UnescapeStringLiteral, Nul) {
  64. std::optional<std::string> str = UnescapeStringLiteral("a\\0b");
  65. ASSERT_NE(str, std::nullopt);
  66. EXPECT_THAT(str->size(), Eq(3));
  67. EXPECT_THAT(strlen(str->c_str()), Eq(1));
  68. EXPECT_THAT((*str)[0], Eq('a'));
  69. EXPECT_THAT((*str)[1], Eq('\0'));
  70. EXPECT_THAT((*str)[2], Eq('b'));
  71. }
  72. TEST(ParseBlockStringLiteral, FailTooFewLines) {
  73. EXPECT_THAT(ParseBlockStringLiteral("").error().message(),
  74. Eq("Too few lines"));
  75. }
  76. TEST(ParseBlockStringLiteral, FailNoLeadingTripleQuotes) {
  77. EXPECT_THAT(ParseBlockStringLiteral("'a'\n").error().message(),
  78. Eq("Should start with triple quotes: 'a'"));
  79. }
  80. TEST(ParseBlockStringLiteral, FailInvalideFiletypeIndicator) {
  81. EXPECT_THAT(ParseBlockStringLiteral("\"\"\"carbon file\n").error().message(),
  82. Eq("Invalid characters in file type indicator: carbon file"));
  83. }
  84. TEST(ParseBlockStringLiteral, FailEndingTripleQuotes) {
  85. EXPECT_THAT(ParseBlockStringLiteral("\"\"\"\n").error().message(),
  86. Eq("Should end with triple quotes: "));
  87. }
  88. TEST(ParseBlockStringLiteral, FailWrongIndent) {
  89. constexpr char Input[] = R"("""
  90. A block string literal
  91. with wrong indent
  92. """)";
  93. EXPECT_THAT(ParseBlockStringLiteral(Input).error().message(),
  94. Eq("Wrong indent for line: with wrong indent, expected 5"));
  95. }
  96. TEST(ParseBlockStringLiteral, FailInvalidEscaping) {
  97. constexpr char Input[] = R"("""
  98. \q
  99. """)";
  100. EXPECT_THAT(ParseBlockStringLiteral(Input).error().message(),
  101. Eq("Invalid escaping in \\q"));
  102. constexpr char InputRaw[] = R"("""
  103. \#q
  104. """)";
  105. EXPECT_THAT(ParseBlockStringLiteral(InputRaw, 1).error().message(),
  106. Eq("Invalid escaping in \\#q"));
  107. }
  108. TEST(ParseBlockStringLiteral, OkEmptyString) {
  109. constexpr char Input[] = R"("""
  110. """)";
  111. EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(""));
  112. }
  113. TEST(ParseBlockStringLiteral, OkOneLineString) {
  114. constexpr char Input[] = R"("""
  115. A block string literal
  116. """)";
  117. constexpr char Expected[] = R"(A block string literal
  118. )";
  119. EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));
  120. }
  121. TEST(ParseBlockStringLiteral, OkTwoLineString) {
  122. constexpr char Input[] = R"("""
  123. A block string literal
  124. with indent.
  125. """)";
  126. constexpr char Expected[] = R"(A block string literal
  127. with indent.
  128. )";
  129. EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));
  130. }
  131. TEST(ParseBlockStringLiteral, OkWithFileTypeIndicator) {
  132. constexpr char Input[] = R"("""carbon
  133. A block string literal
  134. with file type indicator.
  135. """)";
  136. constexpr char Expected[] = R"(A block string literal
  137. with file type indicator.
  138. )";
  139. EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));
  140. }
  141. TEST(ParseBlockStringLiteral, OkWhitespaceAfterOpeningQuotes) {
  142. constexpr char Input[] = R"("""
  143. A block string literal
  144. """)";
  145. constexpr char Expected[] = R"(A block string literal
  146. )";
  147. EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));
  148. }
  149. TEST(ParseBlockStringLiteral, OkWithEmptyLines) {
  150. constexpr char Input[] = R"("""
  151. A block string literal
  152. with
  153. empty
  154. lines.
  155. """)";
  156. constexpr char Expected[] = R"(A block string literal
  157. with
  158. empty
  159. lines.
  160. )";
  161. EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));
  162. }
  163. TEST(ParseBlockStringLiteral, OkWithSlashNewlineEscape) {
  164. constexpr char Input[] = R"("""
  165. A block string literal\
  166. """)";
  167. constexpr char Expected[] = "A block string literal";
  168. EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));
  169. }
  170. TEST(ParseBlockStringLiteral, OkWithDoubleSlashNewline) {
  171. constexpr char Input[] = R"("""
  172. A block string literal\\
  173. """)";
  174. constexpr char Expected[] = R"(A block string literal\
  175. )";
  176. EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));
  177. }
  178. TEST(ParseBlockStringLiteral, OkWithTripleSlashNewline) {
  179. constexpr char Input[] = R"("""
  180. A block string literal\\\
  181. """)";
  182. constexpr char Expected[] = R"(A block string literal\)";
  183. EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));
  184. }
  185. TEST(ParseBlockStringLiteral, OkMultipleSlashes) {
  186. constexpr char Input[] = R"("""
  187. A block string literal\
  188. \
  189. \
  190. \
  191. """)";
  192. constexpr char Expected[] = "A block string literal";
  193. EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));
  194. }
  195. } // namespace
  196. } // namespace Carbon::Testing