Files
acceptance-tests
data
docs
external
Newtonsoft.Json
api-doc-tools
api-snapshot
aspnetwebstack
bdwgc
binary-reference-assemblies
bockbuild
boringssl
cecil
cecil-legacy
corefx
corert
helix-binaries
ikdasm
ikvm
illinker-test-assets
linker
llvm-project
clang
clang-tools-extra
compiler-rt
libcxx
libcxxabi
libunwind
lld
lldb
llvm
bindings
cmake
docs
examples
include
lib
projects
resources
runtimes
scripts
test
tools
unittests
ADT
Analysis
AsmParser
BinaryFormat
Bitcode
CodeGen
DebugInfo
ExecutionEngine
FuzzMutate
IR
LineEditor
Linker
MC
MI
Object
ObjectYAML
Option
ProfileData
Support
DynamicLibrary
ARMAttributeParser.cpp
AlignOfTest.cpp
AllocatorTest.cpp
ArrayRecyclerTest.cpp
BinaryStreamTest.cpp
BlockFrequencyTest.cpp
BranchProbabilityTest.cpp
CMakeLists.txt
CachePruningTest.cpp
Casting.cpp
Chrono.cpp
CommandLineTest.cpp
CompressionTest.cpp
ConvertUTFTest.cpp
CrashRecoveryTest.cpp
DataExtractorTest.cpp
DebugTest.cpp
EndianStreamTest.cpp
EndianTest.cpp
ErrnoTest.cpp
ErrorOrTest.cpp
ErrorTest.cpp
FileOutputBufferTest.cpp
FormatVariadicTest.cpp
GlobPatternTest.cpp
Host.cpp
LEB128Test.cpp
LineIteratorTest.cpp
LockFileManagerTest.cpp
MD5Test.cpp
ManagedStatic.cpp
MathExtrasTest.cpp
MemoryBufferTest.cpp
MemoryTest.cpp
NativeFormatTests.cpp
ParallelTest.cpp
Path.cpp
ProcessTest.cpp
ProgramTest.cpp
RegexTest.cpp
ReplaceFileTest.cpp
ReverseIterationTest.cpp
ScaledNumberTest.cpp
SourceMgrTest.cpp
SpecialCaseListTest.cpp
StringPool.cpp
SwapByteOrderTest.cpp
TarWriterTest.cpp
TargetParserTest.cpp
ThreadLocalTest.cpp
ThreadPool.cpp
Threading.cpp
TimerTest.cpp
TrailingObjectsTest.cpp
TrigramIndexTest.cpp
TypeNameTest.cpp
UnicodeTest.cpp
YAMLIOTest.cpp
YAMLParserTest.cpp
formatted_raw_ostream_test.cpp
raw_ostream_test.cpp
raw_pwrite_stream_test.cpp
raw_sha1_ostream_test.cpp
xxhashTest.cpp
Target
Transforms
XRay
tools
CMakeLists.txt
utils
.arcconfig
.clang-format
.clang-tidy
.gitattributes
.gitignore
CMakeLists.txt
CODE_OWNERS.TXT
CREDITS.TXT
LICENSE.TXT
LLVMBuild.txt
README.txt
RELEASE_TESTERS.TXT
configure
llvm.spec.in
openmp
polly
nuget-buildtasks
nunit-lite
roslyn-binaries
rx
xunit-binaries
how-to-bump-roslyn-binaries.md
ikvm-native
llvm
m4
man
mcs
mk
mono
msvc
netcore
po
runtime
samples
scripts
support
tools
COPYING.LIB
LICENSE
Makefile.am
Makefile.in
NEWS
README.md
acinclude.m4
aclocal.m4
autogen.sh
code_of_conduct.md
compile
config.guess
config.h.in
config.rpath
config.sub
configure.REMOVED.git-id
configure.ac.REMOVED.git-id
depcomp
install-sh
ltmain.sh.REMOVED.git-id
missing
mkinstalldirs
mono-uninstalled.pc.in
test-driver
winconfig.h
linux-packaging-mono/external/llvm-project/llvm/unittests/Support/YAMLParserTest.cpp

336 lines
12 KiB
C++
Raw Normal View History

//===- unittest/Support/YAMLParserTest ------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/YAMLParser.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
namespace llvm {
static void SuppressDiagnosticsOutput(const SMDiagnostic &, void *) {
// Prevent SourceMgr from writing errors to stderr
// to reduce noise in unit test runs.
}
// Assumes Ctx is an SMDiagnostic where Diag can be stored.
static void CollectDiagnosticsOutput(const SMDiagnostic &Diag, void *Ctx) {
SMDiagnostic* DiagOut = static_cast<SMDiagnostic*>(Ctx);
*DiagOut = Diag;
}
// Checks that the given input gives a parse error. Makes sure that an error
// text is available and the parse fails.
static void ExpectParseError(StringRef Message, StringRef Input) {
SourceMgr SM;
yaml::Stream Stream(Input, SM);
SM.setDiagHandler(SuppressDiagnosticsOutput);
EXPECT_FALSE(Stream.validate()) << Message << ": " << Input;
EXPECT_TRUE(Stream.failed()) << Message << ": " << Input;
}
// Checks that the given input can be parsed without error.
static void ExpectParseSuccess(StringRef Message, StringRef Input) {
SourceMgr SM;
yaml::Stream Stream(Input, SM);
EXPECT_TRUE(Stream.validate()) << Message << ": " << Input;
}
TEST(YAMLParser, ParsesEmptyArray) {
ExpectParseSuccess("Empty array", "[]");
}
TEST(YAMLParser, FailsIfNotClosingArray) {
ExpectParseError("Not closing array", "[");
ExpectParseError("Not closing array", " [ ");
ExpectParseError("Not closing array", " [x");
}
TEST(YAMLParser, ParsesEmptyArrayWithWhitespace) {
ExpectParseSuccess("Array with spaces", " [ ] ");
ExpectParseSuccess("All whitespaces", "\t\r\n[\t\n \t\r ]\t\r \n\n");
}
TEST(YAMLParser, ParsesEmptyObject) {
ExpectParseSuccess("Empty object", "[{}]");
}
TEST(YAMLParser, ParsesObject) {
ExpectParseSuccess("Object with an entry", "[{\"a\":\"/b\"}]");
}
TEST(YAMLParser, ParsesMultipleKeyValuePairsInObject) {
ExpectParseSuccess("Multiple key, value pairs",
"[{\"a\":\"/b\",\"c\":\"d\",\"e\":\"f\"}]");
}
TEST(YAMLParser, FailsIfNotClosingObject) {
ExpectParseError("Missing close on empty", "[{]");
ExpectParseError("Missing close after pair", "[{\"a\":\"b\"]");
}
TEST(YAMLParser, FailsIfMissingColon) {
ExpectParseError("Missing colon between key and value", "[{\"a\"\"/b\"}]");
ExpectParseError("Missing colon between key and value", "[{\"a\" \"b\"}]");
}
TEST(YAMLParser, FailsOnMissingQuote) {
ExpectParseError("Missing open quote", "[{a\":\"b\"}]");
ExpectParseError("Missing closing quote", "[{\"a\":\"b}]");
}
TEST(YAMLParser, ParsesEscapedQuotes) {
ExpectParseSuccess("Parses escaped string in key and value",
"[{\"a\":\"\\\"b\\\" \\\" \\\"\"}]");
}
TEST(YAMLParser, ParsesEmptyString) {
ExpectParseSuccess("Parses empty string in value", "[{\"a\":\"\"}]");
}
TEST(YAMLParser, ParsesMultipleObjects) {
ExpectParseSuccess(
"Multiple objects in array",
"["
" { \"a\" : \"b\" },"
" { \"a\" : \"b\" },"
" { \"a\" : \"b\" }"
"]");
}
TEST(YAMLParser, FailsOnMissingComma) {
ExpectParseError(
"Missing comma",
"["
" { \"a\" : \"b\" }"
" { \"a\" : \"b\" }"
"]");
}
TEST(YAMLParser, ParsesSpacesInBetweenTokens) {
ExpectParseSuccess(
"Various whitespace between tokens",
" \t \n\n \r [ \t \n\n \r"
" \t \n\n \r { \t \n\n \r\"a\"\t \n\n \r :"
" \t \n\n \r \"b\"\t \n\n \r } \t \n\n \r,\t \n\n \r"
" \t \n\n \r { \t \n\n \r\"a\"\t \n\n \r :"
" \t \n\n \r \"b\"\t \n\n \r } \t \n\n \r]\t \n\n \r");
}
TEST(YAMLParser, ParsesArrayOfArrays) {
ExpectParseSuccess("Array of arrays", "[[]]");
}
TEST(YAMLParser, ParsesBlockLiteralScalars) {
ExpectParseSuccess("Block literal scalar", "test: |\n Hello\n World\n");
ExpectParseSuccess("Block literal scalar EOF", "test: |\n Hello\n World");
ExpectParseSuccess("Empty block literal scalar header EOF", "test: | ");
ExpectParseSuccess("Empty block literal scalar", "test: |\ntest2: 20");
ExpectParseSuccess("Empty block literal scalar 2", "- | \n \n\n \n- 42");
ExpectParseSuccess("Block literal scalar in sequence",
"- |\n Testing\n Out\n\n- 22");
ExpectParseSuccess("Block literal scalar in document",
"--- |\n Document\n...");
ExpectParseSuccess("Empty non indented lines still count",
"- |\n First line\n \n\n Another line\n\n- 2");
ExpectParseSuccess("Comment in block literal scalar header",
"test: | # Comment \n No Comment\ntest 2: | # Void");
ExpectParseSuccess("Chomping indicators in block literal scalar header",
"test: |- \n Hello\n\ntest 2: |+ \n\n World\n\n\n");
ExpectParseSuccess("Indent indicators in block literal scalar header",
"test: |1 \n \n Hello \n World\n");
ExpectParseSuccess("Chomping and indent indicators in block literals",
"test: |-1\n Hello\ntest 2: |9+\n World");
ExpectParseSuccess("Trailing comments in block literals",
"test: |\n Content\n # Trailing\n #Comment\ntest 2: 3");
ExpectParseError("Invalid block scalar header", "test: | failure");
ExpectParseError("Invalid line indentation", "test: |\n First line\n Error");
ExpectParseError("Long leading space line", "test: |\n \n Test\n");
}
TEST(YAMLParser, NullTerminatedBlockScalars) {
SourceMgr SM;
yaml::Stream Stream("test: |\n Hello\n World\n", SM);
yaml::Document &Doc = *Stream.begin();
yaml::MappingNode *Map = cast<yaml::MappingNode>(Doc.getRoot());
StringRef Value =
cast<yaml::BlockScalarNode>(Map->begin()->getValue())->getValue();
EXPECT_EQ(Value, "Hello\nWorld\n");
EXPECT_EQ(Value.data()[Value.size()], '\0');
}
TEST(YAMLParser, HandlesEndOfFileGracefully) {
ExpectParseError("In string starting with EOF", "[\"");
ExpectParseError("In string hitting EOF", "[\" ");
ExpectParseError("In string escaping EOF", "[\" \\");
ExpectParseError("In array starting with EOF", "[");
ExpectParseError("In array element starting with EOF", "[[], ");
ExpectParseError("In array hitting EOF", "[[] ");
ExpectParseError("In array hitting EOF", "[[]");
ExpectParseError("In object hitting EOF", "{\"\"");
}
TEST(YAMLParser, HandlesNullValuesInKeyValueNodesGracefully) {
ExpectParseError("KeyValueNode with null key", "? \"\n:");
ExpectParseError("KeyValueNode with null value", "test: '");
}
// Checks that the given string can be parsed into an identical string inside
// of an array.
static void ExpectCanParseString(StringRef String) {
std::string StringInArray = (llvm::Twine("[\"") + String + "\"]").str();
SourceMgr SM;
yaml::Stream Stream(StringInArray, SM);
yaml::SequenceNode *ParsedSequence
= dyn_cast<yaml::SequenceNode>(Stream.begin()->getRoot());
StringRef ParsedString
= dyn_cast<yaml::ScalarNode>(
static_cast<yaml::Node*>(ParsedSequence->begin()))->getRawValue();
ParsedString = ParsedString.substr(1, ParsedString.size() - 2);
EXPECT_EQ(String, ParsedString.str());
}
// Checks that parsing the given string inside an array fails.
static void ExpectCannotParseString(StringRef String) {
std::string StringInArray = (llvm::Twine("[\"") + String + "\"]").str();
ExpectParseError((Twine("When parsing string \"") + String + "\"").str(),
StringInArray);
}
TEST(YAMLParser, ParsesStrings) {
ExpectCanParseString("");
ExpectCannotParseString("\\");
ExpectCannotParseString("\"");
ExpectCanParseString(" ");
ExpectCanParseString("\\ ");
ExpectCanParseString("\\\"");
ExpectCannotParseString("\"\\");
ExpectCannotParseString(" \\");
ExpectCanParseString("\\\\");
ExpectCannotParseString("\\\\\\");
ExpectCanParseString("\\\\\\\\");
ExpectCanParseString("\\\" ");
ExpectCannotParseString("\\\\\" ");
ExpectCanParseString("\\\\\\\" ");
ExpectCanParseString(" \\\\ \\\" \\\\\\\" ");
}
TEST(YAMLParser, WorksWithIteratorAlgorithms) {
SourceMgr SM;
yaml::Stream Stream("[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\"]", SM);
yaml::SequenceNode *Array
= dyn_cast<yaml::SequenceNode>(Stream.begin()->getRoot());
EXPECT_EQ(6, std::distance(Array->begin(), Array->end()));
}
TEST(YAMLParser, DefaultDiagnosticFilename) {
SourceMgr SM;
SMDiagnostic GeneratedDiag;
SM.setDiagHandler(CollectDiagnosticsOutput, &GeneratedDiag);
// When we construct a YAML stream over an unnamed string,
// the filename is hard-coded as "YAML".
yaml::Stream UnnamedStream("[]", SM);
UnnamedStream.printError(UnnamedStream.begin()->getRoot(), "Hello, World!");
EXPECT_EQ("YAML", GeneratedDiag.getFilename());
}
TEST(YAMLParser, DiagnosticFilenameFromBufferID) {
SourceMgr SM;
SMDiagnostic GeneratedDiag;
SM.setDiagHandler(CollectDiagnosticsOutput, &GeneratedDiag);
// When we construct a YAML stream over a named buffer,
// we get its ID as filename in diagnostics.
std::unique_ptr<MemoryBuffer> Buffer =
MemoryBuffer::getMemBuffer("[]", "buffername.yaml");
yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
Stream.printError(Stream.begin()->getRoot(), "Hello, World!");
EXPECT_EQ("buffername.yaml", GeneratedDiag.getFilename());
}
TEST(YAMLParser, SameNodeIteratorOperatorNotEquals) {
SourceMgr SM;
yaml::Stream Stream("[\"1\", \"2\"]", SM);
yaml::SequenceNode *Node = dyn_cast<yaml::SequenceNode>(
Stream.begin()->getRoot());
auto Begin = Node->begin();
auto End = Node->end();
EXPECT_TRUE(Begin != End);
EXPECT_FALSE(Begin != Begin);
EXPECT_FALSE(End != End);
}
TEST(YAMLParser, SameNodeIteratorOperatorEquals) {
SourceMgr SM;
yaml::Stream Stream("[\"1\", \"2\"]", SM);
yaml::SequenceNode *Node = dyn_cast<yaml::SequenceNode>(
Stream.begin()->getRoot());
auto Begin = Node->begin();
auto End = Node->end();
EXPECT_FALSE(Begin == End);
EXPECT_TRUE(Begin == Begin);
EXPECT_TRUE(End == End);
}
TEST(YAMLParser, DifferentNodesIteratorOperatorNotEquals) {
SourceMgr SM;
yaml::Stream Stream("[\"1\", \"2\"]", SM);
yaml::Stream AnotherStream("[\"1\", \"2\"]", SM);
yaml::SequenceNode *Node = dyn_cast<yaml::SequenceNode>(
Stream.begin()->getRoot());
yaml::SequenceNode *AnotherNode = dyn_cast<yaml::SequenceNode>(
AnotherStream.begin()->getRoot());
auto Begin = Node->begin();
auto End = Node->end();
auto AnotherBegin = AnotherNode->begin();
auto AnotherEnd = AnotherNode->end();
EXPECT_TRUE(Begin != AnotherBegin);
EXPECT_TRUE(Begin != AnotherEnd);
EXPECT_FALSE(End != AnotherEnd);
}
TEST(YAMLParser, DifferentNodesIteratorOperatorEquals) {
SourceMgr SM;
yaml::Stream Stream("[\"1\", \"2\"]", SM);
yaml::Stream AnotherStream("[\"1\", \"2\"]", SM);
yaml::SequenceNode *Node = dyn_cast<yaml::SequenceNode>(
Stream.begin()->getRoot());
yaml::SequenceNode *AnotherNode = dyn_cast<yaml::SequenceNode>(
AnotherStream.begin()->getRoot());
auto Begin = Node->begin();
auto End = Node->end();
auto AnotherBegin = AnotherNode->begin();
auto AnotherEnd = AnotherNode->end();
EXPECT_FALSE(Begin == AnotherBegin);
EXPECT_FALSE(Begin == AnotherEnd);
EXPECT_TRUE(End == AnotherEnd);
}
} // end namespace llvm