github.com/vipcoin-gold/reviewdog@v1.0.2/service/bitbucket/annotator_test.go (about)

     1  package bitbucket
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/vipcoin-gold/reviewdog/filter"
     8  	"github.com/vipcoin-gold/reviewdog/proto/rdf"
     9  
    10  	"github.com/vipcoin-gold/reviewdog"
    11  
    12  	"github.com/stretchr/testify/suite"
    13  )
    14  
    15  type AnnotatorTestSuite struct {
    16  	suite.Suite
    17  	cli   *MockAPIClient
    18  	owner string
    19  	repo  string
    20  	sha   string
    21  }
    22  
    23  func (s *AnnotatorTestSuite) SetupTest() {
    24  	s.cli = &MockAPIClient{}
    25  	s.owner = "test-owner"
    26  	s.repo = "test-repo"
    27  	s.sha = "test-commit"
    28  }
    29  
    30  // Empty runners list, no comments
    31  func (s *AnnotatorTestSuite) TestEmptyRunnersList() {
    32  	ctx, annotator := s.createAnnotator(nil)
    33  
    34  	err := annotator.Flush(ctx)
    35  	s.Require().NoError(err)
    36  	s.cli.AssertExpectations(s.T())
    37  }
    38  
    39  // Predefined runners list, and no comments
    40  func (s *AnnotatorTestSuite) TestNoComments() {
    41  	runners := []string{"runner1", "runner2"}
    42  	ctx, annotator := s.createAnnotator(runners)
    43  
    44  	for _, runner := range runners {
    45  		s.assumeReportCreated(ctx, runner, reportResultPassed)
    46  	}
    47  
    48  	err := annotator.Flush(ctx)
    49  
    50  	s.Require().NoError(err)
    51  	s.cli.AssertExpectations(s.T())
    52  }
    53  
    54  // Predefined runners list, and one comment
    55  func (s *AnnotatorTestSuite) TestOneComment() {
    56  	runners := []string{"runner1", "runner2"}
    57  	comments := []*reviewdog.Comment{
    58  		s.buildComment(runners[1], 1),
    59  	}
    60  
    61  	ctx, annotator := s.createAnnotator(runners)
    62  	s.setupExpectedAPICalls(ctx, runners, comments)
    63  
    64  	for _, comment := range comments {
    65  		err := annotator.Post(ctx, comment)
    66  		s.Require().NoError(err)
    67  	}
    68  
    69  	err := annotator.Flush(ctx)
    70  
    71  	s.Require().NoError(err)
    72  	s.cli.AssertExpectations(s.T())
    73  }
    74  
    75  // Predefined runners list, and duplicated comment
    76  func (s *AnnotatorTestSuite) TestDuplicateComments() {
    77  	runners := []string{"runner1", "runner2"}
    78  	comments := []*reviewdog.Comment{
    79  		s.buildComment(runners[1], 1),
    80  		s.buildComment(runners[1], 1),
    81  	}
    82  
    83  	ctx, annotator := s.createAnnotator(runners)
    84  	s.setupExpectedAPICalls(ctx, runners, comments)
    85  
    86  	for _, comment := range comments {
    87  		err := annotator.Post(ctx, comment)
    88  		s.Require().NoError(err)
    89  	}
    90  
    91  	err := annotator.Flush(ctx)
    92  
    93  	s.Require().NoError(err)
    94  	s.cli.AssertExpectations(s.T())
    95  }
    96  
    97  // Predefined runners list, and duplicated comment
    98  func (s *AnnotatorTestSuite) TestManyComments() {
    99  	runners := []string{"runner1", "runner2"}
   100  
   101  	comments := make([]*reviewdog.Comment, 333)
   102  	for idx := 0; idx < 333; idx++ {
   103  		comments[idx] = s.buildComment(runners[1], int32(idx))
   104  	}
   105  
   106  	ctx, annotator := s.createAnnotator(runners)
   107  	s.setupExpectedAPICalls(ctx, runners, comments)
   108  
   109  	for _, comment := range comments {
   110  		err := annotator.Post(ctx, comment)
   111  		s.Require().NoError(err)
   112  	}
   113  
   114  	err := annotator.Flush(ctx)
   115  
   116  	s.Require().NoError(err)
   117  	s.cli.AssertExpectations(s.T())
   118  }
   119  
   120  func (s *AnnotatorTestSuite) createAnnotator(runners []string) (context.Context, *ReportAnnotator) {
   121  	ctx := context.Background()
   122  
   123  	for _, runner := range runners {
   124  		s.assumeReportCreated(ctx, runner, reportResultPending)
   125  	}
   126  
   127  	annotator := NewReportAnnotator(s.cli, s.owner, s.repo, s.sha, runners)
   128  
   129  	return ctx, annotator
   130  }
   131  
   132  func (s *AnnotatorTestSuite) setupExpectedAPICalls(
   133  	ctx context.Context,
   134  	runners []string,
   135  	comments []*reviewdog.Comment,
   136  ) {
   137  	commentsMap := s.splitComments(comments)
   138  
   139  	for _, runner := range runners {
   140  		expResult := reportResultPassed
   141  		if len(commentsMap[runner]) > 0 {
   142  			expResult = reportResultFailed
   143  		}
   144  		s.assumeReportCreated(ctx, runner, expResult)
   145  
   146  		for start, annCount := 0, len(commentsMap[runner]); start < annCount; start += annotationsBatchSize {
   147  			end := start + annotationsBatchSize
   148  
   149  			if end > annCount {
   150  				end = annCount
   151  			}
   152  
   153  			s.assumeAnnotationsCreated(ctx, runner, commentsMap[runner][start:end])
   154  		}
   155  	}
   156  }
   157  
   158  func (s *AnnotatorTestSuite) assumeReportCreated(ctx context.Context, runner string, status string) {
   159  	s.cli.On("CreateOrUpdateReport", ctx, s.buildReportReq(runner, status)).Return(nil).Once()
   160  }
   161  
   162  func (s *AnnotatorTestSuite) assumeAnnotationsCreated(
   163  	ctx context.Context,
   164  	runner string,
   165  	comments []*reviewdog.Comment,
   166  ) {
   167  	s.cli.On("CreateOrUpdateAnnotations", ctx, s.buildAnnotationsRequest(runner, comments)).Return(nil).Once()
   168  }
   169  
   170  func (s *AnnotatorTestSuite) buildReportReq(runner string, result string) *ReportRequest {
   171  	report := &ReportRequest{
   172  		ReportID:   reportID(runner, reporter),
   173  		Owner:      s.owner,
   174  		Repository: s.repo,
   175  		Commit:     s.sha,
   176  		Type:       reportTypeBug,
   177  		Title:      reportTitle(runner, reporter),
   178  		Reporter:   reporter,
   179  		Result:     result,
   180  		LogoURL:    logoURL,
   181  	}
   182  
   183  	switch result {
   184  	case reportResultPassed:
   185  		report.Details = "Great news! Reviewdog couldn't spot any issues!"
   186  	case reportResultPending:
   187  		report.Details = "Please wait for Reviewdog to finish checking your code for issues."
   188  	default:
   189  		report.Details = "Woof-Woof! This report generated for you by reviewdog."
   190  	}
   191  
   192  	return report
   193  }
   194  
   195  func (s *AnnotatorTestSuite) buildAnnotationsRequest(runner string, comments []*reviewdog.Comment) *AnnotationsRequest {
   196  	return &AnnotationsRequest{
   197  		Owner:      s.owner,
   198  		Repository: s.repo,
   199  		Commit:     s.sha,
   200  		ReportID:   reportID(runner, reporter),
   201  		Comments:   comments,
   202  	}
   203  }
   204  
   205  func (s *AnnotatorTestSuite) buildComment(toolName string, line int32) *reviewdog.Comment {
   206  	return &reviewdog.Comment{
   207  		ToolName: toolName,
   208  		Result: &filter.FilteredDiagnostic{
   209  			Diagnostic: &rdf.Diagnostic{
   210  				Location: &rdf.Location{
   211  					Path: "main.go",
   212  					Range: &rdf.Range{Start: &rdf.Position{
   213  						Line: line,
   214  					}},
   215  				},
   216  				Message: "test message",
   217  			},
   218  		},
   219  	}
   220  }
   221  
   222  func (s *AnnotatorTestSuite) splitComments(comments []*reviewdog.Comment) map[string][]*reviewdog.Comment {
   223  	commentsMap := make(map[string][]*reviewdog.Comment)
   224  	duplicates := make(map[string]struct{})
   225  
   226  	for _, comment := range comments {
   227  		externalID := externalIDFromDiagnostic(comment.Result.Diagnostic)
   228  		if _, exist := duplicates[externalID]; !exist {
   229  			commentsMap[comment.ToolName] = append(commentsMap[comment.ToolName], comment)
   230  			duplicates[externalID] = struct{}{}
   231  		}
   232  	}
   233  
   234  	return commentsMap
   235  }
   236  
   237  func TestAnnotatorTestSuite(t *testing.T) {
   238  	suite.Run(t, &AnnotatorTestSuite{})
   239  }