[clang] ce0668b - [clang][ssaf] Convert `JSONFormat` tests for `LUSummary` and `LUSummaryEncoding` to lit tests (#192738)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 10 07:13:45 PDT 2026
Author: Aviral Goel
Date: 2026-06-10T07:13:39-07:00
New Revision: ce0668b7346c3bbde4e17907d678a739ab1877dd
URL: https://github.com/llvm/llvm-project/commit/ce0668b7346c3bbde4e17907d678a739ab1877dd
DIFF: https://github.com/llvm/llvm-project/commit/ce0668b7346c3bbde4e17907d678a739ab1877dd.diff
LOG: [clang][ssaf] Convert `JSONFormat` tests for `LUSummary` and `LUSummaryEncoding` to lit tests (#192738)
Added:
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-element-not-object.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-entry-missing-data.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-entry-missing-summary-name.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-not-array.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/duplicate-entity-id-in-data-map.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/duplicate-entity.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/duplicate-summary-name.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-data-element-not-object.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-data-missing-entity-id.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-data-missing-entity-summary.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-id-not-uint64.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-name-missing-namespace.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-name-missing-suffix.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-name-missing-usr.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-element-not-object.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-entry-id-not-uint64.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-entry-missing-id.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-entry-missing-name.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-not-array.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/invalid-syntax.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-duplicate-id.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-element-not-object.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-id-not-uint64.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-linkage-invalid-type.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-linkage-missing-type.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-missing-id.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-missing-linkage.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-extra-id.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-missing-id.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-not-array.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-invalid-kind.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-missing-kind.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-missing-name.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-not-object.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-not-array.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-data.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-id-table.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-linkage-table.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-lu-namespace.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-invalid-kind.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-missing-kind.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-missing-name.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-not-object.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/not-json-extension.txt
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/not-object.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-element-not-object.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-invalid-first-field.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-invalid-pairs-field-type.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-invalid-second-field.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-missing-first-field.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-missing-pairs-field.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-missing-second-field.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/read-entity-summary-no-format-info.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-empty-data-entry.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-empty-namespace.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-external.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-internal.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-multiple.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-none.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-multiple-namespace-elements.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-single-namespace-element.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-two-summary-types.json
clang/test/Analysis/Scalable/ssaf-format/LUSummary/id-table.test
clang/test/Analysis/Scalable/ssaf-format/LUSummary/io.test
clang/test/Analysis/Scalable/ssaf-format/LUSummary/linkage.test
clang/test/Analysis/Scalable/ssaf-format/LUSummary/permissions.test
clang/test/Analysis/Scalable/ssaf-format/LUSummary/round-trip.test
clang/test/Analysis/Scalable/ssaf-format/LUSummary/summary-data.test
clang/test/Analysis/Scalable/ssaf-format/LUSummary/top-level.test
Modified:
clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp
Removed:
################################################################################
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-element-not-object.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-element-not-object.json
new file mode 100644
index 0000000000000..86d3ef89ffe8f
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-element-not-object.json
@@ -0,0 +1,13 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ "invalid"
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-entry-missing-data.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-entry-missing-data.json
new file mode 100644
index 0000000000000..3374f3c31157f
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-entry-missing-data.json
@@ -0,0 +1,15 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-entry-missing-summary-name.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-entry-missing-summary-name.json
new file mode 100644
index 0000000000000..fe9b2c46d4c8f
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-entry-missing-summary-name.json
@@ -0,0 +1,15 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_data": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-not-array.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-not-array.json
new file mode 100644
index 0000000000000..9b53c28a16988
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/data-not-array.json
@@ -0,0 +1,11 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": {}
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/duplicate-entity-id-in-data-map.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/duplicate-entity-id-in-data-map.json
new file mode 100644
index 0000000000000..8a59b795a965b
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/duplicate-entity-id-in-data-map.json
@@ -0,0 +1,54 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "usr": "c:@F at foo",
+ "suffix": "",
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ },
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ]
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "None"
+ }
+ }
+ ],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {
+ "pairs": []
+ }
+ },
+ {
+ "entity_id": 0,
+ "entity_summary": {
+ "pairs": []
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/duplicate-entity.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/duplicate-entity.json
new file mode 100644
index 0000000000000..3330d039515e2
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/duplicate-entity.json
@@ -0,0 +1,59 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "usr": "c:@F at foo",
+ "suffix": "",
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ },
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ]
+ }
+ },
+ {
+ "id": 1,
+ "name": {
+ "usr": "c:@F at foo",
+ "suffix": "",
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ },
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ]
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "None"
+ }
+ },
+ {
+ "id": 1,
+ "linkage": {
+ "type": "None"
+ }
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/duplicate-summary-name.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/duplicate-summary-name.json
new file mode 100644
index 0000000000000..9b223799cfcde
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/duplicate-summary-name.json
@@ -0,0 +1,20 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": []
+ },
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-data-element-not-object.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-data-element-not-object.json
new file mode 100644
index 0000000000000..03dc6925a3679
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-data-element-not-object.json
@@ -0,0 +1,18 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": [
+ "invalid"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-data-missing-entity-id.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-data-missing-entity-id.json
new file mode 100644
index 0000000000000..d312667f7b7e0
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-data-missing-entity-id.json
@@ -0,0 +1,20 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": [
+ {
+ "entity_summary": {}
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-data-missing-entity-summary.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-data-missing-entity-summary.json
new file mode 100644
index 0000000000000..a230bf12d35b6
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-data-missing-entity-summary.json
@@ -0,0 +1,20 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": [
+ {
+ "entity_id": 0
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-id-not-uint64.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-id-not-uint64.json
new file mode 100644
index 0000000000000..efb7db6a7b8d6
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-id-not-uint64.json
@@ -0,0 +1,21 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": [
+ {
+ "entity_id": "not_a_number",
+ "entity_summary": {}
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-name-missing-namespace.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-name-missing-namespace.json
new file mode 100644
index 0000000000000..a04603f75e003
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-name-missing-namespace.json
@@ -0,0 +1,26 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "usr": "c:@F at foo",
+ "suffix": ""
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "None"
+ }
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-name-missing-suffix.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-name-missing-suffix.json
new file mode 100644
index 0000000000000..30adfac73018b
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-name-missing-suffix.json
@@ -0,0 +1,31 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "usr": "c:@F at foo",
+ "namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ]
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "External"
+ }
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-name-missing-usr.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-name-missing-usr.json
new file mode 100644
index 0000000000000..2f36b9095cb45
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/entity-name-missing-usr.json
@@ -0,0 +1,35 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "suffix": "",
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ },
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ]
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "None"
+ }
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-element-not-object.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-element-not-object.json
new file mode 100644
index 0000000000000..b7860f1bcc7be
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-element-not-object.json
@@ -0,0 +1,13 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ "invalid"
+ ],
+ "linkage_table": [],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-entry-id-not-uint64.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-entry-id-not-uint64.json
new file mode 100644
index 0000000000000..dec95270705bc
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-entry-id-not-uint64.json
@@ -0,0 +1,29 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "id": "not_a_number",
+ "name": {
+ "usr": "c:@F at foo",
+ "suffix": "",
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ },
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ]
+ }
+ }
+ ],
+ "linkage_table": [],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-entry-missing-id.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-entry-missing-id.json
new file mode 100644
index 0000000000000..4ec9f8d13a921
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-entry-missing-id.json
@@ -0,0 +1,28 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "name": {
+ "usr": "c:@F at foo",
+ "suffix": "",
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ },
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ]
+ }
+ }
+ ],
+ "linkage_table": [],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-entry-missing-name.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-entry-missing-name.json
new file mode 100644
index 0000000000000..4a7ff4a3f8b30
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-entry-missing-name.json
@@ -0,0 +1,15 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "id": 0
+ }
+ ],
+ "linkage_table": [],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-not-array.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-not-array.json
new file mode 100644
index 0000000000000..6d807d558b0ad
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/id-table-not-array.json
@@ -0,0 +1,11 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": {},
+ "linkage_table": [],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/invalid-syntax.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/invalid-syntax.json
new file mode 100644
index 0000000000000..572686df131de
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/invalid-syntax.json
@@ -0,0 +1 @@
+{ invalid json }
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-duplicate-id.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-duplicate-id.json
new file mode 100644
index 0000000000000..a70f7e8ba8207
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-duplicate-id.json
@@ -0,0 +1,42 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "usr": "c:@F at foo",
+ "suffix": "",
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ },
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ]
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "External"
+ }
+ },
+ {
+ "id": 0,
+ "linkage": {
+ "type": "Internal"
+ }
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-element-not-object.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-element-not-object.json
new file mode 100644
index 0000000000000..4a5116d64fe7c
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-element-not-object.json
@@ -0,0 +1,13 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [
+ "invalid"
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-id-not-uint64.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-id-not-uint64.json
new file mode 100644
index 0000000000000..1fa2adc4972bd
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-id-not-uint64.json
@@ -0,0 +1,18 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [
+ {
+ "id": "not_a_number",
+ "linkage": {
+ "type": "External"
+ }
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-linkage-invalid-type.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-linkage-invalid-type.json
new file mode 100644
index 0000000000000..e76368984868e
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-linkage-invalid-type.json
@@ -0,0 +1,18 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "invalid_type"
+ }
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-linkage-missing-type.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-linkage-missing-type.json
new file mode 100644
index 0000000000000..7926d1a869537
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-linkage-missing-type.json
@@ -0,0 +1,16 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {}
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-missing-id.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-missing-id.json
new file mode 100644
index 0000000000000..e56473d19a15b
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-missing-id.json
@@ -0,0 +1,17 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [
+ {
+ "linkage": {
+ "type": "External"
+ }
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-missing-linkage.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-missing-linkage.json
new file mode 100644
index 0000000000000..e0c88f14ce2e0
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-entry-missing-linkage.json
@@ -0,0 +1,15 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [
+ {
+ "id": 0
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-extra-id.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-extra-id.json
new file mode 100644
index 0000000000000..df8800eeaf815
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-extra-id.json
@@ -0,0 +1,18 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "External"
+ }
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-missing-id.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-missing-id.json
new file mode 100644
index 0000000000000..dafc9ada14147
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-missing-id.json
@@ -0,0 +1,29 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "usr": "c:@F at foo",
+ "suffix": "",
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ },
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ]
+ }
+ }
+ ],
+ "linkage_table": [],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-not-array.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-not-array.json
new file mode 100644
index 0000000000000..c693b839d5750
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/linkage-table-not-array.json
@@ -0,0 +1,11 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": {},
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-invalid-kind.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-invalid-kind.json
new file mode 100644
index 0000000000000..b1dd046962892
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-invalid-kind.json
@@ -0,0 +1,11 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "invalid_kind",
+ "name": "test.cpp"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-missing-kind.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-missing-kind.json
new file mode 100644
index 0000000000000..50631a045c0c9
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-missing-kind.json
@@ -0,0 +1,10 @@
+{
+ "lu_namespace": [
+ {
+ "name": "test.cpp"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-missing-name.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-missing-name.json
new file mode 100644
index 0000000000000..855b771ae594d
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-missing-name.json
@@ -0,0 +1,10 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "CompilationUnit"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-not-object.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-not-object.json
new file mode 100644
index 0000000000000..b515fb62ac8c4
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-element-not-object.json
@@ -0,0 +1,8 @@
+{
+ "lu_namespace": [
+ "invalid"
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-not-array.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-not-array.json
new file mode 100644
index 0000000000000..66719784515c2
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/lu-namespace-not-array.json
@@ -0,0 +1,9 @@
+{
+ "lu_namespace": {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ },
+ "id_table": [],
+ "linkage_table": [],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-data.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-data.json
new file mode 100644
index 0000000000000..5bf3fcc3528fb
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-data.json
@@ -0,0 +1,10 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-id-table.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-id-table.json
new file mode 100644
index 0000000000000..ed3e9267849f1
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-id-table.json
@@ -0,0 +1,9 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-linkage-table.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-linkage-table.json
new file mode 100644
index 0000000000000..774b5df9c6163
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-linkage-table.json
@@ -0,0 +1,10 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-lu-namespace.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-lu-namespace.json
new file mode 100644
index 0000000000000..646de61fb1550
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/missing-lu-namespace.json
@@ -0,0 +1,5 @@
+{
+ "id_table": [],
+ "linkage_table": [],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-invalid-kind.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-invalid-kind.json
new file mode 100644
index 0000000000000..5ccec8e79e461
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-invalid-kind.json
@@ -0,0 +1,32 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "usr": "c:@F at foo",
+ "suffix": "",
+ "namespace": [
+ {
+ "kind": "invalid_kind",
+ "name": "test.cpp"
+ }
+ ]
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "External"
+ }
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-missing-kind.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-missing-kind.json
new file mode 100644
index 0000000000000..e5f9c39fc4a10
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-missing-kind.json
@@ -0,0 +1,31 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "usr": "c:@F at foo",
+ "suffix": "",
+ "namespace": [
+ {
+ "name": "test.cpp"
+ }
+ ]
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "Internal"
+ }
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-missing-name.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-missing-name.json
new file mode 100644
index 0000000000000..a80cca7c12626
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-missing-name.json
@@ -0,0 +1,31 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "usr": "c:@F at foo",
+ "suffix": "",
+ "namespace": [
+ {
+ "kind": "CompilationUnit"
+ }
+ ]
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "None"
+ }
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-not-object.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-not-object.json
new file mode 100644
index 0000000000000..9ff091337d04f
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/namespace-element-not-object.json
@@ -0,0 +1,29 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "usr": "c:@F at foo",
+ "suffix": "",
+ "namespace": [
+ "invalid"
+ ]
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "None"
+ }
+ }
+ ],
+ "data": []
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/not-json-extension.txt b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/not-json-extension.txt
new file mode 100644
index 0000000000000..9e26dfeeb6e64
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/not-json-extension.txt
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/not-object.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/not-object.json
new file mode 100644
index 0000000000000..0637a088a01e8
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/not-object.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-element-not-object.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-element-not-object.json
new file mode 100644
index 0000000000000..cccfd58b39470
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-element-not-object.json
@@ -0,0 +1,25 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {
+ "pairs": [
+ "not_an_object"
+ ]
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-invalid-first-field.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-invalid-first-field.json
new file mode 100644
index 0000000000000..5b17d9a2bdb63
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-invalid-first-field.json
@@ -0,0 +1,30 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {
+ "pairs": [
+ {
+ "first": "not_a_number",
+ "second": {
+ "@": 1
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-invalid-pairs-field-type.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-invalid-pairs-field-type.json
new file mode 100644
index 0000000000000..ea02adf5cec9c
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-invalid-pairs-field-type.json
@@ -0,0 +1,23 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {
+ "pairs": "not_an_array"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-invalid-second-field.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-invalid-second-field.json
new file mode 100644
index 0000000000000..fae104bb55c90
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-invalid-second-field.json
@@ -0,0 +1,30 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {
+ "pairs": [
+ {
+ "first": {
+ "@": 0
+ },
+ "second": "not_a_number"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-missing-first-field.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-missing-first-field.json
new file mode 100644
index 0000000000000..ed31f9727cdbf
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-missing-first-field.json
@@ -0,0 +1,29 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {
+ "pairs": [
+ {
+ "second": {
+ "@": 1
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-missing-pairs-field.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-missing-pairs-field.json
new file mode 100644
index 0000000000000..d9c2c1c8246d4
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-missing-pairs-field.json
@@ -0,0 +1,21 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {}
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-missing-second-field.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-missing-second-field.json
new file mode 100644
index 0000000000000..048f2c812ef78
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/pairs-missing-second-field.json
@@ -0,0 +1,29 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "PairsEntitySummary",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {
+ "pairs": [
+ {
+ "first": {
+ "@": 0
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/read-entity-summary-no-format-info.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/read-entity-summary-no-format-info.json
new file mode 100644
index 0000000000000..65fbdeb079b77
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/read-entity-summary-no-format-info.json
@@ -0,0 +1,21 @@
+{
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "UnregisteredEntitySummary",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {}
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-empty-data-entry.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-empty-data-entry.json
new file mode 100644
index 0000000000000..015f265924f2a
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-empty-data-entry.json
@@ -0,0 +1,16 @@
+{
+ "data": [
+ {
+ "summary_data": [],
+ "summary_name": "PairsEntitySummary"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "lu_namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ]
+}
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-empty-namespace.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-empty-namespace.json
new file mode 100644
index 0000000000000..a31f370ee0fad
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-empty-namespace.json
@@ -0,0 +1,11 @@
+{
+ "data": [],
+ "id_table": [],
+ "linkage_table": [],
+ "lu_namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ]
+}
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-external.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-external.json
new file mode 100644
index 0000000000000..7dbfd924c701e
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-external.json
@@ -0,0 +1,32 @@
+{
+ "data": [],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ],
+ "suffix": "",
+ "usr": "c:@F at baz"
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "External"
+ }
+ }
+ ],
+ "lu_namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ]
+}
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-internal.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-internal.json
new file mode 100644
index 0000000000000..638b77e2c1e3f
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-internal.json
@@ -0,0 +1,32 @@
+{
+ "data": [],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ],
+ "suffix": "",
+ "usr": "c:@F at bar"
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "Internal"
+ }
+ }
+ ],
+ "lu_namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ]
+}
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-multiple.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-multiple.json
new file mode 100644
index 0000000000000..51b59f0458923
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-multiple.json
@@ -0,0 +1,70 @@
+{
+ "data": [],
+ "id_table": [
+ {
+ "id": 1,
+ "name": {
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ],
+ "suffix": "",
+ "usr": "c:@F at bar"
+ }
+ },
+ {
+ "id": 2,
+ "name": {
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ],
+ "suffix": "",
+ "usr": "c:@F at baz"
+ }
+ },
+ {
+ "id": 0,
+ "name": {
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ],
+ "suffix": "",
+ "usr": "c:@F at foo"
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "None"
+ }
+ },
+ {
+ "id": 1,
+ "linkage": {
+ "type": "Internal"
+ }
+ },
+ {
+ "id": 2,
+ "linkage": {
+ "type": "External"
+ }
+ }
+ ],
+ "lu_namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ]
+}
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-none.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-none.json
new file mode 100644
index 0000000000000..2d2e9bf20edab
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-linkage-none.json
@@ -0,0 +1,32 @@
+{
+ "data": [],
+ "id_table": [
+ {
+ "id": 0,
+ "name": {
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ],
+ "suffix": "",
+ "usr": "c:@F at foo"
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "None"
+ }
+ }
+ ],
+ "lu_namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ]
+}
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-multiple-namespace-elements.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-multiple-namespace-elements.json
new file mode 100644
index 0000000000000..86b0ad87e4528
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-multiple-namespace-elements.json
@@ -0,0 +1,19 @@
+{
+ "data": [],
+ "id_table": [],
+ "linkage_table": [],
+ "lu_namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "a.cpp"
+ },
+ {
+ "kind": "CompilationUnit",
+ "name": "b.cpp"
+ },
+ {
+ "kind": "LinkUnit",
+ "name": "libtest.so"
+ }
+ ]
+}
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-single-namespace-element.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-single-namespace-element.json
new file mode 100644
index 0000000000000..a31f370ee0fad
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-single-namespace-element.json
@@ -0,0 +1,11 @@
+{
+ "data": [],
+ "id_table": [],
+ "linkage_table": [],
+ "lu_namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ]
+}
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-two-summary-types.json b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-two-summary-types.json
new file mode 100644
index 0000000000000..f83708321f0f8
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/Inputs/rt-two-summary-types.json
@@ -0,0 +1,240 @@
+{
+ "data": [
+ {
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {
+ "pairs": []
+ }
+ },
+ {
+ "entity_id": 1,
+ "entity_summary": {
+ "pairs": [
+ {
+ "first": {
+ "@": 1
+ },
+ "second": {
+ "@": 3
+ }
+ }
+ ]
+ }
+ },
+ {
+ "entity_id": 2,
+ "entity_summary": {
+ "pairs": [
+ {
+ "first": {
+ "@": 2
+ },
+ "second": {
+ "@": 4
+ }
+ },
+ {
+ "first": {
+ "@": 2
+ },
+ "second": {
+ "@": 3
+ }
+ }
+ ]
+ }
+ },
+ {
+ "entity_id": 3,
+ "entity_summary": {
+ "pairs": [
+ {
+ "first": {
+ "@": 3
+ },
+ "second": {
+ "@": 1
+ }
+ }
+ ]
+ }
+ },
+ {
+ "entity_id": 4,
+ "entity_summary": {
+ "pairs": [
+ {
+ "first": {
+ "@": 4
+ },
+ "second": {
+ "@": 0
+ }
+ },
+ {
+ "first": {
+ "@": 4
+ },
+ "second": {
+ "@": 2
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "summary_name": "PairsEntitySummary"
+ },
+ {
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {
+ "tags": [
+ "entry-point"
+ ]
+ }
+ },
+ {
+ "entity_id": 1,
+ "entity_summary": {
+ "tags": [
+ "internal-only"
+ ]
+ }
+ },
+ {
+ "entity_id": 2,
+ "entity_summary": {
+ "tags": []
+ }
+ },
+ {
+ "entity_id": 3,
+ "entity_summary": {
+ "tags": [
+ "internal-only"
+ ]
+ }
+ },
+ {
+ "entity_id": 4,
+ "entity_summary": {
+ "tags": [
+ "exported",
+ "hot"
+ ]
+ }
+ }
+ ],
+ "summary_name": "TagsEntitySummary"
+ }
+ ],
+ "id_table": [
+ {
+ "id": 1,
+ "name": {
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ],
+ "suffix": "",
+ "usr": "c:@F at bar"
+ }
+ },
+ {
+ "id": 2,
+ "name": {
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ],
+ "suffix": "",
+ "usr": "c:@F at baz"
+ }
+ },
+ {
+ "id": 0,
+ "name": {
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ],
+ "suffix": "",
+ "usr": "c:@F at foo"
+ }
+ },
+ {
+ "id": 4,
+ "name": {
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ],
+ "suffix": "",
+ "usr": "c:@F at quux"
+ }
+ },
+ {
+ "id": 3,
+ "name": {
+ "namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ],
+ "suffix": "",
+ "usr": "c:@F at qux"
+ }
+ }
+ ],
+ "linkage_table": [
+ {
+ "id": 0,
+ "linkage": {
+ "type": "None"
+ }
+ },
+ {
+ "id": 1,
+ "linkage": {
+ "type": "None"
+ }
+ },
+ {
+ "id": 2,
+ "linkage": {
+ "type": "Internal"
+ }
+ },
+ {
+ "id": 3,
+ "linkage": {
+ "type": "Internal"
+ }
+ },
+ {
+ "id": 4,
+ "linkage": {
+ "type": "External"
+ }
+ }
+ ],
+ "lu_namespace": [
+ {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ }
+ ]
+}
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/id-table.test b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/id-table.test
new file mode 100644
index 0000000000000..733cd61d844a2
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/id-table.test
@@ -0,0 +1,148 @@
+// IdTable deserialization error tests: EntityName.namespace, EntityName,
+// EntityIdTable entry, and EntityIdTable structural / consistency errors.
+
+// REQUIRES: plugins
+
+// ============================================================================
+// nestedBuildNamespaceFromJSON() errors (EntityName namespace)
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/namespace-element-not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=NAMESPACE-ELEMENT-NOT-OBJECT
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/namespace-element-not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=NAMESPACE-ELEMENT-NOT-OBJECT
+// NAMESPACE-ELEMENT-NOT-OBJECT: clang-ssaf-format: error: reading LUSummary from file '{{.*}}namespace-element-not-object.json'
+// NAMESPACE-ELEMENT-NOT-OBJECT-NEXT: reading IdTable from field 'id_table'
+// NAMESPACE-ELEMENT-NOT-OBJECT-NEXT: reading EntityIdTable entry from index '0'
+// NAMESPACE-ELEMENT-NOT-OBJECT-NEXT: reading EntityName from field 'name'
+// NAMESPACE-ELEMENT-NOT-OBJECT-NEXT: reading NestedBuildNamespace from field 'namespace'
+// NAMESPACE-ELEMENT-NOT-OBJECT-NEXT: failed to read BuildNamespace from index '0': expected JSON object
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/namespace-element-missing-kind.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=NAMESPACE-ELEMENT-MISSING-KIND
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/namespace-element-missing-kind.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=NAMESPACE-ELEMENT-MISSING-KIND
+// NAMESPACE-ELEMENT-MISSING-KIND: clang-ssaf-format: error: reading LUSummary from file '{{.*}}namespace-element-missing-kind.json'
+// NAMESPACE-ELEMENT-MISSING-KIND-NEXT: reading IdTable from field 'id_table'
+// NAMESPACE-ELEMENT-MISSING-KIND-NEXT: reading EntityIdTable entry from index '0'
+// NAMESPACE-ELEMENT-MISSING-KIND-NEXT: reading EntityName from field 'name'
+// NAMESPACE-ELEMENT-MISSING-KIND-NEXT: reading NestedBuildNamespace from field 'namespace'
+// NAMESPACE-ELEMENT-MISSING-KIND-NEXT: reading BuildNamespace from index '0'
+// NAMESPACE-ELEMENT-MISSING-KIND-NEXT: failed to read BuildNamespaceKind from field 'kind': expected JSON string
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/namespace-element-invalid-kind.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=NAMESPACE-ELEMENT-INVALID-KIND
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/namespace-element-invalid-kind.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=NAMESPACE-ELEMENT-INVALID-KIND
+// NAMESPACE-ELEMENT-INVALID-KIND: clang-ssaf-format: error: reading LUSummary from file '{{.*}}namespace-element-invalid-kind.json'
+// NAMESPACE-ELEMENT-INVALID-KIND-NEXT: reading IdTable from field 'id_table'
+// NAMESPACE-ELEMENT-INVALID-KIND-NEXT: reading EntityIdTable entry from index '0'
+// NAMESPACE-ELEMENT-INVALID-KIND-NEXT: reading EntityName from field 'name'
+// NAMESPACE-ELEMENT-INVALID-KIND-NEXT: reading NestedBuildNamespace from field 'namespace'
+// NAMESPACE-ELEMENT-INVALID-KIND-NEXT: reading BuildNamespace from index '0'
+// NAMESPACE-ELEMENT-INVALID-KIND-NEXT: reading BuildNamespaceKind from field 'kind'
+// NAMESPACE-ELEMENT-INVALID-KIND-NEXT: invalid BuildNamespaceKind value 'invalid_kind' for field 'kind'
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/namespace-element-missing-name.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=NAMESPACE-ELEMENT-MISSING-NAME
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/namespace-element-missing-name.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=NAMESPACE-ELEMENT-MISSING-NAME
+// NAMESPACE-ELEMENT-MISSING-NAME: clang-ssaf-format: error: reading LUSummary from file '{{.*}}namespace-element-missing-name.json'
+// NAMESPACE-ELEMENT-MISSING-NAME-NEXT: reading IdTable from field 'id_table'
+// NAMESPACE-ELEMENT-MISSING-NAME-NEXT: reading EntityIdTable entry from index '0'
+// NAMESPACE-ELEMENT-MISSING-NAME-NEXT: reading EntityName from field 'name'
+// NAMESPACE-ELEMENT-MISSING-NAME-NEXT: reading NestedBuildNamespace from field 'namespace'
+// NAMESPACE-ELEMENT-MISSING-NAME-NEXT: reading BuildNamespace from index '0'
+// NAMESPACE-ELEMENT-MISSING-NAME-NEXT: failed to read BuildNamespaceName from field 'name': expected JSON string
+
+// ============================================================================
+// luEntityNameFromJSON() errors
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/entity-name-missing-usr.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-NAME-MISSING-USR
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/entity-name-missing-usr.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-NAME-MISSING-USR
+// ENTITY-NAME-MISSING-USR: clang-ssaf-format: error: reading LUSummary from file '{{.*}}entity-name-missing-usr.json'
+// ENTITY-NAME-MISSING-USR-NEXT: reading IdTable from field 'id_table'
+// ENTITY-NAME-MISSING-USR-NEXT: reading EntityIdTable entry from index '0'
+// ENTITY-NAME-MISSING-USR-NEXT: reading EntityName from field 'name'
+// ENTITY-NAME-MISSING-USR-NEXT: failed to read USR from field 'usr': expected JSON string
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/entity-name-missing-suffix.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-NAME-MISSING-SUFFIX
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/entity-name-missing-suffix.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-NAME-MISSING-SUFFIX
+// ENTITY-NAME-MISSING-SUFFIX: clang-ssaf-format: error: reading LUSummary from file '{{.*}}entity-name-missing-suffix.json'
+// ENTITY-NAME-MISSING-SUFFIX-NEXT: reading IdTable from field 'id_table'
+// ENTITY-NAME-MISSING-SUFFIX-NEXT: reading EntityIdTable entry from index '0'
+// ENTITY-NAME-MISSING-SUFFIX-NEXT: reading EntityName from field 'name'
+// ENTITY-NAME-MISSING-SUFFIX-NEXT: failed to read Suffix from field 'suffix': expected JSON string
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/entity-name-missing-namespace.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-NAME-MISSING-NAMESPACE
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/entity-name-missing-namespace.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-NAME-MISSING-NAMESPACE
+// ENTITY-NAME-MISSING-NAMESPACE: clang-ssaf-format: error: reading LUSummary from file '{{.*}}entity-name-missing-namespace.json'
+// ENTITY-NAME-MISSING-NAMESPACE-NEXT: reading IdTable from field 'id_table'
+// ENTITY-NAME-MISSING-NAMESPACE-NEXT: reading EntityIdTable entry from index '0'
+// ENTITY-NAME-MISSING-NAMESPACE-NEXT: reading EntityName from field 'name'
+// ENTITY-NAME-MISSING-NAMESPACE-NEXT: failed to read NestedBuildNamespace from field 'namespace': expected JSON array
+
+// ============================================================================
+// luEntityIdTableEntryFromJSON() errors
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/id-table-entry-missing-id.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ID-TABLE-ENTRY-MISSING-ID
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/id-table-entry-missing-id.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ID-TABLE-ENTRY-MISSING-ID
+// ID-TABLE-ENTRY-MISSING-ID: clang-ssaf-format: error: reading LUSummary from file '{{.*}}id-table-entry-missing-id.json'
+// ID-TABLE-ENTRY-MISSING-ID-NEXT: reading IdTable from field 'id_table'
+// ID-TABLE-ENTRY-MISSING-ID-NEXT: reading EntityIdTable entry from index '0'
+// ID-TABLE-ENTRY-MISSING-ID-NEXT: failed to read EntityId from field 'id': expected JSON number (unsigned 64-bit integer)
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/id-table-entry-missing-name.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ID-TABLE-ENTRY-MISSING-NAME
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/id-table-entry-missing-name.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ID-TABLE-ENTRY-MISSING-NAME
+// ID-TABLE-ENTRY-MISSING-NAME: clang-ssaf-format: error: reading LUSummary from file '{{.*}}id-table-entry-missing-name.json'
+// ID-TABLE-ENTRY-MISSING-NAME-NEXT: reading IdTable from field 'id_table'
+// ID-TABLE-ENTRY-MISSING-NAME-NEXT: reading EntityIdTable entry from index '0'
+// ID-TABLE-ENTRY-MISSING-NAME-NEXT: failed to read EntityName from field 'name': expected JSON object
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/id-table-entry-id-not-uint64.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ID-TABLE-ENTRY-ID-NOT-UINT64
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/id-table-entry-id-not-uint64.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ID-TABLE-ENTRY-ID-NOT-UINT64
+// ID-TABLE-ENTRY-ID-NOT-UINT64: clang-ssaf-format: error: reading LUSummary from file '{{.*}}id-table-entry-id-not-uint64.json'
+// ID-TABLE-ENTRY-ID-NOT-UINT64-NEXT: reading IdTable from field 'id_table'
+// ID-TABLE-ENTRY-ID-NOT-UINT64-NEXT: reading EntityIdTable entry from index '0'
+// ID-TABLE-ENTRY-ID-NOT-UINT64-NEXT: failed to read EntityId from field 'id': expected JSON number (unsigned 64-bit integer)
+
+// ============================================================================
+// luEntityIdTableFromJSON() errors
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/id-table-not-array.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ID-TABLE-NOT-ARRAY
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/id-table-not-array.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ID-TABLE-NOT-ARRAY
+// ID-TABLE-NOT-ARRAY: clang-ssaf-format: error: reading LUSummary from file '{{.*}}id-table-not-array.json'
+// ID-TABLE-NOT-ARRAY-NEXT: failed to read IdTable from field 'id_table': expected JSON array
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/id-table-element-not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ID-TABLE-ELEMENT-NOT-OBJECT
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/id-table-element-not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ID-TABLE-ELEMENT-NOT-OBJECT
+// ID-TABLE-ELEMENT-NOT-OBJECT: clang-ssaf-format: error: reading LUSummary from file '{{.*}}id-table-element-not-object.json'
+// ID-TABLE-ELEMENT-NOT-OBJECT-NEXT: reading IdTable from field 'id_table'
+// ID-TABLE-ELEMENT-NOT-OBJECT-NEXT: failed to read EntityIdTable entry from index '0': expected JSON object
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/duplicate-entity.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=DUPLICATE-ENTITY
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/duplicate-entity.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=DUPLICATE-ENTITY
+// DUPLICATE-ENTITY: clang-ssaf-format: error: reading LUSummary from file '{{.*}}duplicate-entity.json'
+// DUPLICATE-ENTITY-NEXT: reading IdTable from field 'id_table'
+// DUPLICATE-ENTITY-NEXT: failed to insert EntityIdTable entry at index '1': encountered duplicate 'EntityId(0)'
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/io.test b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/io.test
new file mode 100644
index 0000000000000..bfce3a17a446d
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/io.test
@@ -0,0 +1,49 @@
+// File-I/O error tests: readJSON() input validation and writeJSON() output
+// validation for clang-ssaf-format --type lu.
+
+// REQUIRES: plugins
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+
+// ============================================================================
+// readJSON() errors
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/invalid-syntax.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=INVALID-SYNTAX
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/invalid-syntax.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=INVALID-SYNTAX
+// INVALID-SYNTAX: clang-ssaf-format: error: reading LUSummary from file '{{.*}}invalid-syntax.json'
+// INVALID-SYNTAX-NEXT: {{.*}}Expected object key
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=NOT-OBJECT
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=NOT-OBJECT
+// NOT-OBJECT: clang-ssaf-format: error: reading LUSummary from file '{{.*}}not-object.json'
+// NOT-OBJECT-NEXT: failed to read LUSummary: expected JSON object
+
+// ============================================================================
+// writeJSON() errors
+// ============================================================================
+
+// RUN: echo '{}' > %t/existing.json
+// RUN: not clang-ssaf-format --type lu %S/Inputs/rt-empty-namespace.json -o %t/existing.json 2>&1 \
+// RUN: | FileCheck %s --check-prefix=WRITE-FILE-ALREADY-EXISTS
+// RUN: echo '{}' > %t/existing-enc.json
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/rt-empty-namespace.json -o %t/existing-enc.json 2>&1 \
+// RUN: | FileCheck %s --check-prefix=WRITE-FILE-ALREADY-EXISTS
+// WRITE-FILE-ALREADY-EXISTS: clang-ssaf-format: error: failed to validate path '{{.*}}existing{{.*}}.json': File already exists
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/rt-empty-namespace.json -o %t/nonexistent-dir/test.json 2>&1 \
+// RUN: | FileCheck %s --check-prefix=WRITE-PARENT-DIR-NOT-FOUND
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/rt-empty-namespace.json -o %t/nonexistent-dir/test.json 2>&1 \
+// RUN: | FileCheck %s --check-prefix=WRITE-PARENT-DIR-NOT-FOUND
+// WRITE-PARENT-DIR-NOT-FOUND: clang-ssaf-format: error: failed to validate path '{{.*}}nonexistent-dir{{.*}}test.json': Parent directory does not exist
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/rt-empty-namespace.json -o %t/test.txt 2>&1 \
+// RUN: | FileCheck %s --check-prefix=WRITE-NOT-JSON-EXTENSION
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/rt-empty-namespace.json -o %t/test.txt 2>&1 \
+// RUN: | FileCheck %s --check-prefix=WRITE-NOT-JSON-EXTENSION
+// WRITE-NOT-JSON-EXTENSION: clang-ssaf-format: error: failed to validate path '{{.*}}test.txt': No format registered for extension 'txt'
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/linkage.test b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/linkage.test
new file mode 100644
index 0000000000000..192219cadbc12
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/linkage.test
@@ -0,0 +1,104 @@
+// LinkageTable deserialization error tests: EntityLinkage, LinkageTable entry,
+// and LinkageTable structural / consistency errors.
+
+// REQUIRES: plugins
+
+// ============================================================================
+// entityLinkageFromJSON() errors
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/linkage-table-entry-linkage-missing-type.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-MISSING-TYPE
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/linkage-table-entry-linkage-missing-type.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-MISSING-TYPE
+// LINKAGE-MISSING-TYPE: clang-ssaf-format: error: reading LUSummary from file '{{.*}}linkage-table-entry-linkage-missing-type.json'
+// LINKAGE-MISSING-TYPE-NEXT: reading LinkageTable from field 'linkage_table'
+// LINKAGE-MISSING-TYPE-NEXT: reading LinkageTable entry from index '0'
+// LINKAGE-MISSING-TYPE-NEXT: reading EntityLinkage from field 'linkage'
+// LINKAGE-MISSING-TYPE-NEXT: failed to read EntityLinkageType from field 'type': expected JSON string
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/linkage-table-entry-linkage-invalid-type.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-INVALID-TYPE
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/linkage-table-entry-linkage-invalid-type.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-INVALID-TYPE
+// LINKAGE-INVALID-TYPE: clang-ssaf-format: error: reading LUSummary from file '{{.*}}linkage-table-entry-linkage-invalid-type.json'
+// LINKAGE-INVALID-TYPE-NEXT: reading LinkageTable from field 'linkage_table'
+// LINKAGE-INVALID-TYPE-NEXT: reading LinkageTable entry from index '0'
+// LINKAGE-INVALID-TYPE-NEXT: reading EntityLinkage from field 'linkage'
+// LINKAGE-INVALID-TYPE-NEXT: reading EntityLinkageType from field 'type'
+// LINKAGE-INVALID-TYPE-NEXT: invalid EntityLinkageType value 'invalid_type' for field 'type'
+
+// ============================================================================
+// linkageTableEntryFromJSON() errors
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/linkage-table-entry-missing-id.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-ENTRY-MISSING-ID
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/linkage-table-entry-missing-id.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-ENTRY-MISSING-ID
+// LINKAGE-ENTRY-MISSING-ID: clang-ssaf-format: error: reading LUSummary from file '{{.*}}linkage-table-entry-missing-id.json'
+// LINKAGE-ENTRY-MISSING-ID-NEXT: reading LinkageTable from field 'linkage_table'
+// LINKAGE-ENTRY-MISSING-ID-NEXT: reading LinkageTable entry from index '0'
+// LINKAGE-ENTRY-MISSING-ID-NEXT: failed to read EntityId from field 'id': expected JSON number (unsigned 64-bit integer)
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/linkage-table-entry-id-not-uint64.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-ENTRY-ID-NOT-UINT64
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/linkage-table-entry-id-not-uint64.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-ENTRY-ID-NOT-UINT64
+// LINKAGE-ENTRY-ID-NOT-UINT64: clang-ssaf-format: error: reading LUSummary from file '{{.*}}linkage-table-entry-id-not-uint64.json'
+// LINKAGE-ENTRY-ID-NOT-UINT64-NEXT: reading LinkageTable from field 'linkage_table'
+// LINKAGE-ENTRY-ID-NOT-UINT64-NEXT: reading LinkageTable entry from index '0'
+// LINKAGE-ENTRY-ID-NOT-UINT64-NEXT: failed to read EntityId from field 'id': expected JSON number (unsigned 64-bit integer)
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/linkage-table-entry-missing-linkage.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-ENTRY-MISSING-LINKAGE
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/linkage-table-entry-missing-linkage.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-ENTRY-MISSING-LINKAGE
+// LINKAGE-ENTRY-MISSING-LINKAGE: clang-ssaf-format: error: reading LUSummary from file '{{.*}}linkage-table-entry-missing-linkage.json'
+// LINKAGE-ENTRY-MISSING-LINKAGE-NEXT: reading LinkageTable from field 'linkage_table'
+// LINKAGE-ENTRY-MISSING-LINKAGE-NEXT: reading LinkageTable entry from index '0'
+// LINKAGE-ENTRY-MISSING-LINKAGE-NEXT: failed to read EntityLinkage from field 'linkage': expected JSON object
+
+// ============================================================================
+// linkageTableFromJSON() errors
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/linkage-table-not-array.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-TABLE-NOT-ARRAY
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/linkage-table-not-array.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-TABLE-NOT-ARRAY
+// LINKAGE-TABLE-NOT-ARRAY: clang-ssaf-format: error: reading LUSummary from file '{{.*}}linkage-table-not-array.json'
+// LINKAGE-TABLE-NOT-ARRAY-NEXT: failed to read LinkageTable from field 'linkage_table': expected JSON array
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/linkage-table-element-not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-TABLE-ELEMENT-NOT-OBJECT
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/linkage-table-element-not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-TABLE-ELEMENT-NOT-OBJECT
+// LINKAGE-TABLE-ELEMENT-NOT-OBJECT: clang-ssaf-format: error: reading LUSummary from file '{{.*}}linkage-table-element-not-object.json'
+// LINKAGE-TABLE-ELEMENT-NOT-OBJECT-NEXT: reading LinkageTable from field 'linkage_table'
+// LINKAGE-TABLE-ELEMENT-NOT-OBJECT-NEXT: failed to read LinkageTable entry from index '0': expected JSON object
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/linkage-table-extra-id.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-TABLE-EXTRA-ID
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/linkage-table-extra-id.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-TABLE-EXTRA-ID
+// LINKAGE-TABLE-EXTRA-ID: clang-ssaf-format: error: reading LUSummary from file '{{.*}}linkage-table-extra-id.json'
+// LINKAGE-TABLE-EXTRA-ID-NEXT: reading LinkageTable from field 'linkage_table'
+// LINKAGE-TABLE-EXTRA-ID-NEXT: reading LinkageTable entry from index '0'
+// LINKAGE-TABLE-EXTRA-ID-NEXT: failed to deserialize LinkageTable: extra 'EntityId(0)' not present in IdTable
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/linkage-table-missing-id.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-TABLE-MISSING-ID
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/linkage-table-missing-id.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-TABLE-MISSING-ID
+// LINKAGE-TABLE-MISSING-ID: clang-ssaf-format: error: reading LUSummary from file '{{.*}}linkage-table-missing-id.json'
+// LINKAGE-TABLE-MISSING-ID-NEXT: reading LinkageTable from field 'linkage_table'
+// LINKAGE-TABLE-MISSING-ID-NEXT: failed to deserialize LinkageTable: missing 'EntityId(0)' present in IdTable
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/linkage-table-duplicate-id.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-TABLE-DUPLICATE-ID
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/linkage-table-duplicate-id.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LINKAGE-TABLE-DUPLICATE-ID
+// LINKAGE-TABLE-DUPLICATE-ID: clang-ssaf-format: error: reading LUSummary from file '{{.*}}linkage-table-duplicate-id.json'
+// LINKAGE-TABLE-DUPLICATE-ID-NEXT: reading LinkageTable from field 'linkage_table'
+// LINKAGE-TABLE-DUPLICATE-ID-NEXT: failed to insert LinkageTable entry at index '1': encountered duplicate 'EntityId(0)'
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/permissions.test b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/permissions.test
new file mode 100644
index 0000000000000..0d2db01a471db
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/permissions.test
@@ -0,0 +1,40 @@
+// Tests for clang-ssaf-format --type lu that require filesystem permission
+// support (symlinks, chmod).
+
+// UNSUPPORTED: system-windows
+// REQUIRES: non-root-user
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+
+// ============================================================================
+// Broken symlink
+// ============================================================================
+
+// RUN: ln -sf %t/nonexistent-target.json %t/broken-symlink.json
+// RUN: not clang-ssaf-format --type lu %t/broken-symlink.json 2>&1 \
+// RUN: | FileCheck %s --check-prefix=BROKEN-SYMLINK
+// BROKEN-SYMLINK: clang-ssaf-format: error: failed to validate path '{{.*}}broken-symlink.json': Path does not exist
+
+// ============================================================================
+// No read permission
+// ============================================================================
+
+// RUN: echo '{"lu_namespace": [{"kind": "LinkUnit", "name": "test.exe"}], "id_table": [], "linkage_table": [], "data": []}' > %t/no-read-permission.json
+// RUN: chmod -r %t/no-read-permission.json
+// RUN: not clang-ssaf-format --type lu %t/no-read-permission.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=NO-READ-PERMISSION
+// RUN: chmod +r %t/no-read-permission.json
+// NO-READ-PERMISSION: clang-ssaf-format: error: reading LUSummary from file '{{.*}}no-read-permission.json'
+// NO-READ-PERMISSION-NEXT: failed to read file '{{.*}}no-read-permission.json': {{.*}}
+
+// ============================================================================
+// Write to directory without write permission
+// ============================================================================
+
+// RUN: mkdir -p %t/write-protected-dir
+// RUN: chmod -w %t/write-protected-dir
+// RUN: not clang-ssaf-format --type lu %S/Inputs/rt-empty-namespace.json -o %t/write-protected-dir/test.json 2>&1 \
+// RUN: | FileCheck %s --check-prefix=WRITE-STREAM-OPEN-FAILURE
+// RUN: chmod +w %t/write-protected-dir
+// WRITE-STREAM-OPEN-FAILURE: clang-ssaf-format: error: failed to validate path '{{.*}}write-protected-dir{{.}}test.json': Parent directory is not writable
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/round-trip.test b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/round-trip.test
new file mode 100644
index 0000000000000..6761ec436fd7f
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/round-trip.test
@@ -0,0 +1,56 @@
+// Round-trip tests: read an LUSummary JSON input, write it back out, and
+//
diff the result against the original.
+
+// REQUIRES: plugins
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+
+// ============================================================================
+// Round-Trip Tests
+// ============================================================================
+
+// RUN: clang-ssaf-format --type lu %S/Inputs/rt-empty-namespace.json -o %t/rt-empty-namespace.json
+// RUN:
diff %S/Inputs/rt-empty-namespace.json %t/rt-empty-namespace.json
+// RUN: clang-ssaf-format --type lu --encoding %S/Inputs/rt-empty-namespace.json -o %t/rt-empty-namespace-enc.json
+// RUN:
diff %S/Inputs/rt-empty-namespace.json %t/rt-empty-namespace-enc.json
+
+// RUN: clang-ssaf-format --type lu %S/Inputs/rt-single-namespace-element.json -o %t/rt-single-namespace-element.json
+// RUN:
diff %S/Inputs/rt-single-namespace-element.json %t/rt-single-namespace-element.json
+// RUN: clang-ssaf-format --type lu --encoding %S/Inputs/rt-single-namespace-element.json -o %t/rt-single-namespace-element-enc.json
+// RUN:
diff %S/Inputs/rt-single-namespace-element.json %t/rt-single-namespace-element-enc.json
+
+// RUN: clang-ssaf-format --type lu %S/Inputs/rt-multiple-namespace-elements.json -o %t/rt-multiple-namespace-elements.json
+// RUN:
diff %S/Inputs/rt-multiple-namespace-elements.json %t/rt-multiple-namespace-elements.json
+// RUN: clang-ssaf-format --type lu --encoding %S/Inputs/rt-multiple-namespace-elements.json -o %t/rt-multiple-namespace-elements-enc.json
+// RUN:
diff %S/Inputs/rt-multiple-namespace-elements.json %t/rt-multiple-namespace-elements-enc.json
+
+// RUN: %clang-ssaf-format-with-plugin --type lu %S/Inputs/rt-two-summary-types.json -o %t/rt-two-summary-types.json
+// RUN:
diff %S/Inputs/rt-two-summary-types.json %t/rt-two-summary-types.json
+// RUN: %clang-ssaf-format-with-plugin --type lu --encoding %S/Inputs/rt-two-summary-types.json -o %t/rt-two-summary-types-enc.json
+// RUN:
diff %S/Inputs/rt-two-summary-types.json %t/rt-two-summary-types-enc.json
+
+// RUN: %clang-ssaf-format-with-plugin --type lu %S/Inputs/rt-empty-data-entry.json -o %t/rt-empty-data-entry.json
+// RUN:
diff %S/Inputs/rt-empty-data-entry.json %t/rt-empty-data-entry.json
+// RUN: %clang-ssaf-format-with-plugin --type lu --encoding %S/Inputs/rt-empty-data-entry.json -o %t/rt-empty-data-entry-enc.json
+// RUN:
diff %S/Inputs/rt-empty-data-entry.json %t/rt-empty-data-entry-enc.json
+
+// RUN: clang-ssaf-format --type lu %S/Inputs/rt-linkage-none.json -o %t/rt-linkage-none.json
+// RUN:
diff %S/Inputs/rt-linkage-none.json %t/rt-linkage-none.json
+// RUN: clang-ssaf-format --type lu --encoding %S/Inputs/rt-linkage-none.json -o %t/rt-linkage-none-enc.json
+// RUN:
diff %S/Inputs/rt-linkage-none.json %t/rt-linkage-none-enc.json
+
+// RUN: clang-ssaf-format --type lu %S/Inputs/rt-linkage-internal.json -o %t/rt-linkage-internal.json
+// RUN:
diff %S/Inputs/rt-linkage-internal.json %t/rt-linkage-internal.json
+// RUN: clang-ssaf-format --type lu --encoding %S/Inputs/rt-linkage-internal.json -o %t/rt-linkage-internal-enc.json
+// RUN:
diff %S/Inputs/rt-linkage-internal.json %t/rt-linkage-internal-enc.json
+
+// RUN: clang-ssaf-format --type lu %S/Inputs/rt-linkage-external.json -o %t/rt-linkage-external.json
+// RUN:
diff %S/Inputs/rt-linkage-external.json %t/rt-linkage-external.json
+// RUN: clang-ssaf-format --type lu --encoding %S/Inputs/rt-linkage-external.json -o %t/rt-linkage-external-enc.json
+// RUN:
diff %S/Inputs/rt-linkage-external.json %t/rt-linkage-external-enc.json
+
+// RUN: clang-ssaf-format --type lu %S/Inputs/rt-linkage-multiple.json -o %t/rt-linkage-multiple.json
+// RUN:
diff %S/Inputs/rt-linkage-multiple.json %t/rt-linkage-multiple.json
+// RUN: clang-ssaf-format --type lu --encoding %S/Inputs/rt-linkage-multiple.json -o %t/rt-linkage-multiple-enc.json
+// RUN:
diff %S/Inputs/rt-linkage-multiple.json %t/rt-linkage-multiple-enc.json
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/summary-data.test b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/summary-data.test
new file mode 100644
index 0000000000000..dcf6a31f5c504
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/summary-data.test
@@ -0,0 +1,202 @@
+// SummaryData / EntityDataMap deserialization error tests, including the
+// PairsEntitySummary plugin error tests that exercise the same parsing path.
+
+// REQUIRES: plugins
+
+// ============================================================================
+// readLUSummary() errors
+// ============================================================================
+
+// Note: --encoding variants are not applicable for EntitySummary deserialization
+// tests because the encoding path stores raw JSON without deserializing.
+// RUN: not clang-ssaf-format --type lu %S/Inputs/read-entity-summary-no-format-info.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=READ-ENTITY-SUMMARY-NO-FORMAT-INFO
+// READ-ENTITY-SUMMARY-NO-FORMAT-INFO: clang-ssaf-format: error: reading LUSummary from file '{{.*}}read-entity-summary-no-format-info.json'
+// READ-ENTITY-SUMMARY-NO-FORMAT-INFO-NEXT: reading SummaryData entries from field 'data'
+// READ-ENTITY-SUMMARY-NO-FORMAT-INFO-NEXT: reading SummaryData entry from index '0'
+// READ-ENTITY-SUMMARY-NO-FORMAT-INFO-NEXT: reading EntitySummary entries from field 'summary_data'
+// READ-ENTITY-SUMMARY-NO-FORMAT-INFO-NEXT: reading EntitySummary entry from index '0'
+// READ-ENTITY-SUMMARY-NO-FORMAT-INFO-NEXT: reading EntitySummary from field 'entity_summary'
+// READ-ENTITY-SUMMARY-NO-FORMAT-INFO-NEXT: failed to deserialize EntitySummary: no FormatInfo registered for 'SummaryName(UnregisteredEntitySummary)'
+
+// ============================================================================
+// PairsEntitySummaryForJSONFormatTest tests
+// ============================================================================
+
+// RUN: not %clang-ssaf-format-with-plugin --type lu %S/Inputs/pairs-missing-pairs-field.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=PAIRS-MISSING-PAIRS-FIELD
+// PAIRS-MISSING-PAIRS-FIELD: clang-ssaf-format: error: reading LUSummary from file '{{.*}}pairs-missing-pairs-field.json'
+// PAIRS-MISSING-PAIRS-FIELD-NEXT: reading SummaryData entries from field 'data'
+// PAIRS-MISSING-PAIRS-FIELD-NEXT: reading SummaryData entry from index '0'
+// PAIRS-MISSING-PAIRS-FIELD-NEXT: reading EntitySummary entries from field 'summary_data'
+// PAIRS-MISSING-PAIRS-FIELD-NEXT: reading EntitySummary entry from index '0'
+// PAIRS-MISSING-PAIRS-FIELD-NEXT: reading EntitySummary from field 'entity_summary'
+// PAIRS-MISSING-PAIRS-FIELD-NEXT: missing or invalid field 'pairs'
+
+// RUN: not %clang-ssaf-format-with-plugin --type lu %S/Inputs/pairs-invalid-pairs-field-type.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=PAIRS-INVALID-PAIRS-FIELD-TYPE
+// PAIRS-INVALID-PAIRS-FIELD-TYPE: clang-ssaf-format: error: reading LUSummary from file '{{.*}}pairs-invalid-pairs-field-type.json'
+// PAIRS-INVALID-PAIRS-FIELD-TYPE-NEXT: reading SummaryData entries from field 'data'
+// PAIRS-INVALID-PAIRS-FIELD-TYPE-NEXT: reading SummaryData entry from index '0'
+// PAIRS-INVALID-PAIRS-FIELD-TYPE-NEXT: reading EntitySummary entries from field 'summary_data'
+// PAIRS-INVALID-PAIRS-FIELD-TYPE-NEXT: reading EntitySummary entry from index '0'
+// PAIRS-INVALID-PAIRS-FIELD-TYPE-NEXT: reading EntitySummary from field 'entity_summary'
+// PAIRS-INVALID-PAIRS-FIELD-TYPE-NEXT: missing or invalid field 'pairs'
+
+// RUN: not %clang-ssaf-format-with-plugin --type lu %S/Inputs/pairs-element-not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=PAIRS-ELEMENT-NOT-OBJECT
+// PAIRS-ELEMENT-NOT-OBJECT: clang-ssaf-format: error: reading LUSummary from file '{{.*}}pairs-element-not-object.json'
+// PAIRS-ELEMENT-NOT-OBJECT-NEXT: reading SummaryData entries from field 'data'
+// PAIRS-ELEMENT-NOT-OBJECT-NEXT: reading SummaryData entry from index '0'
+// PAIRS-ELEMENT-NOT-OBJECT-NEXT: reading EntitySummary entries from field 'summary_data'
+// PAIRS-ELEMENT-NOT-OBJECT-NEXT: reading EntitySummary entry from index '0'
+// PAIRS-ELEMENT-NOT-OBJECT-NEXT: reading EntitySummary from field 'entity_summary'
+// PAIRS-ELEMENT-NOT-OBJECT-NEXT: pairs element at index 0 is not a JSON object
+
+// RUN: not %clang-ssaf-format-with-plugin --type lu %S/Inputs/pairs-missing-first-field.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=PAIRS-MISSING-FIRST-FIELD
+// PAIRS-MISSING-FIRST-FIELD: clang-ssaf-format: error: reading LUSummary from file '{{.*}}pairs-missing-first-field.json'
+// PAIRS-MISSING-FIRST-FIELD-NEXT: reading SummaryData entries from field 'data'
+// PAIRS-MISSING-FIRST-FIELD-NEXT: reading SummaryData entry from index '0'
+// PAIRS-MISSING-FIRST-FIELD-NEXT: reading EntitySummary entries from field 'summary_data'
+// PAIRS-MISSING-FIRST-FIELD-NEXT: reading EntitySummary entry from index '0'
+// PAIRS-MISSING-FIRST-FIELD-NEXT: reading EntitySummary from field 'entity_summary'
+// PAIRS-MISSING-FIRST-FIELD-NEXT: missing or invalid 'first' field at index '0'
+
+// RUN: not %clang-ssaf-format-with-plugin --type lu %S/Inputs/pairs-invalid-first-field.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=PAIRS-INVALID-FIRST-FIELD
+// PAIRS-INVALID-FIRST-FIELD: clang-ssaf-format: error: reading LUSummary from file '{{.*}}pairs-invalid-first-field.json'
+// PAIRS-INVALID-FIRST-FIELD-NEXT: reading SummaryData entries from field 'data'
+// PAIRS-INVALID-FIRST-FIELD-NEXT: reading SummaryData entry from index '0'
+// PAIRS-INVALID-FIRST-FIELD-NEXT: reading EntitySummary entries from field 'summary_data'
+// PAIRS-INVALID-FIRST-FIELD-NEXT: reading EntitySummary entry from index '0'
+// PAIRS-INVALID-FIRST-FIELD-NEXT: reading EntitySummary from field 'entity_summary'
+// PAIRS-INVALID-FIRST-FIELD-NEXT: missing or invalid 'first' field at index '0'
+
+// RUN: not %clang-ssaf-format-with-plugin --type lu %S/Inputs/pairs-missing-second-field.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=PAIRS-MISSING-SECOND-FIELD
+// PAIRS-MISSING-SECOND-FIELD: clang-ssaf-format: error: reading LUSummary from file '{{.*}}pairs-missing-second-field.json'
+// PAIRS-MISSING-SECOND-FIELD-NEXT: reading SummaryData entries from field 'data'
+// PAIRS-MISSING-SECOND-FIELD-NEXT: reading SummaryData entry from index '0'
+// PAIRS-MISSING-SECOND-FIELD-NEXT: reading EntitySummary entries from field 'summary_data'
+// PAIRS-MISSING-SECOND-FIELD-NEXT: reading EntitySummary entry from index '0'
+// PAIRS-MISSING-SECOND-FIELD-NEXT: reading EntitySummary from field 'entity_summary'
+// PAIRS-MISSING-SECOND-FIELD-NEXT: missing or invalid 'second' field at index '0'
+
+// RUN: not %clang-ssaf-format-with-plugin --type lu %S/Inputs/pairs-invalid-second-field.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=PAIRS-INVALID-SECOND-FIELD
+// PAIRS-INVALID-SECOND-FIELD: clang-ssaf-format: error: reading LUSummary from file '{{.*}}pairs-invalid-second-field.json'
+// PAIRS-INVALID-SECOND-FIELD-NEXT: reading SummaryData entries from field 'data'
+// PAIRS-INVALID-SECOND-FIELD-NEXT: reading SummaryData entry from index '0'
+// PAIRS-INVALID-SECOND-FIELD-NEXT: reading EntitySummary entries from field 'summary_data'
+// PAIRS-INVALID-SECOND-FIELD-NEXT: reading EntitySummary entry from index '0'
+// PAIRS-INVALID-SECOND-FIELD-NEXT: reading EntitySummary from field 'entity_summary'
+// PAIRS-INVALID-SECOND-FIELD-NEXT: missing or invalid 'second' field at index '0'
+
+// ============================================================================
+// entityDataMapEntryFromJSON() errors
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/entity-data-missing-entity-id.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-DATA-MISSING-ENTITY-ID
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/entity-data-missing-entity-id.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-DATA-MISSING-ENTITY-ID
+// ENTITY-DATA-MISSING-ENTITY-ID: clang-ssaf-format: error: reading LUSummary from file '{{.*}}entity-data-missing-entity-id.json'
+// ENTITY-DATA-MISSING-ENTITY-ID-NEXT: reading SummaryData entries from field 'data'
+// ENTITY-DATA-MISSING-ENTITY-ID-NEXT: reading SummaryData entry from index '0'
+// ENTITY-DATA-MISSING-ENTITY-ID-NEXT: reading EntitySummary entries from field 'summary_data'
+// ENTITY-DATA-MISSING-ENTITY-ID-NEXT: reading EntitySummary entry from index '0'
+// ENTITY-DATA-MISSING-ENTITY-ID-NEXT: failed to read EntityId from field 'entity_id': expected JSON number (unsigned 64-bit integer)
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/entity-data-missing-entity-summary.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-DATA-MISSING-ENTITY-SUMMARY
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/entity-data-missing-entity-summary.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-DATA-MISSING-ENTITY-SUMMARY
+// ENTITY-DATA-MISSING-ENTITY-SUMMARY: clang-ssaf-format: error: reading LUSummary from file '{{.*}}entity-data-missing-entity-summary.json'
+// ENTITY-DATA-MISSING-ENTITY-SUMMARY-NEXT: reading SummaryData entries from field 'data'
+// ENTITY-DATA-MISSING-ENTITY-SUMMARY-NEXT: reading SummaryData entry from index '0'
+// ENTITY-DATA-MISSING-ENTITY-SUMMARY-NEXT: reading EntitySummary entries from field 'summary_data'
+// ENTITY-DATA-MISSING-ENTITY-SUMMARY-NEXT: reading EntitySummary entry from index '0'
+// ENTITY-DATA-MISSING-ENTITY-SUMMARY-NEXT: failed to read EntitySummary from field 'entity_summary': expected JSON object
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/entity-id-not-uint64.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-ID-NOT-UINT64
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/entity-id-not-uint64.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-ID-NOT-UINT64
+// ENTITY-ID-NOT-UINT64: clang-ssaf-format: error: reading LUSummary from file '{{.*}}entity-id-not-uint64.json'
+// ENTITY-ID-NOT-UINT64-NEXT: reading SummaryData entries from field 'data'
+// ENTITY-ID-NOT-UINT64-NEXT: reading SummaryData entry from index '0'
+// ENTITY-ID-NOT-UINT64-NEXT: reading EntitySummary entries from field 'summary_data'
+// ENTITY-ID-NOT-UINT64-NEXT: reading EntitySummary entry from index '0'
+// ENTITY-ID-NOT-UINT64-NEXT: failed to read EntityId from field 'entity_id': expected JSON number (unsigned 64-bit integer)
+
+// ============================================================================
+// entityDataMapFromJSON() errors
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/entity-data-element-not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-DATA-ELEMENT-NOT-OBJECT
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/entity-data-element-not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=ENTITY-DATA-ELEMENT-NOT-OBJECT
+// ENTITY-DATA-ELEMENT-NOT-OBJECT: clang-ssaf-format: error: reading LUSummary from file '{{.*}}entity-data-element-not-object.json'
+// ENTITY-DATA-ELEMENT-NOT-OBJECT-NEXT: reading SummaryData entries from field 'data'
+// ENTITY-DATA-ELEMENT-NOT-OBJECT-NEXT: reading SummaryData entry from index '0'
+// ENTITY-DATA-ELEMENT-NOT-OBJECT-NEXT: reading EntitySummary entries from field 'summary_data'
+// ENTITY-DATA-ELEMENT-NOT-OBJECT-NEXT: failed to read EntitySummary entry from index '0': expected JSON object
+
+// RUN: not %clang-ssaf-format-with-plugin --type lu %S/Inputs/duplicate-entity-id-in-data-map.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=DUPLICATE-ENTITY-ID-IN-DATA-MAP
+// DUPLICATE-ENTITY-ID-IN-DATA-MAP: clang-ssaf-format: error: reading LUSummary from file '{{.*}}duplicate-entity-id-in-data-map.json'
+// DUPLICATE-ENTITY-ID-IN-DATA-MAP-NEXT: reading SummaryData entries from field 'data'
+// DUPLICATE-ENTITY-ID-IN-DATA-MAP-NEXT: reading SummaryData entry from index '0'
+// DUPLICATE-ENTITY-ID-IN-DATA-MAP-NEXT: reading EntitySummary entries from field 'summary_data'
+// DUPLICATE-ENTITY-ID-IN-DATA-MAP-NEXT: failed to insert EntitySummary entry at index '1': encountered duplicate 'EntityId(0)'
+
+// ============================================================================
+// summaryDataMapFromJSON() errors
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/data-entry-missing-summary-name.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=DATA-ENTRY-MISSING-SUMMARY-NAME
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/data-entry-missing-summary-name.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=DATA-ENTRY-MISSING-SUMMARY-NAME
+// DATA-ENTRY-MISSING-SUMMARY-NAME: clang-ssaf-format: error: reading LUSummary from file '{{.*}}data-entry-missing-summary-name.json'
+// DATA-ENTRY-MISSING-SUMMARY-NAME-NEXT: reading SummaryData entries from field 'data'
+// DATA-ENTRY-MISSING-SUMMARY-NAME-NEXT: reading SummaryData entry from index '0'
+// DATA-ENTRY-MISSING-SUMMARY-NAME-NEXT: failed to read SummaryName from field 'summary_name': expected JSON string
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/data-entry-missing-data.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=DATA-ENTRY-MISSING-DATA
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/data-entry-missing-data.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=DATA-ENTRY-MISSING-DATA
+// DATA-ENTRY-MISSING-DATA: clang-ssaf-format: error: reading LUSummary from file '{{.*}}data-entry-missing-data.json'
+// DATA-ENTRY-MISSING-DATA-NEXT: reading SummaryData entries from field 'data'
+// DATA-ENTRY-MISSING-DATA-NEXT: reading SummaryData entry from index '0'
+// DATA-ENTRY-MISSING-DATA-NEXT: failed to read EntitySummary entries from field 'summary_data': expected JSON array
+
+// ============================================================================
+// summaryDataMapFromJSON() / encodingSummaryDataMapFromJSON() errors
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/data-not-array.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=DATA-NOT-ARRAY
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/data-not-array.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=DATA-NOT-ARRAY
+// DATA-NOT-ARRAY: clang-ssaf-format: error: reading LUSummary from file '{{.*}}data-not-array.json'
+// DATA-NOT-ARRAY-NEXT: failed to read SummaryData entries from field 'data': expected JSON array
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/data-element-not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=DATA-ELEMENT-NOT-OBJECT
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/data-element-not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=DATA-ELEMENT-NOT-OBJECT
+// DATA-ELEMENT-NOT-OBJECT: clang-ssaf-format: error: reading LUSummary from file '{{.*}}data-element-not-object.json'
+// DATA-ELEMENT-NOT-OBJECT-NEXT: reading SummaryData entries from field 'data'
+// DATA-ELEMENT-NOT-OBJECT-NEXT: failed to read SummaryData entry from index '0': expected JSON object
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/duplicate-summary-name.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=DUPLICATE-SUMMARY-NAME
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/duplicate-summary-name.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=DUPLICATE-SUMMARY-NAME
+// DUPLICATE-SUMMARY-NAME: clang-ssaf-format: error: reading LUSummary from file '{{.*}}duplicate-summary-name.json'
+// DUPLICATE-SUMMARY-NAME-NEXT: reading SummaryData entries from field 'data'
+// DUPLICATE-SUMMARY-NAME-NEXT: failed to insert SummaryData entry at index '1': encountered duplicate 'SummaryName(PairsEntitySummary)'
diff --git a/clang/test/Analysis/Scalable/ssaf-format/LUSummary/top-level.test b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/top-level.test
new file mode 100644
index 0000000000000..0acd11e682905
--- /dev/null
+++ b/clang/test/Analysis/Scalable/ssaf-format/LUSummary/top-level.test
@@ -0,0 +1,84 @@
+// Top-level LUSummary structure tests: NestedBuildNamespace 'lu_namespace'
+// field parsing and missing top-level fields (lu_namespace, id_table,
+// linkage_table, data).
+
+// REQUIRES: plugins
+
+// ============================================================================
+// nestedBuildNamespaceFromJSON() errors (lu_namespace field) -- LU-SPECIFIC
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/lu-namespace-not-array.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LU-NAMESPACE-NOT-ARRAY
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/lu-namespace-not-array.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LU-NAMESPACE-NOT-ARRAY
+// LU-NAMESPACE-NOT-ARRAY: clang-ssaf-format: error: reading LUSummary from file '{{.*}}lu-namespace-not-array.json'
+// LU-NAMESPACE-NOT-ARRAY-NEXT: failed to read NestedBuildNamespace from field 'lu_namespace': expected JSON array
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/lu-namespace-element-not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LU-NAMESPACE-ELEMENT-NOT-OBJECT
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/lu-namespace-element-not-object.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LU-NAMESPACE-ELEMENT-NOT-OBJECT
+// LU-NAMESPACE-ELEMENT-NOT-OBJECT: clang-ssaf-format: error: reading LUSummary from file '{{.*}}lu-namespace-element-not-object.json'
+// LU-NAMESPACE-ELEMENT-NOT-OBJECT-NEXT: reading NestedBuildNamespace from field 'lu_namespace'
+// LU-NAMESPACE-ELEMENT-NOT-OBJECT-NEXT: failed to read BuildNamespace from index '0': expected JSON object
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/lu-namespace-element-missing-kind.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LU-NAMESPACE-ELEMENT-MISSING-KIND
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/lu-namespace-element-missing-kind.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LU-NAMESPACE-ELEMENT-MISSING-KIND
+// LU-NAMESPACE-ELEMENT-MISSING-KIND: clang-ssaf-format: error: reading LUSummary from file '{{.*}}lu-namespace-element-missing-kind.json'
+// LU-NAMESPACE-ELEMENT-MISSING-KIND-NEXT: reading NestedBuildNamespace from field 'lu_namespace'
+// LU-NAMESPACE-ELEMENT-MISSING-KIND-NEXT: reading BuildNamespace from index '0'
+// LU-NAMESPACE-ELEMENT-MISSING-KIND-NEXT: failed to read BuildNamespaceKind from field 'kind': expected JSON string
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/lu-namespace-element-invalid-kind.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LU-NAMESPACE-ELEMENT-INVALID-KIND
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/lu-namespace-element-invalid-kind.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LU-NAMESPACE-ELEMENT-INVALID-KIND
+// LU-NAMESPACE-ELEMENT-INVALID-KIND: clang-ssaf-format: error: reading LUSummary from file '{{.*}}lu-namespace-element-invalid-kind.json'
+// LU-NAMESPACE-ELEMENT-INVALID-KIND-NEXT: reading NestedBuildNamespace from field 'lu_namespace'
+// LU-NAMESPACE-ELEMENT-INVALID-KIND-NEXT: reading BuildNamespace from index '0'
+// LU-NAMESPACE-ELEMENT-INVALID-KIND-NEXT: reading BuildNamespaceKind from field 'kind'
+// LU-NAMESPACE-ELEMENT-INVALID-KIND-NEXT: invalid BuildNamespaceKind value 'invalid_kind' for field 'kind'
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/lu-namespace-element-missing-name.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LU-NAMESPACE-ELEMENT-MISSING-NAME
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/lu-namespace-element-missing-name.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=LU-NAMESPACE-ELEMENT-MISSING-NAME
+// LU-NAMESPACE-ELEMENT-MISSING-NAME: clang-ssaf-format: error: reading LUSummary from file '{{.*}}lu-namespace-element-missing-name.json'
+// LU-NAMESPACE-ELEMENT-MISSING-NAME-NEXT: reading NestedBuildNamespace from field 'lu_namespace'
+// LU-NAMESPACE-ELEMENT-MISSING-NAME-NEXT: reading BuildNamespace from index '0'
+// LU-NAMESPACE-ELEMENT-MISSING-NAME-NEXT: failed to read BuildNamespaceName from field 'name': expected JSON string
+
+// ============================================================================
+// readLUSummary() / readLUSummaryEncoding() errors
+// ============================================================================
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/missing-lu-namespace.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=MISSING-LU-NAMESPACE
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/missing-lu-namespace.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=MISSING-LU-NAMESPACE
+// MISSING-LU-NAMESPACE: clang-ssaf-format: error: reading LUSummary from file '{{.*}}missing-lu-namespace.json'
+// MISSING-LU-NAMESPACE-NEXT: failed to read NestedBuildNamespace from field 'lu_namespace': expected JSON array
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/missing-id-table.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=MISSING-ID-TABLE
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/missing-id-table.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=MISSING-ID-TABLE
+// MISSING-ID-TABLE: clang-ssaf-format: error: reading LUSummary from file '{{.*}}missing-id-table.json'
+// MISSING-ID-TABLE-NEXT: failed to read IdTable from field 'id_table': expected JSON array
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/missing-linkage-table.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=MISSING-LINKAGE-TABLE
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/missing-linkage-table.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=MISSING-LINKAGE-TABLE
+// MISSING-LINKAGE-TABLE: clang-ssaf-format: error: reading LUSummary from file '{{.*}}missing-linkage-table.json'
+// MISSING-LINKAGE-TABLE-NEXT: failed to read LinkageTable from field 'linkage_table': expected JSON array
+
+// RUN: not clang-ssaf-format --type lu %S/Inputs/missing-data.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=MISSING-DATA
+// RUN: not clang-ssaf-format --type lu --encoding %S/Inputs/missing-data.json 2>&1 \
+// RUN: | FileCheck %s --match-full-lines --check-prefix=MISSING-DATA
+// MISSING-DATA: clang-ssaf-format: error: reading LUSummary from file '{{.*}}missing-data.json'
+// MISSING-DATA-NEXT: failed to read SummaryData entries from field 'data': expected JSON array
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp
index 3b733634ccb03..b1f2e0f0870f1 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp
@@ -214,1388 +214,9 @@ TEST_P(LUSummaryTest, NoReadPermission) {
EXPECT_THAT_ERROR(std::move(RestoreError), Succeeded());
}
-TEST_P(LUSummaryTest, InvalidSyntax) {
- auto Result = readFromString("{ invalid json }");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("Expected object key"))));
-}
-
-TEST_P(LUSummaryTest, NotObject) {
- auto Result = readFromString("[]");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("failed to read LUSummary"),
- HasSubstr("expected JSON object"))));
-}
-
-// ============================================================================
-// JSONFormat::entityLinkageFromJSON() Error Tests
-// ============================================================================
-
-TEST_P(LUSummaryTest, LinkageTableEntryLinkageMissingType) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [
- {
- "id": 0,
- "linkage": {}
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading LinkageTable from field 'linkage_table'"),
- HasSubstr("reading LinkageTable entry from index '0'"),
- HasSubstr("reading EntityLinkage from field 'linkage'"),
- HasSubstr("failed to read EntityLinkageType from field 'type'"),
- HasSubstr("expected JSON string"))));
-}
-
-TEST_P(LUSummaryTest, LinkageTableEntryLinkageInvalidType) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "invalid_type" }
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading LinkageTable from field 'linkage_table'"),
- HasSubstr("reading LinkageTable entry from index '0'"),
- HasSubstr("reading EntityLinkage from field 'linkage'"),
- HasSubstr("invalid EntityLinkageType value 'invalid_type' for "
- "field 'type'"))));
-}
-
-// ============================================================================
-// JSONFormat::linkageTableEntryFromJSON() Error Tests
-// ============================================================================
-
-TEST_P(LUSummaryTest, LinkageTableEntryMissingId) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [
- {
- "linkage": { "type": "External" }
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading LinkageTable from field 'linkage_table'"),
- HasSubstr("reading LinkageTable entry from index '0'"),
- HasSubstr("failed to read EntityId from field 'id'"),
- HasSubstr("expected JSON number (unsigned 64-bit integer)"))));
-}
-
-TEST_P(LUSummaryTest, LinkageTableEntryIdNotUInt64) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [
- {
- "id": "not_a_number",
- "linkage": { "type": "External" }
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading LinkageTable from field 'linkage_table'"),
- HasSubstr("reading LinkageTable entry from index '0'"),
- HasSubstr("failed to read EntityId from field 'id'"),
- HasSubstr("expected JSON number (unsigned 64-bit integer)"))));
-}
-
-TEST_P(LUSummaryTest, LinkageTableEntryMissingLinkage) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [
- {
- "id": 0
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading LinkageTable from field 'linkage_table'"),
- HasSubstr("reading LinkageTable entry from index '0'"),
- HasSubstr("failed to read EntityLinkage from field 'linkage'"),
- HasSubstr("expected JSON object"))));
-}
-
-// ============================================================================
-// JSONFormat::linkageTableFromJSON() Error Tests
-// ============================================================================
-
-TEST_P(LUSummaryTest, LinkageTableNotArray) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": {},
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("failed to read LinkageTable from field 'linkage_table'"),
- HasSubstr("expected JSON array"))));
-}
-
-TEST_P(LUSummaryTest, LinkageTableElementNotObject) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": ["invalid"],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading LinkageTable from field 'linkage_table'"),
- HasSubstr("failed to read LinkageTable entry from index '0'"),
- HasSubstr("expected JSON object"))));
-}
-
-TEST_P(LUSummaryTest, LinkageTableExtraId) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "External" }
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading LinkageTable from field 'linkage_table'"),
- HasSubstr("reading LinkageTable entry from index '0'"),
- HasSubstr("failed to deserialize LinkageTable"),
- HasSubstr("extra 'EntityId(0)' not present in IdTable"))));
-}
-
-TEST_P(LUSummaryTest, LinkageTableMissingId) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- },
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ]
- }
- }
- ],
- "linkage_table": [],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading LinkageTable from field 'linkage_table'"),
- HasSubstr("failed to deserialize LinkageTable"),
- HasSubstr("missing 'EntityId(0)' present in IdTable"))));
-}
-
-TEST_P(LUSummaryTest, LinkageTableDuplicateId) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- },
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ]
- }
- }
- ],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "External" }
- },
- {
- "id": 0,
- "linkage": { "type": "Internal" }
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading LinkageTable from field 'linkage_table'"),
- HasSubstr("failed to insert LinkageTable entry at index '1'"),
- HasSubstr("encountered duplicate 'EntityId(0)'"))));
-}
-
-// ============================================================================
-// JSONFormat::nestedBuildNamespaceFromJSON() Error Tests (lu_namespace field)
-// ============================================================================
-
-TEST_P(LUSummaryTest, LUNamespaceNotArray) {
- auto Result = readFromString(R"({
- "lu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" },
- "id_table": [],
- "linkage_table": [],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr(
- "failed to read NestedBuildNamespace from field 'lu_namespace'"),
- HasSubstr("expected JSON array"))));
-}
-
-TEST_P(LUSummaryTest, LUNamespaceElementNotObject) {
- auto Result = readFromString(R"({
- "lu_namespace": ["invalid"],
- "id_table": [],
- "linkage_table": [],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading NestedBuildNamespace from field 'lu_namespace'"),
- HasSubstr("failed to read BuildNamespace from index '0'"),
- HasSubstr("expected JSON object"))));
-}
-
-TEST_P(LUSummaryTest, LUNamespaceElementMissingKind) {
- auto Result = readFromString(R"({
- "lu_namespace": [{ "name": "test.cpp" }],
- "id_table": [],
- "linkage_table": [],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading NestedBuildNamespace from field 'lu_namespace'"),
- HasSubstr("reading BuildNamespace from index '0'"),
- HasSubstr("failed to read BuildNamespaceKind from field 'kind'"),
- HasSubstr("expected JSON string"))));
-}
-
-TEST_P(LUSummaryTest, LUNamespaceElementInvalidKind) {
- auto Result = readFromString(R"({
- "lu_namespace": [{ "kind": "invalid_kind", "name": "test.cpp" }],
- "id_table": [],
- "linkage_table": [],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading NestedBuildNamespace from field 'lu_namespace'"),
- HasSubstr("reading BuildNamespace from index '0'"),
- HasSubstr("reading BuildNamespaceKind from field 'kind'"),
- HasSubstr("invalid BuildNamespaceKind value 'invalid_kind' for "
- "field 'kind'"))));
-}
-
-TEST_P(LUSummaryTest, LUNamespaceElementMissingName) {
- auto Result = readFromString(R"({
- "lu_namespace": [{ "kind": "CompilationUnit" }],
- "id_table": [],
- "linkage_table": [],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading NestedBuildNamespace from field 'lu_namespace'"),
- HasSubstr("reading BuildNamespace from index '0'"),
- HasSubstr("failed to read BuildNamespaceName from field 'name'"),
- HasSubstr("expected JSON string"))));
-}
-
-// ============================================================================
-// JSONFormat::nestedBuildNamespaceFromJSON() Error Tests (EntityName namespace)
-// ============================================================================
-
-TEST_P(LUSummaryTest, NamespaceElementNotObject) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": ["invalid"]
- }
- }
- ],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "None" }
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading IdTable from field 'id_table'"),
- HasSubstr("reading EntityIdTable entry from index '0'"),
- HasSubstr("reading EntityName from field 'name'"),
- HasSubstr("reading NestedBuildNamespace from field 'namespace'"),
- HasSubstr("failed to read BuildNamespace from index '0'"),
- HasSubstr("expected JSON object"))));
-}
-
-TEST_P(LUSummaryTest, NamespaceElementMissingKind) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": [
- {
- "name": "test.cpp"
- }
- ]
- }
- }
- ],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "Internal" }
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading IdTable from field 'id_table'"),
- HasSubstr("reading EntityIdTable entry from index '0'"),
- HasSubstr("reading EntityName from field 'name'"),
- HasSubstr("reading NestedBuildNamespace from field 'namespace'"),
- HasSubstr("reading BuildNamespace from index '0'"),
- HasSubstr("failed to read BuildNamespaceKind from field 'kind'"),
- HasSubstr("expected JSON string"))));
-}
-
-TEST_P(LUSummaryTest, NamespaceElementInvalidKind) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": [
- {
- "kind": "invalid_kind",
- "name": "test.cpp"
- }
- ]
- }
- }
- ],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "External" }
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading IdTable from field 'id_table'"),
- HasSubstr("reading EntityIdTable entry from index '0'"),
- HasSubstr("reading EntityName from field 'name'"),
- HasSubstr("reading NestedBuildNamespace from field 'namespace'"),
- HasSubstr("reading BuildNamespace from index '0'"),
- HasSubstr("reading BuildNamespaceKind from field 'kind'"),
- HasSubstr("invalid BuildNamespaceKind value 'invalid_kind' for "
- "field 'kind'"))));
-}
-
-TEST_P(LUSummaryTest, NamespaceElementMissingName) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit"
- }
- ]
- }
- }
- ],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "None" }
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading IdTable from field 'id_table'"),
- HasSubstr("reading EntityIdTable entry from index '0'"),
- HasSubstr("reading EntityName from field 'name'"),
- HasSubstr("reading NestedBuildNamespace from field 'namespace'"),
- HasSubstr("reading BuildNamespace from index '0'"),
- HasSubstr("failed to read BuildNamespaceName from field 'name'"),
- HasSubstr("expected JSON string"))));
-}
-
-// ============================================================================
-// JSONFormat::luEntityNameFromJSON() Error Tests
-// ============================================================================
-
-TEST_P(LUSummaryTest, EntityNameMissingUSR) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- },
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ]
- }
- }
- ],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "None" }
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading IdTable from field 'id_table'"),
- HasSubstr("reading EntityIdTable entry from index '0'"),
- HasSubstr("reading EntityName from field 'name'"),
- HasSubstr("failed to read USR from field 'usr'"),
- HasSubstr("expected JSON string"))));
-}
-
-TEST_P(LUSummaryTest, EntityNameMissingSuffix) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at foo",
- "namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ]
- }
- }
- ],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "External" }
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading IdTable from field 'id_table'"),
- HasSubstr("reading EntityIdTable entry from index '0'"),
- HasSubstr("reading EntityName from field 'name'"),
- HasSubstr("failed to read Suffix from field 'suffix'"),
- HasSubstr("expected JSON string"))));
-}
-
-TEST_P(LUSummaryTest, EntityNameMissingNamespace) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at foo",
- "suffix": ""
- }
- }
- ],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "None" }
- }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading IdTable from field 'id_table'"),
- HasSubstr("reading EntityIdTable entry from index '0'"),
- HasSubstr("reading EntityName from field 'name'"),
- HasSubstr("failed to read NestedBuildNamespace from field "
- "'namespace'"),
- HasSubstr("expected JSON array"))));
-}
-
-// ============================================================================
-// JSONFormat::luEntityIdTableEntryFromJSON() Error Tests
-// ============================================================================
-
-TEST_P(LUSummaryTest, IDTableEntryMissingID) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- },
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ]
- }
- }
- ],
- "linkage_table": [],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading IdTable from field 'id_table'"),
- HasSubstr("reading EntityIdTable entry from index '0'"),
- HasSubstr("failed to read EntityId from field 'id'"),
- HasSubstr("expected JSON number (unsigned 64-bit integer)"))));
-}
-
-TEST_P(LUSummaryTest, IDTableEntryMissingName) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "id": 0
- }
- ],
- "linkage_table": [],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading IdTable from field 'id_table'"),
- HasSubstr("reading EntityIdTable entry from index '0'"),
- HasSubstr("failed to read EntityName from field 'name'"),
- HasSubstr("expected JSON object"))));
-}
-
-TEST_P(LUSummaryTest, IDTableEntryIDNotUInt64) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "id": "not_a_number",
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- },
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ]
- }
- }
- ],
- "linkage_table": [],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading IdTable from field 'id_table'"),
- HasSubstr("reading EntityIdTable entry from index '0'"),
- HasSubstr("failed to read EntityId from field 'id'"),
- HasSubstr("expected JSON number (unsigned 64-bit integer)"))));
-}
-
-// ============================================================================
-// JSONFormat::luEntityIdTableFromJSON() Error Tests
-// ============================================================================
-
-TEST_P(LUSummaryTest, IDTableNotArray) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": {},
- "linkage_table": [],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("failed to read IdTable from field 'id_table'"),
- HasSubstr("expected JSON array"))));
-}
-
-TEST_P(LUSummaryTest, IDTableElementNotObject) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": ["invalid"],
- "linkage_table": [],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading IdTable from field 'id_table'"),
- HasSubstr("failed to read EntityIdTable entry from index '0'"),
- HasSubstr("expected JSON object"))));
-}
-
-TEST_P(LUSummaryTest, DuplicateEntity) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- },
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ]
- }
- },
- {
- "id": 1,
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- },
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ]
- }
- }
- ],
- "linkage_table": [
- { "id": 0, "linkage": { "type": "None" } },
- { "id": 1, "linkage": { "type": "None" } }
- ],
- "data": []
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading IdTable from field 'id_table'"),
- HasSubstr("failed to insert EntityIdTable entry at index '1'"),
- HasSubstr("encountered duplicate 'EntityId(0)'"))));
-}
-
-// ============================================================================
-// JSONFormat::readLUSummary() Error Tests (LUSummary-only)
-// ============================================================================
-
-TEST_F(JSONFormatLUSummaryTest, ReadEntitySummaryNoFormatInfo) {
- auto Result = readLUSummaryFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "UnregisteredEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": {}
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("reading EntitySummary from field 'entity_summary'"),
- HasSubstr("failed to deserialize EntitySummary"),
- HasSubstr(
- "no FormatInfo registered for "
- "'SummaryName(UnregisteredEntitySummaryForJSONFormatTest)'"))));
-}
-
-// ============================================================================
-// PairsEntitySummaryForJSONFormatTest Deserialization Error Tests
-// ============================================================================
-
-TEST_F(JSONFormatLUSummaryTest,
- PairsEntitySummaryForJSONFormatTestMissingPairsField) {
- auto Result = readLUSummaryFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": {}
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("reading EntitySummary from field 'entity_summary'"),
- HasSubstr("missing or invalid field 'pairs'"))));
-}
-
-TEST_F(JSONFormatLUSummaryTest,
- PairsEntitySummaryForJSONFormatTestInvalidPairsFieldType) {
- auto Result = readLUSummaryFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": {
- "pairs": "not_an_array"
- }
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("reading EntitySummary from field 'entity_summary'"),
- HasSubstr("missing or invalid field 'pairs'"))));
-}
-
-TEST_F(JSONFormatLUSummaryTest,
- PairsEntitySummaryForJSONFormatTestPairsElementNotObject) {
- auto Result = readLUSummaryFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": {
- "pairs": ["not_an_object"]
- }
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("reading EntitySummary from field 'entity_summary'"),
- HasSubstr("pairs element at index 0 is not a JSON object"))));
-}
-
-TEST_F(JSONFormatLUSummaryTest,
- PairsEntitySummaryForJSONFormatTestMissingFirstField) {
- auto Result = readLUSummaryFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": {
- "pairs": [
- {
- "second": {"@": 1}
- }
- ]
- }
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("reading EntitySummary from field 'entity_summary'"),
- HasSubstr("missing or invalid 'first' field at index '0'"))));
-}
-
-TEST_F(JSONFormatLUSummaryTest,
- PairsEntitySummaryForJSONFormatTestInvalidFirstField) {
- auto Result = readLUSummaryFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": {
- "pairs": [
- {
- "first": "not_a_number",
- "second": {"@": 1}
- }
- ]
- }
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("reading EntitySummary from field 'entity_summary'"),
- HasSubstr("missing or invalid 'first' field at index '0'"))));
-}
-
-TEST_F(JSONFormatLUSummaryTest,
- PairsEntitySummaryForJSONFormatTestMissingSecondField) {
- auto Result = readLUSummaryFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": {
- "pairs": [
- {
- "first": {"@": 0}
- }
- ]
- }
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("reading EntitySummary from field 'entity_summary'"),
- HasSubstr("missing or invalid 'second' field at index '0'"))));
-}
-
-TEST_F(JSONFormatLUSummaryTest,
- PairsEntitySummaryForJSONFormatTestInvalidSecondField) {
- auto Result = readLUSummaryFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": {
- "pairs": [
- {
- "first": {"@": 0},
- "second": "not_a_number"
- }
- ]
- }
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("reading EntitySummary from field 'entity_summary'"),
- HasSubstr("missing or invalid 'second' field at index '0'"))));
-}
-
-// ============================================================================
-// JSONFormat::entityDataMapFromJSON() Error Tests
-// ============================================================================
-
-TEST_P(LUSummaryTest, EntityDataMissingEntityID) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_summary": {}
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("failed to read EntityId from field 'entity_id'"),
- HasSubstr("expected JSON number (unsigned 64-bit integer)"))));
-}
-
-TEST_P(LUSummaryTest, EntityDataMissingEntitySummary) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("failed to read EntitySummary from field 'entity_summary'"),
- HasSubstr("expected JSON object"))));
-}
-
-TEST_P(LUSummaryTest, EntityIDNotUInt64) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": "not_a_number",
- "entity_summary": {}
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("failed to read EntityId from field 'entity_id'"),
- HasSubstr("expected JSON number (unsigned 64-bit integer)"))));
-}
+// ============================================================================
+// JSONFormat::entityDataMapFromJSON() Error Tests
+// ============================================================================
TEST_F(JSONFormatLUSummaryTest, ReadEntitySummaryMissingData) {
auto Result = readLUSummaryFromString(R"({
@@ -1617,311 +238,24 @@ TEST_F(JSONFormatLUSummaryTest, ReadEntitySummaryMissingData) {
}
]
}
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("failed to deserialize EntitySummary"),
- HasSubstr("null EntitySummary data for "
- "'SummaryName(NullEntitySummaryForJSONFormatTest)'"))));
-}
-
-TEST_F(JSONFormatLUSummaryTest, ReadEntitySummaryMismatchedSummaryName) {
- auto Result = readLUSummaryFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "MismatchedEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": {}
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("failed to deserialize EntitySummary"),
- HasSubstr("EntitySummary data for "
- "'SummaryName(MismatchedEntitySummaryForJSONFormatTest)'"
- " reports mismatched "
- "'SummaryName(MismatchedEntitySummaryForJSONFormatTest_"
- "WrongName)'"))));
-}
-
-// ============================================================================
-// JSONFormat::entityDataMapEntryToJSON() Fatal Tests
-// ============================================================================
-
-TEST_F(JSONFormatLUSummaryTest, WriteEntitySummaryMissingData) {
- NestedBuildNamespace NBN(
- BuildNamespace(BuildNamespaceKind::LinkUnit, "test.exe"));
- LUSummary Summary(std::move(NBN));
-
- NestedBuildNamespace Namespace =
- NestedBuildNamespace::makeCompilationUnit("test.cpp");
- EntityId EI = getIdTable(Summary).getId(
- EntityName{"c:@F at foo", "", std::move(Namespace)});
-
- SummaryName SN("NullEntitySummaryForJSONFormatTest");
- getData(Summary)[SN][EI] = nullptr;
-
- EXPECT_DEATH(
- { (void)writeLUSummary(Summary, "output.json"); },
- "JSONFormat - null EntitySummary data for "
- "'SummaryName\\(NullEntitySummaryForJSONFormatTest\\)'");
-}
-
-TEST_F(JSONFormatLUSummaryTest, WriteEntitySummaryMismatchedSummaryName) {
- NestedBuildNamespace NBN(
- BuildNamespace(BuildNamespaceKind::LinkUnit, "test.exe"));
- LUSummary Summary(std::move(NBN));
-
- NestedBuildNamespace Namespace =
- NestedBuildNamespace::makeCompilationUnit("test.cpp");
- EntityId EI = getIdTable(Summary).getId(
- EntityName{"c:@F at foo", "", std::move(Namespace)});
-
- SummaryName SN("MismatchedEntitySummaryForJSONFormatTest");
- getData(Summary)[SN][EI] =
- std::make_unique<MismatchedEntitySummaryForJSONFormatTest>();
-
- EXPECT_DEATH(
- { (void)writeLUSummary(Summary, "output.json"); },
- "JSONFormat - EntitySummary data for "
- "'SummaryName\\(MismatchedEntitySummaryForJSONFormatTest\\)' "
- "reports "
- "mismatched "
- "'SummaryName\\(MismatchedEntitySummaryForJSONFormatTest_WrongName\\)'");
-}
-
-// ============================================================================
-// JSONFormat::entityDataMapFromJSON() Error Tests
-// ============================================================================
-
-TEST_P(LUSummaryTest, EntityDataElementNotObject) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": ["invalid"]
- }
- ]
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("failed to read EntitySummary entry from index '0'"),
- HasSubstr("expected JSON object"))));
-}
-
-TEST_P(LUSummaryTest, DuplicateEntityIdInDataMap) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- },
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ]
- }
- }
- ],
- "linkage_table": [
- {
- "id": 0,
- "linkage": {
- "type": "None"
- }
- }
- ],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": { "pairs": [] }
- },
- {
- "entity_id": 0,
- "entity_summary": { "pairs": [] }
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("failed to insert EntitySummary entry at index '1'"),
- HasSubstr("encountered duplicate 'EntityId(0)'"))));
-}
-
-// ============================================================================
-// JSONFormat::summaryDataMapFromJSON() Error Tests
-// ============================================================================
-
-TEST_P(LUSummaryTest, DataEntryMissingSummaryName) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_data": []
- }
- ]
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("failed to read SummaryName from field 'summary_name'"),
- HasSubstr("expected JSON string"))));
-}
-
-TEST_P(LUSummaryTest, DataEntryMissingData) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest"
- }
- ]
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("failed to read EntitySummary entries from field "
- "'summary_data'"),
- HasSubstr("expected JSON array"))));
-}
-
-// ============================================================================
-// JSONFormat::summaryDataMapFromJSON() / encodingSummaryDataMapFromJSON() Tests
-// ============================================================================
-
-TEST_P(LUSummaryTest, DataNotArray) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": {}
- })");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("failed to read SummaryData entries from field 'data'"),
- HasSubstr("expected JSON array"))));
-}
-
-TEST_P(LUSummaryTest, DataElementNotObject) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": ["invalid"]
+ ]
})");
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("failed to read SummaryData entry from index '0'"),
- HasSubstr("expected JSON object"))));
+ EXPECT_THAT_EXPECTED(
+ Result,
+ FailedWithMessage(AllOf(
+ HasSubstr("reading LUSummary from file"),
+ HasSubstr("reading SummaryData entries from field 'data'"),
+ HasSubstr("reading SummaryData entry from index '0'"),
+ HasSubstr("reading EntitySummary entries from field 'summary_data'"),
+ HasSubstr("reading EntitySummary entry from index '0'"),
+ HasSubstr("failed to deserialize EntitySummary"),
+ HasSubstr("null EntitySummary data for "
+ "'SummaryName(NullEntitySummaryForJSONFormatTest)'"))));
}
-TEST_P(LUSummaryTest, DuplicateSummaryName) {
- auto Result = readFromString(R"({
+TEST_F(JSONFormatLUSummaryTest, ReadEntitySummaryMismatchedSummaryName) {
+ auto Result = readLUSummaryFromString(R"({
"lu_namespace": [
{
"kind": "LinkUnit",
@@ -1932,103 +266,77 @@ TEST_P(LUSummaryTest, DuplicateSummaryName) {
"linkage_table": [],
"data": [
{
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": []
- },
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": []
+ "summary_name": "MismatchedEntitySummaryForJSONFormatTest",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {}
+ }
+ ]
}
]
})");
- EXPECT_THAT_ERROR(
- std::move(Result),
+ EXPECT_THAT_EXPECTED(
+ Result,
FailedWithMessage(AllOf(
HasSubstr("reading LUSummary from file"),
HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("failed to insert SummaryData entry at index '1'"),
- HasSubstr("encountered duplicate "
- "'SummaryName(PairsEntitySummaryForJSONFormatTest)'"))));
+ HasSubstr("reading SummaryData entry from index '0'"),
+ HasSubstr("reading EntitySummary entries from field 'summary_data'"),
+ HasSubstr("reading EntitySummary entry from index '0'"),
+ HasSubstr("failed to deserialize EntitySummary"),
+ HasSubstr("EntitySummary data for "
+ "'SummaryName(MismatchedEntitySummaryForJSONFormatTest)'"
+ " reports mismatched "
+ "'SummaryName(MismatchedEntitySummaryForJSONFormatTest_"
+ "WrongName)'"))));
}
// ============================================================================
-// JSONFormat::readLUSummary() / readLUSummaryEncoding() Error Tests
+// JSONFormat::entityDataMapEntryToJSON() Fatal Tests
// ============================================================================
-TEST_P(LUSummaryTest, MissingLUNamespace) {
- auto Result = readFromString(R"({
- "id_table": [],
- "linkage_table": [],
- "data": []
- })");
+TEST_F(JSONFormatLUSummaryTest, WriteEntitySummaryMissingData) {
+ NestedBuildNamespace NBN(
+ BuildNamespace(BuildNamespaceKind::LinkUnit, "test.exe"));
+ LUSummary Summary(std::move(NBN));
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr(
- "failed to read NestedBuildNamespace from field 'lu_namespace'"),
- HasSubstr("expected JSON array"))));
-}
+ NestedBuildNamespace Namespace =
+ NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ EntityId EI = getIdTable(Summary).getId(
+ EntityName{"c:@F at foo", "", std::move(Namespace)});
-TEST_P(LUSummaryTest, MissingIDTable) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "data": []
- })");
+ SummaryName SN("NullEntitySummaryForJSONFormatTest");
+ getData(Summary)[SN][EI] = nullptr;
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("failed to read IdTable from field 'id_table'"),
- HasSubstr("expected JSON array"))));
+ EXPECT_DEATH(
+ { (void)writeLUSummary(Summary, "output.json"); },
+ "JSONFormat - null EntitySummary data for "
+ "'SummaryName\\(NullEntitySummaryForJSONFormatTest\\)'");
}
-TEST_P(LUSummaryTest, MissingLinkageTable) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "data": []
- })");
+TEST_F(JSONFormatLUSummaryTest, WriteEntitySummaryMismatchedSummaryName) {
+ NestedBuildNamespace NBN(
+ BuildNamespace(BuildNamespaceKind::LinkUnit, "test.exe"));
+ LUSummary Summary(std::move(NBN));
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("failed to read LinkageTable from field 'linkage_table'"),
- HasSubstr("expected JSON array"))));
-}
+ NestedBuildNamespace Namespace =
+ NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ EntityId EI = getIdTable(Summary).getId(
+ EntityName{"c:@F at foo", "", std::move(Namespace)});
-TEST_P(LUSummaryTest, MissingData) {
- auto Result = readFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": []
- })");
+ SummaryName SN("MismatchedEntitySummaryForJSONFormatTest");
+ getData(Summary)[SN][EI] =
+ std::make_unique<MismatchedEntitySummaryForJSONFormatTest>();
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("failed to read SummaryData entries from field 'data'"),
- HasSubstr("expected JSON array"))));
+ EXPECT_DEATH(
+ { (void)writeLUSummary(Summary, "output.json"); },
+ "JSONFormat - EntitySummary data for "
+ "'SummaryName\\(MismatchedEntitySummaryForJSONFormatTest\\)' "
+ "reports "
+ "mismatched "
+ "'SummaryName\\(MismatchedEntitySummaryForJSONFormatTest_WrongName\\)'");
}
// ============================================================================
@@ -2137,388 +445,4 @@ TEST_F(JSONFormatLUSummaryTest, WriteEntitySummaryNoFormatInfo) {
"'SummaryName(UnregisteredEntitySummaryForJSONFormatTest)'"))));
}
-// ============================================================================
-// Round-Trip Tests - Serialization Verification
-// ============================================================================
-
-TEST_P(LUSummaryTest, RoundTripEmptyNamespace) {
- readWriteCompare(R"({
- "lu_namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": []
- })");
-}
-
-TEST_P(LUSummaryTest, RoundTripSingleNamespaceElement) {
- readWriteCompare(R"({
- "lu_namespace": [
- { "kind": "CompilationUnit", "name": "test.cpp" }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": []
- })");
-}
-
-TEST_P(LUSummaryTest, RoundTripMultipleNamespaceElements) {
- readWriteCompare(R"({
- "lu_namespace": [
- { "kind": "CompilationUnit", "name": "a.cpp" },
- { "kind": "CompilationUnit", "name": "b.cpp" },
- { "kind": "LinkUnit", "name": "libtest.so" }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": []
- })");
-}
-
-TEST_P(LUSummaryTest, RoundTripWithTwoSummaryTypes) {
- readWriteCompare(R"({
- "lu_namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- }
- ],
- "id_table": [
- {
- "id": 3,
- "name": {
- "usr": "c:@F at qux",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- }
- ]
- }
- },
- {
- "id": 1,
- "name": {
- "usr": "c:@F at bar",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- }
- ]
- }
- },
- {
- "id": 4,
- "name": {
- "usr": "c:@F at quux",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- }
- ]
- }
- },
- {
- "id": 0,
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- }
- ]
- }
- },
- {
- "id": 2,
- "name": {
- "usr": "c:@F at baz",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- }
- ]
- }
- }
- ],
- "linkage_table": [
- {
- "id": 3,
- "linkage": { "type": "Internal" }
- },
- {
- "id": 1,
- "linkage": { "type": "None" }
- },
- {
- "id": 4,
- "linkage": { "type": "External" }
- },
- {
- "id": 0,
- "linkage": { "type": "None" }
- },
- {
- "id": 2,
- "linkage": { "type": "Internal" }
- }
- ],
- "data": [
- {
- "summary_name": "TagsEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 4,
- "entity_summary": { "tags": ["exported", "hot"] }
- },
- {
- "entity_id": 1,
- "entity_summary": { "tags": ["internal-only"] }
- },
- {
- "entity_id": 3,
- "entity_summary": { "tags": ["internal-only"] }
- },
- {
- "entity_id": 0,
- "entity_summary": { "tags": ["entry-point"] }
- },
- {
- "entity_id": 2,
- "entity_summary": { "tags": [] }
- }
- ]
- },
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 1,
- "entity_summary": {
- "pairs": [
- { "first": {"@": 1}, "second": {"@": 3} }
- ]
- }
- },
- {
- "entity_id": 4,
- "entity_summary": {
- "pairs": [
- { "first": {"@": 4}, "second": {"@": 0} },
- { "first": {"@": 4}, "second": {"@": 2} }
- ]
- }
- },
- {
- "entity_id": 0,
- "entity_summary": {
- "pairs": []
- }
- },
- {
- "entity_id": 3,
- "entity_summary": {
- "pairs": [
- { "first": {"@": 3}, "second": {"@": 1} }
- ]
- }
- },
- {
- "entity_id": 2,
- "entity_summary": {
- "pairs": [
- { "first": {"@": 2}, "second": {"@": 4} },
- { "first": {"@": 2}, "second": {"@": 3} }
- ]
- }
- }
- ]
- }
- ]
- })");
-}
-
-TEST_P(LUSummaryTest, RoundTripWithEmptyDataEntry) {
- readWriteCompare(R"({
- "lu_namespace": [
- { "kind": "CompilationUnit", "name": "test.cpp" }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "PairsEntitySummaryForJSONFormatTest",
- "summary_data": []
- }
- ]
- })");
-}
-
-TEST_P(LUSummaryTest, RoundTripLinkageTableWithNoneLinkage) {
- readWriteCompare(R"({
- "lu_namespace": [
- { "kind": "CompilationUnit", "name": "test.cpp" }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- }
- ]
- }
- }
- ],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "None" }
- }
- ],
- "data": []
- })");
-}
-
-TEST_P(LUSummaryTest, RoundTripLinkageTableWithInternalLinkage) {
- readWriteCompare(R"({
- "lu_namespace": [
- { "kind": "CompilationUnit", "name": "test.cpp" }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at bar",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- }
- ]
- }
- }
- ],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "Internal" }
- }
- ],
- "data": []
- })");
-}
-
-TEST_P(LUSummaryTest, RoundTripLinkageTableWithExternalLinkage) {
- readWriteCompare(R"({
- "lu_namespace": [
- { "kind": "CompilationUnit", "name": "test.cpp" }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at baz",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- }
- ]
- }
- }
- ],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "External" }
- }
- ],
- "data": []
- })");
-}
-
-TEST_P(LUSummaryTest, RoundTripLinkageTableWithMultipleEntries) {
- readWriteCompare(R"({
- "lu_namespace": [
- { "kind": "CompilationUnit", "name": "test.cpp" }
- ],
- "id_table": [
- {
- "id": 0,
- "name": {
- "usr": "c:@F at foo",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- }
- ]
- }
- },
- {
- "id": 1,
- "name": {
- "usr": "c:@F at bar",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- }
- ]
- }
- },
- {
- "id": 2,
- "name": {
- "usr": "c:@F at baz",
- "suffix": "",
- "namespace": [
- {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- }
- ]
- }
- }
- ],
- "linkage_table": [
- {
- "id": 0,
- "linkage": { "type": "None" }
- },
- {
- "id": 1,
- "linkage": { "type": "Internal" }
- },
- {
- "id": 2,
- "linkage": { "type": "External" }
- }
- ],
- "data": []
- })");
-}
-
} // anonymous namespace
More information about the cfe-commits
mailing list