Skip to content

Commit 1ddf0f1

Browse files
Add pkg_editor unit tests with random files of varying sizes
This commit adds randomness to the pkg_editor unit tests that deal with packing and unpacking files. This ensures that we can cover all file sizes and all types of file contents and improves the robustness of our pkg_editor code.
1 parent 9012ffe commit 1ddf0f1

File tree

2 files changed

+78
-9
lines changed

2 files changed

+78
-9
lines changed

lib/pkg_editor/test/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33

44
add_executable(pkg_editor_test pkg_editor_test.cpp)
55
target_link_libraries(pkg_editor_test PRIVATE CppUTest pkg_editor)
6+
7+
# This section can be removed once the minimum required version of GCC has been raised to 9
8+
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
9+
target_link_libraries(pkg_editor_test PRIVATE stdc++fs)
10+
endif()
11+
612
add_test(pkg_editor_test pkg_editor_test -v)
713

814
if(ZLIB_FOUND)

lib/pkg_editor/test/pkg_editor_test.cpp

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,17 @@
1212
#pragma warning(pop)
1313
#endif
1414

15+
// Replace this library with <filesystem> once we move to GCC 8 or newer
16+
// versions
17+
#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING 1
18+
#include <experimental/filesystem>
19+
20+
#include <climits>
21+
#include <random>
1522
#include <stdio.h>
1623
#include <stdlib.h>
1724
#include <string.h>
25+
#include <string>
1826

1927
#include "pkg_editor/pkg_editor.h"
2028
#include <assert.h>
@@ -40,6 +48,11 @@
4048
#define PACK_UNPACK_FILE ".pack_unpack"
4149
#define PACK_UNPACK_DIR ".pack_unpack_dir"
4250

51+
using random_bytes_engine =
52+
std::independent_bits_engine<std::default_random_engine, CHAR_BIT,
53+
unsigned int>;
54+
namespace fs = std::experimental::filesystem::v1;
55+
4356
static void l_remove_file(const char *filename) {
4457
#ifdef _WIN32
4558
_unlink(filename);
@@ -379,7 +392,7 @@ TEST(package, pack) {
379392
CHECK_EQUAL(1, result);
380393
}
381394

382-
static bool files_same(const char *f1, const char *f2) {
395+
static bool files_same(const fs::path f1, const fs::path f2) {
383396
std::ifstream file1(f1, std::ifstream::ate | std::ifstream::binary);
384397
std::ifstream file2(f2, std::ifstream::ate | std::ifstream::binary);
385398
file1.exceptions(std::ifstream::failbit | std::ifstream::badbit);
@@ -398,11 +411,55 @@ static bool files_same(const char *f1, const char *f2) {
398411
return std::equal(begin1, std::istreambuf_iterator<char>(), begin2);
399412
}
400413

414+
static void generate_random_file(const fs::path &name, size_t size) {
415+
random_bytes_engine rbe;
416+
std::ofstream file(name);
417+
file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
418+
std::generate_n(std::ostreambuf_iterator<char>(file), size,
419+
[&] { return (char)rbe(); });
420+
}
421+
422+
// Creates a folder consisting of a certain number of files with random contents
423+
// and random sizes
424+
static std::vector<fs::path> generate_tmp_folder(const fs::path &tmpdir) {
425+
std::vector<fs::path> files;
426+
427+
std::mt19937 gen{};
428+
std::uniform_int_distribution dis{0, 100000};
429+
430+
fs::remove_all(tmpdir);
431+
fs::create_directory(tmpdir);
432+
433+
// Guarantee we always have one large and one empty file
434+
generate_random_file(files.emplace_back(tmpdir / "empty_file"), 0);
435+
generate_random_file(files.emplace_back(tmpdir / "large_file"), 10000000);
436+
437+
const int num_random_files = 8;
438+
for (int i = 0; i < num_random_files; i++) {
439+
std::string filename = "file" + std::to_string(i);
440+
generate_random_file(files.emplace_back(tmpdir / filename), dis(gen));
441+
}
442+
443+
return files;
444+
}
445+
446+
static bool is_same_tmpdir(const std::vector<fs::path> &files,
447+
const fs::path &unpack_dir) {
448+
return std::all_of(files.begin(), files.end(), [&](const fs::path &path) {
449+
fs::path unpacked_file_path = unpack_dir / path;
450+
return files_same(path, unpacked_file_path);
451+
});
452+
}
453+
401454
TEST(package, unpack) {
402455
int result;
456+
fs::path tmpdir = "tmp";
457+
std::string tmpdir_string = tmpdir.string();
458+
const char *tmpdir_c_str = tmpdir_string.c_str();
459+
std::vector<fs::path> files = generate_tmp_folder(tmpdir);
403460

404461
// Create a known good input.
405-
const char *test_input[] = {"include", "src", "test", NULL};
462+
const char *test_input[] = {tmpdir_c_str, NULL};
406463
result = acl_pkg_pack(PACK_UNPACK_FILE, test_input);
407464
CHECK_EQUAL(1, result);
408465

@@ -411,17 +468,17 @@ TEST(package, unpack) {
411468
CHECK_EQUAL(1, result);
412469

413470
// Compare some files to be sure that they are the same.
414-
CHECK_EQUAL(true,
415-
files_same("CMakeLists.txt", PACK_UNPACK_DIR "/CMakeLists.txt"));
416-
CHECK_EQUAL(true, files_same("test/pkg_editor_test.cpp",
417-
PACK_UNPACK_DIR "/test/pkg_editor_test.cpp"));
471+
CHECK(is_same_tmpdir(files, PACK_UNPACK_DIR));
418472
}
419473

420474
TEST(package, unpack_buffer) {
421475
int result;
422-
476+
fs::path tmpdir = "tmp";
477+
std::string tmpdir_string = tmpdir.string();
478+
const char *tmpdir_c_str = tmpdir_string.c_str();
479+
std::vector<fs::path> files = generate_tmp_folder(tmpdir);
423480
// Create a known good input.
424-
const char *test_input[] = {"include", "src", "test", NULL};
481+
const char *test_input[] = {"include", "src", "test", tmpdir_c_str, NULL};
425482
result = acl_pkg_pack(PACK_UNPACK_FILE, test_input);
426483
CHECK_EQUAL(1, result);
427484

@@ -447,13 +504,18 @@ TEST(package, unpack_buffer) {
447504
PACK_UNPACK_DIR "/src/pkg_editor.c"));
448505
CHECK_EQUAL(true, files_same("test/pkg_editor_test.cpp",
449506
PACK_UNPACK_DIR "/test/pkg_editor_test.cpp"));
507+
CHECK(is_same_tmpdir(files, PACK_UNPACK_DIR));
450508
}
451509

452510
TEST(package, unpack_buffer_stdin) {
453511
int result;
512+
fs::path tmpdir = "tmp";
513+
std::string tmpdir_string = tmpdir.string();
514+
const char *tmpdir_c_str = tmpdir_string.c_str();
515+
std::vector<fs::path> files = generate_tmp_folder(tmpdir);
454516

455517
// Create a known good input.
456-
const char *test_input[] = {"include", "src", "test", NULL};
518+
const char *test_input[] = {"include", "src", "test", tmpdir_c_str, NULL};
457519
result = acl_pkg_pack(PACK_UNPACK_FILE, test_input);
458520
CHECK_EQUAL(1, result);
459521

@@ -496,5 +558,6 @@ TEST(package, unpack_buffer_stdin) {
496558
PACK_UNPACK_DIR "/src/pkg_editor.c"));
497559
CHECK_EQUAL(true, files_same("test/pkg_editor_test.cpp",
498560
PACK_UNPACK_DIR "/test/pkg_editor_test.cpp"));
561+
CHECK(is_same_tmpdir(files, PACK_UNPACK_DIR));
499562
}
500563
#endif

0 commit comments

Comments
 (0)