github.com/reviewdog/reviewdog@v0.17.5-0.20240516205324-0cd103a83d58/filter/filter_test.go (about)

     1  package filter
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	"github.com/google/go-cmp/cmp"
     8  	"google.golang.org/protobuf/testing/protocmp"
     9  
    10  	"github.com/reviewdog/reviewdog/diff"
    11  	"github.com/reviewdog/reviewdog/proto/rdf"
    12  )
    13  
    14  const diffContent = `--- sample.old.txt	2016-10-13 05:09:35.820791185 +0900
    15  +++ sample.new.txt	2016-10-13 05:15:26.839245048 +0900
    16  @@ -1,3 +1,4 @@
    17   unchanged, contextual line
    18  -deleted line
    19  +added line
    20  +added line
    21   unchanged, contextual line
    22  --- nonewline.old.txt	2016-10-13 15:34:14.931778318 +0900
    23  +++ nonewline.new.txt	2016-10-13 15:34:14.868444672 +0900
    24  @@ -1,4 +1,4 @@
    25   " vim: nofixeol noendofline
    26   No newline at end of both the old and new file
    27  -a
    28  -a
    29  \ No newline at end of file
    30  +b
    31  +b
    32  \ No newline at end of file
    33  `
    34  
    35  const diffContentAddedStrip = `diff --git a/test_added.go b/test_added.go
    36  new file mode 100644
    37  index 0000000..264c67e
    38  --- /dev/null
    39  +++ b/test_added.go
    40  @@ -0,0 +1,3 @@
    41  +package reviewdog
    42  +
    43  +var TestAdded = 14
    44  `
    45  
    46  func TestFilterCheckByAddedLines(t *testing.T) {
    47  	results := []*rdf.Diagnostic{
    48  		{
    49  			Location: &rdf.Location{
    50  				Path:  "sample.new.txt",
    51  				Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
    52  			},
    53  		},
    54  		{
    55  			Location: &rdf.Location{
    56  				Path:  "sample.new.txt",
    57  				Range: &rdf.Range{Start: &rdf.Position{Line: 2}},
    58  			},
    59  		},
    60  		{
    61  			Location: &rdf.Location{
    62  				Path:  "nonewline.new.txt",
    63  				Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
    64  			},
    65  		},
    66  		{
    67  			Location: &rdf.Location{
    68  				Path:  "nonewline.new.txt",
    69  				Range: &rdf.Range{Start: &rdf.Position{Line: 3}},
    70  			},
    71  		},
    72  		{
    73  			Message: "outside range (start)",
    74  			Location: &rdf.Location{
    75  				Path: "sample.new.txt",
    76  				Range: &rdf.Range{
    77  					Start: &rdf.Position{Line: 1},
    78  					End:   &rdf.Position{Line: 2},
    79  				},
    80  			},
    81  		},
    82  	}
    83  	want := []*FilteredDiagnostic{
    84  		{
    85  			Diagnostic: &rdf.Diagnostic{
    86  				Location: &rdf.Location{
    87  					Path:  "sample.new.txt",
    88  					Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
    89  				},
    90  			},
    91  			ShouldReport:  false,
    92  			InDiffFile:    true,
    93  			InDiffContext: true,
    94  			SourceLines:   map[int]string{1: "unchanged, contextual line"},
    95  			OldPath:       "sample.old.txt",
    96  			OldLine:       1,
    97  		},
    98  		{
    99  			Diagnostic: &rdf.Diagnostic{
   100  				Location: &rdf.Location{
   101  					Path:  "sample.new.txt",
   102  					Range: &rdf.Range{Start: &rdf.Position{Line: 2}},
   103  				},
   104  			},
   105  			ShouldReport:  true,
   106  			InDiffFile:    true,
   107  			InDiffContext: true,
   108  			SourceLines:   map[int]string{2: "added line"},
   109  			OldPath:       "sample.old.txt",
   110  			OldLine:       0,
   111  		},
   112  		{
   113  			Diagnostic: &rdf.Diagnostic{
   114  				Location: &rdf.Location{
   115  					Path:  "nonewline.new.txt",
   116  					Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
   117  				},
   118  			},
   119  			ShouldReport:  false,
   120  			InDiffFile:    true,
   121  			InDiffContext: true,
   122  			SourceLines:   map[int]string{1: `" vim: nofixeol noendofline`},
   123  			OldPath:       "nonewline.old.txt",
   124  			OldLine:       1,
   125  		},
   126  		{
   127  			Diagnostic: &rdf.Diagnostic{
   128  				Location: &rdf.Location{
   129  					Path:  "nonewline.new.txt",
   130  					Range: &rdf.Range{Start: &rdf.Position{Line: 3}},
   131  				},
   132  			},
   133  			ShouldReport:  true,
   134  			InDiffFile:    true,
   135  			InDiffContext: true,
   136  			SourceLines:   map[int]string{3: "b"},
   137  			OldPath:       "nonewline.old.txt",
   138  			OldLine:       0,
   139  		},
   140  		{
   141  			Diagnostic: &rdf.Diagnostic{
   142  				Message: "outside range (start)",
   143  				Location: &rdf.Location{
   144  					Path: "sample.new.txt",
   145  					Range: &rdf.Range{
   146  						Start: &rdf.Position{Line: 1},
   147  						End:   &rdf.Position{Line: 2},
   148  					},
   149  				},
   150  			},
   151  			ShouldReport:  true,
   152  			InDiffFile:    true,
   153  			InDiffContext: true,
   154  			SourceLines:   map[int]string{1: "unchanged, contextual line", 2: "added line"},
   155  			OldPath:       "sample.old.txt",
   156  			OldLine:       1,
   157  		},
   158  	}
   159  	filediffs, _ := diff.ParseMultiFile(strings.NewReader(diffContent))
   160  	got := FilterCheck(results, filediffs, 0, "", ModeAdded)
   161  	if value := cmp.Diff(got, want, protocmp.Transform()); value != "" {
   162  		t.Error(value)
   163  	}
   164  }
   165  
   166  // All lines that are in diff are taken into account
   167  func TestFilterCheckByDiffContext(t *testing.T) {
   168  	results := []*rdf.Diagnostic{
   169  		{
   170  			Location: &rdf.Location{
   171  				Path:  "sample.new.txt",
   172  				Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
   173  			},
   174  		},
   175  		{
   176  			Location: &rdf.Location{
   177  				Path:  "sample.new.txt",
   178  				Range: &rdf.Range{Start: &rdf.Position{Line: 2}},
   179  			},
   180  		},
   181  		{
   182  			Location: &rdf.Location{
   183  				Path:  "sample.new.txt",
   184  				Range: &rdf.Range{Start: &rdf.Position{Line: 3}},
   185  			},
   186  		},
   187  		{
   188  			Location: &rdf.Location{
   189  				Path:  "sample.new.txt",
   190  				Range: &rdf.Range{Start: &rdf.Position{Line: 3}},
   191  			},
   192  			Suggestions: []*rdf.Suggestion{
   193  				{
   194  					Range: &rdf.Range{
   195  						Start: &rdf.Position{Line: 2},
   196  						End:   &rdf.Position{Line: 4},
   197  					},
   198  				},
   199  			},
   200  		},
   201  	}
   202  	want := []*FilteredDiagnostic{
   203  		{
   204  			Diagnostic: &rdf.Diagnostic{
   205  				Location: &rdf.Location{
   206  					Path:  "sample.new.txt",
   207  					Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
   208  				},
   209  			},
   210  			ShouldReport:  true,
   211  			InDiffFile:    true,
   212  			InDiffContext: true,
   213  			SourceLines:   map[int]string{1: "unchanged, contextual line"},
   214  			OldPath:       "sample.old.txt",
   215  			OldLine:       1,
   216  		},
   217  		{
   218  			Diagnostic: &rdf.Diagnostic{
   219  				Location: &rdf.Location{
   220  					Path:  "sample.new.txt",
   221  					Range: &rdf.Range{Start: &rdf.Position{Line: 2}},
   222  				},
   223  			},
   224  			ShouldReport:  true,
   225  			InDiffFile:    true,
   226  			InDiffContext: true,
   227  			SourceLines:   map[int]string{2: "added line"},
   228  			OldPath:       "sample.old.txt",
   229  			OldLine:       0,
   230  		},
   231  		{
   232  			Diagnostic: &rdf.Diagnostic{
   233  				Location: &rdf.Location{
   234  					Path:  "sample.new.txt",
   235  					Range: &rdf.Range{Start: &rdf.Position{Line: 3}},
   236  				},
   237  			},
   238  			ShouldReport:  true,
   239  			InDiffFile:    true,
   240  			InDiffContext: true,
   241  			SourceLines:   map[int]string{3: "added line"},
   242  			OldPath:       "sample.old.txt",
   243  			OldLine:       0,
   244  		},
   245  		{
   246  			Diagnostic: &rdf.Diagnostic{
   247  				Location: &rdf.Location{
   248  					Path:  "sample.new.txt",
   249  					Range: &rdf.Range{Start: &rdf.Position{Line: 3}},
   250  				},
   251  				Suggestions: []*rdf.Suggestion{
   252  					{
   253  						Range: &rdf.Range{
   254  							Start: &rdf.Position{Line: 2},
   255  							End:   &rdf.Position{Line: 4},
   256  						},
   257  					},
   258  				},
   259  			},
   260  			ShouldReport:                 true,
   261  			InDiffFile:                   true,
   262  			InDiffContext:                true,
   263  			FirstSuggestionInDiffContext: true,
   264  			SourceLines: map[int]string{
   265  				2: "added line",
   266  				3: "added line",
   267  				4: "unchanged, contextual line",
   268  			},
   269  			OldPath: "sample.old.txt",
   270  			OldLine: 0,
   271  		},
   272  	}
   273  	filediffs, _ := diff.ParseMultiFile(strings.NewReader(diffContent))
   274  	got := FilterCheck(results, filediffs, 0, "", ModeDiffContext)
   275  	if value := cmp.Diff(got, want, protocmp.Transform()); value != "" {
   276  		t.Error(value)
   277  	}
   278  }
   279  
   280  func TestFilterCheckByFile(t *testing.T) {
   281  	results := []*rdf.Diagnostic{
   282  		{
   283  			Location: &rdf.Location{
   284  				Path:  "sample.new.txt",
   285  				Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
   286  			},
   287  		},
   288  		{
   289  			Location: &rdf.Location{
   290  				Path:  "sample.new.txt",
   291  				Range: &rdf.Range{Start: &rdf.Position{Line: 2}},
   292  			},
   293  		},
   294  		{
   295  			Message: "outside line",
   296  			Location: &rdf.Location{
   297  				Path:  "sample.new.txt",
   298  				Range: &rdf.Range{Start: &rdf.Position{Line: 5}},
   299  			},
   300  		},
   301  		{
   302  			Message: "outside range (start)",
   303  			Location: &rdf.Location{
   304  				Path: "sample.new.txt",
   305  				Range: &rdf.Range{
   306  					Start: &rdf.Position{Line: 1},
   307  					End:   &rdf.Position{Line: 2},
   308  				},
   309  			},
   310  		},
   311  		{
   312  			Message: "without line",
   313  			Location: &rdf.Location{
   314  				Path:  "sample.new.txt",
   315  				Range: &rdf.Range{Start: &rdf.Position{}},
   316  			},
   317  		},
   318  		{
   319  			Location: &rdf.Location{
   320  				Path:  "unchanged.txt",
   321  				Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
   322  			},
   323  		},
   324  	}
   325  	want := []*FilteredDiagnostic{
   326  		{
   327  			Diagnostic: &rdf.Diagnostic{
   328  				Location: &rdf.Location{
   329  					Path:  "sample.new.txt",
   330  					Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
   331  				},
   332  			},
   333  			ShouldReport:  true,
   334  			InDiffFile:    true,
   335  			InDiffContext: true,
   336  			SourceLines:   map[int]string{1: "unchanged, contextual line"},
   337  			OldPath:       "sample.old.txt",
   338  			OldLine:       1,
   339  		},
   340  		{
   341  			Diagnostic: &rdf.Diagnostic{
   342  				Location: &rdf.Location{
   343  					Path:  "sample.new.txt",
   344  					Range: &rdf.Range{Start: &rdf.Position{Line: 2}},
   345  				},
   346  			},
   347  			ShouldReport:  true,
   348  			InDiffFile:    true,
   349  			InDiffContext: true,
   350  			SourceLines:   map[int]string{2: "added line"},
   351  			OldPath:       "sample.old.txt",
   352  			OldLine:       0,
   353  		},
   354  		{
   355  			Diagnostic: &rdf.Diagnostic{
   356  				Message: "outside line",
   357  				Location: &rdf.Location{
   358  					Path:  "sample.new.txt",
   359  					Range: &rdf.Range{Start: &rdf.Position{Line: 5}},
   360  				},
   361  			},
   362  			ShouldReport:  true,
   363  			InDiffFile:    true,
   364  			InDiffContext: false,
   365  			SourceLines:   map[int]string{},
   366  			OldPath:       "sample.old.txt",
   367  			OldLine:       4,
   368  		},
   369  		{
   370  			Diagnostic: &rdf.Diagnostic{
   371  				Message: "outside range (start)",
   372  				Location: &rdf.Location{
   373  					Path: "sample.new.txt",
   374  					Range: &rdf.Range{
   375  						Start: &rdf.Position{Line: 1},
   376  						End:   &rdf.Position{Line: 2},
   377  					},
   378  				},
   379  			},
   380  			ShouldReport:  true,
   381  			InDiffFile:    true,
   382  			InDiffContext: true,
   383  			SourceLines: map[int]string{
   384  				1: "unchanged, contextual line",
   385  				2: "added line",
   386  			},
   387  			OldPath: "sample.old.txt",
   388  			OldLine: 1,
   389  		},
   390  		{
   391  			Diagnostic: &rdf.Diagnostic{
   392  				Message: "without line",
   393  				Location: &rdf.Location{
   394  					Path:  "sample.new.txt",
   395  					Range: &rdf.Range{Start: &rdf.Position{}},
   396  				},
   397  			},
   398  			ShouldReport:  true,
   399  			InDiffFile:    true,
   400  			InDiffContext: false,
   401  			SourceLines:   map[int]string{},
   402  			OldPath:       "sample.old.txt",
   403  			OldLine:       0,
   404  		},
   405  		{
   406  			Diagnostic: &rdf.Diagnostic{
   407  				Location: &rdf.Location{
   408  					Path:  "unchanged.txt",
   409  					Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
   410  				},
   411  			},
   412  			ShouldReport:  false,
   413  			InDiffFile:    false,
   414  			InDiffContext: false,
   415  			SourceLines:   map[int]string{},
   416  		},
   417  	}
   418  	filediffs, _ := diff.ParseMultiFile(strings.NewReader(diffContent))
   419  	got := FilterCheck(results, filediffs, 0, "", ModeFile)
   420  	if value := cmp.Diff(got, want, protocmp.Transform()); value != "" {
   421  		t.Error(value)
   422  	}
   423  }
   424  
   425  func TestFilterCheckByNoFilter(t *testing.T) {
   426  	results := []*rdf.Diagnostic{
   427  		{
   428  			Location: &rdf.Location{
   429  				Path:  "sample.new.txt",
   430  				Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
   431  			},
   432  		},
   433  		{
   434  			Location: &rdf.Location{
   435  				Path:  "sample.new.txt",
   436  				Range: &rdf.Range{Start: &rdf.Position{Line: 2}},
   437  			},
   438  		},
   439  		{
   440  			Message: "outside line",
   441  			Location: &rdf.Location{
   442  				Path:  "sample.new.txt",
   443  				Range: &rdf.Range{Start: &rdf.Position{Line: 5}},
   444  			},
   445  		},
   446  		{
   447  			Message: "outside range (start)",
   448  			Location: &rdf.Location{
   449  				Path: "sample.new.txt",
   450  				Range: &rdf.Range{
   451  					Start: &rdf.Position{Line: 1},
   452  					End:   &rdf.Position{Line: 2},
   453  				},
   454  			},
   455  		},
   456  		{
   457  			Message: "without line",
   458  			Location: &rdf.Location{
   459  				Path:  "sample.new.txt",
   460  				Range: &rdf.Range{Start: &rdf.Position{}},
   461  			},
   462  		},
   463  		{
   464  			Location: &rdf.Location{
   465  				Path:  "unchanged.txt",
   466  				Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
   467  			},
   468  		},
   469  	}
   470  	want := []*FilteredDiagnostic{
   471  		{
   472  			Diagnostic: &rdf.Diagnostic{
   473  				Location: &rdf.Location{
   474  					Path:  "sample.new.txt",
   475  					Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
   476  				},
   477  			},
   478  			ShouldReport:  true,
   479  			InDiffFile:    true,
   480  			InDiffContext: true,
   481  			SourceLines:   map[int]string{1: "unchanged, contextual line"},
   482  			OldPath:       "sample.old.txt",
   483  			OldLine:       1,
   484  		},
   485  		{
   486  			Diagnostic: &rdf.Diagnostic{
   487  				Location: &rdf.Location{
   488  					Path:  "sample.new.txt",
   489  					Range: &rdf.Range{Start: &rdf.Position{Line: 2}},
   490  				},
   491  			},
   492  			ShouldReport:  true,
   493  			InDiffFile:    true,
   494  			InDiffContext: true,
   495  			SourceLines:   map[int]string{2: "added line"},
   496  			OldPath:       "sample.old.txt",
   497  			OldLine:       0,
   498  		},
   499  		{
   500  			Diagnostic: &rdf.Diagnostic{
   501  				Message: "outside line",
   502  				Location: &rdf.Location{
   503  					Path:  "sample.new.txt",
   504  					Range: &rdf.Range{Start: &rdf.Position{Line: 5}},
   505  				},
   506  			},
   507  			ShouldReport:  true,
   508  			InDiffFile:    true,
   509  			InDiffContext: false,
   510  			SourceLines:   map[int]string{},
   511  			OldPath:       "sample.old.txt",
   512  			OldLine:       4,
   513  		},
   514  		{
   515  			Diagnostic: &rdf.Diagnostic{
   516  				Message: "outside range (start)",
   517  				Location: &rdf.Location{
   518  					Path: "sample.new.txt",
   519  					Range: &rdf.Range{
   520  						Start: &rdf.Position{Line: 1},
   521  						End:   &rdf.Position{Line: 2},
   522  					},
   523  				},
   524  			},
   525  			ShouldReport:  true,
   526  			InDiffFile:    true,
   527  			InDiffContext: true,
   528  			SourceLines: map[int]string{
   529  				1: "unchanged, contextual line",
   530  				2: "added line",
   531  			},
   532  			OldPath: "sample.old.txt",
   533  			OldLine: 1,
   534  		},
   535  		{
   536  			Diagnostic: &rdf.Diagnostic{
   537  				Message: "without line",
   538  				Location: &rdf.Location{
   539  					Path:  "sample.new.txt",
   540  					Range: &rdf.Range{Start: &rdf.Position{}},
   541  				},
   542  			},
   543  			ShouldReport:  true,
   544  			InDiffFile:    true,
   545  			InDiffContext: false,
   546  			SourceLines:   map[int]string{},
   547  			OldPath:       "sample.old.txt",
   548  			OldLine:       0,
   549  		},
   550  		{
   551  			Diagnostic: &rdf.Diagnostic{
   552  				Location: &rdf.Location{
   553  					Path:  "unchanged.txt",
   554  					Range: &rdf.Range{Start: &rdf.Position{Line: 1}},
   555  				},
   556  			},
   557  			ShouldReport:  true,
   558  			InDiffFile:    false,
   559  			InDiffContext: false,
   560  			SourceLines:   map[int]string{},
   561  		},
   562  	}
   563  	filediffs, _ := diff.ParseMultiFile(strings.NewReader(diffContent))
   564  	got := FilterCheck(results, filediffs, 0, "", ModeNoFilter)
   565  	if value := cmp.Diff(got, want, protocmp.Transform()); value != "" {
   566  		t.Error(value)
   567  	}
   568  }
   569  
   570  func findFileDiff(filediffs []*diff.FileDiff, path string, strip int) *diff.FileDiff {
   571  	for _, file := range filediffs {
   572  		if NormalizeDiffPath(file.PathNew, strip) == path {
   573  			return file
   574  		}
   575  	}
   576  	return nil
   577  }
   578  
   579  func TestGetOldPosition(t *testing.T) {
   580  	const strip = 0
   581  	filediffs, _ := diff.ParseMultiFile(strings.NewReader(diffContent))
   582  	tests := []struct {
   583  		newPath     string
   584  		newLine     int
   585  		wantOldPath string
   586  		wantOldLine int
   587  	}{
   588  		{
   589  			newPath:     "sample.new.txt",
   590  			newLine:     1,
   591  			wantOldPath: "sample.old.txt",
   592  			wantOldLine: 1,
   593  		},
   594  		{
   595  			newPath:     "sample.new.txt",
   596  			newLine:     2,
   597  			wantOldPath: "sample.old.txt",
   598  			wantOldLine: 0,
   599  		},
   600  		{
   601  			newPath:     "sample.new.txt",
   602  			newLine:     3,
   603  			wantOldPath: "sample.old.txt",
   604  			wantOldLine: 0,
   605  		},
   606  		{
   607  			newPath:     "sample.new.txt",
   608  			newLine:     14,
   609  			wantOldPath: "sample.old.txt",
   610  			wantOldLine: 13,
   611  		},
   612  		{
   613  			newPath:     "not_found",
   614  			newLine:     14,
   615  			wantOldPath: "",
   616  			wantOldLine: 0,
   617  		},
   618  	}
   619  	for _, tt := range tests {
   620  		fdiff := findFileDiff(filediffs, tt.newPath, strip)
   621  		gotPath, gotLine := getOldPosition(fdiff, strip, tt.newPath, tt.newLine)
   622  		if !(gotPath == tt.wantOldPath && gotLine == tt.wantOldLine) {
   623  			t.Errorf("getOldPosition(..., %s, %d) = (%s, %d), want (%s, %d)",
   624  				tt.newPath, tt.newLine, gotPath, gotLine, tt.wantOldPath, tt.wantOldLine)
   625  		}
   626  	}
   627  }
   628  
   629  func TestGetOldPosition_added(t *testing.T) {
   630  	const strip = 1
   631  	filediffs, _ := diff.ParseMultiFile(strings.NewReader(diffContentAddedStrip))
   632  	path := "test_added.go"
   633  	fdiff := findFileDiff(filediffs, path, strip)
   634  	gotPath, _ := getOldPosition(fdiff, strip, path, 1)
   635  	if gotPath != "" {
   636  		t.Errorf("got %q as old path for added diff file, want empty", gotPath)
   637  	}
   638  }