Reject non-hex workspace colors
9dcf7d3a276e43eecf8c0a17872ec1f927741a95
1 parent
f9d5f530
Makefile
+12 -2
| 189 | 189 | @echo "cc test/unit.c => $@" |
|
| 190 | 190 | @$(CC) $(TEST_CPPFLAGS) $(TEST_CFLAGS) test/unit.c util.c \ |
|
| 191 | 191 | ext-workspace-v1-protocol.c swm-toplevel-v1-protocol.c \ |
|
| 192 | 192 | swm-workspace-v1-protocol.c $(LDLIBS) -o $@ |
|
| 193 | 193 | ||
| 194 | + | $(TEST_BIN)/ctl-unit: test/ctl_unit.c swmctl.c \ |
|
| 195 | + | ext-foreign-toplevel-list-v1-client-protocol.h \ |
|
| 196 | + | swm-toplevel-v1-client-protocol.h swm-workspace-v1-client-protocol.h \ |
|
| 197 | + | ext-foreign-toplevel-list-v1-protocol.c swm-toplevel-v1-protocol.c \ |
|
| 198 | + | swm-workspace-v1-protocol.c | $(TEST_BIN) |
|
| 199 | + | @echo "cc test/ctl_unit.c => $@" |
|
| 200 | + | @$(CC) -I. $(CTL_CPPFLAGS) $(TEST_CFLAGS) test/ctl_unit.c \ |
|
| 201 | + | ext-foreign-toplevel-list-v1-protocol.c swm-toplevel-v1-protocol.c \ |
|
| 202 | + | swm-workspace-v1-protocol.c $(CTL_LDLIBS) -o $@ |
|
| 203 | + | ||
| 194 | 204 | $(TEST_BIN)/swm: $(TEST_COMMON) | $(TEST_BIN) |
|
| 195 | 205 | @echo "cc swm.c => $@" |
|
| 196 | 206 | @$(CC) $(TEST_CPPFLAGS) $(TEST_CFLAGS) $(TEST_SRC)/swm.c util.c \ |
|
| 197 | 207 | ext-workspace-v1-protocol.c swm-toplevel-v1-protocol.c \ |
|
| 198 | 208 | swm-workspace-v1-protocol.c $(LDLIBS) -o $@ |
| 204 | 214 | @echo "cc swmctl.c => $@" |
|
| 205 | 215 | @$(CC) $(CTL_CPPFLAGS) $(TEST_CFLAGS) swmctl.c \ |
|
| 206 | 216 | ext-foreign-toplevel-list-v1-protocol.c swm-toplevel-v1-protocol.c \ |
|
| 207 | 217 | swm-workspace-v1-protocol.c $(CTL_LDLIBS) -o $@ |
|
| 208 | 218 | ||
| 209 | - | test-build: $(TEST_BIN)/unit $(TEST_BIN)/swm $(TEST_BIN)/swmctl |
|
| 219 | + | test-build: $(TEST_BIN)/unit $(TEST_BIN)/ctl-unit $(TEST_BIN)/swm $(TEST_BIN)/swmctl |
|
| 210 | 220 | ||
| 211 | 221 | test: test-build |
|
| 212 | 222 | @SWM_TEST_BUILD=$(abspath $(TEST_BUILD)) PKG_CONFIG=$(PKG_CONFIG) $(PYTHON) test/run.py |
|
| 213 | 223 | ||
| 214 | - | test-unit: $(TEST_BIN)/unit |
|
| 224 | + | test-unit: $(TEST_BIN)/unit $(TEST_BIN)/ctl-unit |
|
| 215 | 225 | @SWM_TEST_BUILD=$(abspath $(TEST_BUILD)) PKG_CONFIG=$(PKG_CONFIG) $(PYTHON) test/run.py unit |
|
| 216 | 226 | ||
| 217 | 227 | test-integration: $(TEST_BIN)/swm $(TEST_BIN)/swmctl |
|
| 218 | 228 | @SWM_TEST_BUILD=$(abspath $(TEST_BUILD)) PKG_CONFIG=$(PKG_CONFIG) $(PYTHON) test/run.py integration |
|
| 219 | 229 |
swmctl.c
+2 -1
| 376 | 376 | static uint32_t parse_color(const char *value) { |
|
| 377 | 377 | char *end; |
|
| 378 | 378 | unsigned long color; |
|
| 379 | 379 | size_t length = strlen(value); |
|
| 380 | 380 | ||
| 381 | - | if ((length != 7 && length != 9) || value[0] != '#') |
|
| 381 | + | if ((length != 7 && length != 9) || value[0] != '#' || |
|
| 382 | + | strspn(value + 1, "0123456789abcdefABCDEF") != length - 1) |
|
| 382 | 383 | usage(); |
|
| 383 | 384 | errno = 0; |
|
| 384 | 385 | color = strtoul(value + 1, &end, 16); |
|
| 385 | 386 | if (errno || *end || color > 0xffffffff) |
|
| 386 | 387 | usage(); |
test/ctl_unit.c
added
+35 -0
| 1 | + | #include <assert.h> |
|
| 2 | + | #include <fcntl.h> |
|
| 3 | + | #include <sys/wait.h> |
|
| 4 | + | #include <unistd.h> |
|
| 5 | + | ||
| 6 | + | #define main swmctl_program_main |
|
| 7 | + | #include "swmctl.c" |
|
| 8 | + | #undef main |
|
| 9 | + | ||
| 10 | + | static void expect_invalid_color(const char *value) { |
|
| 11 | + | pid_t child = fork(); |
|
| 12 | + | int status; |
|
| 13 | + | ||
| 14 | + | assert(child >= 0); |
|
| 15 | + | if (!child) { |
|
| 16 | + | int nullfd = open("/dev/null", O_WRONLY); |
|
| 17 | + | ||
| 18 | + | assert(nullfd >= 0); |
|
| 19 | + | assert(dup2(nullfd, STDERR_FILENO) >= 0); |
|
| 20 | + | close(nullfd); |
|
| 21 | + | parse_color(value); |
|
| 22 | + | _exit(EXIT_SUCCESS); |
|
| 23 | + | } |
|
| 24 | + | assert(waitpid(child, &status, 0) == child); |
|
| 25 | + | assert(WIFEXITED(status)); |
|
| 26 | + | assert(WEXITSTATUS(status) == EXIT_FAILURE); |
|
| 27 | + | } |
|
| 28 | + | ||
| 29 | + | int main(void) { |
|
| 30 | + | assert(parse_color("#012345") == 0x012345ff); |
|
| 31 | + | assert(parse_color("#01234567") == 0x01234567); |
|
| 32 | + | expect_invalid_color("# 12345"); |
|
| 33 | + | expect_invalid_color("#+12345"); |
|
| 34 | + | return EXIT_SUCCESS; |
|
| 35 | + | } |
test/run.py
+7 -1
| 198 | 198 | def prepare_suite(unit: bool, integration: bool) -> None: |
|
| 199 | 199 | """Prepare runtime files for the selected tests.""" |
|
| 200 | 200 | ||
| 201 | 201 | binaries = [ |
|
| 202 | 202 | BIN / name |
|
| 203 | - | for name, selected in (("unit", unit), ("swm", integration), ("swmctl", integration)) |
|
| 203 | + | for name, selected in ( |
|
| 204 | + | ("unit", unit), |
|
| 205 | + | ("ctl-unit", unit), |
|
| 206 | + | ("swm", integration), |
|
| 207 | + | ("swmctl", integration), |
|
| 208 | + | ) |
|
| 204 | 209 | if selected |
|
| 205 | 210 | ] |
|
| 206 | 211 | missing = [binary for binary in binaries if not binary.exists()] |
|
| 207 | 212 | if missing: |
|
| 208 | 213 | raise Failure(f"test binary not built: {missing[0]}; run tests through make") |
| 253 | 258 | env["LLVM_PROFILE_FILE"] = str(PROFILES / "unit-%m-%p.profraw") |
|
| 254 | 259 | env["SWM_TEST_STUB_PATH"] = str(BUILD / "stubs") |
|
| 255 | 260 | env["SWM_TEST_DIR"] = str(runtime) |
|
| 256 | 261 | for name in run(BIN / "unit", "--list", env=env).splitlines(): |
|
| 257 | 262 | test(name, lambda name=name: run(BIN / "unit", name, env=env)) |
|
| 263 | + | test("control-client-parsing", lambda: run(BIN / "ctl-unit", env=env)) |
|
| 258 | 264 | shutil.rmtree(runtime) |
|
| 259 | 265 | ||
| 260 | 266 | ||
| 261 | 267 | def current_title() -> str: |
|
| 262 | 268 | """Return the compositor's published title.""" |