blob: 4a50addecd209f6d980ebfd5e1bb50d4e1ce04b1 [file] [log] [blame]
//===-- SerializationTests.cpp - Binary and YAML serialization unit tests -===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "index/Serialization.h"
#include "index/SymbolYAML.h"
#include "llvm/Support/ScopedPrinter.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using testing::UnorderedElementsAre;
using testing::UnorderedElementsAreArray;
namespace clang {
namespace clangd {
namespace {
const char *YAML1 = R"(
---
ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF856
Name: 'Foo1'
Scope: 'clang::'
SymInfo:
Kind: Function
Lang: Cpp
CanonicalDeclaration:
FileURI: file:///path/foo.h
Start:
Line: 1
Column: 0
End:
Line: 1
Column: 1
Flags: 1
Documentation: 'Foo doc'
ReturnType: 'int'
IncludeHeaders:
- Header: 'include1'
References: 7
- Header: 'include2'
References: 3
...
)";
const char *YAML2 = R"(
---
ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF858
Name: 'Foo2'
Scope: 'clang::'
SymInfo:
Kind: Function
Lang: Cpp
CanonicalDeclaration:
FileURI: file:///path/bar.h
Start:
Line: 1
Column: 0
End:
Line: 1
Column: 1
Flags: 2
Signature: '-sig'
CompletionSnippetSuffix: '-snippet'
...
)";
MATCHER_P(QName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
}
TEST(SerializationTest, YAMLConversions) {
auto Symbols1 = symbolsFromYAML(YAML1);
ASSERT_EQ(Symbols1.size(), 1u);
const auto &Sym1 = *Symbols1.begin();
EXPECT_THAT(Sym1, QName("clang::Foo1"));
EXPECT_EQ(Sym1.Signature, "");
EXPECT_EQ(Sym1.Documentation, "Foo doc");
EXPECT_EQ(Sym1.ReturnType, "int");
EXPECT_EQ(Sym1.CanonicalDeclaration.FileURI, "file:///path/foo.h");
EXPECT_TRUE(Sym1.Flags & Symbol::IndexedForCodeCompletion);
EXPECT_FALSE(Sym1.Flags & Symbol::Deprecated);
EXPECT_THAT(Sym1.IncludeHeaders,
UnorderedElementsAre(IncludeHeaderWithRef("include1", 7u),
IncludeHeaderWithRef("include2", 3u)));
auto Symbols2 = symbolsFromYAML(YAML2);
ASSERT_EQ(Symbols2.size(), 1u);
const auto &Sym2 = *Symbols2.begin();
EXPECT_THAT(Sym2, QName("clang::Foo2"));
EXPECT_EQ(Sym2.Signature, "-sig");
EXPECT_EQ(Sym2.ReturnType, "");
EXPECT_EQ(Sym2.CanonicalDeclaration.FileURI, "file:///path/bar.h");
EXPECT_FALSE(Sym2.Flags & Symbol::IndexedForCodeCompletion);
EXPECT_TRUE(Sym2.Flags & Symbol::Deprecated);
std::string ConcatenatedYAML;
{
llvm::raw_string_ostream OS(ConcatenatedYAML);
SymbolsToYAML(Symbols1, OS);
SymbolsToYAML(Symbols2, OS);
}
auto ConcatenatedSymbols = symbolsFromYAML(ConcatenatedYAML);
EXPECT_THAT(ConcatenatedSymbols,
UnorderedElementsAre(QName("clang::Foo1"), QName("clang::Foo2")));
}
std::vector<std::string> YAMLFromSymbols(const SymbolSlab &Slab) {
std::vector<std::string> Result;
for (const auto &Sym : Slab)
Result.push_back(SymbolToYAML(Sym));
return Result;
}
TEST(SerializationTest, BinaryConversions) {
// We reuse the test symbols from YAML.
auto Slab = symbolsFromYAML(std::string(YAML1) + YAML2);
ASSERT_EQ(Slab.size(), 2u);
// Write to binary format, and parse again.
IndexFileOut Out;
Out.Symbols = &Slab;
std::string Serialized = llvm::to_string(Out);
auto In = readIndexFile(Serialized);
ASSERT_TRUE(bool(In)) << In.takeError();
ASSERT_TRUE(In->Symbols);
// Assert the YAML serializations match, for nice comparisons and diffs.
EXPECT_THAT(YAMLFromSymbols(*In->Symbols),
UnorderedElementsAreArray(YAMLFromSymbols(Slab)));
}
} // namespace
} // namespace clangd
} // namespace clang