Author: kpvdr
Date: 2007-11-15 11:11:21 -0500 (Thu, 15 Nov 2007)
New Revision: 1318
Modified:
store/trunk/cpp/tests/jrnl/unit_test_jdir.cpp
Log:
Mostly completed jdir unit test
Modified: store/trunk/cpp/tests/jrnl/unit_test_jdir.cpp
===================================================================
--- store/trunk/cpp/tests/jrnl/unit_test_jdir.cpp 2007-11-15 13:00:56 UTC (rev 1317)
+++ store/trunk/cpp/tests/jrnl/unit_test_jdir.cpp 2007-11-15 16:11:21 UTC (rev 1318)
@@ -32,21 +32,34 @@
#include <boost/test/results_reporter.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_log.hpp>
+#include <dirent.h>
+#include <errno.h>
#include <fstream>
+#include <iomanip>
#include <iostream>
+#include <jrnl/file_hdr.hpp>
#include <jrnl/jdir.hpp>
#include <jrnl/jerrno.hpp>
#include <jrnl/jexception.hpp>
#include <sys/stat.h>
#define ERRORSTR(e) ::strerror(ret) << " (" << ret <<
")"
+#define NUM_JDAT_FILES 20
+#define NUM_CLEAR_OPS 20
using namespace boost::unit_test;
using namespace rhm::journal;
// Helper function declarations
-void make_file(const char* filename, mode_t fmode = S_IRUSR | S_IWUSR | S_IRGRP |
S_IROTH);
-void make_jrnl_files(const char* dirname);
+void create_file(const char* filename, mode_t fmode = S_IRUSR | S_IWUSR | S_IRGRP |
S_IROTH);
+void create_jrnl_fileset(const char* dirname, const char* base_filename);
+void create_jdat_file(const char* dirname, const char* base_filename, u_int32_t fid,
+ u_int64_t first_rid);
+void create_jinf_file(const char* dirname, const char* base_filename);
+void check_dir_contents(const char* dirname, const char* base_filename, unsigned
num_subdirs,
+ bool jrnl_present);
+unsigned count_dir_contents(const char* dirname, bool incl_files = true, bool incl_dirs =
true);
+void check_dir_not_existing(const char* dirname);
// Test functions of the form
// void fn() {...}
@@ -65,7 +78,7 @@
// Use instance
std::string dir_A("/tmp/A");
std::string dir_Ats("/tmp/A/"); // trailing '/'
- BOOST_CHECK(!jdir::exists(dir_A));
+ check_dir_not_existing("/tmp/A");
jdir dir1(dir_A, "test_base");
dir1.create_dir();
// check all combos of jdir::exists and jdir::is_dir()
@@ -77,30 +90,37 @@
BOOST_CHECK(jdir::is_dir(dir_Ats));
BOOST_CHECK(jdir::is_dir(dir_Ats.c_str()));
BOOST_CHECK(jdir::is_dir(dir_Ats.c_str()));
+ // do it a second time when dir exists
+ dir1.create_dir();
+ BOOST_CHECK(jdir::is_dir(dir_A));
dir1.delete_dir();
BOOST_CHECK(!jdir::exists(dir_A));
// Use static fn
- BOOST_CHECK(!jdir::exists("/tmp/B"));
+ check_dir_not_existing("/tmp/B");
jdir::create_dir("/tmp/B");
BOOST_CHECK(jdir::is_dir("/tmp/B"));
+ jdir::create_dir("/tmp/B");
+ BOOST_CHECK(jdir::is_dir("/tmp/B"));
jdir::delete_dir("/tmp/B");
BOOST_CHECK(!jdir::exists("/tmp/B"));
// Non-empty dirs
- BOOST_CHECK(!jdir::exists("/tmp/C"));
+ check_dir_not_existing("/tmp/C");
jdir::create_dir("/tmp/C");
BOOST_CHECK(jdir::is_dir("/tmp/C"));
- make_file("/tmp/C/test_file_1.txt"); // mode 644 (default)
- make_file("/tmp/C/test_file_2.txt", S_IRWXU | S_IRWXG | S_IRWXO); // mode
777
- make_file("/tmp/C/test_file_3.txt", S_IRUSR | S_IRGRP | S_IROTH); // mode
444 (read-only)
- make_file("/tmp/C/test_file_4.txt", 0); // mode 000 (no permissions)
+ create_file("/tmp/C/test_file_1.txt"); // mode 644 (default)
+ create_file("/tmp/C/test_file_2.txt", S_IRWXU | S_IRWXG | S_IRWXO); // mode
777
+ create_file("/tmp/C/test_file_3.txt", S_IRUSR | S_IRGRP | S_IROTH); // mode
444 (read-only)
+ create_file("/tmp/C/test_file_4.txt", 0); // mode 000 (no permissions)
BOOST_CHECK(jdir::is_dir("/tmp/C"));
+ jdir::create_dir("/tmp/C");
+ BOOST_CHECK(jdir::is_dir("/tmp/C"));
jdir::delete_dir("/tmp/C");
BOOST_CHECK(!jdir::exists("/tmp/C"));
// Check non-existent dirs fail
- BOOST_CHECK(!jdir::exists("/tmp/D"));
+ check_dir_not_existing("/tmp/D");
try
{
jdir::is_dir("/tmp/D");
@@ -115,7 +135,7 @@
void test_create_delete_dir_recursive()
{
// Use instances
- BOOST_CHECK(!jdir::exists("/tmp/E"));
+ check_dir_not_existing("/tmp/E");
jdir dir1("/tmp/E/F/G/H", "test_base");
dir1.create_dir();
BOOST_CHECK(jdir::is_dir("/tmp/E/F/G/H"));
@@ -125,7 +145,7 @@
jdir::delete_dir("/tmp/E"); // delete remaining dirs
BOOST_CHECK(!jdir::exists("/tmp/E"));
- BOOST_CHECK(!jdir::exists("/tmp/F"));
+ check_dir_not_existing("/tmp/F");
jdir dir2("/tmp/F/G/H/I/", "test_base"); // trailing '/'
dir2.create_dir();
BOOST_CHECK(jdir::is_dir("/tmp/F/G/H/I/"));
@@ -136,7 +156,7 @@
BOOST_CHECK(!jdir::exists("/tmp/F"));
// Use static fn
- BOOST_CHECK(!jdir::exists("/tmp/G"));
+ check_dir_not_existing("/tmp/G");
jdir::create_dir("/tmp/G/H/I/J");
BOOST_CHECK(jdir::is_dir("/tmp/G/H/I/J"));
jdir::delete_dir("/tmp/G/H/I/J");
@@ -145,7 +165,7 @@
jdir::delete_dir("/tmp/G");
BOOST_CHECK(!jdir::exists("/tmp/G"));
- BOOST_CHECK(!jdir::exists("/tmp/H"));
+ check_dir_not_existing("/tmp/H");
jdir::create_dir("/tmp/H/I/J/K/");
BOOST_CHECK(jdir::is_dir("/tmp/H/I/J/K/"));
jdir::delete_dir("/tmp/H/I/J/K/");
@@ -155,15 +175,15 @@
BOOST_CHECK(!jdir::exists("/tmp/H"));
// Non-empty dirs
- BOOST_CHECK(!jdir::exists("/tmp/I"));
+ check_dir_not_existing("/tmp/I");
jdir::create_dir("/tmp/I/J/K1/L1");
jdir::create_dir("/tmp/I/J/K1/L2");
jdir::create_dir("/tmp/I/J/K1/L3");
jdir::create_dir("/tmp/I/J/K1/L4");
- make_file("/tmp/I/J/K1/L4/test_file_1.txt"); // mode 644 (default)
- make_file("/tmp/I/J/K1/L4/test_file_2.txt", S_IRWXU | S_IRWXG | S_IRWXO);
// mode 777
- make_file("/tmp/I/J/K1/L4/test_file_3.txt", S_IRUSR | S_IRGRP | S_IROTH);
// mode 444
- make_file("/tmp/I/J/K1/L4/test_file_4.txt", 0); // mode 000 (no
permissions)
+ create_file("/tmp/I/J/K1/L4/test_file_1.txt"); // mode 644 (default)
+ create_file("/tmp/I/J/K1/L4/test_file_2.txt", S_IRWXU | S_IRWXG | S_IRWXO);
// mode 777
+ create_file("/tmp/I/J/K1/L4/test_file_3.txt", S_IRUSR | S_IRGRP | S_IROTH);
// mode 444
+ create_file("/tmp/I/J/K1/L4/test_file_4.txt", 0); // mode 000 (no
permissions)
jdir::create_dir("/tmp/I/J/K2");
jdir::create_dir("/tmp/I/J/K3/L5");
jdir::create_dir("/tmp/I/J/K3/L6");
@@ -178,64 +198,46 @@
BOOST_CHECK(!jdir::exists("/tmp/I"));
}
-void test_clear_dir()
+void test_clear_verify_dir()
{
// Use instances
- BOOST_CHECK(!jdir::exists("/tmp/test_dir_1"));
- jdir test_dir_1("/tmp/test_dir_1", "test_base");
+ const char* jrnl_dir = "/tmp/test_dir_1";
+ const char* bfn = "test_base";
+ check_dir_not_existing(jrnl_dir);
+ jdir test_dir_1(jrnl_dir, bfn);
test_dir_1.create_dir();
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_1"));
- // add some journal files
- make_jrnl_files("/tmp/test_dir_1");
- // clear dir
- test_dir_1.clear_dir();
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_1"));
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_1/_test_base.bak.0001"));
-
BOOST_CHECK(jdir::exists("/tmp/test_dir_1/_test_base.bak.0001/test_base.jinf"));
- // add some more journal files
- make_jrnl_files("/tmp/test_dir_1");
- // clear dir
- test_dir_1.clear_dir();
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_1"));
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_1/_test_base.bak.0001"));
-
BOOST_CHECK(jdir::exists("/tmp/test_dir_1/_test_base.bak.0001/test_base.jinf"));
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_1/_test_base.bak.0002"));
-
BOOST_CHECK(jdir::exists("/tmp/test_dir_1/_test_base.bak.0002/test_base.jinf"));
- // add some more journal files
- make_jrnl_files("/tmp/test_dir_1");
- // clear dir
- test_dir_1.clear_dir();
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_1"));
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_1/_test_base.bak.0001"));
-
BOOST_CHECK(jdir::exists("/tmp/test_dir_1/_test_base.bak.0001/test_base.jinf"));
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_1/_test_base.bak.0002"));
-
BOOST_CHECK(jdir::exists("/tmp/test_dir_1/_test_base.bak.0002/test_base.jinf"));
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_1/_test_base.bak.0003"));
-
BOOST_CHECK(jdir::exists("/tmp/test_dir_1/_test_base.bak.0003/test_base.jinf"));
+ BOOST_CHECK(jdir::is_dir(jrnl_dir));
+ // add journal files, check they exist, then clear them
+ unsigned cnt = 0;
+ while (cnt < NUM_CLEAR_OPS)
+ {
+ create_jrnl_fileset(jrnl_dir, bfn);
+ check_dir_contents(jrnl_dir, bfn, cnt, true);
+ test_dir_1.clear_dir();
+ check_dir_contents(jrnl_dir, bfn, ++cnt, false);
+ }
// clean up
test_dir_1.delete_dir();
- BOOST_CHECK(!jdir::exists("/tmp/test_dir_1"));
+ BOOST_CHECK(!jdir::exists(jrnl_dir));
- // non-existent dir with auto-create true
- BOOST_CHECK(!jdir::exists("/tmp/test_dir_2"));
- jdir test_dir_2("/tmp/test_dir_2", "test_base");
+ // Non-existent dir with auto-create true
+ jrnl_dir = "/tmp/test_dir_2";
+ check_dir_not_existing(jrnl_dir);
+ jdir test_dir_2(jrnl_dir, bfn);
// clear dir
test_dir_2.clear_dir(); // create flag is true by default
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_2"));
- // add some journal files
- make_jrnl_files("/tmp/test_dir_2");
- // clear dir
- test_dir_2.clear_dir();
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_2"));
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_2/_test_base.bak.0001"));
-
BOOST_CHECK(jdir::exists("/tmp/test_dir_2/_test_base.bak.0001/test_base.jinf"));
+ check_dir_contents(jrnl_dir, bfn, 0, false);
+ // clear empty dir, should not create subdir
+ test_dir_2.clear_dir(); // create flag is true by default
+ check_dir_contents(jrnl_dir, bfn, 0, false);
// clean up
test_dir_2.delete_dir();
- BOOST_CHECK(!jdir::exists("/tmp/test_dir_2"));
+ BOOST_CHECK(!jdir::exists(jrnl_dir));
// non-existent dir with auto-create false
- BOOST_CHECK(!jdir::exists("/tmp/test_dir_3"));
- jdir test_dir_3("/tmp/test_dir_3", "test_base");
+ jrnl_dir = "/tmp/test_dir_3";
+ check_dir_not_existing(jrnl_dir);
+ jdir test_dir_3(jrnl_dir, bfn);
try
{
test_dir_3.clear_dir(false);
@@ -246,65 +248,144 @@
BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_JDIR_OPENDIR);
}
- // static fn
- BOOST_CHECK(!jdir::exists("/tmp/test_dir_4"));
- jdir::create_dir("/tmp/test_dir_4");
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_4"));
- // add some journal files
- make_jrnl_files("/tmp/test_dir_4");
- // clear dir
- jdir::clear_dir("/tmp/test_dir_4", "test_base");
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_4"));
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_4/_test_base.bak.0001"));
-
BOOST_CHECK(jdir::exists("/tmp/test_dir_4/_test_base.bak.0001/test_base.jinf"));
- // add some more journal files
- make_jrnl_files("/tmp/test_dir_4");
- // clear dir
- jdir::clear_dir("/tmp/test_dir_4", "test_base");
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_4"));
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_4/_test_base.bak.0001"));
-
BOOST_CHECK(jdir::exists("/tmp/test_dir_4/_test_base.bak.0001/test_base.jinf"));
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_4/_test_base.bak.0002"));
-
BOOST_CHECK(jdir::exists("/tmp/test_dir_4/_test_base.bak.0002/test_base.jinf"));
- // add some more journal files
- make_jrnl_files("/tmp/test_dir_4");
- // clear dir
- jdir::clear_dir("/tmp/test_dir_4", "test_base");
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_4"));
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_4/_test_base.bak.0001"));
-
BOOST_CHECK(jdir::exists("/tmp/test_dir_4/_test_base.bak.0001/test_base.jinf"));
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_4/_test_base.bak.0002"));
-
BOOST_CHECK(jdir::exists("/tmp/test_dir_4/_test_base.bak.0002/test_base.jinf"));
- BOOST_CHECK(jdir::is_dir("/tmp/test_dir_4/_test_base.bak.0003"));
-
BOOST_CHECK(jdir::exists("/tmp/test_dir_4/_test_base.bak.0003/test_base.jinf"));
+ // Use static fn
+ jrnl_dir = "/tmp/test_dir_4";
+ check_dir_not_existing(jrnl_dir);
+ jdir::clear_dir(jrnl_dir, bfn); // should create dir if it does not exist
+ // add journal files, check they exist, then clear them
+ cnt = 0;
+ while (cnt < NUM_CLEAR_OPS)
+ {
+ create_jrnl_fileset(jrnl_dir, bfn);
+ check_dir_contents(jrnl_dir, bfn, cnt, true);
+ jdir::clear_dir(jrnl_dir, bfn);
+ check_dir_contents(jrnl_dir, bfn, ++cnt, false);
+ }
// clean up
- jdir::delete_dir("/tmp/test_dir_4");
- BOOST_CHECK(!jdir::exists("/tmp/test_dir_4"));
+ jdir::delete_dir(jrnl_dir);
+ BOOST_CHECK(!jdir::exists(jrnl_dir));
}
// Helper functions
-void make_file(const char* filename, mode_t fmode)
+void create_file(const char* filename, mode_t fmode)
{
- std::ofstream of(filename, std::ofstream::out | std::ofstream::trunc);
- if (!of.good())
- BOOST_FAIL("Unable to open file " << filename << "
for writing.");
- of.write(filename, ::strlen(filename));
- of.close();
- ::chmod(filename, fmode);
+ std::ofstream of(filename, std::ofstream::out | std::ofstream::trunc);
+ if (!of.good())
+ BOOST_FAIL("Unable to open file " << filename << " for
writing.");
+ of.write(filename, ::strlen(filename));
+ of.close();
+ ::chmod(filename, fmode);
}
-void make_jrnl_files(const char* dirname)
+void create_jrnl_fileset(const char* dirname, const char* base_filename)
{
- make_file(std::string(dirname).append("/test_base.0000.jdat").c_str());
- make_file(std::string(dirname).append("/test_base.0001.jdat").c_str());
- make_file(std::string(dirname).append("/test_base.0002.jdat").c_str());
- make_file(std::string(dirname).append("/test_base.0003.jdat").c_str());
- make_file(std::string(dirname).append("/test_base.0004.jdat").c_str());
- make_file(std::string(dirname).append("/test_base.jinf").c_str());
-
make_file(std::string(dirname).append("/test_base.12345.abcdef.crazy-filename").c_str());
+ create_jinf_file(dirname, base_filename);
+ for (u_int32_t fid = 0; fid < NUM_JDAT_FILES; fid++)
+ {
+ u_int64_t rid = 0x12340000 + (fid * 0x25);
+ create_jdat_file(dirname, base_filename, fid, rid);
+ }
}
+void create_jdat_file(const char* dirname, const char* base_filename, u_int32_t fid,
+ u_int64_t first_rid)
+{
+ std::stringstream fn;
+ fn << dirname << "/" << base_filename <<
".";
+ fn << std::setfill('0') << std::setw(4) << std::hex
<< fid << ".jdat";
+ file_hdr fh(RHM_JDAT_FILE_MAGIC, RHM_JDAT_VERSION, 0, first_rid, fid, 0x200, true);
+ std::ofstream of(fn.str().c_str(), std::ofstream::out | std::ofstream::trunc);
+ if (!of.good())
+ BOOST_FAIL("Unable to open journal data file " << fn <<
" for writing.");
+ of.write((const char*)&fh, sizeof(file_hdr));
+ of.close();
+}
+
+void create_jinf_file(const char* dirname, const char* base_filename)
+{
+ timespec ts;
+ ::clock_gettime(CLOCK_REALTIME, &ts);
+ jinf ji("test journal id", dirname, base_filename, ts);
+ ji.write();
+}
+
+void check_dir_contents(const char* dirname, const char* base_filename, unsigned
num_subdirs,
+ bool jrnl_present)
+{
+ if (jdir::is_dir(dirname))
+ {
+ // Subdir count
+ BOOST_CHECK_EQUAL(count_dir_contents(dirname, false, true), num_subdirs);
+
+ // Journal file count
+ unsigned num_jrnl_files = jrnl_present ? NUM_JDAT_FILES + 1 : 0;
+ BOOST_CHECK_EQUAL(count_dir_contents(dirname, true, false), num_jrnl_files);
+
+ // Check journal files are present
+ if (jrnl_present)
+ try { jdir::verify_dir(dirname, base_filename); }
+ catch(const jexception& e) { BOOST_ERROR(e); }
+ for (unsigned subdir_num = 1; subdir_num <= num_subdirs; subdir_num++)
+ {
+ std::stringstream subdir_name;
+ subdir_name << dirname << "/_" << base_filename
<< ".bak.";
+ subdir_name << std::hex << std::setfill('0') <<
std::setw(4) << subdir_num;
+ try { jdir::verify_dir(subdir_name.str().c_str(), base_filename); }
+ catch(const jexception& e) { BOOST_ERROR(e); }
+ }
+ }
+ else
+ BOOST_ERROR(dirname << " is not a directory");
+}
+
+unsigned count_dir_contents(const char* dirname, bool incl_files, bool incl_dirs)
+{
+ struct dirent* entry;
+ struct stat s;
+ unsigned file_cnt = 0;
+ unsigned dir_cnt = 0;
+ unsigned other_cnt = 0;
+ DIR* dir = ::opendir(dirname);
+ if (!dir)
+ BOOST_FAIL("Unable to open directory " << dirname);
+ while ((entry = ::readdir(dir)) != NULL)
+ {
+ // Ignore . and ..
+ if (strcmp(entry->d_name, ".") != 0 &&
strcmp(entry->d_name, "..") != 0)
+ {
+ std::stringstream fn;
+ fn << dirname << "/" << entry->d_name;
+ if (::stat(fn.str().c_str(), &s))
+ BOOST_FAIL("Unable to stat dir entry " <<
entry->d_name << "; err=" <<
+ strerror(errno));
+ if (S_ISREG(s.st_mode))
+ file_cnt++;
+ else if (S_ISDIR(s.st_mode))
+ dir_cnt++;
+ else
+ other_cnt++;
+ }
+ }
+ if (incl_files)
+ {
+ if (incl_dirs)
+ return file_cnt + dir_cnt;
+ return file_cnt;
+ }
+ else if (incl_dirs)
+ return dir_cnt;
+ return other_cnt;
+}
+
+void check_dir_not_existing(const char* dirname)
+{
+ if (jdir::exists(dirname) && jdir::is_dir(dirname))
+ jdir::delete_dir(dirname);
+ if (jdir::exists(dirname))
+ BOOST_FAIL("Unable to remove directory " << dirname);
+}
+
// Initialize test suite and include test functions
test_suite* init_unit_test_suite(int, char**)
@@ -318,7 +399,7 @@
ts->add(BOOST_TEST_CASE(&test_constructor));
ts->add(BOOST_TEST_CASE(&test_create_delete_dir));
ts->add(BOOST_TEST_CASE(&test_create_delete_dir_recursive));
- ts->add(BOOST_TEST_CASE(&test_clear_dir));
+ ts->add(BOOST_TEST_CASE(&test_clear_verify_dir));
return ts;
}