Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lading_payload/src/common.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub(crate) mod config;
pub(crate) mod strings;
67 changes: 67 additions & 0 deletions lading_payload/src/common/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use rand::distr::uniform::SampleUniform;
use serde::{Deserialize, Serialize as SerdeSerialize};
use std::cmp;

/// Range expression for configuration
#[derive(Debug, Deserialize, SerdeSerialize, Clone, PartialEq, Copy)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]

pub enum ConfRange<T>
where
T: PartialEq + cmp::PartialOrd + Clone + Copy,
{
/// A constant T
Constant(T),
/// In which a T is chosen between `min` and `max`, inclusive of `max`.
Inclusive {
/// The minimum of the range.
min: T,
/// The maximum of the range.
max: T,
},
}

impl<T> ConfRange<T>
where
T: PartialEq + cmp::PartialOrd + Clone + Copy,
{
/// Returns true if the range provided by the user is valid, false
/// otherwise.
pub(crate) fn valid(&self) -> (bool, &'static str) {
match self {
Self::Constant(_) => (true, ""),
Self::Inclusive { min, max } => (min < max, "min must be less than max"),
}
}

pub(crate) fn start(&self) -> T {
match self {
ConfRange::Constant(c) => *c,
ConfRange::Inclusive { min, .. } => *min,
}
}

pub(crate) fn end(&self) -> T {
match self {
ConfRange::Constant(c) => *c,
ConfRange::Inclusive { max, .. } => *max,
}
}
}

impl<T> ConfRange<T>
where
T: PartialEq + cmp::PartialOrd + Clone + Copy + SampleUniform,
{
pub(crate) fn sample<R>(&self, rng: &mut R) -> T
where
R: rand::Rng + ?Sized,
{
match self {
ConfRange::Constant(c) => *c,
ConfRange::Inclusive { min, max } => rng.random_range(*min..=*max),
}
}
}
68 changes: 66 additions & 2 deletions lading_payload/src/common/strings.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! Code for the quick creation of randomize strings

use crate::common::config::ConfRange;
use rand::{Rng, distr::uniform::SampleUniform, seq::IndexedRandom};
use std::ops::Range;

use rand::distr::uniform::SampleUniform;

const ALPHANUM: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

/// A pool of strings
Expand Down Expand Up @@ -131,6 +131,70 @@ impl Pool {
}
}

pub(crate) fn choose_or_not_ref<'a, R, T>(mut rng: &mut R, pool: &'a [T]) -> Option<&'a T>
where
R: rand::Rng + ?Sized,
{
if rng.random() {
pool.choose(&mut rng)
} else {
None
}
}

pub(crate) fn choose_or_not_fn<R, T, F>(rng: &mut R, func: F) -> Option<T>
where
T: Clone,
R: rand::Rng + ?Sized,
F: FnOnce(&mut R) -> Option<T>,
{
if rng.random() { func(rng) } else { None }
}

#[inline]
/// Generate a total number of strings randomly chosen from the range `min_max` with a maximum length
/// per string of `max_length`.
pub(crate) fn random_strings_with_length<R>(
pool: &Pool,
min_max: Range<usize>,
max_length: u16,
rng: &mut R,
) -> Vec<String>
where
R: Rng + ?Sized,
{
let total = rng.random_range(min_max);
let length_range = ConfRange::Inclusive {
min: 1,
max: max_length,
};

random_strings_with_length_range(pool, total, length_range, rng)
}

#[inline]
/// Generate a `total` number of strings with a maximum length per string of
/// `max_length`.
pub(crate) fn random_strings_with_length_range<R>(
pool: &Pool,
total: usize,
length_range: ConfRange<u16>,
mut rng: &mut R,
) -> Vec<String>
where
R: Rng + ?Sized,
{
let mut buf = Vec::with_capacity(total);
for _ in 0..total {
let sz = length_range.sample(&mut rng) as usize;
buf.push(String::from(
pool.of_size(&mut rng, sz)
.expect("failed to generate string"),
));
}
buf
}

#[cfg(test)]
mod test {
use proptest::prelude::*;
Expand Down
145 changes: 10 additions & 135 deletions lading_payload/src/dogstatsd.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
//! `DogStatsD` payload.

use std::{cmp, fmt, io::Write, ops::Range, rc::Rc};
use std::{fmt, io::Write, rc::Rc};

use rand::{
Rng,
distr::{uniform::SampleUniform, weighted::WeightedIndex},
prelude::Distribution,
seq::IndexedRandom,
};
use rand::{Rng, distr::weighted::WeightedIndex, prelude::Distribution};
use serde::{Deserialize, Serialize as SerdeSerialize};
use tracing::{debug, warn};

use crate::{Serialize, common::strings};
use crate::{
Serialize,
common::{
config::ConfRange,
strings,
strings::{random_strings_with_length, random_strings_with_length_range},
},
};

use self::{
common::tags, event::EventGenerator, metric::MetricGenerator,
Expand Down Expand Up @@ -144,69 +146,6 @@ impl Default for ValueConf {
}
}
}
/// Range expression for configuration
#[derive(Debug, Deserialize, SerdeSerialize, Clone, PartialEq, Copy)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]

pub enum ConfRange<T>
where
T: PartialEq + cmp::PartialOrd + Clone + Copy,
{
/// A constant T
Constant(T),
/// In which a T is chosen between `min` and `max`, inclusive of `max`.
Inclusive {
/// The minimum of the range.
min: T,
/// The maximum of the range.
max: T,
},
}

impl<T> ConfRange<T>
where
T: PartialEq + cmp::PartialOrd + Clone + Copy,
{
/// Returns true if the range provided by the user is valid, false
/// otherwise.
fn valid(&self) -> (bool, &'static str) {
match self {
Self::Constant(_) => (true, ""),
Self::Inclusive { min, max } => (min < max, "min must be less than max"),
}
}

fn start(&self) -> T {
match self {
ConfRange::Constant(c) => *c,
ConfRange::Inclusive { min, .. } => *min,
}
}

fn end(&self) -> T {
match self {
ConfRange::Constant(c) => *c,
ConfRange::Inclusive { max, .. } => *max,
}
}
}

impl<T> ConfRange<T>
where
T: PartialEq + cmp::PartialOrd + Clone + Copy + SampleUniform,
{
fn sample<R>(&self, rng: &mut R) -> T
where
R: rand::Rng + ?Sized,
{
match self {
ConfRange::Constant(c) => *c,
ConfRange::Inclusive { min, max } => rng.random_range(*min..=*max),
}
}
}

/// Configure the `DogStatsD` payload.
#[derive(Debug, Deserialize, SerdeSerialize, Clone, PartialEq, Copy)]
Expand Down Expand Up @@ -359,70 +298,6 @@ impl Config {
}
}

fn choose_or_not_ref<'a, R, T>(mut rng: &mut R, pool: &'a [T]) -> Option<&'a T>
where
R: rand::Rng + ?Sized,
{
if rng.random() {
pool.choose(&mut rng)
} else {
None
}
}

fn choose_or_not_fn<R, T, F>(rng: &mut R, func: F) -> Option<T>
where
T: Clone,
R: rand::Rng + ?Sized,
F: FnOnce(&mut R) -> Option<T>,
{
if rng.random() { func(rng) } else { None }
}

#[inline]
/// Generate a total number of strings randomly chosen from the range `min_max` with a maximum length
/// per string of `max_length`.
fn random_strings_with_length<R>(
pool: &strings::Pool,
min_max: Range<usize>,
max_length: u16,
rng: &mut R,
) -> Vec<String>
where
R: Rng + ?Sized,
{
let total = rng.random_range(min_max);
let length_range = ConfRange::Inclusive {
min: 1,
max: max_length,
};

random_strings_with_length_range(pool, total, length_range, rng)
}

#[inline]
/// Generate a `total` number of strings with a maximum length per string of
/// `max_length`.
fn random_strings_with_length_range<R>(
pool: &strings::Pool,
total: usize,
length_range: ConfRange<u16>,
mut rng: &mut R,
) -> Vec<String>
where
R: Rng + ?Sized,
{
let mut buf = Vec::with_capacity(total);
for _ in 0..total {
let sz = length_range.sample(&mut rng) as usize;
buf.push(String::from(
pool.of_size(&mut rng, sz)
.expect("failed to generate string"),
));
}
buf
}

#[derive(Debug, Clone)]
struct MemberGenerator {
kind_weights: WeightedIndex<u16>,
Expand Down
4 changes: 3 additions & 1 deletion lading_payload/src/dogstatsd/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use rand::{Rng, distr::StandardUniform, prelude::Distribution};

use crate::{Error, Generator, common::strings};

use super::{ConfRange, choose_or_not_fn, common};
use self::strings::choose_or_not_fn;

use super::{ConfRange, common};

#[derive(Debug, Clone)]
pub(crate) struct EventGenerator {
Expand Down
4 changes: 3 additions & 1 deletion lading_payload/src/dogstatsd/metric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ use rand::{
use crate::{Error, Generator, common::strings, dogstatsd::metric::template::Template};
use tracing::debug;

use self::strings::choose_or_not_ref;

use super::{
ConfRange, ValueConf, choose_or_not_ref,
ConfRange, ValueConf,
common::{self, NumValueGenerator},
};

Expand Down
7 changes: 2 additions & 5 deletions lading_payload/src/dogstatsd/service_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ use std::fmt;

use rand::{Rng, distr::StandardUniform, prelude::Distribution, seq::IndexedRandom};

use crate::{Error, Generator};
use crate::{Error, Generator, common::strings::choose_or_not_ref};

use super::{
choose_or_not_ref,
common::{self, tags::Tagset},
};
use super::common::{self, tags::Tagset};

#[derive(Debug, Clone)]
pub(crate) struct ServiceCheckGenerator {
Expand Down
Loading