package main import ( "crypto/md5" "fmt" "io" "os" "os/exec" "testing" ) func must[T any](t T, err error) T { if err != nil { panic(err) } return t } func build() func() { must(exec.Command("go", "build", "-o", "testdata/app", "testdata/app.go").CombinedOutput()) must(exec.Command("go", "build", "-o", "appify").CombinedOutput()) return func() { os.RemoveAll("./appify") os.RemoveAll("./testdata/app") } } func Test(t *testing.T) { cleanup := build() defer cleanup() out := must(exec.Command("./appify", "-name", "Test", "-icon", "testdata/machina-square.png", "testdata/app").CombinedOutput()) t.Logf("%q", string(out)) defer os.RemoveAll("Test.app") actualAppHash := filehash("testdata/app") type file struct { path string perm string hash string } for _, f := range []file{ {path: "Test.app", perm: "drwxr-xr-x"}, {path: "Test.app/Contents", perm: "drwxr-xr-x"}, {path: "Test.app/Contents/MacOS", perm: "drwxr-xr-x"}, {path: "Test.app/Contents/MacOS/Test.app", perm: "-rwxr-xr-x", hash: actualAppHash}, {path: "Test.app/Contents/Info.plist", perm: "-rw-r--r--", hash: "0cd092b7b884e87617648dbdadb6a804"}, {path: "Test.app/Contents/Resources", perm: "drwxr-xr-x"}, {path: "Test.app/Contents/Resources/icon.icns", perm: "-rw-r--r--", hash: "23bdc36475094ed8886f319811d3a182"}, } { t.Run(f.path, func(t *testing.T) { info := must(os.Stat(f.path)) if info.Mode().String() != f.perm { t.Logf("%v != %v", info.Mode().String(), f.perm) } if f.hash != "" { actual := filehash(f.path) if actual != f.hash { t.Logf("%v != %v", actual, f.hash) } } }) } } func TestWithPListInjection(t *testing.T) { cleanup := build() defer cleanup() out := must(exec.Command("./appify", "-name", "Test", "-icon", "testdata/machina-square.png", "-plist", "testdata/additionalplist.xml", "testdata/app").CombinedOutput()) t.Logf("%q", string(out)) defer os.RemoveAll("Test.app") actualAppHash := filehash("testdata/app") type file struct { path string perm string hash string } for _, f := range []file{ {path: "Test.app", perm: "drwxr-xr-x"}, {path: "Test.app/Contents", perm: "drwxr-xr-x"}, {path: "Test.app/Contents/MacOS", perm: "drwxr-xr-x"}, {path: "Test.app/Contents/MacOS/Test.app", perm: "-rwxr-xr-x", hash: actualAppHash}, {path: "Test.app/Contents/Info.plist", perm: "-rw-r--r--", hash: "dd977257c7e77dc7739bb4ae70e5f697"}, {path: "Test.app/Contents/Resources", perm: "drwxr-xr-x"}, {path: "Test.app/Contents/Resources/icon.icns", perm: "-rw-r--r--", hash: "23bdc36475094ed8886f319811d3a182"}, } { t.Run(f.path, func(t *testing.T) { info := must(os.Stat(f.path)) if info.Mode().String() != f.perm { t.Logf("%v != %v", info.Mode().String(), f.perm) } if f.hash != "" { actual := filehash(f.path) if actual != f.hash { t.Logf("%v != %v", actual, f.hash) } } }) } } // filehash gets an md5 hash of the file at path. func filehash(path string) string { f := must(os.Open(path)) defer f.Close() h := md5.New() must(io.Copy(h, f)) return fmt.Sprintf("%x", h.Sum(nil)) }