Merge 76f17ecebb7bcfe4f28da52be11299591e126128 into d43d358b044889b17501840ca60fadaa8bdb007d

This commit is contained in:
Tobias Frost 2021-02-10 12:24:50 +01:00 committed by GitHub
commit bd41ccf058
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 312 additions and 10 deletions

View File

@ -24,23 +24,23 @@
#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
cmake_minimum_required( VERSION 2.8.12 )
cmake_minimum_required( VERSION 3.5 )
project(archive_cpp_wrapper)
if(NOT libarchive_LIBRARIES)
# set defaults for ubuntu
set( libarchive_LIBRARIES "/usr/lib/x86_64-linux-gnu/libarchive.so" )
set( libarchive_INCLUDE_DIRS "" )
endif()
include(CTest)
set(CMAKE_CXX_STANDARD 11)
find_package(LibArchive)
add_library(LibArchive::LibArchive INTERFACE IMPORTED GLOBAL)
target_include_directories(LibArchive::LibArchive INTERFACE ${LibArchive_INCLUDE_DIRS})
target_link_libraries(LibArchive::LibArchive INTERFACE ${LibArchive_LIBRARIES})
set(CMAKE_CXX_FLAGS "-Wall -std=c++11")
file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp")
file(GLOB template_implementations "${CMAKE_CURRENT_SOURCE_DIR}/*.ipp")
include_directories( ${libarchive_INCLUDE_DIRS} )
add_library( ${PROJECT_NAME} SHARED
archive_entry.cpp
@ -57,7 +57,9 @@ add_library( ${PROJECT_NAME} SHARED
${template_implementations}
)
target_link_libraries( ${PROJECT_NAME} ${libarchive_LIBRARIES} )
target_link_libraries( ${PROJECT_NAME} PRIVATE LibArchive::LibArchive )
target_include_directories(${PROJECT_NAME} PRIVATE ${libarchive_INCLUDE_DIRS} )
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} )
set_target_properties( ${PROJECT_NAME} PROPERTIES VERSION "1.0.0" SOVERSION "1" )
@ -84,3 +86,10 @@ install(
DESTINATION include
)
# 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;
}