bug: fix certain custom column combinations causing issues (#1140)

* docs: update some docs related to processes

* bug: temp bandaid on column feature to avoid dupes issue
This commit is contained in:
Clement Tsang 2023-05-09 19:20:34 -04:00 committed by GitHub
parent 53d7cbb170
commit dae65bcd56
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 345 additions and 86 deletions

View file

@ -6,6 +6,6 @@ You can configure which columns are shown by the process widget by setting the `
```toml ```toml
[processes] [processes]
# Pick which columns you want to use. # Pick which columns you want to use in any order.
columns = ["cpu%", "mem", "mem%", "pid", "count", "name", "command", "read", "write", "Tread", "twrite", "state", "user", "time"] columns = ["cpu%", "mem", "mem%", "pid", "count", "name", "command", "read", "write", "Tread", "twrite", "state", "user", "time"]
``` ```

View file

@ -19,7 +19,7 @@ By default, the main process table displays the following information for each p
- PID - PID
- Name of the process - Name of the process
- CPU use percentage (note this is averaged out per available thread) - CPU use percentage (note this is averaged out per available thread by default)
- Memory use percentage - Memory use percentage
- Reads per second - Reads per second
- Writes per second - Writes per second

View file

@ -1243,7 +1243,7 @@ impl App {
.proc_state .proc_state
.get_mut_widget_state(self.current_widget.widget_id) .get_mut_widget_state(self.current_widget.widget_id)
{ {
proc_widget_state.select_column(ProcWidgetColumn::ProcNameOrCmd); proc_widget_state.select_column(ProcWidgetColumn::ProcNameOrCommand);
} }
} else if let Some(disk) = self } else if let Some(disk) = self
.disk_state .disk_state

View file

@ -22,10 +22,7 @@ use crate::{
constants::*, constants::*,
units::data_units::DataUnit, units::data_units::DataUnit,
utils::error::{self, BottomError}, utils::error::{self, BottomError},
widgets::{ widgets::*,
BatteryWidgetState, CpuWidgetState, DiskTableWidget, MemWidgetState, NetWidgetState,
ProcColumn, ProcTableConfig, ProcWidgetMode, ProcWidgetState, TempWidgetState,
},
}; };
pub mod layout_options; pub mod layout_options;
@ -35,7 +32,7 @@ use self::process_columns::ProcessConfig;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
#[derive(Clone, Debug, Default, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize)]
pub struct Config { pub struct Config {
pub flags: Option<ConfigFlags>, pub flags: Option<ConfigFlags>,
pub colors: Option<ConfigColours>, pub colors: Option<ConfigColours>,
@ -223,7 +220,7 @@ pub fn build_app(
let network_scale_type = get_network_scale_type(matches, config); let network_scale_type = get_network_scale_type(matches, config);
let network_use_binary_prefix = is_flag_enabled!(network_use_binary_prefix, matches, config); let network_use_binary_prefix = is_flag_enabled!(network_use_binary_prefix, matches, config);
let proc_columns: Option<IndexSet<ProcColumn>> = { let proc_columns: Option<IndexSet<ProcWidgetColumn>> = {
let columns = config let columns = config
.processes .processes
.as_ref() .as_ref()

View file

@ -1,16 +1,16 @@
use serde::{Deserialize, Serialize}; use serde::Deserialize;
use crate::widgets::ProcColumn; use crate::widgets::ProcWidgetColumn;
/// Process column settings. /// Process column settings.
#[derive(Clone, Debug, Default, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize)]
pub struct ProcessConfig { pub struct ProcessConfig {
pub columns: Option<Vec<ProcColumn>>, pub columns: Option<Vec<ProcWidgetColumn>>,
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::widgets::ProcColumn; use crate::widgets::ProcWidgetColumn;
use super::ProcessConfig; use super::ProcessConfig;
@ -31,50 +31,55 @@ mod test {
assert_eq!( assert_eq!(
generated.columns, generated.columns,
Some(vec![ Some(vec![
ProcColumn::CpuPercent, ProcWidgetColumn::Cpu,
ProcColumn::Pid, ProcWidgetColumn::PidOrCount,
ProcColumn::User, ProcWidgetColumn::User,
ProcColumn::MemoryVal, ProcWidgetColumn::Mem,
ProcColumn::TotalRead, ProcWidgetColumn::TotalRead,
ProcColumn::TotalWrite, ProcWidgetColumn::TotalWrite,
ProcColumn::ReadPerSecond, ProcWidgetColumn::ReadPerSecond,
ProcColumn::WritePerSecond, ProcWidgetColumn::WritePerSecond,
ProcColumn::Time, ProcWidgetColumn::Time,
ProcColumn::User, ProcWidgetColumn::User,
ProcColumn::State, ProcWidgetColumn::State,
]), ]),
); );
} }
#[test] #[test]
fn process_column_settings_2() { fn process_column_settings_2() {
let config = r#"columns = ["MEM%"]"#; let config = r#"columns = ["MEM", "TWrite", "Cpuz", "read", "wps"]"#;
let generated: ProcessConfig = toml_edit::de::from_str(config).unwrap();
assert_eq!(generated.columns, Some(vec![ProcColumn::MemoryPercent]));
}
#[test]
fn process_column_settings_3() {
let config = r#"columns = ["MEM%", "TWrite", "Cpuz", "read", "wps"]"#;
toml_edit::de::from_str::<ProcessConfig>(config).expect_err("Should error out!"); toml_edit::de::from_str::<ProcessConfig>(config).expect_err("Should error out!");
} }
#[test] #[test]
fn process_column_settings_4() { fn process_column_settings_3() {
let config = r#"columns = ["Twrite", "T.Write"]"#; let config = r#"columns = ["Twrite", "T.Write"]"#;
let generated: ProcessConfig = toml_edit::de::from_str(config).unwrap(); let generated: ProcessConfig = toml_edit::de::from_str(config).unwrap();
assert_eq!(generated.columns, Some(vec![ProcColumn::TotalWrite; 2])); assert_eq!(
generated.columns,
Some(vec![ProcWidgetColumn::TotalWrite; 2])
);
let config = r#"columns = ["Tread", "T.read"]"#; let config = r#"columns = ["Tread", "T.read"]"#;
let generated: ProcessConfig = toml_edit::de::from_str(config).unwrap(); let generated: ProcessConfig = toml_edit::de::from_str(config).unwrap();
assert_eq!(generated.columns, Some(vec![ProcColumn::TotalRead; 2])); assert_eq!(
generated.columns,
Some(vec![ProcWidgetColumn::TotalRead; 2])
);
let config = r#"columns = ["read", "rps", "r/s"]"#; let config = r#"columns = ["read", "rps", "r/s"]"#;
let generated: ProcessConfig = toml_edit::de::from_str(config).unwrap(); let generated: ProcessConfig = toml_edit::de::from_str(config).unwrap();
assert_eq!(generated.columns, Some(vec![ProcColumn::ReadPerSecond; 3])); assert_eq!(
generated.columns,
Some(vec![ProcWidgetColumn::ReadPerSecond; 3])
);
let config = r#"columns = ["write", "wps", "w/s"]"#; let config = r#"columns = ["write", "wps", "w/s"]"#;
let generated: ProcessConfig = toml_edit::de::from_str(config).unwrap(); let generated: ProcessConfig = toml_edit::de::from_str(config).unwrap();
assert_eq!(generated.columns, Some(vec![ProcColumn::WritePerSecond; 3])); assert_eq!(
generated.columns,
Some(vec![ProcWidgetColumn::WritePerSecond; 3])
);
} }
} }

View file

@ -3,6 +3,7 @@ use std::{borrow::Cow, collections::BTreeMap};
use hashbrown::{HashMap, HashSet}; use hashbrown::{HashMap, HashSet};
use indexmap::IndexSet; use indexmap::IndexSet;
use itertools::Itertools; use itertools::Itertools;
use serde::{de::Error, Deserialize};
use crate::{ use crate::{
app::{ app::{
@ -103,14 +104,14 @@ pub struct ProcTableConfig {
} }
/// A hacky workaround for now. /// A hacky workaround for now.
#[derive(PartialEq, Eq, Hash)] #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub enum ProcWidgetColumn { pub enum ProcWidgetColumn {
PidOrCount, PidOrCount,
ProcNameOrCmd, ProcNameOrCommand,
Cpu, Cpu,
Mem, Mem,
Rps, ReadPerSecond,
Wps, WritePerSecond,
TotalRead, TotalRead,
TotalWrite, TotalWrite,
User, User,
@ -118,6 +119,34 @@ pub enum ProcWidgetColumn {
Time, Time,
} }
impl<'de> Deserialize<'de> for ProcWidgetColumn {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let value = String::deserialize(deserializer)?.to_lowercase();
match value.as_str() {
"cpu%" => Ok(ProcWidgetColumn::Cpu),
"mem" => Ok(ProcWidgetColumn::Mem),
"mem%" => Ok(ProcWidgetColumn::Mem),
"pid" => Ok(ProcWidgetColumn::PidOrCount),
"count" => Ok(ProcWidgetColumn::PidOrCount),
"name" => Ok(ProcWidgetColumn::ProcNameOrCommand),
"command" => Ok(ProcWidgetColumn::ProcNameOrCommand),
"read" | "r/s" | "rps" => Ok(ProcWidgetColumn::ReadPerSecond),
"write" | "w/s" | "wps" => Ok(ProcWidgetColumn::WritePerSecond),
"tread" | "t.read" => Ok(ProcWidgetColumn::TotalRead),
"twrite" | "t.write" => Ok(ProcWidgetColumn::TotalWrite),
"state" => Ok(ProcWidgetColumn::State),
"user" => Ok(ProcWidgetColumn::User),
"time" => Ok(ProcWidgetColumn::Time),
_ => Err(D::Error::custom("doesn't match any column type")),
}
}
}
// This is temporary. Switch back to `ProcColumn` later!
pub struct ProcWidgetState { pub struct ProcWidgetState {
pub mode: ProcWidgetMode, pub mode: ProcWidgetMode,
@ -188,7 +217,7 @@ impl ProcWidgetState {
pub fn new( pub fn new(
config: &AppConfigFields, mode: ProcWidgetMode, table_config: ProcTableConfig, config: &AppConfigFields, mode: ProcWidgetMode, table_config: ProcTableConfig,
colours: &CanvasColours, config_columns: &Option<IndexSet<ProcColumn>>, colours: &CanvasColours, config_columns: &Option<IndexSet<ProcWidgetColumn>>,
) -> Self { ) -> Self {
let process_search_state = { let process_search_state = {
let mut pss = ProcessSearchState::default(); let mut pss = ProcessSearchState::default();
@ -210,15 +239,50 @@ impl ProcWidgetState {
let columns: Vec<SortColumn<ProcColumn>> = { let columns: Vec<SortColumn<ProcColumn>> = {
use ProcColumn::*; use ProcColumn::*;
match config_columns {
Some(columns) if !columns.is_empty() => {
columns.iter().cloned().map(make_column).collect()
}
_ => {
let is_count = matches!(mode, ProcWidgetMode::Grouped); let is_count = matches!(mode, ProcWidgetMode::Grouped);
let is_command = table_config.is_command; let is_command = table_config.is_command;
let mem_vals = table_config.show_memory_as_values; let mem_vals = table_config.show_memory_as_values;
match config_columns {
Some(columns) if !columns.is_empty() => columns
.into_iter()
.map(|c| {
let col = match c {
ProcWidgetColumn::PidOrCount => {
if is_count {
Count
} else {
Pid
}
}
ProcWidgetColumn::ProcNameOrCommand => {
if is_command {
Command
} else {
Name
}
}
ProcWidgetColumn::Cpu => CpuPercent,
ProcWidgetColumn::Mem => {
if mem_vals {
MemoryVal
} else {
MemoryPercent
}
}
ProcWidgetColumn::ReadPerSecond => ReadPerSecond,
ProcWidgetColumn::WritePerSecond => WritePerSecond,
ProcWidgetColumn::TotalRead => TotalRead,
ProcWidgetColumn::TotalWrite => TotalWrite,
ProcWidgetColumn::User => User,
ProcWidgetColumn::State => State,
ProcWidgetColumn::Time => Time,
};
make_column(col)
})
.collect(),
_ => {
let default_columns = [ let default_columns = [
if is_count { Count } else { Pid }, if is_count { Count } else { Pid },
if is_command { Command } else { Name }, if is_command { Command } else { Name },
@ -246,9 +310,9 @@ impl ProcWidgetState {
CpuPercent => ProcWidgetColumn::Cpu, CpuPercent => ProcWidgetColumn::Cpu,
MemoryVal | MemoryPercent => ProcWidgetColumn::Mem, MemoryVal | MemoryPercent => ProcWidgetColumn::Mem,
Pid | Count => ProcWidgetColumn::PidOrCount, Pid | Count => ProcWidgetColumn::PidOrCount,
Name | Command => ProcWidgetColumn::ProcNameOrCmd, Name | Command => ProcWidgetColumn::ProcNameOrCommand,
ReadPerSecond => ProcWidgetColumn::Rps, ReadPerSecond => ProcWidgetColumn::ReadPerSecond,
WritePerSecond => ProcWidgetColumn::Wps, WritePerSecond => ProcWidgetColumn::WritePerSecond,
TotalRead => ProcWidgetColumn::TotalRead, TotalRead => ProcWidgetColumn::TotalRead,
TotalWrite => ProcWidgetColumn::TotalWrite, TotalWrite => ProcWidgetColumn::TotalWrite,
State => ProcWidgetColumn::State, State => ProcWidgetColumn::State,
@ -302,7 +366,7 @@ impl ProcWidgetState {
pub fn is_using_command(&self) -> bool { pub fn is_using_command(&self) -> bool {
self.column_mapping self.column_mapping
.get_index_of(&ProcWidgetColumn::ProcNameOrCmd) .get_index_of(&ProcWidgetColumn::ProcNameOrCommand)
.and_then(|index| { .and_then(|index| {
self.table self.table
.columns .columns
@ -746,7 +810,7 @@ impl ProcWidgetState {
pub fn toggle_command(&mut self) { pub fn toggle_command(&mut self) {
if let Some(index) = self if let Some(index) = self
.column_mapping .column_mapping
.get_index_of(&ProcWidgetColumn::ProcNameOrCmd) .get_index_of(&ProcWidgetColumn::ProcNameOrCommand)
{ {
if let Some(col) = self.table.columns.get_mut(index) { if let Some(col) = self.table.columns.get_mut(index) {
let inner = col.inner_mut(); let inner = col.inner_mut();
@ -1053,10 +1117,9 @@ mod test {
.collect::<Vec<_>>() .collect::<Vec<_>>()
} }
fn init_default_state(columns: &[ProcColumn]) -> ProcWidgetState { fn init_state(table_config: ProcTableConfig, columns: &[ProcWidgetColumn]) -> ProcWidgetState {
let config = AppConfigFields::default(); let config = AppConfigFields::default();
let colours = CanvasColours::default(); let colours = CanvasColours::default();
let table_config = ProcTableConfig::default();
let columns = Some(columns.iter().cloned().collect()); let columns = Some(columns.iter().cloned().collect());
ProcWidgetState::new( ProcWidgetState::new(
@ -1068,33 +1131,49 @@ mod test {
) )
} }
fn init_default_state(columns: &[ProcWidgetColumn]) -> ProcWidgetState {
init_state(ProcTableConfig::default(), columns)
}
#[test] #[test]
fn test_custom_columns() { fn custom_columns() {
let init_columns = vec![
ProcWidgetColumn::PidOrCount,
ProcWidgetColumn::ProcNameOrCommand,
ProcWidgetColumn::Mem,
ProcWidgetColumn::State,
];
let columns = vec![ let columns = vec![
ProcColumn::Pid, ProcColumn::Pid,
ProcColumn::Command, ProcColumn::Name,
ProcColumn::MemoryPercent, ProcColumn::MemoryPercent,
ProcColumn::State, ProcColumn::State,
]; ];
let state = init_default_state(&columns); let state = init_default_state(&init_columns);
assert_eq!(get_columns(&state.table), columns); assert_eq!(get_columns(&state.table), columns);
} }
#[test] #[test]
fn toggle_count_pid() { fn toggle_count_pid() {
let init_columns = [
ProcWidgetColumn::PidOrCount,
ProcWidgetColumn::ProcNameOrCommand,
ProcWidgetColumn::Mem,
ProcWidgetColumn::State,
];
let original_columns = vec![ let original_columns = vec![
ProcColumn::Pid, ProcColumn::Pid,
ProcColumn::Command, ProcColumn::Name,
ProcColumn::MemoryPercent, ProcColumn::MemoryPercent,
ProcColumn::State, ProcColumn::State,
]; ];
let new_columns = vec![ let new_columns = vec![
ProcColumn::Count, ProcColumn::Count,
ProcColumn::Command, ProcColumn::Name,
ProcColumn::MemoryPercent, ProcColumn::MemoryPercent,
]; ];
let mut state = init_default_state(&original_columns); let mut state = init_default_state(&init_columns);
assert_eq!(get_columns(&state.table), original_columns); assert_eq!(get_columns(&state.table), original_columns);
// This should hide the state. // This should hide the state.
@ -1108,20 +1187,27 @@ mod test {
#[test] #[test]
fn toggle_count_pid_2() { fn toggle_count_pid_2() {
let init_columns = [
ProcWidgetColumn::ProcNameOrCommand,
ProcWidgetColumn::Mem,
ProcWidgetColumn::User,
ProcWidgetColumn::State,
ProcWidgetColumn::PidOrCount,
];
let original_columns = vec![ let original_columns = vec![
ProcColumn::Command, ProcColumn::Name,
ProcColumn::MemoryPercent, ProcColumn::MemoryPercent,
ProcColumn::User, ProcColumn::User,
ProcColumn::State, ProcColumn::State,
ProcColumn::Pid, ProcColumn::Pid,
]; ];
let new_columns = vec![ let new_columns = vec![
ProcColumn::Command, ProcColumn::Name,
ProcColumn::MemoryPercent, ProcColumn::MemoryPercent,
ProcColumn::Count, ProcColumn::Count,
]; ];
let mut state = init_default_state(&original_columns); let mut state = init_default_state(&init_columns);
assert_eq!(get_columns(&state.table), original_columns); assert_eq!(get_columns(&state.table), original_columns);
// This should hide the state. // This should hide the state.
@ -1135,20 +1221,30 @@ mod test {
#[test] #[test]
fn toggle_command() { fn toggle_command() {
let init_columns = [
ProcWidgetColumn::PidOrCount,
ProcWidgetColumn::State,
ProcWidgetColumn::Mem,
ProcWidgetColumn::ProcNameOrCommand,
];
let original_columns = vec![ let original_columns = vec![
ProcColumn::Pid, ProcColumn::Pid,
ProcColumn::MemoryPercent,
ProcColumn::State, ProcColumn::State,
ProcColumn::MemoryPercent,
ProcColumn::Command, ProcColumn::Command,
]; ];
let new_columns = vec![ let new_columns = vec![
ProcColumn::Pid, ProcColumn::Pid,
ProcColumn::MemoryPercent,
ProcColumn::State, ProcColumn::State,
ProcColumn::MemoryPercent,
ProcColumn::Name, ProcColumn::Name,
]; ];
let mut state = init_default_state(&original_columns); let table_config = ProcTableConfig {
is_command: true,
..Default::default()
};
let mut state = init_state(table_config, &init_columns);
assert_eq!(get_columns(&state.table), original_columns); assert_eq!(get_columns(&state.table), original_columns);
state.toggle_command(); state.toggle_command();
@ -1160,20 +1256,26 @@ mod test {
#[test] #[test]
fn toggle_mem_percentage() { fn toggle_mem_percentage() {
let init_columns = [
ProcWidgetColumn::PidOrCount,
ProcWidgetColumn::Mem,
ProcWidgetColumn::State,
ProcWidgetColumn::ProcNameOrCommand,
];
let original_columns = vec![ let original_columns = vec![
ProcColumn::Pid, ProcColumn::Pid,
ProcColumn::MemoryPercent, ProcColumn::MemoryPercent,
ProcColumn::State, ProcColumn::State,
ProcColumn::Command, ProcColumn::Name,
]; ];
let new_columns = vec![ let new_columns = vec![
ProcColumn::Pid, ProcColumn::Pid,
ProcColumn::MemoryVal, ProcColumn::MemoryVal,
ProcColumn::State, ProcColumn::State,
ProcColumn::Command, ProcColumn::Name,
]; ];
let mut state = init_default_state(&original_columns); let mut state = init_default_state(&init_columns);
assert_eq!(get_columns(&state.table), original_columns); assert_eq!(get_columns(&state.table), original_columns);
state.toggle_mem_percentage(); state.toggle_mem_percentage();
@ -1185,20 +1287,30 @@ mod test {
#[test] #[test]
fn toggle_mem_percentage_2() { fn toggle_mem_percentage_2() {
let new_columns = vec![ let init_columns = [
ProcColumn::Pid, ProcWidgetColumn::PidOrCount,
ProcColumn::MemoryPercent, ProcWidgetColumn::Mem,
ProcColumn::State, ProcWidgetColumn::State,
ProcColumn::Command, ProcWidgetColumn::ProcNameOrCommand,
]; ];
let original_columns = vec![ let original_columns = vec![
ProcColumn::Pid, ProcColumn::Pid,
ProcColumn::MemoryVal, ProcColumn::MemoryVal,
ProcColumn::State, ProcColumn::State,
ProcColumn::Command, ProcColumn::Name,
];
let new_columns = vec![
ProcColumn::Pid,
ProcColumn::MemoryPercent,
ProcColumn::State,
ProcColumn::Name,
]; ];
let mut state = init_default_state(&original_columns); let table_config = ProcTableConfig {
show_memory_as_values: true,
..Default::default()
};
let mut state = init_state(table_config, &init_columns);
assert_eq!(get_columns(&state.table), original_columns); assert_eq!(get_columns(&state.table), original_columns);
state.toggle_mem_percentage(); state.toggle_mem_percentage();
@ -1209,15 +1321,25 @@ mod test {
} }
#[test] #[test]
fn test_is_using_command() { fn columns_and_is_using_command() {
let init_columns = [
ProcWidgetColumn::PidOrCount,
ProcWidgetColumn::Mem,
ProcWidgetColumn::State,
ProcWidgetColumn::ProcNameOrCommand,
];
let original_columns = vec![ let original_columns = vec![
ProcColumn::Pid, ProcColumn::Pid,
ProcColumn::MemoryVal, ProcColumn::MemoryPercent,
ProcColumn::State, ProcColumn::State,
ProcColumn::Command, ProcColumn::Command,
]; ];
let mut state = init_default_state(&original_columns); let table_config = ProcTableConfig {
is_command: true,
..Default::default()
};
let mut state = init_state(table_config, &init_columns);
assert_eq!(get_columns(&state.table), original_columns); assert_eq!(get_columns(&state.table), original_columns);
assert!(state.is_using_command()); assert!(state.is_using_command());
@ -1229,15 +1351,25 @@ mod test {
} }
#[test] #[test]
fn test_is_memory() { fn columns_and_is_memory() {
let init_columns = [
ProcWidgetColumn::PidOrCount,
ProcWidgetColumn::Mem,
ProcWidgetColumn::State,
ProcWidgetColumn::ProcNameOrCommand,
];
let original_columns = vec![ let original_columns = vec![
ProcColumn::Pid, ProcColumn::Pid,
ProcColumn::MemoryVal, ProcColumn::MemoryVal,
ProcColumn::State, ProcColumn::State,
ProcColumn::Command, ProcColumn::Name,
]; ];
let mut state = init_default_state(&original_columns); let table_config = ProcTableConfig {
show_memory_as_values: true,
..Default::default()
};
let mut state = init_state(table_config, &init_columns);
assert_eq!(get_columns(&state.table), original_columns); assert_eq!(get_columns(&state.table), original_columns);
assert!(!state.is_mem_percent()); assert!(!state.is_mem_percent());
@ -1247,4 +1379,117 @@ mod test {
state.toggle_mem_percentage(); state.toggle_mem_percentage();
assert!(!state.is_mem_percent()); assert!(!state.is_mem_percent());
} }
/// Tests toggling if both mem and mem% columns are configured.
///
/// Currently, this test doesn't really do much, since we treat these two columns as the same - this test is
/// intended for use later when we might allow both at the same time.
#[test]
fn double_memory_sim_toggle() {
let init_columns = [
ProcWidgetColumn::Mem,
ProcWidgetColumn::PidOrCount,
ProcWidgetColumn::State,
ProcWidgetColumn::ProcNameOrCommand,
ProcWidgetColumn::Mem,
];
let original_columns = vec![
ProcColumn::MemoryPercent,
ProcColumn::Pid,
ProcColumn::State,
ProcColumn::Name,
];
let new_columns = vec![
ProcColumn::MemoryVal,
ProcColumn::Pid,
ProcColumn::State,
ProcColumn::Name,
];
let mut state = init_default_state(&init_columns);
assert_eq!(get_columns(&state.table), original_columns);
state.toggle_mem_percentage();
assert_eq!(get_columns(&state.table), new_columns);
state.toggle_mem_percentage();
assert_eq!(get_columns(&state.table), original_columns);
}
/// Tests toggling if both pid and count columns are configured.
///
/// Currently, this test doesn't really do much, since we treat these two columns as the same - this test is
/// intended for use later when we might allow both at the same time.
#[test]
fn pid_and_count_sim_toggle() {
let init_columns = [
ProcWidgetColumn::ProcNameOrCommand,
ProcWidgetColumn::PidOrCount,
ProcWidgetColumn::Mem,
ProcWidgetColumn::State,
ProcWidgetColumn::PidOrCount,
];
let original_columns = vec![
ProcColumn::Name,
ProcColumn::Pid,
ProcColumn::MemoryPercent,
ProcColumn::State,
];
let new_columns = vec![
ProcColumn::Name,
ProcColumn::Count,
ProcColumn::MemoryPercent,
];
let mut state = init_default_state(&init_columns);
assert_eq!(get_columns(&state.table), original_columns);
// This should hide the state.
state.toggle_tab();
assert_eq!(get_columns(&state.table), new_columns);
// This should re-reveal the state.
state.toggle_tab();
assert_eq!(get_columns(&state.table), original_columns);
}
/// Tests toggling if both command and name columns are configured.
///
/// Currently, this test doesn't really do much, since we treat these two columns as the same - this test is
/// intended for use later when we might allow both at the same time.
#[test]
fn command_name_sim_toggle() {
let init_columns = [
ProcWidgetColumn::ProcNameOrCommand,
ProcWidgetColumn::PidOrCount,
ProcWidgetColumn::State,
ProcWidgetColumn::Mem,
ProcWidgetColumn::ProcNameOrCommand,
];
let original_columns = vec![
ProcColumn::Command,
ProcColumn::Pid,
ProcColumn::State,
ProcColumn::MemoryPercent,
];
let new_columns = vec![
ProcColumn::Name,
ProcColumn::Pid,
ProcColumn::State,
ProcColumn::MemoryPercent,
];
let table_config = ProcTableConfig {
is_command: true,
..Default::default()
};
let mut state = init_state(table_config, &init_columns);
assert_eq!(get_columns(&state.table), original_columns);
state.toggle_command();
assert_eq!(get_columns(&state.table), new_columns);
state.toggle_command();
assert_eq!(get_columns(&state.table), original_columns);
}
} }

View file

@ -141,3 +141,13 @@ fn test_invalid_default_widget_count() {
.failure() .failure()
.stderr(predicate::str::contains("number too large")); .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")
.assert()
.failure()
.stderr(predicate::str::contains("doesn't match"));
}

View file

@ -0,0 +1,2 @@
[processes]
columns = ["cpu", "fake"]