service_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. package upgrade
  2. import (
  3. "context"
  4. "io"
  5. "strings"
  6. "testing"
  7. "github.com/Jguer/aur"
  8. "github.com/Jguer/go-alpm/v2"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/stretchr/testify/require"
  11. "github.com/Jguer/yay/v12/pkg/db"
  12. "github.com/Jguer/yay/v12/pkg/db/mock"
  13. "github.com/Jguer/yay/v12/pkg/dep"
  14. "github.com/Jguer/yay/v12/pkg/settings"
  15. "github.com/Jguer/yay/v12/pkg/settings/parser"
  16. "github.com/Jguer/yay/v12/pkg/text"
  17. "github.com/Jguer/yay/v12/pkg/topo"
  18. "github.com/Jguer/yay/v12/pkg/vcs"
  19. mockaur "github.com/Jguer/yay/v12/pkg/dep/mock"
  20. )
  21. func ptrString(s string) *string {
  22. return &s
  23. }
  24. func TestUpgradeService_GraphUpgrades(t *testing.T) {
  25. t.Parallel()
  26. linuxDepInfo := &dep.InstallInfo{
  27. Reason: dep.Explicit,
  28. Source: dep.Sync,
  29. AURBase: nil,
  30. LocalVersion: "4.5.0-1",
  31. Version: "5.0.0-1",
  32. SyncDBName: ptrString("core"),
  33. Upgrade: true,
  34. Devel: false,
  35. }
  36. exampleDepInfoDevel := &dep.InstallInfo{
  37. Source: dep.AUR,
  38. Reason: dep.Dep,
  39. AURBase: ptrString("example"),
  40. LocalVersion: "2.2.1.r32.41baa362-1",
  41. Version: "latest-commit",
  42. Upgrade: true,
  43. Devel: true,
  44. }
  45. newDepInfo := &dep.InstallInfo{
  46. Source: dep.Sync,
  47. Reason: dep.Dep,
  48. SyncDBName: ptrString("core"),
  49. Version: "3.0.1-2",
  50. LocalVersion: "",
  51. Upgrade: false,
  52. Devel: false,
  53. }
  54. exampleDepInfoAUR := &dep.InstallInfo{
  55. Source: dep.AUR,
  56. Reason: dep.Dep,
  57. AURBase: ptrString("example"),
  58. LocalVersion: "2.2.1.r32.41baa362-1",
  59. Version: "2.2.1.r69.g8a10460-1",
  60. Upgrade: true,
  61. Devel: false,
  62. }
  63. yayDepInfo := &dep.InstallInfo{
  64. Reason: dep.Explicit,
  65. Source: dep.AUR,
  66. AURBase: ptrString("yay"),
  67. LocalVersion: "10.2.3",
  68. Version: "10.2.4",
  69. Upgrade: true,
  70. Devel: false,
  71. }
  72. coreDB := mock.NewDB("core")
  73. dbExe := &mock.DBExecutor{
  74. InstalledRemotePackageNamesFn: func() []string {
  75. return []string{"yay", "example-git"}
  76. },
  77. InstalledRemotePackagesFn: func() map[string]mock.IPackage {
  78. mapRemote := make(map[string]mock.IPackage)
  79. mapRemote["yay"] = &mock.Package{
  80. PName: "yay",
  81. PBase: "yay",
  82. PVersion: "10.2.3",
  83. PReason: alpm.PkgReasonExplicit,
  84. }
  85. mapRemote["example-git"] = &mock.Package{
  86. PName: "example-git",
  87. PBase: "example",
  88. PVersion: "2.2.1.r32.41baa362-1",
  89. PReason: alpm.PkgReasonDepend,
  90. }
  91. return mapRemote
  92. },
  93. LocalSatisfierExistsFn: func(string) bool { return false },
  94. SyncSatisfierFn: func(s string) mock.IPackage {
  95. return &mock.Package{
  96. PName: "new-dep",
  97. PVersion: "3.0.1-2",
  98. PDB: coreDB,
  99. }
  100. },
  101. SyncUpgradesFn: func(bool) (map[string]db.SyncUpgrade, error) {
  102. mapUpgrades := make(map[string]db.SyncUpgrade)
  103. mapUpgrades["linux"] = db.SyncUpgrade{
  104. Package: &mock.Package{
  105. PName: "linux",
  106. PVersion: "5.0.0-1",
  107. PReason: alpm.PkgReasonDepend,
  108. PDB: coreDB,
  109. PDepends: mock.DependList{Depends: []alpm.Depend{
  110. {Name: "new-dep", Version: "3.0.1"},
  111. }},
  112. },
  113. LocalVersion: "4.5.0-1",
  114. Reason: alpm.PkgReasonExplicit,
  115. }
  116. mapUpgrades["new-dep"] = db.SyncUpgrade{
  117. Package: &mock.Package{
  118. PName: "new-dep",
  119. PVersion: "3.0.1-2",
  120. PReason: alpm.PkgReasonDepend,
  121. PDB: coreDB,
  122. },
  123. LocalVersion: "",
  124. Reason: alpm.PkgReasonDepend,
  125. }
  126. return mapUpgrades, nil
  127. },
  128. ReposFn: func() []string { return []string{"core"} },
  129. }
  130. vcsStore := &vcs.Mock{
  131. ToUpgradeReturn: []string{"example-git"},
  132. }
  133. mockAUR := &mockaur.MockAUR{
  134. GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
  135. return []aur.Pkg{
  136. {Name: "yay", Version: "10.2.4", PackageBase: "yay"},
  137. {
  138. Name: "example-git", Version: "2.2.1.r69.g8a10460-1",
  139. PackageBase: "example", Depends: []string{"new-dep"},
  140. },
  141. }, nil
  142. },
  143. }
  144. type fields struct {
  145. input io.Reader
  146. output io.Writer
  147. noConfirm bool
  148. devel bool
  149. }
  150. type args struct {
  151. graph *topo.Graph[string, *dep.InstallInfo]
  152. enableDowngrade bool
  153. }
  154. tests := []struct {
  155. name string
  156. fields fields
  157. args args
  158. mustExist map[string]*dep.InstallInfo
  159. mustNotExist map[string]bool
  160. wantExclude []string
  161. wantErr bool
  162. }{
  163. {
  164. name: "no input",
  165. fields: fields{
  166. input: strings.NewReader("\n"),
  167. output: io.Discard,
  168. noConfirm: false,
  169. },
  170. args: args{
  171. graph: nil,
  172. enableDowngrade: false,
  173. },
  174. mustExist: map[string]*dep.InstallInfo{
  175. "yay": yayDepInfo,
  176. "linux": linuxDepInfo,
  177. "example-git": exampleDepInfoAUR,
  178. "new-dep": newDepInfo,
  179. },
  180. mustNotExist: map[string]bool{},
  181. wantErr: false,
  182. wantExclude: []string{},
  183. },
  184. {
  185. name: "no input devel",
  186. fields: fields{
  187. input: strings.NewReader("\n"),
  188. output: io.Discard,
  189. noConfirm: false,
  190. devel: true,
  191. },
  192. args: args{
  193. graph: nil,
  194. enableDowngrade: false,
  195. },
  196. mustExist: map[string]*dep.InstallInfo{
  197. "yay": yayDepInfo,
  198. "linux": linuxDepInfo,
  199. "example-git": exampleDepInfoDevel,
  200. },
  201. mustNotExist: map[string]bool{},
  202. wantErr: false,
  203. wantExclude: []string{},
  204. },
  205. {
  206. name: "exclude example-git",
  207. fields: fields{
  208. input: strings.NewReader("2\n"),
  209. output: io.Discard,
  210. noConfirm: false,
  211. },
  212. args: args{
  213. graph: nil,
  214. enableDowngrade: false,
  215. },
  216. mustExist: map[string]*dep.InstallInfo{
  217. "yay": yayDepInfo,
  218. "linux": linuxDepInfo,
  219. },
  220. mustNotExist: map[string]bool{"example-git": true, "new-dep": true},
  221. wantErr: false,
  222. wantExclude: []string{"example-git", "new-dep"},
  223. },
  224. {
  225. name: "exclude new-dep should have no effect",
  226. fields: fields{
  227. input: strings.NewReader("1 3 4\n"),
  228. output: io.Discard,
  229. noConfirm: false,
  230. },
  231. args: args{
  232. graph: nil,
  233. enableDowngrade: false,
  234. },
  235. mustExist: map[string]*dep.InstallInfo{
  236. "example-git": exampleDepInfoAUR,
  237. "new-dep": newDepInfo,
  238. },
  239. mustNotExist: map[string]bool{"linux": true, "yay": true},
  240. wantErr: false,
  241. wantExclude: []string{"linux", "yay"},
  242. },
  243. {
  244. name: "exclude yay",
  245. fields: fields{
  246. input: strings.NewReader("1\n"),
  247. output: io.Discard,
  248. noConfirm: false,
  249. },
  250. args: args{
  251. graph: nil,
  252. enableDowngrade: false,
  253. },
  254. mustExist: map[string]*dep.InstallInfo{
  255. "linux": linuxDepInfo,
  256. "example-git": exampleDepInfoAUR,
  257. },
  258. mustNotExist: map[string]bool{"yay": true},
  259. wantErr: false,
  260. wantExclude: []string{"yay"},
  261. },
  262. {
  263. name: "exclude linux",
  264. fields: fields{
  265. input: strings.NewReader("4\n"),
  266. output: io.Discard,
  267. noConfirm: false,
  268. },
  269. args: args{
  270. graph: nil,
  271. enableDowngrade: false,
  272. },
  273. mustExist: map[string]*dep.InstallInfo{
  274. "yay": yayDepInfo,
  275. "example-git": exampleDepInfoAUR,
  276. "new-dep": newDepInfo,
  277. },
  278. mustNotExist: map[string]bool{"linux": true},
  279. wantErr: false,
  280. wantExclude: []string{"linux"},
  281. },
  282. {
  283. name: "only linux",
  284. fields: fields{
  285. input: strings.NewReader("^4\n"),
  286. output: io.Discard,
  287. noConfirm: false,
  288. },
  289. args: args{
  290. graph: nil,
  291. enableDowngrade: false,
  292. },
  293. mustExist: map[string]*dep.InstallInfo{
  294. "linux": linuxDepInfo,
  295. },
  296. mustNotExist: map[string]bool{"yay": true, "example-git": true},
  297. wantErr: false,
  298. wantExclude: []string{"yay", "example-git", "new-dep"},
  299. },
  300. {
  301. name: "exclude all",
  302. fields: fields{
  303. input: strings.NewReader("1-4\n"),
  304. output: io.Discard,
  305. noConfirm: false,
  306. },
  307. args: args{
  308. graph: nil,
  309. enableDowngrade: false,
  310. },
  311. mustExist: map[string]*dep.InstallInfo{},
  312. mustNotExist: map[string]bool{"yay": true, "example-git": true, "linux": true},
  313. wantErr: false,
  314. wantExclude: []string{"yay", "example-git", "linux", "new-dep"},
  315. },
  316. }
  317. for _, tt := range tests {
  318. t.Run(tt.name, func(t *testing.T) {
  319. grapher := dep.NewGrapher(dbExe, mockAUR,
  320. false, true, false, false, false, text.NewLogger(tt.fields.output,
  321. tt.fields.input, true, "test"))
  322. cfg := &settings.Configuration{
  323. Devel: tt.fields.devel, Mode: parser.ModeAny,
  324. }
  325. u := &UpgradeService{
  326. log: text.NewLogger(tt.fields.output,
  327. tt.fields.input, true, "test"),
  328. grapher: grapher,
  329. aurCache: mockAUR,
  330. dbExecutor: dbExe,
  331. vcsStore: vcsStore,
  332. cfg: cfg,
  333. noConfirm: tt.fields.noConfirm,
  334. }
  335. got, err := u.GraphUpgrades(context.Background(), tt.args.graph, tt.args.enableDowngrade, func(*Upgrade) bool { return true })
  336. if (err != nil) != tt.wantErr {
  337. t.Errorf("UpgradeService.GraphUpgrades() error = %v, wantErr %v", err, tt.wantErr)
  338. return
  339. }
  340. excluded, err := u.UserExcludeUpgrades(got)
  341. require.NoError(t, err)
  342. for node, info := range tt.mustExist {
  343. assert.True(t, got.Exists(node), node)
  344. assert.Equal(t, info, got.GetNodeInfo(node).Value)
  345. }
  346. for node := range tt.mustNotExist {
  347. assert.False(t, got.Exists(node), node)
  348. }
  349. assert.ElementsMatch(t, tt.wantExclude, excluded)
  350. })
  351. }
  352. }
  353. func TestUpgradeService_GraphUpgradesNoUpdates(t *testing.T) {
  354. t.Parallel()
  355. dbExe := &mock.DBExecutor{
  356. InstalledRemotePackageNamesFn: func() []string {
  357. return []string{"yay", "example-git"}
  358. },
  359. InstalledRemotePackagesFn: func() map[string]mock.IPackage {
  360. mapRemote := make(map[string]mock.IPackage)
  361. mapRemote["yay"] = &mock.Package{
  362. PName: "yay",
  363. PBase: "yay",
  364. PVersion: "10.2.3",
  365. PReason: alpm.PkgReasonExplicit,
  366. }
  367. mapRemote["example-git"] = &mock.Package{
  368. PName: "example-git",
  369. PBase: "example",
  370. PVersion: "2.2.1.r32.41baa362-1",
  371. PReason: alpm.PkgReasonDepend,
  372. }
  373. return mapRemote
  374. },
  375. SyncUpgradesFn: func(bool) (map[string]db.SyncUpgrade, error) {
  376. mapUpgrades := make(map[string]db.SyncUpgrade)
  377. return mapUpgrades, nil
  378. },
  379. ReposFn: func() []string { return []string{"core"} },
  380. }
  381. vcsStore := &vcs.Mock{
  382. ToUpgradeReturn: []string{},
  383. }
  384. mockAUR := &mockaur.MockAUR{
  385. GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
  386. return []aur.Pkg{}, nil
  387. },
  388. }
  389. type fields struct {
  390. input io.Reader
  391. output io.Writer
  392. noConfirm bool
  393. devel bool
  394. }
  395. type args struct {
  396. graph *topo.Graph[string, *dep.InstallInfo]
  397. enableDowngrade bool
  398. }
  399. tests := []struct {
  400. name string
  401. fields fields
  402. args args
  403. mustExist map[string]*dep.InstallInfo
  404. mustNotExist map[string]bool
  405. wantExclude []string
  406. wantErr bool
  407. }{
  408. {
  409. name: "no input",
  410. fields: fields{
  411. input: strings.NewReader(""),
  412. output: io.Discard,
  413. noConfirm: false,
  414. },
  415. args: args{
  416. graph: nil,
  417. enableDowngrade: false,
  418. },
  419. mustExist: map[string]*dep.InstallInfo{},
  420. mustNotExist: map[string]bool{},
  421. wantErr: false,
  422. wantExclude: []string{},
  423. },
  424. }
  425. for _, tt := range tests {
  426. t.Run(tt.name, func(t *testing.T) {
  427. grapher := dep.NewGrapher(dbExe, mockAUR,
  428. false, true, false, false, false, text.NewLogger(tt.fields.output,
  429. tt.fields.input, true, "test"))
  430. cfg := &settings.Configuration{
  431. Devel: tt.fields.devel,
  432. Mode: parser.ModeAny,
  433. }
  434. u := &UpgradeService{
  435. log: text.NewLogger(tt.fields.output,
  436. tt.fields.input, true, "test"),
  437. grapher: grapher,
  438. aurCache: mockAUR,
  439. dbExecutor: dbExe,
  440. vcsStore: vcsStore,
  441. cfg: cfg,
  442. noConfirm: tt.fields.noConfirm,
  443. }
  444. got, err := u.GraphUpgrades(context.Background(), tt.args.graph, tt.args.enableDowngrade, func(*Upgrade) bool { return true })
  445. if (err != nil) != tt.wantErr {
  446. t.Errorf("UpgradeService.GraphUpgrades() error = %v, wantErr %v", err, tt.wantErr)
  447. return
  448. }
  449. excluded, err := u.UserExcludeUpgrades(got)
  450. require.NoError(t, err)
  451. for node, info := range tt.mustExist {
  452. assert.True(t, got.Exists(node), node)
  453. assert.Equal(t, info, got.GetNodeInfo(node).Value)
  454. }
  455. for node := range tt.mustNotExist {
  456. assert.False(t, got.Exists(node), node)
  457. }
  458. assert.ElementsMatch(t, tt.wantExclude, excluded)
  459. })
  460. }
  461. }