github.com/decred/politeia@v1.4.0/politeiawww/legacy/user/cockroachdb/cms_test.go (about)

     1  // Copyright (c) 2020 The Decred developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package cockroachdb
     6  
     7  import (
     8  	"fmt"
     9  	"regexp"
    10  	"strconv"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/DATA-DOG/go-sqlmock"
    15  	"github.com/decred/politeia/politeiawww/legacy/user"
    16  	_ "github.com/jinzhu/gorm/dialects/postgres"
    17  )
    18  
    19  // Tests
    20  func TestNewCodeStats(t *testing.T) {
    21  	cdb, mock, close := setupTestDB(t)
    22  	defer close()
    23  
    24  	// Arguments
    25  	githubName := "github"
    26  	repo := "decred"
    27  	monthAug := 8
    28  	prsAug := []string{"https://github.com/decred/pr/pull/1",
    29  		"https://github.com/decred/pr/pull/2"}
    30  	reviewsAug := []string{"https://github.com/decred/review/pull/1",
    31  		"https://github.com/decred/review/pull/1"}
    32  	mergeAdditionsAug := 100
    33  	mergeDeletionsAug := 99
    34  	updatedAdditionsAug := 300
    35  	updatedDeletionsAug := 299
    36  	reviewAdditionsAug := 200
    37  	reviewDeletionsAug := 199
    38  	commitAdditionsAug := 200
    39  	commitDeletionsAug := 199
    40  
    41  	monthSept := 9
    42  	prsSept := []string{"https://github.com/decred/pr/pull/3",
    43  		"https://github.com/decred/pr/pull/4"}
    44  	reviewsSept := []string{"https://github.com/decred/review/pull/3",
    45  		"https://github.com/decred/review/pull/4"}
    46  	mergeAdditionsSept := 100
    47  	mergeDeletionsSept := 99
    48  	updatedAdditionsSept := 300
    49  	updatedDeletionsSept := 299
    50  	reviewAdditionsSept := 200
    51  	reviewDeletionsSept := 199
    52  	commitAdditionsSept := 200
    53  	commitDeletionsSept := 199
    54  
    55  	year := 2020
    56  
    57  	augID := fmt.Sprintf("%v-%v-%v-%v", githubName, repo, strconv.Itoa(monthAug),
    58  		strconv.Itoa(year))
    59  	codeStats := make([]user.CodeStats, 0, 2)
    60  	codeStats = append(codeStats, user.CodeStats{
    61  		GitHubName:       githubName,
    62  		Repository:       repo,
    63  		Month:            monthAug,
    64  		Year:             year,
    65  		PRs:              prsAug,
    66  		Reviews:          reviewsAug,
    67  		MergedAdditions:  int64(mergeAdditionsAug),
    68  		MergedDeletions:  int64(mergeDeletionsAug),
    69  		UpdatedAdditions: int64(updatedAdditionsAug),
    70  		UpdatedDeletions: int64(updatedDeletionsAug),
    71  		ReviewAdditions:  int64(reviewAdditionsAug),
    72  		ReviewDeletions:  int64(reviewDeletionsAug),
    73  		CommitAdditions:  int64(commitAdditionsAug),
    74  		CommitDeletions:  int64(commitDeletionsAug),
    75  	})
    76  	septID := fmt.Sprintf("%v-%v-%v-%v", githubName, repo,
    77  		strconv.Itoa(monthSept), strconv.Itoa(year))
    78  	codeStats = append(codeStats, user.CodeStats{
    79  		GitHubName:       githubName,
    80  		Repository:       repo,
    81  		Month:            monthSept,
    82  		Year:             year,
    83  		PRs:              prsSept,
    84  		Reviews:          reviewsSept,
    85  		MergedAdditions:  int64(mergeAdditionsSept),
    86  		MergedDeletions:  int64(mergeDeletionsSept),
    87  		UpdatedAdditions: int64(updatedAdditionsSept),
    88  		UpdatedDeletions: int64(updatedDeletionsSept),
    89  		ReviewAdditions:  int64(reviewAdditionsSept),
    90  		ReviewDeletions:  int64(reviewDeletionsSept),
    91  		CommitAdditions:  int64(commitAdditionsSept),
    92  		CommitDeletions:  int64(commitDeletionsSept),
    93  	})
    94  	convertedCodeStatsAug := convertCodestatsToDatabase(codeStats[0])
    95  	convertedCodeStatsSept := convertCodestatsToDatabase(codeStats[1])
    96  	nu := &user.NewCMSCodeStats{
    97  		UserCodeStats: codeStats,
    98  	}
    99  
   100  	// Queries
   101  	sqlInsertCMSCodeStats := `INSERT INTO "cms_code_stats" ` +
   102  		`("id","git_hub_name","repository","month","year","p_rs","reviews",` +
   103  		`"commits",` +
   104  		`"merged_additions","merged_deletions","updated_additions",` +
   105  		`"updated_deletions","review_additions",` +
   106  		`"review_deletions","commit_additions","commit_deletions") VALUES ` +
   107  		`($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16) ` +
   108  		`RETURNING "cms_code_stats"."id"`
   109  
   110  	// Success Expectations
   111  	mock.ExpectBegin()
   112  	// Insert user to db
   113  	mock.ExpectQuery(regexp.QuoteMeta(sqlInsertCMSCodeStats)).
   114  		WithArgs(
   115  			sqlmock.AnyArg(),
   116  			convertedCodeStatsAug.GitHubName,
   117  			convertedCodeStatsAug.Repository,
   118  			convertedCodeStatsAug.Month,
   119  			convertedCodeStatsAug.Year,
   120  			convertedCodeStatsAug.PRs,
   121  			convertedCodeStatsAug.Reviews,
   122  			convertedCodeStatsAug.Commits,
   123  			convertedCodeStatsAug.MergedAdditions,
   124  			convertedCodeStatsAug.MergedDeletions,
   125  			convertedCodeStatsAug.UpdatedAdditions,
   126  			convertedCodeStatsAug.UpdatedDeletions,
   127  			convertedCodeStatsAug.ReviewAdditions,
   128  			convertedCodeStatsAug.ReviewDeletions,
   129  			convertedCodeStatsAug.CommitAdditions,
   130  			convertedCodeStatsAug.CommitDeletions).
   131  		WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(augID))
   132  	mock.ExpectQuery(regexp.QuoteMeta(sqlInsertCMSCodeStats)).
   133  		WithArgs(sqlmock.AnyArg(),
   134  			convertedCodeStatsSept.GitHubName,
   135  			convertedCodeStatsSept.Repository,
   136  			convertedCodeStatsSept.Month,
   137  			convertedCodeStatsSept.Year,
   138  			convertedCodeStatsSept.PRs,
   139  			convertedCodeStatsSept.Reviews,
   140  			convertedCodeStatsSept.Commits,
   141  			convertedCodeStatsSept.MergedAdditions,
   142  			convertedCodeStatsSept.MergedDeletions,
   143  			convertedCodeStatsSept.UpdatedAdditions,
   144  			convertedCodeStatsSept.UpdatedDeletions,
   145  			convertedCodeStatsSept.ReviewAdditions,
   146  			convertedCodeStatsSept.ReviewDeletions,
   147  			convertedCodeStatsSept.CommitAdditions,
   148  			convertedCodeStatsSept.CommitDeletions).
   149  		WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(septID))
   150  	mock.ExpectCommit()
   151  
   152  	// Execute method
   153  	err := cdb.NewCMSCodeStats(nu)
   154  	if err != nil {
   155  		t.Errorf("UserNew unwanted error: %s", err)
   156  	}
   157  
   158  	// Make sure expectations were met for both success and failure
   159  	// conditions
   160  	err = mock.ExpectationsWereMet()
   161  	if err != nil {
   162  		t.Errorf("unfulfilled expectations: %s", err)
   163  	}
   164  }
   165  
   166  func TestUpdateCodeStats(t *testing.T) {
   167  	cdb, mock, close := setupTestDB(t)
   168  	defer close()
   169  
   170  	// Arguments
   171  	githubName := "github"
   172  	repo := "decred"
   173  	monthAug := 8
   174  	mergeAdditionsAug := 100
   175  	mergeDeletionsAug := 99
   176  	updatedAdditionsAug := 300
   177  	updatedDeletionsAug := 299
   178  	reviewAdditionsAug := 200
   179  	reviewDeletionsAug := 199
   180  	commitAdditionsAug := 200
   181  	commitDeletionsAug := 199
   182  	year := 2020
   183  	prsAug := []string{"https://github.com/decred/pr/pull/1",
   184  		"https://github.com/decred/pr/pull/2"}
   185  	reviewsAug := []string{"https://github.com/decred/review/pull/1",
   186  		"https://github.com/decred/review/pull/1"}
   187  	codeStats := make([]user.CodeStats, 0, 1)
   188  	codeStats = append(codeStats, user.CodeStats{
   189  		GitHubName:       githubName,
   190  		Repository:       repo,
   191  		Month:            monthAug,
   192  		Year:             year,
   193  		PRs:              prsAug,
   194  		Reviews:          reviewsAug,
   195  		MergedAdditions:  int64(mergeAdditionsAug),
   196  		MergedDeletions:  int64(mergeDeletionsAug),
   197  		UpdatedAdditions: int64(updatedAdditionsAug),
   198  		UpdatedDeletions: int64(updatedDeletionsAug),
   199  		ReviewAdditions:  int64(reviewAdditionsAug),
   200  		ReviewDeletions:  int64(reviewDeletionsAug),
   201  		CommitAdditions:  int64(commitAdditionsAug),
   202  		CommitDeletions:  int64(commitDeletionsAug),
   203  	})
   204  	ucs := &user.UpdateCMSCodeStats{
   205  		UserCodeStats: codeStats,
   206  	}
   207  	convertCodeStats := convertCodestatsToDatabase(codeStats[0])
   208  	// Query
   209  	sqlUpdateCMSCodeStats := `UPDATE "cms_code_stats" ` +
   210  		`SET "git_hub_name" = $1, "repository" = $2, "month" = $3, ` +
   211  		`"year" = $4, "p_rs" = $5, "reviews" = $6, "commits" = $7, ` +
   212  		`"merged_additions" = $8, ` +
   213  		`"merged_deletions" = $9, "updated_additions" = $10, ` +
   214  		`"updated_deletions" = $11, "review_additions" = $12, ` +
   215  		`"review_deletions" = $13, "commit_additions" = $14, ` +
   216  		`"commit_deletions" = $15 ` +
   217  		`WHERE "cms_code_stats"."id" = $16`
   218  
   219  	augID := fmt.Sprintf("%v-%v-%v-%v", githubName, repo,
   220  		strconv.Itoa(monthAug), strconv.Itoa(year))
   221  
   222  	// Success Expectations
   223  	mock.ExpectBegin()
   224  	mock.ExpectExec(regexp.QuoteMeta(sqlUpdateCMSCodeStats)).
   225  		WithArgs(
   226  			convertCodeStats.GitHubName,
   227  			convertCodeStats.Repository,
   228  			convertCodeStats.Month,
   229  			convertCodeStats.Year,
   230  			convertCodeStats.PRs,
   231  			convertCodeStats.Reviews,
   232  			convertCodeStats.Commits,
   233  			convertCodeStats.MergedAdditions,
   234  			convertCodeStats.MergedDeletions,
   235  			convertCodeStats.UpdatedAdditions,
   236  			convertCodeStats.UpdatedDeletions,
   237  			convertCodeStats.ReviewAdditions,
   238  			convertCodeStats.ReviewDeletions,
   239  			convertCodeStats.CommitAdditions,
   240  			convertCodeStats.CommitDeletions,
   241  			augID).
   242  		WillReturnResult(sqlmock.NewResult(1, 1))
   243  	mock.ExpectCommit()
   244  
   245  	// Execute method
   246  	err := cdb.UpdateCMSCodeStats(ucs)
   247  	if err != nil {
   248  		t.Errorf("UserUpdate unwanted error: %s", err)
   249  	}
   250  
   251  	// Make sure expectations were met
   252  	err = mock.ExpectationsWereMet()
   253  	if err != nil {
   254  		t.Errorf("unfulfilled expectations: %s", err)
   255  	}
   256  }
   257  
   258  func TestCodeStatsByUserMonthYear(t *testing.T) {
   259  	cdb, mock, close := setupTestDB(t)
   260  	defer close()
   261  
   262  	// Arguments
   263  	now := time.Now()
   264  	githubName := "github"
   265  	repo := "decred"
   266  	monthAug := 8
   267  	mergeAdditionsAug := 100
   268  	mergeDeletionsAug := 99
   269  	reviewAdditionsAug := 200
   270  	reviewDeletionsAug := 199
   271  	year := 2020
   272  
   273  	prsAug := "https://github.com/decred/pr/pull/1,https://github.com/decred/pr/pull/2"
   274  	reviewsAug := "https://github.com/decred/review/pull/1,https://github.com/decred/review/pull/1"
   275  
   276  	augID := githubName + repo + strconv.Itoa(monthAug) +
   277  		strconv.Itoa(year)
   278  
   279  	// Mock rows data
   280  	rows := sqlmock.NewRows([]string{
   281  		"id",
   282  		"git_hub_name",
   283  		"repository",
   284  		"month",
   285  		"year",
   286  		"prs",
   287  		"reviews",
   288  		"merge_additions",
   289  		"merge_deletions",
   290  		"review_additions",
   291  		"review_deletions",
   292  		"created_at",
   293  		"updated_at",
   294  	}).AddRow(augID, githubName, repo, monthAug, year, prsAug, reviewsAug,
   295  		mergeAdditionsAug, mergeDeletionsAug, reviewAdditionsAug,
   296  		reviewDeletionsAug, now, now)
   297  
   298  	// Query
   299  	sql := `SELECT * FROM "cms_code_stats" WHERE (git_hub_name = $1 AND ` +
   300  		`month = $2 AND year = $3)`
   301  
   302  	// Success Expectations
   303  	mock.ExpectQuery(regexp.QuoteMeta(sql)).
   304  		WithArgs(githubName, monthAug, year).
   305  		WillReturnRows(rows)
   306  
   307  	csbm := &user.CMSCodeStatsByUserMonthYear{
   308  		GithubName: githubName,
   309  		Month:      monthAug,
   310  		Year:       year,
   311  	}
   312  	// Execute method
   313  	cs, err := cdb.CMSCodeStatsByUserMonthYear(csbm)
   314  	if err != nil {
   315  		t.Errorf("CMSCodeStatsByUserMonthYear unwanted error: %s", err)
   316  	}
   317  	for _, codeStat := range cs {
   318  		// Make sure correct code stat was fetched
   319  		if codeStat.ID != augID {
   320  			t.Errorf("expecting user of id %s but received %s", codeStat.ID,
   321  				augID)
   322  		}
   323  	}
   324  	// Negative Expectations
   325  	randomGithubName := "random"
   326  	csbm = &user.CMSCodeStatsByUserMonthYear{
   327  		GithubName: randomGithubName,
   328  		Month:      monthAug,
   329  		Year:       year,
   330  	}
   331  	expectedError := user.ErrCodeStatsNotFound
   332  	mock.ExpectQuery(regexp.QuoteMeta(sql)).
   333  		WithArgs(randomGithubName, monthAug, year).
   334  		WillReturnError(expectedError)
   335  
   336  	// Execute method
   337  	cs, err = cdb.CMSCodeStatsByUserMonthYear(csbm)
   338  	if err == nil {
   339  		t.Errorf("expecting error but there was none")
   340  	}
   341  
   342  	if len(cs) > 0 {
   343  		t.Errorf("expecting nil user to be returned, but got code stats of "+
   344  			"len %v", len(cs))
   345  	}
   346  
   347  	// Make sure we got the expected error
   348  	if err != expectedError {
   349  		t.Errorf("expecting error %s but got %s", expectedError, err)
   350  	}
   351  
   352  	// Make sure expectations were met for both success and failure
   353  	// conditions
   354  	err = mock.ExpectationsWereMet()
   355  	if err != nil {
   356  		t.Errorf("unfulfilled expectations: %s", err)
   357  	}
   358  }