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/ADT/SmallString.h" 11 #include "llvm/ADT/Twine.h" 12 #include "llvm/Support/Casting.h" 13 #include "llvm/Support/SourceMgr.h" 14 #include "llvm/Support/YAMLParser.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 // Checks that the given input gives a parse error. Makes sure that an error 25 // text is available and the parse fails. 26 static void ExpectParseError(StringRef Message, StringRef Input) { 27 SourceMgr SM; 28 yaml::Stream Stream(Input, SM); 29 SM.setDiagHandler(SuppressDiagnosticsOutput); 30 EXPECT_FALSE(Stream.validate()) << Message << ": " << Input; 31 EXPECT_TRUE(Stream.failed()) << Message << ": " << Input; 32 } 33 34 // Checks that the given input can be parsed without error. 35 static void ExpectParseSuccess(StringRef Message, StringRef Input) { 36 SourceMgr SM; 37 yaml::Stream Stream(Input, SM); 38 EXPECT_TRUE(Stream.validate()) << Message << ": " << Input; 39 } 40 41 TEST(YAMLParser, ParsesEmptyArray) { 42 ExpectParseSuccess("Empty array", "[]"); 43 } 44 45 TEST(YAMLParser, FailsIfNotClosingArray) { 46 ExpectParseError("Not closing array", "["); 47 ExpectParseError("Not closing array", " [ "); 48 ExpectParseError("Not closing array", " [x"); 49 } 50 51 TEST(YAMLParser, ParsesEmptyArrayWithWhitespace) { 52 ExpectParseSuccess("Array with spaces", " [ ] "); 53 ExpectParseSuccess("All whitespaces", "\t\r\n[\t\n \t\r ]\t\r \n\n"); 54 } 55 56 TEST(YAMLParser, ParsesEmptyObject) { 57 ExpectParseSuccess("Empty object", "[{}]"); 58 } 59 60 TEST(YAMLParser, ParsesObject) { 61 ExpectParseSuccess("Object with an entry", "[{\"a\":\"/b\"}]"); 62 } 63 64 TEST(YAMLParser, ParsesMultipleKeyValuePairsInObject) { 65 ExpectParseSuccess("Multiple key, value pairs", 66 "[{\"a\":\"/b\",\"c\":\"d\",\"e\":\"f\"}]"); 67 } 68 69 TEST(YAMLParser, FailsIfNotClosingObject) { 70 ExpectParseError("Missing close on empty", "[{]"); 71 ExpectParseError("Missing close after pair", "[{\"a\":\"b\"]"); 72 } 73 74 TEST(YAMLParser, FailsIfMissingColon) { 75 ExpectParseError("Missing colon between key and value", "[{\"a\"\"/b\"}]"); 76 ExpectParseError("Missing colon between key and value", "[{\"a\" \"b\"}]"); 77 } 78 79 TEST(YAMLParser, FailsOnMissingQuote) { 80 ExpectParseError("Missing open quote", "[{a\":\"b\"}]"); 81 ExpectParseError("Missing closing quote", "[{\"a\":\"b}]"); 82 } 83 84 TEST(YAMLParser, ParsesEscapedQuotes) { 85 ExpectParseSuccess("Parses escaped string in key and value", 86 "[{\"a\":\"\\\"b\\\" \\\" \\\"\"}]"); 87 } 88 89 TEST(YAMLParser, ParsesEmptyString) { 90 ExpectParseSuccess("Parses empty string in value", "[{\"a\":\"\"}]"); 91 } 92 93 TEST(YAMLParser, ParsesMultipleObjects) { 94 ExpectParseSuccess( 95 "Multiple objects in array", 96 "[" 97 " { \"a\" : \"b\" }," 98 " { \"a\" : \"b\" }," 99 " { \"a\" : \"b\" }" 100 "]"); 101 } 102 103 TEST(YAMLParser, FailsOnMissingComma) { 104 ExpectParseError( 105 "Missing comma", 106 "[" 107 " { \"a\" : \"b\" }" 108 " { \"a\" : \"b\" }" 109 "]"); 110 } 111 112 TEST(YAMLParser, ParsesSpacesInBetweenTokens) { 113 ExpectParseSuccess( 114 "Various whitespace between tokens", 115 " \t \n\n \r [ \t \n\n \r" 116 " \t \n\n \r { \t \n\n \r\"a\"\t \n\n \r :" 117 " \t \n\n \r \"b\"\t \n\n \r } \t \n\n \r,\t \n\n \r" 118 " \t \n\n \r { \t \n\n \r\"a\"\t \n\n \r :" 119 " \t \n\n \r \"b\"\t \n\n \r } \t \n\n \r]\t \n\n \r"); 120 } 121 122 TEST(YAMLParser, ParsesArrayOfArrays) { 123 ExpectParseSuccess("Array of arrays", "[[]]"); 124 } 125 126 TEST(YAMLParser, HandlesEndOfFileGracefully) { 127 ExpectParseError("In string starting with EOF", "[\""); 128 ExpectParseError("In string hitting EOF", "[\" "); 129 ExpectParseError("In string escaping EOF", "[\" \\"); 130 ExpectParseError("In array starting with EOF", "["); 131 ExpectParseError("In array element starting with EOF", "[[], "); 132 ExpectParseError("In array hitting EOF", "[[] "); 133 ExpectParseError("In array hitting EOF", "[[]"); 134 ExpectParseError("In object hitting EOF", "{\"\""); 135 } 136 137 // Checks that the given string can be parsed into an identical string inside 138 // of an array. 139 static void ExpectCanParseString(StringRef String) { 140 std::string StringInArray = (llvm::Twine("[\"") + String + "\"]").str(); 141 SourceMgr SM; 142 yaml::Stream Stream(StringInArray, SM); 143 yaml::SequenceNode *ParsedSequence 144 = dyn_cast<yaml::SequenceNode>(Stream.begin()->getRoot()); 145 StringRef ParsedString 146 = dyn_cast<yaml::ScalarNode>( 147 static_cast<yaml::Node*>(ParsedSequence->begin()))->getRawValue(); 148 ParsedString = ParsedString.substr(1, ParsedString.size() - 2); 149 EXPECT_EQ(String, ParsedString.str()); 150 } 151 152 // Checks that parsing the given string inside an array fails. 153 static void ExpectCannotParseString(StringRef String) { 154 std::string StringInArray = (llvm::Twine("[\"") + String + "\"]").str(); 155 ExpectParseError((Twine("When parsing string \"") + String + "\"").str(), 156 StringInArray); 157 } 158 159 TEST(YAMLParser, ParsesStrings) { 160 ExpectCanParseString(""); 161 ExpectCannotParseString("\\"); 162 ExpectCannotParseString("\""); 163 ExpectCanParseString(" "); 164 ExpectCanParseString("\\ "); 165 ExpectCanParseString("\\\""); 166 ExpectCannotParseString("\"\\"); 167 ExpectCannotParseString(" \\"); 168 ExpectCanParseString("\\\\"); 169 ExpectCannotParseString("\\\\\\"); 170 ExpectCanParseString("\\\\\\\\"); 171 ExpectCanParseString("\\\" "); 172 ExpectCannotParseString("\\\\\" "); 173 ExpectCanParseString("\\\\\\\" "); 174 ExpectCanParseString(" \\\\ \\\" \\\\\\\" "); 175 } 176 177 TEST(YAMLParser, WorksWithIteratorAlgorithms) { 178 SourceMgr SM; 179 yaml::Stream Stream("[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\"]", SM); 180 yaml::SequenceNode *Array 181 = dyn_cast<yaml::SequenceNode>(Stream.begin()->getRoot()); 182 EXPECT_EQ(6, std::distance(Array->begin(), Array->end())); 183 } 184 185 } // end namespace llvm 186