1
0
mirror of https://github.com/tw93/Mole.git synced 2026-03-22 16:10:08 +00:00

feat: add JSON output tests and README docs for analyze and status (#556)

* feat: add JSON output tests and README docs for analyze and status

Add 7 BATS tests covering `--json` output for `mo analyze` and `mo status`:
- schema structure
- field types
- pipe auto-detection.

Also document the `--json` flag in a new "Machine-Readable Output" README section, including the auto-detection behavior when piped.

* chore: use waitgroup go in status collector

---------

Co-authored-by: Tw93 <hitw93@gmail.com>
This commit is contained in:
Dylan Joss
2026-03-12 20:40:41 -07:00
committed by GitHub
parent cce26022f3
commit 7350547458
3 changed files with 179 additions and 4 deletions

View File

@@ -210,6 +210,42 @@ Health score is based on CPU, memory, disk, temperature, and I/O load, with colo
Shortcuts: In `mo status`, press `k` to toggle the cat and save the preference, and `q` to quit.
#### Machine-Readable Output
Both `mo analyze` and `mo status` support a `--json` flag for scripting and automation.
`mo status` also auto-detects when its output is piped (not a terminal) and switches to JSON automatically.
```bash
# Disk analysis as JSON
$ mo analyze --json ~/Documents
{
"path": "/Users/you/Documents",
"entries": [
{ "name": "Library", "path": "...", "size": 80939438080, "is_dir": true },
...
],
"total_size": 168393441280,
"total_files": 42187
}
# System status as JSON
$ mo status --json
{
"host": "MacBook-Pro",
"health_score": 92,
"cpu": { "usage": 45.2, "logical_cpu": 8, ... },
"memory": { "total": 25769803776, "used": 15049334784, "used_percent": 58.4 },
"disks": [ ... ],
"uptime": "3d 12h 45m",
...
}
# Auto-detected JSON when piped
$ mo status | jq '.health_score'
92
```
### Project Artifact Purge
Clean old build artifacts such as `node_modules`, `target`, `build`, and `dist` to free up disk space.

View File

@@ -255,9 +255,7 @@ func (c *Collector) Collect() (MetricsSnapshot, error) {
// Helper to launch concurrent collection.
collect := func(fn func() error) {
wg.Add(1)
go func() {
defer wg.Done()
wg.Go(func() {
defer func() {
if r := recover(); r != nil {
errMu.Lock()
@@ -279,7 +277,7 @@ func (c *Collector) Collect() (MetricsSnapshot, error) {
}
errMu.Unlock()
}
}()
})
}
// Launch independent collection tasks.

View File

@@ -11,6 +11,19 @@ setup_file() {
export HOME
mkdir -p "$HOME"
# Build Go binaries from current source for JSON tests.
# Point GOPATH/GOMODCACHE at the real home so go build doesn't write
# module caches into the fake HOME under tests/.
if command -v go > /dev/null 2>&1; then
ANALYZE_BIN="$(mktemp "${TMPDIR:-/tmp}/analyze-go.XXXXXX")"
STATUS_BIN="$(mktemp "${TMPDIR:-/tmp}/status-go.XXXXXX")"
GOPATH="${ORIGINAL_HOME}/go" GOMODCACHE="${ORIGINAL_HOME}/go/pkg/mod" \
go build -o "$ANALYZE_BIN" "$PROJECT_ROOT/cmd/analyze" 2>/dev/null
GOPATH="${ORIGINAL_HOME}/go" GOMODCACHE="${ORIGINAL_HOME}/go/pkg/mod" \
go build -o "$STATUS_BIN" "$PROJECT_ROOT/cmd/status" 2>/dev/null
export ANALYZE_BIN STATUS_BIN
fi
}
teardown_file() {
@@ -19,6 +32,7 @@ teardown_file() {
if [[ -n "${ORIGINAL_HOME:-}" ]]; then
export HOME="$ORIGINAL_HOME"
fi
rm -f "${ANALYZE_BIN:-}" "${STATUS_BIN:-}"
}
create_fake_utils() {
@@ -278,3 +292,130 @@ EOF
run grep "pam_tid.so" "$pam_file"
[ "$status" -ne 0 ]
}
# --- JSON output mode tests ---
@test "mo analyze --json outputs valid JSON with expected fields" {
if [[ ! -x "${ANALYZE_BIN:-}" ]]; then
skip "analyze binary not available (go not installed?)"
fi
run "$ANALYZE_BIN" --json /tmp
[ "$status" -eq 0 ]
# Validate it is parseable JSON
echo "$output" | python3 -c "import sys, json; json.load(sys.stdin)"
# Check required top-level keys
echo "$output" | python3 -c "
import sys, json
data = json.load(sys.stdin)
assert 'path' in data, 'missing path'
assert 'entries' in data, 'missing entries'
assert 'total_size' in data, 'missing total_size'
assert 'total_files' in data, 'missing total_files'
assert isinstance(data['entries'], list), 'entries is not a list'
"
}
@test "mo analyze --json entries contain required fields" {
if [[ ! -x "${ANALYZE_BIN:-}" ]]; then
skip "analyze binary not available (go not installed?)"
fi
run "$ANALYZE_BIN" --json /tmp
[ "$status" -eq 0 ]
echo "$output" | python3 -c "
import sys, json
data = json.load(sys.stdin)
for entry in data['entries']:
assert 'name' in entry, 'entry missing name'
assert 'path' in entry, 'entry missing path'
assert 'size' in entry, 'entry missing size'
assert 'is_dir' in entry, 'entry missing is_dir'
"
}
@test "mo analyze --json path reflects target directory" {
if [[ ! -x "${ANALYZE_BIN:-}" ]]; then
skip "analyze binary not available (go not installed?)"
fi
run "$ANALYZE_BIN" --json /tmp
[ "$status" -eq 0 ]
echo "$output" | python3 -c "
import sys, json
data = json.load(sys.stdin)
assert data['path'] == '/tmp' or data['path'] == '/private/tmp', \
f\"unexpected path: {data['path']}\"
"
}
@test "mo status --json outputs valid JSON with expected fields" {
if [[ ! -x "${STATUS_BIN:-}" ]]; then
skip "status binary not available (go not installed?)"
fi
run "$STATUS_BIN" --json
[ "$status" -eq 0 ]
# Validate it is parseable JSON
echo "$output" | python3 -c "import sys, json; json.load(sys.stdin)"
# Check required top-level keys
echo "$output" | python3 -c "
import sys, json
data = json.load(sys.stdin)
for key in ['cpu', 'memory', 'disks', 'health_score', 'host', 'uptime']:
assert key in data, f'missing key: {key}'
"
}
@test "mo status --json cpu section has expected structure" {
if [[ ! -x "${STATUS_BIN:-}" ]]; then
skip "status binary not available (go not installed?)"
fi
run "$STATUS_BIN" --json
[ "$status" -eq 0 ]
echo "$output" | python3 -c "
import sys, json
data = json.load(sys.stdin)
cpu = data['cpu']
assert 'usage' in cpu, 'cpu missing usage'
assert 'logical_cpu' in cpu, 'cpu missing logical_cpu'
assert isinstance(cpu['usage'], (int, float)), 'cpu usage is not a number'
"
}
@test "mo status --json memory section has expected structure" {
if [[ ! -x "${STATUS_BIN:-}" ]]; then
skip "status binary not available (go not installed?)"
fi
run "$STATUS_BIN" --json
[ "$status" -eq 0 ]
echo "$output" | python3 -c "
import sys, json
data = json.load(sys.stdin)
mem = data['memory']
assert 'total' in mem, 'memory missing total'
assert 'used' in mem, 'memory missing used'
assert 'used_percent' in mem, 'memory missing used_percent'
assert mem['total'] > 0, 'memory total should be positive'
"
}
@test "mo status --json piped to stdout auto-detects JSON mode" {
if [[ ! -x "${STATUS_BIN:-}" ]]; then
skip "status binary not available (go not installed?)"
fi
# When piped (not a tty), status should auto-detect and output JSON
output=$("$STATUS_BIN" 2>/dev/null)
echo "$output" | python3 -c "import sys, json; json.load(sys.stdin)"
}