Skip to content

Commit 9f2319b

Browse files
committed
test: hardlinks details
1 parent b1501c3 commit 9f2319b

2 files changed

Lines changed: 42 additions & 1 deletion

File tree

tests/_utils.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,15 @@ pub fn read_apparent_size(path: &Path) -> u64 {
491491
.len()
492492
}
493493

494+
/// Read [ino](std::os::unix::fs::MetadataExt::ino) of a path.
495+
#[cfg(unix)]
496+
pub fn read_ino(path: &Path) -> u64 {
497+
use std::os::unix::fs::MetadataExt;
498+
path.pipe(symlink_metadata)
499+
.unwrap_or_else(|error| panic!("Can't read metadata at {path:?}: {error}"))
500+
.ino()
501+
}
502+
494503
/// Utility methods to sort various types of arrays.
495504
pub trait IntoSorted<Item>: Sized {
496505
/// Sort an array by [`Ord`] and return it.

tests/deduplicate_hardlinks.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,21 @@ pub use _utils::*;
77
use command_extra::CommandExtra;
88
use parallel_disk_usage::{
99
data_tree::Reflection,
10-
hardlink::hardlink_list::Summary,
10+
hardlink::{
11+
hardlink_list::{self, Summary},
12+
LinkPathListReflection,
13+
},
14+
inode::InodeNumber,
1115
json_data::{JsonData, JsonTree},
1216
size::Bytes,
1317
};
1418
use pipe_trait::Pipe;
1519
use pretty_assertions::assert_eq;
1620
use std::{
21+
collections::HashSet,
1722
iter,
1823
ops::{Add, Mul},
24+
path::PathBuf,
1925
process::{Command, Stdio},
2026
};
2127

@@ -51,6 +57,11 @@ fn multiple_hardlinks_to_a_single_file_with_deduplication() {
5157
.pipe_as_ref(read_apparent_size)
5258
.pipe(Bytes::new);
5359

60+
let file_ino = workspace
61+
.join("file.txt")
62+
.pipe_as_ref(read_ino)
63+
.pipe(InodeNumber::from);
64+
5465
let actual_size = tree.size;
5566
let expected_size = workspace
5667
.pipe_as_ref(read_apparent_size)
@@ -78,6 +89,26 @@ fn multiple_hardlinks_to_a_single_file_with_deduplication() {
7889
};
7990
assert_eq!(actual_children, expected_children);
8091

92+
let actual_shared_details: Vec<_> = tree
93+
.shared
94+
.details
95+
.expect("get details")
96+
.iter()
97+
.cloned()
98+
.collect();
99+
let expected_shared_details = vec![hardlink_list::reflection::ReflectionEntry {
100+
ino: file_ino,
101+
size: file_size,
102+
links: 1 + links,
103+
paths: (0..links)
104+
.map(|num| format!("./link.{num}"))
105+
.chain("./file.txt".to_string().pipe(iter::once))
106+
.map(PathBuf::from)
107+
.collect::<HashSet<_>>()
108+
.pipe(LinkPathListReflection),
109+
}];
110+
assert_eq!(actual_shared_details, expected_shared_details);
111+
81112
let actual_shared_summary = tree.shared.summary;
82113
let expected_shared_summary = {
83114
let mut summary = Summary::default();
@@ -121,6 +152,7 @@ fn multiple_hardlinks_to_a_single_file_without_deduplication() {
121152
.pipe(Bytes::new);
122153
assert_eq!(actual_size, expected_size);
123154

155+
assert!(tree.shared.details.is_none());
124156
assert_eq!(tree.shared.summary, None);
125157
}
126158

0 commit comments

Comments
 (0)