Add basic testsuite (using GTest)

(The test suite will only be created if googletest is availavble)
This commit is contained in:
Tobias Frost 2021-02-10 12:09:37 +01:00
parent de6bb75542
commit 76f17ecebb
12 changed files with 298 additions and 0 deletions

View File

@ -28,6 +28,8 @@ cmake_minimum_required( VERSION 3.5 )
project(archive_cpp_wrapper)
include(CTest)
set(CMAKE_CXX_STANDARD 11)
find_package(LibArchive)
@ -88,3 +90,6 @@ install(
# alias target
add_library(LibArchive::archive_cpp_wrapper ALIAS ${PROJECT_NAME})
add_subdirectory(test)

51
test/CMakeLists.txt Normal file
View File

@ -0,0 +1,51 @@
#BSD 2-Clause license
#
#Copyright (c) 2014, Domen Vrankar
#Copyright (c) 2021, Tobias Frost
#All rights reserved.
#
#Redistribution and use in source and binary forms, with or without modification,
#are permitted provided that the following conditions are met:
#
#1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
#2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
#ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
#ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
find_package(GTest)
if(GTEST_FOUND)
add_executable(libarchive_cpp_wrapper_test)
target_sources(libarchive_cpp_wrapper_test
PRIVATE
test.cpp
)
target_link_libraries(libarchive_cpp_wrapper_test
PRIVATE
LibArchive::archive_cpp_wrapper
GTest::gtest_main
)
add_test(NAME libarchive_cpp_wrapper_test COMMAND libarchive_cpp_wrapper_test)
# this avoids that the test fails if it is not built.(cmake will say "not run", not "failed")
set_tests_properties(libarchive_cpp_wrapper_test PROPERTIES REQUIRED_FILES "$<TARGET_FILE:libarchive_cpp_wrapper_test>")
set_tests_properties(libarchive_cpp_wrapper_test
PROPERTIES ENVIRONMENT "TEST_RESOURCES=${CMAKE_CURRENT_SOURCE_DIR}/resources/")
endif()

11
test/resources/README Normal file
View File

@ -0,0 +1,11 @@
The resources in this directory are generated with :
# test1.tar.gz
dd if=/dev/urandom of=file1_random bs=1 count=16k
dd if=/dev/urandom of=file1_random bs=1 count=16k
dd if=/dev/zero of=file3_zero bs=1 count=16k
tar czf test1.tar.gz file*

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
test/resources/file1_random Normal file

Binary file not shown.

BIN
test/resources/file2_random Normal file

Binary file not shown.

BIN
test/resources/file3_zeros Normal file

Binary file not shown.

BIN
test/resources/test1.tar.gz Normal file

Binary file not shown.

BIN
test/resources/test2.tar.gz Normal file

Binary file not shown.

231
test/test.cpp Normal file
View File

@ -0,0 +1,231 @@
/*
* testsuite for libarchive_cpp_wrapper
*
* Created on: Feb 8, 2021
* Author: coldtobi
* LICENSE is BSD-2 clause.
*/
#include "archive_reader.hpp"
#include "archive_writer.hpp"
#include "archive_exception.hpp"
#include <gtest/gtest.h>
#include <string>
#include <set>
#include <stdlib.h>
#include <unistd.h>
#include <fstream>
namespace ar = ns_archive::ns_reader;
class LibArchiveWrapperTest : public testing::Test {
public:
LibArchiveWrapperTest() = default;
virtual ~LibArchiveWrapperTest() {
if (!HasFailure()) {
for (auto const &x : cleanup_files) {
::unlink(x.c_str());
}
}
}
// Let the test know about archives to de deleted after the test
// (will only be deleted if it succeded, not on failures.)
void deleteAfterTest(const std::string &cleanup) {
cleanup_files.insert(cleanup);
}
std::string getResourceDir() {
auto resources = ::getenv("TEST_RESOURCES");
if(!resources) return "";
std::string ret(resources);
if(ret.size() && (ret.at(ret.size()-1) != '/')) { ret += '/'; }
return ret;
}
std::string getcwd() {
auto cwd = ::getcwd(nullptr, 0);
if(!cwd) { return "/tmp/"; }
std::string ret(cwd);
if(ret.size() && (ret.at(ret.size()-1) != '/')) { ret += '/'; }
free(cwd);
return ret;
}
protected:
std::set<std::string> cleanup_files;
};
TEST_F(LibArchiveWrapperTest, TestReadSimpleArchive) {
// Reading an archive.
auto dutarchive = getResourceDir() + "test1.tar.gz";
std::cerr << dutarchive << std::endl;
std::set<std::string> expected_files{"file1_random", "file2_random", "file3_zeros"};
try
{
std::ifstream fs(dutarchive);
ns_archive::reader reader = ns_archive::reader::make_reader<ar::format::_ALL, ar::filter::_ALL>(fs, 32000);
for(auto entry : reader)
{
std::string filename = entry->get_header_value_pathname();
std::string comparefile = getResourceDir() + filename;
bool isdirectory = (filename.size() && filename[filename.size()-1] == '/');
auto it = expected_files.find(filename);
ASSERT_TRUE(it != expected_files.end());
struct stat sb;
auto statret = stat(comparefile.c_str(),&sb);
EXPECT_EQ(0, statret);
EXPECT_TRUE(S_ISDIR(sb.st_mode) == isdirectory);
if (!isdirectory) {
EXPECT_EQ(sb.st_size, entry->get_header_value_size());
auto original = std::ifstream(comparefile, std::ios::in | std::ios::binary);
auto *buf = new char[sb.st_size];
auto *buf2 = new char[sb.st_size];
auto &entrystream = entry->get_stream();
original.read(buf, sb.st_size);
entrystream.read(buf2, sb.st_size);
EXPECT_TRUE(original.good());
EXPECT_TRUE(entrystream.good());
EXPECT_EQ(0,::memcmp(buf, buf2, sb.st_size));
delete[] buf, buf2;
}
expected_files.erase(filename);
}
}
catch(ns_archive::archive_exception& e)
{
ADD_FAILURE() << e.what();
}
EXPECT_EQ(0, expected_files.size());
}
TEST_F(LibArchiveWrapperTest, TestReadDirectoryArchive) {
// Reading an archive.
auto dutarchive = getResourceDir() + "test2.tar.gz";
std::set<std::string> expected_files{"dir/", "dir/file1_random", "dir/file2_random", "dir/file3_zeros"};
try
{
std::ifstream fs(dutarchive);
ns_archive::reader reader = ns_archive::reader::make_reader<ar::format::_ALL, ar::filter::_ALL>(fs, 32000);
for(auto entry : reader)
{
std::string filename = entry->get_header_value_pathname();
std::string comparefile = getResourceDir() + filename;
bool isdirectory = (filename.size() && filename[filename.size()-1] == '/');
auto it = expected_files.find(filename);
ASSERT_TRUE(it != expected_files.end());
struct stat sb;
auto statret = stat(comparefile.c_str(),&sb);
EXPECT_EQ(0, statret);
EXPECT_TRUE(S_ISDIR(sb.st_mode) == isdirectory);
if (!isdirectory) {
EXPECT_EQ(sb.st_size, entry->get_header_value_size());
auto original = std::ifstream(comparefile, std::ios::in | std::ios::binary);
auto *buf = new char[sb.st_size];
auto *buf2 = new char[sb.st_size];
auto &entrystream = entry->get_stream();
original.read(buf, sb.st_size);
entrystream.read(buf2, sb.st_size);
EXPECT_TRUE(original.good());
EXPECT_TRUE(entrystream.good());
EXPECT_EQ(0,::memcmp(buf, buf2, sb.st_size));
delete[] buf, buf2;
}
expected_files.erase(filename);
}
}
catch(ns_archive::archive_exception& e)
{
ADD_FAILURE() << e.what();
}
EXPECT_EQ(0, expected_files.size());
}
TEST_F(LibArchiveWrapperTest, TestCreateDirectoryArchive) {
auto dutarchive = getcwd() + "test_create.tar.gz";
std::cerr << "DUT: " << dutarchive << std::endl;
std::set<std::string> expected_files{"dir/file1_random", "dir/file2_random", "dir/file3_zeros"};
// Create an archive.
try {
std::ofstream outfs(dutarchive, std::ios::trunc | std::ios::out);
ns_archive::writer writer = ns_archive::writer::make_writer<ns_archive::ns_writer::format::_TAR, ns_archive::ns_writer::filter::_GZIP>(outfs, 10240);
for(const auto& x: expected_files) {
std::ifstream file(getResourceDir() + x);
ASSERT_TRUE(file.good());
ns_archive::entry out_entry(file);
out_entry.set_header_value_pathname(x);
writer.add_entry(out_entry);
}
} catch (ns_archive::archive_exception& e)
{
ADD_FAILURE() << e.what();
}
// Read back the archive and compare the files.
try
{
std::ifstream fs(dutarchive);
deleteAfterTest(dutarchive);
ns_archive::reader reader = ns_archive::reader::make_reader<ar::format::_ALL, ar::filter::_ALL>(fs, 32000);
for(auto entry : reader)
{
std::string filename = entry->get_header_value_pathname();
std::string comparefile = getResourceDir() + filename;
bool isdirectory = (filename.size() && filename[filename.size()-1] == '/');
auto it = expected_files.find(filename);
ASSERT_TRUE(it != expected_files.end());
struct stat sb;
auto statret = stat(comparefile.c_str(),&sb);
EXPECT_EQ(0, statret);
EXPECT_TRUE(S_ISDIR(sb.st_mode) == isdirectory);
if (!isdirectory) {
EXPECT_EQ(sb.st_size, entry->get_header_value_size());
auto original = std::ifstream(comparefile, std::ios::in | std::ios::binary);
auto *buf = new char[sb.st_size];
auto *buf2 = new char[sb.st_size];
auto &entrystream = entry->get_stream();
original.read(buf, sb.st_size);
entrystream.read(buf2, sb.st_size);
EXPECT_TRUE(original.good());
EXPECT_TRUE(entrystream.good());
EXPECT_EQ(0,::memcmp(buf, buf2, sb.st_size));
delete[] buf, buf2;
}
expected_files.erase(filename);
}
}
catch(ns_archive::archive_exception& e)
{
ADD_FAILURE() << e.what() << " Archive: " << dutarchive;
}
EXPECT_EQ(0, expected_files.size());
std::cerr << dutarchive << std::endl;
}