1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
use std::io::Write as _;
use transfer::*;
fn sample_media() -> Vec<ArchiveMediaInput> {
vec![
ArchiveMediaInput {
metadata: ArchivedMediaMetadata {
id: "asset-1".into(),
name: "clip one.mp4".into(),
media_type: "video".into(),
file_type: "video/mp4".into(),
last_modified: 1_753_000_000_000.0,
width: Some(1920.0),
height: Some(1080.0),
duration: Some(12.5),
ephemeral: None,
thumbnail_url: None,
},
data: vec![1, 2, 3, 4],
},
ArchiveMediaInput {
metadata: ArchivedMediaMetadata {
id: "asset-2".into(),
name: ".hidden".into(),
media_type: "audio".into(),
file_type: "audio/wav".into(),
last_modified: 1_753_000_000_001.0,
width: None,
height: None,
duration: None,
ephemeral: Some(true),
thumbnail_url: None,
},
data: vec![5, 6, 7],
},
]
}
#[test]
fn sanitize_matches_web_rules() {
assert_eq!(sanitize_file_name("clip one.mp4"), "clip_one.mp4");
assert_eq!(sanitize_file_name(".."), "file");
assert_eq!(sanitize_file_name("...weird..name.."), "weird..name..");
assert_eq!(sanitize_file_name("a b"), "a_b");
assert_eq!(sanitize_file_name(" "), "file");
assert_eq!(sanitize_file_name("caf\u{00e9}.mov"), "caf_.mov");
}
#[test]
fn archive_round_trip() {
let project_json = r#"{"version":7,"metadata":{"id":"p1"}}"#;
let archive = build_project_archive(project_json, sample_media()).expect("build");
let parsed = parse_project_archive(&archive).expect("parse");
assert_eq!(
parsed.project.get("version").and_then(|v| v.as_u64()),
Some(7)
);
assert_eq!(parsed.media.len(), 2);
assert_eq!(parsed.media[0].entry, "media/asset-1-clip_one.mp4");
assert_eq!(parsed.media[1].entry, "media/asset-2-hidden");
assert_eq!(
parsed.read_media_data("media/asset-1-clip_one.mp4").unwrap(),
&[1, 2, 3, 4]
);
assert_eq!(parsed.read_media_data("media/asset-2-hidden").unwrap(), &[5, 6, 7]);
}
#[test]
fn archive_without_media_is_valid() {
let archive = build_project_archive("{}", Vec::new()).expect("build");
let parsed = parse_project_archive(&archive).expect("parse");
assert!(parsed.media.is_empty());
}
#[test]
fn rejects_garbage() {
let error = parse_project_archive(b"not a zip").unwrap_err();
assert!(error.to_string().contains("unreadable zip file"));
}
#[test]
fn rejects_missing_project_json() {
let mut cursor = std::io::Cursor::new(Vec::new());
{
let mut writer = zip::ZipWriter::new(&mut cursor);
let options: zip::write::SimpleFileOptions = Default::default();
writer.start_file("other.txt", options).unwrap();
writer.write_all(b"hi").unwrap();
writer.finish().unwrap();
}
let error = parse_project_archive(&cursor.into_inner()).unwrap_err();
assert!(error.to_string().contains("project.json is missing"));
}
|