Files
Loki/internal/jean/sys_firstrun_windows_test.go
T
nathaninline 26ce8a9a14 v0.6.14 : creer le dossier bin a la premiere installation
Sur une machine vierge, le premier lancement du fichier telecharge echouait sur
« open C:\ProgramData\jean\bin\jean.exe: The system cannot find the path
specified » : appFirstRun creait le dossier de donnees mais pas son sous-dossier
bin, cree jusqu'ici par le seul `jean install`. AJEAN demarrait alors depuis le
fichier telecharge, sans installation ni raccourcis.

MkdirAll deplace dans installSelf, donc valable quel que soit l'appelant.
Reproduit puis verifie sur banc d'essai Windows (parcours complet depuis un
dossier de donnees inexistant), + test unitaire.
2026-08-04 13:24:42 +02:00

83 lines
2.9 KiB
Go

//go:build windows
package jean
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 `jean 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\jean\bin\jean.exe: The system cannot find the path specified »
// et AJEAN ne s'installait jamais.
func TestInstallSelfCreatesBinDir(t *testing.T) {
binDir := filepath.Join(t.TempDir(), "jean", "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, "jean.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)
}
}