|
| 1 | +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ |
| 2 | +│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ |
| 3 | +╞══════════════════════════════════════════════════════════════════════════════╡ |
| 4 | +│ Copyright 2024 Justine Alexandra Roberts Tunney │ |
| 5 | +│ │ |
| 6 | +│ Permission to use, copy, modify, and/or distribute this software for │ |
| 7 | +│ any purpose with or without fee is hereby granted, provided that the │ |
| 8 | +│ above copyright notice and this permission notice appear in all copies. │ |
| 9 | +│ │ |
| 10 | +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ |
| 11 | +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ |
| 12 | +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ |
| 13 | +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ |
| 14 | +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ |
| 15 | +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ |
| 16 | +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ |
| 17 | +│ PERFORMANCE OF THIS SOFTWARE. │ |
| 18 | +╚─────────────────────────────────────────────────────────────────────────────*/ |
| 19 | +#include "libc/cosmo.h" |
| 20 | +#include "libc/mem/mem.h" |
| 21 | +#include "libc/runtime/runtime.h" |
| 22 | +#include "libc/stdio/rand.h" |
| 23 | +#include "libc/testlib/testlib.h" |
| 24 | +#include "libc/x/x.h" |
| 25 | + |
| 26 | +void SetUpOnce(void) { |
| 27 | + testlib_enable_tmp_setup_teardown(); |
| 28 | +} |
| 29 | + |
| 30 | +TEST(cosmo_args, normalize) { |
| 31 | + char *args[] = {0}; |
| 32 | + char **argv = args; |
| 33 | + ASSERT_EQ(1, cosmo_args(0, &argv)); |
| 34 | + ASSERT_STREQ(GetProgramExecutableName(), argv[0]); |
| 35 | +} |
| 36 | + |
| 37 | +TEST(cosmo_args, test) { |
| 38 | + xbarf(".args", "a b c", -1); |
| 39 | + char *args[] = {"prog", "arg", 0}; |
| 40 | + char **argv = args; |
| 41 | + ASSERT_EQ(5, cosmo_args(".args", &argv)); |
| 42 | + ASSERT_STREQ("prog", argv[0]); |
| 43 | + ASSERT_STREQ("a", argv[1]); |
| 44 | + ASSERT_STREQ("b", argv[2]); |
| 45 | + ASSERT_STREQ("c", argv[3]); |
| 46 | + ASSERT_STREQ("arg", argv[4]); |
| 47 | +} |
| 48 | + |
| 49 | +TEST(cosmo_args, perline) { |
| 50 | + xbarf(".args", "a\nb\nc\n", -1); |
| 51 | + char *args[] = {"prog", "arg", 0}; |
| 52 | + char **argv = args; |
| 53 | + ASSERT_EQ(5, cosmo_args(".args", &argv)); |
| 54 | + ASSERT_STREQ("prog", argv[0]); |
| 55 | + ASSERT_STREQ("a", argv[1]); |
| 56 | + ASSERT_STREQ("b", argv[2]); |
| 57 | + ASSERT_STREQ("c", argv[3]); |
| 58 | + ASSERT_STREQ("arg", argv[4]); |
| 59 | +} |
| 60 | + |
| 61 | +TEST(cosmo_args, dots_end) { |
| 62 | + xbarf(".args", "a b c ...", -1); |
| 63 | + char *args[] = {"prog", "arg", 0}; |
| 64 | + char **argv = args; |
| 65 | + ASSERT_EQ(5, cosmo_args(".args", &argv)); |
| 66 | + ASSERT_STREQ("prog", argv[0]); |
| 67 | + ASSERT_STREQ("a", argv[1]); |
| 68 | + ASSERT_STREQ("b", argv[2]); |
| 69 | + ASSERT_STREQ("c", argv[3]); |
| 70 | + ASSERT_STREQ("arg", argv[4]); |
| 71 | +} |
| 72 | + |
| 73 | +TEST(cosmo_args, dots_middle) { |
| 74 | + xbarf(".args", "a ... b c", -1); |
| 75 | + char *args[] = {"prog", "arg", 0}; |
| 76 | + char **argv = args; |
| 77 | + ASSERT_EQ(5, cosmo_args(".args", &argv)); |
| 78 | + ASSERT_STREQ("prog", argv[0]); |
| 79 | + ASSERT_STREQ("a", argv[1]); |
| 80 | + ASSERT_STREQ("arg", argv[2]); |
| 81 | + ASSERT_STREQ("b", argv[3]); |
| 82 | + ASSERT_STREQ("c", argv[4]); |
| 83 | +} |
| 84 | + |
| 85 | +TEST(cosmo_args, quote) { |
| 86 | + xbarf(".args", " 'hi \\n there'# ", -1); |
| 87 | + char *args[] = {0}; |
| 88 | + char **argv = args; |
| 89 | + ASSERT_EQ(2, cosmo_args(".args", &argv)); |
| 90 | + ASSERT_STREQ("hi \\n there#", argv[1]); |
| 91 | +} |
| 92 | + |
| 93 | +TEST(cosmo_args, dquote) { |
| 94 | + xbarf(".args", " \"hi \\a\\b\\t\\n\\v\\f\\r\\e\\0\\11 \\111 \xab there\"# ", |
| 95 | + -1); |
| 96 | + char *args[] = {0}; |
| 97 | + char **argv = args; |
| 98 | + ASSERT_EQ(2, cosmo_args(".args", &argv)); |
| 99 | + ASSERT_STREQ("hi \a\b\t\n\v\f\r\e\0\11 \111 \xab there#", argv[1]); |
| 100 | +} |
| 101 | + |
| 102 | +TEST(cosmo_args, comment) { |
| 103 | + xbarf(".args", |
| 104 | + "# comment\n" |
| 105 | + "a # hello there\n" |
| 106 | + "b # yup\n", |
| 107 | + -1); |
| 108 | + char *args[] = {0}; |
| 109 | + char **argv = args; |
| 110 | + ASSERT_EQ(3, cosmo_args(".args", &argv)); |
| 111 | + ASSERT_STREQ("a", argv[1]); |
| 112 | + ASSERT_STREQ("b", argv[2]); |
| 113 | +} |
| 114 | + |
| 115 | +TEST(cosmo_args, backslash_newline) { |
| 116 | + xbarf(".args", |
| 117 | + "a\\\n" |
| 118 | + "b\n", |
| 119 | + -1); |
| 120 | + char *args[] = {0}; |
| 121 | + char **argv = args; |
| 122 | + ASSERT_EQ(2, cosmo_args(".args", &argv)); |
| 123 | + ASSERT_STREQ("ab", argv[1]); |
| 124 | +} |
| 125 | + |
| 126 | +TEST(cosmo_args, dotz) { |
| 127 | + xbarf(".args", ". .. ...x", -1); |
| 128 | + char *args[] = {0}; |
| 129 | + char **argv = args; |
| 130 | + ASSERT_EQ(4, cosmo_args(".args", &argv)); |
| 131 | + ASSERT_STREQ(".", argv[1]); |
| 132 | + ASSERT_STREQ("..", argv[2]); |
| 133 | + ASSERT_STREQ("...x", argv[3]); |
| 134 | +} |
| 135 | + |
| 136 | +TEST(cosmo_args, env) { |
| 137 | + setenv("foo", "bar", true); |
| 138 | + xbarf(".args", "$foo x${foo}x \"$foo\" \"${foo}\" $foo", -1); |
| 139 | + char *args[] = {0}; |
| 140 | + char **argv = args; |
| 141 | + ASSERT_EQ(6, cosmo_args(".args", &argv)); |
| 142 | + ASSERT_STREQ("bar", argv[1]); |
| 143 | + ASSERT_STREQ("xbarx", argv[2]); |
| 144 | + ASSERT_STREQ("bar", argv[3]); |
| 145 | + ASSERT_STREQ("bar", argv[4]); |
| 146 | + ASSERT_STREQ("bar", argv[5]); |
| 147 | +} |
| 148 | + |
| 149 | +TEST(cosmo_args, dquote_backslash_newline) { |
| 150 | + setenv("foo", "bar", true); |
| 151 | + xbarf(".args", |
| 152 | + "-p \"\\\n" |
| 153 | + "hello\"\n", |
| 154 | + -1); |
| 155 | + char *args[] = {0}; |
| 156 | + char **argv = args; |
| 157 | + ASSERT_EQ(3, cosmo_args(".args", &argv)); |
| 158 | + ASSERT_STREQ("-p", argv[1]); |
| 159 | + ASSERT_STREQ("hello", argv[2]); |
| 160 | +} |
| 161 | + |
| 162 | +TEST(cosmo_args, dquote_plain_old_newline) { |
| 163 | + setenv("foo", "bar", true); |
| 164 | + xbarf(".args", |
| 165 | + "-p \"\n" |
| 166 | + "hello\"\n", |
| 167 | + -1); |
| 168 | + char *args[] = {0}; |
| 169 | + char **argv = args; |
| 170 | + ASSERT_EQ(3, cosmo_args(".args", &argv)); |
| 171 | + ASSERT_STREQ("-p", argv[1]); |
| 172 | + ASSERT_STREQ("\nhello", argv[2]); |
| 173 | +} |
| 174 | + |
| 175 | +#define LENGTH 128 |
| 176 | +#define ITERATIONS 5000 |
| 177 | +#define CHARSET "abc#'\"$.\\{} \r\n" |
| 178 | + |
| 179 | +TEST(cosmo_args, fuzz) { |
| 180 | + char s[LENGTH + 1] = {0}; |
| 181 | + for (int i = 0; i < ITERATIONS; ++i) { |
| 182 | + for (int j = 0; j < LENGTH; ++j) |
| 183 | + s[j] = CHARSET[rand() % (sizeof(CHARSET) - 1)]; |
| 184 | + xbarf(".args", s, -1); |
| 185 | + char *args[] = {0}; |
| 186 | + char **argv = args; |
| 187 | + cosmo_args(".args", &argv); |
| 188 | + for (int j = 0; argv[j]; ++j) |
| 189 | + free(argv[j]); |
| 190 | + argv[0] = 0; |
| 191 | + } |
| 192 | +} |
0 commit comments