Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

gleam / compiler-core / src / tests.rs
6.1 kB 199 lines
1use std::path::PathBuf; 2 3use itertools::Itertools; 4use serde::Deserialize; 5 6#[derive(Deserialize)] 7struct CargoDenyConfig { 8 advisories: CargoDenyAdvisoriesConfig, 9 licenses: CargoDenyLicensesConfig, 10} 11 12#[derive(Deserialize)] 13struct CargoDenyLicensesConfig { 14 allow: Vec<String>, 15} 16 17#[derive(Deserialize)] 18struct CargoDenyAdvisoriesConfig { 19 ignore: Vec<CargoDenyIgnoreConfig>, 20} 21 22#[derive(Deserialize)] 23struct CargoDenyIgnoreConfig { 24 id: String, 25 reason: String, 26} 27 28#[test] 29fn licence_files_exist_in_repo() { 30 // deny.toml specified which licences dependencies are permitted to have. 31 let dependency_licences = load_cargo_deny_config().licenses.allow; 32 33 // Each licence must exist in the licences directory. 34 let licences_directory = PathBuf::from("../licences"); 35 let licences_missing_licence_file = dependency_licences 36 .iter() 37 .filter(|licence| { 38 let path = licences_directory.join(format!("{licence}.txt")); 39 !std::fs::exists(path).unwrap() 40 }) 41 .collect_vec(); 42 43 assert!( 44 licences_missing_licence_file.is_empty(), 45 " 46All dependency licences must exist in the licences directory. 47These licences are missing their file: 48 49- {licences_missing_licence_file:?}" 50 ); 51} 52 53fn load_cargo_deny_config() -> CargoDenyConfig { 54 let toml = std::fs::read_to_string("../deny.toml").unwrap(); 55 let config = toml::from_str(&toml).unwrap(); 56 config 57} 58 59#[test] 60fn rust_advisories_ignore_deadlines() { 61 let today = time::OffsetDateTime::now_utc().date(); 62 let regex = regex::Regex::new(r"(?m)FIX-DEADLINE: (\d{4})-(\d{2})-(\d{2})").unwrap(); 63 64 for ignored in load_cargo_deny_config().advisories.ignore { 65 let id = ignored.id; 66 let reason = ignored.reason; 67 let Some(captures) = regex.captures(&reason) else { 68 panic!( 69 " 70deny.toml advisory missing deadline! 71Add a line to the `reason` property for {id} with this format: 72 73 FIX-DEADLINE: 2026-01-05 74 75{reason:?} 76" 77 ) 78 }; 79 80 let year = captures[1].parse::<i32>().expect("parse year"); 81 let month = captures[2].parse::<u8>().expect("parse month int"); 82 let month = month.try_into().expect("parse month"); 83 let day = captures[3].parse::<u8>().expect("parse day"); 84 let deadline = time::Date::from_calendar_date(year, month, day).expect("construct date"); 85 86 assert!( 87 today <= deadline, 88 " 89The deadline for fixing advisory {id} has passed. 90Fix it now, or bump the deadline in deny.toml. 91" 92 ) 93 } 94} 95 96#[test] 97fn all_files_have_copyright_notice() { 98 let paths = ignore::WalkBuilder::new("..") 99 .follow_links(false) 100 .git_global(true) 101 .git_ignore(true) 102 .hidden(true) 103 .parents(true) 104 .build() 105 .map(|entry| entry.expect("directory traversal succeeds")) 106 .filter(|entry| { 107 entry 108 .file_type() 109 .map(|type_| type_.is_file()) 110 .unwrap_or(false) 111 }) 112 .map(ignore::DirEntry::into_path) 113 .filter_map(|path| { 114 let file_name = path.file_name().and_then(|s| s.to_str())?; 115 let extension = path.extension()?; 116 117 match extension.to_str().expect("file extension") { 118 // Test files. 119 "new" => return None, 120 "snap" => return None, 121 "txt" if path.starts_with("../test/") || path.starts_with("../licences/") => { 122 return None; 123 } 124 125 // GitHub templates 126 "md" if path.starts_with("../.github/") => return None, 127 128 // Static assets 129 "gz" => return None, 130 "tar" => return None, 131 "exs" => return None, 132 "dockerfile" => return None, 133 "woff2" => return None, 134 "png" => return None, 135 "css" if file_name.ends_with(".min.css") => return None, 136 "js" if file_name.ends_with(".min.js") => return None, 137 138 // Template files to be added to user projects 139 "ps1" if file_name == "erlang-shipment-entrypoint.ps1" => return None, 140 "sh" if file_name == "erlang-shipment-entrypoint.sh" => return None, 141 "mjs" if file_name == "prelude.mjs" || file_name == "echo.mjs" => return None, 142 "erl" if file_name == "gleam@@main.erl" || file_name == "echo.erl" => return None, 143 "mts" if file_name == "prelude.d.mts" => return None, 144 145 // Generated files 146 "toml" if file_name == "manifest.toml" => return None, 147 148 // Source files 149 "config" if file_name == "rebar.config" => (), 150 "css" => (), 151 "proto" => (), 152 "ts" => (), 153 "erl" => (), 154 "ex" => (), 155 "gleam" => (), 156 "hrl" => (), 157 "js" => (), 158 "md" => (), 159 "mjs" => (), 160 "mts" => (), 161 "ps1" => (), 162 "rs" => (), 163 "sh" => (), 164 "toml" => (), 165 166 // HTML templates 167 "html" if path.starts_with("../compiler-core/templates/") => (), 168 169 _ => panic!("Unexpected file extension for {path:?}"), 170 }; 171 172 let text = std::fs::read_to_string(&path).expect("read file"); 173 if text.contains("SPDX-License-Identifier: Apache-2.0") 174 && text.contains("SPDX-FileCopyrightText: 20") 175 { 176 // Licence information is present 177 return None; 178 } 179 180 Some(path.to_str().unwrap().to_string()) 181 }) 182 .join("\n - "); 183 184 if !paths.is_empty() { 185 panic!( 186 "Source files missing SPDX licence information! 187 188Add a comment like this: 189 190 // SPDX-License-Identifier: Apache-2.0 191 // SPDX-FileCopyrightText: 2026 The Gleam contributors 192 193To these files: 194 195- {paths} 196" 197 ) 198 } 199}