summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2024-01-15 04:19:18 -0500
committerGitHub <noreply@github.com>2024-01-15 04:19:18 -0500
commitdd66ae774ca9a93a2c1bd471e3b1ba2075044f15 (patch)
tree8c6c76195150944da8a42b7131b65acb8f78918c /tests
parentf093902aef3954bef79fa348c46e1bf3949675cf (diff)
refactor: simplify some config -> constraints code (#1383)
* refactor: simplify some config -> constraints code * iteratively progress... * update bcr; this might need testing since I removed some old proc code * widget side * fix battery * fix widget tests with bandaid for now The issue was that the calculations assume a certain ratio for CPU legends. * add some tests * bump up * fix proc drawing issues So with the proc widget in certain places, there would be a panic during constraint determination. Looks like back when I wrote this I made some gross assumptions about certain things. In particular, the problem here was that the search added an additional "one" height, so that needs to be accounted for after we removed the "doubling" code. * tests * fix tests * reorganize tests * clippy * fix cross tests not working * fix builds for android
Diffstat (limited to 'tests')
-rw-r--r--tests/integration/arg_tests.rs (renamed from tests/arg_tests.rs)56
-rw-r--r--tests/integration/invalid_config_tests.rs (renamed from tests/invalid_config_tests.rs)88
-rw-r--r--tests/integration/layout_management_tests.rs (renamed from tests/layout_management_tests.rs)0
-rw-r--r--tests/integration/layout_movement_tests.rs (renamed from tests/layout_movement_tests.rs)0
-rw-r--r--tests/integration/main.rs11
-rw-r--r--tests/integration/util.rs144
-rw-r--r--tests/integration/valid_config_tests.rs69
-rw-r--r--tests/util.rs76
-rw-r--r--tests/valid_configs/all_proc.toml22
-rw-r--r--tests/valid_configs/cpu_doughnut.toml29
-rw-r--r--tests/valid_configs/empty_config.toml (renamed from tests/empty_config.toml)0
-rw-r--r--tests/valid_configs/many_proc.toml22
12 files changed, 347 insertions, 170 deletions
diff --git a/tests/arg_tests.rs b/tests/integration/arg_tests.rs
index af4df7b8..13ebc5f0 100644
--- a/tests/arg_tests.rs
+++ b/tests/integration/arg_tests.rs
@@ -1,15 +1,13 @@
//! These tests are mostly here just to ensure that invalid results will be caught when passing arguments.
-mod util;
use assert_cmd::prelude::*;
use predicates::prelude::*;
-use util::*;
+
+use crate::util::{btm_command, no_cfg_btm_command};
#[test]
fn test_small_rate() {
- btm_command()
- .arg("-C")
- .arg("./tests/empty_config.toml")
+ btm_command(&["-C", "./tests/valid_configs/empty_config.toml"])
.arg("-r")
.arg("249")
.assert()
@@ -21,9 +19,7 @@ fn test_small_rate() {
#[test]
fn test_large_default_time() {
- btm_command()
- .arg("-C")
- .arg("./tests/empty_config.toml")
+ no_cfg_btm_command()
.arg("-t")
.arg("18446744073709551616")
.assert()
@@ -33,9 +29,7 @@ fn test_large_default_time() {
#[test]
fn test_small_default_time() {
- btm_command()
- .arg("-C")
- .arg("./tests/empty_config.toml")
+ no_cfg_btm_command()
.arg("-t")
.arg("900")
.assert()
@@ -47,9 +41,7 @@ fn test_small_default_time() {
#[test]
fn test_large_delta_time() {
- btm_command()
- .arg("-C")
- .arg("./tests/empty_config.toml")
+ no_cfg_btm_command()
.arg("-d")
.arg("18446744073709551616")
.assert()
@@ -59,9 +51,7 @@ fn test_large_delta_time() {
#[test]
fn test_small_delta_time() {
- btm_command()
- .arg("-C")
- .arg("./tests/empty_config.toml")
+ no_cfg_btm_command()
.arg("-d")
.arg("900")
.assert()
@@ -73,9 +63,7 @@ fn test_small_delta_time() {
#[test]
fn test_large_rate() {
- btm_command()
- .arg("-C")
- .arg("./tests/empty_config.toml")
+ no_cfg_btm_command()
.arg("-r")
.arg("18446744073709551616")
.assert()
@@ -86,9 +74,7 @@ fn test_large_rate() {
#[test]
fn test_negative_rate() {
// This test should auto fail due to how clap works
- btm_command()
- .arg("-C")
- .arg("./tests/empty_config.toml")
+ no_cfg_btm_command()
.arg("-r")
.arg("-1000")
.assert()
@@ -98,9 +84,7 @@ fn test_negative_rate() {
#[test]
fn test_invalid_rate() {
- btm_command()
- .arg("-C")
- .arg("./tests/empty_config.toml")
+ no_cfg_btm_command()
.arg("-r")
.arg("100-1000")
.assert()
@@ -110,9 +94,7 @@ fn test_invalid_rate() {
#[test]
fn test_conflicting_temps() {
- btm_command()
- .arg("-C")
- .arg("./tests/empty_config.toml")
+ no_cfg_btm_command()
.arg("-c")
.arg("-f")
.assert()
@@ -122,9 +104,7 @@ fn test_conflicting_temps() {
#[test]
fn test_invalid_default_widget_1() {
- btm_command()
- .arg("-C")
- .arg("./tests/empty_config.toml")
+ no_cfg_btm_command()
.arg("--default_widget_type")
.arg("fake_widget")
.assert()
@@ -134,9 +114,7 @@ fn test_invalid_default_widget_1() {
#[test]
fn test_invalid_default_widget_2() {
- btm_command()
- .arg("-C")
- .arg("./tests/empty_config.toml")
+ no_cfg_btm_command()
.arg("--default_widget_type")
.arg("cpu")
.arg("--default_widget_count")
@@ -150,9 +128,7 @@ fn test_invalid_default_widget_2() {
#[test]
fn test_missing_default_widget_type() {
- btm_command()
- .arg("-C")
- .arg("./tests/empty_config.toml")
+ no_cfg_btm_command()
.arg("--default_widget_count")
.arg("3")
.assert()
@@ -165,7 +141,7 @@ fn test_missing_default_widget_type() {
#[test]
#[cfg_attr(feature = "battery", ignore)]
fn test_battery_flag() {
- btm_command()
+ no_cfg_btm_command()
.arg("--battery")
.assert()
.failure()
@@ -177,7 +153,7 @@ fn test_battery_flag() {
#[test]
#[cfg_attr(feature = "gpu", ignore)]
fn test_gpu_flag() {
- btm_command()
+ no_cfg_btm_command()
.arg("--enable_gpu")
.assert()
.failure()
diff --git a/tests/invalid_config_tests.rs b/tests/integration/invalid_config_tests.rs
index 62e2a376..92a67eac 100644
--- a/tests/invalid_config_tests.rs
+++ b/tests/integration/invalid_config_tests.rs
@@ -1,16 +1,13 @@
-mod util;
+//! These tests are for testing some invalid config-file-specific options.
use assert_cmd::prelude::*;
use predicates::prelude::*;
-use util::*;
-// These tests are for testing some config file-specific options.
+use crate::util::btm_command;
#[test]
fn test_toml_mismatch_type() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/toml_mismatch_type.toml")
+ btm_command(&["-C", "./tests/invalid_configs/toml_mismatch_type.toml"])
.assert()
.failure()
.stderr(predicate::str::contains("invalid type"));
@@ -18,9 +15,7 @@ fn test_toml_mismatch_type() {
#[test]
fn test_empty_layout() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/empty_layout.toml")
+ btm_command(&["-C", "./tests/invalid_configs/empty_layout.toml"])
.assert()
.failure()
.stderr(predicate::str::contains("at least one widget"));
@@ -28,21 +23,20 @@ fn test_empty_layout() {
#[test]
fn test_invalid_layout_widget_type() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/invalid_layout_widget_type.toml")
- .assert()
- .failure()
- .stderr(predicate::str::contains("invalid widget name"));
+ btm_command(&[
+ "-C",
+ "./tests/invalid_configs/invalid_layout_widget_type.toml",
+ ])
+ .assert()
+ .failure()
+ .stderr(predicate::str::contains("invalid widget name"));
}
/// This test isn't really needed as this is technically covered by TOML spec.
/// However, I feel like it's worth checking anyways - not like it takes long.
#[test]
fn test_duplicate_temp_type() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/duplicate_temp_type.toml")
+ btm_command(&["-C", "./tests/invalid_configs/duplicate_temp_type.toml"])
.assert()
.failure()
.stderr(predicate::str::contains("duplicate key"));
@@ -51,9 +45,7 @@ fn test_duplicate_temp_type() {
/// Checks for if a hex is valid
#[test]
fn test_invalid_colour_hex() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/invalid_colour_hex.toml")
+ btm_command(&["-C", "./tests/invalid_configs/invalid_colour_hex.toml"])
.assert()
.failure()
.stderr(predicate::str::contains("invalid hex color"));
@@ -62,9 +54,7 @@ fn test_invalid_colour_hex() {
/// Checks for if a hex is too long
#[test]
fn test_invalid_colour_hex_2() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/invalid_colour_hex_2.toml")
+ btm_command(&["-C", "./tests/invalid_configs/invalid_colour_hex_2.toml"])
.assert()
.failure()
.stderr(predicate::str::contains("invalid hex color"));
@@ -74,9 +64,7 @@ fn test_invalid_colour_hex_2() {
/// boundary errors!
#[test]
fn test_invalid_colour_hex_3() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/invalid_colour_hex_3.toml")
+ btm_command(&["-C", "./tests/invalid_configs/invalid_colour_hex_3.toml"])
.assert()
.failure()
.stderr(predicate::str::contains("invalid hex color"));
@@ -84,9 +72,7 @@ fn test_invalid_colour_hex_3() {
#[test]
fn test_invalid_colour_name() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/invalid_colour_name.toml")
+ btm_command(&["-C", "./tests/invalid_configs/invalid_colour_name.toml"])
.assert()
.failure()
.stderr(predicate::str::contains("invalid named color"));
@@ -94,9 +80,7 @@ fn test_invalid_colour_name() {
#[test]
fn test_invalid_colour_rgb() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/invalid_colour_rgb.toml")
+ btm_command(&["-C", "./tests/invalid_configs/invalid_colour_rgb.toml"])
.assert()
.failure()
.stderr(predicate::str::contains("invalid RGB"));
@@ -104,9 +88,7 @@ fn test_invalid_colour_rgb() {
#[test]
fn test_invalid_colour_rgb_2() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/invalid_colour_rgb_2.toml")
+ btm_command(&["-C", "./tests/invalid_configs/invalid_colour_rgb_2.toml"])
.assert()
.failure()
.stderr(predicate::str::contains("invalid RGB"));
@@ -114,9 +96,7 @@ fn test_invalid_colour_rgb_2() {
#[test]
fn test_invalid_colour_string() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/invalid_colour_string.toml")
+ btm_command(&["-C", "./tests/invalid_configs/invalid_colour_string.toml"])
.assert()
.failure()
.stderr(predicate::str::contains("invalid named color"));
@@ -124,29 +104,29 @@ fn test_invalid_colour_string() {
#[test]
fn test_lone_default_widget_count() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/lone_default_widget_count.toml")
- .assert()
- .failure()
- .stderr(predicate::str::contains("it must be used with"));
+ btm_command(&[
+ "-C",
+ "./tests/invalid_configs/lone_default_widget_count.toml",
+ ])
+ .assert()
+ .failure()
+ .stderr(predicate::str::contains("it must be used with"));
}
#[test]
fn test_invalid_default_widget_count() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/invalid_default_widget_count.toml")
- .assert()
- .failure()
- .stderr(predicate::str::contains("number too large"));
+ btm_command(&[
+ "-C",
+ "./tests/invalid_configs/invalid_default_widget_count.toml",
+ ])
+ .assert()
+ .failure()
+ .stderr(predicate::str::contains("number too large"));
}
#[test]
fn test_invalid_process_column() {
- btm_command()
- .arg("-C")
- .arg("./tests/invalid_configs/invalid_process_column.toml")
+ btm_command(&["-C", "./tests/invalid_configs/invalid_process_column.toml"])
.assert()
.failure()
.stderr(predicate::str::contains("doesn't match"));
diff --git a/tests/layout_management_tests.rs b/tests/integration/layout_management_tests.rs
index 711e7f02..711e7f02 100644
--- a/tests/layout_management_tests.rs
+++ b/tests/integration/layout_management_tests.rs
diff --git a/tests/layout_movement_tests.rs b/tests/integration/layout_movement_tests.rs
index d74e62d0..d74e62d0 100644
--- a/tests/layout_movement_tests.rs
+++ b/tests/integration/layout_movement_tests.rs
diff --git a/tests/integration/main.rs b/tests/integration/main.rs
new file mode 100644
index 00000000..01c3f9f5
--- /dev/null
+++ b/tests/integration/main.rs
@@ -0,0 +1,11 @@
+//! Integration tests for bottom.
+
+mod util;
+
+mod arg_tests;
+mod invalid_config_tests;
+mod layout_management_tests;
+mod layout_movement_tests;
+
+#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
+mod valid_config_tests;
diff --git a/tests/integration/util.rs b/tests/integration/util.rs
new file mode 100644
index 00000000..e1ee1ffd
--- /dev/null
+++ b/tests/integration/util.rs
@@ -0,0 +1,144 @@
+use std::{env, ffi::OsString, path::Path, process::Command};
+
+use hashbrown::HashMap;
+
+#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
+use portable_pty::{native_pty_system, Child, CommandBuilder, MasterPty, PtySize};
+
+pub fn abs_path(path: &str) -> OsString {
+ Path::new(path).canonicalize().unwrap().into_os_string()
+}
+
+/// Returns a QEMU runner target given an architecture.
+fn get_qemu_target(arch: &str) -> &str {
+ match arch {
+ "armv7" => "arm",
+ "i686" => "i386",
+ "powerpc" => "ppc",
+ "powerpc64le" => "ppc64le",
+ _ => arch,
+ }
+}
+
+/// This is required since running binary tests via cross can cause be tricky! We need to basically "magically" grab
+/// the correct runner in some cases, which can be done by inspecting env variables that should only show up while
+/// using cross.
+///
+/// Originally inspired by [ripgrep's test files](https://cs.github.com/BurntSushi/ripgrep/blob/9f0e88bcb14e02da1b88872435b17d74786640b5/tests/util.rs#L470),
+/// but adapted to work more generally with the architectures supported by bottom after looking through cross'
+/// [linux-runner](https://github.com/cross-rs/cross/blob/main/docker/linux-runner) file.
+fn cross_runner() -> Option<String> {
+ const TARGET_RUNNER: &str = "CARGO_TARGET_RUNNER";
+ const CROSS_RUNNER: &str = "CROSS_RUNNER";
+
+ let env_mapping = env::vars_os()
+ .filter_map(|(k, v)| {
+ let (k, v) = (k.to_string_lossy(), v.to_string_lossy());
+
+ if k.starts_with("CARGO_TARGET_") && k.ends_with("_RUNNER") && !v.is_empty() {
+ Some((TARGET_RUNNER.to_string(), v.to_string()))
+ } else if k == CROSS_RUNNER && !v.is_empty() {
+ Some((k.to_string(), v.to_string()))
+ } else {
+ None
+ }
+ })
+ .collect::<HashMap<_, _>>();
+
+ if let Some(cross_runner) = env_mapping.get(CROSS_RUNNER) {
+ if cross_runner == "qemu-user" {
+ env_mapping.get(TARGET_RUNNER).map(|target_runner| {
+ format!(
+ "qemu-{}",
+ get_qemu_target(target_runner.split_ascii_whitespace().last().unwrap())
+ )
+ })
+ } else {
+ None
+ }
+ } else {
+ env_mapping.get(TARGET_RUNNER).cloned()
+ }
+}
+
+const BTM_EXE_PATH: &str = env!("CARGO_BIN_EXE_btm");
+const RUNNER_ENV_VARS: [(&str, &str); 1] = [("NO_COLOR", "1")];
+const DEFAULT_CFG: [&str; 2] = ["-C", "./tests/valid_configs/empty_config.toml"];
+
+/// Returns the [`Command`] of a binary invocation of bottom, alongside
+/// any required env variables.
+pub fn btm_command(args: &[&str]) -> Command {
+ let mut cmd = match cross_runner() {
+ None => Command::new(BTM_EXE_PATH),
+ Some(runner) => {
+ let mut cmd = Command::new(runner);
+ cmd.envs(RUNNER_ENV_VARS);
+ cmd.arg(BTM_EXE_PATH);
+ cmd
+ }
+ };
+
+ let mut prev = "";
+ for arg in args.iter() {
+ if prev == "-C" {
+ // This is the config file; make sure we set it to absolute path!
+ cmd.arg(abs_path(arg));
+ } else {
+ cmd.arg(arg);
+ }
+
+ prev = arg;
+ }
+
+ cmd
+}
+
+/// Returns the [`Command`] of a binary invocation of bottom, alongside
+/// any required env variables, and with the default, empty config file.
+pub fn no_cfg_btm_command() -> Command {
+ btm_command(&DEFAULT_CFG)
+}
+
+/// Spawns `btm` in a pty, returning the pair alongside a handle to the child.
+#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
+pub fn spawn_btm_in_pty(args: &[&str]) -> (Box<dyn MasterPty>, Box<dyn Child>) {
+ let native_pty = native_pty_system();
+
+ let pair = native_pty
+ .openpty(PtySize {
+ rows: 100,
+ cols: 100,
+ pixel_width: 1,
+ pixel_height: 1,
+ })
+ .unwrap();
+
+ let btm_exe = BTM_EXE_PATH;
+ let mut cmd = match cross_runner() {
+ None => CommandBuilder::new(btm_exe),
+ Some(runner) => {
+ let mut cmd = CommandBuilder::new(runner);
+ for (env, val) in RUNNER_ENV_VARS {
+ cmd.env(env, val);
+ }
+ cmd.arg(BTM_EXE_PATH);
+
+ cmd
+ }
+ };
+
+ let args = if args.is_empty() { &DEFAULT_CFG } else { args };
+ let mut prev = "";
+ for arg in args.iter() {
+ if prev == "-C" {
+ // This is the config file; make sure we set it to absolute path!
+ cmd.arg(abs_path(arg));
+ } else {
+ cmd.arg(arg);
+ }
+
+ prev = arg;
+ }
+
+ (pair.master, pair.slave.spawn_command(cmd).unwrap())
+}
diff --git a/tests/integration/valid_config_tests.rs b/tests/integration/valid_config_tests.rs
new file mode 100644
index 00000000..b152edb3
--- /dev/null
+++ b/tests/integration/valid_config_tests.rs
@@ -0,0 +1,69 @@
+//! Tests config files that have sometimes caused issues despite being valid.
+
+use std::{io::Read, thread, time::Duration};
+
+use crate::util::spawn_btm_in_pty;
+
+fn reader_to_string(mut reader: Box<dyn Read>) -> String {
+ let mut buf = String::default();
+ reader.read_to_string(&mut buf).unwrap();
+
+ buf
+}
+
+fn run_and_kill(args: &[&str]) {
+ let (master, mut handle) = spawn_btm_in_pty(args);
+ let reader = master.try_clone_reader().unwrap();
+ let _ = master.take_writer().unwrap();
+
+ const TIMES_CHECKED: u64 = 6; // Check 6 times, once every 500ms, for 3 seconds total.
+
+ for _ in 0..TIMES_CHECKED {
+ thread::sleep(Duration::from_millis(500));
+ match handle.try_wait() {
+ Ok(Some(exit)) => {
+ println!("output: {}", reader_to_string(reader));
+ panic!("program terminated unexpectedly (exit status: {exit:?})");
+ }
+ Err(e) => {
+ println!("output: {}", reader_to_string(reader));
+ panic!("error while trying to wait: {e}")
+ }
+ _ => {}
+ }
+ }
+
+ handle.kill().unwrap();
+}
+
+#[test]
+fn test_basic() {
+ run_and_kill(&[]);
+}
+
+/// A test to ensure that a bad config will fail the `run_and_kill` function.
+#[test]
+#[should_panic]
+fn test_bad_basic() {
+ run_and_kill(&["--this_does_not_exist"]);
+}
+
+#[test]
+fn test_empty() {
+ run_and_kill(&["-C", "./tests/valid_configs/empty_config.toml"]);
+}
+
+#[test]
+fn test_many_proc() {
+ run_and_kill(&["-C", "./tests/valid_configs/many_proc.toml"]);
+}
+
+#[test]
+fn test_all_proc() {
+ run_and_kill(&["-C", "./tests/valid_configs/all_proc.toml"]);
+}
+
+#[test]
+fn test_cpu_doughnut() {
+ run_and_kill(&["-C", "./tests/valid_configs/cpu_doughnut.toml"]);
+}
diff --git a/tests/util.rs b/tests/util.rs
deleted file mode 100644
index b89a3027..00000000
--- a/tests/util.rs
+++ /dev/null
@@ -1,76 +0,0 @@
-use std::{env, process::Command};
-
-use hashbrown::HashMap;
-
-/// Returns a QEMU runner target given an architecture.
-fn get_qemu_target(arch: &str) -> &str {
- match arch {
- "armv7" => "arm",
- "i686" => "i386",
- "powerpc" => "ppc",
- "powerpc64le" => "ppc64le",
- _ => arch,
- }
-}
-
-/// This is required since running binary tests via cross can cause be tricky! We need to basically "magically" grab
-/// the correct runner in some cases, which can be done by inspecting env variables that should only show up while
-/// using cross.
-///
-/// Originally inspired by [ripgrep's test files](https://cs.github.com/BurntSushi/ripgrep/blob/9f0e88bcb14e02da1b88872435b17d74786640b5/tests/util.rs#L470),
-/// but adapted to work more generally with the architectures supported by bottom after looking through cross'
-/// [linux-runner](https://github.com/cross-rs/cross/blob/main/docker/linux-runner) file.
-fn cross_runner() -> Option<String> {
- const TARGET_RUNNER: &str = "CARGO_TARGET_RUNNER";
- const CROSS_RUNNER: &str = "CROSS_RUNNER";
-
- let env_mapping = env::vars_os()
- .filter_map(|(k, v)| {
- let (k, v) = (k.to_string_lossy(), v.to_string_lossy());
-
- if k.starts_with("CARGO_TARGET_") && k.ends_with("_RUNNER") && !v.is_empty() {
- Some((TARGET_RUNNER.to_string(), v.to_string()))
- } else if k == CROSS_RUNNER && !v.is_empty() {
- Some((k.to_string(), v.to_string()))
- } else {
- None
- }
- })
- .collect::<HashMap<_, _>>();
-
- if let Some(cross_runner) = env_mapping.get(CROSS_RUNNER) {
- if cross_runner == "qemu-user" {
- env_mapping.get(TARGET_RUNNER).map(|target_runner| {
- format!(
- "qemu-{}",
- get_qemu_target(
- target_runner
- .split_ascii_whitespace()
- .collect::<Vec<_>>()
- .last()
- .unwrap()
- )
- )
- })
- } else {
- None
- }
- } else {
- env_mapping.get(TARGET_RUNNER).cloned()
- }
-}
-
-/// Returns the [`Command`] of a binary invocation of bottom, alongside
-/// any required env variables.
-pub fn btm_command() -> Command {
- let btm_exe = env!("CARGO_BIN_EXE_btm");
- match cross_runner() {
- None => Command::new(btm_exe),
- Some(runner) => {
- let mut cmd = Command::new(runner);
- cmd.env("NO_COLOR", "1");
- cmd.arg(btm_exe);
- cmd
- }
- }
-}
diff --git a/tests/valid_configs/all_proc.toml b/tests/valid_configs/all_proc.toml
new file mode 100644
index 00000000..781e3836
--- /dev/null
+++ b/tests/valid_configs/all_proc.toml
@@ -0,0 +1,22 @@
+[[row]]
+ratio = 30
+[[row.child]]
+type = "proc"
+[[row]]
+ratio = 40
+[[row.child]]
+ratio = 4
+type = "proc"
+[[row.child]]
+ratio = 3
+[[row.child.child]]
+type = "proc"
+[[row.child.child]]
+type = "proc"
+[[row]]
+ratio = 30
+[[row.child]]
+type = "proc"
+[[row.child]]
+type = "proc"
+default = true
diff --git a/tests/valid_configs/cpu_doughnut.toml b/tests/valid_configs/cpu_doughnut.toml
new file mode 100644
index 00000000..c099078f
--- /dev/null
+++ b/tests/valid_configs/cpu_doughnut.toml
@@ -0,0 +1,29 @@
+[[row]]
+[[row.child]]
+type = "cpu"
+[[row.child]]
+type = "cpu"
+[[row.child]]
+type = "cpu"
+
+[[row]]
+[[row.child]]
+[[row.child.child]]
+type = "cpu"
+[[row.child.child]]
+type = "cpu"
+[[row.child]]
+type = "empty"
+[[row.child]]
+[[row.child.child]]
+type = "cpu"
+[[row.child.child]]
+type = "cpu"
+
+[[row]]
+[[row.child]]
+type = "cpu"
+[[row.child]]
+type = "cpu"
+[[row.child]]
+type = "cpu"
diff --git a/tests/empty_config.toml b/tests/valid_configs/empty_config.toml
index b2c0f98b..b2c0f98b 100644
--- a/tests/empty_config.toml
+++ b/tests/valid_configs/empty_config.toml
diff --git a/tests/valid_configs/many_proc.toml b/tests/valid_configs/many_proc.toml
new file mode 100644
index 00000000..440eb469
--- /dev/null
+++ b/tests/valid_configs/many_proc.toml
@@ -0,0 +1,22 @@
+[[row]]
+ratio = 30
+[[row.child]]
+type = "cpu"
+[[row]]
+ratio = 40
+[[row.child]]
+ratio = 4
+type = "mem"
+[[row.child]]
+ratio = 3
+[[row.child.child]]
+type = "proc"
+[[row.child.child]]
+type = "proc"
+[[row]]
+ratio = 30
+[[row.child]]
+type = "net"
+[[row.child]]
+type = "proc"
+default = true