App-Ariza.git | runner/tests/ | test_env.c
/* Paths, token expansion, and PATH.
*
* The values in these cases are the ones every ariza bundle's sidecar
* happens to carry, which makes them readable — but nothing here knows
* that, and that is the point: the runner substitutes one token and
* joins paths, and what the results mean belongs to the renderer that
* wrote them. */
#include <stdlib.h>
#include "support.h"
static void test_path_join(void)
{
T_EQ_OWNED(arz_path_join(t_s("C:\\b"), t_s("site")), "C:\\b\\site");
/* However many separators each side brought, exactly one comes
* out — and it is a backslash, because that is what the sidecar
* records and what a Windows error message should show. */
T_EQ_OWNED(arz_path_join(t_s("C:\\b\\"), t_s("site")), "C:\\b\\site");
T_EQ_OWNED(arz_path_join(t_s("C:\\b"), t_s("\\site")), "C:\\b\\site");
T_EQ_OWNED(arz_path_join(t_s("C:\\b\\\\"), t_s("\\\\site")), "C:\\b\\site");
T_EQ_OWNED(arz_path_join(t_s("C:/b/"), t_s("/site")), "C:/b\\site");
/* Multi-component relatives are the ordinary case: every path in
* the sidecar is bundle-relative. */
T_EQ_OWNED(arz_path_join(t_s("C:\\b"), t_s("site\\bin\\a.raku")),
"C:\\b\\site\\bin\\a.raku");
/* A path with spaces, which is most of C:\Users\… */
T_EQ_OWNED(arz_path_join(t_s("C:\\Program Files\\My App"), t_s("native")),
"C:\\Program Files\\My App\\native");
/* UNC roots keep both leading separators. */
T_EQ_OWNED(arz_path_join(t_s("\\\\host\\share\\b"), t_s("site")),
"\\\\host\\share\\b\\site");
T_EQ_OWNED(arz_path_join(t_s("C:\\b"), t_s("")), "C:\\b");
T_EQ_OWNED(arz_path_join(t_s("C:\\b"), NULL), "C:\\b");
T_EQ_OWNED(arz_path_join(NULL, t_s("site")), "site");
}
static void test_parent_dir(void)
{
/* The runner walks bin\<exec>.exe up twice to reach the bundle
* root, so both steps are this function. */
T_EQ_OWNED(arz_parent_dir(t_s("C:\\b\\bin\\a.exe")), "C:\\b\\bin");
T_EQ_OWNED(arz_parent_dir(t_s("C:\\b\\bin")), "C:\\b");
T_EQ_OWNED(arz_parent_dir(t_s("C:\\b\\bin\\")), "C:\\b");
/* Forward slashes are accepted as separators, and left as they were
* found: this only ever strips, so nothing is normalised behind the
* caller's back. */
T_EQ_OWNED(arz_parent_dir(t_s("C:/b/bin/a.exe")), "C:/b/bin");
/* A drive root keeps its separator: "C:" alone is drive-relative
* and means something else entirely. */
T_EQ_OWNED(arz_parent_dir(t_s("C:\\a")), "C:\\");
T_EQ_OWNED(arz_parent_dir(t_s("\\\\host\\share\\b\\bin")),
"\\\\host\\share\\b");
/* Nothing to strip: a bare name has no parent, and the win32
* layer treats that as "this is not inside a bundle". */
T_CHECK(arz_parent_dir(t_s("a.exe")) == NULL);
T_CHECK(arz_parent_dir(t_s("")) == NULL);
T_CHECK(arz_parent_dir(NULL) == NULL);
}
static void test_expand(void)
{
/* The four values every ariza bundle's sidecar carries, expanded.
* The runner has no idea what any of them are for; it substitutes
* one token and hands the result to SetEnvironmentVariableW. */
T_EQ_OWNED(arz_expand(t_s("inst#{root}\\site"), t_s("C:\\b")),
"inst#C:\\b\\site");
T_EQ_OWNED(arz_expand(t_s("{root}\\native"), t_s("C:\\b")),
"C:\\b\\native");
T_EQ_OWNED(arz_expand(t_s("{root}\\native\\sqlcipher"),
t_s("C:\\Program Files\\My App")),
"C:\\Program Files\\My App\\native\\sqlcipher");
/* A value need not mention the root at all, and may mention it more
* than once. */
T_EQ_OWNED(arz_expand(t_s("plain"), t_s("C:\\b")), "plain");
T_EQ_OWNED(arz_expand(t_s(""), t_s("C:\\b")), "");
T_EQ_OWNED(arz_expand(t_s("{root};{root}\\x"), t_s("C:\\b")),
"C:\\b;C:\\b\\x");
T_EQ_OWNED(arz_expand(t_s("{root}"), t_s("C:\\b")), "C:\\b");
/* `{{` is the way to write a literal brace, so a value that needs
* one is expressible rather than a reason to loosen the parser's
* refusal of unknown tokens. */
T_EQ_OWNED(arz_expand(t_s("{{root}"), t_s("C:\\b")), "{root}");
T_EQ_OWNED(arz_expand(t_s("{{{root}}}"), t_s("C:\\b")), "{C:\\b}}");
/* Non-ASCII on both sides. */
T_EQ_OWNED(arz_expand(t_u8("{root}\\café"), t_u8("C:\\Ünïcode")),
"C:\\Ünïcode\\café");
T_CHECK(arz_expand(NULL, t_s("C:\\b")) == NULL);
}
static void test_interpreter(void)
{
T_EQ_OWNED(arz_interpreter_path(t_s("C:\\b")),
"C:\\b\\rakudo\\bin\\raku.exe");
T_EQ_OWNED(arz_interpreter_path(t_s("C:\\Program Files\\My App")),
"C:\\Program Files\\My App\\rakudo\\bin\\raku.exe");
}
static void test_path_prepend(void)
{
T_EQ_OWNED(arz_env_path_prepend(t_s("C:\\b\\native\\sqlcipher"),
t_s("C:\\Windows\\system32;C:\\Windows")),
"C:\\b\\native\\sqlcipher;C:\\Windows\\system32;C:\\Windows");
/* No trailing ';' when there is nothing to keep: an empty PATH
* entry is the current directory to Windows, and a launcher that
* quietly adds one has widened the DLL search of every process the
* app starts. */
T_EQ_OWNED(arz_env_path_prepend(t_s("C:\\b\\native\\sqlcipher"), NULL),
"C:\\b\\native\\sqlcipher");
T_EQ_OWNED(arz_env_path_prepend(t_s("C:\\b\\native\\sqlcipher"), t_s("")),
"C:\\b\\native\\sqlcipher");
}
int main(void)
{
test_path_join();
test_parent_dir();
test_expand();
test_interpreter();
test_path_prepend();
return t_done("env");
}