選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

repo_list_test.go 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package models
  5. import (
  6. "strings"
  7. "testing"
  8. "code.gitea.io/gitea/models/db"
  9. "code.gitea.io/gitea/models/unittest"
  10. "code.gitea.io/gitea/modules/util"
  11. "github.com/stretchr/testify/assert"
  12. )
  13. func TestSearchRepository(t *testing.T) {
  14. assert.NoError(t, unittest.PrepareTestDatabase())
  15. // test search public repository on explore page
  16. repos, count, err := SearchRepositoryByName(&SearchRepoOptions{
  17. ListOptions: db.ListOptions{
  18. Page: 1,
  19. PageSize: 10,
  20. },
  21. Keyword: "repo_12",
  22. Collaborate: util.OptionalBoolFalse,
  23. })
  24. assert.NoError(t, err)
  25. if assert.Len(t, repos, 1) {
  26. assert.Equal(t, "test_repo_12", repos[0].Name)
  27. }
  28. assert.Equal(t, int64(1), count)
  29. repos, count, err = SearchRepositoryByName(&SearchRepoOptions{
  30. ListOptions: db.ListOptions{
  31. Page: 1,
  32. PageSize: 10,
  33. },
  34. Keyword: "test_repo",
  35. Collaborate: util.OptionalBoolFalse,
  36. })
  37. assert.NoError(t, err)
  38. assert.Equal(t, int64(2), count)
  39. assert.Len(t, repos, 2)
  40. // test search private repository on explore page
  41. repos, count, err = SearchRepositoryByName(&SearchRepoOptions{
  42. ListOptions: db.ListOptions{
  43. Page: 1,
  44. PageSize: 10,
  45. },
  46. Keyword: "repo_13",
  47. Private: true,
  48. Collaborate: util.OptionalBoolFalse,
  49. })
  50. assert.NoError(t, err)
  51. if assert.Len(t, repos, 1) {
  52. assert.Equal(t, "test_repo_13", repos[0].Name)
  53. }
  54. assert.Equal(t, int64(1), count)
  55. repos, count, err = SearchRepositoryByName(&SearchRepoOptions{
  56. ListOptions: db.ListOptions{
  57. Page: 1,
  58. PageSize: 10,
  59. },
  60. Keyword: "test_repo",
  61. Private: true,
  62. Collaborate: util.OptionalBoolFalse,
  63. })
  64. assert.NoError(t, err)
  65. assert.Equal(t, int64(3), count)
  66. assert.Len(t, repos, 3)
  67. // Test non existing owner
  68. repos, count, err = SearchRepositoryByName(&SearchRepoOptions{OwnerID: unittest.NonexistentID})
  69. assert.NoError(t, err)
  70. assert.Empty(t, repos)
  71. assert.Equal(t, int64(0), count)
  72. // Test search within description
  73. repos, count, err = SearchRepository(&SearchRepoOptions{
  74. ListOptions: db.ListOptions{
  75. Page: 1,
  76. PageSize: 10,
  77. },
  78. Keyword: "description_14",
  79. Collaborate: util.OptionalBoolFalse,
  80. IncludeDescription: true,
  81. })
  82. assert.NoError(t, err)
  83. if assert.Len(t, repos, 1) {
  84. assert.Equal(t, "test_repo_14", repos[0].Name)
  85. }
  86. assert.Equal(t, int64(1), count)
  87. // Test NOT search within description
  88. repos, count, err = SearchRepository(&SearchRepoOptions{
  89. ListOptions: db.ListOptions{
  90. Page: 1,
  91. PageSize: 10,
  92. },
  93. Keyword: "description_14",
  94. Collaborate: util.OptionalBoolFalse,
  95. IncludeDescription: false,
  96. })
  97. assert.NoError(t, err)
  98. assert.Empty(t, repos)
  99. assert.Equal(t, int64(0), count)
  100. testCases := []struct {
  101. name string
  102. opts *SearchRepoOptions
  103. count int
  104. }{
  105. {
  106. name: "PublicRepositoriesByName",
  107. opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, Collaborate: util.OptionalBoolFalse},
  108. count: 7,
  109. },
  110. {
  111. name: "PublicAndPrivateRepositoriesByName",
  112. opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, Collaborate: util.OptionalBoolFalse},
  113. count: 14,
  114. },
  115. {
  116. name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitFirstPage",
  117. opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse},
  118. count: 14,
  119. },
  120. {
  121. name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitSecondPage",
  122. opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 2, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse},
  123. count: 14,
  124. },
  125. {
  126. name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitThirdPage",
  127. opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse},
  128. count: 14,
  129. },
  130. {
  131. name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitFourthPage",
  132. opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse},
  133. count: 14,
  134. },
  135. {
  136. name: "PublicRepositoriesOfUser",
  137. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Collaborate: util.OptionalBoolFalse},
  138. count: 2,
  139. },
  140. {
  141. name: "PublicRepositoriesOfUser2",
  142. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Collaborate: util.OptionalBoolFalse},
  143. count: 0,
  144. },
  145. {
  146. name: "PublicRepositoriesOfUser3",
  147. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Collaborate: util.OptionalBoolFalse},
  148. count: 2,
  149. },
  150. {
  151. name: "PublicAndPrivateRepositoriesOfUser",
  152. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, Collaborate: util.OptionalBoolFalse},
  153. count: 4,
  154. },
  155. {
  156. name: "PublicAndPrivateRepositoriesOfUser2",
  157. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, Collaborate: util.OptionalBoolFalse},
  158. count: 0,
  159. },
  160. {
  161. name: "PublicAndPrivateRepositoriesOfUser3",
  162. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true, Collaborate: util.OptionalBoolFalse},
  163. count: 4,
  164. },
  165. {
  166. name: "PublicRepositoriesOfUserIncludingCollaborative",
  167. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15},
  168. count: 5,
  169. },
  170. {
  171. name: "PublicRepositoriesOfUser2IncludingCollaborative",
  172. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18},
  173. count: 1,
  174. },
  175. {
  176. name: "PublicRepositoriesOfUser3IncludingCollaborative",
  177. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20},
  178. count: 3,
  179. },
  180. {
  181. name: "PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
  182. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true},
  183. count: 9,
  184. },
  185. {
  186. name: "PublicAndPrivateRepositoriesOfUser2IncludingCollaborative",
  187. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true},
  188. count: 4,
  189. },
  190. {
  191. name: "PublicAndPrivateRepositoriesOfUser3IncludingCollaborative",
  192. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true},
  193. count: 7,
  194. },
  195. {
  196. name: "PublicRepositoriesOfOrganization",
  197. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Collaborate: util.OptionalBoolFalse},
  198. count: 1,
  199. },
  200. {
  201. name: "PublicAndPrivateRepositoriesOfOrganization",
  202. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Private: true, Collaborate: util.OptionalBoolFalse},
  203. count: 2,
  204. },
  205. {
  206. name: "AllPublic/PublicRepositoriesByName",
  207. opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, AllPublic: true, Collaborate: util.OptionalBoolFalse},
  208. count: 7,
  209. },
  210. {
  211. name: "AllPublic/PublicAndPrivateRepositoriesByName",
  212. opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, AllPublic: true, Collaborate: util.OptionalBoolFalse},
  213. count: 14,
  214. },
  215. {
  216. name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
  217. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: util.OptionalBoolFalse},
  218. count: 28,
  219. },
  220. {
  221. name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
  222. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: util.OptionalBoolFalse},
  223. count: 33,
  224. },
  225. {
  226. name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
  227. opts: &SearchRepoOptions{Keyword: "test", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true},
  228. count: 15,
  229. },
  230. {
  231. name: "AllPublic/PublicAndPrivateRepositoriesOfUser2IncludingCollaborativeByName",
  232. opts: &SearchRepoOptions{Keyword: "test", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, AllPublic: true},
  233. count: 13,
  234. },
  235. {
  236. name: "AllPublic/PublicRepositoriesOfOrganization",
  237. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse, Template: util.OptionalBoolFalse},
  238. count: 28,
  239. },
  240. {
  241. name: "AllTemplates",
  242. opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Template: util.OptionalBoolTrue},
  243. count: 2,
  244. },
  245. {
  246. name: "OwnerSlashRepoSearch",
  247. opts: &SearchRepoOptions{Keyword: "user/repo2", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, OwnerID: 0},
  248. count: 3,
  249. },
  250. {
  251. name: "OwnerSlashSearch",
  252. opts: &SearchRepoOptions{Keyword: "user20/", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, OwnerID: 0},
  253. count: 4,
  254. },
  255. }
  256. for _, testCase := range testCases {
  257. t.Run(testCase.name, func(t *testing.T) {
  258. repos, count, err := SearchRepositoryByName(testCase.opts)
  259. assert.NoError(t, err)
  260. assert.Equal(t, int64(testCase.count), count)
  261. page := testCase.opts.Page
  262. if page <= 0 {
  263. page = 1
  264. }
  265. expectedLen := testCase.opts.PageSize
  266. if testCase.opts.PageSize*page > testCase.count+testCase.opts.PageSize {
  267. expectedLen = 0
  268. } else if testCase.opts.PageSize*page > testCase.count {
  269. expectedLen = testCase.count % testCase.opts.PageSize
  270. }
  271. if assert.Len(t, repos, expectedLen) {
  272. for _, repo := range repos {
  273. assert.NotEmpty(t, repo.Name)
  274. if len(testCase.opts.Keyword) > 0 {
  275. // Keyword match condition is different for search terms of form "owner/repo"
  276. if strings.Count(testCase.opts.Keyword, "/") == 1 {
  277. // May still match as a whole...
  278. wholeMatch := strings.Contains(repo.Name, testCase.opts.Keyword)
  279. pieces := strings.Split(testCase.opts.Keyword, "/")
  280. ownerName := pieces[0]
  281. repoName := pieces[1]
  282. // ... or match in parts
  283. splitMatch := strings.Contains(repo.OwnerName, ownerName) && strings.Contains(repo.Name, repoName)
  284. assert.True(t, wholeMatch || splitMatch, "Keyword '%s' does not match repo '%s/%s'", testCase.opts.Keyword, repo.Owner.Name, repo.Name)
  285. } else {
  286. assert.Contains(t, repo.Name, testCase.opts.Keyword)
  287. }
  288. }
  289. if !testCase.opts.Private {
  290. assert.False(t, repo.IsPrivate)
  291. }
  292. if testCase.opts.Fork == util.OptionalBoolTrue && testCase.opts.Mirror == util.OptionalBoolTrue {
  293. assert.True(t, repo.IsFork || repo.IsMirror)
  294. } else {
  295. switch testCase.opts.Fork {
  296. case util.OptionalBoolFalse:
  297. assert.False(t, repo.IsFork)
  298. case util.OptionalBoolTrue:
  299. assert.True(t, repo.IsFork)
  300. }
  301. switch testCase.opts.Mirror {
  302. case util.OptionalBoolFalse:
  303. assert.False(t, repo.IsMirror)
  304. case util.OptionalBoolTrue:
  305. assert.True(t, repo.IsMirror)
  306. }
  307. }
  308. if testCase.opts.OwnerID > 0 && !testCase.opts.AllPublic {
  309. switch testCase.opts.Collaborate {
  310. case util.OptionalBoolFalse:
  311. assert.Equal(t, testCase.opts.OwnerID, repo.Owner.ID)
  312. case util.OptionalBoolTrue:
  313. assert.NotEqual(t, testCase.opts.OwnerID, repo.Owner.ID)
  314. }
  315. }
  316. }
  317. }
  318. })
  319. }
  320. }
  321. func TestSearchRepositoryByTopicName(t *testing.T) {
  322. assert.NoError(t, unittest.PrepareTestDatabase())
  323. testCases := []struct {
  324. name string
  325. opts *SearchRepoOptions
  326. count int
  327. }{
  328. {
  329. name: "AllPublic/SearchPublicRepositoriesFromTopicAndName",
  330. opts: &SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql"},
  331. count: 2,
  332. },
  333. {
  334. name: "AllPublic/OnlySearchPublicRepositoriesFromTopic",
  335. opts: &SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql", TopicOnly: true},
  336. count: 1,
  337. },
  338. {
  339. name: "AllPublic/OnlySearchMultipleKeywordPublicRepositoriesFromTopic",
  340. opts: &SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql,golang", TopicOnly: true},
  341. count: 2,
  342. },
  343. }
  344. for _, testCase := range testCases {
  345. t.Run(testCase.name, func(t *testing.T) {
  346. _, count, err := SearchRepositoryByName(testCase.opts)
  347. assert.NoError(t, err)
  348. assert.Equal(t, int64(testCase.count), count)
  349. })
  350. }
  351. }