diff options
| author | user <user@clank> | 2026-09-02 14:43:09 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-09-02 14:43:09 +0200 |
| commit | 18d1aef0f9bf4620135fd9f77f26683e6f2f8c00 (patch) | |
| tree | bf3ea334988ce03f61705ba9628941c175c1ee38 /tests | |
| parent | web: the real site is the only site, and web/publish ships it (diff) | |
| download | slosh-18d1aef0f9bf4620135fd9f77f26683e6f2f8c00.tar.gz slosh-18d1aef0f9bf4620135fd9f77f26683e6f2f8c00.tar.xz slosh-18d1aef0f9bf4620135fd9f77f26683e6f2f8c00.zip | |
shaders: remove the .so plugin loader
The static musl release builds cannot dlopen -- musl compiles it out
-- so loadable shader plugins were a feature most shipped binaries
could not use. Nothing we ship used it either: every shader in
contrib/shaders is an expression. Gone: the dlopen/glob loader in
shader.c, shader_dir in the config, the plugin ABI table and entry
macro, the Windows dl*/glob shims that existed only for it, the
contrib/shader-plugin skeleton, its tests, and every doc mention.
shader_abi.h stays as the shader model (cell_t, shade_ctx_t,
shader_t) with a note about what it used to be.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/fuzz/corpus/kdl/config.kdl | 18 | ||||
| -rw-r--r-- | tests/shader_plugin_test.c | 35 | ||||
| -rw-r--r-- | tests/test_shader_plugin.py | 188 |
3 files changed, 0 insertions, 241 deletions
diff --git a/tests/fuzz/corpus/kdl/config.kdl b/tests/fuzz/corpus/kdl/config.kdl index 27f842d..df77b7b 100644 --- a/tests/fuzz/corpus/kdl/config.kdl +++ b/tests/fuzz/corpus/kdl/config.kdl @@ -18,8 +18,6 @@ // // shell consulted when a pane is made, so it applies to the next // pane you open rather than to the ones already running -// shader_dir plugins are loaded on reload but never unloaded, so a new -// .so is picked up and a replaced one needs a new session // // A session started before this file existed still notices it appearing: the // watch is on the directory, and slosh creates that directory at startup so @@ -382,22 +380,6 @@ word_separators "\"'`()[]{}<>;,|" // terminal's real colours the screen will shift slightly while a modal is up. modal_scrim 120 -// Extra shaders can be loaded from shared libraries: any `*.so` in the -// directory below that exports a slosh shader plugin. Once loaded they are -// named here exactly like a built-in. Default: a `shaders` directory beside -// this file, so dropping the .so next to your config is the whole install. -// -// A plugin is native code running in the session's own process, with your -// privileges and no sandbox -- which is the same thing `shell` and a layout's -// `command=` already are, and the reason the search path is a directory you -// own rather than a value that can point anywhere. Install ones you trust. -// -// Adding a plugin and saving this file loads it; nothing is ever unloaded, so -// *replacing* one needs a new session. Skeleton and Makefile: -// contrib/shader-plugin/ -// -// shader_dir "~/.config/slosh/shaders" - // ── projects ──────────────────────────────────────────────────────────────── // // Where you keep your work. Each of these is scanned for subdirectories that diff --git a/tests/shader_plugin_test.c b/tests/shader_plugin_test.c deleted file mode 100644 index c7ece9e..0000000 --- a/tests/shader_plugin_test.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Fixture for test_shader_plugin.py: a shader plugin with nothing to it. - * - * Built twice — once as itself, once with -DBAD_ABI to produce a library that - * announces a version we do not speak, which is the case that has to fail - * safely rather than crash. - */ -#include "shader_abi.h" - -#ifdef BAD_ABI -#undef SLOSH_SHADER_ABI -#define SLOSH_SHADER_ABI 9999 -#endif - -/* Paints every cell's background the configured colour, at full strength when - * amount is 255. Deterministic and position-independent, so the test can - * assert one cell and mean it. */ -static void sh_fill(const shader_t *sh, const shade_ctx_t *ctx, cell_t *c) { - (void)ctx; - if (!sh->amount) return; - c->bg = sh->color; -} - -/* Uses param, so the test can prove a plugin sees the config's number. */ -static void sh_stripe(const shader_t *sh, const shade_ctx_t *ctx, cell_t *c) { - uint16_t n = sh->param ? sh->param : 2; - if (ctx->x % n) return; - c->bg = sh->color; -} - -static const shader_def_t SHADERS[] = { - {"testfill", sh_fill}, - {"teststripe", sh_stripe}, -}; - -SLOSH_SHADER_PLUGIN("test-fixture", SHADERS) diff --git a/tests/test_shader_plugin.py b/tests/test_shader_plugin.py deleted file mode 100644 index 26bec57..0000000 --- a/tests/test_shader_plugin.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env python3 -"""Shaders loaded from shared libraries at runtime. - -The built-ins are compiled in; these are not. What matters is that a plugin's -shader is indistinguishable from a built-in once loaded (same config syntax, -same parameters, same pass), and that everything which can be wrong with a -library fails safely: a wrong ABI, a name that already exists, a directory -that is not there. - -The example in contrib/ is built and loaded here too, so it cannot rot. -""" - -import os -import shutil -import sys -import tempfile - -from harness import Session, check, report - -HERE = os.path.dirname(os.path.abspath(__file__)) -BUILD = os.path.join(HERE, "..", "build") -GOOD = os.path.join(BUILD, "testshader.so") -BAD = os.path.join(BUILD, "badshader.so") -EXAMPLE = os.path.join(BUILD, "exampleshader.so") - -# A pane that paints one known cell and then sits still. -SH = ["/bin/sh", "-c", 'printf "\\033]2;p\\007"; printf "BLOCK\\n"; read x'] - - -def session_dir(plugins, config, shaders_subdir=False): - """A config file, and the plugins it should find beside it.""" - d = tempfile.mkdtemp(prefix="slosh-plug-") - dest = os.path.join(d, "shaders") if shaders_subdir else d - os.makedirs(dest, exist_ok=True) - for p in plugins: - shutil.copy(p, dest) - path = os.path.join(d, "config.kdl") - with open(path, "w") as f: - f.write(config) - return path, dest - - -def bg_at(snap, pane, row=0, col=0): - run = snap.style_at(pane["content_x"] + col, pane["content_y"] + row) - return (run or {}).get("bg") - - -def fg_at(snap, pane, row=0, col=0): - run = snap.style_at(pane["content_x"] + col, pane["content_y"] + row) - return (run or {}).get("fg") - - -def test_a_plugin_shader_is_used_like_a_builtin(): - cfg, d = session_dir( - [GOOD], - 'shader_dir "%s"\nshaders {\n testfill amount=255 color="#00ff00"\n}\n', - ) - # the directory is known only after it exists, so write the config now - with open(cfg, "w") as f: - f.write( - 'shader_dir "%s"\nshaders {\n' - ' testfill amount=255 color="#00ff00"\n}\n' % d - ) - - with Session(SH, cols=40, rows=10, config=cfg) as s: - snap = s.until_text("BLOCK") - pane = s.pane() - check( - "the loaded shader ran", - bg_at(snap, pane) == "#00ff00", - str(snap.style_at(pane["content_x"], pane["content_y"])), - ) - - -def test_it_is_found_beside_the_config_by_default(): - cfg, d = session_dir([GOOD], "", shaders_subdir=True) - with open(cfg, "w") as f: - f.write('shaders {\n testfill amount=255 color="#0000ff"\n}\n') - - with Session(SH, cols=40, rows=10, config=cfg) as s: - snap = s.until_text("BLOCK") - check("no shader_dir needed", bg_at(snap, s.pane()) == "#0000ff", snap.screen()) - - -def test_the_config_number_reaches_the_plugin(): - cfg, d = session_dir([GOOD], "") - with open(cfg, "w") as f: - f.write( - 'shader_dir "%s"\nshaders {\n' - ' teststripe amount=255 band=3 color="#ff0000"\n}\n' % d - ) - - with Session(SH, cols=40, rows=10, config=cfg) as s: - snap = s.until_text("BLOCK") - pane = s.pane() - got = [bg_at(snap, pane, 0, x) for x in range(6)] - check( - "every third column, as asked", - got[0] == "#ff0000" - and got[3] == "#ff0000" - and got[1] != "#ff0000" - and got[2] != "#ff0000", - str(got), - ) - - -def test_a_stale_plugin_is_refused_and_the_rest_still_load(): - cfg, d = session_dir([GOOD, BAD], "") - with open(cfg, "w") as f: - f.write( - 'shader_dir "%s"\nshaders {\n' - ' testfill amount=255 color="#00ff00"\n}\n' % d - ) - - with Session(SH, cols=40, rows=10, config=cfg) as s: - snap = s.until_text("BLOCK") - check("the session is alive", s.alive()) - check( - "the good plugin still loaded", - bg_at(snap, s.pane()) == "#00ff00", - snap.screen(), - ) - - -def test_an_unknown_shader_is_skipped_not_fatal(): - cfg, d = session_dir([], "") - with open(cfg, "w") as f: - f.write("shaders {\n nosuchshader amount=255\n dim amount=0\n}\n") - - with Session(SH, cols=40, rows=10, config=cfg) as s: - snap = s.until_text("BLOCK") - check("the session survives a name it does not know", s.alive()) - check("and still draws", "BLOCK" in snap.screen(), snap.screen()) - - -def test_no_shader_directory_at_all_is_normal(): - cfg, d = session_dir([], "") - with open(cfg, "w") as f: - f.write( - 'shader_dir "/nonexistent/slosh/shaders"\n' - "shaders {\n dim amount=100\n}\n" - ) - - with Session(SH, cols=40, rows=10, config=cfg) as s: - snap = s.until_text("BLOCK") - check("a missing directory is not an error", s.alive()) - check("and the built-ins are unaffected", "BLOCK" in snap.screen()) - - -def test_the_directory_may_be_written_with_a_tilde(): - cfg, d = session_dir([GOOD], "", shaders_subdir=True) - home = os.path.dirname(d) - with open(cfg, "w") as f: - f.write( - 'shader_dir "~/shaders"\nshaders {\n' - ' testfill amount=255 color="#00ff00"\n}\n' - ) - - with Session(SH, cols=40, rows=10, config=cfg, env={"HOME": home}) as s: - snap = s.until_text("BLOCK") - check( - "~ in shader_dir is the home directory", - bg_at(snap, s.pane()) == "#00ff00", - snap.screen(), - ) - - -def test_the_contrib_example_builds_and_loads(): - cfg, d = session_dir([EXAMPLE], "") - with open(cfg, "w") as f: - f.write('shader_dir "%s"\nshaders {\n checker amount=255 band=2\n}\n' % d) - - with Session(SH, cols=40, rows=10, config=cfg) as s: - snap = s.until_text("BLOCK") - pane = s.pane() - # Asserted on the foreground: the checkerboard darkens towards black - # and the default background already *is* black, so two squares that - # differ would still read the same there. Reading the wrong channel - # would make a working effect look like a broken one. - a = fg_at(snap, pane, 0, 0) - b = fg_at(snap, pane, 0, 2) - check("the shipped example draws something", a != b, f"{a} {b}") - - -for name, fn in sorted(list(globals().items())): - if name.startswith("test_"): - fn() -sys.exit(report()) |
