Fork of daniellemaywood.uk/gleam — Wasm codegen work
8.3 kB
251 lines
1use super::*;
2use crate::{
3 build::SourceFingerprint,
4 io::{FileSystemWriter, memory::InMemoryFileSystem},
5 line_numbers::LineNumbers,
6};
7use std::time::Duration;
8
9#[test]
10fn no_cache_present() {
11 let name = "package".into();
12 let src = Utf8Path::new("/src");
13 let artefact = Utf8Path::new("/artefact");
14 let fs = InMemoryFileSystem::new();
15 let warnings = WarningEmitter::null();
16 let incomplete_modules = HashSet::new();
17 let loader = make_loader(&warnings, &name, &fs, src, artefact, &incomplete_modules);
18
19 fs.write(&Utf8Path::new("/src/main.gleam"), "const x = 1")
20 .unwrap();
21
22 let result = loader
23 .load(Utf8Path::new("/src/main.gleam").to_path_buf())
24 .unwrap();
25
26 assert!(result.is_new());
27}
28
29#[test]
30fn cache_present_and_fresh() {
31 let name = "package".into();
32 let src = Utf8Path::new("/src");
33 let artefact = Utf8Path::new("/artefact");
34 let fs = InMemoryFileSystem::new();
35 let warnings = WarningEmitter::null();
36 let incomplete_modules = HashSet::new();
37 let loader = make_loader(&warnings, &name, &fs, src, artefact, &incomplete_modules);
38
39 // The mtime of the source is older than that of the cache
40 write_src(&fs, TEST_SOURCE_1, "/src/main.gleam", 0);
41 write_cache(&fs, TEST_SOURCE_1, "/artefact/main.cache_meta", 1, false);
42
43 let result = loader
44 .load(Utf8Path::new("/src/main.gleam").to_path_buf())
45 .unwrap();
46
47 assert!(result.is_cached());
48}
49
50#[test]
51fn cache_present_and_stale() {
52 let name = "package".into();
53 let src = Utf8Path::new("/src");
54 let artefact = Utf8Path::new("/artefact");
55 let fs = InMemoryFileSystem::new();
56 let warnings = WarningEmitter::null();
57 let incomplete_modules = HashSet::new();
58 let loader = make_loader(&warnings, &name, &fs, src, artefact, &incomplete_modules);
59
60 // The mtime of the source is newer than that of the cache
61 write_src(&fs, TEST_SOURCE_2, "/src/main.gleam", 2);
62 write_cache(&fs, TEST_SOURCE_1, "/artefact/main.cache_meta", 1, false);
63
64 let result = loader
65 .load(Utf8Path::new("/src/main.gleam").to_path_buf())
66 .unwrap();
67
68 assert!(result.is_new());
69}
70
71#[test]
72fn cache_present_and_stale_but_source_is_the_same() {
73 let name = "package".into();
74 let src = Utf8Path::new("/src");
75 let artefact = Utf8Path::new("/artefact");
76 let fs = InMemoryFileSystem::new();
77 let warnings = WarningEmitter::null();
78 let incomplete_modules = HashSet::new();
79 let loader = make_loader(&warnings, &name, &fs, src, artefact, &incomplete_modules);
80
81 // The mtime of the source is newer than that of the cache
82 write_src(&fs, TEST_SOURCE_1, "/src/main.gleam", 2);
83 write_cache(&fs, TEST_SOURCE_1, "/artefact/main.cache_meta", 1, false);
84
85 let result = loader
86 .load(Utf8Path::new("/src/main.gleam").to_path_buf())
87 .unwrap();
88
89 assert!(result.is_cached());
90}
91
92#[test]
93fn cache_present_and_stale_source_is_the_same_lsp_mode() {
94 let name = "package".into();
95 let src = Utf8Path::new("/src");
96 let artefact = Utf8Path::new("/artefact");
97 let fs = InMemoryFileSystem::new();
98 let warnings = WarningEmitter::null();
99 let incomplete_modules = HashSet::new();
100 let mut loader = make_loader(&warnings, &name, &fs, src, artefact, &incomplete_modules);
101 loader.mode = Mode::Lsp;
102
103 // The mtime of the source is newer than that of the cache
104 write_src(&fs, TEST_SOURCE_1, "/src/main.gleam", 2);
105 write_cache(&fs, TEST_SOURCE_1, "/artefact/main.cache_meta", 1, false);
106
107 let result = loader
108 .load(Utf8Path::new("/src/main.gleam").to_path_buf())
109 .unwrap();
110
111 assert!(result.is_cached());
112}
113
114#[test]
115fn cache_present_and_stale_source_is_the_same_lsp_mode_and_invalidated() {
116 let name = "package".into();
117 let src = Utf8Path::new("/src");
118 let artefact = Utf8Path::new("/artefact");
119 let fs = InMemoryFileSystem::new();
120 let warnings = WarningEmitter::null();
121 let mut incomplete_modules = HashSet::new();
122 let _ = incomplete_modules.insert("main".into());
123 let mut loader = make_loader(&warnings, &name, &fs, src, artefact, &incomplete_modules);
124 loader.mode = Mode::Lsp;
125
126 // The mtime of the source is newer than that of the cache
127 write_src(&fs, TEST_SOURCE_1, "/src/main.gleam", 2);
128 write_cache(&fs, TEST_SOURCE_1, "/artefact/main.cache_meta", 1, false);
129
130 let result = loader
131 .load(Utf8Path::new("/src/main.gleam").to_path_buf())
132 .unwrap();
133
134 assert!(result.is_new());
135}
136
137#[test]
138fn cache_present_without_codegen_when_required() {
139 let name = "package".into();
140 let src = Utf8Path::new("/src");
141 let artefact = Utf8Path::new("/artefact");
142 let fs = InMemoryFileSystem::new();
143 let warnings = WarningEmitter::null();
144 let incomplete_modules = HashSet::new();
145 let mut loader = make_loader(&warnings, &name, &fs, src, artefact, &incomplete_modules);
146 loader.codegen = CodegenRequired::Yes;
147
148 // The mtime of the cache is newer than that of the source
149 write_src(&fs, TEST_SOURCE_1, "/src/main.gleam", 0);
150 write_cache(&fs, TEST_SOURCE_1, "/artefact/main.cache_meta", 1, false);
151
152 let result = loader
153 .load(Utf8Path::new("/src/main.gleam").to_path_buf())
154 .unwrap();
155
156 assert!(result.is_new());
157}
158
159#[test]
160fn cache_present_with_codegen_when_required() {
161 let name = "package".into();
162 let src = Utf8Path::new("/src");
163 let artefact = Utf8Path::new("/artefact");
164 let fs = InMemoryFileSystem::new();
165 let warnings = WarningEmitter::null();
166 let incomplete_modules = HashSet::new();
167 let mut loader = make_loader(&warnings, &name, &fs, src, artefact, &incomplete_modules);
168 loader.codegen = CodegenRequired::Yes;
169
170 // The mtime of the cache is newer than that of the source
171 write_src(&fs, TEST_SOURCE_1, "/src/main.gleam", 0);
172 write_cache(&fs, TEST_SOURCE_1, "/artefact/main.cache_meta", 1, true);
173
174 let result = loader
175 .load(Utf8Path::new("/src/main.gleam").to_path_buf())
176 .unwrap();
177
178 assert!(result.is_cached());
179}
180
181#[test]
182fn cache_present_without_codegen_when_not_required() {
183 let name = "package".into();
184 let src = Utf8Path::new("/src");
185 let artefact = Utf8Path::new("/artefact");
186 let fs = InMemoryFileSystem::new();
187 let warnings = WarningEmitter::null();
188 let incomplete_modules = HashSet::new();
189 let mut loader = make_loader(&warnings, &name, &fs, src, artefact, &incomplete_modules);
190 loader.codegen = CodegenRequired::No;
191
192 // The mtime of the cache is newer than that of the source
193 write_src(&fs, TEST_SOURCE_1, "/src/main.gleam", 0);
194 write_cache(&fs, TEST_SOURCE_1, "/artefact/main.cache_meta", 1, false);
195
196 let result = loader
197 .load(Utf8Path::new("/src/main.gleam").to_path_buf())
198 .unwrap();
199
200 assert!(result.is_cached());
201}
202
203const TEST_SOURCE_1: &'static str = "const x = 1";
204const TEST_SOURCE_2: &'static str = "const x = 2";
205
206fn write_cache(
207 fs: &InMemoryFileSystem,
208 source: &str,
209 path: &str,
210 seconds: u64,
211 codegen_performed: bool,
212) {
213 let line_numbers = LineNumbers::new(source);
214 let cache_metadata = CacheMetadata {
215 mtime: SystemTime::UNIX_EPOCH + Duration::from_secs(seconds),
216 codegen_performed,
217 dependencies: vec![],
218 fingerprint: SourceFingerprint::new(source),
219 line_numbers,
220 };
221 let path = Utf8Path::new(path);
222 fs.write_bytes(&path, &cache_metadata.to_binary()).unwrap();
223}
224
225fn write_src(fs: &InMemoryFileSystem, source: &str, path: &str, seconds: u64) {
226 let path = Utf8Path::new(path);
227 fs.write(&path, source).unwrap();
228 fs.set_modification_time(&path, SystemTime::UNIX_EPOCH + Duration::from_secs(seconds));
229}
230
231fn make_loader<'a>(
232 warnings: &'a WarningEmitter,
233 package_name: &'a EcoString,
234 fs: &InMemoryFileSystem,
235 src: &'a Utf8Path,
236 artefact: &'a Utf8Path,
237 incomplete_modules: &'a HashSet<EcoString>,
238) -> ModuleLoader<'a, InMemoryFileSystem> {
239 ModuleLoader {
240 warnings,
241 io: fs.clone(),
242 mode: Mode::Dev,
243 target: Target::Erlang,
244 codegen: CodegenRequired::No,
245 package_name,
246 source_directory: &src,
247 artefact_directory: &artefact,
248 origin: Origin::Src,
249 incomplete_modules,
250 }
251}