diff --git a/src/uu/lsmem/src/lsmem.rs b/src/uu/lsmem/src/lsmem.rs index 092755a..e798811 100644 --- a/src/uu/lsmem/src/lsmem.rs +++ b/src/uu/lsmem/src/lsmem.rs @@ -132,28 +132,35 @@ impl Column { } } -#[derive(Debug, Deserialize, PartialEq, Clone, Copy)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy)] enum ZoneId { - #[serde(rename = "ZONE_DMA")] + #[serde(rename = "DMA")] ZoneDma, - #[serde(rename = "ZONE_DMA32")] + #[serde(rename = "DMA32")] ZoneDma32, - #[serde(rename = "ZONE_NORMAL")] + #[serde(rename = "Normal")] ZoneNormal, - #[serde(rename = "ZONE_HIGHMEM")] + #[serde(rename = "Highmem")] ZoneHighmem, - #[serde(rename = "ZONE_MOVABLE")] + #[serde(rename = "Movable")] ZoneMovable, - #[serde(rename = "ZONE_DEVICE")] + #[serde(rename = "Device")] ZoneDevice, - #[serde(rename = "ZONE_NONE")] + #[serde(rename = "None")] ZoneNone, - #[serde(rename = "ZONE_UNKNOWN")] + #[serde(rename = "Unknown")] ZoneUnknown, #[serde(rename = "MAX_NR_ZONES")] MaxNrZones, } +impl core::fmt::Display for ZoneId { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + let value = serde_json::to_string(self).unwrap().replace("\"", ""); + write!(f, "{}", value) + } +} + impl FromStr for ZoneId { type Err = (); @@ -527,6 +534,17 @@ fn create_table_rows(lsmem: &Lsmem, opts: &Options) -> Vec<TableRow> { row.node = format!("{}", blk.node); } + // Zones + if opts.have_zones { + row.zones = blk + .zones + .iter() + .filter(|zone| **zone != ZoneId::ZoneUnknown) + .map(|zone| zone.to_string()) + .collect::<Vec<String>>() + .join("/"); + } + table_rows.push(row); } table_rows @@ -703,11 +721,23 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } } - let split_columns = matches + let mut split_columns = matches .get_many::<String>(options::SPLIT) .unwrap_or_default() .map(|c| c.to_uppercase()) .collect::<Vec<String>>(); + + // This seems like a bug in util-linux, but effectively, if split_columns is empty, + // then DEFAULT it to the value of custom columns. Becase "zones" is not one of the + // default columns, that means we just happen to not split on it most of the time. + if split_columns.is_empty() { + split_columns = opts + .columns + .iter() + .map(|c| c.get_name().to_string()) + .collect(); + } + opts.split_by_node = split_columns.contains(&Column::Node.get_name().to_string()); opts.split_by_removable = split_columns.contains(&Column::Removable.get_name().to_string()); opts.split_by_state = split_columns.contains(&Column::State.get_name().to_string()); diff --git a/tests/by-util/test_lsmem.rs b/tests/by-util/test_lsmem.rs index dd8e533..a9a6993 100644 --- a/tests/by-util/test_lsmem.rs +++ b/tests/by-util/test_lsmem.rs @@ -120,6 +120,15 @@ fn test_split_node() { sysroot_test_with_args("test_lsmem_split_node.expected", &["-S", "node"]); } +#[test] +fn test_split_output_default() { + // If split is not provided, then it defaults to splitting on the provided(or default) columns + sysroot_test_with_args( + "test_lsmem_split_output_default.expected", + &["-o", "block,size,zones,node"], + ); +} + #[test] fn test_split_removable() { sysroot_test_with_args("test_lsmem_split_removable.expected", &["-S", "removable"]); diff --git a/tests/fixtures/lsmem/test_lsmem_split_output_default.expected b/tests/fixtures/lsmem/test_lsmem_split_output_default.expected new file mode 100644 index 0000000..5ce22b7 --- /dev/null +++ b/tests/fixtures/lsmem/test_lsmem_split_output_default.expected @@ -0,0 +1,8 @@ + BLOCK SIZE ZONES NODE + 0 128M None 0 + 1-6 768M DMA32 0 +32-149 14.8G Normal 0 + +Memory block size: 128M +Total online memory: 15.6G +Total offline memory: 0B