libabigail/tests/test-write-read-archive.cc
Dodji Seketeli e2d450176b Add a symbol database to the ABI Corpus & support symbol aliases
* include/abg-corpus.h (corpus::{g,s}et_{fun,var}_symbol_map{_sptr}):
	Declare new accessors.
	(corpus::lookup_{variable,function}_symbol): Declare new member
	functions.
	* src/abg-corpus.cc (corpus::{g,s}et_{fun,var}_symbol_map{_sptr}):
	Define new accessors.
	(corpus::lookup_{variable,function}_symbol): Define new member
	functions.
	* include/abg-ir.h (string_elf_symbol_sptr_map_type)
	(string_elf_symbol_sptr_map_sptr, elf_symbols)
	(string_elf_symbols_map_type, string_elf_symbols_map_sptr): New
	convenience typedefs.
	(elf_symbol::{get_main_symbol, is_main_symbol, get_next_alias,
	has_aliases, add_alias, get_id_string,
	get_name_and_version_from_id, operator=}): Declare new member
	functions.
	* src/abg-ir.cc (elf_symbol::{get_main_symbol, is_main_symbol,
	get_next_alias, has_aliases, add_alias, get_id_string,
	get_name_and_version_from_id, operator=}): Define new member
	functions.
	* include/abg-reader.h (read_corpus_from_file): Take a shared
	pointer to corpus.
	* src/abg-reader.cc (read_context::{g,s}et_corpus): Define these.
	(build_elf_symbol_db, build_elf_symbol_from_reference)
	(read_symbol_db_from_input): Define new functions.
	(read_corpus_from_input): Adjust.  Make it read symbol databases.
	(build_elf_symbol): Harden this.
	(build_{var,function}_decl): Read the symbol reference.  Do not
	read the local symbol serialization anymore.
	(read_corpus_from_archive): Adjust.
	(read_corpus_from_file): Take a reference to a shared pointer to
	corpus, rather than a reference to the corpus.
	(read_corpus_from_native_xml): Only keep the overload that returns
	a corpus.  Set the current context with the corpus.
	* src/abg-dwarf-reader.cc (addr_elf_symbol_sptr_map_type)
	(addr_elf_symbol_sptr_map_sptr): New convenience typedefs.
	(read_context::{fun_sym_addr_sym_index_map_,
	var_sym_addr_sym_index_map_): Remove.
	(read_context::{fun,var}_addr_sym_map_): New.  Replace the above
	that got removed.
	(read_context::{var,fun}_syms_): New.
	(read_context::lookup_elf_{fn,var}_symbol_from_address): Adjust.
	(read_context::{fun,var}_addr_sym_map{_sptr}): New.
	(read_context::{fun,var}_syms{_sptr}): New.
	(read_context::load_symbol_maps): Replace
	read_context::load_symbol_addr_to_index_maps.  Adjust to load all
	the new maps.
	(read_context::maybe_load_symbol_maps): New.
	(read_debug_info_into_corpus): Renamed build_corpus into this.
	Update to load symbol maps and set it to the corpus.
	* src/abg-writer.cc (write_context::get_fun_symbol_map): New
	accessor.
	(write_elf_symbol_aliases, write_elf_symbol_reference)
	(write_elf_symbols_table): Define new static functions.
	(write_var_decl): Write the reference to the underlying symbol of
	the variable.  Do not write the full symbol here anymore.
	(write_function_decl):  Likewise, write the reference to the
	underlying symbol of the function.  Do not write the full symbol
	here anymore.
	(write_corpus_to_native_xml): Write the symbol databases at the
	beginning of the corpus document.
	* src/abg-comparison.cc
	(corpus_diff::priv::ensure_lookup_tables_populated): Now that the
	corpus has symbols, check if a the symbol of an allegedly deleted
	function (resp. variable) is deleted; if not, then do not report
	the function (resp. variable) as deleted.  Similarly, check if the
	symbol of an allegedly added function (resp. variable) is added.
	if not, the do not report the function (resp. variable) as added.
	* tests/test-write-read-archive.cc (main): Adjust.
	* tools/biar.cc (extract_tus_from_archive): Likewise.
	* tests/data/test-diff-filter/test9-report.txt: Adjust.
	* tests/data/test-read-dwarf/test0.abi: Likewise.
	* tests/data/test-read-dwarf/test1.abi: Likewise.
	* tests/data/test-read-dwarf/test2.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-05-28 16:33:35 +02:00

193 lines
5.3 KiB
C++

// -*- Mode: C++ -*-
//
// Copyright (C) 2013 Red Hat, Inc.
//
// This file is part of the GNU Application Binary Interface Generic
// Analysis and Instrumentation Library (libabigail). This library is
// free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the
// Free Software Foundation; either version 3, or (at your option) any
// later version.
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Lesser Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this program; see the file COPYING-LGPLV3. If
// not, see <http://www.gnu.org/licenses/>.
#include <cstdlib>
#include <iostream>
#include <fstream>
#include "test-utils.h"
#include "abg-ir.h"
#include "abg-corpus.h"
#include "abg-tools-utils.h"
#include "abg-reader.h"
#include "abg-writer.h"
struct InOutSpec
{
const char* in_path;
const char* out_path;
};// end struct InOutSpec
/// This is an aggregate that specifies where the test gets the
/// elements that it reads to build an archive. It also specifies
/// where to write the output result of the element that is written
/// back to disk, for diffing purposes.
InOutSpec archive_elements[] =
{
{
"data/test-write-read-archive/test0.xml",
"output/test-write-read-archive/test0.xml",
},
{
"data/test-write-read-archive/test1.xml",
"output/test-write-read-archive/test2.xml",
},
{
"data/test-write-read-archive/test2.xml",
"output/test-write-read-archive/test2.xml",
},
{
"data/test-write-read-archive/test3.xml",
"output/test-write-read-archive/test3.xml",
},
{
"data/test-write-read-archive/test4.xml",
"output/test-write-read-archive/test4.xml",
},
// This should be the last entry.
{NULL, NULL}
};
#define NUM_ARCHIVES_ELEMENTS \
((sizeof(archive_elements) / sizeof(InOutSpec)) -1)
/// Where to write the archive, and where to read it from to get the
/// base for the diffing.
const InOutSpec archive_spec =
{
"data/test-write-read-archive/archive.abi",
"output/test-write-read-archive/archive.abi"
};
using std::string;
using std::cerr;
using std::ofstream;
using std::tr1::shared_ptr;
using abigail::corpus;
using abigail::corpus_sptr;
using abigail::translation_unit;
using abigail::xml_reader::read_corpus_from_file;
using abigail::xml_writer::write_corpus_to_archive;
int
main()
{
// Read the elements into abigail::translation_unit and stick them
// into an abigail::corpus.
string in_path, out_path;
bool is_ok = true;
out_path =
abigail::tests::get_build_dir() + "/tests/" + archive_spec.out_path;
if (!abigail::tools::ensure_parent_dir_created(out_path))
{
cerr << "Could not create parent director for " << out_path;
return 1;
}
corpus_sptr abi_corpus(new corpus(out_path));
for (InOutSpec *s = archive_elements; s->in_path; ++s)
{
in_path = abigail::tests::get_src_dir() + "/tests/" + s->in_path;
abigail::translation_unit_sptr tu =
abigail::xml_reader::read_translation_unit_from_file(in_path);
if (!tu)
{
cerr << "failed to read " << in_path << "\n";
is_ok = false;
continue;
}
string file_name;
abigail::tools::base_name(tu->get_path(), file_name);
tu->set_path(file_name);
abi_corpus->add(tu);
}
if (!write_corpus_to_archive(abi_corpus))
{
cerr << "failed to write archive file: " << abi_corpus->get_path();
return 1;
}
// Diff the archive members.
//
// Basically, re-read the corpus from disk, walk the loaded
// translation units, write them back and diff them against their
// reference.
abi_corpus->drop_translation_units();
if (abi_corpus->get_translation_units().size())
{
cerr << "In-memory object of abi corpus at '"
<< abi_corpus->get_path()
<< "' still has translation units after call to "
"corpus::drop_translation_units!";
return false;
}
if (read_corpus_from_file(abi_corpus) != NUM_ARCHIVES_ELEMENTS)
{
cerr << "Failed to load the abi corpus from path '"
<< abi_corpus->get_path()
<< "'";
return 1;
}
if (abi_corpus->get_translation_units().size() != NUM_ARCHIVES_ELEMENTS)
{
cerr << "Read " << abi_corpus->get_translation_units().size()
<< " elements from the abi corpus at "
<< abi_corpus->get_path()
<< " instead of "
<< NUM_ARCHIVES_ELEMENTS
<< "\n";
return 1;
}
for (unsigned i = 0; i < NUM_ARCHIVES_ELEMENTS; ++i)
{
InOutSpec& spec = archive_elements[i];
out_path =
abigail::tests::get_build_dir() + "/tests/" + spec.out_path;
using abigail::xml_writer::write_translation_unit;
bool wrote =
write_translation_unit(*abi_corpus->get_translation_units()[i],
/*indent=*/0, out_path);
if (!wrote)
{
cerr << "Failed to serialize translation_unit to '"
<< out_path
<< "'\n";
is_ok = false;
}
string ref =
abigail::tests::get_src_dir() + "/tests/" + spec.in_path;
string cmd = "diff -u " + ref + " " + out_path;
if (system(cmd.c_str()))
is_ok = false;
}
return !is_ok;
}