Skip to content

Commit 951392f

Browse files
committed
Move the test case
1 parent 509e2e1 commit 951392f

File tree

2 files changed

+50
-53
lines changed

2 files changed

+50
-53
lines changed

src/internals.rs

Lines changed: 4 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
mod c;
2-
mod cast;
3-
mod helpers;
1+
pub(crate) mod c;
2+
pub(crate) mod cast;
3+
pub(crate) mod helpers;
44

55
use std::ffi::OsString;
66
use std::mem::size_of;
@@ -20,7 +20,7 @@ const NT_PREFIX: [u16; 4] = helpers::utf16s(br"\??\");
2020
/// Ref: <https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry>
2121
const VERBATIM_PREFIX: [u16; 4] = helpers::utf16s(br"\\?\");
2222

23-
const WCHAR_SIZE: u16 = size_of::<u16>() as _;
23+
pub(crate) const WCHAR_SIZE: u16 = size_of::<u16>() as _;
2424

2525
pub fn create(target: &Path, junction: &Path) -> io::Result<()> {
2626
const UNICODE_NULL_SIZE: u16 = WCHAR_SIZE;
@@ -152,51 +152,3 @@ pub fn get_target(junction: &Path) -> io::Result<PathBuf> {
152152
Err(io::Error::new(io::ErrorKind::Other, "not a reparse tag mount point"))
153153
}
154154
}
155-
156-
#[cfg(test)]
157-
mod tests {
158-
use std::ffi::OsString;
159-
use std::os::windows::ffi::OsStringExt;
160-
use std::os::windows::io::AsRawHandle;
161-
use std::{fs, slice};
162-
163-
use super::*;
164-
165-
#[test]
166-
fn create_populates_print_name() {
167-
// Regression test: the junction reparse point must have a non-empty PrintName
168-
// so that Windows Container layer snapshots correctly preserve the junction target.
169-
let tmpdir = tempfile::tempdir().unwrap();
170-
let target = tmpdir.path().join("target");
171-
let junction = tmpdir.path().join("junction");
172-
fs::create_dir_all(&target).unwrap();
173-
174-
create(&target, &junction).unwrap();
175-
176-
// Read back the raw reparse data
177-
let mut data = cast::BytesAsReparseDataBuffer::new();
178-
{
179-
let file = helpers::open_reparse_point(&junction, false).unwrap();
180-
helpers::get_reparse_data_point(file.as_raw_handle(), data.as_mut_ptr()).unwrap();
181-
}
182-
let rdb = unsafe { data.assume_init() };
183-
184-
assert_eq!(rdb.ReparseTag, c::IO_REPARSE_TAG_MOUNT_POINT);
185-
186-
// Read PrintName
187-
let print_offset = (rdb.ReparseBuffer.PrintNameOffset / WCHAR_SIZE) as usize;
188-
let print_len = (rdb.ReparseBuffer.PrintNameLength / WCHAR_SIZE) as usize;
189-
let print_name = unsafe {
190-
let buf = rdb.ReparseBuffer.PathBuffer.as_ptr().add(print_offset);
191-
slice::from_raw_parts(buf, print_len)
192-
};
193-
194-
// PrintName must not be empty
195-
assert!(print_len > 0, "PrintName must not be empty");
196-
197-
// PrintName should match what get_target returns (the Win32 path without \??\ prefix)
198-
let print_path = PathBuf::from(OsString::from_wide(print_name));
199-
let target_path = get_target(&junction).unwrap();
200-
assert_eq!(print_path, target_path, "PrintName should match the target path");
201-
}
202-
}

src/tests.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
use std::ffi::OsString;
12
use std::fs::{self, File};
23
use std::io::{self, Write};
4+
use std::os::windows::ffi::OsStringExt;
35
use std::os::windows::fs::symlink_file;
6+
use std::os::windows::io::AsRawHandle;
47
#[cfg(miri)]
5-
use std::path::{Path, PathBuf};
8+
use std::path::Path;
9+
use std::path::PathBuf;
10+
use std::slice;
611

712
#[cfg(not(miri))]
813
use tempfile::TempDir;
@@ -265,3 +270,43 @@ fn create_with_verbatim_prefix_paths() {
265270
// get_target returns path without verbatim prefix
266271
assert_eq!(super::get_target(&junction).unwrap(), target);
267272
}
273+
274+
#[test]
275+
fn create_populates_print_name() {
276+
// Regression test: the junction reparse point must have a non-empty PrintName
277+
// so that Windows Container layer snapshots correctly preserve the junction target.
278+
use super::internals::{c, cast, helpers, WCHAR_SIZE};
279+
280+
let tmpdir = tempfile::tempdir().unwrap();
281+
let target = tmpdir.path().join("target");
282+
let junction = tmpdir.path().join("junction");
283+
fs::create_dir_all(&target).unwrap();
284+
285+
super::create(&target, &junction).unwrap();
286+
287+
// Read back the raw reparse data
288+
let mut data = cast::BytesAsReparseDataBuffer::new();
289+
{
290+
let file = helpers::open_reparse_point(&junction, false).unwrap();
291+
helpers::get_reparse_data_point(file.as_raw_handle(), data.as_mut_ptr()).unwrap();
292+
}
293+
let rdb = unsafe { data.assume_init() };
294+
295+
assert_eq!(rdb.ReparseTag, c::IO_REPARSE_TAG_MOUNT_POINT);
296+
297+
// Read PrintName
298+
let print_offset = (rdb.ReparseBuffer.PrintNameOffset / WCHAR_SIZE) as usize;
299+
let print_len = (rdb.ReparseBuffer.PrintNameLength / WCHAR_SIZE) as usize;
300+
let print_name = unsafe {
301+
let buf = rdb.ReparseBuffer.PathBuffer.as_ptr().add(print_offset);
302+
slice::from_raw_parts(buf, print_len)
303+
};
304+
305+
// PrintName must not be empty
306+
assert!(print_len > 0, "PrintName must not be empty");
307+
308+
// PrintName should match what get_target returns (the Win32 path without \??\ prefix)
309+
let print_path = PathBuf::from(OsString::from_wide(print_name));
310+
let target_path = super::get_target(&junction).unwrap();
311+
assert_eq!(print_path, target_path, "PrintName should match the target path");
312+
}

0 commit comments

Comments
 (0)