diff --git a/Cargo.lock b/Cargo.lock
index e608f36..5e59468 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -100,12 +100,6 @@ version = "3.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
 
-[[package]]
-name = "bytecount"
-version = "0.6.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce"
-
 [[package]]
 name = "byteorder"
 version = "1.5.0"
@@ -114,9 +108,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "cc"
-version = "1.2.12"
+version = "1.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2"
+checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda"
 dependencies = [
  "shlex",
 ]
@@ -264,6 +258,12 @@ version = "1.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
 
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
 [[package]]
 name = "errno"
 version = "0.3.10"
@@ -280,12 +280,6 @@ version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
 
-[[package]]
-name = "fnv"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
-
 [[package]]
 name = "getrandom"
 version = "0.3.1"
@@ -305,10 +299,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
 
 [[package]]
-name = "heck"
-version = "0.5.0"
+name = "hashbrown"
+version = "0.15.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
 
 [[package]]
 name = "hermit-abi"
@@ -345,6 +339,16 @@ dependencies = [
  "cc",
 ]
 
+[[package]]
+name = "indexmap"
+version = "2.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
 [[package]]
 name = "io-lifetimes"
 version = "1.0.11"
@@ -489,9 +493,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
 
 [[package]]
 name = "once_cell"
-version = "1.20.2"
+version = "1.20.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
+checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
 
 [[package]]
 name = "os_display"
@@ -499,18 +503,7 @@ version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a6229bad892b46b0dcfaaeb18ad0d2e56400f5aaea05b768bde96e73676cf75"
 dependencies = [
- "unicode-width 0.1.14",
-]
-
-[[package]]
-name = "papergrid"
-version = "0.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b915f831b85d984193fdc3d3611505871dc139b2534530fa01c1a6a6707b6723"
-dependencies = [
- "bytecount",
- "fnv",
- "unicode-width 0.2.0",
+ "unicode-width",
 ]
 
 [[package]]
@@ -587,28 +580,6 @@ dependencies = [
  "yansi",
 ]
 
-[[package]]
-name = "proc-macro-error-attr2"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
-dependencies = [
- "proc-macro2",
- "quote",
-]
-
-[[package]]
-name = "proc-macro-error2"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
-dependencies = [
- "proc-macro-error-attr2",
- "proc-macro2",
- "quote",
- "syn",
-]
-
 [[package]]
 name = "proc-macro2"
 version = "1.0.93"
@@ -666,7 +637,7 @@ checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
 dependencies = [
  "rand_chacha",
  "rand_core 0.9.0",
- "zerocopy 0.8.16",
+ "zerocopy 0.8.17",
 ]
 
 [[package]]
@@ -692,7 +663,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff"
 dependencies = [
  "getrandom",
- "zerocopy 0.8.16",
+ "zerocopy 0.8.17",
 ]
 
 [[package]]
@@ -824,6 +795,7 @@ version = "1.0.138"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949"
 dependencies = [
+ "indexmap",
  "itoa",
  "memchr",
  "ryu",
@@ -889,29 +861,6 @@ dependencies = [
  "windows",
 ]
 
-[[package]]
-name = "tabled"
-version = "0.18.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "121d8171ee5687a4978d1b244f7d99c43e7385a272185a2f1e1fa4dc0979d444"
-dependencies = [
- "papergrid",
- "tabled_derive",
-]
-
-[[package]]
-name = "tabled_derive"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52d9946811baad81710ec921809e2af67ad77719418673b2a3794932d57b7538"
-dependencies = [
- "heck",
- "proc-macro-error2",
- "proc-macro2",
- "quote",
- "syn",
-]
-
 [[package]]
 name = "tempfile"
 version = "3.16.0"
@@ -955,7 +904,7 @@ dependencies = [
  "smawk",
  "terminal_size 0.2.6",
  "unicode-linebreak",
- "unicode-width 0.1.14",
+ "unicode-width",
 ]
 
 [[package]]
@@ -1009,12 +958,6 @@ version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
 
-[[package]]
-name = "unicode-width"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
-
 [[package]]
 name = "utf8parse"
 version = "0.2.2"
@@ -1127,7 +1070,6 @@ dependencies = [
  "clap",
  "serde",
  "serde_json",
- "tabled",
  "uucore",
 ]
 
@@ -1539,11 +1481,11 @@ dependencies = [
 
 [[package]]
 name = "zerocopy"
-version = "0.8.16"
+version = "0.8.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b8c07a70861ce02bad1607b5753ecb2501f67847b9f9ada7c160fff0ec6300c"
+checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713"
 dependencies = [
- "zerocopy-derive 0.8.16",
+ "zerocopy-derive 0.8.17",
 ]
 
 [[package]]
@@ -1559,9 +1501,9 @@ dependencies = [
 
 [[package]]
 name = "zerocopy-derive"
-version = "0.8.16"
+version = "0.8.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5226bc9a9a9836e7428936cde76bb6b22feea1a8bfdbc0d241136e4d13417e25"
+checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/Cargo.toml b/Cargo.toml
index 4ffb60d..3c625d7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -51,9 +51,8 @@ phf_codegen = "0.11.2"
 rand = { version = "0.9.0", features = ["small_rng"] }
 regex = "1.10.2"
 serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0.122"
+serde_json = { version = "1.0.122", features = ["preserve_order"] }
 sysinfo = "0.33"
-tabled = "0.18.0"
 tempfile = "3.9.0"
 textwrap = { version = "0.16.0", features = ["terminal_size"] }
 uucore = "0.0.29"
diff --git a/src/uu/lsmem/Cargo.toml b/src/uu/lsmem/Cargo.toml
index 516aa1d..47cd8d0 100644
--- a/src/uu/lsmem/Cargo.toml
+++ b/src/uu/lsmem/Cargo.toml
@@ -13,6 +13,5 @@ path = "src/main.rs"
 [dependencies]
 uucore = { workspace = true }
 clap = { workspace = true }
-serde  = { workspace = true }
+serde = { workspace = true }
 serde_json = { workspace = true }
-tabled = { workspace = true }
diff --git a/src/uu/lsmem/src/lsmem.rs b/src/uu/lsmem/src/lsmem.rs
index b7db93b..4722247 100644
--- a/src/uu/lsmem/src/lsmem.rs
+++ b/src/uu/lsmem/src/lsmem.rs
@@ -5,54 +5,44 @@
 
 mod utils;
 
-use clap::{crate_version, Command};
+use clap::builder::{EnumValueParser, PossibleValue, PossibleValuesParser};
+use clap::{crate_version, Command, ValueEnum};
 use clap::{Arg, ArgAction};
 use serde::{Deserialize, Serialize};
 use std::borrow::Borrow;
 use std::fs;
 use std::io::{self, BufRead, BufReader};
-use std::path::{Path, PathBuf};
+use std::path::{Path, PathBuf, MAIN_SEPARATOR};
 use std::str::FromStr;
 use uucore::{error::UResult, format_usage, help_about, help_usage};
 
-use tabled::{
-    settings::{
-        location::ByColumnName,
-        object::{self, Rows},
-        Alignment, Modify, Remove, Style,
-    },
-    Table, Tabled,
-};
-
 const ABOUT: &str = help_about!("lsmem.md");
 const USAGE: &str = help_usage!("lsmem.md");
 
 mod options {
+    pub const ALL: &str = "all";
     pub const BYTES: &str = "bytes";
-    pub const NOHEADINGS: &str = "noheadings";
     pub const JSON: &str = "json";
+    pub const NOHEADINGS: &str = "noheadings";
+    pub const OUTPUT: &str = "output";
+    pub const OUTPUT_ALL: &str = "output-all";
     pub const PAIRS: &str = "pairs";
     pub const RAW: &str = "raw";
+    pub const SPLIT: &str = "split";
+    pub const SUMMARY: &str = "summary";
+    pub const SYSROOT: &str = "sysroot";
 }
 
-// const BUFSIZ: usize = 1024;
-
-const PATH_SYS_MEMORY: &str = "/sys/devices/system/memory";
-const PATH_BLOCK_SIZE_BYTES: &str = "/sys/devices/system/memory/block_size_bytes";
-const PATH_VALID_ZONES: &str = "/sys/devices/system/memory/valid_zones";
+const PATH_NAME_MEMORY: &str = "memory";
+const PATH_NAME_NODE: &str = "node";
+const PATH_SUB_BLOCK_SIZE_BYTES: &str = "block_size_bytes";
 const PATH_SUB_REMOVABLE: &str = "removable";
 const PATH_SUB_STATE: &str = "state";
-const NAME_MEMORY: &str = "memory";
+const PATH_SUB_VALID_ZONES: &str = "valid_zones";
+const PATH_SYS_MEMORY: &str = "/sys/devices/system/memory";
 
-// struct ColDesc {
-//     name: &'static str, // Rust's equivalent to `const char *`
-//     whint: f64,         // Rust uses `f64` for double precision floating-point numbers
-//     flags: i32,         // Using `i32` for integers
-//     help: &'static str, // Rust's equivalent to `const char *`
-// }
-
-#[derive(Debug, Deserialize)]
-enum Columns {
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+enum Column {
     #[serde(rename = "RANGE")]
     Range,
     #[serde(rename = "SIZE")]
@@ -68,75 +58,126 @@ enum Columns {
     #[serde(rename = "ZONES")]
     Zones,
 }
-// const SCOLS_FL_RIGHT: i32 = 1;
 
-// static COLDESCS: [ColDesc; 7] = [
-//     ColDesc {
-//         name: "RANGE",
-//         whint: 0.0,
-//         flags: 0,
-//         help: "start and end address of the memory range",
-//     },
-//     ColDesc {
-//         name: "SIZE",
-//         whint: 5.0,
-//         flags: SCOLS_FL_RIGHT,
-//         help: "size of the memory range",
-//     },
-//     ColDesc {
-//         name: "STATE",
-//         whint: 0.0,
-//         flags: SCOLS_FL_RIGHT,
-//         help: "online status of the memory range",
-//     },
-//     ColDesc {
-//         name: "REMOVABLE",
-//         whint: 0.0,
-//         flags: SCOLS_FL_RIGHT,
-//         help: "memory is removable",
-//     },
-//     ColDesc {
-//         name: "BLOCK",
-//         whint: 0.0,
-//         flags: SCOLS_FL_RIGHT,
-//         help: "memory block number or blocks range",
-//     },
-//     ColDesc {
-//         name: "NODE",
-//         whint: 0.0,
-//         flags: SCOLS_FL_RIGHT,
-//         help: "numa node of memory",
-//     },
-//     ColDesc {
-//         name: "ZONES",
-//         whint: 0.0,
-//         flags: SCOLS_FL_RIGHT,
-//         help: "valid zones for the memory range",
-//     },
-// ];
+impl ValueEnum for Column {
+    fn value_variants<'a>() -> &'a [Self] {
+        &[
+            Column::Range,
+            Column::Size,
+            Column::State,
+            Column::Removable,
+            Column::Block,
+            Column::Node,
+            Column::Zones,
+        ]
+    }
 
-#[derive(Debug, Deserialize, PartialEq, Clone, Copy)]
+    fn to_possible_value(&self) -> Option<PossibleValue> {
+        Some(PossibleValue::new(self.get_name()))
+    }
+}
+
+/// Default columns to display if none are explicitly specified.
+const DEFAULT_COLUMNS: &[Column] = &[
+    Column::Range,
+    Column::Size,
+    Column::State,
+    Column::Removable,
+    Column::Block,
+];
+/// Which columns (attributes) are possible to split memory blocks to ranges on.
+const SPLIT_COLUMNS: &[Column] = &[
+    Column::State,
+    Column::Removable,
+    Column::Node,
+    Column::Zones,
+];
+
+impl Column {
+    fn get_name(&self) -> &'static str {
+        match self {
+            Column::Range => "RANGE",
+            Column::Size => "SIZE",
+            Column::State => "STATE",
+            Column::Removable => "REMOVABLE",
+            Column::Block => "BLOCK",
+            Column::Node => "NODE",
+            Column::Zones => "ZONES",
+        }
+    }
+
+    fn get_float_right(&self) -> bool {
+        self != &Column::Range
+    }
+
+    fn get_width_hint(&self) -> usize {
+        if self == &Column::Size {
+            5
+        } else {
+            self.get_name().len()
+        }
+    }
+
+    fn get_help(&self) -> &'static str {
+        match self {
+            Column::Range => "start and end address of the memory range",
+            Column::Size => "size of the memory range",
+            Column::State => "online status of the memory range",
+            Column::Removable => "memory is removable",
+            Column::Block => "memory block number or blocks range",
+            Column::Node => "numa node of memory",
+            Column::Zones => "valid zones for the memory range",
+        }
+    }
+}
+
+#[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 = ();
+
+    fn from_str(input: &str) -> Result<ZoneId, Self::Err> {
+        match input.to_lowercase().as_str() {
+            "dma" => Ok(ZoneId::ZoneDma),
+            "dma32" => Ok(ZoneId::ZoneDma32),
+            "normal" => Ok(ZoneId::ZoneNormal),
+            "highmem" => Ok(ZoneId::ZoneHighmem),
+            "movable" => Ok(ZoneId::ZoneMovable),
+            "device" => Ok(ZoneId::ZoneDevice),
+            "none" => Ok(ZoneId::ZoneNone),
+            "unknown" => Ok(ZoneId::ZoneUnknown),
+            _ => Err(()),
+        }
+    }
+}
+
 #[derive(PartialEq, Clone)]
 enum MemoryState {
     Online,
@@ -194,61 +235,77 @@ impl MemoryBlock {
     }
 }
 
-#[derive(Tabled, Default, Serialize)]
+#[derive(Clone, Debug, PartialEq)]
+enum Summary {
+    Never,
+    Always,
+    Only,
+}
+
+impl ValueEnum for Summary {
+    fn value_variants<'a>() -> &'a [Self] {
+        &[Summary::Never, Summary::Always, Summary::Only]
+    }
+
+    fn to_possible_value(&self) -> Option<PossibleValue> {
+        match self {
+            Summary::Never => Some(PossibleValue::new("never").help("never show summary")),
+            Summary::Always => Some(PossibleValue::new("always").help("always show summary")),
+            Summary::Only => Some(PossibleValue::new("only").help("show summary only")),
+        }
+    }
+}
+
+#[derive(Default, Serialize)]
 struct TableRow {
-    #[tabled(rename = "RANGE")]
     range: String,
-    #[tabled(rename = "SIZE")]
     size: String,
-    #[tabled(rename = "STATE")]
     state: String,
-    #[tabled(rename = "REMOVABLE")]
     removable: String,
-    #[tabled(rename = "BLOCK")]
     block: String,
-    #[tabled(rename = "NODE")]
     #[serde(skip_serializing)]
     node: String,
-    #[tabled(rename = "ZONES")]
     #[serde(skip_serializing)]
     zones: String,
 }
 
 impl TableRow {
-    fn to_pairs_string(&self) -> String {
-        format!(
-            r#"RANGE="{}" SIZE="{}" STATE="{}" REMOVABLE="{}" BLOCK="{}""#,
-            self.range, self.size, self.state, self.removable, self.block
-        )
+    fn get_value(&self, column: &Column) -> String {
+        match column {
+            Column::Range => self.range.clone(),
+            Column::Size => self.size.clone(),
+            Column::State => self.state.clone(),
+            Column::Removable => self.removable.clone(),
+            Column::Block => self.block.clone(),
+            Column::Node => self.node.clone(),
+            Column::Zones => self.zones.clone(),
+        }
     }
-    fn to_raw_string(&self) -> String {
-        format!(
-            r#"{} {} {} {} {}"#,
-            self.range, self.size, self.state, self.removable, self.block
-        )
-    }
-}
-
-#[derive(Serialize)]
-struct TableRowJson {
-    memory: Vec<TableRow>,
 }
 
 struct Options {
-    have_nodes: bool,
-    raw: bool,
-    export: bool,
-    json: bool,
-    noheadings: bool,
-    list_all: bool,
+    // Set by command-line arguments
+    all: bool,
     bytes: bool,
+    columns: Vec<Column>,
+    noheadings: bool,
+    json: bool,
+    pairs: bool,
+    raw: bool,
+    split_by_node: bool,
+    split_by_removable: bool,
+    split_by_state: bool,
+    split_by_zones: bool,
+    /// Default to PATH_SYS_MEMORY, but a prefix can be prepended
+    sysmem: String,
+
+    // Set by read_info
+    have_nodes: bool,
+    have_zones: bool,
+
+    // Computed from flags above
     want_summary: bool,
     want_table: bool,
-    split_by_node: bool,
-    split_by_state: bool,
-    split_by_removable: bool,
-    split_by_zones: bool,
-    have_zones: bool,
 }
 
 struct Lsmem {
@@ -278,36 +335,48 @@ impl Lsmem {
 impl Options {
     fn new() -> Options {
         Options {
-            have_nodes: false,
-            raw: false,
-            export: false,
-            json: false,
-            noheadings: false,
-            list_all: false,
+            all: false,
             bytes: false,
+            columns: Vec::default(),
+            noheadings: false,
+            json: false,
+            pairs: false,
+            raw: false,
+            split_by_node: false,
+            split_by_removable: false,
+            split_by_state: false,
+            split_by_zones: false,
+            sysmem: Path::new(PATH_SYS_MEMORY).display().to_string(),
+
+            have_nodes: false,
+            have_zones: false,
+
             want_summary: true, // default true
             want_table: true,   // default true
-            split_by_node: false,
-            split_by_state: false,
-            split_by_removable: false,
-            split_by_zones: false,
-            have_zones: false,
         }
     }
 }
 
 fn read_info(lsmem: &mut Lsmem, opts: &mut Options) {
+    let path_block_size = Path::new(&opts.sysmem).join(PATH_SUB_BLOCK_SIZE_BYTES);
     lsmem.block_size = u64::from_str_radix(
-        &read_file_content::<String>(Path::new(PATH_BLOCK_SIZE_BYTES)).unwrap(),
+        &read_file_content::<String>(path_block_size.as_path())
+            .expect("Failed to read memory block size"),
         16,
     )
     .unwrap();
-    lsmem.dirs = get_block_paths();
+    lsmem.dirs = get_block_paths(opts);
     lsmem.dirs.sort_by(|a, b| {
-        let filename_a = a.to_str().unwrap().split('/').last().unwrap();
-        let filename_b = b.to_str().unwrap().split('/').last().unwrap();
-        let idx_a: u64 = filename_a[NAME_MEMORY.len()..].parse().unwrap();
-        let idx_b: u64 = filename_b[NAME_MEMORY.len()..].parse().unwrap();
+        let filename_a = a.file_name().expect("Failed parsing memory block name");
+        let filename_a = filename_a.to_str().unwrap();
+        let filename_b = b.file_name().expect("Failed parsing memory block name");
+        let filename_b = filename_b.to_str().unwrap();
+        let idx_a: u64 = filename_a[PATH_NAME_MEMORY.len()..]
+            .parse()
+            .expect("Failed to parse memory block index");
+        let idx_b: u64 = filename_b[PATH_NAME_MEMORY.len()..]
+            .parse()
+            .expect("Failed to parse memory block index");
         idx_a.cmp(&idx_b)
     });
     lsmem.ndirs = lsmem.dirs.len();
@@ -317,8 +386,8 @@ fn read_info(lsmem: &mut Lsmem, opts: &mut Options) {
         }
 
         let mut p = path.clone();
-        p.push("valid_zones");
-        if fs::read_dir(p).is_ok() {
+        p.push(PATH_SUB_VALID_ZONES);
+        if fs::read(&p).is_ok() {
             opts.have_zones = true;
         }
 
@@ -343,13 +412,13 @@ fn read_info(lsmem: &mut Lsmem, opts: &mut Options) {
     }
 }
 
-fn get_block_paths() -> Vec<PathBuf> {
+fn get_block_paths(opts: &mut Options) -> Vec<PathBuf> {
     let mut paths = Vec::<PathBuf>::new();
-    for entry in fs::read_dir(PATH_SYS_MEMORY).unwrap() {
+    for entry in fs::read_dir(&opts.sysmem).unwrap() {
         let entry = entry.unwrap();
         let path = entry.path();
-        let filename = path.to_str().unwrap().split('/').last().unwrap();
-        if path.is_dir() && filename.starts_with(NAME_MEMORY) {
+        let filename = path.file_name().unwrap().to_str().unwrap();
+        if path.is_dir() && filename.starts_with(PATH_NAME_MEMORY) {
             paths.push(path);
         }
     }
@@ -362,7 +431,7 @@ fn is_mergeable(lsmem: &Lsmem, opts: &Options, blk: &MemoryBlock) -> bool {
     }
 
     let curr_block = &lsmem.blocks[lsmem.nblocks - 1];
-    if opts.list_all {
+    if opts.all {
         return false;
     }
     if curr_block.index + curr_block.count != blk.index {
@@ -381,7 +450,6 @@ fn is_mergeable(lsmem: &Lsmem, opts: &Options, blk: &MemoryBlock) -> bool {
         if curr_block.nr_zones != blk.nr_zones {
             return false;
         }
-
         for i in 0..curr_block.nr_zones {
             if curr_block.zones[i] == ZoneId::ZoneUnknown || curr_block.zones[i] != blk.zones[i] {
                 return false;
@@ -395,9 +463,9 @@ fn memory_block_get_node(path: &PathBuf) -> Result<i32, <i32 as FromStr>::Err> {
     for entry in fs::read_dir(path).unwrap() {
         let entry = entry.unwrap();
         let path = entry.path();
-        let filename = path.to_str().unwrap().split('/').last().unwrap();
-        if path.is_dir() && filename.starts_with("node") {
-            return filename["node".len()..].parse();
+        let filename = path.file_name().unwrap().to_str().unwrap();
+        if path.is_dir() && filename.starts_with(PATH_NAME_NODE) {
+            return filename[PATH_NAME_NODE.len()..].parse();
         }
     }
     Ok(-1)
@@ -407,8 +475,8 @@ fn memory_block_read_attrs(opts: &Options, path: &PathBuf) -> MemoryBlock {
     let mut blk = MemoryBlock::new();
     blk.count = 1;
     blk.state = MemoryState::Unknown;
-    let filename = path.to_str().unwrap().split('/').last().unwrap();
-    blk.index = filename[NAME_MEMORY.len()..].parse().unwrap();
+    let filename = path.file_name().unwrap().to_str().unwrap();
+    blk.index = filename[PATH_NAME_MEMORY.len()..].parse().unwrap();
 
     let mut removable_path = path.clone();
     removable_path.push(PATH_SUB_REMOVABLE);
@@ -426,14 +494,16 @@ fn memory_block_read_attrs(opts: &Options, path: &PathBuf) -> MemoryBlock {
 
     blk.nr_zones = 0;
     if opts.have_zones {
-        if let Ok(raw_content) = read_file_content::<String>(Path::new(PATH_VALID_ZONES)) {
+        let vz_path = path.join(PATH_SUB_VALID_ZONES);
+        if let Ok(raw_content) = read_file_content::<String>(Path::new(&vz_path)) {
             let zone_toks = raw_content.split(' ').collect::<Vec<&str>>();
             for (i, zone_tok) in zone_toks
                 .iter()
+                .map(|tok| tok.to_lowercase())
                 .enumerate()
                 .take(std::cmp::min(zone_toks.len(), ZoneId::MaxNrZones as usize))
             {
-                blk.zones[i] = serde_json::from_str(zone_tok).unwrap();
+                blk.zones[i] = ZoneId::from_str(&zone_tok).unwrap();
                 blk.nr_zones += 1;
             }
         }
@@ -488,34 +558,99 @@ 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
 }
 
 fn print_table(lsmem: &Lsmem, opts: &Options) {
-    let mut table = Table::new(create_table_rows(lsmem, opts));
-    table
-        .with(Style::blank())
-        .with(Modify::new(object::Columns::new(1..)).with(Alignment::right()));
+    let table_rows = create_table_rows(lsmem, opts);
+    let mut col_widths = vec![0; opts.columns.len()];
 
-    // the default version
-    table.with(Remove::column(ByColumnName::new("NODE")));
-    table.with(Remove::column(ByColumnName::new("ZONES")));
-
-    if opts.noheadings {
-        table.with(Remove::row(Rows::first()));
+    // Initialize column widths based on pre-defined width hints
+    for (i, column) in opts.columns.iter().enumerate() {
+        col_widths[i] = column.get_width_hint();
     }
 
-    println!("{table}");
+    // Calculate minimum column widths based on the actual data
+    for row in &table_rows {
+        for (i, column) in opts.columns.iter().enumerate() {
+            let width = match column {
+                Column::Range => row.range.len(),
+                Column::Size => row.size.len(),
+                Column::State => row.state.len(),
+                Column::Removable => row.removable.len(),
+                Column::Block => row.block.len(),
+                Column::Node => row.node.len(),
+                Column::Zones => row.zones.len(),
+            };
+            col_widths[i] = col_widths[i].max(width);
+        }
+    }
+
+    if !opts.noheadings {
+        let mut column_names = vec![];
+        for (i, column) in opts.columns.iter().enumerate() {
+            let formatted = if column.get_float_right() {
+                format!("{:>width$}", column.get_name(), width = col_widths[i])
+            } else {
+                format!("{:<width$}", column.get_name(), width = col_widths[i])
+            };
+            column_names.push(formatted);
+        }
+        println!("{}", column_names.join(" "));
+    }
+
+    for row in table_rows {
+        let mut column_values = vec![];
+        for (i, column) in opts.columns.iter().enumerate() {
+            let formatted = if column.get_float_right() {
+                format!("{:>width$}", row.get_value(column), width = col_widths[i])
+            } else {
+                format!("{:<width$}", row.get_value(column), width = col_widths[i])
+            };
+            column_values.push(formatted);
+        }
+        println!("{}", column_values.join(" "));
+    }
 }
 
 fn print_json(lsmem: &Lsmem, opts: &Options) {
-    let table_json = TableRowJson {
-        memory: create_table_rows(lsmem, opts),
-    };
+    let table_rows = create_table_rows(lsmem, opts);
+    let mut memory_records = Vec::new();
 
-    let mut table_json_string = serde_json::to_string_pretty(&table_json).unwrap();
+    for row in table_rows {
+        let mut record = serde_json::Map::new();
+        for column in &opts.columns {
+            record.insert(
+                column.get_name().to_lowercase(),
+                if column == &Column::Size && opts.bytes {
+                    serde_json::Value::Number(row.get_value(column).parse().unwrap())
+                } else {
+                    serde_json::Value::String(row.get_value(column))
+                },
+            );
+        }
+        memory_records.push(serde_json::Value::Object(record));
+    }
+
+    let table_json = serde_json::json!({ "memory": memory_records });
+
+    let mut table_json_string = serde_json::to_string_pretty(&table_json)
+        .unwrap()
+        .replace("  ", "   ") // Ident 3 spaces
+        .replace("},\n      {", "},{"); // Remove newlines between '}, {'
     table_json_string = table_json_string.replace("\"yes\"", "true");
     table_json_string = table_json_string.replace("\"no\"", "false");
     println!("{table_json_string}");
@@ -523,25 +658,36 @@ fn print_json(lsmem: &Lsmem, opts: &Options) {
 
 fn print_pairs(lsmem: &Lsmem, opts: &Options) {
     let table_rows = create_table_rows(lsmem, opts);
-    let table_pairs_string = table_rows
-        .into_iter()
-        .map(|row| row.to_pairs_string())
-        .collect::<Vec<_>>()
-        .join("\n");
-    println!("{table_pairs_string}");
+
+    for row in table_rows {
+        let mut pairs = Vec::new();
+        for col in &opts.columns {
+            pairs.push(format!("{}=\"{}\"", col.get_name(), row.get_value(col)));
+        }
+        println!("{}", pairs.join(" "));
+    }
 }
 
 fn print_raw(lsmem: &Lsmem, opts: &Options) {
     let table_rows = create_table_rows(lsmem, opts);
-    let mut table_raw_string = String::new();
-    for row in table_rows {
-        table_raw_string += &row.to_raw_string();
-        table_raw_string += "\n";
+
+    if !opts.noheadings {
+        let column_names = opts
+            .columns
+            .iter()
+            .map(|col| col.get_name().to_string())
+            .collect::<Vec<String>>();
+        println!("{}", column_names.join(" "));
+    }
+
+    for row in table_rows {
+        let column_values = opts
+            .columns
+            .iter()
+            .map(|col| row.get_value(col).to_string())
+            .collect::<Vec<String>>();
+        println!("{}", column_values.join(" "));
     }
-    // remove the last newline
-    table_raw_string.pop();
-    println!("RANGE SIZE STATE REMOVABLE BLOCK");
-    println!("{table_raw_string}");
 }
 
 fn print_summary(lsmem: &Lsmem, opts: &Options) {
@@ -550,21 +696,13 @@ fn print_summary(lsmem: &Lsmem, opts: &Options) {
         println!("{:<23} {:>15}", "Total online memory:", lsmem.mem_online);
         println!("{:<23} {:>15}", "Total offline memory:", lsmem.mem_offline);
     } else {
-        println!(
-            "{:<23} {:>15}",
-            "Memory block size:",
-            utils::size_to_human_string(lsmem.block_size)
-        );
-        println!(
-            "{:<23} {:>15}",
-            "Total online memory:",
-            utils::size_to_human_string(lsmem.mem_online)
-        );
-        println!(
-            "{:<23} {:>15}",
-            "Total offline memory:",
-            utils::size_to_human_string(lsmem.mem_offline)
-        );
+        let block_size_str = utils::size_to_human_string(lsmem.block_size);
+        let mem_online_str = utils::size_to_human_string(lsmem.mem_online);
+        let mem_offline_str = utils::size_to_human_string(lsmem.mem_offline);
+
+        println!("{:<23} {:>5}", "Memory block size:", block_size_str);
+        println!("{:<23} {:>5}", "Total online memory:", mem_online_str);
+        println!("{:<23} {:>5}", "Total offline memory:", mem_offline_str);
     }
 }
 
@@ -572,11 +710,15 @@ fn read_file_content<T: core::str::FromStr>(path: &Path) -> io::Result<T>
 where
     T::Err: std::fmt::Debug, // Required to unwrap the result of T::from_str
 {
-    let file = fs::File::open(path)?;
+    let file = fs::File::open(path).expect("Failed to open file");
     let mut reader = BufReader::new(file);
     let mut content = String::new();
-    reader.read_line(&mut content)?;
-    Ok(content.trim().to_string().parse().unwrap())
+    reader.read_line(&mut content).expect("Failed to read line");
+    content
+        .trim()
+        .to_string()
+        .parse()
+        .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Failed to parse content"))
 }
 
 #[uucore::main]
@@ -585,22 +727,76 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
 
     let mut lsmem = Lsmem::new();
     let mut opts = Options::new();
+    opts.all = matches.get_flag(options::ALL);
     opts.bytes = matches.get_flag(options::BYTES);
     opts.noheadings = matches.get_flag(options::NOHEADINGS);
     opts.json = matches.get_flag(options::JSON);
-    opts.export = matches.get_flag(options::PAIRS);
+    opts.pairs = matches.get_flag(options::PAIRS);
     opts.raw = matches.get_flag(options::RAW);
+    opts.columns = matches
+        .get_many::<Column>(options::OUTPUT)
+        .unwrap_or_default()
+        .map(|c| c.to_owned())
+        .collect::<Vec<Column>>();
 
-    if opts.json || opts.export || opts.raw {
+    // Only respect --output-all if no column list were provided.
+    // --output takes priority over --output-all.
+    if opts.columns.is_empty() {
+        if matches.get_flag(options::OUTPUT_ALL) {
+            opts.columns = Column::value_variants().to_vec();
+        } else {
+            opts.columns = DEFAULT_COLUMNS.to_vec();
+        }
+    }
+
+    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());
+    opts.split_by_zones = split_columns.contains(&Column::Zones.get_name().to_string());
+
+    if opts.json || opts.pairs || opts.raw {
         opts.want_summary = false;
     }
+    if let Some(summary) = matches.get_one::<Summary>(options::SUMMARY) {
+        match summary {
+            Summary::Never => opts.want_summary = false,
+            Summary::Only => opts.want_table = false,
+            Summary::Always => {} // Default (equivalent to if --summary wasn't provided at all)
+        }
+    }
+
+    if let Some(sysroot) = matches.get_one::<String>(options::SYSROOT) {
+        opts.sysmem = format!(
+            "{}{}{}",
+            sysroot.trim_end_matches(MAIN_SEPARATOR),
+            MAIN_SEPARATOR,
+            opts.sysmem.trim_start_matches(MAIN_SEPARATOR)
+        );
+    }
 
     read_info(&mut lsmem, &mut opts);
 
     if opts.want_table {
         if opts.json {
             print_json(&lsmem, &opts);
-        } else if opts.export {
+        } else if opts.pairs {
             print_pairs(&lsmem, &opts);
         } else if opts.raw {
             print_raw(&lsmem, &opts);
@@ -609,6 +805,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
         }
     }
 
+    // Padding line between table and summary if both are shown
+    if opts.want_table && opts.want_summary {
+        println!();
+    }
+
     if opts.want_summary {
         print_summary(&lsmem, &opts);
     }
@@ -622,6 +823,30 @@ pub fn uu_app() -> Command {
         .about(ABOUT)
         .override_usage(format_usage(USAGE))
         .infer_long_args(true)
+        .arg(
+            Arg::new(options::JSON)
+                .short('J')
+                .long("json")
+                .help("use JSON output format")
+                .action(ArgAction::SetTrue)
+                .conflicts_with_all([options::PAIRS, options::RAW, options::SUMMARY]),
+        )
+        .arg(
+            Arg::new(options::PAIRS)
+                .short('P')
+                .long("pairs")
+                .help("use key=\"value\" output format")
+                .action(ArgAction::SetTrue)
+                .conflicts_with_all([options::JSON, options::RAW, options::SUMMARY]),
+        )
+        .arg(
+            Arg::new(options::ALL)
+                .short('a')
+                .long("all")
+                .help("list each individual memory block")
+                .action(ArgAction::SetTrue)
+                .conflicts_with(options::SPLIT),
+        )
         .arg(
             Arg::new(options::BYTES)
                 .short('b')
@@ -637,20 +862,21 @@ pub fn uu_app() -> Command {
                 .action(ArgAction::SetTrue),
         )
         .arg(
-            Arg::new(options::JSON)
-                .short('J')
-                .long("json")
-                .help("use JSON output format")
-                .action(ArgAction::SetTrue)
-                .conflicts_with_all([options::PAIRS, options::RAW]),
+            Arg::new(options::OUTPUT)
+                .short('o')
+                .long("output")
+                .help("output columns")
+                .ignore_case(true)
+                .action(ArgAction::Set)
+                .value_name("list")
+                .value_delimiter(',')
+                .value_parser(EnumValueParser::<Column>::new()),
         )
         .arg(
-            Arg::new(options::PAIRS)
-                .short('P')
-                .long("pairs")
-                .help("use key=\"value\" output format")
-                .action(ArgAction::SetTrue)
-                .conflicts_with_all([options::JSON, options::RAW]),
+            Arg::new(options::OUTPUT_ALL)
+                .long("output-all")
+                .help("output all columns")
+                .action(ArgAction::SetTrue),
         )
         .arg(
             Arg::new(options::RAW)
@@ -658,6 +884,52 @@ pub fn uu_app() -> Command {
                 .long("raw")
                 .help("use raw output format")
                 .action(ArgAction::SetTrue)
-                .conflicts_with_all([options::JSON, options::PAIRS]),
+                .conflicts_with_all([options::JSON, options::PAIRS, options::SUMMARY]),
         )
+        .arg(
+            Arg::new(options::SPLIT)
+                .short('S')
+                .long("split")
+                .help("split ranges by specified columns")
+                .conflicts_with(options::ALL)
+                .ignore_case(true)
+                .action(ArgAction::Set)
+                .value_name("list")
+                .value_delimiter(',')
+                .value_parser(PossibleValuesParser::new(
+                    SPLIT_COLUMNS
+                        .iter()
+                        .map(|col| col.to_possible_value().unwrap())
+                        .collect::<Vec<_>>(),
+                )),
+        )
+        .arg(
+            Arg::new(options::SYSROOT)
+                .short('s')
+                .long("sysroot")
+                .help("use the specified directory as system root")
+                .action(ArgAction::Set)
+                .value_name("dir"),
+        )
+        .arg(
+            Arg::new(options::SUMMARY)
+                .long("summary")
+                .help("print summary information")
+                .ignore_case(true)
+                .action(ArgAction::Set)
+                .value_name("when")
+                .value_delimiter(',')
+                .value_parser(EnumValueParser::<Summary>::new())
+                .conflicts_with_all([options::RAW, options::PAIRS, options::JSON])
+                .num_args(0..=1)
+                .default_missing_value("only"),
+        )
+        .after_help(format!(
+            "Available output columns:\n{}",
+            Column::value_variants()
+                .iter()
+                .map(|col| format!("{:>11}  {}", col.get_name(), col.get_help()))
+                .collect::<Vec<_>>()
+                .join("\n")
+        ))
 }
diff --git a/src/uu/lsmem/src/utils.rs b/src/uu/lsmem/src/utils.rs
index a0fe491..4f666b2 100644
--- a/src/uu/lsmem/src/utils.rs
+++ b/src/uu/lsmem/src/utils.rs
@@ -1,10 +1,3 @@
-// enum HumanStringSize {
-//     Suffix1Letter = 0,
-//     Suffix3Letter = (1 << 0),
-//     SuffixSpace = (1 << 1),
-//     Decimal2Digits = (1 << 2),
-// }
-
 pub fn size_to_human_string(bytes: u64) -> String {
     let mut buf = String::with_capacity(32);
     let mut dec;
diff --git a/tests/by-util/test_lsmem.rs b/tests/by-util/test_lsmem.rs
index ac8f594..cc2cbba 100644
--- a/tests/by-util/test_lsmem.rs
+++ b/tests/by-util/test_lsmem.rs
@@ -4,8 +4,340 @@
 // file that was distributed with this source code.
 
 use crate::common::util::TestScenario;
+use std::path::Path;
+
+fn write_file_content(dir: &Path, name: &str, content: &str) {
+    std::fs::create_dir_all(dir).unwrap();
+    std::fs::write(dir.join(name), content).unwrap();
+}
+
+const MEMORY_BLOCK_IDS: [usize; 125] = [
+    0, 1, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+    118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+    137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 2, 3, 32, 33, 34, 35, 36, 37,
+    38, 39, 4, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 5, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+    6, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+    83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+];
+
+struct TestSysMemory {
+    sysroot: String,
+}
+
+/// Builds up a fake /sys/devices/system/memory filesystem.
+///
+/// /sys/devices/system/memory/block_size_bytes
+/// /sys/devices/system/memory/memoryXX/removable
+/// /sys/devices/system/memory/memoryXX/state
+/// /sys/devices/system/memory/memoryXX/valid_zones
+/// /sys/devices/system/memory/memoryXX/node0/ (folder)
+///
+/// And removes it automatically after the reference is dropped.
+impl TestSysMemory {
+    fn new() -> Self {
+        let random = rand::random::<u32>();
+        let sysroot = Path::new(&env!("CARGO_MANIFEST_DIR"))
+            .join("target")
+            .join(format!("testsysmem-{random}"));
+        let sysmem = sysroot
+            .join("sys")
+            .join("devices")
+            .join("system")
+            .join("memory");
+        write_file_content(&sysmem, "block_size_bytes", "8000000\n");
+
+        for i in MEMORY_BLOCK_IDS {
+            let block_dir = sysmem.join(format!("memory{}", i));
+            write_file_content(&block_dir, "removable", "1\n");
+            write_file_content(&block_dir, "state", "online\n");
+            let valid_zone = match i {
+                0 => "none\n",
+                1..=6 => "DMA32\n",
+                _ => "Normal\n",
+            };
+            write_file_content(&block_dir, "valid_zones", valid_zone);
+            let node_dir = block_dir.join("node0");
+            write_file_content(&node_dir, ".gitkeep", "");
+        }
+
+        TestSysMemory {
+            sysroot: sysroot.display().to_string(),
+        }
+    }
+}
+
+impl Drop for TestSysMemory {
+    fn drop(&mut self) {
+        std::fs::remove_dir_all(&self.sysroot).unwrap();
+    }
+}
+
+fn sysroot_test_with_args(test_root: &TestSysMemory, expected_output: &str, args: &[&str]) {
+    let mut cmd = new_ucmd!();
+    cmd.arg("-s").arg(&test_root.sysroot);
+    for arg in args {
+        cmd.arg(arg);
+    }
+    cmd.succeeds()
+        .no_stderr()
+        .stdout_is_templated_fixture(expected_output, &[("\r\n", "\n")]);
+}
 
 #[test]
 fn test_invalid_arg() {
     new_ucmd!().arg("--definitely-invalid").fails().code_is(1);
 }
+
+#[test]
+fn test_columns_json() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_columns_json.expected",
+        &["-o", "block,size", "-J"],
+    );
+}
+
+#[test]
+fn test_columns_pairs() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_columns_pairs.expected",
+        &["-o", "block,size", "-P"],
+    );
+}
+
+#[test]
+fn test_columns_raw() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_columns_raw.expected",
+        &["-o", "block,size", "-r"],
+    );
+}
+
+#[test]
+fn test_columns_table() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_columns_table.expected",
+        &["-o", "block,size"],
+    );
+}
+
+#[test]
+fn test_json() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(&test_root, "test_lsmem_json.expected", &["-J"]);
+}
+
+#[test]
+fn test_json_all() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(&test_root, "test_lsmem_json_all.expected", &["-J", "-a"]);
+}
+
+#[test]
+fn test_json_bytes() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(&test_root, "test_lsmem_json_bytes.expected", &["-J", "-b"]);
+}
+
+#[test]
+fn test_json_noheadings() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_json_noheadings.expected",
+        &["-J", "-n"],
+    );
+}
+
+#[test]
+fn test_pairs() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(&test_root, "test_lsmem_pairs.expected", &["-P"]);
+}
+
+#[test]
+fn test_pairs_all() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(&test_root, "test_lsmem_pairs_all.expected", &["-P", "-a"]);
+}
+
+#[test]
+fn test_pairs_bytes() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(&test_root, "test_lsmem_pairs_bytes.expected", &["-P", "-b"]);
+}
+
+#[test]
+fn test_pairs_noheadings() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_pairs_noheadings.expected",
+        &["-P", "-n"],
+    );
+}
+
+#[test]
+fn test_raw() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(&test_root, "test_lsmem_raw.expected", &["-r"]);
+}
+
+#[test]
+fn test_raw_all() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(&test_root, "test_lsmem_raw_all.expected", &["-r", "-a"]);
+}
+
+#[test]
+fn test_raw_bytes() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(&test_root, "test_lsmem_raw_bytes.expected", &["-r", "-b"]);
+}
+
+#[test]
+fn test_raw_noheadings() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_raw_noheadings.expected",
+        &["-r", "-n"],
+    );
+}
+
+#[test]
+fn test_split_node() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "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
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_split_output_default.expected",
+        &["-o", "block,size,zones,node"],
+    );
+}
+
+#[test]
+fn test_split_removable() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_split_removable.expected",
+        &["-S", "removable"],
+    );
+}
+
+#[test]
+fn test_split_state() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_split_state.expected",
+        &["-S", "state"],
+    );
+}
+
+#[test]
+fn test_split_zones() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_split_zones.expected",
+        &["-S", "zones"],
+    );
+}
+
+#[test]
+fn test_summary_always() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_summary_always.expected",
+        &["--summary=always"],
+    );
+}
+
+#[test]
+fn test_summary_empty() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_summary_empty.expected",
+        &["--summary"],
+    );
+}
+
+#[test]
+fn test_summary_never() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_summary_never.expected",
+        &["--summary=never"],
+    );
+}
+
+#[test]
+fn test_summary_only() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(
+        &test_root,
+        "test_lsmem_summary_only.expected",
+        &["--summary=only"],
+    );
+}
+
+#[test]
+fn test_summary_conflict_json() {
+    new_ucmd!().arg("--summary").arg("-J").fails().code_is(1);
+}
+
+#[test]
+fn test_summary_conflict_pairs() {
+    new_ucmd!().arg("--summary").arg("-P").fails().code_is(1);
+}
+
+#[test]
+fn test_summary_conflict_raw() {
+    new_ucmd!().arg("--summary").arg("-r").fails().code_is(1);
+}
+
+#[test]
+fn test_table() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(&test_root, "test_lsmem_table.expected", &[]);
+}
+
+#[test]
+fn test_table_all() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(&test_root, "test_lsmem_table_all.expected", &["-a"]);
+}
+
+#[test]
+fn test_table_bytes() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(&test_root, "test_lsmem_table_bytes.expected", &["-b"]);
+}
+
+#[test]
+fn test_table_noheadings() {
+    let test_root = TestSysMemory::new();
+    sysroot_test_with_args(&test_root, "test_lsmem_table_noheadings.expected", &["-n"]);
+}
diff --git a/tests/fixtures/lsmem/test_lsmem_columns_json.expected b/tests/fixtures/lsmem/test_lsmem_columns_json.expected
new file mode 100644
index 0000000..351ccd2
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_columns_json.expected
@@ -0,0 +1,11 @@
+{
+   "memory": [
+      {
+         "block": "0-6",
+         "size": "896M"
+      },{
+         "block": "32-149",
+         "size": "14.8G"
+      }
+   ]
+}
diff --git a/tests/fixtures/lsmem/test_lsmem_columns_pairs.expected b/tests/fixtures/lsmem/test_lsmem_columns_pairs.expected
new file mode 100644
index 0000000..ad855f1
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_columns_pairs.expected
@@ -0,0 +1,2 @@
+BLOCK="0-6" SIZE="896M"
+BLOCK="32-149" SIZE="14.8G"
diff --git a/tests/fixtures/lsmem/test_lsmem_columns_raw.expected b/tests/fixtures/lsmem/test_lsmem_columns_raw.expected
new file mode 100644
index 0000000..76716c1
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_columns_raw.expected
@@ -0,0 +1,3 @@
+BLOCK SIZE
+0-6 896M
+32-149 14.8G
diff --git a/tests/fixtures/lsmem/test_lsmem_columns_table.expected b/tests/fixtures/lsmem/test_lsmem_columns_table.expected
new file mode 100644
index 0000000..3f16b30
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_columns_table.expected
@@ -0,0 +1,7 @@
+ BLOCK  SIZE
+   0-6  896M
+32-149 14.8G
+
+Memory block size:       128M
+Total online memory:    15.6G
+Total offline memory:      0B
diff --git a/tests/fixtures/lsmem/test_lsmem_json.expected b/tests/fixtures/lsmem/test_lsmem_json.expected
new file mode 100644
index 0000000..c2481b1
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_json.expected
@@ -0,0 +1,17 @@
+{
+   "memory": [
+      {
+         "range": "0x0000000000000000-0x0000000037ffffff",
+         "size": "896M",
+         "state": "online",
+         "removable": true,
+         "block": "0-6"
+      },{
+         "range": "0x0000000100000000-0x00000004afffffff",
+         "size": "14.8G",
+         "state": "online",
+         "removable": true,
+         "block": "32-149"
+      }
+   ]
+}
diff --git a/tests/fixtures/lsmem/test_lsmem_json_all.expected b/tests/fixtures/lsmem/test_lsmem_json_all.expected
new file mode 100644
index 0000000..01d0b67
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_json_all.expected
@@ -0,0 +1,755 @@
+{
+   "memory": [
+      {
+         "range": "0x0000000000000000-0x0000000007ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "0"
+      },{
+         "range": "0x0000000008000000-0x000000000fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "1"
+      },{
+         "range": "0x0000000010000000-0x0000000017ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "2"
+      },{
+         "range": "0x0000000018000000-0x000000001fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "3"
+      },{
+         "range": "0x0000000020000000-0x0000000027ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "4"
+      },{
+         "range": "0x0000000028000000-0x000000002fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "5"
+      },{
+         "range": "0x0000000030000000-0x0000000037ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "6"
+      },{
+         "range": "0x0000000100000000-0x0000000107ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "32"
+      },{
+         "range": "0x0000000108000000-0x000000010fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "33"
+      },{
+         "range": "0x0000000110000000-0x0000000117ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "34"
+      },{
+         "range": "0x0000000118000000-0x000000011fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "35"
+      },{
+         "range": "0x0000000120000000-0x0000000127ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "36"
+      },{
+         "range": "0x0000000128000000-0x000000012fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "37"
+      },{
+         "range": "0x0000000130000000-0x0000000137ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "38"
+      },{
+         "range": "0x0000000138000000-0x000000013fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "39"
+      },{
+         "range": "0x0000000140000000-0x0000000147ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "40"
+      },{
+         "range": "0x0000000148000000-0x000000014fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "41"
+      },{
+         "range": "0x0000000150000000-0x0000000157ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "42"
+      },{
+         "range": "0x0000000158000000-0x000000015fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "43"
+      },{
+         "range": "0x0000000160000000-0x0000000167ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "44"
+      },{
+         "range": "0x0000000168000000-0x000000016fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "45"
+      },{
+         "range": "0x0000000170000000-0x0000000177ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "46"
+      },{
+         "range": "0x0000000178000000-0x000000017fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "47"
+      },{
+         "range": "0x0000000180000000-0x0000000187ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "48"
+      },{
+         "range": "0x0000000188000000-0x000000018fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "49"
+      },{
+         "range": "0x0000000190000000-0x0000000197ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "50"
+      },{
+         "range": "0x0000000198000000-0x000000019fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "51"
+      },{
+         "range": "0x00000001a0000000-0x00000001a7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "52"
+      },{
+         "range": "0x00000001a8000000-0x00000001afffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "53"
+      },{
+         "range": "0x00000001b0000000-0x00000001b7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "54"
+      },{
+         "range": "0x00000001b8000000-0x00000001bfffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "55"
+      },{
+         "range": "0x00000001c0000000-0x00000001c7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "56"
+      },{
+         "range": "0x00000001c8000000-0x00000001cfffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "57"
+      },{
+         "range": "0x00000001d0000000-0x00000001d7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "58"
+      },{
+         "range": "0x00000001d8000000-0x00000001dfffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "59"
+      },{
+         "range": "0x00000001e0000000-0x00000001e7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "60"
+      },{
+         "range": "0x00000001e8000000-0x00000001efffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "61"
+      },{
+         "range": "0x00000001f0000000-0x00000001f7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "62"
+      },{
+         "range": "0x00000001f8000000-0x00000001ffffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "63"
+      },{
+         "range": "0x0000000200000000-0x0000000207ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "64"
+      },{
+         "range": "0x0000000208000000-0x000000020fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "65"
+      },{
+         "range": "0x0000000210000000-0x0000000217ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "66"
+      },{
+         "range": "0x0000000218000000-0x000000021fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "67"
+      },{
+         "range": "0x0000000220000000-0x0000000227ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "68"
+      },{
+         "range": "0x0000000228000000-0x000000022fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "69"
+      },{
+         "range": "0x0000000230000000-0x0000000237ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "70"
+      },{
+         "range": "0x0000000238000000-0x000000023fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "71"
+      },{
+         "range": "0x0000000240000000-0x0000000247ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "72"
+      },{
+         "range": "0x0000000248000000-0x000000024fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "73"
+      },{
+         "range": "0x0000000250000000-0x0000000257ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "74"
+      },{
+         "range": "0x0000000258000000-0x000000025fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "75"
+      },{
+         "range": "0x0000000260000000-0x0000000267ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "76"
+      },{
+         "range": "0x0000000268000000-0x000000026fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "77"
+      },{
+         "range": "0x0000000270000000-0x0000000277ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "78"
+      },{
+         "range": "0x0000000278000000-0x000000027fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "79"
+      },{
+         "range": "0x0000000280000000-0x0000000287ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "80"
+      },{
+         "range": "0x0000000288000000-0x000000028fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "81"
+      },{
+         "range": "0x0000000290000000-0x0000000297ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "82"
+      },{
+         "range": "0x0000000298000000-0x000000029fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "83"
+      },{
+         "range": "0x00000002a0000000-0x00000002a7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "84"
+      },{
+         "range": "0x00000002a8000000-0x00000002afffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "85"
+      },{
+         "range": "0x00000002b0000000-0x00000002b7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "86"
+      },{
+         "range": "0x00000002b8000000-0x00000002bfffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "87"
+      },{
+         "range": "0x00000002c0000000-0x00000002c7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "88"
+      },{
+         "range": "0x00000002c8000000-0x00000002cfffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "89"
+      },{
+         "range": "0x00000002d0000000-0x00000002d7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "90"
+      },{
+         "range": "0x00000002d8000000-0x00000002dfffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "91"
+      },{
+         "range": "0x00000002e0000000-0x00000002e7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "92"
+      },{
+         "range": "0x00000002e8000000-0x00000002efffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "93"
+      },{
+         "range": "0x00000002f0000000-0x00000002f7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "94"
+      },{
+         "range": "0x00000002f8000000-0x00000002ffffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "95"
+      },{
+         "range": "0x0000000300000000-0x0000000307ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "96"
+      },{
+         "range": "0x0000000308000000-0x000000030fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "97"
+      },{
+         "range": "0x0000000310000000-0x0000000317ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "98"
+      },{
+         "range": "0x0000000318000000-0x000000031fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "99"
+      },{
+         "range": "0x0000000320000000-0x0000000327ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "100"
+      },{
+         "range": "0x0000000328000000-0x000000032fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "101"
+      },{
+         "range": "0x0000000330000000-0x0000000337ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "102"
+      },{
+         "range": "0x0000000338000000-0x000000033fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "103"
+      },{
+         "range": "0x0000000340000000-0x0000000347ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "104"
+      },{
+         "range": "0x0000000348000000-0x000000034fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "105"
+      },{
+         "range": "0x0000000350000000-0x0000000357ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "106"
+      },{
+         "range": "0x0000000358000000-0x000000035fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "107"
+      },{
+         "range": "0x0000000360000000-0x0000000367ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "108"
+      },{
+         "range": "0x0000000368000000-0x000000036fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "109"
+      },{
+         "range": "0x0000000370000000-0x0000000377ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "110"
+      },{
+         "range": "0x0000000378000000-0x000000037fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "111"
+      },{
+         "range": "0x0000000380000000-0x0000000387ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "112"
+      },{
+         "range": "0x0000000388000000-0x000000038fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "113"
+      },{
+         "range": "0x0000000390000000-0x0000000397ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "114"
+      },{
+         "range": "0x0000000398000000-0x000000039fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "115"
+      },{
+         "range": "0x00000003a0000000-0x00000003a7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "116"
+      },{
+         "range": "0x00000003a8000000-0x00000003afffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "117"
+      },{
+         "range": "0x00000003b0000000-0x00000003b7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "118"
+      },{
+         "range": "0x00000003b8000000-0x00000003bfffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "119"
+      },{
+         "range": "0x00000003c0000000-0x00000003c7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "120"
+      },{
+         "range": "0x00000003c8000000-0x00000003cfffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "121"
+      },{
+         "range": "0x00000003d0000000-0x00000003d7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "122"
+      },{
+         "range": "0x00000003d8000000-0x00000003dfffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "123"
+      },{
+         "range": "0x00000003e0000000-0x00000003e7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "124"
+      },{
+         "range": "0x00000003e8000000-0x00000003efffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "125"
+      },{
+         "range": "0x00000003f0000000-0x00000003f7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "126"
+      },{
+         "range": "0x00000003f8000000-0x00000003ffffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "127"
+      },{
+         "range": "0x0000000400000000-0x0000000407ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "128"
+      },{
+         "range": "0x0000000408000000-0x000000040fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "129"
+      },{
+         "range": "0x0000000410000000-0x0000000417ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "130"
+      },{
+         "range": "0x0000000418000000-0x000000041fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "131"
+      },{
+         "range": "0x0000000420000000-0x0000000427ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "132"
+      },{
+         "range": "0x0000000428000000-0x000000042fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "133"
+      },{
+         "range": "0x0000000430000000-0x0000000437ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "134"
+      },{
+         "range": "0x0000000438000000-0x000000043fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "135"
+      },{
+         "range": "0x0000000440000000-0x0000000447ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "136"
+      },{
+         "range": "0x0000000448000000-0x000000044fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "137"
+      },{
+         "range": "0x0000000450000000-0x0000000457ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "138"
+      },{
+         "range": "0x0000000458000000-0x000000045fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "139"
+      },{
+         "range": "0x0000000460000000-0x0000000467ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "140"
+      },{
+         "range": "0x0000000468000000-0x000000046fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "141"
+      },{
+         "range": "0x0000000470000000-0x0000000477ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "142"
+      },{
+         "range": "0x0000000478000000-0x000000047fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "143"
+      },{
+         "range": "0x0000000480000000-0x0000000487ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "144"
+      },{
+         "range": "0x0000000488000000-0x000000048fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "145"
+      },{
+         "range": "0x0000000490000000-0x0000000497ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "146"
+      },{
+         "range": "0x0000000498000000-0x000000049fffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "147"
+      },{
+         "range": "0x00000004a0000000-0x00000004a7ffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "148"
+      },{
+         "range": "0x00000004a8000000-0x00000004afffffff",
+         "size": "128M",
+         "state": "online",
+         "removable": true,
+         "block": "149"
+      }
+   ]
+}
diff --git a/tests/fixtures/lsmem/test_lsmem_json_bytes.expected b/tests/fixtures/lsmem/test_lsmem_json_bytes.expected
new file mode 100644
index 0000000..113a775
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_json_bytes.expected
@@ -0,0 +1,17 @@
+{
+   "memory": [
+      {
+         "range": "0x0000000000000000-0x0000000037ffffff",
+         "size": 939524096,
+         "state": "online",
+         "removable": true,
+         "block": "0-6"
+      },{
+         "range": "0x0000000100000000-0x00000004afffffff",
+         "size": 15837691904,
+         "state": "online",
+         "removable": true,
+         "block": "32-149"
+      }
+   ]
+}
diff --git a/tests/fixtures/lsmem/test_lsmem_json_noheadings.expected b/tests/fixtures/lsmem/test_lsmem_json_noheadings.expected
new file mode 100644
index 0000000..c2481b1
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_json_noheadings.expected
@@ -0,0 +1,17 @@
+{
+   "memory": [
+      {
+         "range": "0x0000000000000000-0x0000000037ffffff",
+         "size": "896M",
+         "state": "online",
+         "removable": true,
+         "block": "0-6"
+      },{
+         "range": "0x0000000100000000-0x00000004afffffff",
+         "size": "14.8G",
+         "state": "online",
+         "removable": true,
+         "block": "32-149"
+      }
+   ]
+}
diff --git a/tests/fixtures/lsmem/test_lsmem_pairs.expected b/tests/fixtures/lsmem/test_lsmem_pairs.expected
new file mode 100644
index 0000000..8122df7
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_pairs.expected
@@ -0,0 +1,2 @@
+RANGE="0x0000000000000000-0x0000000037ffffff" SIZE="896M" STATE="online" REMOVABLE="yes" BLOCK="0-6"
+RANGE="0x0000000100000000-0x00000004afffffff" SIZE="14.8G" STATE="online" REMOVABLE="yes" BLOCK="32-149"
diff --git a/tests/fixtures/lsmem/test_lsmem_pairs_all.expected b/tests/fixtures/lsmem/test_lsmem_pairs_all.expected
new file mode 100644
index 0000000..cff130b
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_pairs_all.expected
@@ -0,0 +1,125 @@
+RANGE="0x0000000000000000-0x0000000007ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="0"
+RANGE="0x0000000008000000-0x000000000fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="1"
+RANGE="0x0000000010000000-0x0000000017ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="2"
+RANGE="0x0000000018000000-0x000000001fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="3"
+RANGE="0x0000000020000000-0x0000000027ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="4"
+RANGE="0x0000000028000000-0x000000002fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="5"
+RANGE="0x0000000030000000-0x0000000037ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="6"
+RANGE="0x0000000100000000-0x0000000107ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="32"
+RANGE="0x0000000108000000-0x000000010fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="33"
+RANGE="0x0000000110000000-0x0000000117ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="34"
+RANGE="0x0000000118000000-0x000000011fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="35"
+RANGE="0x0000000120000000-0x0000000127ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="36"
+RANGE="0x0000000128000000-0x000000012fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="37"
+RANGE="0x0000000130000000-0x0000000137ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="38"
+RANGE="0x0000000138000000-0x000000013fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="39"
+RANGE="0x0000000140000000-0x0000000147ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="40"
+RANGE="0x0000000148000000-0x000000014fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="41"
+RANGE="0x0000000150000000-0x0000000157ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="42"
+RANGE="0x0000000158000000-0x000000015fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="43"
+RANGE="0x0000000160000000-0x0000000167ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="44"
+RANGE="0x0000000168000000-0x000000016fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="45"
+RANGE="0x0000000170000000-0x0000000177ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="46"
+RANGE="0x0000000178000000-0x000000017fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="47"
+RANGE="0x0000000180000000-0x0000000187ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="48"
+RANGE="0x0000000188000000-0x000000018fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="49"
+RANGE="0x0000000190000000-0x0000000197ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="50"
+RANGE="0x0000000198000000-0x000000019fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="51"
+RANGE="0x00000001a0000000-0x00000001a7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="52"
+RANGE="0x00000001a8000000-0x00000001afffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="53"
+RANGE="0x00000001b0000000-0x00000001b7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="54"
+RANGE="0x00000001b8000000-0x00000001bfffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="55"
+RANGE="0x00000001c0000000-0x00000001c7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="56"
+RANGE="0x00000001c8000000-0x00000001cfffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="57"
+RANGE="0x00000001d0000000-0x00000001d7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="58"
+RANGE="0x00000001d8000000-0x00000001dfffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="59"
+RANGE="0x00000001e0000000-0x00000001e7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="60"
+RANGE="0x00000001e8000000-0x00000001efffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="61"
+RANGE="0x00000001f0000000-0x00000001f7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="62"
+RANGE="0x00000001f8000000-0x00000001ffffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="63"
+RANGE="0x0000000200000000-0x0000000207ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="64"
+RANGE="0x0000000208000000-0x000000020fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="65"
+RANGE="0x0000000210000000-0x0000000217ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="66"
+RANGE="0x0000000218000000-0x000000021fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="67"
+RANGE="0x0000000220000000-0x0000000227ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="68"
+RANGE="0x0000000228000000-0x000000022fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="69"
+RANGE="0x0000000230000000-0x0000000237ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="70"
+RANGE="0x0000000238000000-0x000000023fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="71"
+RANGE="0x0000000240000000-0x0000000247ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="72"
+RANGE="0x0000000248000000-0x000000024fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="73"
+RANGE="0x0000000250000000-0x0000000257ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="74"
+RANGE="0x0000000258000000-0x000000025fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="75"
+RANGE="0x0000000260000000-0x0000000267ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="76"
+RANGE="0x0000000268000000-0x000000026fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="77"
+RANGE="0x0000000270000000-0x0000000277ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="78"
+RANGE="0x0000000278000000-0x000000027fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="79"
+RANGE="0x0000000280000000-0x0000000287ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="80"
+RANGE="0x0000000288000000-0x000000028fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="81"
+RANGE="0x0000000290000000-0x0000000297ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="82"
+RANGE="0x0000000298000000-0x000000029fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="83"
+RANGE="0x00000002a0000000-0x00000002a7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="84"
+RANGE="0x00000002a8000000-0x00000002afffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="85"
+RANGE="0x00000002b0000000-0x00000002b7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="86"
+RANGE="0x00000002b8000000-0x00000002bfffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="87"
+RANGE="0x00000002c0000000-0x00000002c7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="88"
+RANGE="0x00000002c8000000-0x00000002cfffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="89"
+RANGE="0x00000002d0000000-0x00000002d7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="90"
+RANGE="0x00000002d8000000-0x00000002dfffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="91"
+RANGE="0x00000002e0000000-0x00000002e7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="92"
+RANGE="0x00000002e8000000-0x00000002efffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="93"
+RANGE="0x00000002f0000000-0x00000002f7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="94"
+RANGE="0x00000002f8000000-0x00000002ffffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="95"
+RANGE="0x0000000300000000-0x0000000307ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="96"
+RANGE="0x0000000308000000-0x000000030fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="97"
+RANGE="0x0000000310000000-0x0000000317ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="98"
+RANGE="0x0000000318000000-0x000000031fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="99"
+RANGE="0x0000000320000000-0x0000000327ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="100"
+RANGE="0x0000000328000000-0x000000032fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="101"
+RANGE="0x0000000330000000-0x0000000337ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="102"
+RANGE="0x0000000338000000-0x000000033fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="103"
+RANGE="0x0000000340000000-0x0000000347ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="104"
+RANGE="0x0000000348000000-0x000000034fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="105"
+RANGE="0x0000000350000000-0x0000000357ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="106"
+RANGE="0x0000000358000000-0x000000035fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="107"
+RANGE="0x0000000360000000-0x0000000367ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="108"
+RANGE="0x0000000368000000-0x000000036fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="109"
+RANGE="0x0000000370000000-0x0000000377ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="110"
+RANGE="0x0000000378000000-0x000000037fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="111"
+RANGE="0x0000000380000000-0x0000000387ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="112"
+RANGE="0x0000000388000000-0x000000038fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="113"
+RANGE="0x0000000390000000-0x0000000397ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="114"
+RANGE="0x0000000398000000-0x000000039fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="115"
+RANGE="0x00000003a0000000-0x00000003a7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="116"
+RANGE="0x00000003a8000000-0x00000003afffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="117"
+RANGE="0x00000003b0000000-0x00000003b7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="118"
+RANGE="0x00000003b8000000-0x00000003bfffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="119"
+RANGE="0x00000003c0000000-0x00000003c7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="120"
+RANGE="0x00000003c8000000-0x00000003cfffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="121"
+RANGE="0x00000003d0000000-0x00000003d7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="122"
+RANGE="0x00000003d8000000-0x00000003dfffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="123"
+RANGE="0x00000003e0000000-0x00000003e7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="124"
+RANGE="0x00000003e8000000-0x00000003efffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="125"
+RANGE="0x00000003f0000000-0x00000003f7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="126"
+RANGE="0x00000003f8000000-0x00000003ffffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="127"
+RANGE="0x0000000400000000-0x0000000407ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="128"
+RANGE="0x0000000408000000-0x000000040fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="129"
+RANGE="0x0000000410000000-0x0000000417ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="130"
+RANGE="0x0000000418000000-0x000000041fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="131"
+RANGE="0x0000000420000000-0x0000000427ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="132"
+RANGE="0x0000000428000000-0x000000042fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="133"
+RANGE="0x0000000430000000-0x0000000437ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="134"
+RANGE="0x0000000438000000-0x000000043fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="135"
+RANGE="0x0000000440000000-0x0000000447ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="136"
+RANGE="0x0000000448000000-0x000000044fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="137"
+RANGE="0x0000000450000000-0x0000000457ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="138"
+RANGE="0x0000000458000000-0x000000045fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="139"
+RANGE="0x0000000460000000-0x0000000467ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="140"
+RANGE="0x0000000468000000-0x000000046fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="141"
+RANGE="0x0000000470000000-0x0000000477ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="142"
+RANGE="0x0000000478000000-0x000000047fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="143"
+RANGE="0x0000000480000000-0x0000000487ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="144"
+RANGE="0x0000000488000000-0x000000048fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="145"
+RANGE="0x0000000490000000-0x0000000497ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="146"
+RANGE="0x0000000498000000-0x000000049fffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="147"
+RANGE="0x00000004a0000000-0x00000004a7ffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="148"
+RANGE="0x00000004a8000000-0x00000004afffffff" SIZE="128M" STATE="online" REMOVABLE="yes" BLOCK="149"
diff --git a/tests/fixtures/lsmem/test_lsmem_pairs_bytes.expected b/tests/fixtures/lsmem/test_lsmem_pairs_bytes.expected
new file mode 100644
index 0000000..bef7a7d
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_pairs_bytes.expected
@@ -0,0 +1,2 @@
+RANGE="0x0000000000000000-0x0000000037ffffff" SIZE="939524096" STATE="online" REMOVABLE="yes" BLOCK="0-6"
+RANGE="0x0000000100000000-0x00000004afffffff" SIZE="15837691904" STATE="online" REMOVABLE="yes" BLOCK="32-149"
diff --git a/tests/fixtures/lsmem/test_lsmem_pairs_noheadings.expected b/tests/fixtures/lsmem/test_lsmem_pairs_noheadings.expected
new file mode 100644
index 0000000..8122df7
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_pairs_noheadings.expected
@@ -0,0 +1,2 @@
+RANGE="0x0000000000000000-0x0000000037ffffff" SIZE="896M" STATE="online" REMOVABLE="yes" BLOCK="0-6"
+RANGE="0x0000000100000000-0x00000004afffffff" SIZE="14.8G" STATE="online" REMOVABLE="yes" BLOCK="32-149"
diff --git a/tests/fixtures/lsmem/test_lsmem_raw.expected b/tests/fixtures/lsmem/test_lsmem_raw.expected
new file mode 100644
index 0000000..4ef5064
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_raw.expected
@@ -0,0 +1,3 @@
+RANGE SIZE STATE REMOVABLE BLOCK
+0x0000000000000000-0x0000000037ffffff 896M online yes 0-6
+0x0000000100000000-0x00000004afffffff 14.8G online yes 32-149
diff --git a/tests/fixtures/lsmem/test_lsmem_raw_all.expected b/tests/fixtures/lsmem/test_lsmem_raw_all.expected
new file mode 100644
index 0000000..97182c3
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_raw_all.expected
@@ -0,0 +1,126 @@
+RANGE SIZE STATE REMOVABLE BLOCK
+0x0000000000000000-0x0000000007ffffff 128M online yes 0
+0x0000000008000000-0x000000000fffffff 128M online yes 1
+0x0000000010000000-0x0000000017ffffff 128M online yes 2
+0x0000000018000000-0x000000001fffffff 128M online yes 3
+0x0000000020000000-0x0000000027ffffff 128M online yes 4
+0x0000000028000000-0x000000002fffffff 128M online yes 5
+0x0000000030000000-0x0000000037ffffff 128M online yes 6
+0x0000000100000000-0x0000000107ffffff 128M online yes 32
+0x0000000108000000-0x000000010fffffff 128M online yes 33
+0x0000000110000000-0x0000000117ffffff 128M online yes 34
+0x0000000118000000-0x000000011fffffff 128M online yes 35
+0x0000000120000000-0x0000000127ffffff 128M online yes 36
+0x0000000128000000-0x000000012fffffff 128M online yes 37
+0x0000000130000000-0x0000000137ffffff 128M online yes 38
+0x0000000138000000-0x000000013fffffff 128M online yes 39
+0x0000000140000000-0x0000000147ffffff 128M online yes 40
+0x0000000148000000-0x000000014fffffff 128M online yes 41
+0x0000000150000000-0x0000000157ffffff 128M online yes 42
+0x0000000158000000-0x000000015fffffff 128M online yes 43
+0x0000000160000000-0x0000000167ffffff 128M online yes 44
+0x0000000168000000-0x000000016fffffff 128M online yes 45
+0x0000000170000000-0x0000000177ffffff 128M online yes 46
+0x0000000178000000-0x000000017fffffff 128M online yes 47
+0x0000000180000000-0x0000000187ffffff 128M online yes 48
+0x0000000188000000-0x000000018fffffff 128M online yes 49
+0x0000000190000000-0x0000000197ffffff 128M online yes 50
+0x0000000198000000-0x000000019fffffff 128M online yes 51
+0x00000001a0000000-0x00000001a7ffffff 128M online yes 52
+0x00000001a8000000-0x00000001afffffff 128M online yes 53
+0x00000001b0000000-0x00000001b7ffffff 128M online yes 54
+0x00000001b8000000-0x00000001bfffffff 128M online yes 55
+0x00000001c0000000-0x00000001c7ffffff 128M online yes 56
+0x00000001c8000000-0x00000001cfffffff 128M online yes 57
+0x00000001d0000000-0x00000001d7ffffff 128M online yes 58
+0x00000001d8000000-0x00000001dfffffff 128M online yes 59
+0x00000001e0000000-0x00000001e7ffffff 128M online yes 60
+0x00000001e8000000-0x00000001efffffff 128M online yes 61
+0x00000001f0000000-0x00000001f7ffffff 128M online yes 62
+0x00000001f8000000-0x00000001ffffffff 128M online yes 63
+0x0000000200000000-0x0000000207ffffff 128M online yes 64
+0x0000000208000000-0x000000020fffffff 128M online yes 65
+0x0000000210000000-0x0000000217ffffff 128M online yes 66
+0x0000000218000000-0x000000021fffffff 128M online yes 67
+0x0000000220000000-0x0000000227ffffff 128M online yes 68
+0x0000000228000000-0x000000022fffffff 128M online yes 69
+0x0000000230000000-0x0000000237ffffff 128M online yes 70
+0x0000000238000000-0x000000023fffffff 128M online yes 71
+0x0000000240000000-0x0000000247ffffff 128M online yes 72
+0x0000000248000000-0x000000024fffffff 128M online yes 73
+0x0000000250000000-0x0000000257ffffff 128M online yes 74
+0x0000000258000000-0x000000025fffffff 128M online yes 75
+0x0000000260000000-0x0000000267ffffff 128M online yes 76
+0x0000000268000000-0x000000026fffffff 128M online yes 77
+0x0000000270000000-0x0000000277ffffff 128M online yes 78
+0x0000000278000000-0x000000027fffffff 128M online yes 79
+0x0000000280000000-0x0000000287ffffff 128M online yes 80
+0x0000000288000000-0x000000028fffffff 128M online yes 81
+0x0000000290000000-0x0000000297ffffff 128M online yes 82
+0x0000000298000000-0x000000029fffffff 128M online yes 83
+0x00000002a0000000-0x00000002a7ffffff 128M online yes 84
+0x00000002a8000000-0x00000002afffffff 128M online yes 85
+0x00000002b0000000-0x00000002b7ffffff 128M online yes 86
+0x00000002b8000000-0x00000002bfffffff 128M online yes 87
+0x00000002c0000000-0x00000002c7ffffff 128M online yes 88
+0x00000002c8000000-0x00000002cfffffff 128M online yes 89
+0x00000002d0000000-0x00000002d7ffffff 128M online yes 90
+0x00000002d8000000-0x00000002dfffffff 128M online yes 91
+0x00000002e0000000-0x00000002e7ffffff 128M online yes 92
+0x00000002e8000000-0x00000002efffffff 128M online yes 93
+0x00000002f0000000-0x00000002f7ffffff 128M online yes 94
+0x00000002f8000000-0x00000002ffffffff 128M online yes 95
+0x0000000300000000-0x0000000307ffffff 128M online yes 96
+0x0000000308000000-0x000000030fffffff 128M online yes 97
+0x0000000310000000-0x0000000317ffffff 128M online yes 98
+0x0000000318000000-0x000000031fffffff 128M online yes 99
+0x0000000320000000-0x0000000327ffffff 128M online yes 100
+0x0000000328000000-0x000000032fffffff 128M online yes 101
+0x0000000330000000-0x0000000337ffffff 128M online yes 102
+0x0000000338000000-0x000000033fffffff 128M online yes 103
+0x0000000340000000-0x0000000347ffffff 128M online yes 104
+0x0000000348000000-0x000000034fffffff 128M online yes 105
+0x0000000350000000-0x0000000357ffffff 128M online yes 106
+0x0000000358000000-0x000000035fffffff 128M online yes 107
+0x0000000360000000-0x0000000367ffffff 128M online yes 108
+0x0000000368000000-0x000000036fffffff 128M online yes 109
+0x0000000370000000-0x0000000377ffffff 128M online yes 110
+0x0000000378000000-0x000000037fffffff 128M online yes 111
+0x0000000380000000-0x0000000387ffffff 128M online yes 112
+0x0000000388000000-0x000000038fffffff 128M online yes 113
+0x0000000390000000-0x0000000397ffffff 128M online yes 114
+0x0000000398000000-0x000000039fffffff 128M online yes 115
+0x00000003a0000000-0x00000003a7ffffff 128M online yes 116
+0x00000003a8000000-0x00000003afffffff 128M online yes 117
+0x00000003b0000000-0x00000003b7ffffff 128M online yes 118
+0x00000003b8000000-0x00000003bfffffff 128M online yes 119
+0x00000003c0000000-0x00000003c7ffffff 128M online yes 120
+0x00000003c8000000-0x00000003cfffffff 128M online yes 121
+0x00000003d0000000-0x00000003d7ffffff 128M online yes 122
+0x00000003d8000000-0x00000003dfffffff 128M online yes 123
+0x00000003e0000000-0x00000003e7ffffff 128M online yes 124
+0x00000003e8000000-0x00000003efffffff 128M online yes 125
+0x00000003f0000000-0x00000003f7ffffff 128M online yes 126
+0x00000003f8000000-0x00000003ffffffff 128M online yes 127
+0x0000000400000000-0x0000000407ffffff 128M online yes 128
+0x0000000408000000-0x000000040fffffff 128M online yes 129
+0x0000000410000000-0x0000000417ffffff 128M online yes 130
+0x0000000418000000-0x000000041fffffff 128M online yes 131
+0x0000000420000000-0x0000000427ffffff 128M online yes 132
+0x0000000428000000-0x000000042fffffff 128M online yes 133
+0x0000000430000000-0x0000000437ffffff 128M online yes 134
+0x0000000438000000-0x000000043fffffff 128M online yes 135
+0x0000000440000000-0x0000000447ffffff 128M online yes 136
+0x0000000448000000-0x000000044fffffff 128M online yes 137
+0x0000000450000000-0x0000000457ffffff 128M online yes 138
+0x0000000458000000-0x000000045fffffff 128M online yes 139
+0x0000000460000000-0x0000000467ffffff 128M online yes 140
+0x0000000468000000-0x000000046fffffff 128M online yes 141
+0x0000000470000000-0x0000000477ffffff 128M online yes 142
+0x0000000478000000-0x000000047fffffff 128M online yes 143
+0x0000000480000000-0x0000000487ffffff 128M online yes 144
+0x0000000488000000-0x000000048fffffff 128M online yes 145
+0x0000000490000000-0x0000000497ffffff 128M online yes 146
+0x0000000498000000-0x000000049fffffff 128M online yes 147
+0x00000004a0000000-0x00000004a7ffffff 128M online yes 148
+0x00000004a8000000-0x00000004afffffff 128M online yes 149
diff --git a/tests/fixtures/lsmem/test_lsmem_raw_bytes.expected b/tests/fixtures/lsmem/test_lsmem_raw_bytes.expected
new file mode 100644
index 0000000..d040477
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_raw_bytes.expected
@@ -0,0 +1,3 @@
+RANGE SIZE STATE REMOVABLE BLOCK
+0x0000000000000000-0x0000000037ffffff 939524096 online yes 0-6
+0x0000000100000000-0x00000004afffffff 15837691904 online yes 32-149
diff --git a/tests/fixtures/lsmem/test_lsmem_raw_noheadings.expected b/tests/fixtures/lsmem/test_lsmem_raw_noheadings.expected
new file mode 100644
index 0000000..caffea9
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_raw_noheadings.expected
@@ -0,0 +1,2 @@
+0x0000000000000000-0x0000000037ffffff 896M online yes 0-6
+0x0000000100000000-0x00000004afffffff 14.8G online yes 32-149
diff --git a/tests/fixtures/lsmem/test_lsmem_split_node.expected b/tests/fixtures/lsmem/test_lsmem_split_node.expected
new file mode 100644
index 0000000..2f1ca26
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_split_node.expected
@@ -0,0 +1,7 @@
+RANGE                                  SIZE  STATE REMOVABLE  BLOCK
+0x0000000000000000-0x0000000037ffffff  896M online       yes    0-6
+0x0000000100000000-0x00000004afffffff 14.8G online       yes 32-149
+
+Memory block size:       128M
+Total online memory:    15.6G
+Total offline memory:      0B
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
diff --git a/tests/fixtures/lsmem/test_lsmem_split_removable.expected b/tests/fixtures/lsmem/test_lsmem_split_removable.expected
new file mode 100644
index 0000000..2f1ca26
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_split_removable.expected
@@ -0,0 +1,7 @@
+RANGE                                  SIZE  STATE REMOVABLE  BLOCK
+0x0000000000000000-0x0000000037ffffff  896M online       yes    0-6
+0x0000000100000000-0x00000004afffffff 14.8G online       yes 32-149
+
+Memory block size:       128M
+Total online memory:    15.6G
+Total offline memory:      0B
diff --git a/tests/fixtures/lsmem/test_lsmem_split_state.expected b/tests/fixtures/lsmem/test_lsmem_split_state.expected
new file mode 100644
index 0000000..2f1ca26
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_split_state.expected
@@ -0,0 +1,7 @@
+RANGE                                  SIZE  STATE REMOVABLE  BLOCK
+0x0000000000000000-0x0000000037ffffff  896M online       yes    0-6
+0x0000000100000000-0x00000004afffffff 14.8G online       yes 32-149
+
+Memory block size:       128M
+Total online memory:    15.6G
+Total offline memory:      0B
diff --git a/tests/fixtures/lsmem/test_lsmem_split_zones.expected b/tests/fixtures/lsmem/test_lsmem_split_zones.expected
new file mode 100644
index 0000000..8c7743e
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_split_zones.expected
@@ -0,0 +1,8 @@
+RANGE                                  SIZE  STATE REMOVABLE  BLOCK
+0x0000000000000000-0x0000000007ffffff  128M online       yes      0
+0x0000000008000000-0x0000000037ffffff  768M online       yes    1-6
+0x0000000100000000-0x00000004afffffff 14.8G online       yes 32-149
+
+Memory block size:       128M
+Total online memory:    15.6G
+Total offline memory:      0B
diff --git a/tests/fixtures/lsmem/test_lsmem_summary_always.expected b/tests/fixtures/lsmem/test_lsmem_summary_always.expected
new file mode 100644
index 0000000..2f1ca26
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_summary_always.expected
@@ -0,0 +1,7 @@
+RANGE                                  SIZE  STATE REMOVABLE  BLOCK
+0x0000000000000000-0x0000000037ffffff  896M online       yes    0-6
+0x0000000100000000-0x00000004afffffff 14.8G online       yes 32-149
+
+Memory block size:       128M
+Total online memory:    15.6G
+Total offline memory:      0B
diff --git a/tests/fixtures/lsmem/test_lsmem_summary_empty.expected b/tests/fixtures/lsmem/test_lsmem_summary_empty.expected
new file mode 100644
index 0000000..6ce4160
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_summary_empty.expected
@@ -0,0 +1,3 @@
+Memory block size:       128M
+Total online memory:    15.6G
+Total offline memory:      0B
diff --git a/tests/fixtures/lsmem/test_lsmem_summary_never.expected b/tests/fixtures/lsmem/test_lsmem_summary_never.expected
new file mode 100644
index 0000000..88dc2b9
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_summary_never.expected
@@ -0,0 +1,3 @@
+RANGE                                  SIZE  STATE REMOVABLE  BLOCK
+0x0000000000000000-0x0000000037ffffff  896M online       yes    0-6
+0x0000000100000000-0x00000004afffffff 14.8G online       yes 32-149
diff --git a/tests/fixtures/lsmem/test_lsmem_summary_only.expected b/tests/fixtures/lsmem/test_lsmem_summary_only.expected
new file mode 100644
index 0000000..6ce4160
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_summary_only.expected
@@ -0,0 +1,3 @@
+Memory block size:       128M
+Total online memory:    15.6G
+Total offline memory:      0B
diff --git a/tests/fixtures/lsmem/test_lsmem_table.expected b/tests/fixtures/lsmem/test_lsmem_table.expected
new file mode 100644
index 0000000..2f1ca26
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_table.expected
@@ -0,0 +1,7 @@
+RANGE                                  SIZE  STATE REMOVABLE  BLOCK
+0x0000000000000000-0x0000000037ffffff  896M online       yes    0-6
+0x0000000100000000-0x00000004afffffff 14.8G online       yes 32-149
+
+Memory block size:       128M
+Total online memory:    15.6G
+Total offline memory:      0B
diff --git a/tests/fixtures/lsmem/test_lsmem_table_all.expected b/tests/fixtures/lsmem/test_lsmem_table_all.expected
new file mode 100644
index 0000000..7a14188
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_table_all.expected
@@ -0,0 +1,130 @@
+RANGE                                  SIZE  STATE REMOVABLE BLOCK
+0x0000000000000000-0x0000000007ffffff  128M online       yes     0
+0x0000000008000000-0x000000000fffffff  128M online       yes     1
+0x0000000010000000-0x0000000017ffffff  128M online       yes     2
+0x0000000018000000-0x000000001fffffff  128M online       yes     3
+0x0000000020000000-0x0000000027ffffff  128M online       yes     4
+0x0000000028000000-0x000000002fffffff  128M online       yes     5
+0x0000000030000000-0x0000000037ffffff  128M online       yes     6
+0x0000000100000000-0x0000000107ffffff  128M online       yes    32
+0x0000000108000000-0x000000010fffffff  128M online       yes    33
+0x0000000110000000-0x0000000117ffffff  128M online       yes    34
+0x0000000118000000-0x000000011fffffff  128M online       yes    35
+0x0000000120000000-0x0000000127ffffff  128M online       yes    36
+0x0000000128000000-0x000000012fffffff  128M online       yes    37
+0x0000000130000000-0x0000000137ffffff  128M online       yes    38
+0x0000000138000000-0x000000013fffffff  128M online       yes    39
+0x0000000140000000-0x0000000147ffffff  128M online       yes    40
+0x0000000148000000-0x000000014fffffff  128M online       yes    41
+0x0000000150000000-0x0000000157ffffff  128M online       yes    42
+0x0000000158000000-0x000000015fffffff  128M online       yes    43
+0x0000000160000000-0x0000000167ffffff  128M online       yes    44
+0x0000000168000000-0x000000016fffffff  128M online       yes    45
+0x0000000170000000-0x0000000177ffffff  128M online       yes    46
+0x0000000178000000-0x000000017fffffff  128M online       yes    47
+0x0000000180000000-0x0000000187ffffff  128M online       yes    48
+0x0000000188000000-0x000000018fffffff  128M online       yes    49
+0x0000000190000000-0x0000000197ffffff  128M online       yes    50
+0x0000000198000000-0x000000019fffffff  128M online       yes    51
+0x00000001a0000000-0x00000001a7ffffff  128M online       yes    52
+0x00000001a8000000-0x00000001afffffff  128M online       yes    53
+0x00000001b0000000-0x00000001b7ffffff  128M online       yes    54
+0x00000001b8000000-0x00000001bfffffff  128M online       yes    55
+0x00000001c0000000-0x00000001c7ffffff  128M online       yes    56
+0x00000001c8000000-0x00000001cfffffff  128M online       yes    57
+0x00000001d0000000-0x00000001d7ffffff  128M online       yes    58
+0x00000001d8000000-0x00000001dfffffff  128M online       yes    59
+0x00000001e0000000-0x00000001e7ffffff  128M online       yes    60
+0x00000001e8000000-0x00000001efffffff  128M online       yes    61
+0x00000001f0000000-0x00000001f7ffffff  128M online       yes    62
+0x00000001f8000000-0x00000001ffffffff  128M online       yes    63
+0x0000000200000000-0x0000000207ffffff  128M online       yes    64
+0x0000000208000000-0x000000020fffffff  128M online       yes    65
+0x0000000210000000-0x0000000217ffffff  128M online       yes    66
+0x0000000218000000-0x000000021fffffff  128M online       yes    67
+0x0000000220000000-0x0000000227ffffff  128M online       yes    68
+0x0000000228000000-0x000000022fffffff  128M online       yes    69
+0x0000000230000000-0x0000000237ffffff  128M online       yes    70
+0x0000000238000000-0x000000023fffffff  128M online       yes    71
+0x0000000240000000-0x0000000247ffffff  128M online       yes    72
+0x0000000248000000-0x000000024fffffff  128M online       yes    73
+0x0000000250000000-0x0000000257ffffff  128M online       yes    74
+0x0000000258000000-0x000000025fffffff  128M online       yes    75
+0x0000000260000000-0x0000000267ffffff  128M online       yes    76
+0x0000000268000000-0x000000026fffffff  128M online       yes    77
+0x0000000270000000-0x0000000277ffffff  128M online       yes    78
+0x0000000278000000-0x000000027fffffff  128M online       yes    79
+0x0000000280000000-0x0000000287ffffff  128M online       yes    80
+0x0000000288000000-0x000000028fffffff  128M online       yes    81
+0x0000000290000000-0x0000000297ffffff  128M online       yes    82
+0x0000000298000000-0x000000029fffffff  128M online       yes    83
+0x00000002a0000000-0x00000002a7ffffff  128M online       yes    84
+0x00000002a8000000-0x00000002afffffff  128M online       yes    85
+0x00000002b0000000-0x00000002b7ffffff  128M online       yes    86
+0x00000002b8000000-0x00000002bfffffff  128M online       yes    87
+0x00000002c0000000-0x00000002c7ffffff  128M online       yes    88
+0x00000002c8000000-0x00000002cfffffff  128M online       yes    89
+0x00000002d0000000-0x00000002d7ffffff  128M online       yes    90
+0x00000002d8000000-0x00000002dfffffff  128M online       yes    91
+0x00000002e0000000-0x00000002e7ffffff  128M online       yes    92
+0x00000002e8000000-0x00000002efffffff  128M online       yes    93
+0x00000002f0000000-0x00000002f7ffffff  128M online       yes    94
+0x00000002f8000000-0x00000002ffffffff  128M online       yes    95
+0x0000000300000000-0x0000000307ffffff  128M online       yes    96
+0x0000000308000000-0x000000030fffffff  128M online       yes    97
+0x0000000310000000-0x0000000317ffffff  128M online       yes    98
+0x0000000318000000-0x000000031fffffff  128M online       yes    99
+0x0000000320000000-0x0000000327ffffff  128M online       yes   100
+0x0000000328000000-0x000000032fffffff  128M online       yes   101
+0x0000000330000000-0x0000000337ffffff  128M online       yes   102
+0x0000000338000000-0x000000033fffffff  128M online       yes   103
+0x0000000340000000-0x0000000347ffffff  128M online       yes   104
+0x0000000348000000-0x000000034fffffff  128M online       yes   105
+0x0000000350000000-0x0000000357ffffff  128M online       yes   106
+0x0000000358000000-0x000000035fffffff  128M online       yes   107
+0x0000000360000000-0x0000000367ffffff  128M online       yes   108
+0x0000000368000000-0x000000036fffffff  128M online       yes   109
+0x0000000370000000-0x0000000377ffffff  128M online       yes   110
+0x0000000378000000-0x000000037fffffff  128M online       yes   111
+0x0000000380000000-0x0000000387ffffff  128M online       yes   112
+0x0000000388000000-0x000000038fffffff  128M online       yes   113
+0x0000000390000000-0x0000000397ffffff  128M online       yes   114
+0x0000000398000000-0x000000039fffffff  128M online       yes   115
+0x00000003a0000000-0x00000003a7ffffff  128M online       yes   116
+0x00000003a8000000-0x00000003afffffff  128M online       yes   117
+0x00000003b0000000-0x00000003b7ffffff  128M online       yes   118
+0x00000003b8000000-0x00000003bfffffff  128M online       yes   119
+0x00000003c0000000-0x00000003c7ffffff  128M online       yes   120
+0x00000003c8000000-0x00000003cfffffff  128M online       yes   121
+0x00000003d0000000-0x00000003d7ffffff  128M online       yes   122
+0x00000003d8000000-0x00000003dfffffff  128M online       yes   123
+0x00000003e0000000-0x00000003e7ffffff  128M online       yes   124
+0x00000003e8000000-0x00000003efffffff  128M online       yes   125
+0x00000003f0000000-0x00000003f7ffffff  128M online       yes   126
+0x00000003f8000000-0x00000003ffffffff  128M online       yes   127
+0x0000000400000000-0x0000000407ffffff  128M online       yes   128
+0x0000000408000000-0x000000040fffffff  128M online       yes   129
+0x0000000410000000-0x0000000417ffffff  128M online       yes   130
+0x0000000418000000-0x000000041fffffff  128M online       yes   131
+0x0000000420000000-0x0000000427ffffff  128M online       yes   132
+0x0000000428000000-0x000000042fffffff  128M online       yes   133
+0x0000000430000000-0x0000000437ffffff  128M online       yes   134
+0x0000000438000000-0x000000043fffffff  128M online       yes   135
+0x0000000440000000-0x0000000447ffffff  128M online       yes   136
+0x0000000448000000-0x000000044fffffff  128M online       yes   137
+0x0000000450000000-0x0000000457ffffff  128M online       yes   138
+0x0000000458000000-0x000000045fffffff  128M online       yes   139
+0x0000000460000000-0x0000000467ffffff  128M online       yes   140
+0x0000000468000000-0x000000046fffffff  128M online       yes   141
+0x0000000470000000-0x0000000477ffffff  128M online       yes   142
+0x0000000478000000-0x000000047fffffff  128M online       yes   143
+0x0000000480000000-0x0000000487ffffff  128M online       yes   144
+0x0000000488000000-0x000000048fffffff  128M online       yes   145
+0x0000000490000000-0x0000000497ffffff  128M online       yes   146
+0x0000000498000000-0x000000049fffffff  128M online       yes   147
+0x00000004a0000000-0x00000004a7ffffff  128M online       yes   148
+0x00000004a8000000-0x00000004afffffff  128M online       yes   149
+
+Memory block size:       128M
+Total online memory:    15.6G
+Total offline memory:      0B
diff --git a/tests/fixtures/lsmem/test_lsmem_table_bytes.expected b/tests/fixtures/lsmem/test_lsmem_table_bytes.expected
new file mode 100644
index 0000000..544c850
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_table_bytes.expected
@@ -0,0 +1,7 @@
+RANGE                                        SIZE  STATE REMOVABLE  BLOCK
+0x0000000000000000-0x0000000037ffffff   939524096 online       yes    0-6
+0x0000000100000000-0x00000004afffffff 15837691904 online       yes 32-149
+
+Memory block size:            134217728
+Total online memory:        16777216000
+Total offline memory:                 0
diff --git a/tests/fixtures/lsmem/test_lsmem_table_noheadings.expected b/tests/fixtures/lsmem/test_lsmem_table_noheadings.expected
new file mode 100644
index 0000000..b89d705
--- /dev/null
+++ b/tests/fixtures/lsmem/test_lsmem_table_noheadings.expected
@@ -0,0 +1,6 @@
+0x0000000000000000-0x0000000037ffffff  896M online       yes    0-6
+0x0000000100000000-0x00000004afffffff 14.8G online       yes 32-149
+
+Memory block size:       128M
+Total online memory:    15.6G
+Total offline memory:      0B