1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2013-2022 Red Hat, Inc.
5 //
6 // Author: Dodji Seketeli
7
8 /// @file
9 ///
10 /// This program runs a diff between input files and compares the
11 /// resulting report with a reference report. If the resulting report
12 /// is different from the reference report, the test has failed.
13 ///
14 /// The set of input files and reference reports to consider should be
15 /// present in the source distribution.
16
17 #include <string>
18 #include <fstream>
19 #include <iostream>
20 #include <cstdlib>
21 #include "abg-tools-utils.h"
22 #include "abg-reader.h"
23 #include "test-utils.h"
24 #include "abg-comparison.h"
25 #include "abg-corpus.h"
26
27 using std::string;
28 using std::ofstream;
29 using std::cerr;
30
31 struct InOutSpec
32 {
33 const char* first_in_path;
34 const char* second_in_path;
35 const char* ref_diff_path;
36 const char* out_path;
37 };// end struct InOutSpec
38
39 static InOutSpec specs[] =
40 {
41 {
42 "data/test-abidiff/test-enum0-v0.cc.bi",
43 "data/test-abidiff/test-enum0-v1.cc.bi",
44 "data/test-abidiff/test-enum0-report.txt",
45 "output/test-abidiff/test-enum0-report.txt"
46 },
47 {
48 "data/test-abidiff/test-enum1-v0.cc.bi",
49 "data/test-abidiff/test-enum1-v1.cc.bi",
50 "data/test-abidiff/test-enum1-report.txt",
51 "output/test-abidiff/test-enum1-report.txt"
52 },
53 {
54 "data/test-abidiff/test-qual-type0-v0.cc.bi",
55 "data/test-abidiff/test-qual-type0-v1.cc.bi",
56 "data/test-abidiff/test-qual-type0-report.txt",
57 "output/test-abidiff/test-qual-type0-report.txt"
58 },
59 {
60 "data/test-abidiff/test-struct0-v0.cc.bi",
61 "data/test-abidiff/test-struct0-v1.cc.bi",
62 "data/test-abidiff/test-struct0-report.txt",
63 "output/test-abidiff/test-struct0-report.txt"
64 },
65 {
66 "data/test-abidiff/test-struct1-v0.cc.bi",
67 "data/test-abidiff/test-struct1-v1.cc.bi",
68 "data/test-abidiff/test-struct1-report.txt",
69 "output/test-abidiff/test-struct1-report.txt"
70 },
71 {
72 "data/test-abidiff/test-var0-v0.cc.bi",
73 "data/test-abidiff/test-var0-v1.cc.bi",
74 "data/test-abidiff/test-var0-report.txt",
75 "output/test-abidiff/test-var0-report.txt"
76 },
77 {
78 "data/test-abidiff/test-PR18166-libtirpc.so.abi",
79 "data/test-abidiff/test-PR18166-libtirpc.so.abi",
80 "data/test-abidiff/empty-report.txt",
81 "output/test-abidiff/test-PR18166-libtirpc.so.report.txt"
82 },
83 {
84 "data/test-abidiff/test-PR18791-v0.so.abi",
85 "data/test-abidiff/test-PR18791-v1.so.abi",
86 "data/test-abidiff/test-PR18791-report0.txt",
87 "output/test-abidiff/test-PR18791-report0.txt"
88 },
89 {
90 "data/test-abidiff/test-PR24552-v0.abi",
91 "data/test-abidiff/test-PR24552-v1.abi",
92 "data/test-abidiff/empty-report.txt",
93 "output/test-abidiff/test-PR24552-report0.txt"
94 },
95 {
96 "data/test-abidiff/test-empty-corpus-0.xml",
97 "data/test-abidiff/test-empty-corpus-0.xml",
98 "data/test-abidiff/empty-report.txt",
99 "output/test-abidiff/test-empty-corpus-report-0.txt"
100 },
101 {
102 "data/test-abidiff/test-empty-corpus-1.xml",
103 "data/test-abidiff/test-empty-corpus-1.xml",
104 "data/test-abidiff/empty-report.txt",
105 "output/test-abidiff/test-empty-corpus-report-1.txt"
106 },
107 {
108 "data/test-abidiff/test-empty-corpus-2.xml",
109 "data/test-abidiff/test-empty-corpus-2.xml",
110 "data/test-abidiff/empty-report.txt",
111 "output/test-abidiff/test-empty-corpus-report-1.txt"
112 },
113 {
114 "data/test-abidiff/test-crc-0.xml",
115 "data/test-abidiff/test-crc-1.xml",
116 "data/test-abidiff/test-crc-report-0-1.txt",
117 "output/test-abidiff/test-crc-report-0-1.txt"
118 },
119 {
120 "data/test-abidiff/test-crc-1.xml",
121 "data/test-abidiff/test-crc-0.xml",
122 "data/test-abidiff/test-crc-report-1-0.txt",
123 "output/test-abidiff/test-crc-report-1-0.txt"
124 },
125 {
126 "data/test-abidiff/test-crc-1.xml",
127 "data/test-abidiff/test-crc-2.xml",
128 "data/test-abidiff/test-crc-report-1-2.txt",
129 "output/test-abidiff/test-crc-report-1-2.txt"
130 },
131 {
132 "data/test-abidiff/test-namespace-0.xml",
133 "data/test-abidiff/test-namespace-1.xml",
134 "data/test-abidiff/test-namespace-report.txt",
135 "output/test-abidiff/test-namespace-report-0-1.txt"
136 },
137 {
138 "data/test-abidiff/test-PR27616-v0.xml",
139 "data/test-abidiff/test-PR27616-v1.xml",
140 "data/test-abidiff/empty-report.txt",
141 "output/test-abidiff/empty-report.txt"
142 },
143 {
144 "data/test-abidiff/test-PR27616-squished-v0.abi",
145 "data/test-abidiff/test-PR27616-squished-v1.abi",
146 "data/test-abidiff/empty-report.txt",
147 "output/test-abidiff/empty-report.txt"
148 },
149 {
150 "data/test-abidiff/test-PR27985-v0.o.abi",
151 "data/test-abidiff/test-PR27985-v1.o.abi",
152 "data/test-abidiff/test-PR27985-report.txt",
153 "output/test-abidiff/test-PR27985-report.txt"
154 },
155 // This should be the last entry.
156 {0, 0, 0, 0}
157 };
158
159 #define NUM_SPEC_ELEMS \
160 ((sizeof(specs) / sizeof(InOutSpec)) - 1)
161
162 using std::string;
163 using std::cerr;
164 using std::ofstream;
165 using abigail::tools_utils::file_type;
166 using abigail::tools_utils::check_file;
167 using abigail::tools_utils::guess_file_type;
168 using abigail::ir::environment;
169 using abigail::ir::environment_sptr;
170 using abigail::corpus_sptr;
171 using abigail::corpus_group_sptr;
172 using abigail::translation_unit;
173 using abigail::translation_unit_sptr;
174 using abigail::comparison::corpus_diff_sptr;
175 using abigail::comparison::translation_unit_diff_sptr;
176 using abigail::comparison::compute_diff;
177 using abigail::comparison::diff_context_sptr;
178 using abigail::comparison::diff_context;
179
180 using namespace abigail;
181
182 int
main(int,char * [])183 main(int, char*[])
184 {
185 bool is_ok = true;
186
187 string out_path =
188 string(abigail::tests::get_build_dir()) + "/tests/" + specs->out_path;
189 if (!abigail::tools_utils::ensure_parent_dir_created(out_path))
190 {
191 cerr << "Could not create parent director for " << out_path;
192 return 1;
193 }
194
195 string first_in_path, second_in_path, ref_diff_path;
196 for (InOutSpec *s = specs; s->first_in_path; ++s)
197 {
198 first_in_path =
199 string(abigail::tests::get_src_dir()) + "/tests/" + s->first_in_path;
200 second_in_path =
201 string(abigail::tests::get_src_dir()) + "/tests/" + s->second_in_path;
202 ref_diff_path =
203 string(abigail::tests::get_src_dir()) + "/tests/" + s->ref_diff_path;
204 out_path =
205 string(abigail::tests::get_build_dir()) + "/tests/" + s->out_path;
206
207 if (!abigail::tools_utils::ensure_parent_dir_created(out_path))
208 {
209 cerr << "Could not create parent directory for " << out_path;
210 continue;
211 }
212
213 environment env;
214 translation_unit_sptr tu1, tu2;
215 corpus_sptr corpus1, corpus2;
216 corpus_group_sptr corpus_group1, corpus_group2;
217 file_type t = guess_file_type(first_in_path);
218 if (t == abigail::tools_utils::FILE_TYPE_NATIVE_BI)
219 tu1 = abixml::read_translation_unit_from_file(first_in_path, env);
220 else if (t == abigail::tools_utils::FILE_TYPE_XML_CORPUS)
221 corpus1 = abixml::read_corpus_from_abixml_file(first_in_path, env);
222 else if (t == abigail::tools_utils::FILE_TYPE_XML_CORPUS_GROUP)
223 corpus_group1 =
224 abixml::read_corpus_group_from_abixml_file(first_in_path, env);
225 else
226 abort();
227 if (!tu1 && !corpus1 && !corpus_group1)
228 {
229 cerr << "failed to read " << first_in_path << "\n";
230 is_ok = false;
231 continue;
232 }
233
234 t = guess_file_type(second_in_path);
235 if (t == abigail::tools_utils::FILE_TYPE_NATIVE_BI)
236 tu2 = abixml::read_translation_unit_from_file(second_in_path, env);
237 else if (t == abigail::tools_utils::FILE_TYPE_XML_CORPUS)
238 corpus2 = abixml::read_corpus_from_abixml_file(second_in_path, env);
239 else if (t == abigail::tools_utils::FILE_TYPE_XML_CORPUS_GROUP)
240 corpus_group2 =
241 abixml::read_corpus_group_from_abixml_file(first_in_path, env);
242 else
243 abort();
244 if (!tu2 && !corpus2 && !corpus_group2)
245 {
246 cerr << "failed to read " << second_in_path << "\n";
247 is_ok = false;
248 continue;
249 }
250
251 translation_unit_diff_sptr d1;
252 corpus_diff_sptr d2;
253 diff_context_sptr ctxt(new diff_context);
254 ctxt->show_locs(false);
255 if (tu1)
256 d1= compute_diff(tu1, tu2, ctxt);
257 else if (corpus1)
258 d2 = compute_diff(corpus1, corpus2, ctxt);
259 else if (corpus_group1)
260 d2 = compute_diff(corpus_group1, corpus_group2, ctxt);
261 ofstream of(out_path.c_str(), std::ios_base::trunc);
262 if (!of.is_open())
263 {
264 cerr << "failed to read " << s->out_path << "\n";
265 is_ok = false;
266 continue;
267 }
268
269 if (d1)
270 d1->report(of);
271 else
272 d2->report(of);
273 of.close();
274
275 string cmd = "diff -u " + ref_diff_path + " " + out_path;
276 if (system(cmd.c_str()))
277 is_ok = false;
278 }
279
280 return !is_ok;
281 }
282