Browse Source

Add tests for db indexer in indexer_test.go (#27087)

As described in the title.
Some points: 
1. Why need those tests?
Because `buildIssueOverview` is not well tested, there are several
continuous bugs in the issue overview webpage.
2. Why in indexer_test.go?
It's hard to put those tests in `./modules/indexer/issue/db/db_test.go`
because those tests need 'real' data in db mocked by fixtures instead of
random data in `./modules/indexer/issue/internal/tests`. When using
'real' data(`unittest.PrepareTestDatabase`), `InitIssueIndexer` and the
package `init()` function of `indexer` are required to init indexer.
3. Why only db?
The other three indexer engines are well tested by random data and it's
okay to also test them with 'real' data in db mocked by fixtures. Any
follow-up PR is welcome.
4. Those tests are really basic, any more complicated tests are welcome.
5. I think it's also necessary to add tests in `TestAPISearchIssues`
in`api_test_issue.go` and `TestIssues` in `home_test.go`
tags/v1.21.0-rc0
Nanguan Lin 8 months ago
parent
commit
7cdbe65a2c
No account linked to committer's email address
1 changed files with 324 additions and 131 deletions
  1. 324
    131
      modules/indexer/issues/indexer_test.go

+ 324
- 131
modules/indexer/issues/indexer_test.go View File

@@ -5,14 +5,12 @@ package issues

import (
"context"
"fmt"
"path"
"path/filepath"
"testing"
"time"

"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/indexer/issues/bleve"
"code.gitea.io/gitea/modules/indexer/issues/internal"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"

@@ -29,186 +27,381 @@ func TestMain(m *testing.M) {
})
}

func TestBleveSearchIssues(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
setting.CfgProvider, _ = setting.NewConfigProviderFromData("")

tmpIndexerDir := t.TempDir()

setting.CfgProvider.Section("queue.issue_indexer").Key("DATADIR").MustString(path.Join(tmpIndexerDir, "issues.queue"))

oldIssuePath := setting.Indexer.IssuePath
setting.Indexer.IssuePath = path.Join(tmpIndexerDir, "issues.queue")
defer func() {
setting.Indexer.IssuePath = oldIssuePath
}()

setting.Indexer.IssueType = "bleve"
setting.LoadQueueSettings()
InitIssueIndexer(true)
defer func() {
if bleveIndexer, ok := (*globalIndexer.Load()).(*bleve.Indexer); ok {
bleveIndexer.Close()
}
}()

time.Sleep(5 * time.Second)

t.Run("issue2", func(t *testing.T) {
ids, _, err := SearchIssues(context.TODO(), &SearchOptions{
Keyword: "issue2",
RepoIDs: []int64{1},
})
assert.NoError(t, err)
assert.EqualValues(t, []int64{2}, ids)
})

t.Run("first", func(t *testing.T) {
ids, _, err := SearchIssues(context.TODO(), &SearchOptions{
Keyword: "first",
RepoIDs: []int64{1},
})
assert.NoError(t, err)
assert.EqualValues(t, []int64{1}, ids)
})

t.Run("for", func(t *testing.T) {
ids, _, err := SearchIssues(context.TODO(), &SearchOptions{
Keyword: "for",
RepoIDs: []int64{1},
})
assert.NoError(t, err)
assert.ElementsMatch(t, []int64{1, 2, 3, 5, 11}, ids)
})

t.Run("good", func(t *testing.T) {
ids, _, err := SearchIssues(context.TODO(), &SearchOptions{
Keyword: "good",
RepoIDs: []int64{1},
})
assert.NoError(t, err)
assert.EqualValues(t, []int64{1}, ids)
})
}

func TestDBSearchIssuesWithKeyword(t *testing.T) {
func TestDBSearchIssues(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

setting.Indexer.IssueType = "db"
InitIssueIndexer(true)

t.Run("issue2", func(t *testing.T) {
ids, _, err := SearchIssues(context.TODO(), &SearchOptions{
Keyword: "issue2",
RepoIDs: []int64{1},
})
assert.NoError(t, err)
assert.EqualValues(t, []int64{2}, ids)
})

t.Run("first", func(t *testing.T) {
ids, _, err := SearchIssues(context.TODO(), &SearchOptions{
Keyword: "first",
RepoIDs: []int64{1},
})
assert.NoError(t, err)
assert.EqualValues(t, []int64{1}, ids)
})
t.Run("search issues with keyword", searchIssueWithKeyword)
t.Run("search issues in repo", searchIssueInRepo)
t.Run("search issues by ID", searchIssueByID)
t.Run("search issues is pr", searchIssueIsPull)
t.Run("search issues is closed", searchIssueIsClosed)
t.Run("search issues by milestone", searchIssueByMilestoneID)
t.Run("search issues by label", searchIssueByLabelID)
t.Run("search issues by time", searchIssueByTime)
t.Run("search issues with order", searchIssueWithOrder)
t.Run("search issues in project", searchIssueInProject)
t.Run("search issues with paginator", searchIssueWithPaginator)
}

t.Run("for", func(t *testing.T) {
ids, _, err := SearchIssues(context.TODO(), &SearchOptions{
Keyword: "for",
RepoIDs: []int64{1},
})
assert.NoError(t, err)
assert.ElementsMatch(t, []int64{1, 2, 3, 5, 11}, ids)
})
func searchIssueWithKeyword(t *testing.T) {
tests := []struct {
opts SearchOptions
expectedIDs []int64
}{
{
SearchOptions{
Keyword: "issue2",
RepoIDs: []int64{1},
},
[]int64{2},
},
{
SearchOptions{
Keyword: "first",
RepoIDs: []int64{1},
},
[]int64{1},
},
{
SearchOptions{
Keyword: "for",
RepoIDs: []int64{1},
},
[]int64{11, 5, 3, 2, 1},
},
{
SearchOptions{
Keyword: "good",
RepoIDs: []int64{1},
},
[]int64{1},
},
}

t.Run("good", func(t *testing.T) {
ids, _, err := SearchIssues(context.TODO(), &SearchOptions{
Keyword: "good",
RepoIDs: []int64{1},
})
assert.NoError(t, err)
assert.EqualValues(t, []int64{1}, ids)
})
for _, test := range tests {
issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, test.expectedIDs, issueIDs)
}
}

// TODO: add more tests
func TestDBSearchIssueWithoutKeyword(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
func searchIssueInRepo(t *testing.T) {
tests := []struct {
opts SearchOptions
expectedIDs []int64
}{
{
SearchOptions{
RepoIDs: []int64{1},
},
[]int64{11, 5, 3, 2, 1},
},
{
SearchOptions{
RepoIDs: []int64{2},
},
[]int64{7, 4},
},
{
SearchOptions{
RepoIDs: []int64{3},
},
[]int64{12, 6},
},
{
SearchOptions{
RepoIDs: []int64{4},
},
[]int64{},
},
{
SearchOptions{
RepoIDs: []int64{5},
},
[]int64{15},
},
}

setting.Indexer.IssueType = "db"
InitIssueIndexer(true)
for _, test := range tests {
issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, test.expectedIDs, issueIDs)
}
}

func searchIssueByID(t *testing.T) {
int64Pointer := func(x int64) *int64 {
return &x
}
for _, test := range []struct {
tests := []struct {
opts SearchOptions
expectedIDs []int64
}{
{
SearchOptions{
RepoIDs: []int64{1},
PosterID: int64Pointer(1),
},
[]int64{11, 5, 3, 2, 1},
[]int64{11, 6, 3, 2, 1},
},
{
SearchOptions{
RepoIDs: []int64{1},
AssigneeID: int64Pointer(1),
},
[]int64{6, 1},
},
{
SearchOptions{
MentionID: int64Pointer(4),
},
[]int64{1},
},
{
SearchOptions{
RepoIDs: []int64{1},
PosterID: int64Pointer(1),
ReviewedID: int64Pointer(1),
},
[]int64{},
},
{
SearchOptions{
ReviewRequestedID: int64Pointer(1),
},
[]int64{12},
},
{
SearchOptions{
SubscriberID: int64Pointer(1),
},
[]int64{11, 6, 5, 3, 2, 1},
},
}

for _, test := range tests {
issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, test.expectedIDs, issueIDs)
}
}

func searchIssueIsPull(t *testing.T) {
tests := []struct {
opts SearchOptions
expectedIDs []int64
}{
{
SearchOptions{
IsPull: util.OptionalBoolFalse,
},
[]int64{17, 16, 15, 14, 13, 6, 5, 18, 10, 7, 4, 1},
},
{
SearchOptions{
IsPull: util.OptionalBoolTrue,
},
[]int64{11, 3, 2, 1},
[]int64{12, 11, 19, 9, 8, 3, 2},
},
}
for _, test := range tests {
issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, test.expectedIDs, issueIDs)
}
}

func searchIssueIsClosed(t *testing.T) {
tests := []struct {
opts SearchOptions
expectedIDs []int64
}{
{
SearchOptions{
RepoIDs: []int64{1},
IsClosed: util.OptionalBoolFalse,
},
[]int64{11, 3, 2, 1},
[]int64{17, 16, 15, 14, 13, 12, 11, 6, 19, 18, 10, 7, 9, 8, 3, 2, 1},
},
{
SearchOptions{
RepoIDs: []int64{1},
IsClosed: util.OptionalBoolTrue,
},
[]int64{5},
[]int64{5, 4},
},
}
for _, test := range tests {
issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, test.expectedIDs, issueIDs)
}
}

func searchIssueByMilestoneID(t *testing.T) {
tests := []struct {
opts SearchOptions
expectedIDs []int64
}{
{
SearchOptions{
MilestoneIDs: []int64{1},
},
[]int64{2},
},
{
SearchOptions{
RepoIDs: []int64{1},
MilestoneIDs: []int64{3},
},
[]int64{11, 5, 3, 2, 1},
[]int64{3},
},
}
for _, test := range tests {
issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, test.expectedIDs, issueIDs)
}
}

func searchIssueByLabelID(t *testing.T) {
tests := []struct {
opts SearchOptions
expectedIDs []int64
}{
{
SearchOptions{
IncludedLabelIDs: []int64{1},
},
[]int64{2, 1},
},
{
SearchOptions{
RepoIDs: []int64{1},
AssigneeID: int64Pointer(1),
IncludedLabelIDs: []int64{4},
},
[]int64{2},
},
{
SearchOptions{
ExcludedLabelIDs: []int64{1},
},
[]int64{17, 16, 15, 14, 13, 12, 11, 6, 5, 19, 18, 10, 7, 4, 9, 8, 3},
},
}
for _, test := range tests {
issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, test.expectedIDs, issueIDs)
}
}

func searchIssueByTime(t *testing.T) {
int64Pointer := func(i int64) *int64 {
return &i
}
tests := []struct {
opts SearchOptions
expectedIDs []int64
}{
{
SearchOptions{
UpdatedAfterUnix: int64Pointer(0),
},
[]int64{17, 16, 15, 14, 13, 12, 11, 6, 5, 19, 18, 10, 7, 4, 9, 8, 3, 2, 1},
},
}
for _, test := range tests {
issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, test.expectedIDs, issueIDs)
}
}

func searchIssueWithOrder(t *testing.T) {
tests := []struct {
opts SearchOptions
expectedIDs []int64
}{
{
SearchOptions{
SortBy: internal.SortByCreatedAsc,
},
[]int64{1, 2, 3, 8, 9, 4, 7, 10, 18, 19, 5, 6, 11, 12, 13, 14, 15, 16, 17},
},
}
for _, test := range tests {
issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, test.expectedIDs, issueIDs)
}
}

func searchIssueInProject(t *testing.T) {
int64Pointer := func(i int64) *int64 {
return &i
}
tests := []struct {
opts SearchOptions
expectedIDs []int64
}{
{
SearchOptions{
ProjectID: int64Pointer(1),
},
[]int64{5, 3, 2, 1},
},
{
SearchOptions{
ProjectBoardID: int64Pointer(1),
},
[]int64{1},
},
}
for _, test := range tests {
issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, test.expectedIDs, issueIDs)
}
}

func searchIssueWithPaginator(t *testing.T) {
tests := []struct {
opts SearchOptions
expectedIDs []int64
expectedTotal int64
}{
{
SearchOptions{
RepoIDs: []int64{1},
PosterID: int64Pointer(1),
Paginator: &db.ListOptions{
PageSize: 5,
},
},
[]int64{11, 3, 2, 1},
[]int64{17, 16, 15, 14, 13},
19,
},
} {
t.Run(fmt.Sprintf("%#v", test.opts), func(t *testing.T) {
issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, test.expectedIDs, issueIDs)
})
}
for _, test := range tests {
issueIDs, total, err := SearchIssues(context.TODO(), &test.opts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, test.expectedIDs, issueIDs)
assert.Equal(t, test.expectedTotal, total)
}
}

Loading…
Cancel
Save