Return-Path: X-Original-To: apmail-qpid-commits-archive@www.apache.org Delivered-To: apmail-qpid-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E84DF10E1A for ; Tue, 8 Oct 2013 15:09:41 +0000 (UTC) Received: (qmail 38160 invoked by uid 500); 8 Oct 2013 15:09:34 -0000 Delivered-To: apmail-qpid-commits-archive@qpid.apache.org Received: (qmail 38129 invoked by uid 500); 8 Oct 2013 15:09:33 -0000 Mailing-List: contact commits-help@qpid.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@qpid.apache.org Delivered-To: mailing list commits@qpid.apache.org Received: (qmail 38080 invoked by uid 99); 8 Oct 2013 15:09:29 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 08 Oct 2013 15:09:29 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 08 Oct 2013 15:09:24 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id C199B2388B34; Tue, 8 Oct 2013 15:09:04 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1530301 [3/8] - in /qpid/trunk/qpid: cpp/src/tests/legacystore/ cpp/src/tests/legacystore/federation/ cpp/src/tests/legacystore/jrnl/ cpp/src/tests/legacystore/jrnl/jtt/ cpp/src/tests/legacystore/python_tests/ tools/src/py/ tools/src/py/qp... Date: Tue, 08 Oct 2013 15:09:01 -0000 To: commits@qpid.apache.org From: astitcher@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20131008150904.C199B2388B34@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jdir.cpp URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jdir.cpp?rev=1530301&view=auto ============================================================================== --- qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jdir.cpp (added) +++ qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jdir.cpp Tue Oct 8 15:09:00 2013 @@ -0,0 +1,416 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "../unit_test.h" + +#include +#include +#include +#include +#include +#include +#include "qpid/legacystore/jrnl/file_hdr.h" +#include "qpid/legacystore/jrnl/jcfg.h" +#include "qpid/legacystore/jrnl/jdir.h" +#include "qpid/legacystore/jrnl/jerrno.h" +#include "qpid/legacystore/jrnl/jexception.h" +#include + +#define NUM_JFILES 4 +#define JFSIZE_SBLKS 128 + +#define ERRORSTR(e) std::strerror(e) << " (" << e << ")" +#define NUM_CLEAR_OPS 20 + +using namespace boost::unit_test; +using namespace mrg::journal; +using namespace std; + +QPID_AUTO_TEST_SUITE(jdir_suite) + +const string test_filename("_ut_jdir"); +const char* tdp = getenv("TMP_DATA_DIR"); +const string test_dir(tdp && strlen(tdp) > 0 ? string(tdp) + "/_ut_jdir" : "/var/tmp/_ut_jdir"); + +// === Helper functions === + +void create_file(const char* filename, mode_t fmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) +{ + ofstream of(filename, ofstream::out | ofstream::trunc); + if (!of.good()) + BOOST_FAIL("Unable to open file " << filename << " for writing."); + of.write(filename, std::strlen(filename)); + of.close(); + ::chmod(filename, fmode); +} + +void create_file(const string filename, mode_t fmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) +{ + create_file(filename.c_str(), fmode); +} + +void create_jdat_file(const char* dirname, const char* base_filename, u_int32_t fid, + u_int64_t first_rid) +{ + stringstream fn; + fn << dirname << "/" << base_filename << "."; + fn << setfill('0') << hex << setw(4) << fid << ".jdat"; + file_hdr fh(RHM_JDAT_FILE_MAGIC, RHM_JDAT_VERSION, 0, first_rid, fid, 0x200, true); + ofstream of(fn.str().c_str(), ofstream::out | 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, NUM_JFILES, false, 0, JFSIZE_SBLKS, + JRNL_WMGR_DEF_PAGE_SIZE, JRNL_WMGR_DEF_PAGES, ts); + ji.write(); +} + +void create_jrnl_fileset(const char* dirname, const char* base_filename) +{ + create_jinf_file(dirname, base_filename); + for (u_int32_t fid = 0; fid < NUM_JFILES; fid++) + { + u_int64_t rid = 0x12340000 + (fid * 0x25); + create_jdat_file(dirname, base_filename, fid, rid); + } +} + +unsigned count_dir_contents(const char* dirname, bool incl_files, bool incl_dirs = true) +{ + 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 (std::strcmp(entry->d_name, ".") != 0 && std::strcmp(entry->d_name, "..") != 0) + { + 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=" << + ERRORSTR(errno)); + if (S_ISREG(s.st_mode)) + file_cnt++; + else if (S_ISDIR(s.st_mode)) + dir_cnt++; + else + other_cnt++; + } + } + ::closedir(dir); + 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_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_JFILES + 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++) + { + stringstream subdir_name; + subdir_name << dirname << "/_" << base_filename << ".bak."; + subdir_name << hex << setfill('0') << 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"); +} + +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); +} + +void check_dir_not_existing(const string dirname) +{ + check_dir_not_existing(dirname.c_str()); +} + +// === Test suite === + +QPID_AUTO_TEST_CASE(constructor) +{ + cout << test_filename << ".constructor: " << flush; + string dir(test_dir + "/A/B/C/D/E/F"); + string bfn("test_base"); + jdir dir1(dir, bfn); + BOOST_CHECK(dir1.dirname().compare(dir) == 0); + BOOST_CHECK(dir1.base_filename().compare(bfn) == 0); + cout << "ok" << endl; +} + +QPID_AUTO_TEST_CASE(create_delete_dir) +{ + cout << test_filename << ".create_delete_dir: " << flush; + // Use instance + string dir_A(test_dir + "/A"); + string dir_Ats(test_dir + "/A/"); // trailing '/' + check_dir_not_existing(test_dir + "/A"); + jdir dir1(dir_A, "test_base"); + dir1.create_dir(); + // check all combos of jdir::exists and jdir::is_dir() + BOOST_CHECK(jdir::exists(dir_A)); + BOOST_CHECK(jdir::exists(dir_Ats)); + BOOST_CHECK(jdir::exists(dir_A.c_str())); + BOOST_CHECK(jdir::exists(dir_Ats.c_str())); + BOOST_CHECK(jdir::is_dir(dir_A)); + 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 + check_dir_not_existing(test_dir + "/B"); + jdir::create_dir(test_dir + "/B"); + BOOST_CHECK(jdir::is_dir(test_dir + "/B")); + jdir::create_dir(test_dir + "/B"); + BOOST_CHECK(jdir::is_dir(test_dir + "/B")); + jdir::delete_dir(test_dir + "/B"); + BOOST_CHECK(!jdir::exists(test_dir + "/B")); + + // Non-empty dirs + check_dir_not_existing(test_dir + "/C"); + jdir::create_dir(test_dir + "/C"); + BOOST_CHECK(jdir::is_dir(test_dir + "/C")); + create_file(test_dir + "/C/test_file_1.txt"); // mode 644 (default) + create_file(test_dir + "/C/test_file_2.txt", S_IRWXU | S_IRWXG | S_IRWXO); // mode 777 + create_file(test_dir + "/C/test_file_3.txt", S_IRUSR | S_IRGRP | S_IROTH); // mode 444 (read-only) + create_file(test_dir + "/C/test_file_4.txt", 0); // mode 000 (no permissions) + BOOST_CHECK(jdir::is_dir(test_dir + "/C")); + jdir::create_dir(test_dir + "/C"); + BOOST_CHECK(jdir::is_dir(test_dir + "/C")); + jdir::delete_dir(test_dir + "/C"); + BOOST_CHECK(!jdir::exists(test_dir + "/C")); + + // Check non-existent dirs fail + check_dir_not_existing(test_dir + "/D"); + try + { + jdir::is_dir(test_dir + "/D"); + BOOST_ERROR("jdir::is_dir() failed to throw jexeption for non-existent directory."); + } + catch(const jexception& e) + { + BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_JDIR_STAT); + } + cout << "ok" << endl; +} + +QPID_AUTO_TEST_CASE(create_delete_dir_recursive) +{ + cout << test_filename << ".create_delete_dir_recursive: " << flush; + // Use instances + check_dir_not_existing(test_dir + "/E"); + jdir dir1(test_dir + "/E/F/G/H", "test_base"); + dir1.create_dir(); + BOOST_CHECK(jdir::is_dir(test_dir + "/E/F/G/H")); + dir1.delete_dir(); + BOOST_CHECK(!jdir::exists(test_dir + "/E/F/G/H")); // only H deleted, E/F/G remain + BOOST_CHECK(jdir::exists(test_dir + "/E/F/G")); + jdir::delete_dir(test_dir + "/E"); // delete remaining dirs + BOOST_CHECK(!jdir::exists(test_dir + "/E")); + + check_dir_not_existing(test_dir + "/F"); + jdir dir2(test_dir + "/F/G/H/I/", "test_base"); // trailing '/' + dir2.create_dir(); + BOOST_CHECK(jdir::is_dir(test_dir + "/F/G/H/I/")); + dir2.delete_dir(); + BOOST_CHECK(!jdir::exists(test_dir + "/F/G/H/I/")); + BOOST_CHECK(jdir::exists(test_dir + "/F/G/H/")); + jdir::delete_dir(test_dir + "/F"); + BOOST_CHECK(!jdir::exists(test_dir + "/F")); + + check_dir_not_existing(test_dir + "/G"); + jdir dir3(test_dir + "/G/H//I//J", "test_base"); // extra '/' in path + dir3.create_dir(); + BOOST_CHECK(jdir::is_dir(test_dir + "/G/H//I//J")); + dir3.delete_dir(); + BOOST_CHECK(!jdir::exists(test_dir + "/G/H//I//J")); + BOOST_CHECK(jdir::exists(test_dir + "/G/H//I")); + jdir::delete_dir(test_dir + "/F"); + BOOST_CHECK(!jdir::exists(test_dir + "/F")); + + // Use static fn + check_dir_not_existing(test_dir + "/H"); + jdir::create_dir(test_dir + "/H/I/J/K"); + BOOST_CHECK(jdir::is_dir(test_dir + "/H/I/J/K")); + jdir::delete_dir(test_dir + "/H/I/J/K"); + BOOST_CHECK(!jdir::exists(test_dir + "/H/I/J/K")); // only J deleted, H/I/J remain + BOOST_CHECK(jdir::exists(test_dir + "/H/I/J")); + jdir::delete_dir(test_dir + "/H"); + BOOST_CHECK(!jdir::exists(test_dir + "/H")); + + check_dir_not_existing(test_dir + "/I"); + jdir::create_dir(test_dir + "/I/J/K/L/"); // trailing '/' + BOOST_CHECK(jdir::is_dir(test_dir + "/I/J/K/L/")); + jdir::delete_dir(test_dir + "/I/J/K/L/"); + BOOST_CHECK(!jdir::exists(test_dir + "/I/J/K/L/")); + BOOST_CHECK(jdir::exists(test_dir + "/I/J/K/")); + jdir::delete_dir(test_dir + "/I"); + BOOST_CHECK(!jdir::exists(test_dir + "/I")); + + check_dir_not_existing(test_dir + "//J"); + jdir::create_dir(test_dir + "//J//K//L//M"); // extra '/' in path + BOOST_CHECK(jdir::is_dir(test_dir + "//J//K//L//M")); + jdir::delete_dir(test_dir + "//J//K//L//M"); + BOOST_CHECK(!jdir::exists(test_dir + "//J//K//L//M")); + BOOST_CHECK(jdir::exists(test_dir + "//J//K//L")); + jdir::delete_dir(test_dir + "//J"); + BOOST_CHECK(!jdir::exists(test_dir + "//J")); + + // Non-empty dirs + check_dir_not_existing(test_dir + "/K"); + jdir::create_dir(test_dir + "/K/L/M1/N1"); + jdir::create_dir(test_dir + "/K/L/M1/N2"); + jdir::create_dir(test_dir + "/K/L/M1/N3"); + jdir::create_dir(test_dir + "/K/L/M1/N4"); + create_file(test_dir + "/K/L/M1/N4/test_file_1.txt"); // mode 644 (default) + create_file(test_dir + "/K/L/M1/N4/test_file_2.txt", S_IRWXU | S_IRWXG | S_IRWXO); // mode 777 + create_file(test_dir + "/K/L/M1/N4/test_file_3.txt", S_IRUSR | S_IRGRP | S_IROTH); // mode 444 + create_file(test_dir + "/K/L/M1/N4/test_file_4.txt", 0); // mode 000 (no permissions) + jdir::create_dir(test_dir + "/K/L/M2"); + jdir::create_dir(test_dir + "/K/L/M3/N5"); + jdir::create_dir(test_dir + "/K/L/M3/N6"); + BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M1/N1")); + BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M1/N2")); + BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M1/N3")); + BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M1/N4")); + BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M2")); + BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M3/N5")); + BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M3/N6")); + jdir::delete_dir(test_dir + "/K"); + BOOST_CHECK(!jdir::exists(test_dir + "/K")); + cout << "ok" << endl; +} + +QPID_AUTO_TEST_CASE(clear_verify_dir) +{ + cout << test_filename << ".clear_verify_dir: " << flush; + // Use instances + const char* jrnl_dir = "/var/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(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(jrnl_dir)); + + // Non-existent dir with auto-create true + jrnl_dir = "/var/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 + 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(jrnl_dir)); + + // non-existent dir with auto-create false + jrnl_dir = "/var/tmp/test_dir_3"; + check_dir_not_existing(jrnl_dir); + jdir test_dir_3(jrnl_dir, bfn); + try + { + test_dir_3.clear_dir(false); + BOOST_ERROR("jdir::clear_dir(flase) failed to throw jexeption for non-existent directory."); + } + catch(const jexception& e) + { + BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_JDIR_OPENDIR); + } + + // Use static fn + jrnl_dir = "/var/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(jrnl_dir); + BOOST_CHECK(!jdir::exists(jrnl_dir)); + cout << "ok" << endl; +} + +QPID_AUTO_TEST_SUITE_END() Added: qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jerrno.cpp URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jerrno.cpp?rev=1530301&view=auto ============================================================================== --- qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jerrno.cpp (added) +++ qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jerrno.cpp Tue Oct 8 15:09:00 2013 @@ -0,0 +1,47 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "../unit_test.h" + +#include +#include +#include "qpid/legacystore/jrnl/jerrno.h" + +using namespace boost::unit_test; +using namespace mrg::journal; +using namespace std; + +QPID_AUTO_TEST_SUITE(jerrno_suite) +using namespace mrg::journal; + +const string test_filename("_ut_jerrno"); + +QPID_AUTO_TEST_CASE(jerrno_val) +{ + cout << test_filename << ".jerrno_val: " << flush; + const char* m = "JERR__MALLOC"; + string malloc_msg = string(jerrno::err_msg(jerrno::JERR__MALLOC)); + BOOST_CHECK(malloc_msg.substr(0, std::strlen(m)).compare(m) == 0); + BOOST_CHECK(std::strcmp(jerrno::err_msg(0), "") == 0); + cout << "ok" << endl; +} + +QPID_AUTO_TEST_SUITE_END() Added: qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jexception.cpp URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jexception.cpp?rev=1530301&view=auto ============================================================================== --- qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jexception.cpp (added) +++ qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jexception.cpp Tue Oct 8 15:09:00 2013 @@ -0,0 +1,346 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "../unit_test.h" + +#include +#include +#include "qpid/legacystore/jrnl/jerrno.h" +#include "qpid/legacystore/jrnl/jexception.h" + +using namespace boost::unit_test; +using namespace mrg::journal; +using namespace std; + +QPID_AUTO_TEST_SUITE(jexception_suite) + +const string test_filename("_ut_jexception"); + +// === Helper functions === + +void throw_exception(const jexception& e, std::size_t what_len, std::size_t ai_len, + std::size_t tc_len, std::size_t tf_len) +{ + try { throw e; } + catch (const jexception& e) + { + BOOST_CHECK_EQUAL(std::strlen(e.what()), what_len); + BOOST_CHECK_EQUAL(e.additional_info().size(), ai_len); + BOOST_CHECK_EQUAL(e.throwing_class().size(), tc_len); + BOOST_CHECK_EQUAL(e.throwing_fn().size(), tf_len); + } +} + +void throw_exception(const jexception& e, std::size_t what_len, std::size_t ai_len) +{ + throw_exception(e, what_len, ai_len, 0, 0); +} + +void throw_exception(const jexception& e, std::size_t what_len, std::size_t tc_len, + std::size_t tf_len) +{ + throw_exception(e, what_len, 0, tc_len, tf_len); +} + +// === Test suite === + +QPID_AUTO_TEST_CASE(constructor_1) +{ + cout << test_filename << ".constructor_1: " << flush; + try + { + jexception e1; + BOOST_CHECK_EQUAL(e1.err_code(), (u_int32_t)0); + BOOST_CHECK(e1.additional_info().size() == 0); + BOOST_CHECK(e1.throwing_class().size() == 0); + BOOST_CHECK(e1.throwing_fn().size() == 0); + BOOST_CHECK(std::strlen(e1.what()) > 0); + throw e1; + } + catch (const jexception& e) + { + BOOST_CHECK_EQUAL(e.err_code(), (u_int32_t)0); + BOOST_CHECK(e.additional_info().size() == 0); + BOOST_CHECK(e.throwing_class().size() == 0); + BOOST_CHECK(e.throwing_fn().size() == 0); + BOOST_CHECK(std::strlen(e.what()) > 0); + } + cout << "ok" << endl; +} + +QPID_AUTO_TEST_CASE(constructor_2) +{ + cout << test_filename << ".constructor_2: " << flush; + const u_int32_t err_code = 2; + try + { + jexception e2(err_code); + BOOST_CHECK_EQUAL(e2.err_code(), err_code); + BOOST_CHECK(e2.additional_info().size() == 0); + BOOST_CHECK(e2.throwing_class().size() == 0); + BOOST_CHECK(e2.throwing_fn().size() == 0); + BOOST_CHECK(std::strlen(e2.what()) > 0); + throw e2; + } + catch (const jexception& e) + { + BOOST_CHECK_EQUAL(e.err_code(), err_code); + BOOST_CHECK(e.additional_info().size() == 0); + BOOST_CHECK(e.throwing_class().size() == 0); + BOOST_CHECK(e.throwing_fn().size() == 0); + BOOST_CHECK(std::strlen(e.what()) > 0); + } + cout << "ok" << endl; +} + +QPID_AUTO_TEST_CASE(constructor_3a) +{ + cout << test_filename << ".constructor_3a: " << flush; + const char* err_msg = "exception3"; + try + { + jexception e3(err_msg); + BOOST_CHECK_EQUAL(e3.err_code(), (u_int32_t)0); + BOOST_CHECK(e3.additional_info().compare(err_msg) == 0); + BOOST_CHECK(e3.throwing_class().size() == 0); + BOOST_CHECK(e3.throwing_fn().size() == 0); + BOOST_CHECK(std::strlen(e3.what()) > 0); + throw e3; + } + catch (const jexception& e) + { + BOOST_CHECK_EQUAL(e.err_code(), (u_int32_t)0); + BOOST_CHECK(e.additional_info().compare(err_msg) == 0); + BOOST_CHECK(e.throwing_class().size() == 0); + BOOST_CHECK(e.throwing_fn().size() == 0); + BOOST_CHECK(std::strlen(e.what()) > 0); + } + cout << "ok" << endl; +} + +QPID_AUTO_TEST_CASE(constructor_3b) +{ + cout << test_filename << ".constructor_3b: " << flush; + const string err_msg("exception3"); + try + { + jexception e3(err_msg); + BOOST_CHECK_EQUAL(e3.err_code(), (u_int32_t)0); + BOOST_CHECK(e3.additional_info().compare(err_msg) == 0); + BOOST_CHECK(e3.throwing_class().size() == 0); + BOOST_CHECK(e3.throwing_fn().size() == 0); + BOOST_CHECK(std::strlen(e3.what()) > 0); + throw e3; + } + catch (const jexception& e) + { + BOOST_CHECK_EQUAL(e.err_code(), (u_int32_t)0); + BOOST_CHECK(e.additional_info().compare(err_msg) == 0); + BOOST_CHECK(e.throwing_class().size() == 0); + BOOST_CHECK(e.throwing_fn().size() == 0); + BOOST_CHECK(std::strlen(e.what()) > 0); + } + cout << "ok" << endl; +} + +QPID_AUTO_TEST_CASE(constructor_4a) +{ + cout << test_filename << ".constructor_4a: " << flush; + const u_int32_t err_code = 4; + const char* err_msg = "exception4"; + try + { + jexception e4(err_code, err_msg); + BOOST_CHECK_EQUAL(e4.err_code(), err_code); + BOOST_CHECK(e4.additional_info().compare(err_msg) == 0); + BOOST_CHECK(e4.throwing_class().size() == 0); + BOOST_CHECK(e4.throwing_fn().size() == 0); + BOOST_CHECK(std::strlen(e4.what()) > 0); + throw e4; + } + catch (const jexception& e) + { + BOOST_CHECK_EQUAL(e.err_code(), err_code); + BOOST_CHECK(e.additional_info().compare(err_msg) == 0); + BOOST_CHECK(e.throwing_class().size() == 0); + BOOST_CHECK(e.throwing_fn().size() == 0); + BOOST_CHECK(std::strlen(e.what()) > 0); + } + cout << "ok" << endl; +} + +QPID_AUTO_TEST_CASE(constructor_4b) +{ + cout << test_filename << ".constructor_4b: " << flush; + const u_int32_t err_code = 4; + const string err_msg("exception4"); + try + { + jexception e4(err_code, err_msg); + BOOST_CHECK_EQUAL(e4.err_code(), err_code); + BOOST_CHECK(e4.additional_info().compare(err_msg) == 0); + BOOST_CHECK(e4.throwing_class().size() == 0); + BOOST_CHECK(e4.throwing_fn().size() == 0); + BOOST_CHECK(std::strlen(e4.what()) > 0); + throw e4; + } + catch (const jexception& e) + { + BOOST_CHECK_EQUAL(e.err_code(), err_code); + BOOST_CHECK(e.additional_info().compare(err_msg) == 0); + BOOST_CHECK(e.throwing_class().size() == 0); + BOOST_CHECK(e.throwing_fn().size() == 0); + BOOST_CHECK(std::strlen(e.what()) > 0); + } + cout << "ok" << endl; +} + +QPID_AUTO_TEST_CASE(constructor_5a) +{ + cout << test_filename << ".constructor_5a: " << flush; + const u_int32_t err_code = 5; + const char* err_class = "class5"; + const char* err_fn = "fn5"; + try + { + jexception e5(err_code, err_class, err_fn); + BOOST_CHECK_EQUAL(e5.err_code(), err_code); + BOOST_CHECK(e5.additional_info().size() == 0); + BOOST_CHECK(e5.throwing_class().compare(err_class) == 0); + BOOST_CHECK(e5.throwing_fn().compare(err_fn) == 0); + BOOST_CHECK(std::strlen(e5.what()) > 0); + throw e5; + } + catch (const jexception& e) + { + BOOST_CHECK_EQUAL(e.err_code(), err_code); + BOOST_CHECK(e.additional_info().size() == 0); + BOOST_CHECK(e.throwing_class().compare(err_class) == 0); + BOOST_CHECK(e.throwing_fn().compare(err_fn) == 0); + BOOST_CHECK(std::strlen(e.what()) > 0); + } + cout << "ok" << endl; +} + +QPID_AUTO_TEST_CASE(constructor_5b) +{ + cout << test_filename << ".constructor_5b: " << flush; + const u_int32_t err_code = 5; + const string err_class("class5"); + const string err_fn("fn5"); + try + { + jexception e5(err_code, err_class, err_fn); + BOOST_CHECK_EQUAL(e5.err_code(), err_code); + BOOST_CHECK(e5.additional_info().size() == 0); + BOOST_CHECK(e5.throwing_class().compare(err_class) == 0); + BOOST_CHECK(e5.throwing_fn().compare(err_fn) == 0); + BOOST_CHECK(std::strlen(e5.what()) > 0); + throw e5; + } + catch (const jexception& e) + { + BOOST_CHECK_EQUAL(e.err_code(), err_code); + BOOST_CHECK(e.additional_info().size() == 0); + BOOST_CHECK(e.throwing_class().compare(err_class) == 0); + BOOST_CHECK(e.throwing_fn().compare(err_fn) == 0); + BOOST_CHECK(std::strlen(e.what()) > 0); + } + cout << "ok" << endl; +} + +QPID_AUTO_TEST_CASE(constructor_6a) +{ + cout << test_filename << ".constructor_6a: " << flush; + const u_int32_t err_code = 6; + const char* err_msg = "exception6"; + const char* err_class = "class6"; + const char* err_fn = "fn6"; + try + { + jexception e6(err_code, err_msg, err_class, err_fn); + BOOST_CHECK_EQUAL(e6.err_code(), err_code); + BOOST_CHECK(e6.additional_info().compare(err_msg) == 0); + BOOST_CHECK(e6.throwing_class().compare(err_class) == 0); + BOOST_CHECK(e6.throwing_fn().compare(err_fn) == 0); + BOOST_CHECK(std::strlen(e6.what()) > 0); + throw e6; + } + catch (const jexception& e) + { + BOOST_CHECK_EQUAL(e.err_code(), err_code); + BOOST_CHECK(e.additional_info().compare(err_msg) == 0); + BOOST_CHECK(e.throwing_class().compare(err_class) == 0); + BOOST_CHECK(e.throwing_fn().compare(err_fn) == 0); + BOOST_CHECK(std::strlen(e.what()) > 0); + } + cout << "ok" << endl; +} + +QPID_AUTO_TEST_CASE(constructor_6b) +{ + cout << test_filename << ".constructor_6b: " << flush; + const u_int32_t err_code = 6; + const string err_msg("exception6"); + const string err_class("class6"); + const string err_fn("fn6"); + try + { + jexception e6(err_code, err_msg, err_class, err_fn); + BOOST_CHECK_EQUAL(e6.err_code(), err_code); + BOOST_CHECK(e6.additional_info().compare(err_msg) == 0); + BOOST_CHECK(e6.throwing_class().compare(err_class) == 0); + BOOST_CHECK(e6.throwing_fn().compare(err_fn) == 0); + BOOST_CHECK(std::strlen(e6.what()) > 0); + throw e6; + } + catch (const jexception& e) + { + BOOST_CHECK_EQUAL(e.err_code(), err_code); + BOOST_CHECK(e.additional_info().compare(err_msg) == 0); + BOOST_CHECK(e.throwing_class().compare(err_class) == 0); + BOOST_CHECK(e.throwing_fn().compare(err_fn) == 0); + BOOST_CHECK(std::strlen(e.what()) > 0); + } + cout << "ok" << endl; +} + +QPID_AUTO_TEST_CASE(msg_scope) +{ + cout << test_filename << ".msg_scope: " << flush; + try + { + // These will go out of scope as soon as jexception is thrown... + const string msg("Error message"); + const string cls("class"); + const string fn("function"); + throw jexception(100, msg, cls, fn); + } + catch (const jexception& e) + { + stringstream ss; + ss << e; + BOOST_CHECK(ss.str().size() > 0); + } + cout << "ok" << endl; +} + +QPID_AUTO_TEST_SUITE_END() Added: qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jinf.cpp URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jinf.cpp?rev=1530301&view=auto ============================================================================== --- qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jinf.cpp (added) +++ qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_jinf.cpp Tue Oct 8 15:09:00 2013 @@ -0,0 +1,402 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "../unit_test.h" + +#include +#include +#include "qpid/legacystore/jrnl/jcntl.h" + +using namespace boost::unit_test; +using namespace mrg::journal; +using namespace std; + +QPID_AUTO_TEST_SUITE(jinf_suite) + +const string test_filename("_ut_jinf"); + +#include "_st_helper_fns.h" + +timespec ts; + +QPID_AUTO_TEST_CASE(write_constructor) +{ + string test_name = get_test_name(test_filename, "write_constructor"); + const string jid = test_name + "_jid"; + const string base_filename = test_name + "_bfn"; + jdir::create_dir(test_dir); // Check test dir exists; create it if not + ::clock_gettime(CLOCK_REALTIME, &ts); + jinf ji(jid, test_dir, base_filename, NUM_JFILES, false, 0, JFSIZE_SBLKS, JRNL_WMGR_DEF_PAGE_SIZE, JRNL_WMGR_DEF_PAGES, ts); + BOOST_CHECK_EQUAL(ji.jver(), RHM_JDAT_VERSION); + BOOST_CHECK(ji.jid().compare(jid) == 0); + BOOST_CHECK(ji.jdir().compare(test_dir) == 0); + BOOST_CHECK(ji.base_filename().compare(base_filename) == 0); + const timespec this_ts = ji.ts(); + BOOST_CHECK_EQUAL(this_ts.tv_sec, ts.tv_sec); + BOOST_CHECK_EQUAL(this_ts.tv_nsec, ts.tv_nsec); + BOOST_CHECK_EQUAL(ji.num_jfiles(), u_int16_t(NUM_JFILES)); + BOOST_CHECK_EQUAL(ji.is_ae(), false); + BOOST_CHECK_EQUAL(ji.ae_max_jfiles(), u_int16_t(0)); + BOOST_CHECK_EQUAL(ji.jfsize_sblks(), u_int32_t(JFSIZE_SBLKS)); + BOOST_CHECK_EQUAL(ji.sblk_size_dblks(), u_int16_t(JRNL_SBLK_SIZE)); + BOOST_CHECK_EQUAL(ji.dblk_size(), u_int32_t(JRNL_DBLK_SIZE)); + BOOST_CHECK_EQUAL(ji.wcache_pgsize_sblks(), u_int32_t(JRNL_WMGR_DEF_PAGE_SIZE)); + BOOST_CHECK_EQUAL(ji.wcache_num_pages(), u_int16_t(JRNL_WMGR_DEF_PAGES)); + BOOST_CHECK_EQUAL(ji.rcache_pgsize_sblks(), u_int32_t(JRNL_RMGR_PAGE_SIZE)); + BOOST_CHECK_EQUAL(ji.rcache_num_pages(), u_int16_t(JRNL_RMGR_PAGES)); + ji.write(); + cout << "done" << endl; +} + +QPID_AUTO_TEST_CASE(read_constructor) +{ + string test_name = get_test_name(test_filename, "read_constructor"); + const string jid = test_name + "_jid"; + const string base_filename = test_name + "_bfn"; + lfid_pfid_map::create_new_jinf(jid, base_filename, false); + + stringstream fn; + fn << test_dir << "/" < sblk_buffer(expand_size, 0); + of.write(&sblk_buffer[0], expand_size); + of.close(); + + stringstream fn; + fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION; + jinf ji(fn.str(), false); + try + { + ji.analyze(); + BOOST_FAIL("Failed to detect irregular journal file size in file \"" << filename << "\""); + } + catch (const jexception& e) {} // ignore - expected + + m.destroy_journal(); + } + cout << "done" << endl; +} + +QPID_AUTO_TEST_CASE(analyze_owi_in_non_ae_journal) +{ + string test_name = get_test_name(test_filename, "analyze_owi_in_non_ae_journal"); + const string jid = test_name + "_jid"; + const string base_filename = test_name + "_bfn"; + lfid_pfid_map m(jid, base_filename); + for (u_int16_t oldest_file = 1; oldest_file < NUM_DEFAULT_JFILES-1; oldest_file++) + { + for (u_int16_t bad_owi_file = oldest_file + 1; bad_owi_file < NUM_DEFAULT_JFILES; bad_owi_file++) + { + m.journal_create(NUM_DEFAULT_JFILES, NUM_DEFAULT_JFILES, oldest_file, bad_owi_file); + m.write_journal(false, 0); + + stringstream fn; + fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION; + jinf ji(fn.str(), false); + try + { + ji.analyze(); + BOOST_FAIL("Failed to detect irregular OWI flag in non-ae journal file \"" << fn << "\""); + } + catch (const jexception& e) {} // ignore - expected + + m.destroy_journal(); + } + } + cout << "done" << endl; +} + +QPID_AUTO_TEST_CASE(analyze_owi_in_ae_min_size_journal) +{ + string test_name = get_test_name(test_filename, "analyze_owi_in_ae_min_size_journal"); + const string jid = test_name + "_jid"; + const string base_filename = test_name + "_bfn"; + lfid_pfid_map m(jid, base_filename); + for (u_int16_t oldest_file = 1; oldest_file < NUM_JFILES-1; oldest_file++) + { + for (u_int16_t bad_owi_file = oldest_file + 1; bad_owi_file < NUM_JFILES; bad_owi_file++) + { + m.journal_create(NUM_JFILES, NUM_JFILES, oldest_file, bad_owi_file); + m.write_journal(true, 16); + + stringstream fn; + fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION; + jinf ji(fn.str(), false); + try + { + ji.analyze(); + BOOST_FAIL("Failed to detect irregular OWI flag in min-sized ae journal file \"" << fn << "\""); + } + catch (const jexception& e) {} // ignore - expected + + m.destroy_journal(); + } + } + cout << "done" << endl; +} + +QPID_AUTO_TEST_SUITE_END() Added: qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_lpmgr.cpp URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_lpmgr.cpp?rev=1530301&view=auto ============================================================================== --- qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_lpmgr.cpp (added) +++ qpid/trunk/qpid/cpp/src/tests/legacystore/jrnl/_ut_lpmgr.cpp Tue Oct 8 15:09:00 2013 @@ -0,0 +1,886 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "../unit_test.h" +#include +#include +#include "qpid/legacystore/jrnl/jcntl.h" +#include "qpid/legacystore/jrnl/lpmgr.h" + +using namespace boost::unit_test; +using namespace mrg::journal; +using namespace std; + +QPID_AUTO_TEST_SUITE(arr_cnt_suite) + +const string test_filename("_ut_lpmgr"); + +#include "_st_helper_fns.h" + +// === Helper functions and definitions === + +typedef vector flist; +typedef flist::const_iterator flist_citr; + +class lpmgr_test_helper +{ + lpmgr_test_helper() {} + virtual ~lpmgr_test_helper() {} + +public: + static void check_pfids_lfids(const lpmgr& lm, const u_int16_t pfids[], const u_int16_t lfids[], + const size_t pfid_lfid_size) + { + vector res; + lm.get_pfid_list(res); + vectors_equal(lm, pfids, pfid_lfid_size, res, true); + lm.get_lfid_list(res); + vectors_equal(lm, lfids, pfid_lfid_size, res, false); + } + + static void check_pfids_lfids(const lpmgr& lm, const flist& pfids, const flist lfids) + { + vector res; + lm.get_pfid_list(res); + vectors_equal(lm, pfids, res, true); + lm.get_lfid_list(res); + vectors_equal(lm, lfids, res, false); + } + + static void check_linear_pfids_lfids(const lpmgr& lm, const size_t pfid_lfid_size) + { + vector res; + lm.get_pfid_list(res); + linear_vectors_equal(lm, pfid_lfid_size, res, true); + lm.get_lfid_list(res); + linear_vectors_equal(lm, pfid_lfid_size, res, false); + } + + static void rcvdat_init(rcvdat& rd, const u_int16_t num_jfiles, const bool ae, const u_int16_t ae_max_jfiles, + const u_int16_t pfids[]) + { + rd.reset(num_jfiles, ae, ae_max_jfiles); + load_vector(pfids, num_jfiles, rd._fid_list); + rd._jempty = false; + rd._lfid = pfids[num_jfiles - 1]; + rd._eo = 100 * JRNL_DBLK_SIZE * JRNL_SBLK_SIZE; + } + + static void rcvdat_init(rcvdat& rd, const flist& pfidl, const bool ae, const u_int16_t ae_max_jfiles) + { + const u_int16_t num_jfiles = pfidl.size(); + rd.reset(num_jfiles, ae, ae_max_jfiles); + load_vector(pfidl, rd._fid_list); + rd._jempty = false; + rd._lfid = pfidl[num_jfiles - 1]; + rd._eo = 100 * JRNL_DBLK_SIZE * JRNL_SBLK_SIZE; + } + + static void initialize(lpmgr& lm, test_jrnl& jc, const u_int16_t num_jfiles, const bool ae, + const u_int16_t ae_max_jfiles) + { + lm.initialize(num_jfiles, ae, ae_max_jfiles, &jc, &jc.new_fcntl); + BOOST_CHECK_EQUAL(lm.is_init(), true); + BOOST_CHECK_EQUAL(lm.is_ae(), ae); + BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles); + BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles); + if (num_jfiles) + check_linear_pfids_lfids(lm, num_jfiles); + else + BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0); + } + + // version which sets up the lfid_pfid_map for later manipulation by insert tests + static void initialize(lfid_pfid_map& lfm, lpmgr& lm, test_jrnl& jc, const u_int16_t num_jfiles, const bool ae, + const u_int16_t ae_max_jfiles) + { + lfm.journal_create(num_jfiles, num_jfiles); + initialize(lm, jc, num_jfiles, ae, ae_max_jfiles); + } + + static void prepare_recover(lfid_pfid_map& lfm, const u_int16_t size) + { + if (size < 4) BOOST_FAIL("prepare_recover(): size parameter (" << size << ") too small."); + lfm.journal_create(4, 4); // initial journal of size 4 + u_int16_t s = 4; // cumulative size + while (s < size) + { + const u_int16_t ins_posn = u_int16_t(s * ::drand48()); // this insert posn + if (3.0 * ::drand48() > 1.0 || size - s < 2) // 2:1 chance of single insert when >= 2 still to insert + { + lfm.journal_insert(ins_posn); // single insert + s++; + } + else + { + // multiple insert, either 2 - 5 + const u_int16_t max_ins_size = size - s >5 ? 5 : size - s; + const u_int16_t ins_size = 2 + u_int16_t((max_ins_size - 2) * ::drand48()); // this insert size + lfm.journal_insert(ins_posn, ins_size); + s += ins_size; + } + } + } + + static void recover(lfid_pfid_map& lfm, lpmgr& lm, test_jrnl& jc, const bool ae, const u_int16_t ae_max_jfiles) + { + flist pfidl; + flist lfidl; + rcvdat rd; + const u_int16_t num_jfiles = lfm.size(); + + lfm.get_pfid_list(pfidl); + lfm.get_lfid_list(lfidl); + lm.finalize(); // clear all file handles before erasing old journal files + lfm.write_journal(ae, ae_max_jfiles, JFSIZE_SBLKS); + + lpmgr_test_helper::rcvdat_init(rd, pfidl, ae, ae_max_jfiles); + lm.recover(rd, &jc, &jc.new_fcntl); + BOOST_CHECK_EQUAL(lm.is_init(), true); + BOOST_CHECK_EQUAL(lm.is_ae(), ae); + BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles); + BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles); + if (num_jfiles) + check_pfids_lfids(lm, pfidl, lfidl); + else + BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0); + } + + static void finalize(lpmgr& lm) + { + lm.finalize(); + BOOST_CHECK_EQUAL(lm.is_init(), false); + BOOST_CHECK_EQUAL(lm.is_ae(), false); + BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), u_int16_t(0)); + BOOST_CHECK_EQUAL(lm.num_jfiles(), u_int16_t(0)); + BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0); + vector res; + lm.get_pfid_list(res); + BOOST_CHECK_EQUAL(res.size(), u_int16_t(0)); + lm.get_lfid_list(res); + BOOST_CHECK_EQUAL(res.size(), u_int16_t(0)); + } + + static void insert(lfid_pfid_map& lfm, lpmgr& lm, test_jrnl& jc, const u_int16_t after_lfid, const u_int16_t incr = 1) + { + flist pfidl; + flist lfidl; + const u_int16_t num_jfiles = lm.num_jfiles(); + lfm.journal_insert(after_lfid, incr); + lfm.get_pfid_list(pfidl); + lfm.get_lfid_list(lfidl); + lm.insert(after_lfid, &jc, &jc.new_fcntl, incr); + BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles + incr); + lpmgr_test_helper::check_pfids_lfids(lm, pfidl, lfidl); + } + + static void check_ae_max_jfiles(lpmgr& lm, const u_int16_t num_jfiles, const u_int16_t ae_max_jfiles) + { + bool legal = ae_max_jfiles > num_jfiles || ae_max_jfiles == 0; + + lm.set_ae(false); + BOOST_CHECK(!lm.is_ae()); + if (legal) + { + lm.set_ae_max_jfiles(ae_max_jfiles); + BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles); + lm.set_ae(true); + BOOST_CHECK(lm.is_ae()); + BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), ae_max_jfiles + ? ae_max_jfiles - num_jfiles + : JRNL_MAX_NUM_FILES - num_jfiles); + } + else + { + lm.set_ae_max_jfiles(ae_max_jfiles); + BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles); + try + { + lm.set_ae(true); // should raise exception + BOOST_ERROR("Auto-expand enabled with out-of-range ae_max_jfiles"); + } + catch (const jexception& e) { BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_LFMGR_BADAEFNUMLIM); } + BOOST_CHECK(!lm.is_ae()); + BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), 0); + } + BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles); + } + + static void check_multiple_initialization_recover(lfid_pfid_map& lfm, test_jrnl& jc, + const u_int16_t num_jfiles_arr[][2], const bool init_flag_0, const bool finalize_flag, + const bool init_flag_1) + { + unsigned i_njf = 0; + while (num_jfiles_arr[i_njf][0] && num_jfiles_arr[i_njf][1]) // cycle through each entry in num_jfiles_arr + { + for (unsigned i1_njf = 0; i1_njf <= 1; i1_njf++) // cycle through the two numbers in each entry of num_jfiles_arr + { + const u_int16_t num_jfiles_0 = num_jfiles_arr[i_njf][i1_njf == 0]; // first number in pair + const u_int16_t num_jfiles_1 = num_jfiles_arr[i_njf][i1_njf != 0]; // second number in pair + + for (unsigned i_ae = 0; i_ae < 4; i_ae++) // cycle through combinations of enabling AE + { + const bool ae_0 = i_ae & 0x1; // first bit: enable AE on first init + const bool ae_1 = i_ae & 0x2; // second bit: enable AE on second init + for (unsigned i_aemjf = 0; i_aemjf < 4; i_aemjf++) // cycle through combinations of enabling/disabling ae limit + { + const u_int16_t ae_max_jfiles_0 = i_aemjf & 0x1 ? 3 * num_jfiles_0 : 0; // max ae files, 0 = disable max + const u_int16_t ae_max_jfiles_1 = i_aemjf & 0x2 ? 4 * num_jfiles_1 : 0; // max ae files, 0 = disable max + + lpmgr lm; // DUT + + if (init_flag_0) + initialize(lm, jc, num_jfiles_0, ae_0, ae_max_jfiles_0); + else + { + prepare_recover(lfm, num_jfiles_0); + recover(lfm, lm, jc, ae_1, ae_max_jfiles_0); + lfm.destroy_journal(); + } + + if (finalize_flag) finalize(lm); + + if (init_flag_1) + initialize(lm, jc, num_jfiles_1, ae_1, ae_max_jfiles_1); + else + { + prepare_recover(lfm, num_jfiles_1); + recover(lfm, lm, jc, ae_1, ae_max_jfiles_1); + lfm.destroy_journal(); + } + } + } + } + i_njf++; + } + } + + static void check_insert(lfid_pfid_map& lfm, lpmgr& lm, test_jrnl& jc, const u_int16_t after_lfid, + const u_int16_t incr = 1) + { + const u_int16_t num_jfiles = lm.num_jfiles(); + const u_int16_t ae_max_jfiles = lm.ae_max_jfiles(); + const u_int16_t effective_ae_max_jfiles = ae_max_jfiles ? ae_max_jfiles : JRNL_MAX_NUM_FILES; + BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), effective_ae_max_jfiles - num_jfiles); + bool legal = lm.is_ae() && num_jfiles + incr <= effective_ae_max_jfiles; + if (legal) + { + insert(lfm, lm, jc, after_lfid, incr); + BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles + incr); + BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), effective_ae_max_jfiles - num_jfiles - incr); + } + else + { + try + { + insert(lfm, lm, jc, after_lfid, incr); + if (lm.is_ae()) + BOOST_ERROR("lpmgr::insert() succeeded and exceeded limit"); + else + BOOST_ERROR("lpmgr::insert() succeeded with auto-expand disabled"); + } + catch (const jexception& e) + { + if (lm.is_ae()) + BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_LFMGR_AEFNUMLIMIT); + else + BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_LFMGR_AEDISABLED); + } + BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles); + BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), effective_ae_max_jfiles - num_jfiles); + } + } + + static void check_limit(lfid_pfid_map& lfm, test_jrnl& jc, const bool ae, const u_int16_t num_jfiles, + const u_int16_t ae_max_jfiles) + { + lpmgr lm; + + for (unsigned i = 0; i < 2; i++) + { + if (i) + initialize(lfm, lm, jc, num_jfiles, ae, ae_max_jfiles); + else + { + prepare_recover(lfm, num_jfiles); + recover(lfm, lm, jc, ae, ae_max_jfiles); + } + + // use up all available files + unsigned j = ae_max_jfiles ? ae_max_jfiles : JRNL_MAX_NUM_FILES; + while (ae && j > num_jfiles) + { + const u_int16_t posn = static_cast((lm.num_jfiles() - 1) * ::drand48()); + const u_int16_t incr = 1 + static_cast((lm.ae_jfiles_rem() > 4 + ? 3 : lm.ae_jfiles_rem() - 1) * ::drand48()); + check_insert(lfm, lm, jc, posn, incr); + j -= incr; + } + // these should be over the limit or illegal + check_insert(lfm, lm, jc, 0); + check_insert(lfm, lm, jc, 2, 2); + lfm.destroy_journal(); + } + } + +private: + static void load_vector(const u_int16_t a[], const size_t n, flist& v) + { + for (size_t i = 0; i < n; i++) + v.push_back(a[i]); + } + + static void load_vector(const flist& a, flist& b) + { + for (flist_citr i = a.begin(); i < a.end(); i++) + b.push_back(*i); + } + + static void vectors_equal(const lpmgr& lm, const u_int16_t a[], const size_t n, const flist& b, + const bool pfid_check) + { + BOOST_CHECK_EQUAL(n, b.size()); + for (size_t i = 0; i < n; i++) + { + BOOST_CHECK_EQUAL(a[i], b[i]); + fcntl* fp = lm.get_fcntlp(i); + BOOST_CHECK_MESSAGE(fp != (void*)0, "Unexpected void pointer returned by lpmgr::get_fcntlp()"); + if (fp) BOOST_CHECK_EQUAL(pfid_check ? fp->pfid() : fp->lfid(), pfid_check ? a[i] : i); + } + } + + static void vectors_equal(const lpmgr& lm, const flist& a, const flist& b, const bool pfid_check) + { + BOOST_CHECK_EQUAL(a.size(), b.size()); + for (size_t i = 0; i < a.size(); i++) + { + BOOST_CHECK_EQUAL(a[i], b[i]); + fcntl* fp = lm.get_fcntlp(i); + BOOST_CHECK_MESSAGE(fp != (void*)0, "Unexpected void pointer returned by lpmgr::get_fcntlp()"); + if (fp) BOOST_CHECK_EQUAL(pfid_check ? fp->pfid() : fp->lfid(), pfid_check ? a[i] : i); + } + } + + static void linear_vectors_equal(const lpmgr& lm, const size_t n, const flist& f, const bool pfid_check) + { + BOOST_CHECK_EQUAL(n, f.size()); + for (size_t i = 0; i < n; i++) + { + BOOST_CHECK_EQUAL(i, f[i]); + fcntl* fp = lm.get_fcntlp(i); + BOOST_CHECK_MESSAGE(fp != (void*)0, "Unexpected void pointer returned by lpmgr::get_fcntlp()"); + if (fp) BOOST_CHECK_EQUAL(pfid_check ? fp->pfid() : fp->lfid(), i); + } + } +}; + +// === Tests === + +#ifndef LONG_TEST +/* + * ============================================== + * NORMAL TESTS + * This section contains normal "make check" tests + * for building/packaging. These are built when + * LONG_TEST is _not_ defined. + * ============================================== + */ + +/* + * Check that after construction, the fcntl array _fcntl_arr is empty and the is_init() function returns false. + */ +QPID_AUTO_TEST_CASE(default_constructor) +{ + string test_name = get_test_name(test_filename, "default_constructor"); + try + { + lpmgr lm; + BOOST_CHECK_EQUAL(lm.is_init(), false); + BOOST_CHECK_EQUAL(lm.is_ae(), false); + BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), u_int16_t(0)); + BOOST_CHECK_EQUAL(lm.num_jfiles(), u_int16_t(0)); + BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0); + } + catch(const exception& e) { BOOST_FAIL(e.what()); } + cout << "done" << endl; +} + +/* + * Check that initialize() correctly creates an ordered fcntl array _fcntl_arr. + */ +QPID_AUTO_TEST_CASE(initialize) +{ + string test_name = get_test_name(test_filename, "initialize"); + const u_int16_t num_jfiles = 8; + try + { + jdir::create_dir(test_dir); // Check test dir exists; create it if not + test_jrnl_cb cb; + test_jrnl jc(test_name, test_dir, test_name, cb); + { + lpmgr lm; + lpmgr_test_helper::initialize(lm, jc, num_jfiles, false, 0); + } + { + lpmgr lm; + lpmgr_test_helper::initialize(lm, jc, num_jfiles, true, 0); + } + { + lpmgr lm; + lpmgr_test_helper::initialize(lm, jc, num_jfiles, true, 5 * num_jfiles); + } + } + catch(const exception& e) { BOOST_FAIL(e.what()); } + cout << "done" << endl; +} + +/* + * Check that recover() correctly sets up the specified pfid list order. + */ +QPID_AUTO_TEST_CASE(recover) +{ + string test_name = get_test_name(test_filename, "recover"); + ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() + try + { + test_jrnl_cb cb; + test_jrnl jc(test_name, test_dir, test_name, cb); + lfid_pfid_map lfm(test_name, test_name); + + { + lpmgr lm; + lpmgr_test_helper::prepare_recover(lfm, 8); + lpmgr_test_helper::recover(lfm, lm, jc, false, 0); + lfm.destroy_journal(); + } + { + lpmgr lm; + lpmgr_test_helper::prepare_recover(lfm, 8); + lpmgr_test_helper::recover(lfm, lm, jc, true, 0); + lfm.destroy_journal(); + } + { + lpmgr lm; + lpmgr_test_helper::prepare_recover(lfm, 8); + lpmgr_test_helper::recover(lfm, lm, jc, true, 5 * lfm.size()); + lfm.destroy_journal(); + } + } + catch(const exception& e) { BOOST_FAIL(e.what()); } + cout << "done" << endl; +} + +/* + * Check that finalize() after an initialize() empties _fcntl_arr and that afterwards is_init() returns false. + */ +QPID_AUTO_TEST_CASE(initialize_finalize) +{ + string test_name = get_test_name(test_filename, "initialize_finalize"); + const u_int16_t num_jfiles = 8; + try + { + jdir::create_dir(test_dir); // Check test dir exists; create it if not + test_jrnl_cb cb; + test_jrnl jc(test_name, test_dir, test_name, cb); + { + lpmgr lm; + lpmgr_test_helper::initialize(lm, jc, num_jfiles, false, 0); + lpmgr_test_helper::finalize(lm); + } + { + lpmgr lm; + lpmgr_test_helper::initialize(lm, jc, num_jfiles, true, 0); + lpmgr_test_helper::finalize(lm); + } + { + lpmgr lm; + lpmgr_test_helper::initialize(lm, jc, num_jfiles, true, 5 * num_jfiles); + lpmgr_test_helper::finalize(lm); + } + } + catch(const exception& e) { BOOST_FAIL(e.what()); } + cout << "done" << endl; +} + +/* + * Check that finalize() after a recover() empties _fcntl_arr and that afterwards is_init() returns false. + */ +QPID_AUTO_TEST_CASE(recover_finalize) +{ + string test_name = get_test_name(test_filename, "recover_finalize"); + const u_int16_t num_jfiles = 8; + ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() + try + { + test_jrnl_cb cb; + test_jrnl jc(test_name, test_dir, test_name, cb); + lfid_pfid_map lfm(test_name, test_name); + + { + lpmgr lm; + lpmgr_test_helper::prepare_recover(lfm, num_jfiles); + lpmgr_test_helper::recover(lfm, lm, jc, false, 0); + lpmgr_test_helper::finalize(lm); + lfm.destroy_journal(); + } + { + lpmgr lm; + lpmgr_test_helper::prepare_recover(lfm, num_jfiles); + lpmgr_test_helper::recover(lfm, lm, jc, true, 0); + lpmgr_test_helper::finalize(lm); + lfm.destroy_journal(); + } + { + lpmgr lm; + lpmgr_test_helper::prepare_recover(lfm, num_jfiles); + lpmgr_test_helper::recover(lfm, lm, jc, true, 5 * lfm.size()); + lpmgr_test_helper::finalize(lm); + lfm.destroy_journal(); + } + } + catch(const exception& e) { BOOST_FAIL(e.what()); } + cout << "done" << endl; +} + +/* + * Check that 0 and/or null and other extreme/boundary parameters behave as expected. + */ +QPID_AUTO_TEST_CASE(zero_null_params) +{ + string test_name = get_test_name(test_filename, "zero_null_params"); + const u_int16_t num_jfiles = 8; + try + { + test_jrnl_cb cb; + test_jrnl jc(test_name, test_dir, test_name, cb); + lfid_pfid_map lfm(test_name, test_name); + lpmgr lm; + lpmgr_test_helper::initialize(lfm, lm, jc, num_jfiles, true, 0); + + // Check that inserting 0 files works ok + lpmgr_test_helper::insert(lfm, lm, jc, 0, 0); + lpmgr_test_helper::insert(lfm, lm, jc, 2, 0); + lpmgr_test_helper::insert(lfm, lm, jc, num_jfiles - 1, 0); + } + catch(const exception& e) { BOOST_FAIL(e.what()); } + cout << "done" << endl; +} + +/* + * Check that initialize()/recover() works correctly after a previous initialize()/recover() with/without an intervening + * finalize(). + */ +QPID_AUTO_TEST_CASE(multiple_initialization_recover) +{ + string test_name = get_test_name(test_filename, "multiple_initialization_recover"); + ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() + + // Set combinations of value pairs to be used for number of journal files in first and second init + u_int16_t num_jfiles_arr[][2] = {{8, 12}, {4, 7}, {0, 0}}; // end with zeros + try + { + test_jrnl_cb cb; + test_jrnl jc(test_name, test_dir, test_name, cb); + lfid_pfid_map lfm(test_name, test_name); + for (unsigned p = 0; p < 8; p++) + { + const bool i_0 = p & 0x01; // first bit + const bool i_1 = p & 0x02; // second bit + const bool f = p & 0x04; // third bit + lpmgr_test_helper::check_multiple_initialization_recover(lfm, jc, num_jfiles_arr, i_0, f, i_1); + } + } + catch(const exception& e) { BOOST_FAIL(e.what()); } + cout << "done" << endl; +} + +/* + * Check that insert() works correctly after initialize() and shifts the pfid sequence beyond the insert point correctly: + * + * The following sequence is tested: + * initialize 4 pfids=[0,1,2,3] lfids=[0,1,2,3] + * insert 1 after lfid 0 pfids=[0,4,1,2,3] lfids=[0,2,3,4,1] + * insert 2 after lfid 2 pfids=[0,4,1,5,6,2,3] lfids=[0,2,5,6,1,3,4] + * insert 1 after lfid 6 pfids=[0,4,1,5,6,2,3,7] lfids=[0,2,5,6,1,3,4,7] + * issert 1 after lfid 3 pfids=[0,4,1,5,8,6,2,3,7] lfids=[0,2,6,7,1,3,5,8,4] + */ +QPID_AUTO_TEST_CASE(initialize_insert) +{ + string test_name = get_test_name(test_filename, "initialize_insert"); + const u_int16_t initial_num_jfiles = 8; + try + { + jdir::create_dir(test_dir); // Check test dir exists; create it if not + test_jrnl_cb cb; + test_jrnl jc(test_name, test_dir, test_name, cb); + lfid_pfid_map lfm(test_name, test_name); + lpmgr lm; + lpmgr_test_helper::initialize(lfm, lm, jc, initial_num_jfiles, true, 0); + + lpmgr_test_helper::insert(lfm, lm, jc, 0); + lpmgr_test_helper::insert(lfm, lm, jc, 2, 2); + lpmgr_test_helper::insert(lfm, lm, jc, 6); + lpmgr_test_helper::insert(lfm, lm, jc, 3); + } + catch(const exception& e) { BOOST_FAIL(e.what()); } + cout << "done" << endl; +} + +/* + * Check that insert() works correctly after recover() and shifts the pfid sequence beyond the insert point correctly: + * + * The following sequence is tested: + * recover 4 pfids=[0,2,3,1] lfids=[0,3,1,2] + * insert 1 after lfid 0 pfids=[0,4,2,3,1] lfids=[0,4,2,3,1] + * insert 2 after lfid 2 pfids=[0,4,2,5,6,3,1] lfids=[0,6,2,5,1,3,4] + * insert 1 after lfid 6 pfids=[0,4,2,5,6,3,1,7] lfids=[0,6,2,5,1,3,4,7] + * issert 1 after lfid 3 pfids=[0,4,2,5,8,6,3,1,7] lfids=[0,7,2,6,1,3,5,8,4] + */ +QPID_AUTO_TEST_CASE(recover_insert) +{ + string test_name = get_test_name(test_filename, "recover_insert"); + const u_int16_t initial_num_jfiles = 4; + ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() + try + { + jdir::create_dir(test_dir); // Check test dir exists; create it if not + test_jrnl_cb cb; + test_jrnl jc(test_name, test_dir, test_name, cb); + lfid_pfid_map lfm(test_name, test_name); + lpmgr lm; + lpmgr_test_helper::prepare_recover(lfm, initial_num_jfiles); + lpmgr_test_helper::recover(lfm, lm, jc, true, 0); + + lpmgr_test_helper::insert(lfm, lm, jc, 0); + lpmgr_test_helper::insert(lfm, lm, jc, 2, 2); + lpmgr_test_helper::insert(lfm, lm, jc, 6); + lpmgr_test_helper::insert(lfm, lm, jc, 3); + } + catch(const exception& e) { BOOST_FAIL(e.what()); } + cout << "done" << endl; +} + +/* + * Check that illegal ae parameter combinations are caught and result in an exception being thrown. + */ +QPID_AUTO_TEST_CASE(ae_parameters) +{ + string test_name = get_test_name(test_filename, "ae_parameters"); + ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() + try + { + jdir::create_dir(test_dir); // Check test dir exists; create it if not + test_jrnl_cb cb; + test_jrnl jc(test_name, test_dir, test_name, cb); + lfid_pfid_map lfm(test_name, test_name); + const u_int16_t num_jfiles = 8; + lpmgr lm; + + for (unsigned i = 0; i < 2; i++) + { + if (i) + lpmgr_test_helper::initialize(lfm, lm, jc, num_jfiles, false, 0); + else + { + lpmgr_test_helper::prepare_recover(lfm, num_jfiles); + lpmgr_test_helper::recover(lfm, lm, jc, false, 0); + } + + lpmgr_test_helper::check_ae_max_jfiles(lm, num_jfiles, num_jfiles - 2); + lpmgr_test_helper::check_ae_max_jfiles(lm, num_jfiles, 0); + lpmgr_test_helper::check_ae_max_jfiles(lm, num_jfiles, 2 * num_jfiles); + lpmgr_test_helper::check_ae_max_jfiles(lm, num_jfiles, num_jfiles); + lfm.destroy_journal(); + } + } + catch(const exception& e) { BOOST_FAIL(e.what()); } + cout << "done" << endl; +} + +/* + * Check that initialized or recovered journals with auto-expand disabled will not allow either inserts or appends. + */ +QPID_AUTO_TEST_CASE(ae_disabled) +{ + string test_name = get_test_name(test_filename, "ae_disabled"); + ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() + try + { + jdir::create_dir(test_dir); // Check test dir exists; create it if not + test_jrnl_cb cb; + test_jrnl jc(test_name, test_dir, test_name, cb); + lfid_pfid_map lfm(test_name, test_name); + lpmgr_test_helper::check_limit(lfm, jc, false, 8, 0); + } + catch(const exception& e) { BOOST_FAIL(e.what()); } + cout << "done" << endl; +} + +/* + * Check that initialized or recovered journals with auto-expand enabled and a file limit set will enforce the correct + * limits on inserts and appends. + */ +QPID_AUTO_TEST_CASE(ae_enabled_limit) +{ + string test_name = get_test_name(test_filename, "ae_enabled_limit"); + ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() + try + { + jdir::create_dir(test_dir); // Check test dir exists; create it if not + test_jrnl_cb cb; + test_jrnl jc(test_name, test_dir, test_name, cb); + lfid_pfid_map lfm(test_name, test_name); + lpmgr_test_helper::check_limit(lfm, jc, true, 8, 32); + } + catch(const exception& e) { BOOST_FAIL(e.what()); } + cout << "done" << endl; +} + +/* + * Check that initialized or recovered journals with auto-expand enabled and no file limit set (0) will allow inserts and + * appends up to the file limit JRNL_MAX_NUM_FILES. + */ +QPID_AUTO_TEST_CASE(ae_enabled_unlimited) +{ + string test_name = get_test_name(test_filename, "ae_enabled_unlimited"); + ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() + try + { + jdir::create_dir(test_dir); // Check test dir exists; create it if not + test_jrnl_cb cb; + test_jrnl jc(test_name, test_dir, test_name, cb); + lfid_pfid_map lfm(test_name, test_name); + lpmgr_test_helper::check_limit(lfm, jc, true, 8, 0); + } + catch(const exception& e) { BOOST_FAIL(e.what()); } + cout << "done" << endl; +} + +#else +/* + * ============================================== + * LONG TESTS + * This section contains long tests and soak tests, + * and are run using target check-long (ie "make + * check-long"). These are built when LONG_TEST is + * defined. + * ============================================== + */ + +/* + * Tests randomized combinations of initialization/recovery, initial size, number, size and location of inserts. + * + * To reproduce a specific test, comment out the get_seed() statement and uncomment the literal below, adjusting the seed + * value to that required. + */ +QPID_AUTO_TEST_CASE(randomized_tests) +{ + string test_name = get_test_name(test_filename, "randomized_tests"); + const long seed = get_seed(); + // const long seed = 0x2d9b69d32; + cout << "seed=0x" << hex << seed << dec << " " << flush; + ::srand48(seed); + + lfid_pfid_map lfm(test_name, test_name); + flist pfidl; + flist lfidl; + rcvdat rd; + u_int16_t curr_ae_max_jfiles = 0; + jdir::create_dir(test_dir); // Check test dir exists; create it if not + + for (int test_num = 0; test_num < 250; test_num++) + { + test_jrnl_cb cb; + test_jrnl jc(test_name, test_dir, test_name, cb); + lpmgr lm; + // 50% chance of recovery except first run and if there is still ae space left + const bool recover_flag = test_num > 0 && + curr_ae_max_jfiles > lfm.size() && + 2.0 * ::drand48() < 1.0; + if (recover_flag) + { + // Recover from previous iteration + lfm.get_pfid_list(pfidl); + lfm.get_lfid_list(lfidl); + lfm.write_journal(true, curr_ae_max_jfiles, JFSIZE_SBLKS); + lpmgr_test_helper::rcvdat_init(rd, pfidl, true, curr_ae_max_jfiles); + lm.recover(rd, &jc, &jc.new_fcntl); + lpmgr_test_helper::check_pfids_lfids(lm, pfidl, lfidl); + } + else + { + // Initialize from scratch + const u_int16_t num_jfiles = 4 + u_int16_t(21.0 * ::drand48()); // size: 4 - 25 files + curr_ae_max_jfiles = u_int16_t(4 * num_jfiles * ::drand48()); // size: 0 - 100 files + if (curr_ae_max_jfiles > JRNL_MAX_NUM_FILES) curr_ae_max_jfiles = JRNL_MAX_NUM_FILES; + else if (curr_ae_max_jfiles <= num_jfiles) curr_ae_max_jfiles = 0; + lfm.destroy_journal(); + lfm.journal_create(num_jfiles, num_jfiles); + lfm.get_pfid_list(pfidl); + lfm.get_lfid_list(lfidl); + lm.initialize(num_jfiles, true, curr_ae_max_jfiles, &jc, &jc.new_fcntl); + lpmgr_test_helper::check_linear_pfids_lfids(lm, num_jfiles); + } + + // Loop to insert pfids + const int num_inserts = 1 + int(lfm.size() * ::drand48()); + for (int i = 0; i < num_inserts; i++) + { + const u_int16_t size = lm.num_jfiles(); + const u_int16_t after_lfid = u_int16_t(1.0 * size * ::drand48()); + const u_int16_t num_jfiles = 1 + u_int16_t(4.0 * ::drand48()); + const bool legal = lm.ae_max_jfiles() + ? size + num_jfiles <= lm.ae_max_jfiles() + : size + num_jfiles <= JRNL_MAX_NUM_FILES; + if (legal) + { + lfm.journal_insert(after_lfid, num_jfiles); + lfm.get_pfid_list(pfidl); + lfm.get_lfid_list(lfidl); + + lm.insert(after_lfid, &jc, &jc.new_fcntl, num_jfiles); + lpmgr_test_helper::check_pfids_lfids(lm, pfidl, lfidl); + } + else + { + try + { + lm.insert(after_lfid, &jc, &jc.new_fcntl, num_jfiles); + BOOST_FAIL("lpmgr::insert() succeeded and exceeded limit"); + } + catch (const jexception& e) + { + BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_LFMGR_AEFNUMLIMIT); + break; // no more inserts... + } + } + } + lm.finalize(); + BOOST_CHECK_EQUAL(lm.is_init(), false); + BOOST_CHECK_EQUAL(lm.num_jfiles(), u_int16_t(0)); + BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0); + } + cout << "done" << endl; +} + +#endif + +QPID_AUTO_TEST_SUITE_END() --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org For additional commands, e-mail: commits-help@qpid.apache.org