1*9e3b08aeSAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2*9e3b08aeSAndroid Build Coastguard Worker // -*- mode: C++ -*-
3*9e3b08aeSAndroid Build Coastguard Worker //
4*9e3b08aeSAndroid Build Coastguard Worker // Copyright 2023 Google LLC
5*9e3b08aeSAndroid Build Coastguard Worker //
6*9e3b08aeSAndroid Build Coastguard Worker // Licensed under the Apache License v2.0 with LLVM Exceptions (the
7*9e3b08aeSAndroid Build Coastguard Worker // "License"); you may not use this file except in compliance with the
8*9e3b08aeSAndroid Build Coastguard Worker // License. You may obtain a copy of the License at
9*9e3b08aeSAndroid Build Coastguard Worker //
10*9e3b08aeSAndroid Build Coastguard Worker // https://llvm.org/LICENSE.txt
11*9e3b08aeSAndroid Build Coastguard Worker //
12*9e3b08aeSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
13*9e3b08aeSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
14*9e3b08aeSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*9e3b08aeSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
16*9e3b08aeSAndroid Build Coastguard Worker // limitations under the License.
17*9e3b08aeSAndroid Build Coastguard Worker //
18*9e3b08aeSAndroid Build Coastguard Worker // Author: Giuliano Procida
19*9e3b08aeSAndroid Build Coastguard Worker
20*9e3b08aeSAndroid Build Coastguard Worker #include <cstddef>
21*9e3b08aeSAndroid Build Coastguard Worker #include <filesystem>
22*9e3b08aeSAndroid Build Coastguard Worker #include <iostream>
23*9e3b08aeSAndroid Build Coastguard Worker #include <optional>
24*9e3b08aeSAndroid Build Coastguard Worker #include <vector>
25*9e3b08aeSAndroid Build Coastguard Worker
26*9e3b08aeSAndroid Build Coastguard Worker #include <catch2/catch.hpp>
27*9e3b08aeSAndroid Build Coastguard Worker #include <libxml/tree.h>
28*9e3b08aeSAndroid Build Coastguard Worker #include "abigail_reader.h"
29*9e3b08aeSAndroid Build Coastguard Worker #include "equality.h"
30*9e3b08aeSAndroid Build Coastguard Worker #include "graph.h"
31*9e3b08aeSAndroid Build Coastguard Worker #include "runtime.h"
32*9e3b08aeSAndroid Build Coastguard Worker
33*9e3b08aeSAndroid Build Coastguard Worker namespace {
34*9e3b08aeSAndroid Build Coastguard Worker
filename_to_path(const char * f)35*9e3b08aeSAndroid Build Coastguard Worker std::filesystem::path filename_to_path(const char* f) {
36*9e3b08aeSAndroid Build Coastguard Worker return std::filesystem::path("testdata") / f;
37*9e3b08aeSAndroid Build Coastguard Worker }
38*9e3b08aeSAndroid Build Coastguard Worker
Read(const char * input)39*9e3b08aeSAndroid Build Coastguard Worker stg::abixml::Document Read(const char* input) {
40*9e3b08aeSAndroid Build Coastguard Worker stg::Runtime runtime(std::cerr, false);
41*9e3b08aeSAndroid Build Coastguard Worker return stg::abixml::Read(runtime, filename_to_path(input));
42*9e3b08aeSAndroid Build Coastguard Worker }
43*9e3b08aeSAndroid Build Coastguard Worker
Read(stg::Graph & graph,const char * input)44*9e3b08aeSAndroid Build Coastguard Worker stg::Id Read(stg::Graph& graph, const char* input) {
45*9e3b08aeSAndroid Build Coastguard Worker stg::Runtime runtime(std::cerr, false);
46*9e3b08aeSAndroid Build Coastguard Worker return stg::abixml::Read(runtime, graph, filename_to_path(input));
47*9e3b08aeSAndroid Build Coastguard Worker }
48*9e3b08aeSAndroid Build Coastguard Worker
49*9e3b08aeSAndroid Build Coastguard Worker struct EqualTreeTestCase {
50*9e3b08aeSAndroid Build Coastguard Worker const char* name;
51*9e3b08aeSAndroid Build Coastguard Worker const char* left;
52*9e3b08aeSAndroid Build Coastguard Worker const char* right;
53*9e3b08aeSAndroid Build Coastguard Worker bool equal;
54*9e3b08aeSAndroid Build Coastguard Worker };
55*9e3b08aeSAndroid Build Coastguard Worker
56*9e3b08aeSAndroid Build Coastguard Worker TEST_CASE("EqualTree") {
57*9e3b08aeSAndroid Build Coastguard Worker const auto test = GENERATE(
58*9e3b08aeSAndroid Build Coastguard Worker EqualTreeTestCase(
59*9e3b08aeSAndroid Build Coastguard Worker {"cleaning",
60*9e3b08aeSAndroid Build Coastguard Worker "abigail_dirty.xml",
61*9e3b08aeSAndroid Build Coastguard Worker "abigail_clean.xml",
62*9e3b08aeSAndroid Build Coastguard Worker true}),
63*9e3b08aeSAndroid Build Coastguard Worker EqualTreeTestCase(
64*9e3b08aeSAndroid Build Coastguard Worker {"self comparison",
65*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_0.xml",
66*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_0.xml",
67*9e3b08aeSAndroid Build Coastguard Worker true}),
68*9e3b08aeSAndroid Build Coastguard Worker EqualTreeTestCase(
69*9e3b08aeSAndroid Build Coastguard Worker {"attribute order is irrelevant",
70*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_0.xml",
71*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_1.xml",
72*9e3b08aeSAndroid Build Coastguard Worker true}),
73*9e3b08aeSAndroid Build Coastguard Worker EqualTreeTestCase(
74*9e3b08aeSAndroid Build Coastguard Worker {"element order is relevant",
75*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_0.xml",
76*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_2.xml",
77*9e3b08aeSAndroid Build Coastguard Worker false}),
78*9e3b08aeSAndroid Build Coastguard Worker EqualTreeTestCase(
79*9e3b08aeSAndroid Build Coastguard Worker {"attribute missing",
80*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_0.xml",
81*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_3.xml",
82*9e3b08aeSAndroid Build Coastguard Worker false}),
83*9e3b08aeSAndroid Build Coastguard Worker EqualTreeTestCase(
84*9e3b08aeSAndroid Build Coastguard Worker {"element missing",
85*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_0.xml",
86*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_4.xml",
87*9e3b08aeSAndroid Build Coastguard Worker false}),
88*9e3b08aeSAndroid Build Coastguard Worker EqualTreeTestCase(
89*9e3b08aeSAndroid Build Coastguard Worker {"attribute changed",
90*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_0.xml",
91*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_5.xml",
92*9e3b08aeSAndroid Build Coastguard Worker false}),
93*9e3b08aeSAndroid Build Coastguard Worker EqualTreeTestCase(
94*9e3b08aeSAndroid Build Coastguard Worker {"element changed",
95*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_0.xml",
96*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_6.xml",
97*9e3b08aeSAndroid Build Coastguard Worker false}));
98*9e3b08aeSAndroid Build Coastguard Worker
99*9e3b08aeSAndroid Build Coastguard Worker SECTION(test.name) {
100*9e3b08aeSAndroid Build Coastguard Worker const stg::abixml::Document left_document = Read(test.left);
101*9e3b08aeSAndroid Build Coastguard Worker const stg::abixml::Document right_document = Read(test.right);
102*9e3b08aeSAndroid Build Coastguard Worker xmlNodePtr left_root = xmlDocGetRootElement(left_document.get());
103*9e3b08aeSAndroid Build Coastguard Worker xmlNodePtr right_root = xmlDocGetRootElement(right_document.get());
104*9e3b08aeSAndroid Build Coastguard Worker stg::abixml::Clean(left_root);
105*9e3b08aeSAndroid Build Coastguard Worker stg::abixml::Clean(right_root);
106*9e3b08aeSAndroid Build Coastguard Worker CHECK(stg::abixml::EqualTree(left_root, right_root) == test.equal);
107*9e3b08aeSAndroid Build Coastguard Worker CHECK(stg::abixml::EqualTree(right_root, left_root) == test.equal);
108*9e3b08aeSAndroid Build Coastguard Worker }
109*9e3b08aeSAndroid Build Coastguard Worker }
110*9e3b08aeSAndroid Build Coastguard Worker
111*9e3b08aeSAndroid Build Coastguard Worker struct SubTreeTestCase {
112*9e3b08aeSAndroid Build Coastguard Worker const char* name;
113*9e3b08aeSAndroid Build Coastguard Worker const char* left;
114*9e3b08aeSAndroid Build Coastguard Worker const char* right;
115*9e3b08aeSAndroid Build Coastguard Worker bool left_sub_right;
116*9e3b08aeSAndroid Build Coastguard Worker bool right_sub_left;
117*9e3b08aeSAndroid Build Coastguard Worker };
118*9e3b08aeSAndroid Build Coastguard Worker
119*9e3b08aeSAndroid Build Coastguard Worker TEST_CASE("SubTree") {
120*9e3b08aeSAndroid Build Coastguard Worker const auto test = GENERATE(
121*9e3b08aeSAndroid Build Coastguard Worker SubTreeTestCase(
122*9e3b08aeSAndroid Build Coastguard Worker {"self comparison",
123*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_0.xml",
124*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_0.xml",
125*9e3b08aeSAndroid Build Coastguard Worker true, true}),
126*9e3b08aeSAndroid Build Coastguard Worker SubTreeTestCase(
127*9e3b08aeSAndroid Build Coastguard Worker {"attribute missing",
128*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_0.xml",
129*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_3.xml",
130*9e3b08aeSAndroid Build Coastguard Worker false, true}),
131*9e3b08aeSAndroid Build Coastguard Worker SubTreeTestCase(
132*9e3b08aeSAndroid Build Coastguard Worker {"element missing",
133*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_0.xml",
134*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_4.xml",
135*9e3b08aeSAndroid Build Coastguard Worker false, true}),
136*9e3b08aeSAndroid Build Coastguard Worker SubTreeTestCase(
137*9e3b08aeSAndroid Build Coastguard Worker {"member-type access special case",
138*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_0.xml",
139*9e3b08aeSAndroid Build Coastguard Worker "abigail_tree_7.xml",
140*9e3b08aeSAndroid Build Coastguard Worker true, true}));
141*9e3b08aeSAndroid Build Coastguard Worker
142*9e3b08aeSAndroid Build Coastguard Worker SECTION(test.name) {
143*9e3b08aeSAndroid Build Coastguard Worker const stg::abixml::Document left_document = Read(test.left);
144*9e3b08aeSAndroid Build Coastguard Worker const stg::abixml::Document right_document = Read(test.right);
145*9e3b08aeSAndroid Build Coastguard Worker xmlNodePtr left_root = xmlDocGetRootElement(left_document.get());
146*9e3b08aeSAndroid Build Coastguard Worker xmlNodePtr right_root = xmlDocGetRootElement(right_document.get());
147*9e3b08aeSAndroid Build Coastguard Worker stg::abixml::Clean(left_root);
148*9e3b08aeSAndroid Build Coastguard Worker stg::abixml::Clean(right_root);
149*9e3b08aeSAndroid Build Coastguard Worker CHECK(stg::abixml::SubTree(left_root, right_root) == test.left_sub_right);
150*9e3b08aeSAndroid Build Coastguard Worker CHECK(stg::abixml::SubTree(right_root, left_root) == test.right_sub_left);
151*9e3b08aeSAndroid Build Coastguard Worker }
152*9e3b08aeSAndroid Build Coastguard Worker }
153*9e3b08aeSAndroid Build Coastguard Worker
154*9e3b08aeSAndroid Build Coastguard Worker struct TidyTestCase {
155*9e3b08aeSAndroid Build Coastguard Worker const char* name;
156*9e3b08aeSAndroid Build Coastguard Worker const std::vector<const char*> files;
157*9e3b08aeSAndroid Build Coastguard Worker };
158*9e3b08aeSAndroid Build Coastguard Worker
159*9e3b08aeSAndroid Build Coastguard Worker TEST_CASE("Tidy") {
160*9e3b08aeSAndroid Build Coastguard Worker const auto test = GENERATE(
161*9e3b08aeSAndroid Build Coastguard Worker TidyTestCase(
162*9e3b08aeSAndroid Build Coastguard Worker {"bad DWARF ELF link",
163*9e3b08aeSAndroid Build Coastguard Worker {"abigail_bad_dwarf_elf_link_0.xml",
164*9e3b08aeSAndroid Build Coastguard Worker "abigail_bad_dwarf_elf_link_1.xml",
165*9e3b08aeSAndroid Build Coastguard Worker "abigail_bad_dwarf_elf_link_2.xml"}}),
166*9e3b08aeSAndroid Build Coastguard Worker TidyTestCase(
167*9e3b08aeSAndroid Build Coastguard Worker {"anonymous type normalisation",
168*9e3b08aeSAndroid Build Coastguard Worker {"abigail_anonymous_types_0.xml",
169*9e3b08aeSAndroid Build Coastguard Worker "abigail_anonymous_types_1.xml",
170*9e3b08aeSAndroid Build Coastguard Worker "abigail_anonymous_types_2.xml",
171*9e3b08aeSAndroid Build Coastguard Worker "abigail_anonymous_types_3.xml",
172*9e3b08aeSAndroid Build Coastguard Worker "abigail_anonymous_types_4.xml"}}),
173*9e3b08aeSAndroid Build Coastguard Worker TidyTestCase(
174*9e3b08aeSAndroid Build Coastguard Worker {"duplicate data members",
175*9e3b08aeSAndroid Build Coastguard Worker {"abigail_duplicate_data_members_0.xml",
176*9e3b08aeSAndroid Build Coastguard Worker "abigail_duplicate_data_members_1.xml"}}),
177*9e3b08aeSAndroid Build Coastguard Worker TidyTestCase(
178*9e3b08aeSAndroid Build Coastguard Worker {"duplicate type resolution - exact duplicate",
179*9e3b08aeSAndroid Build Coastguard Worker {"abigail_duplicate_types_0.xml",
180*9e3b08aeSAndroid Build Coastguard Worker "abigail_duplicate_types_1.xml"}}),
181*9e3b08aeSAndroid Build Coastguard Worker TidyTestCase(
182*9e3b08aeSAndroid Build Coastguard Worker {"duplicate type resolution - partial duplicate",
183*9e3b08aeSAndroid Build Coastguard Worker {"abigail_duplicate_types_0.xml",
184*9e3b08aeSAndroid Build Coastguard Worker "abigail_duplicate_types_2.xml"}}),
185*9e3b08aeSAndroid Build Coastguard Worker TidyTestCase(
186*9e3b08aeSAndroid Build Coastguard Worker {"duplicate type resolution - multiple partial duplicates",
187*9e3b08aeSAndroid Build Coastguard Worker {"abigail_duplicate_types_0.xml",
188*9e3b08aeSAndroid Build Coastguard Worker "abigail_duplicate_types_3.xml"}}),
189*9e3b08aeSAndroid Build Coastguard Worker TidyTestCase(
190*9e3b08aeSAndroid Build Coastguard Worker {"duplicate type resolution - no maximal duplicate",
191*9e3b08aeSAndroid Build Coastguard Worker {"abigail_duplicate_types_4.xml",
192*9e3b08aeSAndroid Build Coastguard Worker "abigail_duplicate_types_5.xml"}}),
193*9e3b08aeSAndroid Build Coastguard Worker TidyTestCase(
194*9e3b08aeSAndroid Build Coastguard Worker {"duplicate type resolution - different scopes",
195*9e3b08aeSAndroid Build Coastguard Worker {"abigail_duplicate_types_4.xml",
196*9e3b08aeSAndroid Build Coastguard Worker "abigail_duplicate_types_6.xml"}}),
197*9e3b08aeSAndroid Build Coastguard Worker TidyTestCase(
198*9e3b08aeSAndroid Build Coastguard Worker {"duplicate type resolution - stray anonymous member",
199*9e3b08aeSAndroid Build Coastguard Worker {"abigail_duplicate_types_7.xml",
200*9e3b08aeSAndroid Build Coastguard Worker "abigail_duplicate_types_8.xml"}}),
201*9e3b08aeSAndroid Build Coastguard Worker TidyTestCase(
202*9e3b08aeSAndroid Build Coastguard Worker {"corpus group handling",
203*9e3b08aeSAndroid Build Coastguard Worker {"abigail_duplicate_types_0.xml",
204*9e3b08aeSAndroid Build Coastguard Worker "abigail_duplicate_types_9.xml"}}));
205*9e3b08aeSAndroid Build Coastguard Worker
206*9e3b08aeSAndroid Build Coastguard Worker SECTION(test.name) {
207*9e3b08aeSAndroid Build Coastguard Worker // Read inputs.
208*9e3b08aeSAndroid Build Coastguard Worker stg::Graph graph;
209*9e3b08aeSAndroid Build Coastguard Worker std::vector<stg::Id> ids;
210*9e3b08aeSAndroid Build Coastguard Worker ids.reserve(test.files.size());
211*9e3b08aeSAndroid Build Coastguard Worker for (const char* file : test.files) {
212*9e3b08aeSAndroid Build Coastguard Worker ids.push_back(Read(graph, file));
213*9e3b08aeSAndroid Build Coastguard Worker }
214*9e3b08aeSAndroid Build Coastguard Worker
215*9e3b08aeSAndroid Build Coastguard Worker // Useless equality cache.
216*9e3b08aeSAndroid Build Coastguard Worker struct NoCache {
Query__anon5a9898f20111::NoCache217*9e3b08aeSAndroid Build Coastguard Worker static std::optional<bool> Query(const stg::Pair&) {
218*9e3b08aeSAndroid Build Coastguard Worker return std::nullopt;
219*9e3b08aeSAndroid Build Coastguard Worker }
AllSame__anon5a9898f20111::NoCache220*9e3b08aeSAndroid Build Coastguard Worker void AllSame(const std::vector<stg::Pair>&) {}
AllDifferent__anon5a9898f20111::NoCache221*9e3b08aeSAndroid Build Coastguard Worker void AllDifferent(const std::vector<stg::Pair>&) {}
222*9e3b08aeSAndroid Build Coastguard Worker };
223*9e3b08aeSAndroid Build Coastguard Worker
224*9e3b08aeSAndroid Build Coastguard Worker // Check exact equality.
225*9e3b08aeSAndroid Build Coastguard Worker NoCache cache;
226*9e3b08aeSAndroid Build Coastguard Worker for (size_t ix = 1; ix < ids.size(); ++ix) {
227*9e3b08aeSAndroid Build Coastguard Worker CHECK(stg::Equals<NoCache>(graph, cache)(ids[0], ids[ix]));
228*9e3b08aeSAndroid Build Coastguard Worker }
229*9e3b08aeSAndroid Build Coastguard Worker }
230*9e3b08aeSAndroid Build Coastguard Worker }
231*9e3b08aeSAndroid Build Coastguard Worker
232*9e3b08aeSAndroid Build Coastguard Worker } // namespace
233