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("eval");
110    f.insert("source");
111    f.insert("getopts");
112    f.insert("trap");
113    f.insert("ln");
114    f.insert("readlink");
115    f.insert("realpath");
116    f.insert("stat");
117    f.insert("find");
118    f.insert("chmod");
119    f.insert("date");
120    f.insert("echo-escape");
121    f.insert("printf-repeat");
122    f.insert("errexit");
123    f.insert("trap-exit");
124    f.insert("parameter-strip");
125
126    // New syntax features (gap implementation)
127    f.insert("double-bracket");
128    f.insert("bash-rematch");
129    f.insert("c-style-for");
130    f.insert("arith-command");
131    f.insert("pipe-ampersand");
132    f.insert("case-fallthrough");
133    f.insert("case-continue-testing");
134    f.insert("select");
135    f.insert("locale-quoting");
136    f.insert("dynamic-fd");
137    f.insert("move-fd");
138
139    // Arrays
140    f.insert("indexed-array");
141    f.insert("associative-array");
142
143    // Variable features
144    f.insert("random-variable");
145    f.insert("lineno-variable");
146    f.insert("seconds-variable");
147    f.insert("pipestatus");
148    f.insert("funcname-variable");
149    f.insert("bash-source-variable");
150    f.insert("nameref");
151
152    // Expansion features
153    f.insert("case-modification");
154    f.insert("anchored-substitution");
155    f.insert("substitution-glob");
156    f.insert("indirect-expansion");
157    f.insert("prefix-expansion");
158    f.insert("transformation-operators");
159
160    // Arithmetic features
161    f.insert("arithmetic-comparison");
162    f.insert("arithmetic-parentheses");
163    f.insert("arithmetic-assignment");
164    f.insert("arithmetic-bases");
165
166    // Builtin features
167    f.insert("declare");
168    f.insert("alias");
169    f.insert("let");
170    f.insert("printf-format");
171    f.insert("read-flags");
172    f.insert("shopt");
173    f.insert("mapfile");
174    f.insert("builtin-keyword");
175    f.insert("source-path");
176
177    // Shell option features
178    f.insert("pipefail");
179    f.insert("nounset");
180    f.insert("xtrace");
181    f.insert("noglob");
182    f.insert("allexport");
183
184    // Glob features
185    f.insert("extglob");
186    f.insert("globstar");
187
188    // New utilities
189    f.insert("mktemp");
190    f.insert("yes");
191    f.insert("paste");
192    f.insert("md5sum");
193    f.insert("sha256sum");
194    f.insert("base64");
195    f.insert("rev");
196    f.insert("column");
197
198    // Advanced utilities
199    f.insert("awk");
200    f.insert("jq");
201    f.insert("diff");
202    f.insert("patch");
203    f.insert("rg");
204    f.insert("tree");
205    f.insert("xxd");
206    f.insert("dd");
207    f.insert("strings");
208    f.insert("split");
209    f.insert("bc");
210    f.insert("tar");
211    f.insert("gzip");
212    f.insert("gunzip");
213    f.insert("du");
214    f.insert("fd");
215    f.insert("file");
216    f.insert("comm");
217    f.insert("yq");
218
219    f
220}
221
222/// Check which required features are missing.
223pub fn missing_features(requires: &[String]) -> Vec<String> {
224    let implemented = implemented_features();
225    requires
226        .iter()
227        .filter(|r| !implemented.contains(r.as_str()))
228        .cloned()
229        .collect()
230}