aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authoruser <user@clank>2026-09-02 14:43:09 +0200
committeruser <user@clank>2026-09-02 14:43:09 +0200
commit18d1aef0f9bf4620135fd9f77f26683e6f2f8c00 (patch)
treebf3ea334988ce03f61705ba9628941c175c1ee38 /tests
parentweb: the real site is the only site, and web/publish ships it (diff)
downloadslosh-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.kdl18
-rw-r--r--tests/shader_plugin_test.c35
-rw-r--r--tests/test_shader_plugin.py188
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())