libabigail/tests/test-write-read-archive.cc
Dodji Seketeli 18bbfb5ec3 Fix archive writing support
The runtestwritereadarchive test is failing on Rawhide (Fedora 23) for
me now.  It appears it was because the content to write to the zip
archive is in a buffer which is stored in a vector of buffers.

When the vector grows, the buffers are potentially copied over, and
the old buffers are destroyed, making the address of the old buffers
being stalled.  But then those old address are used by the code that
write stuff in the zip archive.  Ooops.

This patch essentially replaces the vector of buffer with a list, so
that growing the list doesn't invalidate the buffers.  The patch also
does away with using deprecated APIs of libzip.

	* configure.ac: Require libzip 0.10.1 at least.
	* src/abg-writer.cc (archive_write_ctxt::serialized_tus): Make
	this be a list<string>, rather than a vector<string>.
	(create_archive_write_context): Truncate the archive if it exists
	already.
	(write_translation_unit_to_archive): Do not use the deprecated
	zip_add() function anymore.  Rather, use zip_file_add().
	* tests/test-write-read-archive.cc (main): Double check if the
	translation unit we read is empty or not.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-04-24 19:59:19 +02:00

193 lines
5.3 KiB
C++

// -*- Mode: C++ -*-
//
// Copyright (C) 2013-2015 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_utils::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 || tu->is_empty())
{
cerr << "failed to read " << in_path << "\n";
is_ok = false;
continue;
}
string file_name;
abigail::tools_utils::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;
}