1 // Copyright (c) 2015-2016 The Khronos Group Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <string>
16 
17 #include "test/unit_spirv.h"
18 
19 namespace spvtools {
20 namespace {
21 
22 using spvtest::AutoText;
23 
24 #define TAB "\t"
25 #define NEWLINE "\n"
26 #define BACKSLASH R"(\)"
27 #define QUOTE R"(")"
28 
TEST(TextWordGet,NullTerminator)29 TEST(TextWordGet, NullTerminator) {
30   std::string word;
31   spv_position_t endPosition = {};
32   ASSERT_EQ(
33       SPV_SUCCESS,
34       AssemblyContext(AutoText("Word"), nullptr).getWord(&word, &endPosition));
35   ASSERT_EQ(4u, endPosition.column);
36   ASSERT_EQ(0u, endPosition.line);
37   ASSERT_EQ(4u, endPosition.index);
38   ASSERT_STREQ("Word", word.c_str());
39 }
40 
41 TEST(TextWordGet, TabTerminator) {
42   std::string word;
43   spv_position_t endPosition = {};
44   ASSERT_EQ(SPV_SUCCESS, AssemblyContext(AutoText("Word\t"), nullptr)
45                              .getWord(&word, &endPosition));
46   ASSERT_EQ(4u, endPosition.column);
47   ASSERT_EQ(0u, endPosition.line);
48   ASSERT_EQ(4u, endPosition.index);
49   ASSERT_STREQ("Word", word.c_str());
50 }
51 
52 TEST(TextWordGet, SpaceTerminator) {
53   std::string word;
54   spv_position_t endPosition = {};
55   ASSERT_EQ(
56       SPV_SUCCESS,
57       AssemblyContext(AutoText("Word "), nullptr).getWord(&word, &endPosition));
58   ASSERT_EQ(4u, endPosition.column);
59   ASSERT_EQ(0u, endPosition.line);
60   ASSERT_EQ(4u, endPosition.index);
61   ASSERT_STREQ("Word", word.c_str());
62 }
63 
64 TEST(TextWordGet, SemicolonTerminator) {
65   std::string word;
66   spv_position_t endPosition = {};
67   ASSERT_EQ(
68       SPV_SUCCESS,
69       AssemblyContext(AutoText("Wo;rd"), nullptr).getWord(&word, &endPosition));
70   ASSERT_EQ(2u, endPosition.column);
71   ASSERT_EQ(0u, endPosition.line);
72   ASSERT_EQ(2u, endPosition.index);
73   ASSERT_STREQ("Wo", word.c_str());
74 }
75 
TEST(TextWordGet,NoTerminator)76 TEST(TextWordGet, NoTerminator) {
77   const std::string full_text = "abcdefghijklmn";
78   for (size_t len = 1; len <= full_text.size(); ++len) {
79     std::string word;
80     spv_text_t text = {full_text.data(), len};
81     spv_position_t endPosition = {};
82     ASSERT_EQ(SPV_SUCCESS,
83               AssemblyContext(&text, nullptr).getWord(&word, &endPosition));
84     ASSERT_EQ(0u, endPosition.line);
85     ASSERT_EQ(len, endPosition.column);
86     ASSERT_EQ(len, endPosition.index);
87     ASSERT_EQ(full_text.substr(0, len), word);
88   }
89 }
90 
91 TEST(TextWordGet, MultipleWords) {
92   AutoText input("Words in a sentence");
93   AssemblyContext data(input, nullptr);
94 
95   spv_position_t endPosition = {};
96   const char* words[] = {"Words", "in", "a", "sentence"};
97 
98   std::string word;
99   for (uint32_t wordIndex = 0; wordIndex < 4; ++wordIndex) {
100     ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &endPosition));
101     ASSERT_EQ(strlen(words[wordIndex]),
102               endPosition.column - data.position().column);
103     ASSERT_EQ(0u, endPosition.line);
104     ASSERT_EQ(strlen(words[wordIndex]),
105               endPosition.index - data.position().index);
106     ASSERT_STREQ(words[wordIndex], word.c_str());
107 
108     data.setPosition(endPosition);
109     if (3 != wordIndex) {
110       ASSERT_EQ(SPV_SUCCESS, data.advance());
111     } else {
112       ASSERT_EQ(SPV_END_OF_STREAM, data.advance());
113     }
114   }
115 }
116 
117 TEST(TextWordGet, QuotesAreKept) {
118   AutoText input(R"("quotes" "around words")");
119   const char* expected[] = {R"("quotes")", R"("around words")"};
120   AssemblyContext data(input, nullptr);
121 
122   std::string word;
123   spv_position_t endPosition = {};
124   ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &endPosition));
125   EXPECT_EQ(8u, endPosition.column);
126   EXPECT_EQ(0u, endPosition.line);
127   EXPECT_EQ(8u, endPosition.index);
128   EXPECT_STREQ(expected[0], word.c_str());
129 
130   // Move to the next word.
131   data.setPosition(endPosition);
132   data.seekForward(1);
133 
134   ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &endPosition));
135   EXPECT_EQ(23u, endPosition.column);
136   EXPECT_EQ(0u, endPosition.line);
137   EXPECT_EQ(23u, endPosition.index);
138   EXPECT_STREQ(expected[1], word.c_str());
139 }
140 
141 TEST(TextWordGet, QuotesBetweenWordsActLikeGlue) {
142   AutoText input(R"(quotes" "between words)");
143   const char* expected[] = {R"(quotes" "between)", "words"};
144   AssemblyContext data(input, nullptr);
145 
146   std::string word;
147   spv_position_t endPosition = {};
148   ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &endPosition));
149   EXPECT_EQ(16u, endPosition.column);
150   EXPECT_EQ(0u, endPosition.line);
151   EXPECT_EQ(16u, endPosition.index);
152   EXPECT_STREQ(expected[0], word.c_str());
153 
154   // Move to the next word.
155   data.setPosition(endPosition);
156   data.seekForward(1);
157 
158   ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &endPosition));
159   EXPECT_EQ(22u, endPosition.column);
160   EXPECT_EQ(0u, endPosition.line);
161   EXPECT_EQ(22u, endPosition.index);
162   EXPECT_STREQ(expected[1], word.c_str());
163 }
164 
165 TEST(TextWordGet, QuotingWhitespace) {
166   AutoText input(QUOTE "white " NEWLINE TAB " space" QUOTE);
167   // Whitespace surrounded by quotes acts like glue.
168   std::string word;
169   spv_position_t endPosition = {};
170   ASSERT_EQ(SPV_SUCCESS,
171             AssemblyContext(input, nullptr).getWord(&word, &endPosition));
172   EXPECT_EQ(input.str.length(), endPosition.column);
173   EXPECT_EQ(0u, endPosition.line);
174   EXPECT_EQ(input.str.length(), endPosition.index);
175   EXPECT_EQ(input.str, word);
176 }
177 
178 TEST(TextWordGet, QuoteAlone) {
179   AutoText input(QUOTE);
180   std::string word;
181   spv_position_t endPosition = {};
182   ASSERT_EQ(SPV_SUCCESS,
183             AssemblyContext(input, nullptr).getWord(&word, &endPosition));
184   ASSERT_EQ(1u, endPosition.column);
185   ASSERT_EQ(0u, endPosition.line);
186   ASSERT_EQ(1u, endPosition.index);
187   ASSERT_STREQ(QUOTE, word.c_str());
188 }
189 
190 TEST(TextWordGet, EscapeAlone) {
191   AutoText input(BACKSLASH);
192   std::string word;
193   spv_position_t endPosition = {};
194   ASSERT_EQ(SPV_SUCCESS,
195             AssemblyContext(input, nullptr).getWord(&word, &endPosition));
196   ASSERT_EQ(1u, endPosition.column);
197   ASSERT_EQ(0u, endPosition.line);
198   ASSERT_EQ(1u, endPosition.index);
199   ASSERT_STREQ(BACKSLASH, word.c_str());
200 }
201 
202 TEST(TextWordGet, EscapeAtEndOfInput) {
203   AutoText input("word" BACKSLASH);
204   std::string word;
205   spv_position_t endPosition = {};
206   ASSERT_EQ(SPV_SUCCESS,
207             AssemblyContext(input, nullptr).getWord(&word, &endPosition));
208   ASSERT_EQ(5u, endPosition.column);
209   ASSERT_EQ(0u, endPosition.line);
210   ASSERT_EQ(5u, endPosition.index);
211   ASSERT_STREQ("word" BACKSLASH, word.c_str());
212 }
213 
214 TEST(TextWordGet, Escaping) {
215   AutoText input("w" BACKSLASH QUOTE "o" BACKSLASH NEWLINE "r" BACKSLASH ";d");
216   std::string word;
217   spv_position_t endPosition = {};
218   ASSERT_EQ(SPV_SUCCESS,
219             AssemblyContext(input, nullptr).getWord(&word, &endPosition));
220   ASSERT_EQ(10u, endPosition.column);
221   ASSERT_EQ(0u, endPosition.line);
222   ASSERT_EQ(10u, endPosition.index);
223   ASSERT_EQ(input.str, word);
224 }
225 
TEST(TextWordGet,EscapingEscape)226 TEST(TextWordGet, EscapingEscape) {
227   AutoText input("word" BACKSLASH BACKSLASH " abc");
228   std::string word;
229   spv_position_t endPosition = {};
230   ASSERT_EQ(SPV_SUCCESS,
231             AssemblyContext(input, nullptr).getWord(&word, &endPosition));
232   ASSERT_EQ(6u, endPosition.column);
233   ASSERT_EQ(0u, endPosition.line);
234   ASSERT_EQ(6u, endPosition.index);
235   ASSERT_STREQ("word" BACKSLASH BACKSLASH, word.c_str());
236 }
237 
238 TEST(TextWordGet, CRLF) {
239   AutoText input("abc\r\nd");
240   AssemblyContext data(input, nullptr);
241   std::string word;
242   spv_position_t pos = {};
243   ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &pos));
244   EXPECT_EQ(3u, pos.column);
245   EXPECT_STREQ("abc", word.c_str());
246   data.setPosition(pos);
247   data.advance();
248   ASSERT_EQ(SPV_SUCCESS, data.getWord(&word, &pos));
249   EXPECT_EQ(1u, pos.column);
250   EXPECT_STREQ("d", word.c_str());
251 }
252 
253 }  // namespace
254 }  // namespace spvtools
255