OSDN Git Service

Fix signed/unsigned compare warning I introduced
[android-x86/external-llvm.git] / unittests / Support / YAMLParserTest.cpp
1 //===- unittest/Support/YAMLParserTest ------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/Support/YAMLParser.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/Support/Casting.h"
13 #include "llvm/Support/MemoryBuffer.h"
14 #include "llvm/Support/SourceMgr.h"
15 #include "gtest/gtest.h"
16
17 namespace llvm {
18
19 static void SuppressDiagnosticsOutput(const SMDiagnostic &, void *) {
20   // Prevent SourceMgr from writing errors to stderr
21   // to reduce noise in unit test runs.
22 }
23
24 // Assumes Ctx is an SMDiagnostic where Diag can be stored.
25 static void CollectDiagnosticsOutput(const SMDiagnostic &Diag, void *Ctx) {
26   SMDiagnostic* DiagOut = static_cast<SMDiagnostic*>(Ctx);
27   *DiagOut = Diag;
28 }
29
30 // Checks that the given input gives a parse error. Makes sure that an error
31 // text is available and the parse fails.
32 static void ExpectParseError(StringRef Message, StringRef Input) {
33   SourceMgr SM;
34   yaml::Stream Stream(Input, SM);
35   SM.setDiagHandler(SuppressDiagnosticsOutput);
36   EXPECT_FALSE(Stream.validate()) << Message << ": " << Input;
37   EXPECT_TRUE(Stream.failed()) << Message << ": " << Input;
38 }
39
40 // Checks that the given input can be parsed without error.
41 static void ExpectParseSuccess(StringRef Message, StringRef Input) {
42   SourceMgr SM;
43   yaml::Stream Stream(Input, SM);
44   EXPECT_TRUE(Stream.validate()) << Message << ": " << Input;
45 }
46
47 TEST(YAMLParser, ParsesEmptyArray) {
48   ExpectParseSuccess("Empty array", "[]");
49 }
50
51 TEST(YAMLParser, FailsIfNotClosingArray) {
52   ExpectParseError("Not closing array", "[");
53   ExpectParseError("Not closing array", "  [  ");
54   ExpectParseError("Not closing array", "  [x");
55 }
56
57 TEST(YAMLParser, ParsesEmptyArrayWithWhitespace) {
58   ExpectParseSuccess("Array with spaces", "  [  ]  ");
59   ExpectParseSuccess("All whitespaces", "\t\r\n[\t\n \t\r ]\t\r \n\n");
60 }
61
62 TEST(YAMLParser, ParsesEmptyObject) {
63   ExpectParseSuccess("Empty object", "[{}]");
64 }
65
66 TEST(YAMLParser, ParsesObject) {
67   ExpectParseSuccess("Object with an entry", "[{\"a\":\"/b\"}]");
68 }
69
70 TEST(YAMLParser, ParsesMultipleKeyValuePairsInObject) {
71   ExpectParseSuccess("Multiple key, value pairs",
72                      "[{\"a\":\"/b\",\"c\":\"d\",\"e\":\"f\"}]");
73 }
74
75 TEST(YAMLParser, FailsIfNotClosingObject) {
76   ExpectParseError("Missing close on empty", "[{]");
77   ExpectParseError("Missing close after pair", "[{\"a\":\"b\"]");
78 }
79
80 TEST(YAMLParser, FailsIfMissingColon) {
81   ExpectParseError("Missing colon between key and value", "[{\"a\"\"/b\"}]");
82   ExpectParseError("Missing colon between key and value", "[{\"a\" \"b\"}]");
83 }
84
85 TEST(YAMLParser, FailsOnMissingQuote) {
86   ExpectParseError("Missing open quote", "[{a\":\"b\"}]");
87   ExpectParseError("Missing closing quote", "[{\"a\":\"b}]");
88 }
89
90 TEST(YAMLParser, ParsesEscapedQuotes) {
91   ExpectParseSuccess("Parses escaped string in key and value",
92                      "[{\"a\":\"\\\"b\\\"  \\\" \\\"\"}]");
93 }
94
95 TEST(YAMLParser, ParsesEmptyString) {
96   ExpectParseSuccess("Parses empty string in value", "[{\"a\":\"\"}]");
97 }
98
99 TEST(YAMLParser, ParsesMultipleObjects) {
100   ExpectParseSuccess(
101       "Multiple objects in array",
102       "["
103       " { \"a\" : \"b\" },"
104       " { \"a\" : \"b\" },"
105       " { \"a\" : \"b\" }"
106       "]");
107 }
108
109 TEST(YAMLParser, FailsOnMissingComma) {
110   ExpectParseError(
111       "Missing comma",
112       "["
113       " { \"a\" : \"b\" }"
114       " { \"a\" : \"b\" }"
115       "]");
116 }
117
118 TEST(YAMLParser, ParsesSpacesInBetweenTokens) {
119   ExpectParseSuccess(
120       "Various whitespace between tokens",
121       " \t \n\n \r [ \t \n\n \r"
122       " \t \n\n \r { \t \n\n \r\"a\"\t \n\n \r :"
123       " \t \n\n \r \"b\"\t \n\n \r } \t \n\n \r,\t \n\n \r"
124       " \t \n\n \r { \t \n\n \r\"a\"\t \n\n \r :"
125       " \t \n\n \r \"b\"\t \n\n \r } \t \n\n \r]\t \n\n \r");
126 }
127
128 TEST(YAMLParser, ParsesArrayOfArrays) {
129   ExpectParseSuccess("Array of arrays", "[[]]");
130 }
131
132 TEST(YAMLParser, ParsesBlockLiteralScalars) {
133   ExpectParseSuccess("Block literal scalar", "test: |\n  Hello\n  World\n");
134   ExpectParseSuccess("Block literal scalar EOF", "test: |\n  Hello\n  World");
135   ExpectParseSuccess("Empty block literal scalar header EOF", "test: | ");
136   ExpectParseSuccess("Empty block literal scalar", "test: |\ntest2: 20");
137   ExpectParseSuccess("Empty block literal scalar 2", "- | \n  \n\n \n- 42");
138   ExpectParseSuccess("Block literal scalar in sequence",
139                      "- |\n  Testing\n  Out\n\n- 22");
140   ExpectParseSuccess("Block literal scalar in document",
141                      "--- |\n  Document\n...");
142   ExpectParseSuccess("Empty non indented lines still count",
143                      "- |\n  First line\n \n\n  Another line\n\n- 2");
144   ExpectParseSuccess("Comment in block literal scalar header",
145                      "test: | # Comment \n  No Comment\ntest 2: | # Void");
146   ExpectParseSuccess("Chomping indicators in block literal scalar header",
147                      "test: |- \n  Hello\n\ntest 2: |+ \n\n  World\n\n\n");
148   ExpectParseSuccess("Indent indicators in block literal scalar header",
149                      "test: |1 \n  \n Hello \n  World\n");
150   ExpectParseSuccess("Chomping and indent indicators in block literals",
151                      "test: |-1\n Hello\ntest 2: |9+\n         World");
152   ExpectParseSuccess("Trailing comments in block literals",
153                      "test: |\n  Content\n # Trailing\n  #Comment\ntest 2: 3");
154   ExpectParseError("Invalid block scalar header", "test: | failure");
155   ExpectParseError("Invalid line indentation", "test: |\n  First line\n Error");
156   ExpectParseError("Long leading space line", "test: |\n   \n  Test\n");
157 }
158
159 TEST(YAMLParser, NullTerminatedBlockScalars) {
160   SourceMgr SM;
161   yaml::Stream Stream("test: |\n  Hello\n  World\n", SM);
162   yaml::Document &Doc = *Stream.begin();
163   yaml::MappingNode *Map = cast<yaml::MappingNode>(Doc.getRoot());
164   StringRef Value =
165       cast<yaml::BlockScalarNode>(Map->begin()->getValue())->getValue();
166
167   EXPECT_EQ(Value, "Hello\nWorld\n");
168   EXPECT_EQ(Value.data()[Value.size()], '\0');
169 }
170
171 TEST(YAMLParser, HandlesEndOfFileGracefully) {
172   ExpectParseError("In string starting with EOF", "[\"");
173   ExpectParseError("In string hitting EOF", "[\"   ");
174   ExpectParseError("In string escaping EOF", "[\"  \\");
175   ExpectParseError("In array starting with EOF", "[");
176   ExpectParseError("In array element starting with EOF", "[[], ");
177   ExpectParseError("In array hitting EOF", "[[] ");
178   ExpectParseError("In array hitting EOF", "[[]");
179   ExpectParseError("In object hitting EOF", "{\"\"");
180 }
181
182 TEST(YAMLParser, HandlesNullValuesInKeyValueNodesGracefully) {
183   ExpectParseError("KeyValueNode with null key", "? \"\n:");
184   ExpectParseError("KeyValueNode with null value", "test: '");
185 }
186
187 // Checks that the given string can be parsed into an identical string inside
188 // of an array.
189 static void ExpectCanParseString(StringRef String) {
190   std::string StringInArray = (llvm::Twine("[\"") + String + "\"]").str();
191   SourceMgr SM;
192   yaml::Stream Stream(StringInArray, SM);
193   yaml::SequenceNode *ParsedSequence
194     = dyn_cast<yaml::SequenceNode>(Stream.begin()->getRoot());
195   StringRef ParsedString
196     = dyn_cast<yaml::ScalarNode>(
197       static_cast<yaml::Node*>(ParsedSequence->begin()))->getRawValue();
198   ParsedString = ParsedString.substr(1, ParsedString.size() - 2);
199   EXPECT_EQ(String, ParsedString.str());
200 }
201
202 // Checks that parsing the given string inside an array fails.
203 static void ExpectCannotParseString(StringRef String) {
204   std::string StringInArray = (llvm::Twine("[\"") + String + "\"]").str();
205   ExpectParseError((Twine("When parsing string \"") + String + "\"").str(),
206                    StringInArray);
207 }
208
209 TEST(YAMLParser, ParsesStrings) {
210   ExpectCanParseString("");
211   ExpectCannotParseString("\\");
212   ExpectCannotParseString("\"");
213   ExpectCanParseString(" ");
214   ExpectCanParseString("\\ ");
215   ExpectCanParseString("\\\"");
216   ExpectCannotParseString("\"\\");
217   ExpectCannotParseString(" \\");
218   ExpectCanParseString("\\\\");
219   ExpectCannotParseString("\\\\\\");
220   ExpectCanParseString("\\\\\\\\");
221   ExpectCanParseString("\\\" ");
222   ExpectCannotParseString("\\\\\" ");
223   ExpectCanParseString("\\\\\\\" ");
224   ExpectCanParseString("    \\\\  \\\"  \\\\\\\"   ");
225 }
226
227 TEST(YAMLParser, WorksWithIteratorAlgorithms) {
228   SourceMgr SM;
229   yaml::Stream Stream("[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\"]", SM);
230   yaml::SequenceNode *Array
231     = dyn_cast<yaml::SequenceNode>(Stream.begin()->getRoot());
232   EXPECT_EQ(6, std::distance(Array->begin(), Array->end()));
233 }
234
235 TEST(YAMLParser, DefaultDiagnosticFilename) {
236   SourceMgr SM;
237
238   SMDiagnostic GeneratedDiag;
239   SM.setDiagHandler(CollectDiagnosticsOutput, &GeneratedDiag);
240
241   // When we construct a YAML stream over an unnamed string,
242   // the filename is hard-coded as "YAML".
243   yaml::Stream UnnamedStream("[]", SM);
244   UnnamedStream.printError(UnnamedStream.begin()->getRoot(), "Hello, World!");
245   EXPECT_EQ("YAML", GeneratedDiag.getFilename());
246 }
247
248 TEST(YAMLParser, DiagnosticFilenameFromBufferID) {
249   SourceMgr SM;
250
251   SMDiagnostic GeneratedDiag;
252   SM.setDiagHandler(CollectDiagnosticsOutput, &GeneratedDiag);
253
254   // When we construct a YAML stream over a named buffer,
255   // we get its ID as filename in diagnostics.
256   std::unique_ptr<MemoryBuffer> Buffer =
257       MemoryBuffer::getMemBuffer("[]", "buffername.yaml");
258   yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
259   Stream.printError(Stream.begin()->getRoot(), "Hello, World!");
260   EXPECT_EQ("buffername.yaml", GeneratedDiag.getFilename());
261 }
262
263 TEST(YAMLParser, SameNodeIteratorOperatorNotEquals) {
264   SourceMgr SM;
265   yaml::Stream Stream("[\"1\", \"2\"]", SM);
266
267   yaml::SequenceNode *Node = dyn_cast<yaml::SequenceNode>(
268                                               Stream.begin()->getRoot());
269
270   auto Begin = Node->begin();
271   auto End = Node->end();
272
273   EXPECT_TRUE(Begin != End);
274   EXPECT_FALSE(Begin != Begin);
275   EXPECT_FALSE(End != End);
276 }
277
278 TEST(YAMLParser, SameNodeIteratorOperatorEquals) {
279   SourceMgr SM;
280   yaml::Stream Stream("[\"1\", \"2\"]", SM);
281
282   yaml::SequenceNode *Node = dyn_cast<yaml::SequenceNode>(
283                                               Stream.begin()->getRoot());
284
285   auto Begin = Node->begin();
286   auto End = Node->end();
287
288   EXPECT_FALSE(Begin == End);
289   EXPECT_TRUE(Begin == Begin);
290   EXPECT_TRUE(End == End);
291 }
292
293 TEST(YAMLParser, DifferentNodesIteratorOperatorNotEquals) {
294   SourceMgr SM;
295   yaml::Stream Stream("[\"1\", \"2\"]", SM);
296   yaml::Stream AnotherStream("[\"1\", \"2\"]", SM);
297
298   yaml::SequenceNode *Node = dyn_cast<yaml::SequenceNode>(
299                                                   Stream.begin()->getRoot());
300   yaml::SequenceNode *AnotherNode = dyn_cast<yaml::SequenceNode>(
301                                               AnotherStream.begin()->getRoot());
302
303   auto Begin = Node->begin();
304   auto End = Node->end();
305
306   auto AnotherBegin = AnotherNode->begin();
307   auto AnotherEnd = AnotherNode->end();
308
309   EXPECT_TRUE(Begin != AnotherBegin);
310   EXPECT_TRUE(Begin != AnotherEnd);
311   EXPECT_FALSE(End != AnotherEnd);
312 }
313
314 TEST(YAMLParser, DifferentNodesIteratorOperatorEquals) {
315   SourceMgr SM;
316   yaml::Stream Stream("[\"1\", \"2\"]", SM);
317   yaml::Stream AnotherStream("[\"1\", \"2\"]", SM);
318
319   yaml::SequenceNode *Node = dyn_cast<yaml::SequenceNode>(
320                                                     Stream.begin()->getRoot());
321   yaml::SequenceNode *AnotherNode = dyn_cast<yaml::SequenceNode>(
322                                              AnotherStream.begin()->getRoot());
323
324   auto Begin = Node->begin();
325   auto End = Node->end();
326
327   auto AnotherBegin = AnotherNode->begin();
328   auto AnotherEnd = AnotherNode->end();
329
330   EXPECT_FALSE(Begin == AnotherBegin);
331   EXPECT_FALSE(Begin == AnotherEnd);
332   EXPECT_TRUE(End == AnotherEnd);
333 }
334
335 } // end namespace llvm