nandi/rustnimpublic Fork 0
ae9f986fc43d0fc9ab029946e2c7a25cdc72b4ed
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 · 96 lines · 3.2 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");
37 let a = d.join("a.rs");
38 let b = d.join("b.rs");
39 fs::write(&a, "pub fn double(x: i32) -> i32 { x * 2 }\n").unwrap();
40 fs::write(
41 &b,
42 "fn main() { println!(\"{}\", double(21)); }\n",
43 )
44 .unwrap();
45
46 // `double` is defined in a.rs and called from b.rs: it resolves only
47 // because both were passed in.
48 let (ok, out, err) = run(&d, &[a.to_str().unwrap(), b.to_str().unwrap()]);
49 assert!(ok, "multi-file transpile failed: {err}");
50 assert!(out.contains("proc double"), "missing `double`:\n{out}");
51 assert!(out.contains("proc main"), "missing `main`:\n{out}");
52
53 // b.rs alone must fail rather than emit a call to something undefined.
54 let (ok, _, err) = run(&d, &[b.to_str().unwrap()]);
55 assert!(!ok, "b.rs alone should not transpile");
56 assert!(err.contains("unknown function `double`"), "unexpected: {err}");
57}
58
59#[test]
60fn cfg_is_evaluated_against_the_feature_set() {
61 let d = work("cfg");
62 let f = d.join("c.rs");
63 fs::write(
64 &f,
65 "#[cfg(feature = \"extra\")]\n\
66 fn extra() -> i32 { 1 }\n\
67 #[cfg(not(feature = \"extra\"))]\n\
68 fn plain() -> i32 { 2 }\n\
69 fn main() {}\n",
70 )
71 .unwrap();
72
73 let (ok, out, err) = run(&d, &[f.to_str().unwrap()]);
74 assert!(ok, "{err}");
75 assert!(!out.contains("proc extra"), "gated-off item was emitted:\n{out}");
76 assert!(out.contains("proc plain"), "gated-on item missing:\n{out}");
77
78 let (ok, out, err) = run(&d, &[f.to_str().unwrap(), "--cfg", "feature=extra"]);
79 assert!(ok, "{err}");
80 assert!(out.contains("proc extra"), "feature item missing:\n{out}");
81 assert!(!out.contains("proc plain"), "`not(feature)` item was emitted:\n{out}");
82}
83
84#[test]
85fn an_unevaluable_cfg_predicate_is_reported_not_assumed() {
86 let d = work("cfg-unknown");
87 let f = d.join("d.rs");
88 fs::write(
89 &f,
90 "#[cfg(target_os = \"linux\")]\nfn only_linux() -> i32 { 1 }\nfn main() {}\n",
91 )
92 .unwrap();
93 let (ok, _, err) = run(&d, &[f.to_str().unwrap()]);
94 assert!(!ok, "an unevaluable cfg must not be silently resolved");
95 assert!(err.contains("not a predicate rustnim can evaluate"), "unexpected: {err}");
96}