1mod bitmap;
2mod commands;
3mod types;
4mod util;
5
6pub use bitmap::*;
8pub use commands::*;
9pub use types::*;
10pub use util::*;
11
12#[cfg(test)]
13mod tests {
14 use super::*;
15
16 #[test]
17 fn test_afp_status_round_trip() {
18 let status = FPGetSrvrInfo {
19 machine_type: MacString::from("Macintosh"),
20 afp_versions: vec![
21 AfpVersion::Version1_1,
22 AfpVersion::Version2,
23 AfpVersion::Version2_1,
24 ],
25 uams: vec![AfpUam::NoUserAuthent, AfpUam::CleartxtPasswrd],
26 volume_icon: Some([0xAA; 256]), flags: 0x0001, server_name: MacString::from("Test Server"),
29 };
30
31 let bytes = status.to_bytes().expect("Serialization failed");
32
33 assert_eq!(bytes.len(), 368);
34
35 let parsed = FPGetSrvrInfo::parse(&bytes).expect("Parsing failed");
36
37 assert_eq!(status, parsed);
38 }
39
40 #[test]
41 fn test_afp_status_no_icon() {
42 let status = FPGetSrvrInfo {
43 machine_type: MacString::from("Macintosh"),
44 afp_versions: vec![AfpVersion::Version2],
45 uams: vec![AfpUam::NoUserAuthent],
46 volume_icon: None,
47 flags: 0,
48 server_name: MacString::from("Mini"),
49 };
50
51 let bytes = status.to_bytes().expect("Serialization failed");
52 let parsed = FPGetSrvrInfo::parse(&bytes).expect("Parsing failed");
53
54 assert_eq!(status, parsed);
55 }
56
57 #[test]
58 fn test_afp_status_binary() {
59 let test_data: &[u8] = &[
61 0x0, 0x2b, 0x0, 0x35, 0x0, 0x63, 0x0, 0x9d, 0x80, 0xb, 0xc, 0x50, 0x6f, 0x77, 0x65,
62 0x72, 0x42, 0x6f, 0x6f, 0x6b, 0x20, 0x47, 0x33, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
63 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
64 0x9, 0x4d, 0x61, 0x63, 0x69, 0x6e, 0x74, 0x6f, 0x73, 0x68, 0x3, 0xe, 0x41, 0x46, 0x50,
65 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x2e, 0x31, 0xe, 0x41, 0x46,
66 0x50, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x2e, 0x30, 0xe, 0x41,
67 0x46, 0x50, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x2e, 0x31, 0x3,
68 0x10, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x74, 0x78, 0x74, 0x20, 0x70, 0x61, 0x73, 0x73,
69 0x77, 0x72, 0x64, 0x10, 0x52, 0x61, 0x6e, 0x64, 0x6e, 0x75, 0x6d, 0x20, 0x65, 0x78,
70 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x16, 0x32, 0x2d, 0x57, 0x61, 0x79, 0x20, 0x52,
71 0x61, 0x6e, 0x64, 0x6e, 0x75, 0x6d, 0x20, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
72 0x65, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x9f, 0xe0,
73 0x0, 0x4, 0x50, 0x30, 0x0, 0x8, 0x30, 0x28, 0x0, 0x10, 0x10, 0x3c, 0x7, 0xa0, 0x8, 0x4,
74 0x18, 0x7f, 0x4, 0x4, 0x10, 0x0, 0x82, 0x4, 0x10, 0x0, 0x81, 0x4, 0x10, 0x0, 0x82, 0x4,
75 0x10, 0x0, 0x84, 0x4, 0x10, 0x0, 0x88, 0x4, 0x10, 0x0, 0x90, 0x4, 0x10, 0x0, 0xb0, 0x4,
76 0x10, 0x0, 0xd0, 0x4, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x2, 0x3f, 0xff, 0xff,
77 0xfc, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x5, 0x0,
78 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0x8, 0x80, 0x0, 0x0, 0x8, 0x80, 0x0, 0x0, 0xf, 0x80,
79 0x0, 0x0, 0xa, 0x80, 0xbf, 0xff, 0xf2, 0x74, 0x0, 0x0, 0x5, 0x0, 0xbf, 0xff, 0xf8,
80 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x3, 0x9f, 0xe0,
81 0x0, 0x7, 0xdf, 0xf0, 0x0, 0xf, 0xff, 0xf8, 0x0, 0x1f, 0xff, 0xfc, 0x7, 0xbf, 0xff,
82 0xfc, 0x1f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xfc, 0x1f,
83 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff,
84 0xfc, 0x1f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x7f,
85 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0,
86 0x0, 0x7, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0,
87 0xf, 0x80, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xf, 0x80, 0xbf, 0xff, 0xff, 0xf4, 0xbf,
88 0xff, 0xfd, 0xf4, 0xbf, 0xff, 0xf8, 0xf4,
89 ];
90
91 let packet = FPGetSrvrInfo::parse(test_data).expect("Failed to parse test data");
92
93 assert_eq!(packet.machine_type.as_str(), "Macintosh");
95 assert_eq!(packet.afp_versions.len(), 3);
96 assert_eq!(packet.uams.len(), 3);
97 assert_eq!(packet.server_name.as_str(), "PowerBook G3");
98
99 let encoded = packet.to_bytes().expect("Failed to encode packet");
101 let reparsed = FPGetSrvrInfo::parse(&encoded).expect("Failed to reparse encoded data");
102
103 assert_eq!(packet, reparsed);
105 }
106
107 #[test]
108 fn test_fplogin_no_auth() {
109 let login = FPLogin {
111 afp_version: AfpVersion::Version2,
112 auth: FPLoginAuth::NoUserAuthent,
113 };
114
115 let encoded = login.to_bytes().expect("Failed to encode");
116 let decoded = FPLogin::parse(&encoded).expect("Failed to parse");
117
118 assert_eq!(login, decoded);
119 assert_eq!(decoded.afp_version, AfpVersion::Version2);
120 assert_eq!(decoded.auth, FPLoginAuth::NoUserAuthent);
121 }
122
123 #[test]
124 fn test_fplogin_cleartext() {
125 let mut password = [0u8; 8];
127 password[..4].copy_from_slice(b"pass");
128
129 let login = FPLogin {
130 afp_version: AfpVersion::Version2_1,
131 auth: FPLoginAuth::CleartxtPasswrd {
132 username: MacString::from("testuser"),
133 password,
134 },
135 };
136
137 let encoded = login.to_bytes().expect("Failed to encode");
138 let decoded = FPLogin::parse(&encoded).expect("Failed to parse");
139
140 assert_eq!(login, decoded);
141 assert_eq!(decoded.afp_version, AfpVersion::Version2_1);
142
143 if let FPLoginAuth::CleartxtPasswrd {
144 username,
145 password: pwd,
146 } = decoded.auth
147 {
148 assert_eq!(username.as_str(), "testuser");
149 assert_eq!(&pwd[..4], b"pass");
150 assert_eq!(&pwd[4..], &[0, 0, 0, 0]); } else {
152 panic!("Expected CleartxtPasswrd auth");
153 }
154 }
155
156 #[test]
157 fn test_fplogin_round_trip() {
158 let test_cases = vec![
160 FPLogin {
161 afp_version: AfpVersion::Version1,
162 auth: FPLoginAuth::NoUserAuthent,
163 },
164 FPLogin {
165 afp_version: AfpVersion::Version2,
166 auth: FPLoginAuth::CleartxtPasswrd {
167 username: MacString::from("admin"),
168 password: *b"secret\0\0",
169 },
170 },
171 ];
172
173 for original in test_cases {
174 let encoded = original.to_bytes().expect("Failed to encode");
175 let decoded = FPLogin::parse(&encoded).expect("Failed to parse");
176 assert_eq!(original, decoded);
177 }
178 }
179
180 #[test]
181 fn test_fplogin_errors() {
182 assert!(FPLogin::parse(&[]).is_err());
184
185 assert!(FPLogin::parse(&[5]).is_err());
187
188 let invalid_version = vec![
190 10, b'B', b'a', b'd', b'V', b'e', b'r', b's', b'i', b'o', b'n', 16, b'N', b'o', b' ',
191 b'U', b's', b'e', b'r', b' ', b'A', b'u', b't', b'h', b'e', b'n', b't',
192 ];
193 assert!(FPLogin::parse(&invalid_version).is_err());
194
195 let invalid_uam = vec![
197 14, b'A', b'F', b'P', b'V', b'e', b'r', b's', b'i', b'o', b'n', b' ', b'2', b'.', b'0',
198 10, b'B', b'a', b'd', b'U', b'A', b'M', b'N', b'a', b'm', b'e',
199 ];
200 assert!(FPLogin::parse(&invalid_uam).is_err());
201
202 let missing_password = vec![
204 14, b'A', b'F', b'P', b'V', b'e', b'r', b's', b'i', b'o', b'n', b' ', b'2', b'.', b'0',
205 16, b'C', b'l', b'e', b'a', b'r', b't', b'x', b't', b' ', b'P', b'a', b's', b's', b'w',
206 b'r', b'd', 4, b'u', b's', b'e', b'r',
207 ];
209 assert!(FPLogin::parse(&missing_password).is_err());
210 }
211
212 #[test]
213 fn test_fplogin_long_username() {
214 let long_username = "a".repeat(300);
216 let mut password = [0u8; 8];
217 password[..4].copy_from_slice(b"test");
218
219 let login = FPLogin {
220 afp_version: AfpVersion::Version2,
221 auth: FPLoginAuth::CleartxtPasswrd {
222 username: MacString::from(long_username.clone()),
223 password,
224 },
225 };
226
227 let encoded = login.to_bytes().expect("Failed to encode");
228 let decoded = FPLogin::parse(&encoded).expect("Failed to parse");
229
230 if let FPLoginAuth::CleartxtPasswrd { username, .. } = decoded.auth {
232 assert_eq!(username.len(), 255);
233 assert_eq!(username.as_str(), "a".repeat(255));
234 } else {
235 panic!("Expected CleartxtPasswrd auth");
236 }
237 }
238}