Nothing to see here, move along meow
1use lancer_core::fs::{BLOCK_SIZE_MIN, Compression};
2use lancer_lancerfs::test_helpers::setup_fs;
3
4#[test]
5fn compressible_data_roundtrip() {
6 let mut fs = setup_fs(4096);
7 let root = fs.root_block();
8 let (_inode, block) = fs.create_file(root, b"compressed");
9
10 let data = vec![0u8; BLOCK_SIZE_MIN as usize * 4];
11 fs.write_file_compressed(block, 0, &data, Compression::Lz4);
12 fs.commit();
13
14 let read_back = fs.read_file(block, 0, data.len());
15 assert_eq!(read_back, data);
16}
17
18#[test]
19fn compressible_data_uses_less_physical_space() {
20 let mut fs = setup_fs(4096);
21 let root = fs.root_block();
22 let (_inode, block) = fs.create_file(root, b"comp_check");
23
24 let data = vec![0u8; BLOCK_SIZE_MIN as usize];
25 fs.write_file_compressed(block, 0, &data, Compression::Lz4);
26
27 let inode = fs.read_inode(block);
28 assert_eq!(inode.size, data.len() as u64);
29
30 let block_ref = &inode.direct[0];
31 assert_eq!(
32 block_ref.compression_enum(),
33 Some(Compression::Lz4),
34 "compressible data must be stored with Lz4 compression"
35 );
36
37 let phys_block = lancer_lancerfs::blockref_block_num(block_ref);
38 let mut raw = [0u8; 4096];
39 fs.bio.read_blocks(phys_block, 1, &mut raw).unwrap();
40 let compressed_len = u32::from_le_bytes([raw[0], raw[1], raw[2], raw[3]]) as usize;
41 assert!(
42 compressed_len < BLOCK_SIZE_MIN as usize,
43 "compressed payload ({compressed_len}) must be smaller than block size ({})",
44 BLOCK_SIZE_MIN
45 );
46 assert!(
47 compressed_len <= BLOCK_SIZE_MIN as usize / 2,
48 "all-zeros block must achieve at least 2:1 compression ratio: \
49 compressed={compressed_len}, half_block={}",
50 BLOCK_SIZE_MIN / 2
51 );
52}
53
54#[test]
55fn incompressible_data_stored_uncompressed() {
56 let mut fs = setup_fs(4096);
57 let root = fs.root_block();
58 let (_inode, block) = fs.create_file(root, b"random");
59
60 let mut data = vec![0u8; BLOCK_SIZE_MIN as usize];
61 let mut state: u64 = 0xDEAD_BEEF_CAFE_BABE;
62 data.iter_mut().for_each(|byte| {
63 state = state
64 .wrapping_mul(6364136223846793005)
65 .wrapping_add(1442695040888963407);
66 *byte = (state >> 33) as u8;
67 });
68
69 fs.write_file_compressed(block, 0, &data, Compression::Lz4);
70 fs.commit();
71
72 let inode = fs.read_inode(block);
73 let block_ref = &inode.direct[0];
74 assert_eq!(
75 block_ref.compression_enum(),
76 Some(Compression::None),
77 "incompressible data must fall back to uncompressed storage"
78 );
79
80 let read_back = fs.read_file(block, 0, data.len());
81 assert_eq!(read_back, data);
82}
83
84#[test]
85fn no_compression_roundtrip() {
86 let mut fs = setup_fs(4096);
87 let root = fs.root_block();
88 let (_inode, block) = fs.create_file(root, b"uncompressed");
89
90 let data: Vec<u8> = (0..BLOCK_SIZE_MIN as usize * 2)
91 .map(|i| (i % 251) as u8)
92 .collect();
93 fs.write_file(block, 0, &data);
94 fs.commit();
95
96 let read_back = fs.read_file(block, 0, data.len());
97 assert_eq!(read_back, data);
98}
99
100#[test]
101fn mixed_compressed_uncompressed_blocks() {
102 let mut fs = setup_fs(4096);
103 let root = fs.root_block();
104 let (_inode, block) = fs.create_file(root, b"mixed");
105
106 let zeros = vec![0u8; BLOCK_SIZE_MIN as usize];
107 fs.write_file_compressed(block, 0, &zeros, Compression::Lz4);
108
109 let mut random = vec![0u8; BLOCK_SIZE_MIN as usize];
110 let mut state: u64 = 0x1234_5678_9ABC_DEF0;
111 random.iter_mut().for_each(|byte| {
112 state = state
113 .wrapping_mul(6364136223846793005)
114 .wrapping_add(1442695040888963407);
115 *byte = (state >> 33) as u8;
116 });
117 fs.write_file_compressed(block, BLOCK_SIZE_MIN as u64, &random, Compression::Lz4);
118 fs.commit();
119
120 let read_first = fs.read_file(block, 0, BLOCK_SIZE_MIN as usize);
121 let read_second = fs.read_file(block, BLOCK_SIZE_MIN as u64, BLOCK_SIZE_MIN as usize);
122
123 assert_eq!(read_first, zeros);
124 assert_eq!(read_second, random);
125}