//go:build windows package ajean 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 `ajean 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) } }