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  }