#!/usr/bin/env bash
# run-tests.sh — test suite untuk proyek server file lokal.
# Suite menyiapkan folder kerja terisolasi (mktemp), lalu menguji:
# struktur share hasil deploy/buat-struktur.sh (folder, mode, fixture
# group), directive wajib pada config/smb.conf dan config/exports
# lewat deploy/verifikasi-share.sh, entri config/fstab-share, pewarisan
# setgid pada folder share, serta penolakan tulis pada file read-only.
# Jalankan dari mana saja: bash tests/run-tests.sh

set -u

SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
PROJ_DIR=$(dirname "$SCRIPT_DIR")

PASS=0
FAIL=0
WORK=""

# assert_eq <harapan> <nyata> <pesan>: bandingkan dua nilai.
assert_eq() {
    if [ "$1" = "$2" ]; then
        PASS=$((PASS + 1))
        printf 'OK    %s\n' "$3"
    else
        FAIL=$((FAIL + 1))
        printf 'GAGAL %s: harapan %s, nyata %s\n' "$3" "$1" "$2"
    fi
}

bersihkan() {
    if [ -n "$WORK" ]; then
        rm -rf "$WORK"
    fi
}
trap bersihkan EXIT

WORK=$(mktemp -d)
cd "$WORK" || exit 1

# --- uji 1: buat-struktur.sh membangun struktur yang sesuai ---------------
bash "$PROJ_DIR/deploy/buat-struktur.sh" latihan > /dev/null 2>&1
assert_eq 0 "$?" "buat-struktur.sh keluar 0"
for nama in dokumen media backup; do
    [ -d "latihan/share/$nama" ]
    assert_eq 0 "$?" "share $nama dibuat"
done
assert_eq 2770 "$(stat -c '%a' latihan/share/dokumen)" \
    "mode dokumen 2770"
assert_eq 2775 "$(stat -c '%a' latihan/share/media)" \
    "mode media 2775"
assert_eq 2770 "$(stat -c '%a' latihan/share/backup)" \
    "mode backup 2770"

# --- uji 2: fixture group tercatat, skrip idempoten ------------------------
grep -q '^keluarga:x:1100:budi,siti$' latihan/etc/group
assert_eq 0 "$?" "fixture group memuat keluarga:budi,siti"
grep -q '^tamu:x:1101:tamu1$' latihan/etc/group
assert_eq 0 "$?" "fixture group memuat tamu"
bash "$PROJ_DIR/deploy/buat-struktur.sh" latihan > /dev/null 2>&1
assert_eq 0 "$?" "buat-struktur.sh idempoten (dijalankan dua kali)"

# --- uji 3: konfigurasi bawaan lolos verifikasi-share.sh -------------------
bash "$PROJ_DIR/deploy/verifikasi-share.sh" "$PROJ_DIR/config" \
    > /dev/null 2>&1
assert_eq 0 "$?" "config/ lolos verifikasi-share.sh"

# --- uji 4: konfigurasi rusak tertangkap -----------------------------------
mkdir -p rusak
printf '[global]\n[dokumen]\npath = /srv/share/dokumen\nread only = no\n' \
    > rusak/smb.conf
printf '/srv/share/dokumen  192.0.2.0/24(rw,async)\n' > rusak/exports
bash "$PROJ_DIR/deploy/verifikasi-share.sh" rusak > /dev/null 2>&1
if [ "$?" -gt 0 ]; then
    PASS=$((PASS + 1))
    printf 'OK    konfigurasi rusak tertangkap (exit bukan 0)\n'
else
    FAIL=$((FAIL + 1))
    printf 'GAGAL konfigurasi rusak tertangkap: verifikasi-share.sh keluar 0\n'
fi

# --- uji 5: entri fstab-share memuat nofail dan enam field -----------------
grep -q 'nofail' "$PROJ_DIR/config/fstab-share"
assert_eq 0 "$?" "fstab-share memuat nofail"
jumlah=$(awk '!/^[[:space:]]*#/ && NF { print NF }' \
    "$PROJ_DIR/config/fstab-share" | sort -u)
assert_eq 6 "$jumlah" "entri fstab-share berisi enam field"
mnt=$(awk '$2 == "/srv/share" { print $2 }' "$PROJ_DIR/config/fstab-share")
assert_eq "/srv/share" "$mnt" "mountpoint fstab-share /srv/share"

# --- uji 6: setgid diwarisi oleh isi baru folder share ---------------------
mkdir -p latihan/share/dokumen/laporan
touch latihan/share/dokumen/laporan/catatan.txt
assert_eq "$(stat -c '%G' latihan/share/dokumen)" \
    "$(stat -c '%G' latihan/share/dokumen/laporan/catatan.txt)" \
    "file baru mewarisi group folder share"
mode_sub=$(stat -c '%a' latihan/share/dokumen/laporan)
if [ "$(( 8#$mode_sub & 8#2000 ))" -ne 0 ]; then
    PASS=$((PASS + 1))
    printf 'OK    folder baru mewarisi bit setgid (%s)\n' "$mode_sub"
else
    FAIL=$((FAIL + 1))
    printf 'GAGAL folder baru mewarisi bit setgid: mode %s tanpa bit 2000\n' \
        "$mode_sub"
fi

# --- uji 7: tulis ditolak pada file read-only ------------------------------
printf 'isi awal\n' > latihan/kunci.txt
chmod 444 latihan/kunci.txt
if (echo 'tambahan' >> latihan/kunci.txt) 2> /dev/null; then
    FAIL=$((FAIL + 1))
    printf 'GAGAL tulis ke file ro ditolak: append justru berhasil\n'
else
    PASS=$((PASS + 1))
    printf 'OK    tulis ke file ro ditolak\n'
fi
assert_eq 'isi awal' "$(cat latihan/kunci.txt)" "isi file ro tidak berubah"
chmod 644 latihan/kunci.txt
echo 'tambahan' >> latihan/kunci.txt
assert_eq 0 "$?" "tulis diizinkan kembali setelah mode rw"

# --- ringkasan ----------------------------------------------------------------
if [ "$FAIL" -eq 0 ]; then
    printf 'PASSED: %d/%d test lulus\n' "$PASS" "$PASS"
else
    printf 'FAILED: %d/%d test lulus\n' "$PASS" "$((PASS + FAIL))"
fi
[ "$FAIL" -eq 0 ]
