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
96
97
98
99
100
101
102
103
104
|
#[cfg(test)]
mod tests {
use std::fs::File;
use std::process::{Command, Output};
use tinyld::linker::{LinkWarning, Linker};
fn panic_warning_handler(warning: LinkWarning) {
eprintln!("warning: {warning}");
panic!("this should not generate a warning");
}
fn test_linker<'a>() -> Linker<'a> {
let mut linker = Linker::new();
linker.set_warning_handler(panic_warning_handler);
linker
}
fn file(s: &str) -> String {
format!("./tests/{s}")
}
fn add(linker: &mut Linker, src: &str, is_local: bool) {
let f = file(src);
let s = if is_local { &f } else { src };
linker.add_input(s).expect(&format!("failed to add {s}"));
}
fn link(linker: &Linker, out: &str, entry: &str) {
linker
.link_to_file(&file(out), entry)
.expect("failed to link");
}
fn run_with_stdin(name: &str, stdin: Option<&str>) -> Output {
let mut command = Command::new(&file(name));
if let Some(s) = stdin {
let file = File::open(&file(s)).expect("stdin file does not exist");
command.stdin(file);
}
let output = command.output().expect("failed to run output executable");
assert!(output.status.success());
assert!(output.stderr.is_empty());
output
}
fn run(name: &str) -> std::process::Output {
run_with_stdin(name, None)
}
#[test]
fn tiny_c() {
let mut linker = test_linker();
add(&mut linker, "tiny.c", true);
link(&linker, "test.out", "entry");
let output = run("tiny.out");
assert!(output.stdout.is_empty());
}
#[test]
fn basic_c() {
let mut linker = test_linker();
add(&mut linker, "basic.c", true);
add(&mut linker, "libc.so.6", false);
link(&linker, "basic.out", "entry");
let output = run("basic.out");
assert_eq!(output.stdout, b"137\n");
}
#[test]
fn dylib_c() {
let status = Command::new("gcc")
.args(&[
"-m32",
"-fPIC",
"-shared",
&file("dylib.c"),
"-o",
&file("dylib.so"),
])
.status()
.expect("failed to create dylib.so");
assert!(status.success());
let mut linker = test_linker();
add(&mut linker, "dylib-test.c", true);
add(&mut linker, "dylib.so", true);
add(&mut linker, "libc.so.6", false);
link(&linker, "dylib-test.out", "entry");
let output = run("dylib-test.out");
assert_eq!(output.stdout, b"7\n8\n");
}
#[test]
fn cpp() {
let mut linker = test_linker();
add(&mut linker, "cpp.cpp", true);
add(&mut linker, "libc.so.6", false);
add(&mut linker, "libstdc++.so.6", false);
link(&linker, "cpp.out", "main");
let output = run_with_stdin("cpp.out", Some("cpp-input.txt"));
assert_eq!(output.stdout, b"0\n7\n65\n212\n233\n");
}
}
|