Step 1 — Unify preset logic (eliminate dual implementation)
- src/cli/preset.rs: add missing fields (chunk_limit, multi_thread_streams,
multi_thread_cutoff), fix Office buffer_size 64M→128M, implement FromStr
- src/web/api.rs: post_preset() now calls Preset::apply() — no more inlined
params; Office write_back unified to 5s (was 3s in API)
Step 2 — Fix setup.rs connection test: warn→bail
- All 4 "Warning: Could not connect/resolve" prints replaced with anyhow::bail!
matching deploy/setup.rs behavior
Step 3 — Web UI: add [web] and [notifications] edit sections
- templates/web/tabs/config.html: new collapsible Web UI (password) and
Notifications (webhook_url, cache_threshold_pct, nas_offline_minutes,
writeback_depth) sections, both tagged "No restart"
- Also adds [log] section (file path + level select, "Full restart")
Step 4 — Full cron expression support in warmup scheduler
- Cargo.toml: add cron = "0.12", chrono = "0.4"
- supervisor.rs: normalize_cron_schedule() converts 5-field standard cron to
7-field cron crate format; replaces naive hour-only matching
Step 5 — Adaptive bandwidth algorithm
- supervisor.rs: extract compute_adaptive_limit() pure function; sliding
window of 6 samples, cv>0.3→congested (−25%, floor 1MiB/s), stable
near-limit→maintain, under-utilizing→+10% (capped at limit_up)
Step 6 — warpgate update command
- src/cli/update.rs: query GitHub Releases API, compare with CARGO_PKG_VERSION
- src/main.rs: add Update{apply}, SetupWifi, CloneMac{interface} commands
- src/cli/wifi.rs: TODO stub for WiFi AP setup
Unit tests (+35, total 188→223)
- cli/preset.rs: 10 tests — FromStr, all fields for each preset, idempotency,
connection/share isolation, write_back consistency regression
- supervisor.rs: 14 tests — normalize_cron_schedule (5 cases),
compute_adaptive_limit (9 cases: congestion, floor, stable, under-utilizing,
cap, zero-current, zero-max, empty window)
- config.rs: 11 tests — WebConfig (3), NotificationsConfig (4), LogConfig (4)
Shell tests (+4 scripts)
- tests/09-cli/test-preset-cli.sh: preset CLI without daemon; checks all
three presets write correct values including unified buffer_size/write_back
- tests/09-cli/test-update-command.sh: update command; skips on no-network
- tests/10-scheduled/test-cron-warmup-schedule.sh: "* * * * *" fires in <90s
- tests/10-scheduled/test-adaptive-bandwidth.sh: adaptive loop stability
- tests/harness/config-gen.sh: add warmup.warmup_schedule override support
- tests/run-all.sh: add 10-scheduled category
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
260 lines
7.7 KiB
Bash
Executable File
260 lines
7.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Warpgate Integration Test — Config Generator
|
|
#
|
|
# Generates a config.toml pointing at the mock NAS for testing.
|
|
# Supports override parameters as key=value arguments.
|
|
#
|
|
# Usage:
|
|
# source config-gen.sh
|
|
# _gen_config # defaults
|
|
# _gen_config cache.max_size=10M # override one field
|
|
# _gen_config writeback.write_back=0s # instant write-back
|
|
|
|
set -euo pipefail
|
|
|
|
_gen_config() {
|
|
local config_file="${TEST_CONFIG:-$TEST_DIR/config.toml}"
|
|
|
|
# Defaults pointing at mock NAS
|
|
local conn_name="${TEST_CONN_NAME:-nas}"
|
|
local nas_host="${MOCK_NAS_IP:-10.99.0.2}"
|
|
local nas_user="root"
|
|
local nas_key_file="${TEST_SSH_KEY:-$TEST_DIR/test_key}"
|
|
local sftp_port="22"
|
|
local sftp_connections="4"
|
|
|
|
local cache_dir="${CACHE_DIR:-$TEST_DIR/cache}"
|
|
local cache_max_size="200G"
|
|
local cache_max_age="720h"
|
|
local cache_min_free="1G"
|
|
|
|
local read_chunk_size="16M"
|
|
local read_chunk_limit="64M"
|
|
local read_ahead="32M"
|
|
local buffer_size="16M"
|
|
|
|
local bw_limit_up="0"
|
|
local bw_limit_down="0"
|
|
local bw_adaptive="true"
|
|
|
|
local write_back="5s"
|
|
local transfers="4"
|
|
|
|
local dir_cache_time="5s"
|
|
|
|
local enable_smb="true"
|
|
local enable_nfs="false"
|
|
local enable_webdav="false"
|
|
local nfs_allowed_network="10.99.0.0/24"
|
|
local webdav_port="8080"
|
|
|
|
local warmup_auto="false"
|
|
local warmup_schedule=""
|
|
local warmup_rules=""
|
|
|
|
local smb_auth_enabled="false"
|
|
local smb_auth_username=""
|
|
local smb_auth_smb_pass=""
|
|
|
|
# Default share: single share at /
|
|
local share_name="${TEST_SHARE_NAME:-data}"
|
|
local share_remote_path="${TEST_SHARE_REMOTE_PATH:-/}"
|
|
local share_mount_point="${TEST_MOUNT:-$TEST_DIR/mnt}"
|
|
local shares_config=""
|
|
|
|
# Apply overrides
|
|
for override in "$@"; do
|
|
local key="${override%%=*}"
|
|
local value="${override#*=}"
|
|
|
|
case "$key" in
|
|
connection.name|conn_name) conn_name="$value" ;;
|
|
connection.nas_host|nas_host) nas_host="$value" ;;
|
|
connection.nas_user|nas_user) nas_user="$value" ;;
|
|
connection.nas_key_file|nas_key_file) nas_key_file="$value" ;;
|
|
connection.sftp_port|sftp_port) sftp_port="$value" ;;
|
|
connection.sftp_connections|sftp_connections) sftp_connections="$value" ;;
|
|
cache.dir|cache_dir) cache_dir="$value" ;;
|
|
cache.max_size|cache_max_size) cache_max_size="$value" ;;
|
|
cache.max_age|cache_max_age) cache_max_age="$value" ;;
|
|
cache.min_free|cache_min_free) cache_min_free="$value" ;;
|
|
read.chunk_size|read_chunk_size) read_chunk_size="$value" ;;
|
|
read.chunk_limit|read_chunk_limit) read_chunk_limit="$value" ;;
|
|
read.read_ahead|read_ahead) read_ahead="$value" ;;
|
|
read.buffer_size|buffer_size) buffer_size="$value" ;;
|
|
bandwidth.limit_up|bw_limit_up) bw_limit_up="$value" ;;
|
|
bandwidth.limit_down|bw_limit_down) bw_limit_down="$value" ;;
|
|
bandwidth.adaptive|bw_adaptive) bw_adaptive="$value" ;;
|
|
writeback.write_back|write_back) write_back="$value" ;;
|
|
writeback.transfers|transfers) transfers="$value" ;;
|
|
directory_cache.cache_time|dir_cache_time) dir_cache_time="$value" ;;
|
|
protocols.enable_smb|enable_smb) enable_smb="$value" ;;
|
|
protocols.enable_nfs|enable_nfs) enable_nfs="$value" ;;
|
|
protocols.enable_webdav|enable_webdav) enable_webdav="$value" ;;
|
|
protocols.nfs_allowed_network|nfs_allowed_network) nfs_allowed_network="$value" ;;
|
|
protocols.webdav_port|webdav_port) webdav_port="$value" ;;
|
|
warmup.auto|warmup_auto) warmup_auto="$value" ;;
|
|
warmup.warmup_schedule|warmup_schedule) warmup_schedule="$value" ;;
|
|
warmup.rules) warmup_rules="$value" ;;
|
|
smb_auth.enabled|smb_auth_enabled) smb_auth_enabled="$value" ;;
|
|
smb_auth.username|smb_auth_username) smb_auth_username="$value" ;;
|
|
smb_auth.smb_pass|smb_auth_smb_pass) smb_auth_smb_pass="$value" ;;
|
|
share.name|share_name) share_name="$value" ;;
|
|
share.remote_path|share_remote_path) share_remote_path="$value" ;;
|
|
share.mount_point|share_mount_point) share_mount_point="$value" ;;
|
|
shares) shares_config="$value" ;;
|
|
*) echo "WARNING: unknown config override: $key" >&2 ;;
|
|
esac
|
|
done
|
|
|
|
cat > "$config_file" <<CONFIG_EOF
|
|
[[connections]]
|
|
name = "$conn_name"
|
|
nas_host = "$nas_host"
|
|
nas_user = "$nas_user"
|
|
nas_key_file = "$nas_key_file"
|
|
sftp_port = $sftp_port
|
|
sftp_connections = $sftp_connections
|
|
|
|
[cache]
|
|
dir = "$cache_dir"
|
|
max_size = "$cache_max_size"
|
|
max_age = "$cache_max_age"
|
|
min_free = "$cache_min_free"
|
|
|
|
[read]
|
|
chunk_size = "$read_chunk_size"
|
|
chunk_limit = "$read_chunk_limit"
|
|
read_ahead = "$read_ahead"
|
|
buffer_size = "$buffer_size"
|
|
|
|
[bandwidth]
|
|
limit_up = "$bw_limit_up"
|
|
limit_down = "$bw_limit_down"
|
|
adaptive = $bw_adaptive
|
|
|
|
[writeback]
|
|
write_back = "$write_back"
|
|
transfers = $transfers
|
|
|
|
[directory_cache]
|
|
cache_time = "$dir_cache_time"
|
|
|
|
[protocols]
|
|
enable_smb = $enable_smb
|
|
enable_nfs = $enable_nfs
|
|
enable_webdav = $enable_webdav
|
|
nfs_allowed_network = "$nfs_allowed_network"
|
|
webdav_port = $webdav_port
|
|
|
|
[warmup]
|
|
auto = $warmup_auto
|
|
CONFIG_EOF
|
|
|
|
# Append warmup_schedule if set
|
|
if [[ -n "$warmup_schedule" ]]; then
|
|
echo "warmup_schedule = \"$warmup_schedule\"" >> "$config_file"
|
|
fi
|
|
|
|
# Append smb_auth section if enabled
|
|
if [[ "$smb_auth_enabled" == "true" ]]; then
|
|
cat >> "$config_file" <<SMB_AUTH_EOF
|
|
|
|
[smb_auth]
|
|
enabled = true
|
|
SMB_AUTH_EOF
|
|
if [[ -n "$smb_auth_username" ]]; then
|
|
echo "username = \"$smb_auth_username\"" >> "$config_file"
|
|
fi
|
|
if [[ -n "$smb_auth_smb_pass" ]]; then
|
|
echo "smb_pass = \"$smb_auth_smb_pass\"" >> "$config_file"
|
|
fi
|
|
fi
|
|
|
|
# Append shares config — use override or default single share
|
|
if [[ -n "$shares_config" ]]; then
|
|
echo "" >> "$config_file"
|
|
echo "$shares_config" >> "$config_file"
|
|
else
|
|
cat >> "$config_file" <<SHARES_EOF
|
|
|
|
[[shares]]
|
|
name = "$share_name"
|
|
connection = "$conn_name"
|
|
remote_path = "$share_remote_path"
|
|
mount_point = "$share_mount_point"
|
|
SHARES_EOF
|
|
fi
|
|
|
|
# Append warmup rules if specified
|
|
if [[ -n "$warmup_rules" ]]; then
|
|
echo "" >> "$config_file"
|
|
echo "$warmup_rules" >> "$config_file"
|
|
fi
|
|
|
|
export TEST_CONFIG="$config_file"
|
|
}
|
|
|
|
# Generate a minimal config (only required fields)
|
|
_gen_minimal_config() {
|
|
local config_file="${TEST_CONFIG:-$TEST_DIR/config.toml}"
|
|
local conn_name="${TEST_CONN_NAME:-nas}"
|
|
|
|
cat > "$config_file" <<CONFIG_EOF
|
|
[[connections]]
|
|
name = "$conn_name"
|
|
nas_host = "${MOCK_NAS_IP:-10.99.0.2}"
|
|
nas_user = "root"
|
|
nas_key_file = "${TEST_SSH_KEY:-$TEST_DIR/test_key}"
|
|
|
|
[cache]
|
|
dir = "${CACHE_DIR:-$TEST_DIR/cache}"
|
|
|
|
[[shares]]
|
|
name = "data"
|
|
connection = "$conn_name"
|
|
remote_path = "/"
|
|
mount_point = "${TEST_MOUNT:-$TEST_DIR/mnt}"
|
|
CONFIG_EOF
|
|
|
|
export TEST_CONFIG="$config_file"
|
|
}
|
|
|
|
# Generate an intentionally broken config
|
|
_gen_broken_config() {
|
|
local config_file="${TEST_CONFIG:-$TEST_DIR/config.toml}"
|
|
local type="${1:-missing_field}"
|
|
|
|
case "$type" in
|
|
missing_field)
|
|
# Missing nas_host
|
|
cat > "$config_file" <<CONFIG_EOF
|
|
[[connections]]
|
|
name = "nas"
|
|
nas_user = "root"
|
|
|
|
[cache]
|
|
dir = "/tmp/cache"
|
|
|
|
[[shares]]
|
|
name = "data"
|
|
connection = "nas"
|
|
remote_path = "/"
|
|
mount_point = "/tmp/mnt"
|
|
CONFIG_EOF
|
|
;;
|
|
bad_toml)
|
|
cat > "$config_file" <<CONFIG_EOF
|
|
[[connections
|
|
name = "broken toml
|
|
CONFIG_EOF
|
|
;;
|
|
*)
|
|
echo "Unknown broken config type: $type" >&2
|
|
return 1
|
|
;;
|
|
esac
|
|
|
|
export TEST_CONFIG="$config_file"
|
|
}
|