mirror of
https://github.com/uutils/util-linux.git
synced 2026-06-10 16:13:52 -07:00
Move to use uutests
This commit is contained in:
committed by
Daniel Hofstetter
parent
b95a5dae6a
commit
fa608413b2
Generated
+53
@@ -262,6 +262,22 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e9666f4a9a948d4f1dff0c08a4512b0f7c86414b23960104c243c10d79f4c3"
|
||||
dependencies = [
|
||||
"ctor-proc-macro",
|
||||
"dtor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctor-proc-macro"
|
||||
version = "0.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f211af61d8efdd104f96e57adf5e426ba1bc3ed7a4ead616e15e5881fd79c4d"
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.4.0"
|
||||
@@ -310,6 +326,21 @@ dependencies = [
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtor"
|
||||
version = "0.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "222ef136a1c687d4aa0395c175f2c4586e379924c352fd02f7870cf7de783c23"
|
||||
dependencies = [
|
||||
"dtor-proc-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtor-proc-macro"
|
||||
version = "0.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7454e41ff9012c00d53cf7f475c5e3afa3b91b7c90568495495e8d9bf47a1055"
|
||||
|
||||
[[package]]
|
||||
name = "dunce"
|
||||
version = "1.0.5"
|
||||
@@ -1198,6 +1229,7 @@ dependencies = [
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"clap_mangen",
|
||||
"ctor",
|
||||
"dns-lookup",
|
||||
"libc",
|
||||
"nix",
|
||||
@@ -1231,6 +1263,7 @@ dependencies = [
|
||||
"uu_uuidgen",
|
||||
"uucore",
|
||||
"uuid",
|
||||
"uutests",
|
||||
"xattr",
|
||||
]
|
||||
|
||||
@@ -1472,6 +1505,26 @@ dependencies = [
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uutests"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12453ee52c9cffa6bf2c74f9f35ed0c824b846cb0b4bdee829d8150332e7204c"
|
||||
dependencies = [
|
||||
"ctor",
|
||||
"glob",
|
||||
"libc",
|
||||
"nix",
|
||||
"pretty_assertions",
|
||||
"rand",
|
||||
"regex",
|
||||
"rlimit",
|
||||
"tempfile",
|
||||
"time",
|
||||
"uucore",
|
||||
"xattr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
|
||||
+5
-2
@@ -56,6 +56,7 @@ libmount-sys = "0.1.1"
|
||||
linux-raw-sys = { version = "0.10.0", features = ["ioctl"] }
|
||||
md-5 = "0.10.6"
|
||||
nix = { version = "0.30", default-features = false }
|
||||
parse_datetime = "0.11.0"
|
||||
phf = "0.12.0"
|
||||
phf_codegen = "0.12.1"
|
||||
rand = { version = "0.9.0", features = ["small_rng"] }
|
||||
@@ -71,21 +72,21 @@ textwrap = { version = "0.16.0", features = ["terminal_size"] }
|
||||
thiserror = "2.0"
|
||||
uucore = "0.1.0"
|
||||
uuid = { version = "1.16.0", features = ["rng-rand"] }
|
||||
uutests = "0.1.0"
|
||||
windows = { version = "0.61.1" }
|
||||
xattr = "1.3.1"
|
||||
parse_datetime = "0.11.0"
|
||||
|
||||
[dependencies]
|
||||
clap = { workspace = true }
|
||||
clap_complete = { workspace = true }
|
||||
clap_mangen = { workspace = true }
|
||||
dns-lookup = { workspace = true }
|
||||
parse_datetime = {workspace = true}
|
||||
phf = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
textwrap = { workspace = true }
|
||||
uucore = { workspace = true }
|
||||
parse_datetime = {workspace = true}
|
||||
|
||||
#
|
||||
blockdev = { optional = true, version = "0.0.1", package = "uu_blockdev", path = "src/uu/blockdev" }
|
||||
@@ -107,6 +108,7 @@ setsid = { optional = true, version = "0.0.1", package = "uu_setsid", path ="src
|
||||
uuidgen = { optional = true, version = "0.0.1", package = "uu_uuidgen", path ="src/uu/uuidgen" }
|
||||
|
||||
[dev-dependencies]
|
||||
ctor = "0.4.1"
|
||||
# dmesg test require fixed-boot-time feature turned on.
|
||||
dmesg = { version = "0.0.1", package = "uu_dmesg", path = "src/uu/dmesg", features = ["fixed-boot-time"] }
|
||||
libc = { workspace = true }
|
||||
@@ -114,6 +116,7 @@ pretty_assertions = "1"
|
||||
rand = { workspace = true }
|
||||
regex = { workspace = true }
|
||||
tempfile = { workspace = true }
|
||||
uutests = { workspace = true }
|
||||
uucore = { workspace = true, features = ["entries", "process", "signals"] }
|
||||
uuid = { workspace = true }
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn test_invalid_arg() {
|
||||
@@ -23,9 +25,12 @@ fn test_report_mutually_exclusive_with_others() {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
mod linux {
|
||||
use crate::common::util::TestScenario;
|
||||
use regex::Regex;
|
||||
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn test_fails_on_first_error() {
|
||||
new_ucmd!()
|
||||
@@ -56,7 +61,9 @@ mod linux {
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
mod non_linux {
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn test_fails_on_unsupported_platforms() {
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
// file that was distributed with this source code.
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::new_ucmd;
|
||||
#[cfg(target_os = "linux")]
|
||||
use uutests::util::TestScenario;
|
||||
#[cfg(target_os = "linux")]
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
use crate::common::util::TestScenario;
|
||||
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn test_invalid_arg() {
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn test_invalid_arg() {
|
||||
@@ -23,7 +25,10 @@ fn test_operations_mutually_exclusive() {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
mod linux {
|
||||
use crate::common::util::TestScenario;
|
||||
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn test_fails_on_non_existing_path() {
|
||||
@@ -48,7 +53,9 @@ mod linux {
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
mod non_linux {
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn test_fails_on_unsupported_platforms() {
|
||||
|
||||
@@ -4,8 +4,13 @@
|
||||
// file that was distributed with this source code.
|
||||
// spell-checker:ignore (words) symdir somefakedir
|
||||
|
||||
use uutests::at_and_ucmd;
|
||||
#[cfg(unix)]
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::new_ucmd;
|
||||
#[cfg(unix)]
|
||||
use uutests::util::TestScenario;
|
||||
#[cfg(unix)]
|
||||
use uutests::util_name;
|
||||
|
||||
#[cfg(unix)]
|
||||
use regex::Regex;
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn test_invalid_arg() {
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
// file that was distributed with this source code.
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::new_ucmd;
|
||||
#[cfg(target_os = "linux")]
|
||||
use uutests::util::TestScenario;
|
||||
#[cfg(target_os = "linux")]
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use crate::common::util::TestScenario;
|
||||
use std::path::Path;
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
fn write_file_content(dir: &Path, name: &str, content: &str) {
|
||||
std::fs::create_dir_all(dir).unwrap();
|
||||
|
||||
@@ -7,7 +7,9 @@ use std::io::Write;
|
||||
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn test_invalid_arg() {
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn test_invalid_verb() {
|
||||
@@ -24,7 +26,9 @@ fn test_no_terminal() {
|
||||
|
||||
#[cfg(not(target_family = "unix"))]
|
||||
mod non_unix {
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn test_fails_on_unsupported_platforms() {
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use crate::common::util::TestScenario;
|
||||
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
#[test]
|
||||
fn test_invalid_arg() {
|
||||
new_ucmd!().arg("--definitely-invalid").fails().code_is(1);
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
// file that was distributed with this source code.
|
||||
// spell-checker:ignore (words) symdir somefakedir
|
||||
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn test_invalid_arg() {
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::at_and_ucmd;
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn test_invalid_arg() {
|
||||
|
||||
@@ -5,8 +5,11 @@
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
mod unix {
|
||||
use crate::common::util::{TestScenario, UCommand, TESTS_BINARY};
|
||||
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::get_tests_binary;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util::UCommand;
|
||||
use uutests::util_name;
|
||||
#[test]
|
||||
fn test_invalid_arg() {
|
||||
new_ucmd!().arg("--definitely-invalid").fails().code_is(1);
|
||||
@@ -77,8 +80,11 @@ mod unix {
|
||||
|
||||
#[test]
|
||||
fn unprivileged_user_cannot_steal_controlling_tty() {
|
||||
let shell_cmd =
|
||||
format!("{TESTS_BINARY} setsid -w -c {TESTS_BINARY} setsid -w -c /b/usrin/true");
|
||||
let shell_cmd = format!(
|
||||
"{} setsid -w -c {} setsid -w -c /b/usrin/true",
|
||||
get_tests_binary(),
|
||||
get_tests_binary()
|
||||
);
|
||||
UCommand::new()
|
||||
.terminal_simulation(true)
|
||||
.arg(&shell_cmd)
|
||||
@@ -92,7 +98,8 @@ mod unix {
|
||||
#[test]
|
||||
fn unprivileged_user_can_take_new_controlling_tty() {
|
||||
let shell_cmd = format!(
|
||||
"/usr/bin/cat /proc/self/stat; {TESTS_BINARY} setsid -w -c /usr/bin/cat /proc/self/stat"
|
||||
"/usr/bin/cat /proc/self/stat; {} setsid -w -c /usr/bin/cat /proc/self/stat",
|
||||
get_tests_binary()
|
||||
);
|
||||
|
||||
let cmd_result = UCommand::new()
|
||||
@@ -124,7 +131,8 @@ mod unix {
|
||||
#[test]
|
||||
fn setsid_takes_session_leadership() {
|
||||
let shell_cmd = format!(
|
||||
"/usr/bin/cat /proc/self/stat; {TESTS_BINARY} setsid /usr/bin/cat /proc/self/stat"
|
||||
"/usr/bin/cat /proc/self/stat; {} setsid /usr/bin/cat /proc/self/stat",
|
||||
get_tests_binary()
|
||||
);
|
||||
|
||||
let cmd_result = UCommand::new()
|
||||
@@ -161,7 +169,9 @@ mod unix {
|
||||
|
||||
#[cfg(not(target_family = "unix"))]
|
||||
mod non_unix {
|
||||
use crate::common::util::TestScenario;
|
||||
use uutests::new_ucmd;
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
|
||||
#[test]
|
||||
fn unsupported_platforms() {
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
// This file is part of the uutils coreutils package.
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
/// Platform-independent helper for constructing a `PathBuf` from individual elements
|
||||
#[macro_export]
|
||||
macro_rules! path_concat {
|
||||
($e:expr, ..$n:expr) => {{
|
||||
use std::path::PathBuf;
|
||||
let n = $n;
|
||||
let mut pb = PathBuf::new();
|
||||
for _ in 0..n {
|
||||
pb.push($e);
|
||||
}
|
||||
pb.to_str().unwrap().to_owned()
|
||||
}};
|
||||
($($e:expr),*) => {{
|
||||
use std::path::PathBuf;
|
||||
let mut pb = PathBuf::new();
|
||||
$(
|
||||
pb.push($e);
|
||||
)*
|
||||
pb.to_str().unwrap().to_owned()
|
||||
}};
|
||||
}
|
||||
|
||||
/// Deduce the name of the test binary from the test filename.
|
||||
///
|
||||
/// e.g.: `tests/by-util/test_cat.rs` -> `cat`
|
||||
#[macro_export]
|
||||
macro_rules! util_name {
|
||||
() => {
|
||||
module_path!()
|
||||
.split("_")
|
||||
.nth(1)
|
||||
.and_then(|s| s.split("::").next())
|
||||
.expect("no test name")
|
||||
};
|
||||
}
|
||||
|
||||
/// Convenience macro for acquiring a [`UCommand`] builder.
|
||||
///
|
||||
/// Returns the following:
|
||||
/// - a [`UCommand`] builder for invoking the binary to be tested
|
||||
///
|
||||
/// This macro is intended for quick, single-call tests. For more complex tests
|
||||
/// that require multiple invocations of the tested binary, see [`TestScenario`]
|
||||
///
|
||||
/// [`UCommand`]: crate::tests::common::util::UCommand
|
||||
/// [`TestScenario]: crate::tests::common::util::TestScenario
|
||||
#[macro_export]
|
||||
macro_rules! new_ucmd {
|
||||
() => {
|
||||
TestScenario::new(util_name!()).ucmd()
|
||||
};
|
||||
}
|
||||
|
||||
/// Convenience macro for acquiring a [`UCommand`] builder and a test path.
|
||||
///
|
||||
/// Returns a tuple containing the following:
|
||||
/// - an [`AtPath`] that points to a unique temporary test directory
|
||||
/// - a [`UCommand`] builder for invoking the binary to be tested
|
||||
///
|
||||
/// This macro is intended for quick, single-call tests. For more complex tests
|
||||
/// that require multiple invocations of the tested binary, see [`TestScenario`]
|
||||
///
|
||||
/// [`UCommand`]: crate::tests::common::util::UCommand
|
||||
/// [`AtPath`]: crate::tests::common::util::AtPath
|
||||
/// [`TestScenario]: crate::tests::common::util::TestScenario
|
||||
#[macro_export]
|
||||
macro_rules! at_and_ucmd {
|
||||
() => {{
|
||||
let ts = TestScenario::new(util_name!());
|
||||
(ts.fixtures.clone(), ts.ucmd())
|
||||
}};
|
||||
}
|
||||
|
||||
/// If `common::util::expected_result` returns an error, i.e. the `util` in `$PATH` doesn't
|
||||
/// include a coreutils version string or the version is too low,
|
||||
/// this macro can be used to automatically skip the test and print the reason.
|
||||
#[macro_export]
|
||||
macro_rules! unwrap_or_return {
|
||||
( $e:expr ) => {
|
||||
match $e {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
println!("test skipped: {}", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
// This file is part of the uutils coreutils package.
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
#[macro_use]
|
||||
pub mod macros;
|
||||
pub mod random;
|
||||
pub mod util;
|
||||
@@ -1,340 +0,0 @@
|
||||
// This file is part of the uutils util-linux package.
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use rand::distr::{Distribution, Uniform};
|
||||
use rand::{rng, Rng};
|
||||
|
||||
/// Samples alphanumeric characters `[A-Za-z0-9]` including newline `\n`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// use rand::{Rng, thread_rng};
|
||||
///
|
||||
/// let vec = thread_rng()
|
||||
/// .sample_iter(AlphanumericNewline)
|
||||
/// .take(10)
|
||||
/// .collect::<Vec<u8>>();
|
||||
/// println!("Random chars: {}", String::from_utf8(vec).unwrap());
|
||||
/// ```
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct AlphanumericNewline;
|
||||
|
||||
impl AlphanumericNewline {
|
||||
/// The charset to act upon
|
||||
const CHARSET: &'static [u8] =
|
||||
b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n";
|
||||
|
||||
/// Generate a random byte from [`Self::CHARSET`] and return it as `u8`.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `rng`: A [`rand::Rng`]
|
||||
///
|
||||
/// returns: u8
|
||||
fn random<R>(rng: &mut R) -> u8
|
||||
where
|
||||
R: Rng + ?Sized,
|
||||
{
|
||||
let idx = rng.random_range(0..Self::CHARSET.len());
|
||||
Self::CHARSET[idx]
|
||||
}
|
||||
}
|
||||
|
||||
impl Distribution<u8> for AlphanumericNewline {
|
||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
|
||||
Self::random(rng)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a random string from a [`Distribution`]
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// use crate::common::random::{AlphanumericNewline, RandomString};
|
||||
/// use rand::distributions::Alphanumeric;
|
||||
///
|
||||
/// // generates a 100 byte string with characters from AlphanumericNewline
|
||||
/// let random_string = RandomString::generate(AlphanumericNewline, 100);
|
||||
/// assert_eq!(100, random_string.len());
|
||||
///
|
||||
/// // generates a 100 byte string with 10 newline characters not ending with a newline
|
||||
/// let string = RandomString::generate_with_delimiter(Alphanumeric, b'\n', 10, false, 100);
|
||||
/// assert_eq!(100, random_string.len());
|
||||
/// ```
|
||||
pub struct RandomString;
|
||||
|
||||
impl RandomString {
|
||||
/// Generate a random string from the given [`Distribution`] with the given `length` in bytes.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `dist`: A u8 [`Distribution`]
|
||||
/// * `length`: the length of the resulting string in bytes
|
||||
///
|
||||
/// returns: String
|
||||
pub fn generate<D>(dist: D, length: usize) -> String
|
||||
where
|
||||
D: Distribution<u8>,
|
||||
{
|
||||
rng()
|
||||
.sample_iter(dist)
|
||||
.take(length)
|
||||
.map(|b| b as char)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Generate a random string from the [`Distribution`] with the given `length` in bytes. The
|
||||
/// function takes a `delimiter`, which is randomly distributed in the string, such that exactly
|
||||
/// `num_delimiter` amount of `delimiter`s occur. If `end_with_delimiter` is set, then the
|
||||
/// string ends with the delimiter, else the string does not end with the delimiter.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `dist`: A `u8` [`Distribution`]
|
||||
/// * `delimiter`: A `u8` delimiter, which does not need to be included in the `Distribution`
|
||||
/// * `num_delimiter`: The number of `delimiter`s contained in the resulting string
|
||||
/// * `end_with_delimiter`: If the string shall end with the given delimiter
|
||||
/// * `length`: the length of the resulting string in bytes
|
||||
///
|
||||
/// returns: String
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// use crate::common::random::{AlphanumericNewline, RandomString};
|
||||
///
|
||||
/// // generates a 100 byte string with 10 '\0' byte characters not ending with a '\0' byte
|
||||
/// let string = RandomString::generate_with_delimiter(AlphanumericNewline, 0, 10, false, 100);
|
||||
/// assert_eq!(100, random_string.len());
|
||||
/// assert_eq!(
|
||||
/// 10,
|
||||
/// random_string.as_bytes().iter().filter(|p| **p == 0).count()
|
||||
/// );
|
||||
/// assert!(!random_string.as_bytes().ends_with(&[0]));
|
||||
/// ```
|
||||
pub fn generate_with_delimiter<D>(
|
||||
dist: D,
|
||||
delimiter: u8,
|
||||
num_delimiter: usize,
|
||||
end_with_delimiter: bool,
|
||||
length: usize,
|
||||
) -> String
|
||||
where
|
||||
D: Distribution<u8>,
|
||||
{
|
||||
if length == 0 {
|
||||
return String::new();
|
||||
} else if length == 1 {
|
||||
return if num_delimiter > 0 {
|
||||
String::from(delimiter as char)
|
||||
} else {
|
||||
String::from(rng().sample(&dist) as char)
|
||||
};
|
||||
}
|
||||
|
||||
let samples = length - 1;
|
||||
let mut result: Vec<u8> = rng().sample_iter(&dist).take(samples).collect();
|
||||
|
||||
if num_delimiter == 0 {
|
||||
result.push(rng().sample(&dist));
|
||||
return String::from_utf8(result).unwrap();
|
||||
}
|
||||
|
||||
let num_delimiter = if end_with_delimiter {
|
||||
num_delimiter - 1
|
||||
} else {
|
||||
num_delimiter
|
||||
};
|
||||
|
||||
// safe to unwrap because samples is at least 1, thus high > low
|
||||
let between = Uniform::new(0, samples).unwrap();
|
||||
for _ in 0..num_delimiter {
|
||||
let mut pos = between.sample(&mut rng());
|
||||
let turn = pos;
|
||||
while result[pos] == delimiter {
|
||||
pos += 1;
|
||||
if pos >= samples {
|
||||
pos = 0;
|
||||
}
|
||||
if pos == turn {
|
||||
break;
|
||||
}
|
||||
}
|
||||
result[pos] = delimiter;
|
||||
}
|
||||
|
||||
if end_with_delimiter {
|
||||
result.push(delimiter);
|
||||
} else {
|
||||
result.push(rng().sample(&dist));
|
||||
}
|
||||
|
||||
String::from_utf8(result).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rand::distr::Alphanumeric;
|
||||
|
||||
#[test]
|
||||
fn test_random_string_generate() {
|
||||
let random_string = RandomString::generate(AlphanumericNewline, 0);
|
||||
assert_eq!(0, random_string.len());
|
||||
|
||||
let random_string = RandomString::generate(AlphanumericNewline, 1);
|
||||
assert_eq!(1, random_string.len());
|
||||
|
||||
let random_string = RandomString::generate(AlphanumericNewline, 100);
|
||||
assert_eq!(100, random_string.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_random_string_generate_with_delimiter_when_length_is_zero() {
|
||||
let random_string = RandomString::generate_with_delimiter(Alphanumeric, 0, 0, false, 0);
|
||||
assert_eq!(0, random_string.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_random_string_generate_with_delimiter_when_num_delimiter_is_greater_than_length() {
|
||||
let random_string = RandomString::generate_with_delimiter(Alphanumeric, 0, 2, false, 1);
|
||||
assert_eq!(1, random_string.len());
|
||||
assert!(random_string.as_bytes().contains(&0));
|
||||
assert!(random_string.as_bytes().ends_with(&[0]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_random_string_generate_with_delimiter_should_end_with_delimiter() {
|
||||
let random_string = RandomString::generate_with_delimiter(Alphanumeric, 0, 1, true, 1);
|
||||
assert_eq!(1, random_string.len());
|
||||
assert_eq!(
|
||||
1,
|
||||
random_string.as_bytes().iter().filter(|p| **p == 0).count()
|
||||
);
|
||||
assert!(random_string.as_bytes().ends_with(&[0]));
|
||||
|
||||
let random_string = RandomString::generate_with_delimiter(Alphanumeric, 0, 1, false, 1);
|
||||
assert_eq!(1, random_string.len());
|
||||
assert_eq!(
|
||||
1,
|
||||
random_string.as_bytes().iter().filter(|p| **p == 0).count()
|
||||
);
|
||||
assert!(random_string.as_bytes().ends_with(&[0]));
|
||||
|
||||
let random_string = RandomString::generate_with_delimiter(Alphanumeric, 0, 1, true, 2);
|
||||
assert_eq!(2, random_string.len());
|
||||
assert_eq!(
|
||||
1,
|
||||
random_string.as_bytes().iter().filter(|p| **p == 0).count()
|
||||
);
|
||||
assert!(random_string.as_bytes().ends_with(&[0]));
|
||||
|
||||
let random_string = RandomString::generate_with_delimiter(Alphanumeric, 0, 2, true, 2);
|
||||
assert_eq!(2, random_string.len());
|
||||
assert_eq!(
|
||||
2,
|
||||
random_string.as_bytes().iter().filter(|p| **p == 0).count()
|
||||
);
|
||||
assert!(random_string.as_bytes().ends_with(&[0]));
|
||||
|
||||
let random_string = RandomString::generate_with_delimiter(Alphanumeric, 0, 1, true, 3);
|
||||
assert_eq!(3, random_string.len());
|
||||
assert_eq!(
|
||||
1,
|
||||
random_string.as_bytes().iter().filter(|p| **p == 0).count()
|
||||
);
|
||||
assert!(random_string.as_bytes().ends_with(&[0]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_random_string_generate_with_delimiter_should_not_end_with_delimiter() {
|
||||
let random_string = RandomString::generate_with_delimiter(Alphanumeric, 0, 0, false, 1);
|
||||
assert_eq!(1, random_string.len());
|
||||
assert_eq!(
|
||||
0,
|
||||
random_string.as_bytes().iter().filter(|p| **p == 0).count()
|
||||
);
|
||||
|
||||
let random_string = RandomString::generate_with_delimiter(Alphanumeric, 0, 0, true, 1);
|
||||
assert_eq!(1, random_string.len());
|
||||
assert_eq!(
|
||||
0,
|
||||
random_string.as_bytes().iter().filter(|p| **p == 0).count()
|
||||
);
|
||||
|
||||
let random_string = RandomString::generate_with_delimiter(Alphanumeric, 0, 1, false, 2);
|
||||
assert_eq!(2, random_string.len());
|
||||
assert_eq!(
|
||||
1,
|
||||
random_string.as_bytes().iter().filter(|p| **p == 0).count()
|
||||
);
|
||||
assert!(!random_string.as_bytes().ends_with(&[0]));
|
||||
|
||||
let random_string = RandomString::generate_with_delimiter(Alphanumeric, 0, 1, false, 3);
|
||||
assert_eq!(3, random_string.len());
|
||||
assert_eq!(
|
||||
1,
|
||||
random_string.as_bytes().iter().filter(|p| **p == 0).count()
|
||||
);
|
||||
assert!(!random_string.as_bytes().ends_with(&[0]));
|
||||
|
||||
let random_string = RandomString::generate_with_delimiter(Alphanumeric, 0, 2, false, 3);
|
||||
assert_eq!(3, random_string.len());
|
||||
assert_eq!(
|
||||
2,
|
||||
random_string.as_bytes().iter().filter(|p| **p == 0).count()
|
||||
);
|
||||
assert!(!random_string.as_bytes().ends_with(&[0]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generate_with_delimiter_with_greater_length() {
|
||||
let random_string =
|
||||
RandomString::generate_with_delimiter(Alphanumeric, 0, 100, false, 1000);
|
||||
assert_eq!(1000, random_string.len());
|
||||
assert_eq!(
|
||||
100,
|
||||
random_string.as_bytes().iter().filter(|p| **p == 0).count()
|
||||
);
|
||||
assert!(!random_string.as_bytes().ends_with(&[0]));
|
||||
|
||||
let random_string = RandomString::generate_with_delimiter(Alphanumeric, 0, 100, true, 1000);
|
||||
assert_eq!(1000, random_string.len());
|
||||
assert_eq!(
|
||||
100,
|
||||
random_string.as_bytes().iter().filter(|p| **p == 0).count()
|
||||
);
|
||||
assert!(random_string.as_bytes().ends_with(&[0]));
|
||||
}
|
||||
|
||||
/// Originally used to exclude an error within the `random` module. The two
|
||||
/// affected tests timed out on windows, but only in the ci. These tests are
|
||||
/// also the source for the concrete numbers. The timed out tests are
|
||||
/// `test_tail.rs::test_pipe_when_lines_option_given_input_size_has_multiple_size_of_buffer_size`
|
||||
/// `test_tail.rs::test_pipe_when_bytes_option_given_input_size_has_multiple_size_of_buffer_size`.
|
||||
#[test]
|
||||
fn test_generate_random_strings_when_length_is_around_critical_buffer_sizes() {
|
||||
let length = 8192 * 3;
|
||||
let random_string = RandomString::generate(AlphanumericNewline, length);
|
||||
assert_eq!(length, random_string.len());
|
||||
|
||||
let length = 8192 * 3 + 1;
|
||||
let random_string =
|
||||
RandomString::generate_with_delimiter(Alphanumeric, b'\n', 100, true, length);
|
||||
assert_eq!(length, random_string.len());
|
||||
assert_eq!(
|
||||
100,
|
||||
random_string
|
||||
.as_bytes()
|
||||
.iter()
|
||||
.filter(|p| **p == b'\n')
|
||||
.count()
|
||||
);
|
||||
assert!(!random_string.as_bytes().ends_with(&[0]));
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user