#!/bin/sh # fs-label-test.sh — `takana fs-label` contra un ext4 DE VERDAD. # # ── POR QUÉ NO ALCANZAN LOS TESTS DE UNIDAD ──────────────────────────────────────────────────── # Los de `fs_label.rs` trabajan sobre un superbloque sintético, y por eso no traían `metadata_csum` # — el flag que obliga a recalcular el crc32c. Con el cálculo mal, esos tests seguían verdes y # `e2fsck` decía «Superblock checksum does not match» sobre un filesystem perfecto. Medido el # 2026-10-02: el error era el complemento final del crc, que la convención de «crc32c de una # cadena» lleva y ext4 no. # # Acá se arma un ext4 real, se le cambia la etiqueta y se le pregunta a `e2fsck`. Es la única forma # de saber que el checksum quedó bien, porque el único que lo valida es quien lo valida de verdad. # # sh scripts/fs-label-test.sh set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT" for h in mke2fs e2fsck dumpe2fs; do command -v "$h" >/dev/null 2>&1 || { echo "falta $h (e2fsprogs): no puedo probar esto" >&2; exit 2; } done TAKANA="${TAKANA:-$ROOT/target/release/takana}" [ -x "$TAKANA" ] || TAKANA="$ROOT/target/debug/takana" [ -x "$TAKANA" ] || { echo "no hay binario takana (cargo build -p takana-cli)" >&2; exit 2; } T="${TMPDIR:-/var/tmp}/fs-label-test.$$"; rm -rf "$T"; mkdir -p "$T/arbol/etc" trap 'rm -rf "$T"' EXIT echo contenido > "$T/arbol/etc/algo" OK=0; MAL=0 ok() { OK=$((OK+1)); printf ' ✓ %s\n' "$1"; } mal() { MAL=$((MAL+1)); printf ' ✗ %s\n' "$1"; } armar() { rm -f "$T/fs.img"; truncate -s 64M "$T/fs.img" mke2fs -q -t ext4 -L "antes" -d "$T/arbol" "$T/fs.img"; } # ⚠ El rótulo es «Filesystem volume name», no «Volume name»: con el patrón corto el lector devolvía # vacío SIEMPRE y el banco acusaba al código por no haber sabido mirar. Por eso el caso 3 empieza # leyendo la etiqueta vieja — si el lector no la ve, el que está roto es el lector. etiqueta() { dumpe2fs -h "$T/fs.img" 2>/dev/null | sed -n 's/^Filesystem volume name: *//p'; } fsck_limpio() { e2fsck -fn "$T/fs.img" 2>&1 | grep -qi "checksum does not match" && return 1 || return 0; } echo "== 1. el ext4 de prueba trae metadata_csum (si no, este banco no prueba nada) ==" armar if dumpe2fs -h "$T/fs.img" 2>/dev/null | grep -q "metadata_csum"; then ok "trae metadata_csum: el checksum del superbloque está en juego" else mal "este mke2fs NO pone metadata_csum: el banco no puede ver el defecto que busca" fi echo "== 2. el brazo de control: antes de tocar nada, e2fsck está contento ==" fsck_limpio && ok "el filesystem recién hecho pasa e2fsck" || mal "ya venía roto: el banco no sirve" echo "== 3. la etiqueta se cambia ==" # El control del instrumento, antes de usarlo: si no sabe leer la etiqueta que mke2fs acaba de # poner, cualquier veredicto suyo sobre la nueva no significa nada. [ "$(etiqueta)" = "antes" ] && ok "control: el lector ve la etiqueta que puso mke2fs" \ || mal "control: el lector NO ve la etiqueta original (leyó «$(etiqueta)»): el banco es ciego" "$TAKANA" fs-label "$T/fs.img" hammer-root >/dev/null [ "$(etiqueta)" = "hammer-root" ] && ok "dumpe2fs lee «hammer-root»" || mal "la etiqueta quedó en «$(etiqueta)»" echo "== 4. y el superbloque SIGUE VÁLIDO ==" # Ésta es la comprobación entera. Sin ella, el banco diría que todo anda con un filesystem que el # kernel monta de sólo lectura. fsck_limpio && ok "e2fsck no se queja del checksum" \ || mal "e2fsck: $(e2fsck -fn "$T/fs.img" 2>&1 | grep -i checksum | head -1)" echo "== 5. los datos no se tocaron ==" debugfs -R "ls /etc" "$T/fs.img" 2>/dev/null | grep -q algo \ && ok "el contenido sigue ahí" || mal "se perdió el contenido" echo "== 6. donde no hay superbloque, no se escribe ==" rm -f "$T/basura.img"; head -c 4096 /dev/zero > "$T/basura.img" ANTES=$(sha256sum "$T/basura.img" | cut -d' ' -f1) "$TAKANA" fs-label "$T/basura.img" hammer-root >/dev/null 2>&1 && mal "aceptó un fichero sin ext" || ok "rechaza lo que no es ext" [ "$(sha256sum "$T/basura.img" | cut -d' ' -f1)" = "$ANTES" ] && ok "y no lo tocó" || mal "escribió igual" echo printf '%d bien · %d mal\n' "$OK" "$MAL" [ "$MAL" = "0" ] || exit 1