unsloth/tests/sh/test_setup_webview_cache_clear.sh
shimmyshimmer cbb1508513 Address review: Linux data-dir caches, bash invocation, pre-webview clear
Three review findings, all verified:

1. wry keys the WebKitGTK base-cache dir to the app DATA dir (same as
base-data), so on Linux the stale frontend cache also lives under
~/.local/share/ai.unsloth.studio. Clear the cache-typed subdirs there
(WebKitCache, CacheStorage, serviceworkers) while keeping localstorage,
indexeddb, and cookies. Tests extended to 23 assertions.

2. run_all.sh invoked the new test with sh, but the extracted setup.sh
function uses bash arrays; dash aborts with a syntax error before any
assertion. Invoke with bash.

3. The in-app desktop update runs start_backend_update before
downloadAndInstall/relaunch, so setup.ps1/setup.sh clear caches while
the live WebView still holds them and silently fail. Clear the caches
from the Rust side in main() before the Builder runs: the config window
(and the WebView lock) exists by the time setup hooks fire, so this is
the one point where the profile is guaranteed unlocked. Same cache-only
path lists per OS; cargo check passes.
2026-07-23 02:35:51 -07:00

103 lines
5.2 KiB
Bash
Executable file

#!/bin/bash
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
# Unit tests for _clear_webview_caches() from studio/setup.sh.
#
# The WebView caches keyed by the app bundle id (ai.unsloth.studio) hold copies
# of the previous frontend, so an install/update must clear them or the app can
# keep rendering old styles. Clearing must be cache-only: LocalStorage,
# IndexedDB, app data, and unrelated apps' caches stay intact.
#
# Follows the extract-via-sed pattern of test_uninstall_shared_icon.sh; uname
# is overridden per test with a shell function to select the OS branch.
# shellcheck disable=SC2329 # uname stubs are invoked inside the extracted function
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SETUP_SH="$SCRIPT_DIR/../../studio/setup.sh"
BID="ai.unsloth.studio"
PASS=0
FAIL=0
_TMP_ROOT=$(mktemp -d)
trap 'rm -rf "$_TMP_ROOT"' EXIT
assert_gone() { _l="$1"; if [ -e "$2" ]; then echo " FAIL: $_l (still present: $2)"; FAIL=$((FAIL+1)); else echo " PASS: $_l"; PASS=$((PASS+1)); fi; }
assert_present() { _l="$1"; if [ -e "$2" ]; then echo " PASS: $_l"; PASS=$((PASS+1)); else echo " FAIL: $_l (missing: $2)"; FAIL=$((FAIL+1)); fi; }
# Extract just the function definition (top-level, closes at column 0).
FUNC_FILE=$(mktemp -p "$_TMP_ROOT")
sed -n '/^_clear_webview_caches() {/,/^}/p' "$SETUP_SH" > "$FUNC_FILE"
# shellcheck disable=SC1090
. "$FUNC_FILE"
substep() { :; } # stub the setup.sh logger
# ── 1. macOS: cache paths removed, user-facing storage kept ──
H=$(mktemp -d -p "$_TMP_ROOT")
mkdir -p "$H/Library/Caches/$BID/WebKit/NetworkCache" \
"$H/Library/WebKit/$BID/WebsiteData/CacheStorage" \
"$H/Library/WebKit/$BID/WebsiteData/ServiceWorkers" \
"$H/Library/WebKit/$BID/WebsiteData/DiskCache" \
"$H/Library/WebKit/$BID/WebsiteData/LocalStorage" \
"$H/Library/WebKit/$BID/WebsiteData/IndexedDB" \
"$H/Library/Application Support/$BID" \
"$H/Library/Caches/com.other.app"
uname() { echo Darwin; }
HOME="$H" _clear_webview_caches
assert_gone "macOS: Caches/$BID removed" "$H/Library/Caches/$BID"
assert_gone "macOS: WebsiteData/CacheStorage removed" "$H/Library/WebKit/$BID/WebsiteData/CacheStorage"
assert_gone "macOS: WebsiteData/ServiceWorkers removed" "$H/Library/WebKit/$BID/WebsiteData/ServiceWorkers"
assert_gone "macOS: WebsiteData/DiskCache removed" "$H/Library/WebKit/$BID/WebsiteData/DiskCache"
assert_present "macOS: LocalStorage kept" "$H/Library/WebKit/$BID/WebsiteData/LocalStorage"
assert_present "macOS: IndexedDB kept" "$H/Library/WebKit/$BID/WebsiteData/IndexedDB"
assert_present "macOS: Application Support kept" "$H/Library/Application Support/$BID"
assert_present "macOS: unrelated app cache kept" "$H/Library/Caches/com.other.app"
# ── 2. Linux: cache paths removed (XDG cache dir AND the cache subdirs wry
# keys to the app data dir), user-facing storage kept ──
H=$(mktemp -d -p "$_TMP_ROOT")
D="$H/.local/share/$BID"
mkdir -p "$H/.cache/$BID" "$D/WebKitCache" "$D/CacheStorage" "$D/serviceworkers" \
"$D/localstorage" "$D/indexeddb" "$H/.config/$BID" "$H/.cache/other.app"
: > "$D/cookies.sqlite"
uname() { echo Linux; }
HOME="$H" XDG_CACHE_HOME="" XDG_DATA_HOME="" _clear_webview_caches
assert_gone "linux: ~/.cache/$BID removed" "$H/.cache/$BID"
assert_gone "linux: data-dir WebKitCache removed" "$D/WebKitCache"
assert_gone "linux: data-dir CacheStorage removed" "$D/CacheStorage"
assert_gone "linux: data-dir serviceworkers removed" "$D/serviceworkers"
assert_present "linux: localstorage kept" "$D/localstorage"
assert_present "linux: indexeddb kept" "$D/indexeddb"
assert_present "linux: cookies kept" "$D/cookies.sqlite"
assert_present "linux: ~/.config/$BID kept" "$H/.config/$BID"
assert_present "linux: unrelated app cache kept" "$H/.cache/other.app"
# ── 3. Linux: XDG_CACHE_HOME / XDG_DATA_HOME overrides honored ──
H=$(mktemp -d -p "$_TMP_ROOT")
XDG=$(mktemp -d -p "$_TMP_ROOT")
mkdir -p "$XDG/cache/$BID" "$XDG/data/$BID/WebKitCache" "$XDG/data/$BID/localstorage" "$H/.cache/$BID"
HOME="$H" XDG_CACHE_HOME="$XDG/cache" XDG_DATA_HOME="$XDG/data" _clear_webview_caches
assert_gone "linux: XDG_CACHE_HOME/$BID removed" "$XDG/cache/$BID"
assert_gone "linux: XDG_DATA_HOME WebKitCache removed" "$XDG/data/$BID/WebKitCache"
assert_present "linux: XDG_DATA_HOME localstorage kept" "$XDG/data/$BID/localstorage"
assert_present "linux: ~/.cache/$BID kept under override" "$H/.cache/$BID"
# ── 4. Nothing to clear is a clean no-op ──
H=$(mktemp -d -p "$_TMP_ROOT")
uname() { echo Darwin; }
if HOME="$H" _clear_webview_caches; then
echo " PASS: empty HOME -> no-op exit 0"; PASS=$((PASS+1))
else
echo " FAIL: empty HOME -> nonzero exit"; FAIL=$((FAIL+1))
fi
# ── 5. Unknown OS is a no-op ──
H=$(mktemp -d -p "$_TMP_ROOT")
mkdir -p "$H/Library/Caches/$BID"
uname() { echo SunOS; }
HOME="$H" _clear_webview_caches
assert_present "unknown OS: nothing removed" "$H/Library/Caches/$BID"
echo ""
echo "Results: $PASS passed, $FAIL failed"
[ "$FAIL" = 0 ]