/*
* Copyright (C) 2018-present ScyllaDB
*/
/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see .
*/
#pragma once
#include
#include
#include
#include
#include
#include "bytes.hh"
namespace tests::random {
inline std::default_random_engine& gen() {
return seastar::testing::local_random_engine;
}
/// Produces random integers from a set of steps.
///
/// Each step has a weight and a uniform distribution that determines the range
/// of values for that step. The probability of the generated number to be from
/// any given step is Ws/Wt, where Ws is the weight of the step and Wt is the
/// sum of the weight of all steps.
template
class stepped_int_distribution {
public:
struct step {
double weight;
std::pair range;
};
private:
std::discrete_distribution _step_index_dist;
std::vector> _step_ranges;
public:
explicit stepped_int_distribution(std::initializer_list steps) {
std::vector step_weights;
for (auto& s : steps) {
step_weights.push_back(s.weight);
_step_ranges.emplace_back(s.range.first, s.range.second);
}
_step_index_dist = std::discrete_distribution{step_weights.begin(), step_weights.end()};
}
template
Integer operator()(RandomEngine& engine) {
return _step_ranges[_step_index_dist(engine)](engine);
}
};
template
T get_int(T min, T max, RandomEngine& engine) {
std::uniform_int_distribution dist(min, max);
return dist(engine);
}
template
T get_int(T max, RandomEngine& engine) {
return get_int(T{0}, max, engine);
}
template
T get_int(RandomEngine& engine) {
return get_int(T{0}, std::numeric_limits::max(), engine);
}
template
T get_int() {
return get_int(T{0}, std::numeric_limits::max(), gen());
}
template
T get_int(T max) {
return get_int(T{0}, max, gen());
}
template
T get_int(T min, T max) {
return get_int(min, max, gen());
}
template
Real get_real(Real min, Real max, RandomEngine& engine) {
auto dist = std::uniform_real_distribution(min, max);
return dist(engine);
}
template
Real get_real(Real max, RandomEngine& engine) {
return get_real(Real{0}, max, engine);
}
template
Real get_real(RandomEngine& engine) {
return get_real(Real{0}, std::numeric_limits::max(), engine);
}
template
Real get_real(Real min, Real max) {
return get_real(min, max, gen());
}
template
Real get_real(Real max) {
return get_real(Real{0}, max, gen());
}
template
Real get_real() {
return get_real(Real{0}, std::numeric_limits::max(), gen());
}
template
inline bool get_bool(RandomEngine& engine) {
static std::bernoulli_distribution dist;
return dist(engine);
}
inline bool get_bool() {
return get_bool(gen());
}
inline bytes get_bytes(size_t n) {
bytes b(bytes::initialized_later(), n);
boost::generate(b, [] { return get_int(); });
return b;
}
inline bytes get_bytes() {
return get_bytes(get_int(128 * 1024));
}
template
inline sstring get_sstring(size_t n, RandomEngine& engine) {
sstring str = uninitialized_string(n);
boost::generate(str, [&engine] { return get_int('a', 'z', engine); });
return str;
}
inline sstring get_sstring(size_t n) {
return get_sstring(n, gen());
}
inline sstring get_sstring() {
return get_sstring(get_int(1024));
}
// Picks a random subset of size `m` from the given vector.
template
std::vector random_subset(std::vector v, unsigned m, std::mt19937& engine) {
assert(m <= v.size());
std::shuffle(v.begin(), v.end(), engine);
return {v.begin(), v.begin() + m};
}
// Picks a random subset of size `m` from the set {0, ..., `n` - 1}.
template
std::vector random_subset(unsigned n, unsigned m, std::mt19937& engine) {
assert(m <= n);
std::vector the_set(n);
std::iota(the_set.begin(), the_set.end(), T{});
return random_subset(std::move(the_set), m, engine);
}
}