[mike@mwxm4]
This commit is contained in:
+235
@@ -0,0 +1,235 @@
|
||||
// ================================================================================== tests for gbld (mwx'2026)
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func inTempDir(t *testing.T) { // ------------------------------------- run a test in an empty working directory
|
||||
t.Helper()
|
||||
old, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
dir := t.TempDir()
|
||||
if err := os.Chdir(dir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { os.Chdir(old) })
|
||||
}
|
||||
|
||||
func write(t *testing.T, name, content string) { // ------------------------------------------ write a test file
|
||||
t.Helper()
|
||||
if err := os.WriteFile(name, []byte(content), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGettargetversion(t *testing.T) { // ------------------------------------------- find 'var version = ..'
|
||||
inTempDir(t)
|
||||
|
||||
if _, err := gettargetversion(); err == nil {
|
||||
t.Error("expected an error when no version is defined")
|
||||
}
|
||||
|
||||
write(t, "other.go", "package main\n\n"+`var tbversion = "0.1.0"`+"\n")
|
||||
if _, err := gettargetversion(); err == nil {
|
||||
t.Error("tbversion must not be taken for the target version")
|
||||
}
|
||||
|
||||
write(t, "app.go", "package main\n\n"+`var version = "2.3.0" // release`+"\n")
|
||||
v, err := gettargetversion()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v != "2.3.0" {
|
||||
t.Errorf("got %q, want 2.3.0 (a trailing comment must not break the match)", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBumpbuild(t *testing.T) { // ------------------------------------- counter increases, comment survives
|
||||
inTempDir(t)
|
||||
|
||||
write(t, "build.go", "package main\n\n"+`var build = "41" // counter`+"\n")
|
||||
bumpbuild()
|
||||
|
||||
c, err := os.ReadFile("build.go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := "package main\n\n" + `var build = "42" // counter` + "\n"
|
||||
if string(c) != want {
|
||||
t.Errorf("got %q, want %q", string(c), want)
|
||||
}
|
||||
|
||||
files, _ := filepath.Glob("tmp/build.go.*") // the backup is what protects the users file
|
||||
if len(files) != 1 {
|
||||
t.Errorf("expected exactly one backup in tmp/, got %v", files)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackupPruning(t *testing.T) { // ---------------------------------- tmp/ must not grow without bounds
|
||||
inTempDir(t)
|
||||
|
||||
write(t, "build.go", "package main\n\n"+`var build = "1"`+"\n")
|
||||
for i := 0; i < KEEPBACKUPS+5; i++ { // same second: force distinct names to test the pruning itself
|
||||
if err := backup("build.go"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
write(t, SF("tmp/build.go.2026010112000%02d", i), "old backup")
|
||||
prunebackups("build.go", KEEPBACKUPS)
|
||||
}
|
||||
|
||||
files, _ := filepath.Glob("tmp/build.go.*")
|
||||
if len(files) > KEEPBACKUPS {
|
||||
t.Errorf("got %d backups, want at most %d", len(files), KEEPBACKUPS)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBumpbuildKeepsLongLines(t *testing.T) { // -------------- a >64k line must not truncate the file anymore
|
||||
inTempDir(t)
|
||||
|
||||
long := strings.Repeat("x", 100*1024)
|
||||
write(t, "build.go", "package main\n\n"+`var build = "1"`+"\n\nvar long = \""+long+"\"\n")
|
||||
bumpbuild()
|
||||
|
||||
c, err := os.ReadFile("build.go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(string(c), `var build = "2"`) {
|
||||
t.Error("counter was not increased")
|
||||
}
|
||||
if !strings.Contains(string(c), long) {
|
||||
t.Error("long line was lost - the file got truncated")
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifact(t *testing.T) { // --------------------------------------------- windows artifacts need '.exe'
|
||||
if got := artifact("gbld", "1.2.3", "linux", "amd64"); got != "gbld_1.2.3_linux_amd64" {
|
||||
t.Errorf("got %q", got)
|
||||
}
|
||||
if got := artifact("gbld", "1.2.3", "windows", "amd64"); got != "gbld_1.2.3_windows_amd64.exe" {
|
||||
t.Errorf("got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileExists(t *testing.T) { // --------------------------------- must not panic on unreadable entries
|
||||
inTempDir(t)
|
||||
|
||||
write(t, "there.go", "package main\n")
|
||||
if !fileExists("there.go") {
|
||||
t.Error("existing file not found")
|
||||
}
|
||||
if fileExists("missing.go") {
|
||||
t.Error("missing file reported as existing")
|
||||
}
|
||||
os.Mkdir("adir", 0755)
|
||||
if fileExists("adir") {
|
||||
t.Error("a directory is not a file")
|
||||
}
|
||||
|
||||
os.Mkdir("locked", 0000) // no permission: os.Stat fails with something other than IsNotExist
|
||||
defer os.Chmod("locked", 0755)
|
||||
if fileExists("locked/x.go") {
|
||||
t.Error("unreadable path reported as existing")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetchecksum(t *testing.T) { // ------------------------------------- checksums are read and validated
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/checksums.txt" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
w.Write([]byte("aabb gbld_1.0.0_linux_amd64\n" +
|
||||
"0f0f gbld_1.0.0_windows_amd64.exe\n" +
|
||||
"zzzz broken_sum\n"))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
|
||||
sum, err := getchecksum(client, srv.URL+"/checksums.txt", "gbld_1.0.0_linux_amd64")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(sum) != 2 || sum[0] != 0xaa || sum[1] != 0xbb {
|
||||
t.Errorf("wrong checksum decoded: %x", sum)
|
||||
}
|
||||
|
||||
if _, err := getchecksum(client, srv.URL+"/checksums.txt", "gbld_1.0.0_darwin_arm64"); err == nil {
|
||||
t.Error("a missing entry must be an error - never update without a checksum")
|
||||
}
|
||||
if _, err := getchecksum(client, srv.URL+"/checksums.txt", "broken_sum"); err == nil {
|
||||
t.Error("a malformed checksum must be an error")
|
||||
}
|
||||
if _, err := getchecksum(client, srv.URL+"/missing.txt", "gbld_1.0.0_linux_amd64"); err == nil {
|
||||
t.Error("a missing checksums.txt must be an error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoupdateRejectsWrongChecksum(t *testing.T) { // ------------- a manipulated download is never applied
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("this is not the binary you asked for"))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
err := doupdate(&http.Client{Timeout: 5 * time.Second}, srv.URL+"/gbld", []byte{0xde, 0xad, 0xbe, 0xef})
|
||||
if err == nil {
|
||||
t.Fatal("update with a wrong checksum was accepted")
|
||||
}
|
||||
if !strings.Contains(strings.ToLower(err.Error()), "checksum") {
|
||||
t.Errorf("expected a checksum error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchStatus(t *testing.T) { // -------------------------------------- http errors must not be swallowed
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "nope", http.StatusInternalServerError)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
if _, err := fetch(&http.Client{Timeout: 5 * time.Second}, srv.URL, 1<<20); err == nil {
|
||||
t.Error("http 500 was reported as success")
|
||||
}
|
||||
}
|
||||
|
||||
func TestToolbox(t *testing.T) { // ------------------------------------------------ toolbox edge cases
|
||||
if got := Shortstr("abcdef", 4); got != "ab.." {
|
||||
t.Errorf("Shortstr: got %q", got)
|
||||
}
|
||||
if got := Shortstr("abcdef", 1); got != ".." { // must not panic
|
||||
t.Errorf("Shortstr with a tiny length: got %q", got)
|
||||
}
|
||||
if got := Dec("!!!not valid!!!"); got != "" { // must not panic
|
||||
t.Errorf("Dec of garbage: got %q", got)
|
||||
}
|
||||
if got := Dec(Enc("secret")); got != "secret" {
|
||||
t.Errorf("Enc/Dec roundtrip: got %q", got)
|
||||
}
|
||||
|
||||
in := []string{"a", "b", "a", "c"}
|
||||
out := RemoveAllMatches(in, "a")
|
||||
if strings.Join(out, "") != "bc" {
|
||||
t.Errorf("RemoveAllMatches: got %v", out)
|
||||
}
|
||||
if strings.Join(in, "") != "abac" {
|
||||
t.Errorf("RemoveAllMatches modified the callers slice: %v", in)
|
||||
}
|
||||
|
||||
if !Checkip("10.0.0.0/8", "10.1.2.3") || Checkip("10.0.0.0/8", "192.168.0.1") {
|
||||
t.Error("Checkip cidr")
|
||||
}
|
||||
if Checkip("10.0.0.0/8", "not an ip") {
|
||||
t.Error("Checkip accepted an invalid address")
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================================================================= END
|
||||
Reference in New Issue
Block a user