local_install_test.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  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. RemoveMake: "no",
  121. Runtime: &settings.Runtime{
  122. CmdBuilder: cmdBuilder,
  123. VCSStore: &vcs.Mock{},
  124. AURCache: &mockaur.MockAUR{
  125. GetFn: func(ctx context.Context, query *metadata.AURQuery) ([]aur.Pkg, error) {
  126. return []aur.Pkg{}, nil
  127. },
  128. },
  129. },
  130. }
  131. err = handleCmd(context.Background(), config, cmdArgs, db)
  132. require.NoError(t, err)
  133. require.Len(t, mockRunner.ShowCalls, len(wantShow))
  134. require.Len(t, mockRunner.CaptureCalls, len(wantCapture))
  135. for i, call := range mockRunner.ShowCalls {
  136. show := call.Args[0].(*exec.Cmd).String()
  137. show = strings.ReplaceAll(show, tmpDir, "/testdir") // replace the temp dir with a static path
  138. show = strings.ReplaceAll(show, makepkgBin, "makepkg")
  139. show = strings.ReplaceAll(show, pacmanBin, "pacman")
  140. show = strings.ReplaceAll(show, gitBin, "pacman")
  141. // options are in a different order on different systems and on CI root user is used
  142. assert.Subset(t, strings.Split(show, " "), strings.Split(wantShow[i], " "), fmt.Sprintf("%d - %s", i, show))
  143. }
  144. }
  145. func TestIntegrationLocalInstallMissingDep(t *testing.T) {
  146. wantErr := "could not find dotnet-sdk>=6"
  147. makepkgBin := t.TempDir() + "/makepkg"
  148. pacmanBin := t.TempDir() + "/pacman"
  149. gitBin := t.TempDir() + "/git"
  150. tmpDir := t.TempDir()
  151. f, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)
  152. require.NoError(t, err)
  153. require.NoError(t, f.Close())
  154. f, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)
  155. require.NoError(t, err)
  156. require.NoError(t, f.Close())
  157. f, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)
  158. require.NoError(t, err)
  159. require.NoError(t, f.Close())
  160. tars := []string{
  161. tmpDir + "/jellyfin-10.8.4-1-x86_64.pkg.tar.zst",
  162. tmpDir + "/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst",
  163. tmpDir + "/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst",
  164. }
  165. wantShow := []string{}
  166. wantCapture := []string{}
  167. captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
  168. return strings.Join(tars, "\n"), "", nil
  169. }
  170. once := sync.Once{}
  171. showOverride := func(cmd *exec.Cmd) error {
  172. once.Do(func() {
  173. for _, tar := range tars {
  174. f, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)
  175. require.NoError(t, err)
  176. require.NoError(t, f.Close())
  177. }
  178. })
  179. return nil
  180. }
  181. mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}
  182. cmdBuilder := &exe.CmdBuilder{
  183. MakepkgBin: makepkgBin,
  184. SudoBin: "su",
  185. PacmanBin: pacmanBin,
  186. PacmanConfigPath: "/etc/pacman.conf",
  187. GitBin: "git",
  188. Runner: mockRunner,
  189. SudoLoopEnabled: false,
  190. }
  191. cmdArgs := parser.MakeArguments()
  192. cmdArgs.AddArg("B")
  193. cmdArgs.AddArg("i")
  194. cmdArgs.AddTarget("testdata/jfin")
  195. db := &mock.DBExecutor{
  196. AlpmArchitecturesFn: func() ([]string, error) {
  197. return []string{"x86_64"}, nil
  198. },
  199. LocalSatisfierExistsFn: func(s string) bool {
  200. switch s {
  201. case "dotnet-sdk>=6", "dotnet-sdk<7", "dotnet-runtime>=6", "dotnet-runtime<7", "jellyfin-server=10.8.4", "jellyfin-web=10.8.4":
  202. return false
  203. }
  204. return true
  205. },
  206. SyncSatisfierFn: func(s string) mock.IPackage {
  207. switch s {
  208. case "dotnet-runtime>=6", "dotnet-runtime<7":
  209. return &mock.Package{
  210. PName: "dotnet-runtime-6.0",
  211. PBase: "dotnet-runtime-6.0",
  212. PVersion: "6.0.100-1",
  213. PDB: mock.NewDB("community"),
  214. }
  215. }
  216. return nil
  217. },
  218. }
  219. config := &settings.Configuration{
  220. Runtime: &settings.Runtime{
  221. CmdBuilder: cmdBuilder,
  222. VCSStore: &vcs.Mock{},
  223. AURCache: &mockaur.MockAUR{
  224. GetFn: func(ctx context.Context, query *metadata.AURQuery) ([]aur.Pkg, error) {
  225. return []aur.Pkg{}, nil
  226. },
  227. },
  228. },
  229. }
  230. err = handleCmd(context.Background(), config, cmdArgs, db)
  231. require.Error(t, err)
  232. require.EqualError(t, err, wantErr)
  233. require.Len(t, mockRunner.ShowCalls, len(wantShow))
  234. require.Len(t, mockRunner.CaptureCalls, len(wantCapture))
  235. for i, call := range mockRunner.ShowCalls {
  236. show := call.Args[0].(*exec.Cmd).String()
  237. show = strings.ReplaceAll(show, tmpDir, "/testdir") // replace the temp dir with a static path
  238. show = strings.ReplaceAll(show, makepkgBin, "makepkg")
  239. show = strings.ReplaceAll(show, pacmanBin, "pacman")
  240. show = strings.ReplaceAll(show, gitBin, "pacman")
  241. // options are in a different order on different systems and on CI root user is used
  242. assert.Subset(t, strings.Split(show, " "), strings.Split(wantShow[i], " "), fmt.Sprintf("%d - %s", i, show))
  243. }
  244. }