Skip to main content

wasmsh_testkit/
features.rs

1//! Feature gate registry for the TOML test runner.
2//!
3//! Tests declare `requires = ["feature1", "feature2"]`. If any required
4//! feature is not in the implemented set, the test is skipped.
5
6use std::collections::HashSet;
7
8/// Returns the set of features currently implemented in wasmsh.
9#[must_use]
10pub fn implemented_features() -> HashSet<&'static str> {
11    let mut f = HashSet::new();
12
13    // Shell syntax
14    f.insert("simple-command");
15    f.insert("pipeline");
16    f.insert("and-or-list");
17    f.insert("semicolon-list");
18    f.insert("pipeline-negation");
19    f.insert("variable-assignment");
20    f.insert("redirection");
21    f.insert("here-doc");
22    f.insert("here-doc-expansion");
23    f.insert("single-quoting");
24    f.insert("double-quoting");
25    f.insert("backslash-escape");
26    f.insert("parameter-expansion");
27    f.insert("parameter-default");
28    f.insert("parameter-assign-default");
29    f.insert("parameter-alternative");
30    f.insert("parameter-error");
31    f.insert("parameter-length");
32    f.insert("arithmetic-expansion");
33    f.insert("nested-expansion");
34    f.insert("comment");
35    f.insert("if");
36    f.insert("while");
37    f.insert("until");
38    f.insert("for-in");
39    f.insert("case");
40    f.insert("subshell");
41    f.insert("brace-group");
42    f.insert("function");
43
44    // Builtins
45    f.insert("echo");
46    f.insert("printf");
47    f.insert("pwd");
48    f.insert("cd");
49    f.insert("export");
50    f.insert("unset");
51    f.insert("readonly");
52    f.insert("test");
53    f.insert("read");
54    f.insert("true");
55    f.insert("false");
56    f.insert("colon");
57
58    // Utilities
59    f.insert("cat");
60    f.insert("ls");
61    f.insert("mkdir");
62    f.insert("rm");
63    f.insert("touch");
64    f.insert("head");
65    f.insert("tail");
66    f.insert("wc");
67    f.insert("grep");
68    f.insert("sed");
69    f.insert("sort");
70    f.insert("uniq");
71    f.insert("cut");
72    f.insert("tr");
73    f.insert("tee");
74    f.insert("seq");
75    f.insert("basename");
76    f.insert("dirname");
77    f.insert("mv");
78    f.insert("cp");
79    f.insert("env");
80    f.insert("printenv");
81    f.insert("id");
82    f.insert("whoami");
83    f.insert("uname");
84    f.insert("hostname");
85    f.insert("sleep");
86    f.insert("expr");
87    f.insert("xargs");
88
89    // Shell features
90    f.insert("glob-expansion");
91    f.insert("brace-expansion");
92    f.insert("here-string");
93    f.insert("ansi-c-quoting");
94    f.insert("stderr-redirection");
95    f.insert("fd-redirection");
96    f.insert("tilde-expansion");
97    f.insert("command-substitution");
98    f.insert("parameter-substitution");
99    f.insert("parameter-substring");
100    f.insert("break");
101    f.insert("continue");
102    f.insert("exit");
103    f.insert("return");
104    f.insert("local");
105    f.insert("shift");
106    f.insert("set");
107    f.insert("type");
108    f.insert("command-builtin");
109    f.insert("times");
110    f.insert("dirs");
111    f.insert("pushd");
112    f.insert("popd");
113    f.insert("umask");
114    f.insert("wait");
115    f.insert("ulimit");
116    f.insert("exec-builtin");
117    f.insert("eval");
118    f.insert("source");
119    f.insert("getopts");
120    f.insert("trap");
121    f.insert("ln");
122    f.insert("readlink");
123    f.insert("realpath");
124    f.insert("stat");
125    f.insert("find");
126    f.insert("chmod");
127    f.insert("date");
128    f.insert("echo-escape");
129    f.insert("printf-repeat");
130    f.insert("errexit");
131    f.insert("trap-exit");
132    f.insert("trap-err");
133    f.insert("trap-debug");
134    f.insert("trap-return");
135    f.insert("parameter-strip");
136
137    // New syntax features (gap implementation)
138    f.insert("double-bracket");
139    f.insert("bash-rematch");
140    f.insert("c-style-for");
141    f.insert("arith-command");
142    f.insert("pipe-ampersand");
143    f.insert("case-fallthrough");
144    f.insert("case-continue-testing");
145    f.insert("select");
146    f.insert("locale-quoting");
147    f.insert("dynamic-fd");
148    f.insert("move-fd");
149    f.insert("time-keyword");
150
151    // Arrays
152    f.insert("indexed-array");
153    f.insert("associative-array");
154
155    // Variable features
156    f.insert("random-variable");
157    f.insert("lineno-variable");
158    f.insert("seconds-variable");
159    f.insert("pipestatus");
160    f.insert("funcname-variable");
161    f.insert("bash-source-variable");
162    f.insert("nameref");
163
164    // Expansion features
165    f.insert("case-modification");
166    f.insert("anchored-substitution");
167    f.insert("substitution-glob");
168    f.insert("indirect-expansion");
169    f.insert("prefix-expansion");
170    f.insert("transformation-operators");
171
172    // Arithmetic features
173    f.insert("arithmetic-comparison");
174    f.insert("arithmetic-parentheses");
175    f.insert("arithmetic-assignment");
176    f.insert("arithmetic-bases");
177
178    // Builtin features
179    f.insert("declare");
180    f.insert("alias");
181    f.insert("let");
182    f.insert("printf-format");
183    f.insert("read-flags");
184    f.insert("shopt");
185    f.insert("mapfile");
186    f.insert("builtin-keyword");
187    f.insert("source-path");
188
189    // Shell option features
190    f.insert("pipefail");
191    f.insert("nounset");
192    f.insert("xtrace");
193    f.insert("noglob");
194    f.insert("allexport");
195
196    // Glob features
197    f.insert("extglob");
198    f.insert("globstar");
199
200    // New utilities
201    f.insert("mktemp");
202    f.insert("yes");
203    f.insert("paste");
204    f.insert("md5sum");
205    f.insert("sha256sum");
206    f.insert("base64");
207    f.insert("rev");
208    f.insert("column");
209
210    // Advanced utilities
211    f.insert("awk");
212    f.insert("jq");
213    f.insert("diff");
214    f.insert("patch");
215    f.insert("rg");
216    f.insert("tree");
217    f.insert("xxd");
218    f.insert("dd");
219    f.insert("strings");
220    f.insert("split");
221    f.insert("bc");
222    f.insert("tar");
223    f.insert("gzip");
224    f.insert("gunzip");
225    f.insert("du");
226    f.insert("fd");
227    f.insert("file");
228    f.insert("comm");
229    f.insert("yq");
230
231    f
232}
233
234/// Check which required features are missing.
235pub fn missing_features(requires: &[String]) -> Vec<String> {
236    let implemented = implemented_features();
237    requires
238        .iter()
239        .filter(|r| !implemented.contains(r.as_str()))
240        .cloned()
241        .collect()
242}