Fork of daniellemaywood.uk/gleam — Wasm codegen work
5.3 kB
192 lines
1use std::{env, io::Read, process::Stdio};
2
3use camino::{Utf8Path, Utf8PathBuf};
4use gleam_core::{
5 build::{Runtime, Target},
6 io::Command,
7 paths::ProjectPaths,
8};
9
10use gleam_cli::{
11 fs,
12 run::{self, Which},
13};
14
15fn run_and_produce_pretty_snapshot(
16 target: Option<Target>,
17 runtime: Option<Runtime>,
18 project_directory: Utf8PathBuf,
19) -> String {
20 let project_root = fs::get_project_root(project_directory).expect("project root");
21 let paths = ProjectPaths::new(project_root);
22
23 let output = run_and_capture_output(&paths, "main", target, runtime)
24 // Since the echo output's contains a path we will replace the `\` with a `/`
25 // so that the snapshot doesn't fail on Windows in CI.
26 .replace("src\\", "src/");
27
28 let main_module_content =
29 fs::read(paths.src_directory().join("main.gleam")).expect("read main module");
30
31 format!(
32 "--- main.gleam ----------------------
33{main_module_content}
34
35--- gleam run output ----------------
36{output}
37"
38 )
39}
40
41fn run_and_capture_output(
42 paths: &ProjectPaths,
43 main_module: &str,
44 target: Option<Target>,
45 runtime: Option<Runtime>,
46) -> String {
47 fs::delete_directory(&paths.build_directory()).expect("delete build directory content");
48
49 let Command {
50 program,
51 args,
52 env,
53 cwd: _,
54 stdio: _,
55 } = run::setup(
56 paths,
57 vec![],
58 target,
59 runtime,
60 Some(main_module.into()),
61 Which::Src,
62 true,
63 )
64 .expect("run setup");
65
66 let mut process = std::process::Command::new(&program)
67 .args(args)
68 .stdin(Stdio::null())
69 .stdout(Stdio::null())
70 .stderr(Stdio::piped())
71 .envs(env.iter().map(|pair| (&pair.0, &pair.1)))
72 .current_dir(paths.root())
73 .spawn()
74 .unwrap_or_else(|e| panic!("Failed to spawn process '{}': {}", &program, &e));
75
76 let mut stderr = process.stderr.take().expect("take stderr");
77 let mut output = String::new();
78 let _ = stderr.read_to_string(&mut output).expect("read stderr");
79 let _ = process.wait().expect("run with no errors");
80 output
81}
82
83macro_rules! assert_echo {
84 ($project_name: expr) => {
85 let snapshot_name = snapshot_name(None, None, $project_name);
86 insta::allow_duplicates! {
87 assert_echo!(&snapshot_name, Some(Target::Erlang), None, $project_name);
88 assert_echo!(&snapshot_name, Some(Target::JavaScript), Some(Runtime::Bun), $project_name);
89 assert_echo!(&snapshot_name, Some(Target::JavaScript), Some(Runtime::Deno), $project_name);
90 assert_echo!(&snapshot_name, Some(Target::JavaScript), Some(Runtime::NodeJs), $project_name);
91 }
92 };
93
94 ($target: expr, $project_name: expr) => {
95 let snapshot_name = snapshot_name(Some($target), None, $project_name);
96 match $target {
97 Target::JavaScript => insta::allow_duplicates! {
98 assert_echo!(&snapshot_name, Some($target), Some(Runtime::Bun), $project_name);
99 assert_echo!(&snapshot_name, Some($target), Some(Runtime::Deno), $project_name);
100 assert_echo!(&snapshot_name, Some($target), Some(Runtime::NodeJs), $project_name);
101 },
102 Target::Erlang => {
103 assert_echo!(&snapshot_name, Some($target), None, $project_name);
104 }
105 }
106 };
107
108 ($snapshot_name: expr, $target: expr, $runtime: expr, $project_name: expr) => {
109 let path = fs::canonicalise(&Utf8Path::new("../test-output/cases").join($project_name))
110 .expect("canonicalise path");
111 let output = run_and_produce_pretty_snapshot($target, $runtime, path);
112 insta::assert_snapshot!($snapshot_name.to_string(), output);
113 };
114}
115
116fn snapshot_name(target: Option<Target>, runtime: Option<Runtime>, suffix: &str) -> String {
117 let prefix = match (target, runtime) {
118 (None, None) => "".into(),
119 (None, Some(runtime)) => format!("{runtime}-"),
120 (Some(target), None) => format!("{target}-"),
121 (Some(target), Some(runtime)) => format!("{target}-{runtime}-"),
122 };
123 format!("{prefix}{suffix}")
124}
125
126#[test]
127fn echo_bitarray() {
128 assert_echo!(Target::JavaScript, "echo_bitarray");
129 assert_echo!(Target::Erlang, "echo_bitarray");
130}
131
132#[test]
133fn echo_bool() {
134 assert_echo!("echo_bool");
135}
136
137#[test]
138fn echo_custom_type() {
139 assert_echo!(Target::Erlang, "echo_custom_type");
140 assert_echo!(Target::JavaScript, "echo_custom_type");
141}
142
143#[test]
144fn echo_dict() {
145 assert_echo!("echo_dict");
146}
147
148#[test]
149fn echo_float() {
150 assert_echo!(Target::Erlang, "echo_float");
151 assert_echo!(Target::JavaScript, "echo_float");
152}
153
154#[test]
155fn echo_function() {
156 assert_echo!("echo_function");
157}
158
159#[test]
160fn echo_importing_module_named_inspect() {
161 assert_echo!("echo_importing_module_named_inspect");
162}
163
164#[test]
165fn echo_int() {
166 assert_echo!("echo_int");
167}
168
169#[test]
170fn echo_list() {
171 assert_echo!("echo_list");
172}
173
174#[test]
175fn echo_nil() {
176 assert_echo!("echo_nil");
177}
178
179#[test]
180fn echo_string() {
181 assert_echo!("echo_string");
182}
183
184#[test]
185fn echo_tuple() {
186 assert_echo!("echo_tuple");
187}
188
189#[test]
190fn echo_non_record_atom_tag() {
191 assert_echo!(Target::Erlang, "echo_non_record_atom_tag");
192}