[PATCH] D53081: [clang-doc] Add unit tests for serialization

2018-10-16 Thread Julie Hockett via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rCTE344650: [clang-doc] Add unit tests for serialization 
(authored by juliehockett, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D53081?vs=169754=169907#toc

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53081

Files:
  unittests/CMakeLists.txt
  unittests/clang-doc/CMakeLists.txt
  unittests/clang-doc/ClangDocTest.cpp
  unittests/clang-doc/ClangDocTest.h
  unittests/clang-doc/SerializeTest.cpp

Index: unittests/clang-doc/ClangDocTest.cpp
===
--- unittests/clang-doc/ClangDocTest.cpp
+++ unittests/clang-doc/ClangDocTest.cpp
@@ -0,0 +1,182 @@
+//===-- clang-doc/ClangDocTest.cpp ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "Representation.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace doc {
+
+NamespaceInfo *InfoAsNamespace(Info *I) {
+  assert(I->IT == InfoType::IT_namespace);
+  return static_cast(I);
+}
+
+RecordInfo *InfoAsRecord(Info *I) {
+  assert(I->IT == InfoType::IT_record);
+  return static_cast(I);
+}
+
+FunctionInfo *InfoAsFunction(Info *I) {
+  assert(I->IT == InfoType::IT_function);
+  return static_cast(I);
+}
+
+EnumInfo *InfoAsEnum(Info *I) {
+  assert(I->IT == InfoType::IT_enum);
+  return static_cast(I);
+}
+
+void CheckCommentInfo(CommentInfo , CommentInfo ) {
+  EXPECT_EQ(Expected.Kind, Actual.Kind);
+  EXPECT_EQ(Expected.Text, Actual.Text);
+  EXPECT_EQ(Expected.Name, Actual.Name);
+  EXPECT_EQ(Expected.Direction, Actual.Direction);
+  EXPECT_EQ(Expected.ParamName, Actual.ParamName);
+  EXPECT_EQ(Expected.CloseName, Actual.CloseName);
+  EXPECT_EQ(Expected.SelfClosing, Actual.SelfClosing);
+  EXPECT_EQ(Expected.Explicit, Actual.Explicit);
+
+  ASSERT_EQ(Expected.AttrKeys.size(), Actual.AttrKeys.size());
+  for (size_t Idx = 0; Idx < Actual.AttrKeys.size(); ++Idx)
+EXPECT_EQ(Expected.AttrKeys[Idx], Actual.AttrKeys[Idx]);
+
+  ASSERT_EQ(Expected.AttrValues.size(), Actual.AttrValues.size());
+  for (size_t Idx = 0; Idx < Actual.AttrValues.size(); ++Idx)
+EXPECT_EQ(Expected.AttrValues[Idx], Actual.AttrValues[Idx]);
+
+  ASSERT_EQ(Expected.Args.size(), Actual.Args.size());
+  for (size_t Idx = 0; Idx < Actual.Args.size(); ++Idx)
+EXPECT_EQ(Expected.Args[Idx], Actual.Args[Idx]);
+
+  ASSERT_EQ(Expected.Children.size(), Actual.Children.size());
+  for (size_t Idx = 0; Idx < Actual.Children.size(); ++Idx)
+CheckCommentInfo(*Expected.Children[Idx], *Actual.Children[Idx]);
+}
+
+void CheckReference(Reference , Reference ) {
+  EXPECT_EQ(Expected.Name, Actual.Name);
+  EXPECT_EQ(Expected.RefType, Actual.RefType);
+}
+
+void CheckTypeInfo(TypeInfo *Expected, TypeInfo *Actual) {
+  CheckReference(Expected->Type, Actual->Type);
+}
+
+void CheckFieldTypeInfo(FieldTypeInfo *Expected, FieldTypeInfo *Actual) {
+  CheckTypeInfo(Expected, Actual);
+  EXPECT_EQ(Expected->Name, Actual->Name);
+}
+
+void CheckMemberTypeInfo(MemberTypeInfo *Expected, MemberTypeInfo *Actual) {
+  CheckFieldTypeInfo(Expected, Actual);
+  EXPECT_EQ(Expected->Access, Actual->Access);
+}
+
+void CheckBaseInfo(Info *Expected, Info *Actual) {
+  EXPECT_EQ(size_t(20), Actual->USR.size());
+  EXPECT_EQ(Expected->Name, Actual->Name);
+  ASSERT_EQ(Expected->Namespace.size(), Actual->Namespace.size());
+  for (size_t Idx = 0; Idx < Actual->Namespace.size(); ++Idx)
+CheckReference(Expected->Namespace[Idx], Actual->Namespace[Idx]);
+  ASSERT_EQ(Expected->Description.size(), Actual->Description.size());
+  for (size_t Idx = 0; Idx < Actual->Description.size(); ++Idx)
+CheckCommentInfo(Expected->Description[Idx], Actual->Description[Idx]);
+}
+
+void CheckSymbolInfo(SymbolInfo *Expected, SymbolInfo *Actual) {
+  CheckBaseInfo(Expected, Actual);
+  EXPECT_EQ(Expected->DefLoc.hasValue(), Actual->DefLoc.hasValue());
+  if (Expected->DefLoc.hasValue() && Actual->DefLoc.hasValue()) {
+EXPECT_EQ(Expected->DefLoc->LineNumber, Actual->DefLoc->LineNumber);
+EXPECT_EQ(Expected->DefLoc->Filename, Actual->DefLoc->Filename);
+  }
+  ASSERT_EQ(Expected->Loc.size(), Actual->Loc.size());
+  for (size_t Idx = 0; Idx < Actual->Loc.size(); ++Idx)
+EXPECT_EQ(Expected->Loc[Idx], Actual->Loc[Idx]);
+}
+
+void CheckFunctionInfo(FunctionInfo *Expected, FunctionInfo *Actual) {
+  CheckSymbolInfo(Expected, Actual);
+
+  EXPECT_EQ(Expected->IsMethod, Actual->IsMethod);
+  CheckReference(Expected->Parent, Actual->Parent);
+  CheckTypeInfo(>ReturnType, >ReturnType);
+
+  ASSERT_EQ(Expected->Params.size(), Actual->Params.size());
+  for (size_t Idx = 0; Idx < Actual->Params.size(); ++Idx)
+

[PATCH] D53081: [clang-doc] Add unit tests for serialization

2018-10-15 Thread Jake Ehrlich via Phabricator via cfe-commits
jakehehrlich accepted this revision.
jakehehrlich added a comment.
This revision is now accepted and ready to land.

LGTM, I'd file a bug about SmallString not taking const char* in its 
constructor and I'd also put a TODO somewhere to fix that once that's resolved.


https://reviews.llvm.org/D53081



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53081: [clang-doc] Add unit tests for serialization

2018-10-15 Thread Julie Hockett via Phabricator via cfe-commits
juliehockett updated this revision to Diff 169754.
juliehockett marked an inline comment as done.

https://reviews.llvm.org/D53081

Files:
  clang-tools-extra/unittests/CMakeLists.txt
  clang-tools-extra/unittests/clang-doc/CMakeLists.txt
  clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp
  clang-tools-extra/unittests/clang-doc/ClangDocTest.h
  clang-tools-extra/unittests/clang-doc/SerializeTest.cpp

Index: clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
===
--- /dev/null
+++ clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
@@ -0,0 +1,346 @@
+//===-- clang-doc/SerializeTest.cpp ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "Serialize.h"
+#include "ClangDocTest.h"
+#include "Representation.h"
+#include "clang/AST/Comment.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace doc {
+
+class ClangDocSerializeTestVisitor
+: public RecursiveASTVisitor {
+
+  EmittedInfoList 
+  bool Public;
+
+  comments::FullComment *getComment(const NamedDecl *D) const {
+if (RawComment *Comment =
+D->getASTContext().getRawCommentForDeclNoCache(D)) {
+  Comment->setAttached();
+  return Comment->parse(D->getASTContext(), nullptr, D);
+}
+return nullptr;
+  }
+
+public:
+  ClangDocSerializeTestVisitor(EmittedInfoList , bool Public)
+  : EmittedInfos(EmittedInfos), Public(Public) {}
+
+  bool VisitNamespaceDecl(const NamespaceDecl *D) {
+auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+
+  bool VisitFunctionDecl(const FunctionDecl *D) {
+// Don't visit CXXMethodDecls twice
+if (dyn_cast(D))
+  return true;
+auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+
+  bool VisitCXXMethodDecl(const CXXMethodDecl *D) {
+auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+
+  bool VisitRecordDecl(const RecordDecl *D) {
+auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+
+  bool VisitEnumDecl(const EnumDecl *D) {
+auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+};
+
+void ExtractInfosFromCode(StringRef Code, size_t NumExpectedInfos, bool Public,
+  EmittedInfoList ) {
+  auto ASTUnit = clang::tooling::buildASTFromCode(Code);
+  auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
+  ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
+  Visitor.TraverseTranslationUnitDecl(TU);
+  ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
+}
+
+void ExtractInfosFromCodeWithArgs(StringRef Code, size_t NumExpectedInfos,
+  bool Public, EmittedInfoList ,
+  std::vector ) {
+  auto ASTUnit = clang::tooling::buildASTFromCodeWithArgs(Code, Args);
+  auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
+  ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
+  Visitor.TraverseTranslationUnitDecl(TU);
+  ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
+}
+
+// Test serialization of namespace declarations.
+TEST(SerializeTest, emitNamespaceInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode("namespace A { namespace B { void f() {} } }", 3,
+   /*Public=*/false, Infos);
+
+  NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
+  NamespaceInfo ExpectedA(EmptySID, "A");
+  CheckNamespaceInfo(, A);
+
+  NamespaceInfo *B = InfoAsNamespace(Infos[1].get());
+  NamespaceInfo ExpectedB(EmptySID, "B");
+  ExpectedB.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+  CheckNamespaceInfo(, B);
+
+  NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[2].get());
+  NamespaceInfo ExpectedBWithFunction(EmptySID);
+  FunctionInfo F;
+  F.Name = "f";
+  F.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
+  F.DefLoc = Location(0, llvm::SmallString<16>("test.cpp"));
+  F.Namespace.emplace_back(EmptySID, "B", InfoType::IT_namespace);
+  

[PATCH] D53081: [clang-doc] Add unit tests for serialization

2018-10-15 Thread Petr Hosek via Phabricator via cfe-commits
phosek added inline comments.



Comment at: clang-tools-extra/unittests/clang-doc/SerializeTest.cpp:320
+  ExtractInfosFromCodeWithArgs(
+  "export module M;\n"
+  "int moduleFunction(int x);\n"

Can you use raw strings here (and elsewhere in this file) as well?


https://reviews.llvm.org/D53081



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53081: [clang-doc] Add unit tests for serialization

2018-10-15 Thread Julie Hockett via Phabricator via cfe-commits
juliehockett updated this revision to Diff 169748.
juliehockett marked 2 inline comments as done.

https://reviews.llvm.org/D53081

Files:
  clang-tools-extra/unittests/CMakeLists.txt
  clang-tools-extra/unittests/clang-doc/CMakeLists.txt
  clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp
  clang-tools-extra/unittests/clang-doc/ClangDocTest.h
  clang-tools-extra/unittests/clang-doc/SerializeTest.cpp

Index: clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
===
--- /dev/null
+++ clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
@@ -0,0 +1,349 @@
+//===-- clang-doc/SerializeTest.cpp ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "Serialize.h"
+#include "ClangDocTest.h"
+#include "Representation.h"
+#include "clang/AST/Comment.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace doc {
+
+class ClangDocSerializeTestVisitor
+: public RecursiveASTVisitor {
+
+  EmittedInfoList 
+  bool Public;
+
+  comments::FullComment *getComment(const NamedDecl *D) const {
+if (RawComment *Comment =
+D->getASTContext().getRawCommentForDeclNoCache(D)) {
+  Comment->setAttached();
+  return Comment->parse(D->getASTContext(), nullptr, D);
+}
+return nullptr;
+  }
+
+public:
+  ClangDocSerializeTestVisitor(EmittedInfoList , bool Public)
+  : EmittedInfos(EmittedInfos), Public(Public) {}
+
+  bool VisitNamespaceDecl(const NamespaceDecl *D) {
+auto I = serialize::emitInfo(D, getComment(D), /*Line=*/ 0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+
+  bool VisitFunctionDecl(const FunctionDecl *D) {
+// Don't visit CXXMethodDecls twice
+if (dyn_cast(D))
+  return true;
+auto I = serialize::emitInfo(D, getComment(D), /*Line=*/ 0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+
+  bool VisitCXXMethodDecl(const CXXMethodDecl *D) {
+auto I = serialize::emitInfo(D, getComment(D), /*Line=*/ 0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+
+  bool VisitRecordDecl(const RecordDecl *D) {
+auto I = serialize::emitInfo(D, getComment(D), /*Line=*/ 0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+
+  bool VisitEnumDecl(const EnumDecl *D) {
+auto I = serialize::emitInfo(D, getComment(D), /*Line=*/ 0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+};
+
+void ExtractInfosFromCode(StringRef Code, size_t NumExpectedInfos, bool Public,
+  EmittedInfoList ) {
+  auto ASTUnit = clang::tooling::buildASTFromCode(Code);
+  auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
+  ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
+  Visitor.TraverseTranslationUnitDecl(TU);
+  ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
+}
+
+void ExtractInfosFromCodeWithArgs(StringRef Code, size_t NumExpectedInfos,
+  bool Public, EmittedInfoList ,
+  std::vector ) {
+  auto ASTUnit = clang::tooling::buildASTFromCodeWithArgs(Code, Args);
+  auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
+  ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
+  Visitor.TraverseTranslationUnitDecl(TU);
+  ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
+}
+
+// Test serialization of namespace declarations.
+TEST(SerializeTest, emitNamespaceInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode("namespace A { namespace B { void f() {} } }", 3,
+   /*Public=*/false, Infos);
+
+  NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
+  NamespaceInfo ExpectedA(EmptySID, "A");
+  CheckNamespaceInfo(, A);
+
+  NamespaceInfo *B = InfoAsNamespace(Infos[1].get());
+  NamespaceInfo ExpectedB(EmptySID, "B");
+  ExpectedB.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+  CheckNamespaceInfo(, B);
+
+  NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[2].get());
+  NamespaceInfo ExpectedBWithFunction(EmptySID);
+  FunctionInfo F;
+  F.Name = "f";
+  F.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
+  F.DefLoc = Location(0, llvm::SmallString<16>("test.cpp"));
+  F.Namespace.emplace_back(EmptySID, "B", InfoType::IT_namespace);
+  

[PATCH] D53081: [clang-doc] Add unit tests for serialization

2018-10-14 Thread Petr Hosek via Phabricator via cfe-commits
phosek added inline comments.



Comment at: clang-tools-extra/unittests/clang-doc/SerializeTest.cpp:27
+comments::FullComment *
+getComment(const NamedDecl *D) const {
+  if (RawComment *Comment = D->getASTContext().getRawCommentForDeclNoCache(D)) 
{

Nit: this function seems to be wrongly indented.



Comment at: clang-tools-extra/unittests/clang-doc/SerializeTest.cpp:40
+  bool VisitNamespaceDecl(const NamespaceDecl *D) {
+auto I = serialize::emitInfo(D, getComment(D), /*Line*/ 0,
+ /*File=*/"test.cpp", Public);

Nit: this should be `/*Line=*/` for consistency, the same below.


https://reviews.llvm.org/D53081



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53081: [clang-doc] Add unit tests for serialization

2018-10-10 Thread Julie Hockett via Phabricator via cfe-commits
juliehockett created this revision.
juliehockett added reviewers: leonardchan, jakehehrlich, lebedev.ri.
juliehockett added a project: clang-tools-extra.
Herald added subscribers: kadircet, arphaman, mgorny.

This is part of a move to convert clang-doc's tests to a more maintainable unit 
test framework, with a smaller number of integration tests to maintain and more 
granular failure feedback.


https://reviews.llvm.org/D53081

Files:
  clang-tools-extra/unittests/CMakeLists.txt
  clang-tools-extra/unittests/clang-doc/CMakeLists.txt
  clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp
  clang-tools-extra/unittests/clang-doc/ClangDocTest.h
  clang-tools-extra/unittests/clang-doc/SerializeTest.cpp

Index: clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
===
--- /dev/null
+++ clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
@@ -0,0 +1,346 @@
+//===-- clang-doc/SerializeTest.cpp ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "Serialize.h"
+#include "ClangDocTest.h"
+#include "Representation.h"
+#include "clang/AST/Comment.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace doc {
+
+class ClangDocSerializeTestVisitor
+: public RecursiveASTVisitor {
+
+  EmittedInfoList 
+  bool Public;
+
+comments::FullComment *
+getComment(const NamedDecl *D) const {
+  if (RawComment *Comment = D->getASTContext().getRawCommentForDeclNoCache(D)) {
+Comment->setAttached();
+return Comment->parse(D->getASTContext(), nullptr, D);
+  }
+  return nullptr;
+}
+
+public:
+  ClangDocSerializeTestVisitor(EmittedInfoList , bool Public)
+  : EmittedInfos(EmittedInfos), Public(Public) {}
+
+  bool VisitNamespaceDecl(const NamespaceDecl *D) {
+auto I = serialize::emitInfo(D, getComment(D), /*Line*/ 0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+
+  bool VisitFunctionDecl(const FunctionDecl *D) {
+// Don't visit CXXMethodDecls twice
+if (dyn_cast(D))
+  return true;
+auto I = serialize::emitInfo(D, getComment(D), /*Line*/ 0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+
+  bool VisitCXXMethodDecl(const CXXMethodDecl *D) {
+auto I = serialize::emitInfo(D, getComment(D), /*Line*/ 0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+
+  bool VisitRecordDecl(const RecordDecl *D) {
+auto I = serialize::emitInfo(D, getComment(D), /*Line*/ 0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+
+  bool VisitEnumDecl(const EnumDecl *D) {
+auto I = serialize::emitInfo(D, getComment(D), /*Line*/ 0,
+ /*File=*/"test.cpp", Public);
+if (I)
+  EmittedInfos.emplace_back(std::move(I));
+return true;
+  }
+};
+
+void ExtractInfosFromCode(StringRef Code, size_t NumExpectedInfos, bool Public,
+  EmittedInfoList ) {
+  auto ASTUnit = clang::tooling::buildASTFromCode(Code);
+  auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
+  ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
+  Visitor.TraverseTranslationUnitDecl(TU);
+  ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
+}
+
+void ExtractInfosFromCodeWithArgs(StringRef Code, size_t NumExpectedInfos, bool Public,
+  EmittedInfoList , std::vector& Args) {
+  auto ASTUnit = clang::tooling::buildASTFromCodeWithArgs(Code, Args);
+  auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
+  ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
+  Visitor.TraverseTranslationUnitDecl(TU);
+  ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
+}
+
+// Test serialization of namespace declarations.
+TEST(SerializeTest, emitNamespaceInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode("namespace A { namespace B { void f() {} } }", 3,
+   /*Public=*/false, Infos);
+
+  NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
+  NamespaceInfo ExpectedA(EmptySID, "A");
+  CheckNamespaceInfo(, A);
+
+  NamespaceInfo *B = InfoAsNamespace(Infos[1].get());
+  NamespaceInfo ExpectedB(EmptySID, "B");
+  ExpectedB.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+  CheckNamespaceInfo(, B);
+
+  NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[2].get());
+  NamespaceInfo ExpectedBWithFunction(EmptySID);
+  FunctionInfo F;
+