Files
Loki/internal/ajean/sys_network_test.go
T
nathaninline 52baab5786 v0.8.4 : l'historique s'exporte, le moteur se laisse joindre, les modeles en plusieurs fichiers marchent
Trois retours d'utilisateurs apres la 0.8.3.

Export de la conversation (regression de la 0.8 : conversation.json a
disparu dans ajean.db, verrouille et binaire). Bouton dans l'UI +
commande 'ajean export [--json] [fichier]', endpoint /api/chat/export.

Ecoute reseau du moteur : interrupteur 'joignable depuis le reseau local'
dans le panneau Acces OpenAI (HOST + regle de pare-feu Windows), commande
'ajean network [on|off|status]'. HOST devient un reglage de machine
preserve au changement de preset.

Modeles GGUF decoupes en tranches -00001-of-000NN : une famille = un
modele. Telechargement de toutes les tranches depuis n'importe quel lien,
sonde d'espace disque sur le total, liste et suppression regroupees,
demarrage refuse avec le nom du fichier manquant.
2026-08-08 20:01:54 +02:00

107 lines
3.1 KiB
Go

package ajean
import (
"encoding/json"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
)
func TestEngineHostDefautEtBascule(t *testing.T) {
testHome(t)
// Clé absente : c'est le défaut de backend_serve.go qui s'applique, soit toutes
// les interfaces. Annoncer « fermé » ici serait un mensonge.
if h := engineHost(); h != hostAllInterfaces {
t.Fatalf("HOST absent → %q ; attendu %q", h, hostAllInterfaces)
}
if !lanExposed() {
t.Fatal("HOST absent devrait compter comme exposé")
}
if _, err := setLANExposure(false); err != nil {
t.Fatal(err)
}
if lanExposed() || ReadConfig()["HOST"] != hostLocalOnly {
t.Fatalf("fermeture sans effet : HOST=%q", ReadConfig()["HOST"])
}
if _, err := setLANExposure(true); err != nil {
t.Fatal(err)
}
if !lanExposed() || ReadConfig()["HOST"] != hostAllInterfaces {
t.Fatalf("ouverture sans effet : HOST=%q", ReadConfig()["HOST"])
}
}
// « localhost » écrit à la main vaut boucle locale, au même titre que 127.0.0.1.
func TestLanExposedReconnaitLocalhost(t *testing.T) {
testHome(t)
for _, h := range []string{"127.0.0.1", "localhost", "::1", "LOCALHOST"} {
if err := SetConfigKey("HOST", h); err != nil {
t.Fatal(err)
}
if lanExposed() {
t.Errorf("HOST=%q compté comme exposé", h)
}
}
for _, h := range []string{"0.0.0.0", "192.168.1.25", "::"} {
if err := SetConfigKey("HOST", h); err != nil {
t.Fatal(err)
}
if !lanExposed() {
t.Errorf("HOST=%q compté comme fermé", h)
}
}
}
// Une machine volontairement fermée ne doit pas se rouvrir toute seule parce
// qu'on bascule sur un preset écrit avant que HOST existe.
func TestHostSurvitAuChangementDePreset(t *testing.T) {
testHome(t)
if _, err := setLANExposure(false); err != nil {
t.Fatal(err)
}
p := filepath.Join(t.TempDir(), "vieux.env")
if err := os.WriteFile(p, []byte("MODEL=\"x.gguf\"\nCTX=4096\n"), 0o644); err != nil {
t.Fatal(err)
}
if err := applyPresetFile(p); err != nil {
t.Fatal(err)
}
if ReadConfig()["HOST"] != hostLocalOnly {
t.Fatalf("HOST perdu à la bascule : %q", ReadConfig()["HOST"])
}
// Mais un preset qui revendique HOST garde le dernier mot.
if err := os.WriteFile(p, []byte("MODEL=\"x.gguf\"\nHOST=\"0.0.0.0\"\n"), 0o644); err != nil {
t.Fatal(err)
}
if err := applyPresetFile(p); err != nil {
t.Fatal(err)
}
if ReadConfig()["HOST"] != hostAllInterfaces {
t.Fatalf("le preset n'a pas pu imposer HOST : %q", ReadConfig()["HOST"])
}
}
func TestHandleNetwork(t *testing.T) {
testHome(t)
rr := httptest.NewRecorder()
handleNetwork(rr, httptest.NewRequest("POST", "/api/network", strings.NewReader(`{"exposed":false}`)))
if rr.Code != 200 {
t.Fatalf("HTTP %d : %s", rr.Code, rr.Body)
}
var out struct {
OK bool `json:"ok"`
Status netStatus `json:"status"`
}
if err := json.Unmarshal(rr.Body.Bytes(), &out); err != nil {
t.Fatal(err)
}
if !out.OK || out.Status.Exposed || out.Status.Host != hostLocalOnly {
t.Fatalf("état inattendu : %+v", out.Status)
}
if out.Status.Port == 0 || !strings.Contains(out.Status.URL, "/v1") {
t.Fatalf("endpoint mal formé : %+v", out.Status)
}
}