feat(ml): auto-commit con 14 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
package ml
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestSdcliResolveBinary_NotFound verifica que SdcliResolveBinary retorna error
|
||||
// cuando no hay binario en PATH ni hint. Forzamos PATH="" para que LookPath
|
||||
// no encuentre nada, lo que hace el test determinista independientemente del
|
||||
// entorno del desarrollador.
|
||||
func TestSdcliResolveBinary_NotFound(t *testing.T) {
|
||||
t.Setenv("PATH", "")
|
||||
_, err := SdcliResolveBinary("")
|
||||
if err == nil {
|
||||
t.Fatal("expected error when sd not in PATH, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
// TestSdcliResolveBinary_Hint verifica que un hint valido (archivo ejecutable)
|
||||
// se resuelve con Source="config" sin necesidad de PATH.
|
||||
func TestSdcliResolveBinary_Hint(t *testing.T) {
|
||||
// Crear archivo temporal ejecutable que simula el binario sd.
|
||||
// El script simplemente sale con 0; --version devolvera string vacio
|
||||
// pero eso no es error (version es best-effort).
|
||||
f, err := os.CreateTemp("", "sd-test-*")
|
||||
if err != nil {
|
||||
t.Fatalf("creating temp file: %v", err)
|
||||
}
|
||||
defer os.Remove(f.Name())
|
||||
|
||||
f.Close()
|
||||
|
||||
script := []byte("#!/bin/sh\necho 'sd-test 0.1'\n")
|
||||
if err := os.WriteFile(f.Name(), script, 0o755); err != nil {
|
||||
t.Fatalf("writing temp file: %v", err)
|
||||
}
|
||||
if err := os.Chmod(f.Name(), 0o755); err != nil {
|
||||
t.Fatalf("chmod temp file: %v", err)
|
||||
}
|
||||
|
||||
bin, err := SdcliResolveBinary(f.Name())
|
||||
if err != nil {
|
||||
t.Fatalf("SdcliResolveBinary(hint): %v", err)
|
||||
}
|
||||
if bin.Source != "config" {
|
||||
t.Fatalf("expected source=config, got %q", bin.Source)
|
||||
}
|
||||
if bin.Path != f.Name() {
|
||||
t.Fatalf("expected path=%q, got %q", f.Name(), bin.Path)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSdcliGenerate_RequiresBinary es un test de integracion que salta si el
|
||||
// binario sd no esta instalado en PATH. Si esta disponible, tambien requiere
|
||||
// el modelo SD Turbo en el vault para ejecutar una generacion real.
|
||||
func TestSdcliGenerate_RequiresBinary(t *testing.T) {
|
||||
bin, err := SdcliResolveBinary("")
|
||||
if err != nil {
|
||||
t.Skipf("sd binary not in PATH, skipping integration test: %v", err)
|
||||
}
|
||||
|
||||
modelPath := "/home/lucas/vaults/imagegen_models/diffusers/sd-turbo/sd_turbo.safetensors"
|
||||
if _, err := os.Stat(modelPath); err != nil {
|
||||
t.Skipf("SD Turbo model not in vault (%s), skipping: %v", modelPath, err)
|
||||
}
|
||||
|
||||
cfg := GenerationConfig{
|
||||
Prompt: "a red apple",
|
||||
Seed: 42,
|
||||
Steps: 4,
|
||||
CfgScale: 1.0,
|
||||
Sampler: "euler_a",
|
||||
Width: 512,
|
||||
Height: 512,
|
||||
Model: ModelRef{
|
||||
Name: "sd-turbo",
|
||||
ModelType: "sd15",
|
||||
Quantization: "fp16",
|
||||
Path: modelPath,
|
||||
},
|
||||
}
|
||||
|
||||
outPath := t.TempDir() + "/out.png"
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var progressCalled bool
|
||||
res, err := SdcliGenerate(ctx, bin, cfg, outPath, func(p SdcliProgress) {
|
||||
progressCalled = true
|
||||
t.Logf("progress: step %d/%d (%.1f%%) %.2fit/s",
|
||||
p.Step, p.TotalSteps, p.Percent, p.ItPerSec)
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("SdcliGenerate: %v", err)
|
||||
}
|
||||
if len(res.ImageBytes) == 0 {
|
||||
t.Fatal("expected non-empty image bytes")
|
||||
}
|
||||
if res.Format != "png" {
|
||||
t.Fatalf("expected format=png, got %q", res.Format)
|
||||
}
|
||||
if res.DurationMs <= 0 {
|
||||
t.Fatalf("expected positive duration_ms, got %d", res.DurationMs)
|
||||
}
|
||||
if res.Meta["backend"] != "sdcli" {
|
||||
t.Fatalf("expected meta.backend=sdcli, got %v", res.Meta["backend"])
|
||||
}
|
||||
t.Logf("generated %d bytes in %dms (progress_called=%v)",
|
||||
len(res.ImageBytes), res.DurationMs, progressCalled)
|
||||
}
|
||||
Reference in New Issue
Block a user