exarch_core/
test_utils.rs1#![allow(clippy::unwrap_used, clippy::missing_panics_doc)]
12
13use std::io::Cursor;
14use std::io::Write;
15
16#[must_use]
28pub fn create_test_tar(entries: Vec<(&str, &[u8])>) -> Vec<u8> {
29 let mut ar = tar::Builder::new(Vec::new());
30 for (path, data) in entries {
31 let mut header = tar::Header::new_gnu();
32 header.set_size(data.len() as u64);
33 header.set_mode(0o644);
34 header.set_cksum();
35 ar.append_data(&mut header, path, data).unwrap();
36 }
37 ar.into_inner().unwrap()
38}
39
40#[must_use]
53pub fn create_test_zip(entries: Vec<(&str, &[u8])>) -> Vec<u8> {
54 use zip::write::SimpleFileOptions;
55 use zip::write::ZipWriter;
56
57 let buffer = Vec::new();
58 let mut zip = ZipWriter::new(Cursor::new(buffer));
59
60 let options = SimpleFileOptions::default()
61 .compression_method(zip::CompressionMethod::Stored)
62 .unix_permissions(0o644);
63
64 for (path, data) in entries {
65 zip.start_file(path, options).unwrap();
66 zip.write_all(data).unwrap();
67 }
68
69 zip.finish().unwrap().into_inner()
70}
71
72pub struct TarTestBuilder {
88 builder: tar::Builder<Vec<u8>>,
89}
90
91impl TarTestBuilder {
92 #[must_use]
94 pub fn new() -> Self {
95 Self {
96 builder: tar::Builder::new(Vec::new()),
97 }
98 }
99
100 #[must_use]
102 pub fn add_file(mut self, path: &str, data: &[u8]) -> Self {
103 let mut header = tar::Header::new_gnu();
104 header.set_size(data.len() as u64);
105 header.set_mode(0o644);
106 header.set_cksum();
107 self.builder.append_data(&mut header, path, data).unwrap();
108 self
109 }
110
111 #[must_use]
113 pub fn add_file_with_mode(mut self, path: &str, data: &[u8], mode: u32) -> Self {
114 let mut header = tar::Header::new_gnu();
115 header.set_size(data.len() as u64);
116 header.set_mode(mode);
117 header.set_cksum();
118 self.builder.append_data(&mut header, path, data).unwrap();
119 self
120 }
121
122 #[must_use]
124 pub fn add_directory(mut self, path: &str) -> Self {
125 let mut header = tar::Header::new_gnu();
126 header.set_size(0);
127 header.set_mode(0o755);
128 header.set_entry_type(tar::EntryType::Directory);
129 header.set_cksum();
130 self.builder
131 .append_data(&mut header, path, std::io::empty())
132 .unwrap();
133 self
134 }
135
136 #[must_use]
138 pub fn add_symlink(mut self, path: &str, target: &str) -> Self {
139 let mut header = tar::Header::new_gnu();
140 header.set_size(0);
141 header.set_mode(0o777);
142 header.set_entry_type(tar::EntryType::Symlink);
143 header.set_link_name(target).unwrap();
144 header.set_cksum();
145 self.builder
146 .append_data(&mut header, path, std::io::empty())
147 .unwrap();
148 self
149 }
150
151 #[must_use]
153 pub fn add_hardlink(mut self, path: &str, target: &str) -> Self {
154 let mut header = tar::Header::new_gnu();
155 header.set_size(0);
156 header.set_mode(0o644);
157 header.set_entry_type(tar::EntryType::Link);
158 header.set_link_name(target).unwrap();
159 header.set_cksum();
160 self.builder
161 .append_data(&mut header, path, std::io::empty())
162 .unwrap();
163 self
164 }
165
166 #[must_use]
168 pub fn build(self) -> Vec<u8> {
169 self.builder.into_inner().unwrap()
170 }
171}
172
173impl Default for TarTestBuilder {
174 fn default() -> Self {
175 Self::new()
176 }
177}
178
179pub struct ZipTestBuilder {
192 zip: zip::ZipWriter<Cursor<Vec<u8>>>,
193}
194
195impl ZipTestBuilder {
196 #[must_use]
198 pub fn new() -> Self {
199 Self {
200 zip: zip::ZipWriter::new(Cursor::new(Vec::new())),
201 }
202 }
203
204 #[must_use]
206 pub fn add_file(mut self, path: &str, data: &[u8]) -> Self {
207 use zip::write::SimpleFileOptions;
208
209 let options = SimpleFileOptions::default()
210 .compression_method(zip::CompressionMethod::Stored)
211 .unix_permissions(0o644);
212
213 self.zip.start_file(path, options).unwrap();
214 self.zip.write_all(data).unwrap();
215 self
216 }
217
218 #[must_use]
220 pub fn add_file_with_mode(mut self, path: &str, data: &[u8], mode: u32) -> Self {
221 use zip::write::SimpleFileOptions;
222
223 let options = SimpleFileOptions::default()
224 .compression_method(zip::CompressionMethod::Stored)
225 .unix_permissions(mode);
226
227 self.zip.start_file(path, options).unwrap();
228 self.zip.write_all(data).unwrap();
229 self
230 }
231
232 #[must_use]
234 pub fn add_directory(mut self, path: &str) -> Self {
235 use zip::write::SimpleFileOptions;
236
237 let options = SimpleFileOptions::default().unix_permissions(0o755);
238 self.zip.add_directory(path, options).unwrap();
239 self
240 }
241
242 #[cfg(unix)]
244 #[must_use]
245 pub fn add_symlink(mut self, path: &str, target: &str) -> Self {
246 use zip::write::SimpleFileOptions;
247
248 let options = SimpleFileOptions::default().unix_permissions(0o120_777);
250
251 self.zip.start_file(path, options).unwrap();
252 self.zip.write_all(target.as_bytes()).unwrap();
253 self
254 }
255
256 #[must_use]
258 pub fn build(self) -> Vec<u8> {
259 self.zip.finish().unwrap().into_inner()
260 }
261}
262
263impl Default for ZipTestBuilder {
264 fn default() -> Self {
265 Self::new()
266 }
267}
268
269#[cfg(test)]
270mod tests {
271 use super::*;
272
273 #[test]
274 fn test_create_test_tar() {
275 let tar_data = create_test_tar(vec![("file.txt", b"hello")]);
276 assert!(!tar_data.is_empty());
277 }
278
279 #[test]
280 fn test_create_test_zip() {
281 let zip_data = create_test_zip(vec![("file.txt", b"hello")]);
282 assert!(!zip_data.is_empty());
283 }
284
285 #[test]
286 fn test_tar_builder() {
287 let tar_data = TarTestBuilder::new()
288 .add_file("file.txt", b"content")
289 .add_directory("dir/")
290 .build();
291 assert!(!tar_data.is_empty());
292 }
293
294 #[test]
295 fn test_zip_builder() {
296 let zip_data = ZipTestBuilder::new()
297 .add_file("file.txt", b"content")
298 .add_directory("dir/")
299 .build();
300 assert!(!zip_data.is_empty());
301 }
302}