1e01aa904Sopenharmony_ci// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2e01aa904Sopenharmony_ci// -*- Mode: C++ -*-
3e01aa904Sopenharmony_ci//
4e01aa904Sopenharmony_ci// Copyright (C) 2013-2022 Red Hat, Inc.
5e01aa904Sopenharmony_ci
6e01aa904Sopenharmony_ci/// @file read an XML corpus file (in the native Abigail XML format),
7e01aa904Sopenharmony_ci/// save it back and diff the resulting XML file against the input
8e01aa904Sopenharmony_ci/// file.  They should be identical.
9e01aa904Sopenharmony_ci
10e01aa904Sopenharmony_ci#include <cstdlib>
11e01aa904Sopenharmony_ci#include <cstring>
12e01aa904Sopenharmony_ci#include <fstream>
13e01aa904Sopenharmony_ci#include <iostream>
14e01aa904Sopenharmony_ci#include <memory>
15e01aa904Sopenharmony_ci#include <string>
16e01aa904Sopenharmony_ci#include <vector>
17e01aa904Sopenharmony_ci#include "abg-ir.h"
18e01aa904Sopenharmony_ci#include "abg-reader.h"
19e01aa904Sopenharmony_ci#include "abg-writer.h"
20e01aa904Sopenharmony_ci#include "abg-workers.h"
21e01aa904Sopenharmony_ci#include "abg-tools-utils.h"
22e01aa904Sopenharmony_ci#include "test-utils.h"
23e01aa904Sopenharmony_ci
24e01aa904Sopenharmony_ciusing std::string;
25e01aa904Sopenharmony_ciusing std::vector;
26e01aa904Sopenharmony_ciusing std::ofstream;
27e01aa904Sopenharmony_ciusing std::cerr;
28e01aa904Sopenharmony_ci
29e01aa904Sopenharmony_ciusing std::dynamic_pointer_cast;
30e01aa904Sopenharmony_ci
31e01aa904Sopenharmony_ciusing abigail::tools_utils::file_type;
32e01aa904Sopenharmony_ciusing abigail::tools_utils::check_file;
33e01aa904Sopenharmony_ciusing abigail::tools_utils::guess_file_type;
34e01aa904Sopenharmony_ciusing abigail::tests::get_build_dir;
35e01aa904Sopenharmony_ciusing abigail::ir::environment;
36e01aa904Sopenharmony_ciusing abigail::ir::environment_sptr;
37e01aa904Sopenharmony_ciusing abigail::translation_unit_sptr;
38e01aa904Sopenharmony_ciusing abigail::corpus_sptr;
39e01aa904Sopenharmony_ci
40e01aa904Sopenharmony_ciusing abigail::workers::queue;
41e01aa904Sopenharmony_ciusing abigail::workers::task;
42e01aa904Sopenharmony_ciusing abigail::workers::task_sptr;
43e01aa904Sopenharmony_ciusing abigail::workers::get_number_of_threads;
44e01aa904Sopenharmony_ci
45e01aa904Sopenharmony_ci/// This is an aggregate that specifies where a test shall get its
46e01aa904Sopenharmony_ci/// input from, and where it shall write its ouput to.
47e01aa904Sopenharmony_cistruct InOutSpec
48e01aa904Sopenharmony_ci{
49e01aa904Sopenharmony_ci  const char* in_path;
50e01aa904Sopenharmony_ci  const char* in_suppr_spec_path;
51e01aa904Sopenharmony_ci  const char* ref_out_path;
52e01aa904Sopenharmony_ci  const char* out_path;
53e01aa904Sopenharmony_ci};// end struct InOutSpec
54e01aa904Sopenharmony_ci
55e01aa904Sopenharmony_ci
56e01aa904Sopenharmony_ciInOutSpec in_out_specs[] =
57e01aa904Sopenharmony_ci{
58e01aa904Sopenharmony_ci  {
59e01aa904Sopenharmony_ci    "data/test-read-write/test0.xml",
60e01aa904Sopenharmony_ci    "",
61e01aa904Sopenharmony_ci    "data/test-read-write/test0.xml",
62e01aa904Sopenharmony_ci    "output/test-read-write/test0.xml"
63e01aa904Sopenharmony_ci  },
64e01aa904Sopenharmony_ci  {
65e01aa904Sopenharmony_ci    "data/test-read-write/test1.xml",
66e01aa904Sopenharmony_ci    "",
67e01aa904Sopenharmony_ci    "data/test-read-write/test1.xml",
68e01aa904Sopenharmony_ci    "output/test-read-write/test1.xml"
69e01aa904Sopenharmony_ci  },
70e01aa904Sopenharmony_ci  {
71e01aa904Sopenharmony_ci    "data/test-read-write/test2.xml",
72e01aa904Sopenharmony_ci    "",
73e01aa904Sopenharmony_ci    "data/test-read-write/test2.xml",
74e01aa904Sopenharmony_ci    "output/test-read-write/test2.xml"
75e01aa904Sopenharmony_ci  },
76e01aa904Sopenharmony_ci  {
77e01aa904Sopenharmony_ci    "data/test-read-write/test3.xml",
78e01aa904Sopenharmony_ci    "",
79e01aa904Sopenharmony_ci    "data/test-read-write/test3.xml",
80e01aa904Sopenharmony_ci    "output/test-read-write/test3.xml"
81e01aa904Sopenharmony_ci  },
82e01aa904Sopenharmony_ci  {
83e01aa904Sopenharmony_ci    "data/test-read-write/test4.xml",
84e01aa904Sopenharmony_ci    "",
85e01aa904Sopenharmony_ci    "data/test-read-write/test4.xml",
86e01aa904Sopenharmony_ci    "output/test-read-write/test4.xml"
87e01aa904Sopenharmony_ci  },
88e01aa904Sopenharmony_ci  {
89e01aa904Sopenharmony_ci    "data/test-read-write/test5.xml",
90e01aa904Sopenharmony_ci    "",
91e01aa904Sopenharmony_ci    "data/test-read-write/test5.xml",
92e01aa904Sopenharmony_ci    "output/test-read-write/test5.xml"
93e01aa904Sopenharmony_ci  },
94e01aa904Sopenharmony_ci  {
95e01aa904Sopenharmony_ci    "data/test-read-write/test6.xml",
96e01aa904Sopenharmony_ci    "",
97e01aa904Sopenharmony_ci    "data/test-read-write/test6.xml",
98e01aa904Sopenharmony_ci    "output/test-read-write/test6.xml"
99e01aa904Sopenharmony_ci  },
100e01aa904Sopenharmony_ci  {
101e01aa904Sopenharmony_ci    "data/test-read-write/test7.xml",
102e01aa904Sopenharmony_ci    "",
103e01aa904Sopenharmony_ci    "data/test-read-write/test7.xml",
104e01aa904Sopenharmony_ci    "output/test-read-write/test7.xml"
105e01aa904Sopenharmony_ci  },
106e01aa904Sopenharmony_ci  {
107e01aa904Sopenharmony_ci    "data/test-read-write/test8.xml",
108e01aa904Sopenharmony_ci    "",
109e01aa904Sopenharmony_ci    "data/test-read-write/test8.xml",
110e01aa904Sopenharmony_ci    "output/test-read-write/test8.xml"
111e01aa904Sopenharmony_ci  },
112e01aa904Sopenharmony_ci  {
113e01aa904Sopenharmony_ci    "data/test-read-write/test9.xml",
114e01aa904Sopenharmony_ci    "",
115e01aa904Sopenharmony_ci    "data/test-read-write/test9.xml",
116e01aa904Sopenharmony_ci    "output/test-read-write/test9.xml"
117e01aa904Sopenharmony_ci  },
118e01aa904Sopenharmony_ci  {
119e01aa904Sopenharmony_ci    "data/test-read-write/test10.xml",
120e01aa904Sopenharmony_ci    "",
121e01aa904Sopenharmony_ci    "data/test-read-write/test10.xml",
122e01aa904Sopenharmony_ci    "output/test-read-write/test10.xml"
123e01aa904Sopenharmony_ci  },
124e01aa904Sopenharmony_ci  {
125e01aa904Sopenharmony_ci    "data/test-read-write/test11.xml",
126e01aa904Sopenharmony_ci    "",
127e01aa904Sopenharmony_ci    "data/test-read-write/test11.xml",
128e01aa904Sopenharmony_ci    "output/test-read-write/test11.xml"
129e01aa904Sopenharmony_ci  },
130e01aa904Sopenharmony_ci  {
131e01aa904Sopenharmony_ci    "data/test-read-write/test12.xml",
132e01aa904Sopenharmony_ci    "",
133e01aa904Sopenharmony_ci    "data/test-read-write/test12.xml",
134e01aa904Sopenharmony_ci    "output/test-read-write/test12.xml"
135e01aa904Sopenharmony_ci  },
136e01aa904Sopenharmony_ci  {
137e01aa904Sopenharmony_ci    "data/test-read-write/test13.xml",
138e01aa904Sopenharmony_ci    "",
139e01aa904Sopenharmony_ci    "data/test-read-write/test13.xml",
140e01aa904Sopenharmony_ci    "output/test-read-write/test13.xml"
141e01aa904Sopenharmony_ci  },
142e01aa904Sopenharmony_ci  {
143e01aa904Sopenharmony_ci    "data/test-read-write/test14.xml",
144e01aa904Sopenharmony_ci    "",
145e01aa904Sopenharmony_ci    "data/test-read-write/test14.xml",
146e01aa904Sopenharmony_ci    "output/test-read-write/test14.xml"
147e01aa904Sopenharmony_ci  },
148e01aa904Sopenharmony_ci  {
149e01aa904Sopenharmony_ci    "data/test-read-write/test15.xml",
150e01aa904Sopenharmony_ci    "",
151e01aa904Sopenharmony_ci    "data/test-read-write/test15.xml",
152e01aa904Sopenharmony_ci    "output/test-read-write/test15.xml"
153e01aa904Sopenharmony_ci  },
154e01aa904Sopenharmony_ci  {
155e01aa904Sopenharmony_ci    "data/test-read-write/test16.xml",
156e01aa904Sopenharmony_ci    "",
157e01aa904Sopenharmony_ci    "data/test-read-write/test16.xml",
158e01aa904Sopenharmony_ci    "output/test-read-write/test16.xml"
159e01aa904Sopenharmony_ci  },
160e01aa904Sopenharmony_ci  {
161e01aa904Sopenharmony_ci    "data/test-read-write/test17.xml",
162e01aa904Sopenharmony_ci    "",
163e01aa904Sopenharmony_ci    "data/test-read-write/test17.xml",
164e01aa904Sopenharmony_ci    "output/test-read-write/test17.xml"
165e01aa904Sopenharmony_ci  },
166e01aa904Sopenharmony_ci  {
167e01aa904Sopenharmony_ci    "data/test-read-write/test18.xml",
168e01aa904Sopenharmony_ci    "",
169e01aa904Sopenharmony_ci    "data/test-read-write/test18.xml",
170e01aa904Sopenharmony_ci    "output/test-read-write/test18.xml"
171e01aa904Sopenharmony_ci  },
172e01aa904Sopenharmony_ci  {
173e01aa904Sopenharmony_ci    "data/test-read-write/test19.xml",
174e01aa904Sopenharmony_ci    "",
175e01aa904Sopenharmony_ci    "data/test-read-write/test19.xml",
176e01aa904Sopenharmony_ci    "output/test-read-write/test19.xml"
177e01aa904Sopenharmony_ci  },
178e01aa904Sopenharmony_ci  {
179e01aa904Sopenharmony_ci    "data/test-read-write/test20.xml",
180e01aa904Sopenharmony_ci    "",
181e01aa904Sopenharmony_ci    "data/test-read-write/test20.xml",
182e01aa904Sopenharmony_ci    "output/test-read-write/test20.xml"
183e01aa904Sopenharmony_ci  },
184e01aa904Sopenharmony_ci  {
185e01aa904Sopenharmony_ci    "data/test-read-write/test21.xml",
186e01aa904Sopenharmony_ci    "",
187e01aa904Sopenharmony_ci    "data/test-read-write/test21.xml",
188e01aa904Sopenharmony_ci    "output/test-read-write/test21.xml"
189e01aa904Sopenharmony_ci  },
190e01aa904Sopenharmony_ci  {
191e01aa904Sopenharmony_ci    "data/test-read-write/test22.xml",
192e01aa904Sopenharmony_ci    "",
193e01aa904Sopenharmony_ci    "data/test-read-write/test22.xml",
194e01aa904Sopenharmony_ci    "output/test-read-write/test22.xml"
195e01aa904Sopenharmony_ci  },
196e01aa904Sopenharmony_ci  {
197e01aa904Sopenharmony_ci    "data/test-read-write/test23.xml",
198e01aa904Sopenharmony_ci    "",
199e01aa904Sopenharmony_ci    "data/test-read-write/test23.xml",
200e01aa904Sopenharmony_ci    "output/test-read-write/test23.xml"
201e01aa904Sopenharmony_ci  },
202e01aa904Sopenharmony_ci  {
203e01aa904Sopenharmony_ci    "data/test-read-write/test24.xml",
204e01aa904Sopenharmony_ci    "",
205e01aa904Sopenharmony_ci    "data/test-read-write/test24.xml",
206e01aa904Sopenharmony_ci    "output/test-read-write/test24.xml"
207e01aa904Sopenharmony_ci  },
208e01aa904Sopenharmony_ci  {
209e01aa904Sopenharmony_ci    "data/test-read-write/test25.xml",
210e01aa904Sopenharmony_ci    "",
211e01aa904Sopenharmony_ci    "data/test-read-write/test25.xml",
212e01aa904Sopenharmony_ci    "output/test-read-write/test25.xml"
213e01aa904Sopenharmony_ci  },
214e01aa904Sopenharmony_ci  {
215e01aa904Sopenharmony_ci    "data/test-read-write/test26.xml",
216e01aa904Sopenharmony_ci    "",
217e01aa904Sopenharmony_ci    "data/test-read-write/test26.xml",
218e01aa904Sopenharmony_ci    "output/test-read-write/test26.xml"
219e01aa904Sopenharmony_ci  },
220e01aa904Sopenharmony_ci  {
221e01aa904Sopenharmony_ci    "data/test-read-write/test27.xml",
222e01aa904Sopenharmony_ci    "",
223e01aa904Sopenharmony_ci    "data/test-read-write/test27.xml",
224e01aa904Sopenharmony_ci    "output/test-read-write/test27.xml"
225e01aa904Sopenharmony_ci  },
226e01aa904Sopenharmony_ci  {
227e01aa904Sopenharmony_ci    "data/test-read-write/test28.xml",
228e01aa904Sopenharmony_ci    "data/test-read-write/test28-drop-std-fns.abignore",
229e01aa904Sopenharmony_ci    "data/test-read-write/test28-without-std-fns-ref.xml",
230e01aa904Sopenharmony_ci    "output/test-read-write/test28-without-std-fns.xml"
231e01aa904Sopenharmony_ci  },
232e01aa904Sopenharmony_ci  {
233e01aa904Sopenharmony_ci    "data/test-read-write/test28.xml",
234e01aa904Sopenharmony_ci    "data/test-read-write/test28-drop-std-vars.abignore",
235e01aa904Sopenharmony_ci    "data/test-read-write/test28-without-std-vars-ref.xml",
236e01aa904Sopenharmony_ci    "output/test-read-write/test28-without-std-vars.xml"
237e01aa904Sopenharmony_ci  },
238e01aa904Sopenharmony_ci  {
239e01aa904Sopenharmony_ci    "data/test-read-write/test-crc.xml",
240e01aa904Sopenharmony_ci    "",
241e01aa904Sopenharmony_ci    "data/test-read-write/test-crc.xml",
242e01aa904Sopenharmony_ci    "output/test-read-write/test-crc.xml",
243e01aa904Sopenharmony_ci  },
244e01aa904Sopenharmony_ci  // This should be the last entry.
245e01aa904Sopenharmony_ci  {NULL, NULL, NULL, NULL}
246e01aa904Sopenharmony_ci};
247e01aa904Sopenharmony_ci
248e01aa904Sopenharmony_ci/// A task wihch reads an abixml file using abilint and compares its
249e01aa904Sopenharmony_ci/// output against a reference output.
250e01aa904Sopenharmony_cistruct test_task : public abigail::workers::task
251e01aa904Sopenharmony_ci{
252e01aa904Sopenharmony_ci  InOutSpec spec;
253e01aa904Sopenharmony_ci  bool is_ok;
254e01aa904Sopenharmony_ci  string in_path, out_path, in_suppr_spec_path, ref_out_path;
255e01aa904Sopenharmony_ci  string diff_cmd, error_message;
256e01aa904Sopenharmony_ci
257e01aa904Sopenharmony_ci  /// Constructor of the task.
258e01aa904Sopenharmony_ci  ///
259e01aa904Sopenharmony_ci  /// @param the spec of where to find the abixml file to read and the
260e01aa904Sopenharmony_ci  /// reference output of the test.
261e01aa904Sopenharmony_ci  test_task( InOutSpec& s)
262e01aa904Sopenharmony_ci    : spec(s),
263e01aa904Sopenharmony_ci      is_ok(true)
264e01aa904Sopenharmony_ci  {}
265e01aa904Sopenharmony_ci
266e01aa904Sopenharmony_ci  /// This method defines what the task performs.
267e01aa904Sopenharmony_ci  virtual void
268e01aa904Sopenharmony_ci  perform()
269e01aa904Sopenharmony_ci  {
270e01aa904Sopenharmony_ci    string input_suffix(spec.in_path);
271e01aa904Sopenharmony_ci    in_path =
272e01aa904Sopenharmony_ci      string(abigail::tests::get_src_dir()) + "/tests/" + input_suffix;
273e01aa904Sopenharmony_ci
274e01aa904Sopenharmony_ci    if (!check_file(in_path, cerr))
275e01aa904Sopenharmony_ci      {
276e01aa904Sopenharmony_ci	is_ok = false;
277e01aa904Sopenharmony_ci	return;
278e01aa904Sopenharmony_ci      }
279e01aa904Sopenharmony_ci
280e01aa904Sopenharmony_ci    string ref_out_path_suffix(spec.ref_out_path);
281e01aa904Sopenharmony_ci    ref_out_path =
282e01aa904Sopenharmony_ci      string(abigail::tests::get_src_dir())
283e01aa904Sopenharmony_ci      + "/tests/" + ref_out_path_suffix;
284e01aa904Sopenharmony_ci
285e01aa904Sopenharmony_ci    if (!check_file(ref_out_path, cerr))
286e01aa904Sopenharmony_ci      {
287e01aa904Sopenharmony_ci	is_ok = false;
288e01aa904Sopenharmony_ci	return;
289e01aa904Sopenharmony_ci      }
290e01aa904Sopenharmony_ci
291e01aa904Sopenharmony_ci    if (spec.in_suppr_spec_path && strcmp(spec.in_suppr_spec_path, ""))
292e01aa904Sopenharmony_ci      {
293e01aa904Sopenharmony_ci	in_suppr_spec_path = string(spec.in_suppr_spec_path);
294e01aa904Sopenharmony_ci	in_suppr_spec_path =
295e01aa904Sopenharmony_ci	  string(abigail::tests::get_src_dir())
296e01aa904Sopenharmony_ci	  + "/tests/"
297e01aa904Sopenharmony_ci	  + in_suppr_spec_path;
298e01aa904Sopenharmony_ci      }
299e01aa904Sopenharmony_ci    else
300e01aa904Sopenharmony_ci      in_suppr_spec_path.clear();
301e01aa904Sopenharmony_ci
302e01aa904Sopenharmony_ci    environment_sptr env(new environment);
303e01aa904Sopenharmony_ci    translation_unit_sptr tu;
304e01aa904Sopenharmony_ci    corpus_sptr corpus;
305e01aa904Sopenharmony_ci
306e01aa904Sopenharmony_ci    file_type t = guess_file_type(in_path);
307e01aa904Sopenharmony_ci    if (t == abigail::tools_utils::FILE_TYPE_UNKNOWN)
308e01aa904Sopenharmony_ci      {
309e01aa904Sopenharmony_ci	cerr << in_path << "is an unknown file type\n";
310e01aa904Sopenharmony_ci	is_ok = false;
311e01aa904Sopenharmony_ci	return;
312e01aa904Sopenharmony_ci      }
313e01aa904Sopenharmony_ci
314e01aa904Sopenharmony_ci    string output_suffix(spec.out_path);
315e01aa904Sopenharmony_ci    out_path =
316e01aa904Sopenharmony_ci      string(abigail::tests::get_build_dir()) + "/tests/" + output_suffix;
317e01aa904Sopenharmony_ci    if (!abigail::tools_utils::ensure_parent_dir_created(out_path))
318e01aa904Sopenharmony_ci      {
319e01aa904Sopenharmony_ci	error_message =
320e01aa904Sopenharmony_ci	  "Could not create parent director for " + out_path;
321e01aa904Sopenharmony_ci	is_ok = false;
322e01aa904Sopenharmony_ci	return;
323e01aa904Sopenharmony_ci      }
324e01aa904Sopenharmony_ci
325e01aa904Sopenharmony_ci    string abilint = string(get_build_dir()) + "/tools/abilint";
326e01aa904Sopenharmony_ci    if (!in_suppr_spec_path.empty())
327e01aa904Sopenharmony_ci      abilint +=string(" --suppr ") + in_suppr_spec_path;
328e01aa904Sopenharmony_ci    string cmd = abilint + " " + in_path + " > " + out_path;
329e01aa904Sopenharmony_ci
330e01aa904Sopenharmony_ci    if (system(cmd.c_str()))
331e01aa904Sopenharmony_ci      {
332e01aa904Sopenharmony_ci	error_message =
333e01aa904Sopenharmony_ci	  "ABI XML file doesn't pass abilint: " + out_path + "\n";
334e01aa904Sopenharmony_ci	is_ok = false;
335e01aa904Sopenharmony_ci      }
336e01aa904Sopenharmony_ci
337e01aa904Sopenharmony_ci    cmd = "diff -u " + ref_out_path + " " + out_path;
338e01aa904Sopenharmony_ci    diff_cmd = cmd;
339e01aa904Sopenharmony_ci    if (system(cmd.c_str()))
340e01aa904Sopenharmony_ci      is_ok = false;
341e01aa904Sopenharmony_ci  }
342e01aa904Sopenharmony_ci};// end struct test_task
343e01aa904Sopenharmony_ci
344e01aa904Sopenharmony_ci/// A convenience typedef for shared
345e01aa904Sopenharmony_citypedef shared_ptr<test_task> test_task_sptr;
346e01aa904Sopenharmony_ci
347e01aa904Sopenharmony_ci/// Walk the array of InOutSpecs above, read the input files it points
348e01aa904Sopenharmony_ci/// to, write it into the output it points to and diff them.
349e01aa904Sopenharmony_ciint
350e01aa904Sopenharmony_cimain()
351e01aa904Sopenharmony_ci{
352e01aa904Sopenharmony_ci  using abigail::workers::queue;
353e01aa904Sopenharmony_ci  using abigail::workers::task;
354e01aa904Sopenharmony_ci  using abigail::workers::task_sptr;
355e01aa904Sopenharmony_ci  using abigail::workers::get_number_of_threads;
356e01aa904Sopenharmony_ci
357e01aa904Sopenharmony_ci  const size_t num_tests = sizeof(in_out_specs) / sizeof (InOutSpec) - 1;
358e01aa904Sopenharmony_ci  size_t num_workers = std::min(get_number_of_threads(), num_tests);
359e01aa904Sopenharmony_ci  queue task_queue(num_workers);
360e01aa904Sopenharmony_ci
361e01aa904Sopenharmony_ci  bool is_ok = true;
362e01aa904Sopenharmony_ci
363e01aa904Sopenharmony_ci
364e01aa904Sopenharmony_ci  string in_path, out_path, in_suppr_spec_path, ref_out_path;
365e01aa904Sopenharmony_ci  for (InOutSpec* s = in_out_specs; s->in_path; ++s)
366e01aa904Sopenharmony_ci    {
367e01aa904Sopenharmony_ci      test_task_sptr t(new test_task(*s));
368e01aa904Sopenharmony_ci      ABG_ASSERT(task_queue.schedule_task(t));
369e01aa904Sopenharmony_ci    }
370e01aa904Sopenharmony_ci
371e01aa904Sopenharmony_ci  /// Wait for all worker threads to finish their job, and wind down.
372e01aa904Sopenharmony_ci  task_queue.wait_for_workers_to_complete();
373e01aa904Sopenharmony_ci
374e01aa904Sopenharmony_ci  // Now walk the results and print whatever error messages need to be
375e01aa904Sopenharmony_ci  // printed.
376e01aa904Sopenharmony_ci
377e01aa904Sopenharmony_ci  const vector<task_sptr>& completed_tasks =
378e01aa904Sopenharmony_ci    task_queue.get_completed_tasks();
379e01aa904Sopenharmony_ci
380e01aa904Sopenharmony_ci  ABG_ASSERT(completed_tasks.size() == num_tests);
381e01aa904Sopenharmony_ci
382e01aa904Sopenharmony_ci  for (vector<task_sptr>::const_iterator ti = completed_tasks.begin();
383e01aa904Sopenharmony_ci       ti != completed_tasks.end();
384e01aa904Sopenharmony_ci       ++ti)
385e01aa904Sopenharmony_ci    {
386e01aa904Sopenharmony_ci      test_task_sptr t = dynamic_pointer_cast<test_task>(*ti);
387e01aa904Sopenharmony_ci      if (!t->is_ok)
388e01aa904Sopenharmony_ci	{
389e01aa904Sopenharmony_ci	  is_ok = false;
390e01aa904Sopenharmony_ci
391e01aa904Sopenharmony_ci	  if (!t->error_message.empty())
392e01aa904Sopenharmony_ci	    cerr << t->error_message << '\n';
393e01aa904Sopenharmony_ci
394e01aa904Sopenharmony_ci	  if (!t->diff_cmd.empty())
395e01aa904Sopenharmony_ci	    if (system(t->diff_cmd.c_str()) == -1)
396e01aa904Sopenharmony_ci	      cerr << "execution of '" << t->diff_cmd << "' failed\n";
397e01aa904Sopenharmony_ci	}
398e01aa904Sopenharmony_ci    }
399e01aa904Sopenharmony_ci
400e01aa904Sopenharmony_ci  return !is_ok;
401e01aa904Sopenharmony_ci}
402