[clang] [clang][ssaf] Refactor `JSONFormatTest` into a directory with a shared fixture header (PR #182523)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 20 11:03:39 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Aviral Goel (aviralg)
<details>
<summary>Changes</summary>
This change converts `Serialization/JSONFormatTest.cpp` into a directory to support reuse of the `JSONFormatTest` fixture by upcoming test files for additional data structures with JSON serialization support. New test files for other serializable data structures can now include `JSONFormatTest.h`, inherit from `JSONFormatTest`, and add their own fixture and tests without duplicating the filesystem scaffolding.
---
Patch is 30.74 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/182523.diff
3 Files Affected:
- (modified) clang/unittests/Analysis/Scalable/CMakeLists.txt (+1-1)
- (added) clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest/JSONFormatTest.h (+144)
- (renamed) clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest/TUSummaryTest.cpp (+65-177)
``````````diff
diff --git a/clang/unittests/Analysis/Scalable/CMakeLists.txt b/clang/unittests/Analysis/Scalable/CMakeLists.txt
index 5529ca06de170..bf0d0e2f3fdea 100644
--- a/clang/unittests/Analysis/Scalable/CMakeLists.txt
+++ b/clang/unittests/Analysis/Scalable/CMakeLists.txt
@@ -11,7 +11,7 @@ add_distinct_clang_unittest(ClangScalableAnalysisTests
Registries/MockSummaryExtractor2.cpp
Registries/SerializationFormatRegistryTest.cpp
Registries/SummaryExtractorRegistryTest.cpp
- Serialization/JSONFormatTest.cpp
+ Serialization/JSONFormatTest/TUSummaryTest.cpp
SummaryNameTest.cpp
TestFixture.cpp
TUSummaryBuilderTest.cpp
diff --git a/clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest/JSONFormatTest.h b/clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest/JSONFormatTest.h
new file mode 100644
index 0000000000000..f0d733d874afa
--- /dev/null
+++ b/clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest/JSONFormatTest.h
@@ -0,0 +1,144 @@
+//===- JSONFormatTest.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Test fixture and helpers for SSAF JSON serialization format unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_ANALYSIS_SCALABLE_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
+#define LLVM_CLANG_UNITTESTS_ANALYSIS_SCALABLE_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+// ============================================================================
+// Test Fixture
+// ============================================================================
+
+class JSONFormatTest : public ::testing::Test {
+public:
+ using PathString = llvm::SmallString<128>;
+
+protected:
+ llvm::SmallString<128> TestDir;
+
+ void SetUp() override {
+ std::error_code EC =
+ llvm::sys::fs::createUniqueDirectory("json-format-test", TestDir);
+ ASSERT_FALSE(EC) << "Failed to create temp directory: " << EC.message();
+ }
+
+ void TearDown() override { llvm::sys::fs::remove_directories(TestDir); }
+
+ PathString makePath(llvm::StringRef FileOrDirectoryName) const {
+ PathString FullPath = TestDir;
+ llvm::sys::path::append(FullPath, FileOrDirectoryName);
+
+ return FullPath;
+ }
+
+ PathString makePath(llvm::StringRef Dir, llvm::StringRef FileName) const {
+ PathString FullPath = TestDir;
+ llvm::sys::path::append(FullPath, Dir, FileName);
+
+ return FullPath;
+ }
+
+ llvm::Expected<PathString>
+ makeDirectory(llvm::StringRef DirectoryName) const {
+ PathString DirPath = makePath(DirectoryName);
+
+ std::error_code EC = llvm::sys::fs::create_directory(DirPath);
+ if (EC) {
+ return llvm::createStringError(EC, "Failed to create directory '%s': %s",
+ DirPath.c_str(), EC.message().c_str());
+ }
+
+ return DirPath;
+ }
+
+ llvm::Expected<PathString>
+ makeSymlink(llvm::StringRef TargetFileName,
+ llvm::StringRef SymlinkFileName) const {
+ PathString TargetPath = makePath(TargetFileName);
+ PathString SymlinkPath = makePath(SymlinkFileName);
+
+ std::error_code EC = llvm::sys::fs::create_link(TargetPath, SymlinkPath);
+ if (EC) {
+ return llvm::createStringError(
+ EC, "Failed to create symlink '%s' -> '%s': %s", SymlinkPath.c_str(),
+ TargetPath.c_str(), EC.message().c_str());
+ }
+
+ return SymlinkPath;
+ }
+
+ llvm::Error setPermission(llvm::StringRef FileName,
+ llvm::sys::fs::perms Perms) const {
+ PathString Path = makePath(FileName);
+
+ std::error_code EC = llvm::sys::fs::setPermissions(Path, Perms);
+ if (EC) {
+ return llvm::createStringError(EC,
+ "Failed to set permissions on '%s': %s",
+ Path.c_str(), EC.message().c_str());
+ }
+
+ return llvm::Error::success();
+ }
+
+ llvm::Expected<llvm::json::Value>
+ readJSONFromFile(llvm::StringRef FileName) const {
+ PathString FilePath = makePath(FileName);
+
+ auto BufferOrError = llvm::MemoryBuffer::getFile(FilePath);
+ if (!BufferOrError) {
+ return llvm::createStringError(BufferOrError.getError(),
+ "Failed to read file: %s",
+ FilePath.c_str());
+ }
+
+ llvm::Expected<llvm::json::Value> ExpectedValue =
+ llvm::json::parse(BufferOrError.get()->getBuffer());
+ if (!ExpectedValue)
+ return ExpectedValue.takeError();
+
+ return *ExpectedValue;
+ }
+
+ llvm::Expected<PathString> writeJSON(llvm::StringRef JSON,
+ llvm::StringRef FileName) const {
+ PathString FilePath = makePath(FileName);
+
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(FilePath, EC);
+ if (EC) {
+ return llvm::createStringError(EC, "Failed to create file '%s': %s",
+ FilePath.c_str(), EC.message().c_str());
+ }
+
+ OS << JSON;
+ OS.close();
+
+ if (OS.has_error()) {
+ return llvm::createStringError(
+ OS.error(), "Failed to write to file '%s': %s", FilePath.c_str(),
+ OS.error().message().c_str());
+ }
+
+ return FilePath;
+ }
+};
+
+#endif // LLVM_CLANG_UNITTESTS_ANALYSIS_SCALABLE_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
\ No newline at end of file
diff --git a/clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest.cpp b/clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest/TUSummaryTest.cpp
similarity index 88%
rename from clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest.cpp
rename to clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest/TUSummaryTest.cpp
index 62890da28e248..2cdbec9675662 100644
--- a/clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest.cpp
+++ b/clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest/TUSummaryTest.cpp
@@ -1,4 +1,4 @@
-//===- unittests/Analysis/Scalable/JSONFormatTest.cpp --------------------===//
+//===- TUSummaryTest.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,32 +6,24 @@
//
//===----------------------------------------------------------------------===//
//
-// Unit tests for SSAF JSON serialization format reading and writing.
+// Unit tests for SSAF JSON serialization format reading and writing of
+// TUSummary.
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/Scalable/Serialization/JSONFormat.h"
#include "clang/Analysis/Scalable/TUSummary/TUSummary.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
+#include "JSONFormatTest.h"
+#include "clang/Analysis/Scalable/Serialization/JSONFormat.h"
#include "llvm/Support/Registry.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include <algorithm>
#include <memory>
-#include <string>
#include <vector>
using namespace clang::ssaf;
using namespace llvm;
using ::testing::AllOf;
using ::testing::HasSubstr;
-
namespace {
// ============================================================================
@@ -108,117 +100,8 @@ static llvm::Registry<JSONFormat::FormatInfo>::Add<
"PairsEntitySummaryForJSONFormatTest",
"Format info for PairsArrayEntitySummary");
-// ============================================================================
-// Test Fixture
-// ============================================================================
-
-class JSONFormatTest : public ::testing::Test {
-public:
- using PathString = SmallString<128>;
-
+class JSONFormatTUSummaryTest : public JSONFormatTest {
protected:
- SmallString<128> TestDir;
-
- void SetUp() override {
- std::error_code EC =
- sys::fs::createUniqueDirectory("json-format-test", TestDir);
- ASSERT_FALSE(EC) << "Failed to create temp directory: " << EC.message();
- }
-
- void TearDown() override { sys::fs::remove_directories(TestDir); }
-
- PathString makePath(StringRef FileOrDirectoryName) const {
- PathString FullPath = TestDir;
- sys::path::append(FullPath, FileOrDirectoryName);
-
- return FullPath;
- }
-
- PathString makePath(StringRef Dir, StringRef FileName) const {
- PathString FullPath = TestDir;
- sys::path::append(FullPath, Dir, FileName);
-
- return FullPath;
- }
-
- Expected<PathString> makeDirectory(StringRef DirectoryName) const {
- PathString DirPath = makePath(DirectoryName);
-
- std::error_code EC = sys::fs::create_directory(DirPath);
- if (EC) {
- return createStringError(EC, "Failed to create directory '%s': %s",
- DirPath.c_str(), EC.message().c_str());
- }
-
- return DirPath;
- }
-
- Expected<PathString> makeSymlink(StringRef TargetFileName,
- StringRef SymlinkFileName) const {
- PathString TargetPath = makePath(TargetFileName);
- PathString SymlinkPath = makePath(SymlinkFileName);
-
- std::error_code EC = sys::fs::create_link(TargetPath, SymlinkPath);
- if (EC) {
- return createStringError(EC, "Failed to create symlink '%s' -> '%s': %s",
- SymlinkPath.c_str(), TargetPath.c_str(),
- EC.message().c_str());
- }
-
- return SymlinkPath;
- }
-
- llvm::Error setPermission(StringRef FileName,
- const sys::fs::perms Perms) const {
- PathString Path = makePath(FileName);
-
- std::error_code EC = sys::fs::setPermissions(Path, Perms);
- if (EC) {
- return createStringError(EC, "Failed to set permissions on '%s': %s",
- Path.c_str(), EC.message().c_str());
- }
-
- return llvm::Error::success();
- }
-
- Expected<json::Value> readJSONFromFile(StringRef FileName) const {
- PathString FilePath = makePath(FileName);
-
- auto BufferOrError = MemoryBuffer::getFile(FilePath);
- if (!BufferOrError) {
- return createStringError(BufferOrError.getError(),
- "Failed to read file: %s", FilePath.c_str());
- }
-
- Expected<json::Value> ExpectedValue =
- json::parse(BufferOrError.get()->getBuffer());
- if (!ExpectedValue)
- return ExpectedValue.takeError();
-
- return *ExpectedValue;
- }
-
- Expected<PathString> writeJSON(StringRef JSON, StringRef FileName) const {
- PathString FilePath = makePath(FileName);
-
- std::error_code EC;
- llvm::raw_fd_ostream OS(FilePath, EC);
- if (EC) {
- return createStringError(EC, "Failed to create file '%s': %s",
- FilePath.c_str(), EC.message().c_str());
- }
-
- OS << JSON;
- OS.close();
-
- if (OS.has_error()) {
- return createStringError(OS.error(), "Failed to write to file '%s': %s",
- FilePath.c_str(), OS.error().message().c_str());
- }
-
- return FilePath;
- }
-
llvm::Expected<TUSummary> readTUSummaryFromFile(StringRef FileName) const {
PathString FilePath = makePath(FileName);
@@ -362,7 +245,7 @@ class JSONFormatTest : public ::testing::Test {
// readJSON() Error Tests
// ============================================================================
-TEST_F(JSONFormatTest, NonexistentFile) {
+TEST_F(JSONFormatTUSummaryTest, NonexistentFile) {
auto Result = readTUSummaryFromFile("nonexistent.json");
EXPECT_THAT_EXPECTED(
@@ -370,7 +253,7 @@ TEST_F(JSONFormatTest, NonexistentFile) {
HasSubstr("file does not exist"))));
}
-TEST_F(JSONFormatTest, PathIsDirectory) {
+TEST_F(JSONFormatTUSummaryTest, PathIsDirectory) {
PathString DirName("test_directory.json");
auto ExpectedDirPath = makeDirectory(DirName);
@@ -384,7 +267,7 @@ TEST_F(JSONFormatTest, PathIsDirectory) {
HasSubstr("path is a directory, not a file"))));
}
-TEST_F(JSONFormatTest, NotJsonExtension) {
+TEST_F(JSONFormatTUSummaryTest, NotJsonExtension) {
PathString FileName("test.txt");
auto ExpectedFilePath = writeJSON("{}", FileName);
@@ -399,7 +282,7 @@ TEST_F(JSONFormatTest, NotJsonExtension) {
HasSubstr("file does not end with '.json' extension"))));
}
-TEST_F(JSONFormatTest, BrokenSymlink) {
+TEST_F(JSONFormatTUSummaryTest, BrokenSymlink) {
#ifdef _WIN32
GTEST_SKIP() << "Symlink model differs on Windows";
#endif
@@ -416,7 +299,7 @@ TEST_F(JSONFormatTest, BrokenSymlink) {
HasSubstr("failed to read file"))));
}
-TEST_F(JSONFormatTest, NoReadPermission) {
+TEST_F(JSONFormatTUSummaryTest, NoReadPermission) {
#ifdef _WIN32
GTEST_SKIP() << "Permission model differs on Windows";
#endif
@@ -449,7 +332,7 @@ TEST_F(JSONFormatTest, NoReadPermission) {
EXPECT_THAT_ERROR(std::move(RestoreError), Succeeded());
}
-TEST_F(JSONFormatTest, InvalidSyntax) {
+TEST_F(JSONFormatTUSummaryTest, InvalidSyntax) {
auto Result = readTUSummaryFromString("{ invalid json }");
EXPECT_THAT_EXPECTED(
@@ -457,7 +340,7 @@ TEST_F(JSONFormatTest, InvalidSyntax) {
HasSubstr("Expected object key"))));
}
-TEST_F(JSONFormatTest, NotObject) {
+TEST_F(JSONFormatTUSummaryTest, NotObject) {
auto Result = readTUSummaryFromString("[]");
EXPECT_THAT_EXPECTED(
@@ -470,7 +353,7 @@ TEST_F(JSONFormatTest, NotObject) {
// JSONFormat::buildNamespaceKindFromJSON() Error Tests
// ============================================================================
-TEST_F(JSONFormatTest, InvalidKind) {
+TEST_F(JSONFormatTUSummaryTest, InvalidKind) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "invalid_kind",
@@ -494,7 +377,7 @@ TEST_F(JSONFormatTest, InvalidKind) {
// JSONFormat::buildNamespaceFromJSON() Error Tests
// ============================================================================
-TEST_F(JSONFormatTest, MissingKind) {
+TEST_F(JSONFormatTUSummaryTest, MissingKind) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"name": "test.cpp"
@@ -512,7 +395,7 @@ TEST_F(JSONFormatTest, MissingKind) {
HasSubstr("expected JSON string"))));
}
-TEST_F(JSONFormatTest, MissingName) {
+TEST_F(JSONFormatTUSummaryTest, MissingName) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit"
@@ -534,7 +417,7 @@ TEST_F(JSONFormatTest, MissingName) {
// JSONFormat::nestedBuildNamespaceFromJSON() Error Tests
// ============================================================================
-TEST_F(JSONFormatTest, NamespaceElementNotObject) {
+TEST_F(JSONFormatTUSummaryTest, NamespaceElementNotObject) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit",
@@ -565,7 +448,7 @@ TEST_F(JSONFormatTest, NamespaceElementNotObject) {
HasSubstr("expected JSON object"))));
}
-TEST_F(JSONFormatTest, NamespaceElementMissingKind) {
+TEST_F(JSONFormatTUSummaryTest, NamespaceElementMissingKind) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit",
@@ -601,7 +484,7 @@ TEST_F(JSONFormatTest, NamespaceElementMissingKind) {
HasSubstr("expected JSON string"))));
}
-TEST_F(JSONFormatTest, NamespaceElementInvalidKind) {
+TEST_F(JSONFormatTUSummaryTest, NamespaceElementInvalidKind) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit",
@@ -639,7 +522,7 @@ TEST_F(JSONFormatTest, NamespaceElementInvalidKind) {
"invalid 'kind' BuildNamespaceKind value 'invalid_kind'"))));
}
-TEST_F(JSONFormatTest, NamespaceElementMissingName) {
+TEST_F(JSONFormatTUSummaryTest, NamespaceElementMissingName) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit",
@@ -679,7 +562,7 @@ TEST_F(JSONFormatTest, NamespaceElementMissingName) {
// JSONFormat::entityNameFromJSON() Error Tests
// ============================================================================
-TEST_F(JSONFormatTest, EntityNameMissingUSR) {
+TEST_F(JSONFormatTUSummaryTest, EntityNameMissingUSR) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit",
@@ -707,7 +590,7 @@ TEST_F(JSONFormatTest, EntityNameMissingUSR) {
HasSubstr("expected JSON string"))));
}
-TEST_F(JSONFormatTest, EntityNameMissingSuffix) {
+TEST_F(JSONFormatTUSummaryTest, EntityNameMissingSuffix) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit",
@@ -735,7 +618,7 @@ TEST_F(JSONFormatTest, EntityNameMissingSuffix) {
HasSubstr("expected JSON string"))));
}
-TEST_F(JSONFormatTest, EntityNameMissingNamespace) {
+TEST_F(JSONFormatTUSummaryTest, EntityNameMissingNamespace) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit",
@@ -769,7 +652,7 @@ TEST_F(JSONFormatTest, EntityNameMissingNamespace) {
// JSONFormat::entityIdTableEntryFromJSON() Error Tests
// ============================================================================
-TEST_F(JSONFormatTest, IDTableEntryMissingID) {
+TEST_F(JSONFormatTUSummaryTest, IDTableEntryMissingID) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit",
@@ -797,7 +680,7 @@ TEST_F(JSONFormatTest, IDTableEntryMissingID) {
HasSubstr("expected JSON number (unsigned 64-bit integer)"))));
}
-TEST_F(JSONFormatTest, IDTableEntryMissingName) {
+TEST_F(JSONFormatTUSummaryTest, IDTableEntryMissingName) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit",
@@ -820,7 +703,7 @@ TEST_F(JSONFormatTest, IDTableEntryMissingName) {
HasSubstr("expected JSON object"))));
}
-TEST_F(JSONFormatTest, IDTableEntryIDNotUInt64) {
+TEST_F(JSONFormatTUSummaryTest, IDTableEntryIDNotUInt64) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit",
@@ -853,7 +736,7 @@ TEST_F(JSONFormatTest, IDTableEntryIDNotUInt64) {
// JSONFormat::entityIdTableFromJSON() Error Tests
// ============================================================================
-TEST_F(JSONFormatTest, IDTableNotArray) {
+TEST_F(JSONFormatTUSummaryTest, IDTableNotArray) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit",
@@ -870,7 +753,7 @@ TEST_F(JSONFormatTest, IDTableNotArray) {
HasSubstr("expected JSON array"))));
}
-TEST_F(JSONFormatTest, IDTableElementNotObject) {
+TEST_F(JSONFormatTUSummaryTest, IDTableElementNotObject) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit",
@@ -889,7 +772,7 @@ TEST_F(JSONFormatTest, IDTableElementNotObject) {
HasSubstr("expected JSON object"))));
}
-TEST_F(JSONFormatTest, DuplicateEntity) {
+TEST_F(JSONFormatTUSummaryTest, DuplicateEntity) {
auto Result = readTUSummaryFromString(R"({
"tu_namespace": {
"kind": "compilation_unit",
@@ -939,7 +822,7 @@ TEST_F(JSONFormatTest, DuplicateEntity) {
// JSONFormat::entitySummaryFromJSON() Error Tests
// ============================================================================
-TEST_F(JSONFormatTest, EntitySummaryNoFormatInfo) {
+TEST_F(JSONFormatTUSummaryTest, EntitySummaryNoFormatInfo) {
auto Result = readTUSummaryFromString(R"({
...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/182523
More information about the cfe-commits
mailing list