2017-02-07 14:47:55 +03:00
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package models
import (
"reflect"
2017-02-28 04:42:10 +03:00
"strings"
2017-02-07 14:47:55 +03:00
"testing"
"github.com/stretchr/testify/assert"
)
2017-05-20 11:48:22 +03:00
// consistencyCheckable a type that can be tested for database consistency
type consistencyCheckable interface {
checkForConsistency ( t * testing . T )
2017-02-07 14:47:55 +03:00
}
// CheckConsistencyForAll test that the entire database is consistent
func CheckConsistencyForAll ( t * testing . T ) {
CheckConsistencyFor ( t ,
& User { } ,
& Repository { } ,
& Issue { } ,
& PullRequest { } ,
& Milestone { } ,
& Label { } ,
2017-02-28 04:42:10 +03:00
& Team { } ,
& Action { } )
2017-02-07 14:47:55 +03:00
}
// CheckConsistencyFor test that all matching database entries are consistent
func CheckConsistencyFor ( t * testing . T , beansToCheck ... interface { } ) {
for _ , bean := range beansToCheck {
sliceType := reflect . SliceOf ( reflect . TypeOf ( bean ) )
sliceValue := reflect . MakeSlice ( sliceType , 0 , 10 )
ptrToSliceValue := reflect . New ( sliceType )
ptrToSliceValue . Elem ( ) . Set ( sliceValue )
2019-06-23 18:22:43 +03:00
assert . NoError ( t , x . Table ( bean ) . Find ( ptrToSliceValue . Interface ( ) ) )
2017-02-07 14:47:55 +03:00
sliceValue = ptrToSliceValue . Elem ( )
for i := 0 ; i < sliceValue . Len ( ) ; i ++ {
entity := sliceValue . Index ( i ) . Interface ( )
2017-05-20 11:48:22 +03:00
checkable , ok := entity . ( consistencyCheckable )
2017-02-07 14:47:55 +03:00
if ! ok {
t . Errorf ( "Expected %+v (of type %T) to be checkable for consistency" ,
entity , entity )
} else {
2017-05-20 11:48:22 +03:00
checkable . checkForConsistency ( t )
2017-02-07 14:47:55 +03:00
}
}
}
}
// getCount get the count of database entries matching bean
func getCount ( t * testing . T , e Engine , bean interface { } ) int64 {
count , err := e . Count ( bean )
assert . NoError ( t , err )
return count
}
// assertCount test the count of database entries matching bean
func assertCount ( t * testing . T , bean interface { } , expected int ) {
assert . EqualValues ( t , expected , getCount ( t , x , bean ) ,
"Failed consistency test, the counted bean (of type %T) was %+v" , bean , bean )
}
2017-05-20 11:48:22 +03:00
func ( user * User ) checkForConsistency ( t * testing . T ) {
2017-02-07 14:47:55 +03:00
assertCount ( t , & Repository { OwnerID : user . ID } , user . NumRepos )
assertCount ( t , & Star { UID : user . ID } , user . NumStars )
assertCount ( t , & OrgUser { OrgID : user . ID } , user . NumMembers )
assertCount ( t , & Team { OrgID : user . ID } , user . NumTeams )
assertCount ( t , & Follow { UserID : user . ID } , user . NumFollowing )
assertCount ( t , & Follow { FollowID : user . ID } , user . NumFollowers )
2017-02-08 09:29:21 +03:00
if user . Type != UserTypeOrganization {
assert . EqualValues ( t , 0 , user . NumMembers )
assert . EqualValues ( t , 0 , user . NumTeams )
}
2017-02-07 14:47:55 +03:00
}
2017-05-20 11:48:22 +03:00
func ( repo * Repository ) checkForConsistency ( t * testing . T ) {
2017-02-28 04:42:10 +03:00
assert . Equal ( t , repo . LowerName , strings . ToLower ( repo . Name ) , "repo: %+v" , repo )
2017-02-07 14:47:55 +03:00
assertCount ( t , & Star { RepoID : repo . ID } , repo . NumStars )
assertCount ( t , & Milestone { RepoID : repo . ID } , repo . NumMilestones )
assertCount ( t , & Repository { ForkID : repo . ID } , repo . NumForks )
if repo . IsFork {
AssertExistsAndLoadBean ( t , & Repository { ID : repo . ForkID } )
}
2019-11-10 12:22:19 +03:00
actual := getCount ( t , x . Where ( "Mode<>?" , RepoWatchModeDont ) , & Watch { RepoID : repo . ID } )
assert . EqualValues ( t , repo . NumWatches , actual ,
"Unexpected number of watches for repo %+v" , repo )
actual = getCount ( t , x . Where ( "is_pull=?" , false ) , & Issue { RepoID : repo . ID } )
2017-02-08 09:29:21 +03:00
assert . EqualValues ( t , repo . NumIssues , actual ,
"Unexpected number of issues for repo %+v" , repo )
actual = getCount ( t , x . Where ( "is_pull=? AND is_closed=?" , false , true ) , & Issue { RepoID : repo . ID } )
2017-02-07 14:47:55 +03:00
assert . EqualValues ( t , repo . NumClosedIssues , actual ,
"Unexpected number of closed issues for repo %+v" , repo )
2017-02-08 09:29:21 +03:00
actual = getCount ( t , x . Where ( "is_pull=?" , true ) , & Issue { RepoID : repo . ID } )
2017-02-07 14:47:55 +03:00
assert . EqualValues ( t , repo . NumPulls , actual ,
"Unexpected number of pulls for repo %+v" , repo )
2017-02-08 09:29:21 +03:00
actual = getCount ( t , x . Where ( "is_pull=? AND is_closed=?" , true , true ) , & Issue { RepoID : repo . ID } )
2017-02-07 14:47:55 +03:00
assert . EqualValues ( t , repo . NumClosedPulls , actual ,
"Unexpected number of closed pulls for repo %+v" , repo )
2017-02-08 09:29:21 +03:00
actual = getCount ( t , x . Where ( "is_closed=?" , true ) , & Milestone { RepoID : repo . ID } )
2017-02-07 14:47:55 +03:00
assert . EqualValues ( t , repo . NumClosedMilestones , actual ,
"Unexpected number of closed milestones for repo %+v" , repo )
}
2017-05-20 11:48:22 +03:00
func ( issue * Issue ) checkForConsistency ( t * testing . T ) {
2017-02-08 09:29:21 +03:00
actual := getCount ( t , x . Where ( "type=?" , CommentTypeComment ) , & Comment { IssueID : issue . ID } )
assert . EqualValues ( t , issue . NumComments , actual ,
"Unexpected number of comments for issue %+v" , issue )
2017-02-07 14:47:55 +03:00
if issue . IsPull {
pr := AssertExistsAndLoadBean ( t , & PullRequest { IssueID : issue . ID } ) . ( * PullRequest )
assert . EqualValues ( t , pr . Index , issue . Index )
}
}
2017-05-20 11:48:22 +03:00
func ( pr * PullRequest ) checkForConsistency ( t * testing . T ) {
2017-02-07 14:47:55 +03:00
issue := AssertExistsAndLoadBean ( t , & Issue { ID : pr . IssueID } ) . ( * Issue )
assert . True ( t , issue . IsPull )
assert . EqualValues ( t , issue . Index , pr . Index )
}
2017-05-20 11:48:22 +03:00
func ( milestone * Milestone ) checkForConsistency ( t * testing . T ) {
2017-02-07 14:47:55 +03:00
assertCount ( t , & Issue { MilestoneID : milestone . ID } , milestone . NumIssues )
2017-02-08 09:29:21 +03:00
actual := getCount ( t , x . Where ( "is_closed=?" , true ) , & Issue { MilestoneID : milestone . ID } )
2017-02-07 14:47:55 +03:00
assert . EqualValues ( t , milestone . NumClosedIssues , actual ,
"Unexpected number of closed issues for milestone %+v" , milestone )
}
2017-05-20 11:48:22 +03:00
func ( label * Label ) checkForConsistency ( t * testing . T ) {
2017-02-07 14:47:55 +03:00
issueLabels := make ( [ ] * IssueLabel , 0 , 10 )
assert . NoError ( t , x . Find ( & issueLabels , & IssueLabel { LabelID : label . ID } ) )
assert . EqualValues ( t , label . NumIssues , len ( issueLabels ) ,
"Unexpected number of issue for label %+v" , label )
issueIDs := make ( [ ] int64 , len ( issueLabels ) )
for i , issueLabel := range issueLabels {
issueIDs [ i ] = issueLabel . IssueID
}
expected := int64 ( 0 )
if len ( issueIDs ) > 0 {
2017-02-08 09:29:21 +03:00
expected = getCount ( t , x . In ( "id" , issueIDs ) . Where ( "is_closed=?" , true ) , & Issue { } )
2017-02-07 14:47:55 +03:00
}
assert . EqualValues ( t , expected , label . NumClosedIssues ,
"Unexpected number of closed issues for label %+v" , label )
}
2017-05-20 11:48:22 +03:00
func ( team * Team ) checkForConsistency ( t * testing . T ) {
2017-02-07 14:47:55 +03:00
assertCount ( t , & TeamUser { TeamID : team . ID } , team . NumMembers )
assertCount ( t , & TeamRepo { TeamID : team . ID } , team . NumRepos )
}
2017-02-28 04:42:10 +03:00
2017-05-20 11:48:22 +03:00
func ( action * Action ) checkForConsistency ( t * testing . T ) {
2017-02-28 04:42:10 +03:00
repo := AssertExistsAndLoadBean ( t , & Repository { ID : action . RepoID } ) . ( * Repository )
assert . Equal ( t , repo . IsPrivate , action . IsPrivate , "action: %+v" , action )
}