]> git.proxmox.com Git - pxar.git/blame - tests/compat.rs
decoder: aio: Make `TokioReader` public
[pxar.git] / tests / compat.rs
CommitLineData
3a7b42d0
WB
1//! Test for old timestamp format compatibility.
2
3use std::io::{self, Read};
4
5use endian_trait::Endian;
6
7use pxar::{decoder, format, EntryKind};
8
9fn write_raw_struct<T: Endian, W: io::Write + ?Sized>(output: &mut W, data: T) -> io::Result<()> {
10 let data = data.to_le();
11 output.write_all(unsafe {
12 std::slice::from_raw_parts(&data as *const T as *const u8, std::mem::size_of::<T>())
13 })
14}
15
16fn write_data<W>(output: &mut W, htype: u64, data: &[u8]) -> io::Result<()>
17where
18 W: io::Write + ?Sized,
19{
20 let header = format::Header::with_content_size(htype, data.len() as u64);
21 header.check_header_size()?;
22 write_raw_struct(output, header)?;
23 output.write_all(data)
24}
25
26fn write_entry<T, W>(output: &mut W, htype: u64, data: T) -> io::Result<()>
27where
28 T: Endian,
29 W: io::Write + ?Sized,
30{
31 let data = data.to_le();
32 let data = unsafe {
33 std::slice::from_raw_parts(&data as *const T as *const u8, std::mem::size_of::<T>())
34 };
35 write_data(output, htype, data)
36}
37
38const MAY_1_2015_1530: u64 = 1430487000u64;
39
40const FILE_NAME: &str = "file.txt";
41const FILE_NAME_BYTES: &[u8] = b"file.txt\0";
42const FILE_CONTENT: &[u8] = b"This is a small text file.\n";
2ea8aff2 43const ROOT_STAT: format::Stat_V1 = format::Stat_V1 {
3a7b42d0
WB
44 mode: format::mode::IFDIR | 0o755,
45 flags: 0,
46 uid: 1000,
47 gid: 1000,
48 mtime: MAY_1_2015_1530 * 1_000_000_000u64,
49};
2ea8aff2 50const FILE_STAT: format::Stat_V1 = format::Stat_V1 {
3a7b42d0
WB
51 mode: format::mode::IFREG | 0o644,
52 flags: 0,
53 uid: 1000,
54 gid: 1000,
55 mtime: MAY_1_2015_1530 * 1_000_000_000u64,
56};
57
58fn create_archive() -> io::Result<Vec<u8>> {
59 let mut out = Vec::new();
60
61 write_entry(&mut out, format::PXAR_ENTRY_V1, ROOT_STAT.clone())?;
62
63 let file_offset = out.len();
64 write_data(&mut out, format::PXAR_FILENAME, FILE_NAME_BYTES)?;
65 write_entry(&mut out, format::PXAR_ENTRY_V1, FILE_STAT.clone())?;
66 write_data(&mut out, format::PXAR_PAYLOAD, FILE_CONTENT)?;
67
68 let mut gbt = Vec::new();
69 write_raw_struct(
70 &mut gbt,
71 format::GoodbyeItem::new(
72 FILE_NAME.as_bytes(),
73 file_offset as u64,
74 FILE_CONTENT.len() as u64,
75 ),
76 )?;
77
78 let gbt_size = gbt.len();
79 write_raw_struct(
80 &mut gbt,
81 format::GoodbyeItem {
82 hash: format::PXAR_GOODBYE_TAIL_MARKER,
83 offset: out.len() as u64,
84 size: gbt_size as u64,
85 },
86 )?;
87
88 write_data(&mut out, format::PXAR_GOODBYE, &{ gbt })?;
89
90 Ok(out)
91}
92
93#[test]
94fn test_archive() {
95 let archive = create_archive().expect("failed to create test archive");
96 let mut input = &archive[..];
97 let mut decoder = decoder::Decoder::from_std(&mut input).expect("failed to create decoder");
98
99 let item = decoder
100 .next()
101 .expect("missing root directory in test archive")
102 .expect("failed to extract root directory from test archive");
103 match item.kind() {
104 EntryKind::Directory => (),
105 other => panic!("unexpected root entry in archive: {:?}", other),
106 }
107 assert_eq!(item.file_name(), "");
108 assert_eq!(item.metadata().stat, ROOT_STAT.into());
109 assert_eq!(
110 item.metadata().stat.mtime,
180186c5 111 format::StatxTimestamp::new(MAY_1_2015_1530 as i64, 0),
3a7b42d0
WB
112 );
113
114 let item = decoder
115 .next()
116 .expect("missing file entry in test archive")
117 .expect("failed to extract file entry from test archive");
118 match item.kind() {
119 EntryKind::File { size, .. } => assert_eq!(*size, FILE_CONTENT.len() as u64),
120 other => panic!("unexpected file entry in archive: {:?}", other),
121 }
122 assert_eq!(item.file_name(), FILE_NAME);
123 assert_eq!(item.metadata().stat, FILE_STAT.into());
124 let mut content = Vec::new();
125 decoder
126 .contents()
127 .expect("failed to get contents for file entry")
128 .read_to_end(&mut content)
129 .expect("failed to read test file contents");
130 assert_eq!(&content[..], FILE_CONTENT);
131
132 assert!(decoder.next().is_none(), "expected end of test archive");
133}