code.gitea.io/gitea@v1.22.3/modules/indexer/issues/indexer_test.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package issues 5 6 import ( 7 "context" 8 "testing" 9 10 "code.gitea.io/gitea/models/db" 11 "code.gitea.io/gitea/models/issues" 12 "code.gitea.io/gitea/models/unittest" 13 "code.gitea.io/gitea/modules/indexer/issues/internal" 14 "code.gitea.io/gitea/modules/optional" 15 "code.gitea.io/gitea/modules/setting" 16 17 _ "code.gitea.io/gitea/models" 18 _ "code.gitea.io/gitea/models/actions" 19 _ "code.gitea.io/gitea/models/activities" 20 21 "github.com/stretchr/testify/assert" 22 ) 23 24 func TestMain(m *testing.M) { 25 unittest.MainTest(m) 26 } 27 28 func TestDBSearchIssues(t *testing.T) { 29 assert.NoError(t, unittest.PrepareTestDatabase()) 30 31 setting.Indexer.IssueType = "db" 32 InitIssueIndexer(true) 33 34 t.Run("search issues with keyword", searchIssueWithKeyword) 35 t.Run("search issues in repo", searchIssueInRepo) 36 t.Run("search issues by ID", searchIssueByID) 37 t.Run("search issues is pr", searchIssueIsPull) 38 t.Run("search issues is closed", searchIssueIsClosed) 39 t.Run("search issues by milestone", searchIssueByMilestoneID) 40 t.Run("search issues by label", searchIssueByLabelID) 41 t.Run("search issues by time", searchIssueByTime) 42 t.Run("search issues with order", searchIssueWithOrder) 43 t.Run("search issues in project", searchIssueInProject) 44 t.Run("search issues with paginator", searchIssueWithPaginator) 45 } 46 47 func searchIssueWithKeyword(t *testing.T) { 48 tests := []struct { 49 opts SearchOptions 50 expectedIDs []int64 51 }{ 52 { 53 SearchOptions{ 54 Keyword: "issue2", 55 RepoIDs: []int64{1}, 56 }, 57 []int64{2}, 58 }, 59 { 60 SearchOptions{ 61 Keyword: "first", 62 RepoIDs: []int64{1}, 63 }, 64 []int64{1}, 65 }, 66 { 67 SearchOptions{ 68 Keyword: "for", 69 RepoIDs: []int64{1}, 70 }, 71 []int64{11, 5, 3, 2, 1}, 72 }, 73 { 74 SearchOptions{ 75 Keyword: "good", 76 RepoIDs: []int64{1}, 77 }, 78 []int64{1}, 79 }, 80 } 81 82 for _, test := range tests { 83 issueIDs, _, err := SearchIssues(context.TODO(), &test.opts) 84 if !assert.NoError(t, err) { 85 return 86 } 87 assert.Equal(t, test.expectedIDs, issueIDs) 88 } 89 } 90 91 func searchIssueInRepo(t *testing.T) { 92 tests := []struct { 93 opts SearchOptions 94 expectedIDs []int64 95 }{ 96 { 97 SearchOptions{ 98 RepoIDs: []int64{1}, 99 }, 100 []int64{11, 5, 3, 2, 1}, 101 }, 102 { 103 SearchOptions{ 104 RepoIDs: []int64{2}, 105 }, 106 []int64{7, 4}, 107 }, 108 { 109 SearchOptions{ 110 RepoIDs: []int64{3}, 111 }, 112 []int64{12, 6}, 113 }, 114 { 115 SearchOptions{ 116 RepoIDs: []int64{4}, 117 }, 118 []int64{}, 119 }, 120 { 121 SearchOptions{ 122 RepoIDs: []int64{5}, 123 }, 124 []int64{15}, 125 }, 126 } 127 128 for _, test := range tests { 129 issueIDs, _, err := SearchIssues(context.TODO(), &test.opts) 130 if !assert.NoError(t, err) { 131 return 132 } 133 assert.Equal(t, test.expectedIDs, issueIDs) 134 } 135 } 136 137 func searchIssueByID(t *testing.T) { 138 tests := []struct { 139 opts SearchOptions 140 expectedIDs []int64 141 }{ 142 { 143 opts: SearchOptions{ 144 PosterID: optional.Some(int64(1)), 145 }, 146 expectedIDs: []int64{11, 6, 3, 2, 1}, 147 }, 148 { 149 opts: SearchOptions{ 150 AssigneeID: optional.Some(int64(1)), 151 }, 152 expectedIDs: []int64{6, 1}, 153 }, 154 { 155 // NOTE: This tests no assignees filtering and also ToSearchOptions() to ensure it will set AssigneeID to 0 when it is passed as -1. 156 opts: *ToSearchOptions("", &issues.IssuesOptions{AssigneeID: -1}), 157 expectedIDs: []int64{22, 21, 16, 15, 14, 13, 12, 11, 20, 5, 19, 18, 10, 7, 4, 9, 8, 3, 2}, 158 }, 159 { 160 opts: SearchOptions{ 161 MentionID: optional.Some(int64(4)), 162 }, 163 expectedIDs: []int64{1}, 164 }, 165 { 166 opts: SearchOptions{ 167 ReviewedID: optional.Some(int64(1)), 168 }, 169 expectedIDs: []int64{}, 170 }, 171 { 172 opts: SearchOptions{ 173 ReviewRequestedID: optional.Some(int64(1)), 174 }, 175 expectedIDs: []int64{12}, 176 }, 177 { 178 opts: SearchOptions{ 179 SubscriberID: optional.Some(int64(1)), 180 }, 181 expectedIDs: []int64{11, 6, 5, 3, 2, 1}, 182 }, 183 { 184 // issue 20 request user 15 and team 5 which user 15 belongs to 185 // the review request number of issue 20 should be 1 186 opts: SearchOptions{ 187 ReviewRequestedID: optional.Some(int64(15)), 188 }, 189 expectedIDs: []int64{12, 20}, 190 }, 191 { 192 // user 20 approved the issue 20, so return nothing 193 opts: SearchOptions{ 194 ReviewRequestedID: optional.Some(int64(20)), 195 }, 196 expectedIDs: []int64{}, 197 }, 198 } 199 200 for _, test := range tests { 201 issueIDs, _, err := SearchIssues(context.TODO(), &test.opts) 202 if !assert.NoError(t, err) { 203 return 204 } 205 assert.Equal(t, test.expectedIDs, issueIDs) 206 } 207 } 208 209 func searchIssueIsPull(t *testing.T) { 210 tests := []struct { 211 opts SearchOptions 212 expectedIDs []int64 213 }{ 214 { 215 SearchOptions{ 216 IsPull: optional.Some(false), 217 }, 218 []int64{17, 16, 15, 14, 13, 6, 5, 18, 10, 7, 4, 1}, 219 }, 220 { 221 SearchOptions{ 222 IsPull: optional.Some(true), 223 }, 224 []int64{22, 21, 12, 11, 20, 19, 9, 8, 3, 2}, 225 }, 226 } 227 for _, test := range tests { 228 issueIDs, _, err := SearchIssues(context.TODO(), &test.opts) 229 if !assert.NoError(t, err) { 230 return 231 } 232 assert.Equal(t, test.expectedIDs, issueIDs) 233 } 234 } 235 236 func searchIssueIsClosed(t *testing.T) { 237 tests := []struct { 238 opts SearchOptions 239 expectedIDs []int64 240 }{ 241 { 242 SearchOptions{ 243 IsClosed: optional.Some(false), 244 }, 245 []int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 19, 18, 10, 7, 9, 8, 3, 2, 1}, 246 }, 247 { 248 SearchOptions{ 249 IsClosed: optional.Some(true), 250 }, 251 []int64{5, 4}, 252 }, 253 } 254 for _, test := range tests { 255 issueIDs, _, err := SearchIssues(context.TODO(), &test.opts) 256 if !assert.NoError(t, err) { 257 return 258 } 259 assert.Equal(t, test.expectedIDs, issueIDs) 260 } 261 } 262 263 func searchIssueByMilestoneID(t *testing.T) { 264 tests := []struct { 265 opts SearchOptions 266 expectedIDs []int64 267 }{ 268 { 269 SearchOptions{ 270 MilestoneIDs: []int64{1}, 271 }, 272 []int64{2}, 273 }, 274 { 275 SearchOptions{ 276 MilestoneIDs: []int64{3}, 277 }, 278 []int64{3}, 279 }, 280 } 281 for _, test := range tests { 282 issueIDs, _, err := SearchIssues(context.TODO(), &test.opts) 283 if !assert.NoError(t, err) { 284 return 285 } 286 assert.Equal(t, test.expectedIDs, issueIDs) 287 } 288 } 289 290 func searchIssueByLabelID(t *testing.T) { 291 tests := []struct { 292 opts SearchOptions 293 expectedIDs []int64 294 }{ 295 { 296 SearchOptions{ 297 IncludedLabelIDs: []int64{1}, 298 }, 299 []int64{2, 1}, 300 }, 301 { 302 SearchOptions{ 303 IncludedLabelIDs: []int64{4}, 304 }, 305 []int64{2}, 306 }, 307 { 308 SearchOptions{ 309 ExcludedLabelIDs: []int64{1}, 310 }, 311 []int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 5, 19, 18, 10, 7, 4, 9, 8, 3}, 312 }, 313 } 314 for _, test := range tests { 315 issueIDs, _, err := SearchIssues(context.TODO(), &test.opts) 316 if !assert.NoError(t, err) { 317 return 318 } 319 assert.Equal(t, test.expectedIDs, issueIDs) 320 } 321 } 322 323 func searchIssueByTime(t *testing.T) { 324 tests := []struct { 325 opts SearchOptions 326 expectedIDs []int64 327 }{ 328 { 329 SearchOptions{ 330 UpdatedAfterUnix: optional.Some(int64(0)), 331 }, 332 []int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 5, 19, 18, 10, 7, 4, 9, 8, 3, 2, 1}, 333 }, 334 } 335 for _, test := range tests { 336 issueIDs, _, err := SearchIssues(context.TODO(), &test.opts) 337 if !assert.NoError(t, err) { 338 return 339 } 340 assert.Equal(t, test.expectedIDs, issueIDs) 341 } 342 } 343 344 func searchIssueWithOrder(t *testing.T) { 345 tests := []struct { 346 opts SearchOptions 347 expectedIDs []int64 348 }{ 349 { 350 SearchOptions{ 351 SortBy: internal.SortByCreatedAsc, 352 }, 353 []int64{1, 2, 3, 8, 9, 4, 7, 10, 18, 19, 5, 6, 20, 11, 12, 13, 14, 15, 16, 17, 21, 22}, 354 }, 355 } 356 for _, test := range tests { 357 issueIDs, _, err := SearchIssues(context.TODO(), &test.opts) 358 if !assert.NoError(t, err) { 359 return 360 } 361 assert.Equal(t, test.expectedIDs, issueIDs) 362 } 363 } 364 365 func searchIssueInProject(t *testing.T) { 366 tests := []struct { 367 opts SearchOptions 368 expectedIDs []int64 369 }{ 370 { 371 SearchOptions{ 372 ProjectID: optional.Some(int64(1)), 373 }, 374 []int64{5, 3, 2, 1}, 375 }, 376 { 377 SearchOptions{ 378 ProjectBoardID: optional.Some(int64(1)), 379 }, 380 []int64{1}, 381 }, 382 { 383 SearchOptions{ 384 ProjectBoardID: optional.Some(int64(0)), // issue with in default board 385 }, 386 []int64{2}, 387 }, 388 } 389 for _, test := range tests { 390 issueIDs, _, err := SearchIssues(context.TODO(), &test.opts) 391 if !assert.NoError(t, err) { 392 return 393 } 394 assert.Equal(t, test.expectedIDs, issueIDs) 395 } 396 } 397 398 func searchIssueWithPaginator(t *testing.T) { 399 tests := []struct { 400 opts SearchOptions 401 expectedIDs []int64 402 expectedTotal int64 403 }{ 404 { 405 SearchOptions{ 406 Paginator: &db.ListOptions{ 407 PageSize: 5, 408 }, 409 }, 410 []int64{22, 21, 17, 16, 15}, 411 22, 412 }, 413 } 414 for _, test := range tests { 415 issueIDs, total, err := SearchIssues(context.TODO(), &test.opts) 416 if !assert.NoError(t, err) { 417 return 418 } 419 assert.Equal(t, test.expectedIDs, issueIDs) 420 assert.Equal(t, test.expectedTotal, total) 421 } 422 }