nandi/rustnimpublic Fork 0
ff34e1b3229df6e21b0c5d77053bb9b7364db5cd
Commits
Clone
git clone https://git.rickub.com/nandi/rustnim.git
git clone ssh://git@rickub.com/nandi/rustnim.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

multifile.rs · 149 lines · 5.1 KBRust Blame HistoryRaw
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 8h ago1//! Multi-file input and `#[cfg]` evaluation.
2//!
3//! The differential runner drives one `.rs` per case, so the multi-file path
4//! and the feature-gating that goes with it are checked here instead. A Rust
5//! crate splits across files with `mod`; Nim has no equivalent inside a single
6//! output file, so the items are flattened in argument order.
7
8use std::fs;
9use std::path::{Path, PathBuf};
10use std::process::Command;
11
12const RUSTNIM: &str = env!("CARGO_BIN_EXE_rustnim");
13
14fn work(name: &str) -> PathBuf {
15 let d = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/.work").join(name);
16 let _ = fs::remove_dir_all(&d);
17 fs::create_dir_all(&d).unwrap();
18 d
19}
20
21fn run(dir: &Path, args: &[&str]) -> (bool, String, String) {
22 let out = Command::new(RUSTNIM)
23 .args(args)
24 .env("TMPDIR", dir)
25 .output()
26 .expect("spawn rustnim");
27 (
28 out.status.success(),
29 String::from_utf8_lossy(&out.stdout).into_owned(),
30 String::from_utf8_lossy(&out.stderr).into_owned(),
31 )
32}
33
34#[test]
35fn files_are_flattened_into_one_module() {
36 let d = work("multifile");
Add closures and unsafe; base16ct's lower.rs and upper.rs go through 0a375d8 nandithebull 7h ago37 let root = d.join("root.rs");
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 8h ago38 let a = d.join("a.rs");
39 fs::write(&a, "pub fn double(x: i32) -> i32 { x * 2 }\n").unwrap();
40 fs::write(
Add closures and unsafe; base16ct's lower.rs and upper.rs go through 0a375d8 nandithebull 7h ago41 &root,
42 "mod a;\nuse crate::a::double;\nfn main() { println!(\"{}\", double(21)); }\n",
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 8h ago43 )
44 .unwrap();
45
Add closures and unsafe; base16ct's lower.rs and upper.rs go through 0a375d8 nandithebull 7h ago46 // The first input is the crate root; `a.rs` becomes module `a`, and its
47 // items are emitted with that prefix so two modules may define the same
48 // name.
49 let (ok, out, err) = run(&d, &[root.to_str().unwrap(), a.to_str().unwrap()]);
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 8h ago50 assert!(ok, "multi-file transpile failed: {err}");
Add closures and unsafe; base16ct's lower.rs and upper.rs go through 0a375d8 nandithebull 7h ago51 assert!(out.contains("proc a_double"), "missing `a_double`:\n{out}");
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 8h ago52 assert!(out.contains("proc main"), "missing `main`:\n{out}");
Add closures and unsafe; base16ct's lower.rs and upper.rs go through 0a375d8 nandithebull 7h ago53 assert!(out.contains("a_double(21"), "call not qualified:\n{out}");
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 8h ago54
Add closures and unsafe; base16ct's lower.rs and upper.rs go through 0a375d8 nandithebull 7h ago55 // The root alone must fail rather than emit a call to something undefined.
56 let (ok, _, err) = run(&d, &[root.to_str().unwrap()]);
57 assert!(!ok, "the root alone should not transpile");
58 assert!(err.contains("mod a;"), "unexpected: {err}");
59}
60
61#[test]
62fn two_modules_may_define_the_same_name() {
63 let d = work("modcollide");
64 let root = d.join("root.rs");
65 let x = d.join("x.rs");
66 let y = d.join("y.rs");
67 fs::write(&x, "pub fn go() -> i32 { 1 }\n").unwrap();
68 fs::write(&y, "pub fn go() -> i32 { 2 }\n").unwrap();
69 fs::write(
70 &root,
71 "mod x;\nmod y;\nfn main() { println!(\"{} {}\", x::go(), y::go()); }\n",
72 )
73 .unwrap();
74
75 let (ok, out, err) = run(
76 &d,
77 &[root.to_str().unwrap(), x.to_str().unwrap(), y.to_str().unwrap()],
78 );
79 assert!(ok, "{err}");
80 assert!(out.contains("proc x_go") && out.contains("proc y_go"), "{out}");
81 assert!(out.contains("x_go()") && out.contains("y_go()"), "{out}");
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 8h ago82}
83
84#[test]
85fn cfg_is_evaluated_against_the_feature_set() {
86 let d = work("cfg");
87 let f = d.join("c.rs");
88 fs::write(
89 &f,
90 "#[cfg(feature = \"extra\")]\n\
91 fn extra() -> i32 { 1 }\n\
92 #[cfg(not(feature = \"extra\"))]\n\
93 fn plain() -> i32 { 2 }\n\
94 fn main() {}\n",
95 )
96 .unwrap();
97
98 let (ok, out, err) = run(&d, &[f.to_str().unwrap()]);
99 assert!(ok, "{err}");
100 assert!(!out.contains("proc extra"), "gated-off item was emitted:\n{out}");
101 assert!(out.contains("proc plain"), "gated-on item missing:\n{out}");
102
103 let (ok, out, err) = run(&d, &[f.to_str().unwrap(), "--cfg", "feature=extra"]);
104 assert!(ok, "{err}");
105 assert!(out.contains("proc extra"), "feature item missing:\n{out}");
106 assert!(!out.contains("proc plain"), "`not(feature)` item was emitted:\n{out}");
107}
108
109#[test]
110fn an_unevaluable_cfg_predicate_is_reported_not_assumed() {
111 let d = work("cfg-unknown");
112 let f = d.join("d.rs");
113 fs::write(
114 &f,
Evaluate host cfg predicates, and measure what that actually buys 0e6c394 nandithebull 6h ago115 // A build-script `cfg`: nothing about the host determines it, so
116 // there is no value we could know.
117 "#[cfg(crossbeam_loom)]\nfn under_loom() -> i32 { 1 }\nfn main() {}\n",
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 8h ago118 )
119 .unwrap();
120 let (ok, _, err) = run(&d, &[f.to_str().unwrap()]);
121 assert!(!ok, "an unevaluable cfg must not be silently resolved");
122 assert!(err.contains("not a predicate rustnim can evaluate"), "unexpected: {err}");
123}
Evaluate host cfg predicates, and measure what that actually buys 0e6c394 nandithebull 6h ago124
125#[test]
126fn host_facts_are_evaluated() {
127 // These are determined by the machine the generated Nim is compiled for,
128 // so they are known rather than chosen.
129 let d = work("cfg-host");
130 let f = d.join("h.rs");
131 fs::write(
132 &f,
133 "#[cfg(unix)]\nfn on_unix() -> i32 { 1 }\n\
134 #[cfg(windows)]\nfn on_windows() -> i32 { 2 }\n\
135 #[cfg(doctest)]\nfn in_doctest() -> i32 { 3 }\n\
136 fn main() {}\n",
137 )
138 .unwrap();
139 let (ok, out, err) = run(&d, &[f.to_str().unwrap()]);
140 assert!(ok, "{err}");
141 assert!(!out.contains("in_doctest"), "doctest item was emitted:\n{out}");
142 if cfg!(unix) {
143 assert!(out.contains("proc on_unix"), "{out}");
144 assert!(!out.contains("on_windows"), "{out}");
145 } else {
146 assert!(out.contains("proc on_windows"), "{out}");
147 assert!(!out.contains("on_unix"), "{out}");
148 }
149}