xref: /aosp_15_r20/external/stg/abigail_reader_test.cc (revision 9e3b08ae94a55201065475453d799e8b1378bea6)
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