bool do_tests(int repeat, int max_num_phases, double max_rate, long long trials) { boost::mt19937 gen; boost::random::uniform_int_distribution<> num_phases_dist(BOOST_RANDOM_HYPEREXP_NUM_PHASES_MIN, max_num_phases); int errors = 0; for (int i = 0; i < repeat; ++i) { const int num_phases = num_phases_dist(gen); boost::random::uniform_real_distribution<> prob_dist(BOOST_RANDOM_HYPEREXP_PROBABILITY_MIN, BOOST_RANDOM_HYPEREXP_PROBABILITY_MAX); boost::random::uniform_real_distribution<> rate_dist(BOOST_RANDOM_HYPEREXP_RATE_MIN, max_rate); const std::vector<double> probabilities = detail::normalize_copy(detail::make_random_vector<double>(num_phases, prob_dist, gen)); const std::vector<double> rates = detail::make_random_vector<double>(num_phases, rate_dist, gen); if (!do_test(probabilities, rates, trials, gen)) { ++errors; } } if (errors != 0) { std::cout << "*** " << errors << " errors detected ***" << std::endl; } return errors == 0; }
static void test(securefs::BtreeDirectory& dir, securefs::Directory& reference, unsigned rounds, double prob_get, double prob_add, double prob_del, unsigned sequence) { (void)sequence; // May be used later bool is_prob_valid = (prob_get >= 0 && prob_add >= 0 && prob_del >= 0 && prob_get + prob_add + prob_del <= 1.0); REQUIRE(is_prob_valid); std::mt19937 engine{std::random_device{}()}; std::uniform_real_distribution<> prob_dist(0, 1); std::uniform_int_distribution<int> name_dist(0, 65535); std::vector<std::string> filenames, filenames_prime; securefs::Directory::callback inserter = [&](const std::string& name, const securefs::id_type&, int) -> bool { filenames.push_back(name); return true; }; securefs::Directory::callback inserter_prime = [&](const std::string& name, const securefs::id_type&, int) -> bool { filenames_prime.push_back(name); return true; }; dir.iterate_over_entries(inserter); reference.iterate_over_entries(inserter_prime); std::sort(filenames.begin(), filenames.end()); std::sort(filenames_prime.begin(), filenames_prime.end()); bool equal_filenames = (filenames == filenames_prime); REQUIRE(equal_filenames); securefs::id_type id, id_prime; int type, type_prime; for (unsigned i = 0; i < rounds; ++i) { auto p = prob_dist(engine); if (p < prob_get) { filenames.clear(); dir.iterate_over_entries(inserter); for (const std::string& n : filenames) { bool got = dir.get_entry(n, id, type); bool got_prime = reference.get_entry(n, id_prime, type_prime); REQUIRE(got == got_prime); REQUIRE(id == id_prime); REQUIRE(type == type_prime); } } else if (p < prob_get + prob_add) { auto name = fmt::format("{0:12d}", name_dist(engine)); securefs::generate_random(id.data(), id.size()); type = S_IFREG; bool added = dir.add_entry(name, id, type); bool added_prime = reference.add_entry(name, id, type); REQUIRE(added == added_prime); filenames.push_back(std::move(name)); } else if (p < prob_get + prob_add + prob_del) { if (filenames.empty()) continue; std::uniform_int_distribution<size_t> index_dist(0, filenames.size() - 1); size_t idx = index_dist(engine); bool removed = dir.remove_entry(filenames[idx], id, type); bool removed_prime = reference.remove_entry(filenames[idx], id_prime, type_prime); REQUIRE(removed == removed_prime); filenames.erase(filenames.begin() + idx); } else { REQUIRE(dir.validate_free_list()); REQUIRE(dir.validate_btree_structure()); } } }