1mod figlet;
26mod shared;
27mod toilet;
28
29pub use figlet::FIGlet;
30pub use shared::{FIGcharacter, FIGure, HeaderLine};
31pub use toilet::Toilet;
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36 use crate::shared::{
37 FontData, SM_BIGX, SM_EQUAL, SM_HARDBLANK, SM_HIERARCHY, SM_KERN, SM_LOWLINE, SM_PAIR,
38 SM_SMUSH,
39 };
40 use std::fs;
41 use std::path::Path;
42
43 fn fixture(path: &str) -> String {
44 let root = Path::new(env!("CARGO_MANIFEST_DIR"));
45 fs::read_to_string(root.join(path)).unwrap()
46 }
47
48 fn full_smush_font() -> FIGlet {
49 let mut font = FIGlet::standard().unwrap();
50 font.header_line.full_layout = Some(
51 SM_EQUAL | SM_LOWLINE | SM_HIERARCHY | SM_PAIR | SM_BIGX | SM_HARDBLANK | SM_SMUSH,
52 );
53 font
54 }
55
56 fn assert_golden_fixture_figlet(font: &FIGlet, message: &str, fixture_path: &str) {
57 let figure = font.convert(message).unwrap();
58 assert_eq!(fixture(fixture_path), figure.as_str());
59 }
60
61 fn assert_golden_fixture_toilet(font: &Toilet, message: &str, fixture_path: &str) {
62 let figure = font.convert(message).unwrap();
63 assert_eq!(fixture(fixture_path), figure.as_str());
64 }
65
66 #[test]
67 fn test_new_headerline() {
68 let line = "flf2a$ 6 5 20 15 3 0 143 229";
69 let headerline = HeaderLine::try_from(line).unwrap();
70
71 assert_eq!(line, headerline.header_line);
72 assert_eq!("flf2a", headerline.signature);
73 assert_eq!('$', headerline.hardblank);
74 assert_eq!(6, headerline.height);
75 assert_eq!(5, headerline.baseline);
76 assert_eq!(20, headerline.max_length);
77 assert_eq!(15, headerline.old_layout);
78 assert_eq!(3, headerline.comment_lines);
79 assert_eq!(Some(0), headerline.print_direction);
80 assert_eq!(Some(143), headerline.full_layout);
81 assert_eq!(Some(229), headerline.codetag_count);
82 }
83
84 #[test]
85 fn test_new_figfont() {
86 let font = FIGlet::standard().unwrap();
87
88 assert_eq!("flf2a$ 6 5 16 15 11 0 24463", font.header_line.header_line);
89 assert_eq!("flf2a", font.header_line.signature);
90 assert_eq!('$', font.header_line.hardblank);
91 assert_eq!(6, font.header_line.height);
92 assert_eq!(5, font.header_line.baseline);
93 assert_eq!(16, font.header_line.max_length);
94 assert_eq!(15, font.header_line.old_layout);
95 assert_eq!(11, font.header_line.comment_lines);
96 assert_eq!(Some(0), font.header_line.print_direction);
97 assert_eq!(Some(24463), font.header_line.full_layout);
98 assert_eq!(None, font.header_line.codetag_count);
99
100 let one_font = font.fonts.get(&('F' as u32)).unwrap();
101 assert_eq!(70, one_font.code);
102 assert_eq!(8, one_font.width);
103 assert_eq!(6, one_font.height);
104 assert_eq!(6, one_font.characters.len());
105 assert_eq!(" _____ ", one_font.characters.first().unwrap());
106 }
107
108 #[test]
109 fn test_convert() {
110 let standard_font = FIGlet::standard().unwrap();
111 let figure = standard_font.convert("FIGlet").unwrap();
112
113 assert_eq!(6, figure.height);
114 assert_eq!(6, figure.characters.len());
115 assert_eq!(" _____ ", figure.characters[0].characters.first().unwrap());
116 }
117
118 #[test]
119 fn test_convert_empty_string() {
120 let font = FIGlet::standard().unwrap();
121 assert!(font.convert("").is_none());
122 }
123
124 #[test]
125 fn test_convert_single_character() {
126 let font = FIGlet::standard().unwrap();
127 let figure = font.convert("A").unwrap();
128 assert_eq!(1, figure.characters.len());
129 assert_eq!(6, figure.height);
130 }
131
132 #[test]
133 fn test_convert_all_ascii_printable() {
134 let font = FIGlet::standard().unwrap();
135 let all_ascii: String = (32..=126).map(|c| char::from_u32(c).unwrap()).collect();
136 let figure = font.convert(&all_ascii).unwrap();
137 assert_eq!(95, figure.characters.len());
138 }
139
140 #[test]
141 fn test_convert_with_unknown_characters() {
142 let font = FIGlet::standard().unwrap();
143 let figure = font.convert("Hello世界").unwrap();
144 assert_eq!(5, figure.characters.len());
145 }
146
147 #[test]
148 fn test_figure_as_str() {
149 let font = FIGlet::standard().unwrap();
150 let figure = font.convert("Hi").unwrap();
151 let s = figure.as_str();
152 assert!(!s.is_empty());
153 assert_eq!(figure.height as usize, s.lines().count());
154 }
155
156 #[test]
157 fn test_figure_display() {
158 let font = FIGlet::standard().unwrap();
159 let figure = font.convert("AB").unwrap();
160 let display_output = format!("{}", figure);
161 let debug_output = format!("{:?}", figure);
162
163 assert!(!display_output.is_empty());
164 assert!(display_output.contains('\n'));
165 assert!(!debug_output.is_empty());
166 }
167
168 #[test]
169 fn test_standard_golden_samples() {
170 let font = FIGlet::standard().unwrap();
171 assert_golden_fixture_figlet(&font, "Test", "tests/fixtures/figlet_standard_test.txt");
172 assert_golden_fixture_figlet(&font, "FIGlet", "tests/fixtures/figlet_standard_figlet.txt");
173 assert_golden_fixture_figlet(
174 &font,
175 "-4.5",
176 "tests/fixtures/figlet_standard_negative_float.txt",
177 );
178 assert_golden_fixture_figlet(
179 &font,
180 "Hello Rust",
181 "tests/fixtures/figlet_standard_hello_rust.txt",
182 );
183 }
184
185 #[test]
186 fn test_small_golden_samples() {
187 let font = FIGlet::small().unwrap();
188 assert_golden_fixture_figlet(&font, "Test", "tests/fixtures/figlet_small_test.txt");
189 assert_golden_fixture_figlet(&font, "FIGlet", "tests/fixtures/figlet_small_figlet.txt");
190 assert_golden_fixture_figlet(
191 &font,
192 "-4.5",
193 "tests/fixtures/figlet_small_negative_float.txt",
194 );
195 assert_golden_fixture_figlet(
196 &font,
197 "Hello Rust",
198 "tests/fixtures/figlet_small_hello_rust.txt",
199 );
200 }
201
202 #[test]
203 fn test_effective_layout_prefers_full_layout() {
204 let header = HeaderLine::try_from("flf2a$ 6 5 20 15 3 0 143 229").unwrap();
205 assert_eq!(143, header.effective_layout());
206 }
207
208 #[test]
209 fn test_effective_layout_uses_old_layout_compatibility() {
210 let kerning = HeaderLine::try_from("flf2a$ 6 5 20 0 3").unwrap();
211 let full_width = HeaderLine::try_from("flf2a$ 6 5 20 -1 3").unwrap();
212 let smushing = HeaderLine::try_from("flf2a$ 6 5 20 15 3").unwrap();
213
214 assert_eq!(SM_KERN, kerning.effective_layout());
215 assert_eq!(0, full_width.effective_layout());
216 assert_eq!(143, smushing.effective_layout());
217 }
218
219 #[test]
220 fn test_smush_rule_equal() {
221 let font = full_smush_font();
222 let renderer = crate::shared::render(&font.header_line, &font.fonts, "||").unwrap();
223 assert!(renderer.is_not_empty());
224 }
225
226 #[test]
227 fn test_smush_rule_lowline_and_hierarchy() {
228 let font = full_smush_font();
229 let figure = font.convert("_/|>").unwrap();
230 assert!(figure.is_not_empty());
231 }
232
233 #[test]
234 fn test_figure_is_not_empty() {
235 let font = FIGlet::standard().unwrap();
236 assert!(font.convert("Test").unwrap().is_not_empty());
237 }
238
239 #[test]
240 fn test_figure_with_only_unknown_chars() {
241 let font = FIGlet::standard().unwrap();
242 assert!(font.convert("\u{4E2D}\u{6587}").is_none());
243 }
244
245 #[test]
246 fn test_figfont_clone() {
247 let font1 = FIGlet::standard().unwrap();
248 let font2 = font1.clone();
249
250 assert!(font1.convert("Test").is_some());
251 assert!(font2.convert("Test").is_some());
252 }
253
254 #[test]
255 fn test_standard_font_loading() {
256 let font1 = FIGlet::standard().unwrap();
257 let font2 = FIGlet::from_file("resources/standard.flf").unwrap();
258
259 assert_eq!(font1.header_line.header_line, font2.header_line.header_line);
260 assert_eq!(font1.comments, font2.comments);
261 }
262
263 #[test]
264 fn test_small_font_loading() {
265 let font1 = FIGlet::small().unwrap();
266 let font2 = FIGlet::from_file("resources/small.flf").unwrap();
267
268 assert_eq!(font1.header_line.header_line, font2.header_line.header_line);
269 assert_eq!(font1.comments, font2.comments);
270 }
271
272 #[test]
273 fn test_big_golden_samples() {
274 let font = FIGlet::big().unwrap();
275 assert_golden_fixture_figlet(&font, "Test", "tests/fixtures/figlet_big_test.txt");
276 assert_golden_fixture_figlet(&font, "FIGlet", "tests/fixtures/figlet_big_figlet.txt");
277 assert_golden_fixture_figlet(
278 &font,
279 "-4.5",
280 "tests/fixtures/figlet_big_negative_float.txt",
281 );
282 assert_golden_fixture_figlet(
283 &font,
284 "Hello Rust",
285 "tests/fixtures/figlet_big_hello_rust.txt",
286 );
287 }
288
289 #[test]
290 fn test_slant_golden_samples() {
291 let font = FIGlet::slant().unwrap();
292 assert_golden_fixture_figlet(&font, "Test", "tests/fixtures/figlet_slant_test.txt");
293 assert_golden_fixture_figlet(&font, "FIGlet", "tests/fixtures/figlet_slant_figlet.txt");
294 assert_golden_fixture_figlet(
295 &font,
296 "-4.5",
297 "tests/fixtures/figlet_slant_negative_float.txt",
298 );
299 assert_golden_fixture_figlet(
300 &font,
301 "Hello Rust",
302 "tests/fixtures/figlet_slant_hello_rust.txt",
303 );
304 }
305
306 #[test]
307 fn test_big_font_loading() {
308 let font1 = FIGlet::big().unwrap();
309 let font2 = FIGlet::from_file("resources/big.flf").unwrap();
310
311 assert_eq!(font1.header_line.header_line, font2.header_line.header_line);
312 assert_eq!(font1.comments, font2.comments);
313 }
314
315 #[test]
316 fn test_slant_font_loading() {
317 let font1 = FIGlet::slant().unwrap();
318 let font2 = FIGlet::from_file("resources/slant.flf").unwrap();
319
320 assert_eq!(font1.header_line.header_line, font2.header_line.header_line);
321 assert_eq!(font1.comments, font2.comments);
322 }
323
324 #[test]
325 fn test_figure_character_width_and_height() {
326 let font = FIGlet::standard().unwrap();
327 let figure = font.convert("ABC").unwrap();
328
329 for char in &figure.characters {
330 assert_eq!(figure.height, char.height);
331 assert!(char.width > 0);
332 }
333 }
334
335 #[test]
336 fn test_latin_characters() {
337 let font = FIGlet::standard().unwrap();
338 let figure = font.convert("\u{00C4}\u{00D6}\u{00DC}").unwrap();
339 assert_eq!(3, figure.characters.len());
340 }
341
342 #[test]
343 fn test_from_content_invalid() {
344 assert!(FIGlet::from_content("").is_err());
345 assert!(FIGlet::from_content("invalid").is_err());
346 }
347
348 #[test]
349 fn test_headerline_invalid() {
350 assert!(HeaderLine::try_from("flf2a$ 6").is_err());
351 }
352
353 #[test]
354 fn test_toilet_header_supports_tlf_signature() {
355 let header = HeaderLine::try_from("tlf2a$ 4 3 8 0 16 0 64 0").unwrap();
356 assert_eq!("tlf2a", header.signature);
357 assert_eq!(4, header.height);
358 }
359
360 #[test]
361 fn test_toilet_from_content() {
362 let content = fixture("resources/smblock.tlf");
363 let font = Toilet::from_content(&content).unwrap();
364 assert_eq!("tlf2a", font.header_line.signature);
365 assert!(font.convert("Test").is_some());
366 }
367
368 #[test]
369 fn test_toilet_builtin_text_font_loading() {
370 let font1 = Toilet::smblock().unwrap();
371 let font2 = Toilet::from_file("resources/smblock.tlf").unwrap();
372 assert_eq!(font1.header_line.header_line, font2.header_line.header_line);
373 assert_eq!(font1.comments, font2.comments);
374 }
375
376 #[test]
377 fn test_toilet_builtin_zipped_font_loading() {
378 let font1 = Toilet::mono12().unwrap();
379 let font2 = Toilet::from_file("resources/mono12.tlf").unwrap();
380 assert_eq!(font1.header_line.header_line, font2.header_line.header_line);
381 assert_eq!(font1.comments, font2.comments);
382 }
383
384 #[test]
385 fn test_toilet_smblock_golden_samples() {
386 let font = Toilet::smblock().unwrap();
387 assert_golden_fixture_toilet(&font, "Test", "tests/fixtures/toilet_smblock_test.txt");
388 assert_golden_fixture_toilet(&font, "FIGlet", "tests/fixtures/toilet_smblock_figlet.txt");
389 assert_golden_fixture_toilet(
390 &font,
391 "-4.5",
392 "tests/fixtures/toilet_smblock_negative_float.txt",
393 );
394 }
395
396 #[test]
397 fn test_toilet_future_golden_samples() {
398 let font = Toilet::future().unwrap();
399 assert_golden_fixture_toilet(&font, "Test", "tests/fixtures/toilet_future_test.txt");
400 assert_golden_fixture_toilet(
401 &font,
402 "Hello Rust",
403 "tests/fixtures/toilet_future_hello_rust.txt",
404 );
405 }
406
407 #[test]
408 fn test_toilet_wideterm_golden_samples() {
409 let font = Toilet::wideterm().unwrap();
410 assert_golden_fixture_toilet(&font, "FIGlet", "tests/fixtures/toilet_wideterm_figlet.txt");
411 }
412
413 #[test]
414 fn test_toilet_mono12_golden_samples() {
415 let font = Toilet::mono12().unwrap();
416 assert_golden_fixture_toilet(&font, "Test", "tests/fixtures/toilet_mono12_test.txt");
417 }
418
419 #[test]
420 fn test_toilet_mono9_golden_samples() {
421 let font = Toilet::mono9().unwrap();
422 assert_golden_fixture_toilet(
423 &font,
424 "Hello Rust",
425 "tests/fixtures/toilet_mono9_hello_rust.txt",
426 );
427 }
428
429 #[test]
430 fn test_toilet_external_zipped_font_matches_builtin() {
431 let external = Toilet::from_file("resources/mono9.tlf").unwrap();
432 let builtin = Toilet::mono9().unwrap();
433 assert_eq!(
434 builtin.convert("Test").unwrap().as_str(),
435 external.convert("Test").unwrap().as_str()
436 );
437 }
438
439 #[test]
440 fn test_toilet_unknown_chars_are_skipped() {
441 let font = Toilet::smblock().unwrap();
442 let figure = font.convert("Toilet世界").unwrap();
443 assert_eq!(6, figure.characters.len());
444 }
445
446 #[test]
447 fn test_toilet_from_content_invalid() {
448 assert!(Toilet::from_content("").is_err());
449 }
450
451 #[test]
452 fn test_from_font_data_roundtrip() {
453 let font = FIGlet::standard().unwrap();
454 let data = FontData {
455 header_line: font.header_line.clone(),
456 comments: font.comments.clone(),
457 fonts: font.fonts.clone(),
458 };
459 let cloned = FIGlet::from(data);
460 assert_eq!(
461 font.convert("Test").unwrap().as_str(),
462 cloned.convert("Test").unwrap().as_str()
463 );
464 }
465}