···1919 cache: true
20202121 - name: Run tests
2222- run: go test ./src
2222+ run: go test ./...
23232424 - name: Vet
2525- run: go vet ./src
2525+ run: go vet ./...
26262727 - name: Build
2828- run: go build -o /tmp/appherder ./src
2828+ run: go build ./...
+106
cmd/appherder/install_test.go
···11+package main
22+33+import (
44+ "os"
55+ "path/filepath"
66+ "testing"
77+)
88+99+// fakeExtract simulates `appimage --appimage-extract` by populating a
1010+// squashfs-root directory with a desktop file and icon, mirroring what a real
1111+// AppImage runtime writes during extraction.
1212+func fakeExtract(t *testing.T, desktop string, icon []byte) func(name string, args []string, dir string) error {
1313+ t.Helper()
1414+ return func(name string, args []string, dir string) error {
1515+ root := filepath.Join(dir, "squashfs-root")
1616+ if err := os.MkdirAll(root, 0o755); err != nil {
1717+ return err
1818+ }
1919+ if desktop != "" {
2020+ if err := os.WriteFile(filepath.Join(root, "example.desktop"), []byte(desktop), 0o644); err != nil {
2121+ return err
2222+ }
2323+ }
2424+ if icon != nil {
2525+ if err := os.WriteFile(filepath.Join(root, ".DirIcon"), icon, 0o644); err != nil {
2626+ return err
2727+ }
2828+ }
2929+ return nil
3030+ }
3131+}
3232+3333+func TestInstallWritesAppImageIconAndDesktopFile(t *testing.T) {
3434+ home := t.TempDir()
3535+ src := t.TempDir()
3636+ appimage := filepath.Join(src, "Example.AppImage")
3737+ if err := os.WriteFile(appimage, []byte("appimage-bytes"), 0o644); err != nil {
3838+ t.Fatal(err)
3939+ }
4040+4141+ iconBytes := []byte("icon-bytes")
4242+ a := app{
4343+ homeDir: func() (string, error) { return home, nil },
4444+ run: fakeExtract(t, sampleDesktopFile, iconBytes),
4545+ }
4646+4747+ if err := a.install(appimage); err != nil {
4848+ t.Fatalf("install: %v", err)
4949+ }
5050+5151+ // AppImage copied into ~/AppImages and made executable.
5252+ installedAppImage := filepath.Join(home, "AppImages", "Example.appimage")
5353+ info, err := os.Stat(installedAppImage)
5454+ if err != nil {
5555+ t.Fatalf("stat installed appimage: %v", err)
5656+ }
5757+ if info.Mode().Perm()&0o111 == 0 {
5858+ t.Fatalf("installed appimage is not executable: %v", info.Mode())
5959+ }
6060+ if got, _ := os.ReadFile(installedAppImage); string(got) != "appimage-bytes" {
6161+ t.Fatalf("installed appimage contents = %q", got)
6262+ }
6363+6464+ // Icon copied into ~/AppImages/.icons/<app>.
6565+ installedIcon := filepath.Join(home, "AppImages", ".icons", "Example")
6666+ if got, _ := os.ReadFile(installedIcon); string(got) != string(iconBytes) {
6767+ t.Fatalf("installed icon contents = %q", got)
6868+ }
6969+7070+ // Desktop file written and patched to point at the installed paths.
7171+ installedDesktop := filepath.Join(home, ".local", "share", "applications", "Example.desktop")
7272+ desktop, err := readDesktopFile(installedDesktop)
7373+ if err != nil {
7474+ t.Fatalf("read installed desktop file: %v", err)
7575+ }
7676+ assertDesktopValue(t, desktop, desktopEntrySection, "TryExec", installedAppImage)
7777+ assertDesktopValue(t, desktop, desktopEntrySection, "Icon", installedIcon)
7878+ assertDesktopExec(t, desktop, desktopEntrySection,
7979+ []string{"env", "FOO=bar", "DESKTOPINTEGRATION=1", installedAppImage, "%U"})
8080+}
8181+8282+func TestInstallWithoutDesktopFileStillInstallsAppImage(t *testing.T) {
8383+ home := t.TempDir()
8484+ src := t.TempDir()
8585+ appimage := filepath.Join(src, "Example.AppImage")
8686+ if err := os.WriteFile(appimage, []byte("appimage-bytes"), 0o644); err != nil {
8787+ t.Fatal(err)
8888+ }
8989+9090+ a := app{
9191+ homeDir: func() (string, error) { return home, nil },
9292+ run: fakeExtract(t, "", nil),
9393+ }
9494+9595+ if err := a.install(appimage); err != nil {
9696+ t.Fatalf("install: %v", err)
9797+ }
9898+9999+ if _, err := os.Stat(filepath.Join(home, "AppImages", "Example.appimage")); err != nil {
100100+ t.Fatalf("stat installed appimage: %v", err)
101101+ }
102102+ // No desktop file in the extracted AppImage means none is written.
103103+ if _, err := os.Stat(filepath.Join(home, ".local", "share", "applications", "Example.desktop")); !os.IsNotExist(err) {
104104+ t.Fatalf("expected no desktop file, stat err: %v", err)
105105+ }
106106+}