local_install_test.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "os/exec"
  7. "strings"
  8. "sync"
  9. "testing"
  10. aur "github.com/Jguer/aur"
  11. "github.com/Jguer/aur/metadata"
  12. "github.com/stretchr/testify/assert"
  13. "github.com/stretchr/testify/require"
  14. "github.com/Jguer/yay/v11/pkg/db/mock"
  15. mockaur "github.com/Jguer/yay/v11/pkg/dep/mock"
  16. "github.com/Jguer/yay/v11/pkg/settings"
  17. "github.com/Jguer/yay/v11/pkg/settings/exe"
  18. "github.com/Jguer/yay/v11/pkg/settings/parser"
  19. "github.com/Jguer/yay/v11/pkg/vcs"
  20. )
  21. func TestIntegrationLocalInstall(t *testing.T) {
  22. makepkgBin := t.TempDir() + "/makepkg"
  23. pacmanBin := t.TempDir() + "/pacman"
  24. gitBin := t.TempDir() + "/git"
  25. tmpDir := t.TempDir()
  26. f, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)
  27. require.NoError(t, err)
  28. require.NoError(t, f.Close())
  29. f, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)
  30. require.NoError(t, err)
  31. require.NoError(t, f.Close())
  32. f, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)
  33. require.NoError(t, err)
  34. require.NoError(t, f.Close())
  35. tars := []string{
  36. tmpDir + "/jellyfin-10.8.4-1-x86_64.pkg.tar.zst",
  37. tmpDir + "/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst",
  38. tmpDir + "/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst",
  39. }
  40. wantShow := []string{
  41. "makepkg --verifysource -Ccf",
  42. "pacman -S --config /etc/pacman.conf -- community/dotnet-sdk-6.0 community/dotnet-runtime-6.0",
  43. "pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 dotnet-sdk-6.0",
  44. "makepkg --nobuild -fC --ignorearch",
  45. "makepkg -c --nobuild --noextract --ignorearch",
  46. "makepkg --nobuild -fC --ignorearch",
  47. "makepkg -c --nobuild --noextract --ignorearch",
  48. "makepkg --nobuild -fC --ignorearch",
  49. "makepkg -c --nobuild --noextract --ignorearch",
  50. "pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst",
  51. "pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin-server jellyfin jellyfin-web",
  52. }
  53. wantCapture := []string{
  54. "makepkg --packagelist",
  55. "git -C testdata/jfin git reset --hard HEAD",
  56. "git -C testdata/jfin git merge --no-edit --ff",
  57. "makepkg --packagelist",
  58. "makepkg --packagelist",
  59. }
  60. captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
  61. return strings.Join(tars, "\n"), "", nil
  62. }
  63. once := sync.Once{}
  64. showOverride := func(cmd *exec.Cmd) error {
  65. once.Do(func() {
  66. for _, tar := range tars {
  67. f, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)
  68. require.NoError(t, err)
  69. require.NoError(t, f.Close())
  70. }
  71. })
  72. return nil
  73. }
  74. mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}
  75. cmdBuilder := &exe.CmdBuilder{
  76. MakepkgBin: makepkgBin,
  77. SudoBin: "su",
  78. PacmanBin: pacmanBin,
  79. PacmanConfigPath: "/etc/pacman.conf",
  80. GitBin: "git",
  81. Runner: mockRunner,
  82. SudoLoopEnabled: false,
  83. }
  84. cmdArgs := parser.MakeArguments()
  85. cmdArgs.AddArg("B")
  86. cmdArgs.AddArg("i")
  87. cmdArgs.AddTarget("testdata/jfin")
  88. db := &mock.DBExecutor{
  89. AlpmArchitecturesFn: func() ([]string, error) {
  90. return []string{"x86_64"}, nil
  91. },
  92. LocalSatisfierExistsFn: func(s string) bool {
  93. switch s {
  94. case "dotnet-sdk>=6", "dotnet-sdk<7", "dotnet-runtime>=6", "dotnet-runtime<7", "jellyfin-server=10.8.4", "jellyfin-web=10.8.4":
  95. return false
  96. }
  97. return true
  98. },
  99. SyncSatisfierFn: func(s string) mock.IPackage {
  100. switch s {
  101. case "dotnet-runtime>=6", "dotnet-runtime<7":
  102. return &mock.Package{
  103. PName: "dotnet-runtime-6.0",
  104. PBase: "dotnet-runtime-6.0",
  105. PVersion: "6.0.100-1",
  106. PDB: mock.NewDB("community"),
  107. }
  108. case "dotnet-sdk>=6", "dotnet-sdk<7":
  109. return &mock.Package{
  110. PName: "dotnet-sdk-6.0",
  111. PBase: "dotnet-sdk-6.0",
  112. PVersion: "6.0.100-1",
  113. PDB: mock.NewDB("community"),
  114. }
  115. }
  116. return nil
  117. },
  118. }
  119. config := &settings.Configuration{
  120. Runtime: &settings.Runtime{
  121. CmdBuilder: cmdBuilder,
  122. VCSStore: &vcs.Mock{},
  123. AURCache: &mockaur.MockAUR{
  124. GetFn: func(ctx context.Context, query *metadata.AURQuery) ([]aur.Pkg, error) {
  125. return []aur.Pkg{}, nil
  126. },
  127. },
  128. },
  129. }
  130. err = handleCmd(context.Background(), config, cmdArgs, db)
  131. require.NoError(t, err)
  132. require.Len(t, mockRunner.ShowCalls, len(wantShow))
  133. require.Len(t, mockRunner.CaptureCalls, len(wantCapture))
  134. for i, call := range mockRunner.ShowCalls {
  135. show := call.Args[0].(*exec.Cmd).String()
  136. show = strings.ReplaceAll(show, tmpDir, "/testdir") // replace the temp dir with a static path
  137. show = strings.ReplaceAll(show, makepkgBin, "makepkg")
  138. show = strings.ReplaceAll(show, pacmanBin, "pacman")
  139. show = strings.ReplaceAll(show, gitBin, "pacman")
  140. // options are in a different order on different systems and on CI root user is used
  141. assert.Subset(t, strings.Split(show, " "), strings.Split(wantShow[i], " "), fmt.Sprintf("%d - %s", i, show))
  142. }
  143. }
  144. func TestIntegrationLocalInstallMissingDep(t *testing.T) {
  145. wantErr := "could not find dotnet-sdk>=6"
  146. makepkgBin := t.TempDir() + "/makepkg"
  147. pacmanBin := t.TempDir() + "/pacman"
  148. gitBin := t.TempDir() + "/git"
  149. tmpDir := t.TempDir()
  150. f, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)
  151. require.NoError(t, err)
  152. require.NoError(t, f.Close())
  153. f, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)
  154. require.NoError(t, err)
  155. require.NoError(t, f.Close())
  156. f, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)
  157. require.NoError(t, err)
  158. require.NoError(t, f.Close())
  159. tars := []string{
  160. tmpDir + "/jellyfin-10.8.4-1-x86_64.pkg.tar.zst",
  161. tmpDir + "/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst",
  162. tmpDir + "/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst",
  163. }
  164. wantShow := []string{}
  165. wantCapture := []string{}
  166. captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
  167. return strings.Join(tars, "\n"), "", nil
  168. }
  169. once := sync.Once{}
  170. showOverride := func(cmd *exec.Cmd) error {
  171. once.Do(func() {
  172. for _, tar := range tars {
  173. f, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)
  174. require.NoError(t, err)
  175. require.NoError(t, f.Close())
  176. }
  177. })
  178. return nil
  179. }
  180. mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}
  181. cmdBuilder := &exe.CmdBuilder{
  182. MakepkgBin: makepkgBin,
  183. SudoBin: "su",
  184. PacmanBin: pacmanBin,
  185. PacmanConfigPath: "/etc/pacman.conf",
  186. GitBin: "git",
  187. Runner: mockRunner,
  188. SudoLoopEnabled: false,
  189. }
  190. cmdArgs := parser.MakeArguments()
  191. cmdArgs.AddArg("B")
  192. cmdArgs.AddArg("i")
  193. cmdArgs.AddTarget("testdata/jfin")
  194. db := &mock.DBExecutor{
  195. AlpmArchitecturesFn: func() ([]string, error) {
  196. return []string{"x86_64"}, nil
  197. },
  198. LocalSatisfierExistsFn: func(s string) bool {
  199. switch s {
  200. case "dotnet-sdk>=6", "dotnet-sdk<7", "dotnet-runtime>=6", "dotnet-runtime<7", "jellyfin-server=10.8.4", "jellyfin-web=10.8.4":
  201. return false
  202. }
  203. return true
  204. },
  205. SyncSatisfierFn: func(s string) mock.IPackage {
  206. switch s {
  207. case "dotnet-runtime>=6", "dotnet-runtime<7":
  208. return &mock.Package{
  209. PName: "dotnet-runtime-6.0",
  210. PBase: "dotnet-runtime-6.0",
  211. PVersion: "6.0.100-1",
  212. PDB: mock.NewDB("community"),
  213. }
  214. }
  215. return nil
  216. },
  217. }
  218. config := &settings.Configuration{
  219. Runtime: &settings.Runtime{
  220. CmdBuilder: cmdBuilder,
  221. VCSStore: &vcs.Mock{},
  222. AURCache: &mockaur.MockAUR{
  223. GetFn: func(ctx context.Context, query *metadata.AURQuery) ([]aur.Pkg, error) {
  224. return []aur.Pkg{}, nil
  225. },
  226. },
  227. },
  228. }
  229. err = handleCmd(context.Background(), config, cmdArgs, db)
  230. require.Error(t, err)
  231. require.EqualError(t, err, wantErr)
  232. require.Len(t, mockRunner.ShowCalls, len(wantShow))
  233. require.Len(t, mockRunner.CaptureCalls, len(wantCapture))
  234. for i, call := range mockRunner.ShowCalls {
  235. show := call.Args[0].(*exec.Cmd).String()
  236. show = strings.ReplaceAll(show, tmpDir, "/testdir") // replace the temp dir with a static path
  237. show = strings.ReplaceAll(show, makepkgBin, "makepkg")
  238. show = strings.ReplaceAll(show, pacmanBin, "pacman")
  239. show = strings.ReplaceAll(show, gitBin, "pacman")
  240. // options are in a different order on different systems and on CI root user is used
  241. assert.Subset(t, strings.Split(show, " "), strings.Split(wantShow[i], " "), fmt.Sprintf("%d - %s", i, show))
  242. }
  243. }