keys_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "testing"
  7. rpc "github.com/mikkeloscar/aur"
  8. gopkg "github.com/mikkeloscar/gopkgbuild"
  9. )
  10. func newPkg(basename string) *rpc.Pkg {
  11. return &rpc.Pkg{Name: basename, PackageBase: basename}
  12. }
  13. func newSplitPkg(basename, name string) *rpc.Pkg {
  14. return &rpc.Pkg{Name: name, PackageBase: basename}
  15. }
  16. func TestFormatKeysToImport(t *testing.T) {
  17. casetests := []struct {
  18. keySet pgpKeySet
  19. bases map[string][]*rpc.Pkg
  20. expected string
  21. alternate string
  22. wantError bool
  23. }{
  24. // Single key, required by single package.
  25. {
  26. keySet: pgpKeySet{"KEY-1": []*rpc.Pkg{newPkg("PKG-foo")}},
  27. expected: fmt.Sprintf("GPG keys need importing:\n\tKEY-1, required by: PKG-foo\n%s Import?", arrow),
  28. wantError: false,
  29. },
  30. // Single key, required by two packages.
  31. {
  32. keySet: pgpKeySet{"KEY-1": []*rpc.Pkg{newPkg("PKG-foo"), newPkg("PKG-bar")}},
  33. expected: fmt.Sprintf("GPG keys need importing:\n\tKEY-1, required by: PKG-foo PKG-bar\n%s Import?", arrow),
  34. wantError: false,
  35. },
  36. // Two keys, each required by a single package. Since iterating the map
  37. // does not force any particular order, we cannot really predict the
  38. // order in which the elements will appear. As we have only two cases,
  39. // let's add the second possibility to the alternate variable, to check
  40. // if there are any errors.
  41. {
  42. keySet: pgpKeySet{"KEY-1": []*rpc.Pkg{newPkg("PKG-foo")}, "KEY-2": []*rpc.Pkg{newPkg("PKG-bar")}},
  43. expected: fmt.Sprintf("GPG keys need importing:\n\tKEY-1, required by: PKG-foo\n\tKEY-2, required by: PKG-bar\n%s Import?", arrow),
  44. alternate: fmt.Sprintf("GPG keys need importing:\n\tKEY-2, required by: PKG-bar\n\tKEY-1, required by: PKG-foo\n%s Import?", arrow),
  45. wantError: false,
  46. },
  47. // Two keys required by single package.
  48. {
  49. keySet: pgpKeySet{"KEY-1": []*rpc.Pkg{newPkg("PKG-foo")}, "KEY-2": []*rpc.Pkg{newPkg("PKG-foo")}},
  50. expected: fmt.Sprintf("GPG keys need importing:\n\tKEY-1, required by: PKG-foo\n\tKEY-2, required by: PKG-foo\n%s Import?", arrow),
  51. alternate: fmt.Sprintf("GPG keys need importing:\n\tKEY-2, required by: PKG-foo\n\tKEY-1, required by: PKG-foo\n%s Import?", arrow),
  52. wantError: false,
  53. },
  54. // Two keys, one of them required by two packages.
  55. {
  56. keySet: pgpKeySet{"KEY-1": []*rpc.Pkg{newPkg("PKG-foo"), newPkg("PKG-bar")}, "KEY-2": []*rpc.Pkg{newPkg("PKG-bar")}},
  57. expected: fmt.Sprintf("GPG keys need importing:\n\tKEY-1, required by: PKG-foo PKG-bar\n\tKEY-2, required by: PKG-bar\n%s Import?", arrow),
  58. alternate: fmt.Sprintf("GPG keys need importing:\n\tKEY-2, required by: PKG-bar\n\tKEY-1, required by: PKG-foo PKG-bar\n%s Import?", arrow),
  59. wantError: false,
  60. },
  61. // Two keys, split package (linux-ck/linux-ck-headers).
  62. {
  63. keySet: pgpKeySet{"ABAF11C65A2970B130ABE3C479BE3E4300411886": []*rpc.Pkg{newPkg("linux-ck")}, "647F28654894E3BD457199BE38DBBDC86092693E": []*rpc.Pkg{newPkg("linux-ck")}},
  64. bases: map[string][]*rpc.Pkg{"linux-ck": {newSplitPkg("linux-ck", "linux-ck-headers"), newPkg("linux-ck")}},
  65. expected: fmt.Sprintf("GPG keys need importing:\n\tABAF11C65A2970B130ABE3C479BE3E4300411886, required by: linux-ck (linux-ck-headers linux-ck)\n\t647F28654894E3BD457199BE38DBBDC86092693E, required by: linux-ck (linux-ck-headers linux-ck)\n%s Import?", arrow),
  66. alternate: fmt.Sprintf("GPG keys need importing:\n\t647F28654894E3BD457199BE38DBBDC86092693E, required by: linux-ck (linux-ck-headers linux-ck)\n\tABAF11C65A2970B130ABE3C479BE3E4300411886, required by: linux-ck (linux-ck-headers linux-ck)\n%s Import?", arrow),
  67. wantError: false,
  68. },
  69. // One key, three split packages.
  70. {
  71. keySet: pgpKeySet{"KEY-1": []*rpc.Pkg{newPkg("PKG-foo")}},
  72. bases: map[string][]*rpc.Pkg{"PKG-foo": {newPkg("PKG-foo"), newSplitPkg("PKG-foo", "PKG-foo-1"), newSplitPkg("PKG-foo", "PKG-foo-2")}},
  73. expected: fmt.Sprintf("GPG keys need importing:\n\tKEY-1, required by: PKG-foo (PKG-foo PKG-foo-1 PKG-foo-2)\n%s Import?", arrow),
  74. wantError: false,
  75. },
  76. // No keys, should fail.
  77. {
  78. keySet: pgpKeySet{},
  79. expected: "",
  80. wantError: true,
  81. },
  82. }
  83. for _, tt := range casetests {
  84. question, err := formatKeysToImport(tt.keySet, tt.bases)
  85. if !tt.wantError {
  86. if err != nil {
  87. t.Fatalf("Got error %q, want no error", err)
  88. }
  89. if question != tt.expected && question != tt.alternate {
  90. t.Fatalf("Got %q\n, expected: %q", question, tt.expected)
  91. }
  92. continue
  93. }
  94. // Here, we want to see the error.
  95. if err == nil {
  96. t.Fatalf("Got no error; want error")
  97. }
  98. }
  99. }
  100. func TestImportKeys(t *testing.T) {
  101. keyringDir, err := ioutil.TempDir("/tmp", "yay-test-keyring")
  102. if err != nil {
  103. t.Fatalf("Unable to init test keyring %q: %v\n", keyringDir, err)
  104. }
  105. // Removing the leftovers.
  106. defer os.RemoveAll(keyringDir)
  107. config.GpgBin = "gpg"
  108. config.GpgFlags = fmt.Sprintf("--homedir %s", keyringDir)
  109. casetests := []struct {
  110. keys []string
  111. wantError bool
  112. }{
  113. // Single key, should succeed.
  114. // C52048C0C0748FEE227D47A2702353E0F7E48EDB: Thomas Dickey.
  115. {
  116. keys: []string{"C52048C0C0748FEE227D47A2702353E0F7E48EDB"},
  117. wantError: false,
  118. },
  119. // Two keys, should succeed as well.
  120. // 11E521D646982372EB577A1F8F0871F202119294: Tom Stellard.
  121. // B6C8F98282B944E3B0D5C2530FC3042E345AD05D: Hans Wennborg.
  122. {
  123. keys: []string{"11E521D646982372EB577A1F8F0871F202119294",
  124. "B6C8F98282B944E3B0D5C2530FC3042E345AD05D"},
  125. wantError: false,
  126. },
  127. // Single invalid key, should fail.
  128. {
  129. keys: []string{"THIS-SHOULD-FAIL"},
  130. wantError: true,
  131. },
  132. // Two invalid keys, should fail.
  133. {
  134. keys: []string{"THIS-SHOULD-FAIL", "THIS-ONE-SHOULD-FAIL-TOO"},
  135. wantError: true,
  136. },
  137. // Invalid + valid key. Should fail as well.
  138. // 647F28654894E3BD457199BE38DBBDC86092693E: Greg Kroah-Hartman.
  139. {
  140. keys: []string{"THIS-SHOULD-FAIL",
  141. "647F28654894E3BD457199BE38DBBDC86092693E"},
  142. wantError: true,
  143. },
  144. }
  145. for _, tt := range casetests {
  146. err := importKeys(tt.keys)
  147. if !tt.wantError {
  148. if err != nil {
  149. t.Fatalf("Got error %q, want no error", err)
  150. }
  151. continue
  152. }
  153. // Here, we want to see the error.
  154. if err == nil {
  155. t.Fatalf("Got no error; want error")
  156. }
  157. }
  158. }
  159. func TestCheckPgpKeys(t *testing.T) {
  160. keyringDir, err := ioutil.TempDir("/tmp", "yay-test-keyring")
  161. if err != nil {
  162. t.Fatalf("Unable to init test keyring: %v\n", err)
  163. }
  164. defer os.RemoveAll(keyringDir)
  165. buildDir, err := ioutil.TempDir("/tmp", "yay-test-build-dir")
  166. if err != nil {
  167. t.Fatalf("Unable to init temp build dir: %v\n", err)
  168. }
  169. defer os.RemoveAll(buildDir)
  170. config.BuildDir = buildDir
  171. config.GpgBin = "gpg"
  172. config.GpgFlags = fmt.Sprintf("--homedir %s", keyringDir)
  173. casetests := []struct {
  174. pkgs []*rpc.Pkg
  175. srcinfos map[string]*gopkg.PKGBUILD
  176. bases map[string][]*rpc.Pkg
  177. wantError bool
  178. }{
  179. // cower: single package, one valid key not yet in the keyring.
  180. // 487EACC08557AD082088DABA1EB2638FF56C0C53: Dave Reisner.
  181. {
  182. pkgs: []*rpc.Pkg{newPkg("cower")},
  183. srcinfos: map[string]*gopkg.PKGBUILD{"cower": &gopkg.PKGBUILD{Pkgbase: "cower", Validpgpkeys: []string{"487EACC08557AD082088DABA1EB2638FF56C0C53"}}},
  184. bases: map[string][]*rpc.Pkg{"cower": {newPkg("cower")}},
  185. wantError: false,
  186. },
  187. // libc++: single package, two valid keys not yet in the keyring.
  188. // 11E521D646982372EB577A1F8F0871F202119294: Tom Stellard.
  189. // B6C8F98282B944E3B0D5C2530FC3042E345AD05D: Hans Wennborg.
  190. {
  191. pkgs: []*rpc.Pkg{newPkg("libc++")},
  192. srcinfos: map[string]*gopkg.PKGBUILD{"libc++": &gopkg.PKGBUILD{Pkgbase: "libc++", Validpgpkeys: []string{"11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D"}}},
  193. bases: map[string][]*rpc.Pkg{"libc++": {newPkg("libc++")}},
  194. wantError: false,
  195. },
  196. // Two dummy packages requiring the same key.
  197. // ABAF11C65A2970B130ABE3C479BE3E4300411886: Linus Torvalds.
  198. {
  199. pkgs: []*rpc.Pkg{newPkg("dummy-1"), newPkg("dummy-2")},
  200. srcinfos: map[string]*gopkg.PKGBUILD{"dummy-1": &gopkg.PKGBUILD{Pkgbase: "dummy-1", Validpgpkeys: []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"}}, "dummy-2": &gopkg.PKGBUILD{Pkgbase: "dummy-2", Validpgpkeys: []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"}}},
  201. bases: map[string][]*rpc.Pkg{"dummy-1": {newPkg("dummy-1")}, "dummy-2": {newPkg("dummy-2")}},
  202. wantError: false,
  203. },
  204. // dummy package: single package, two valid keys, one of them already
  205. // in the keyring.
  206. // 11E521D646982372EB577A1F8F0871F202119294: Tom Stellard.
  207. // C52048C0C0748FEE227D47A2702353E0F7E48EDB: Thomas Dickey.
  208. {
  209. pkgs: []*rpc.Pkg{newPkg("dummy-3")},
  210. srcinfos: map[string]*gopkg.PKGBUILD{"dummy-3": &gopkg.PKGBUILD{Pkgbase: "dummy-3", Validpgpkeys: []string{"11E521D646982372EB577A1F8F0871F202119294", "C52048C0C0748FEE227D47A2702353E0F7E48EDB"}}},
  211. bases: map[string][]*rpc.Pkg{"dummy-3": {newPkg("dummy-3")}},
  212. wantError: false,
  213. },
  214. // Two dummy packages with existing keys.
  215. {
  216. pkgs: []*rpc.Pkg{newPkg("dummy-4"), newPkg("dummy-5")},
  217. srcinfos: map[string]*gopkg.PKGBUILD{"dummy-4": &gopkg.PKGBUILD{Pkgbase: "dummy-4", Validpgpkeys: []string{"11E521D646982372EB577A1F8F0871F202119294"}}, "dummy-5": &gopkg.PKGBUILD{Pkgbase: "dummy-5", Validpgpkeys: []string{"C52048C0C0748FEE227D47A2702353E0F7E48EDB"}}},
  218. bases: map[string][]*rpc.Pkg{"dummy-4": {newPkg("dummy-4")}, "dummy-5": {newPkg("dummy-5")}},
  219. wantError: false,
  220. },
  221. // Dummy package with invalid key, should fail.
  222. {
  223. pkgs: []*rpc.Pkg{newPkg("dummy-7")},
  224. srcinfos: map[string]*gopkg.PKGBUILD{"dummy-7": &gopkg.PKGBUILD{Pkgbase: "dummy-7", Validpgpkeys: []string{"THIS-SHOULD-FAIL"}}},
  225. bases: map[string][]*rpc.Pkg{"dummy-7": {newPkg("dummy-7")}},
  226. wantError: true,
  227. },
  228. // Dummy package with both an invalid an another valid key, should fail.
  229. // A314827C4E4250A204CE6E13284FC34C8E4B1A25: Thomas Bächler.
  230. {
  231. pkgs: []*rpc.Pkg{newPkg("dummy-8")},
  232. srcinfos: map[string]*gopkg.PKGBUILD{"dummy-8": &gopkg.PKGBUILD{Pkgbase: "dummy-8", Validpgpkeys: []string{"A314827C4E4250A204CE6E13284FC34C8E4B1A25", "THIS-SHOULD-FAIL"}}},
  233. bases: map[string][]*rpc.Pkg{"dummy-8": {newPkg("dummy-8")}},
  234. wantError: true,
  235. },
  236. }
  237. for _, tt := range casetests {
  238. err := checkPgpKeys(tt.pkgs, tt.bases, tt.srcinfos)
  239. if !tt.wantError {
  240. if err != nil {
  241. t.Fatalf("Got error %q, want no error", err)
  242. }
  243. continue
  244. }
  245. // Here, we want to see the error.
  246. if err == nil {
  247. t.Fatalf("Got no error; want error")
  248. }
  249. }
  250. }