mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-11 17:26:57 +02:00
- module github.com/R0m1k3/Loki, cmd/loki, internal/loki (package loki) - LOKI_HOME, LOKI_MODEL_DIRS, LOKI_SERVICE, LOKI_DL_CONNS ; /etc/loki ; units loki-engine / loki-ui ; binaire et aide CLI - updateRepo pointe sur R0m1k3/Loki (l'auto-update ne tirera plus les binaires AJEAN amont) Conservé à l'identique : le domaine ajean.link (service de tunnel amont), les littéraux de migration 0.7.x (migrate_07.go), RELEASE_NOTES.md et LICENSE (historique et licence de l'amont). go build/vet/test : verts.
139 lines
4.6 KiB
Go
139 lines
4.6 KiB
Go
//go:build windows
|
|
|
|
package loki
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"testing"
|
|
)
|
|
|
|
// binaryVersion pilote la mise à jour automatique du binaire installé quand on
|
|
// lance le fichier téléchargé : si elle renvoie du vide, plus aucune mise à jour
|
|
// n'a lieu, et en silence. C'est exactement ce qui arrivait avec la première
|
|
// implémentation (exécuter `loki version`, dont la sortie est vide pour un
|
|
// binaire en sous-système GUI). D'où ces tests sur la plomberie syscall.
|
|
func TestBinaryVersionReadsResource(t *testing.T) {
|
|
// kernel32.dll porte toujours une ressource de version.
|
|
dll := filepath.Join(os.Getenv("SystemRoot"), "System32", "kernel32.dll")
|
|
if _, err := os.Stat(dll); err != nil {
|
|
t.Skip("kernel32.dll introuvable")
|
|
}
|
|
v := binaryVersion(dll)
|
|
if !regexp.MustCompile(`^\d+\.\d+\.\d+$`).MatchString(v) {
|
|
t.Fatalf("binaryVersion(kernel32.dll) = %q, attendu une version x.y.z", v)
|
|
}
|
|
}
|
|
|
|
// Sur une machine vierge, le dossier bin n'existe pas encore : installSelf doit
|
|
// le créer. Sans ça, le premier lancement échouait sur « open
|
|
// C:\ProgramData\loki\bin\loki.exe: The system cannot find the path specified »
|
|
// et Loki ne s'installait jamais.
|
|
func TestInstallSelfCreatesBinDir(t *testing.T) {
|
|
binDir := filepath.Join(t.TempDir(), "loki", "bin") // deux niveaux absents
|
|
dst, err := installSelf(binDir)
|
|
if err != nil {
|
|
t.Fatalf("installSelf sur un dossier absent : %v", err)
|
|
}
|
|
if _, err := os.Stat(dst); err != nil {
|
|
t.Fatalf("binaire non écrit : %v", err)
|
|
}
|
|
}
|
|
|
|
// replaceInstalled doit écraser le binaire en place, y compris quand le fichier
|
|
// cible existe déjà, et laisser l'ancien de côté sans le confondre avec la cible.
|
|
func TestReplaceInstalled(t *testing.T) {
|
|
dir := t.TempDir()
|
|
target := filepath.Join(dir, "loki.exe")
|
|
if err := os.WriteFile(target, []byte("ancienne version"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := replaceInstalled(target); err != nil {
|
|
t.Fatalf("replaceInstalled : %v", err)
|
|
}
|
|
got, err := os.ReadFile(target)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// installSelf copie l'exécutable courant (ici le binaire de test).
|
|
self, err := os.ReadFile(os.Args[0])
|
|
if err != nil {
|
|
t.Skip("binaire de test illisible")
|
|
}
|
|
if len(got) != len(self) {
|
|
t.Fatalf("cible = %d octets, attendu %d (le binaire courant)", len(got), len(self))
|
|
}
|
|
if _, err := os.Stat(target + ".old"); err == nil {
|
|
t.Error(".old subsiste alors que la cible n'était pas verrouillée")
|
|
}
|
|
}
|
|
|
|
// Un fichier sans ressource de version doit renvoyer "" : runAsInstaller s'en
|
|
// sert pour s'abstenir plutôt que de remplacer un binaire au hasard.
|
|
func TestBinaryVersionWithoutResource(t *testing.T) {
|
|
p := filepath.Join(t.TempDir(), "vide.exe")
|
|
if err := os.WriteFile(p, []byte("pas un exe"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if v := binaryVersion(p); v != "" {
|
|
t.Fatalf("binaryVersion sur un fichier sans ressource = %q, attendu \"\"", v)
|
|
}
|
|
}
|
|
|
|
// Reproduit le cas signale en usage : l'alias « loki.exe » est EN COURS
|
|
// d'execution au moment de la mise a jour. copyExe seul echouait, l'alias
|
|
// restait fige sur une version perimee, et tout raccourci le visant relancait
|
|
// indefiniment l'ancienne version — qui affichait « une version plus recente
|
|
// est deja installee » a chaque lancement.
|
|
func TestReplaceExeSurchargeUnFichierVerrouille(t *testing.T) {
|
|
dir := t.TempDir()
|
|
src := filepath.Join(dir, "neuf.exe")
|
|
dst := filepath.Join(dir, "loki.exe")
|
|
if err := os.WriteFile(src, []byte("VERSION-NEUVE"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(dst, []byte("version-perimee"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Verrou exclusif : imite un .exe en cours d'execution sous Windows.
|
|
held, err := os.OpenFile(dst, os.O_RDONLY, 0)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer held.Close()
|
|
|
|
if err := replaceExe(src, dst); err != nil {
|
|
t.Fatalf("remplacement impossible: %v", err)
|
|
}
|
|
b, err := os.ReadFile(dst)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(b) != "VERSION-NEUVE" {
|
|
t.Fatalf("l'alias est reste perime: %q", b)
|
|
}
|
|
}
|
|
|
|
// Le remplacement ne doit JAMAIS faire disparaitre la cible : si la copie
|
|
// echoue apres le renommage, l'ancien fichier revient a sa place.
|
|
func TestReplaceExeRestaureSiLaCopieEchoue(t *testing.T) {
|
|
dir := t.TempDir()
|
|
dst := filepath.Join(dir, "loki.exe")
|
|
if err := os.WriteFile(dst, []byte("a-preserver"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Source inexistante : la copie echouera forcement.
|
|
if err := replaceExe(filepath.Join(dir, "absent.exe"), dst); err == nil {
|
|
t.Fatal("attendu une erreur")
|
|
}
|
|
b, err := os.ReadFile(dst)
|
|
if err != nil {
|
|
t.Fatalf("le fichier a disparu: %v", err)
|
|
}
|
|
if string(b) != "a-preserver" {
|
|
t.Fatalf("contenu altere: %q", b)
|
|
}
|
|
}
|