From 4b23e6a69449b985c74ad797257c30250e60ec9a Mon Sep 17 00:00:00 2001
From: Ethan Koenig <etk39@cornell.edu>
Date: Sun, 8 Jan 2017 22:08:36 -0500
Subject: [PATCH] Unit tests for models/action (#619)

---
 models/access_test.go      |  28 +--
 models/action_test.go      | 340 +++++++++++++++++++++++++++++++++++++
 models/fixtures/action.yml |  22 +++
 models/fixtures/user.yml   |   5 +
 models/setup_for_test.go   |  23 ++-
 5 files changed, 398 insertions(+), 20 deletions(-)
 create mode 100644 models/action_test.go
 create mode 100644 models/fixtures/action.yml

diff --git a/models/access_test.go b/models/access_test.go
index c9847f0069..a2e59b3e96 100644
--- a/models/access_test.go
+++ b/models/access_test.go
@@ -19,10 +19,10 @@ var accessModes = []AccessMode{
 func TestAccessLevel(t *testing.T) {
 	assert.NoError(t, PrepareTestDatabase())
 
-	user1 := &User{ID: 2}; LoadTestFixture(t, user1)
-	user2 := &User{ID: 4}; LoadTestFixture(t, user2)
-	repo1 := &Repository{OwnerID: 2, IsPrivate: false}; LoadTestFixture(t, repo1)
-	repo2 := &Repository{OwnerID: 3, IsPrivate: true}; LoadTestFixture(t, repo2)
+	user1 := &User{ID: 2}; AssertExistsAndLoadBean(t, user1)
+	user2 := &User{ID: 4}; AssertExistsAndLoadBean(t, user2)
+	repo1 := &Repository{OwnerID: 2, IsPrivate: false}; AssertExistsAndLoadBean(t, repo1)
+	repo2 := &Repository{OwnerID: 3, IsPrivate: true}; AssertExistsAndLoadBean(t, repo2)
 
 	level, err := AccessLevel(user1, repo1)
 	assert.NoError(t, err)
@@ -44,10 +44,10 @@ func TestAccessLevel(t *testing.T) {
 func TestHasAccess(t *testing.T) {
 	assert.NoError(t, PrepareTestDatabase())
 
-	user1 := &User{ID: 2}; LoadTestFixture(t, user1)
-	user2 := &User{ID: 4}; LoadTestFixture(t, user2)
-	repo1 := &Repository{OwnerID: 2, IsPrivate: false}; LoadTestFixture(t, repo1)
-	repo2 := &Repository{OwnerID: 3, IsPrivate: true}; LoadTestFixture(t, repo2)
+	user1 := &User{ID: 2}; AssertExistsAndLoadBean(t, user1)
+	user2 := &User{ID: 4}; AssertExistsAndLoadBean(t, user2)
+	repo1 := &Repository{OwnerID: 2, IsPrivate: false}; AssertExistsAndLoadBean(t, repo1)
+	repo2 := &Repository{OwnerID: 3, IsPrivate: true}; AssertExistsAndLoadBean(t, repo2)
 
 	for _, accessMode := range accessModes {
 		has, err := HasAccess(user1, repo1, accessMode)
@@ -71,8 +71,8 @@ func TestHasAccess(t *testing.T) {
 func TestUser_GetRepositoryAccesses(t *testing.T) {
 	assert.NoError(t, PrepareTestDatabase())
 
-	user1 := &User{ID: 1}; LoadTestFixture(t, user1)
-	user2 := &User{ID: 2}; LoadTestFixture(t, user2)
+	user1 := &User{ID: 1}; AssertExistsAndLoadBean(t, user1)
+	user2 := &User{ID: 2}; AssertExistsAndLoadBean(t, user2)
 
 	accesses, err := user1.GetRepositoryAccesses()
 	assert.NoError(t, err)
@@ -82,8 +82,8 @@ func TestUser_GetRepositoryAccesses(t *testing.T) {
 func TestUser_GetAccessibleRepositories(t *testing.T) {
 	assert.NoError(t, PrepareTestDatabase())
 
-	user1 := &User{ID: 1}; LoadTestFixture(t, user1)
-	user2 := &User{ID: 2}; LoadTestFixture(t, user2)
+	user1 := &User{ID: 1}; AssertExistsAndLoadBean(t, user1)
+	user2 := &User{ID: 2}; AssertExistsAndLoadBean(t, user2)
 
 	repos, err := user1.GetAccessibleRepositories(0)
 	assert.NoError(t, err)
@@ -98,7 +98,7 @@ func TestUser_GetAccessibleRepositories(t *testing.T) {
 func TestRepository_RecalculateAccesses(t *testing.T) {
 	// test with organization repo
 	assert.NoError(t, PrepareTestDatabase())
-	repo1 := &Repository{ID: 3}; LoadTestFixture(t, repo1)
+	repo1 := &Repository{ID: 3}; AssertExistsAndLoadBean(t, repo1)
 	assert.NoError(t, repo1.GetOwner())
 
 	sess := x.NewSession()
@@ -119,7 +119,7 @@ func TestRepository_RecalculateAccesses(t *testing.T) {
 func TestRepository_RecalculateAccesses2(t *testing.T) {
 	// test with non-organization repo
 	assert.NoError(t, PrepareTestDatabase())
-	repo1 := &Repository{ID: 4}; LoadTestFixture(t, repo1)
+	repo1 := &Repository{ID: 4}; AssertExistsAndLoadBean(t, repo1)
 	assert.NoError(t, repo1.GetOwner())
 
 	sess := x.NewSession()
diff --git a/models/action_test.go b/models/action_test.go
new file mode 100644
index 0000000000..f60bc511b1
--- /dev/null
+++ b/models/action_test.go
@@ -0,0 +1,340 @@
+package models
+
+import (
+	"testing"
+
+	"code.gitea.io/gitea/modules/setting"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestAction_GetRepoPath(t *testing.T) {
+	action := &Action{
+		RepoUserName: "username",
+		RepoName:     "reponame",
+	}
+	assert.Equal(t, "username/reponame", action.GetRepoPath())
+}
+
+func TestAction_GetRepoLink(t *testing.T) {
+	action := &Action{
+		RepoUserName: "username",
+		RepoName:     "reponame",
+	}
+	setting.AppSubURL = "/suburl/"
+	assert.Equal(t, "/suburl/username/reponame", action.GetRepoLink())
+	setting.AppSubURL = ""
+	assert.Equal(t, "/username/reponame", action.GetRepoLink())
+}
+
+func TestNewRepoAction(t *testing.T) {
+	assert.NoError(t, PrepareTestDatabase())
+
+	user := &User{ID: 2}
+	AssertExistsAndLoadBean(t, user)
+	repo := &Repository{OwnerID: user.ID}
+	AssertExistsAndLoadBean(t, repo)
+	repo.Owner = user
+
+	actionBean := &Action{
+		OpType:       ActionCreateRepo,
+		ActUserID:    user.ID,
+		RepoID:       repo.ID,
+		ActUserName:  user.Name,
+		RepoName:     repo.Name,
+		RepoUserName: repo.Owner.Name,
+		IsPrivate:    repo.IsPrivate,
+	}
+
+	AssertNotExistsBean(t, actionBean)
+	assert.NoError(t, NewRepoAction(user, repo))
+	AssertExistsAndLoadBean(t, actionBean)
+}
+
+func TestRenameRepoAction(t *testing.T) {
+	assert.NoError(t, PrepareTestDatabase())
+
+	user := &User{ID: 2}
+	AssertExistsAndLoadBean(t, user)
+	repo := &Repository{OwnerID: user.ID}
+	AssertExistsAndLoadBean(t, repo)
+	repo.Owner = user
+
+	oldRepoName := repo.Name
+	const newRepoName = "newRepoName"
+	repo.Name = newRepoName
+
+	actionBean := &Action{
+		OpType:       ActionRenameRepo,
+		ActUserID:    user.ID,
+		ActUserName:  user.Name,
+		RepoID:       repo.ID,
+		RepoName:     repo.Name,
+		RepoUserName: repo.Owner.Name,
+		IsPrivate:    repo.IsPrivate,
+		Content:      oldRepoName,
+	}
+	AssertNotExistsBean(t, actionBean)
+	assert.NoError(t, RenameRepoAction(user, oldRepoName, repo))
+	AssertExistsAndLoadBean(t, actionBean)
+}
+
+func TestPushCommits_ToAPIPayloadCommits(t *testing.T) {
+	pushCommits := NewPushCommits()
+	pushCommits.Commits = []*PushCommit{
+		{
+			Sha1:           "abcdef1",
+			CommitterEmail: "user2@example.com",
+			CommitterName:  "User Two",
+			AuthorEmail:    "user4@example.com",
+			AuthorName:     "User Four",
+			Message:        "message1",
+		},
+		{
+			Sha1:           "abcdef2",
+			CommitterEmail: "user2@example.com",
+			CommitterName:  "User Two",
+			AuthorEmail:    "user2@example.com",
+			AuthorName:     "User Two",
+			Message:        "message2",
+		},
+	}
+	pushCommits.Len = len(pushCommits.Commits)
+
+	payloadCommits := pushCommits.ToAPIPayloadCommits("/username/reponame")
+	assert.Len(t, payloadCommits, 2)
+	assert.Equal(t, "abcdef1", payloadCommits[0].ID)
+	assert.Equal(t, "message1", payloadCommits[0].Message)
+	assert.Equal(t, "/username/reponame/commit/abcdef1", payloadCommits[0].URL)
+	assert.Equal(t, "User Two", payloadCommits[0].Committer.Name)
+	assert.Equal(t, "user2", payloadCommits[0].Committer.UserName)
+	assert.Equal(t, "User Four", payloadCommits[0].Author.Name)
+	assert.Equal(t, "user4", payloadCommits[0].Author.UserName)
+
+	assert.Equal(t, "abcdef2", payloadCommits[1].ID)
+	assert.Equal(t, "message2", payloadCommits[1].Message)
+	assert.Equal(t, "/username/reponame/commit/abcdef2", payloadCommits[1].URL)
+	assert.Equal(t, "User Two", payloadCommits[1].Committer.Name)
+	assert.Equal(t, "user2", payloadCommits[1].Committer.UserName)
+	assert.Equal(t, "User Two", payloadCommits[1].Author.Name)
+	assert.Equal(t, "user2", payloadCommits[1].Author.UserName)
+}
+
+func TestPushCommits_AvatarLink(t *testing.T) {
+	pushCommits := NewPushCommits()
+	pushCommits.Commits = []*PushCommit{
+		{
+			Sha1:           "abcdef1",
+			CommitterEmail: "user2@example.com",
+			CommitterName:  "User Two",
+			AuthorEmail:    "user4@example.com",
+			AuthorName:     "User Four",
+			Message:        "message1",
+		},
+		{
+			Sha1:           "abcdef2",
+			CommitterEmail: "user2@example.com",
+			CommitterName:  "User Two",
+			AuthorEmail:    "user2@example.com",
+			AuthorName:     "User Two",
+			Message:        "message2",
+		},
+	}
+	pushCommits.Len = len(pushCommits.Commits)
+
+	assert.Equal(t,
+		"https://secure.gravatar.com/avatar/ab53a2911ddf9b4817ac01ddcd3d975f",
+		pushCommits.AvatarLink("user2@example.com"))
+
+	assert.Equal(t,
+		"https://secure.gravatar.com/avatar/19ade630b94e1e0535b3df7387434154",
+		pushCommits.AvatarLink("nonexistent@example.com"))
+}
+
+func TestUpdateIssuesCommit(t *testing.T) {
+	assert.NoError(t, PrepareTestDatabase())
+	pushCommits := []*PushCommit{
+		{
+			Sha1:           "abcdef1",
+			CommitterEmail: "user2@example.com",
+			CommitterName:  "User Two",
+			AuthorEmail:    "user4@example.com",
+			AuthorName:     "User Four",
+			Message:        "start working on #1",
+		},
+		{
+			Sha1:           "abcdef2",
+			CommitterEmail: "user2@example.com",
+			CommitterName:  "User Two",
+			AuthorEmail:    "user2@example.com",
+			AuthorName:     "User Two",
+			Message:        "a plain message",
+		},
+		{
+			Sha1:           "abcdef2",
+			CommitterEmail: "user2@example.com",
+			CommitterName:  "User Two",
+			AuthorEmail:    "user2@example.com",
+			AuthorName:     "User Two",
+			Message:        "close #2",
+		},
+	}
+
+	user := &User{ID: 2}
+	AssertExistsAndLoadBean(t, user)
+	repo := &Repository{ID: 1}
+	AssertExistsAndLoadBean(t, repo)
+	repo.Owner = user
+
+	commentBean := &Comment{
+		Type:      CommentTypeCommitRef,
+		CommitSHA: "abcdef1",
+		PosterID:  user.ID,
+		IssueID:   1,
+	}
+	issueBean := &Issue{RepoID: repo.ID, Index: 2}
+
+	AssertNotExistsBean(t, commentBean)
+	AssertNotExistsBean(t, &Issue{RepoID: repo.ID, Index: 2}, "is_closed=1")
+	assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits))
+	AssertExistsAndLoadBean(t, commentBean)
+	AssertExistsAndLoadBean(t, issueBean, "is_closed=1")
+}
+
+func TestCommitRepoAction(t *testing.T) {
+	assert.NoError(t, PrepareTestDatabase())
+
+	user := &User{ID: 2}
+	AssertExistsAndLoadBean(t, user)
+	repo := &Repository{ID: 2, OwnerID: user.ID}
+	AssertExistsAndLoadBean(t, repo)
+	repo.Owner = user
+
+	pushCommits := NewPushCommits()
+	pushCommits.Commits = []*PushCommit{
+		{
+			Sha1:           "abcdef1",
+			CommitterEmail: "user2@example.com",
+			CommitterName:  "User Two",
+			AuthorEmail:    "user4@example.com",
+			AuthorName:     "User Four",
+			Message:        "message1",
+		},
+		{
+			Sha1:           "abcdef2",
+			CommitterEmail: "user2@example.com",
+			CommitterName:  "User Two",
+			AuthorEmail:    "user2@example.com",
+			AuthorName:     "User Two",
+			Message:        "message2",
+		},
+	}
+	pushCommits.Len = len(pushCommits.Commits)
+
+	actionBean := &Action{
+		OpType:      ActionCommitRepo,
+		ActUserID:   user.ID,
+		ActUserName: user.Name,
+		RepoID:      repo.ID,
+		RepoName:    repo.Name,
+		RefName:     "refName",
+		IsPrivate:   repo.IsPrivate,
+	}
+	AssertNotExistsBean(t, actionBean)
+	assert.NoError(t, CommitRepoAction(CommitRepoActionOptions{
+		PusherName:  user.Name,
+		RepoOwnerID: user.ID,
+		RepoName:    repo.Name,
+		RefFullName: "refName",
+		OldCommitID: "oldCommitID",
+		NewCommitID: "newCommitID",
+		Commits:     pushCommits,
+	}))
+	AssertExistsAndLoadBean(t, actionBean)
+}
+
+func TestTransferRepoAction(t *testing.T) {
+	assert.NoError(t, PrepareTestDatabase())
+
+	user2 := &User{ID: 2}
+	AssertExistsAndLoadBean(t, user2)
+	user4 := &User{ID: 4}
+	AssertExistsAndLoadBean(t, user4)
+	repo := &Repository{ID: 1, OwnerID: user2.ID}
+	AssertExistsAndLoadBean(t, repo)
+
+	repo.OwnerID = user4.ID
+	repo.Owner = user4
+
+	actionBean := &Action{
+		OpType:       ActionTransferRepo,
+		ActUserID:    user2.ID,
+		ActUserName:  user2.Name,
+		RepoID:       repo.ID,
+		RepoName:     repo.Name,
+		RepoUserName: repo.Owner.Name,
+		IsPrivate:    repo.IsPrivate,
+	}
+	AssertNotExistsBean(t, actionBean)
+	assert.NoError(t, TransferRepoAction(user2, user2, repo))
+	AssertExistsAndLoadBean(t, actionBean)
+}
+
+func TestMergePullRequestAction(t *testing.T) {
+	assert.NoError(t, PrepareTestDatabase())
+	user := &User{ID: 2}
+	AssertExistsAndLoadBean(t, user)
+	repo := &Repository{ID: 1, OwnerID: user.ID}
+	AssertExistsAndLoadBean(t, repo)
+	repo.Owner = user
+	issue := &Issue{ID: 3, RepoID: repo.ID}
+	AssertExistsAndLoadBean(t, issue)
+
+	actionBean := &Action{
+		OpType:       ActionMergePullRequest,
+		ActUserID:    user.ID,
+		ActUserName:  user.Name,
+		RepoID:       repo.ID,
+		RepoName:     repo.Name,
+		RepoUserName: repo.Owner.Name,
+		IsPrivate:    repo.IsPrivate,
+	}
+	AssertNotExistsBean(t, actionBean)
+	assert.NoError(t, MergePullRequestAction(user, repo, issue))
+	AssertExistsAndLoadBean(t, actionBean)
+}
+
+func TestGetFeeds(t *testing.T) {
+	// test with an individual user
+	assert.NoError(t, PrepareTestDatabase())
+	user := &User{ID: 2}
+	AssertExistsAndLoadBean(t, user)
+
+	actions, err := GetFeeds(user, user.ID, 0, false)
+	assert.NoError(t, err)
+	assert.Len(t, actions, 1)
+	assert.Equal(t, int64(1), actions[0].ID)
+	assert.Equal(t, user.ID, actions[0].UserID)
+
+	actions, err = GetFeeds(user, user.ID, 0, true)
+	assert.NoError(t, err)
+	assert.Len(t, actions, 0)
+}
+
+func TestGetFeeds2(t *testing.T) {
+	// test with an organization user
+	assert.NoError(t, PrepareTestDatabase())
+	user := &User{ID: 3}
+	AssertExistsAndLoadBean(t, user)
+
+	actions, err := GetFeeds(user, user.ID, 0, false)
+	assert.NoError(t, err)
+	assert.Len(t, actions, 1)
+	assert.Equal(t, int64(2), actions[0].ID)
+	assert.Equal(t, user.ID, actions[0].UserID)
+
+	actions, err = GetFeeds(user, user.ID, 0, true)
+	assert.NoError(t, err)
+	assert.Len(t, actions, 1)
+	assert.Equal(t, int64(2), actions[0].ID)
+	assert.Equal(t, user.ID, actions[0].UserID)
+}
diff --git a/models/fixtures/action.yml b/models/fixtures/action.yml
new file mode 100644
index 0000000000..f4f10dde2b
--- /dev/null
+++ b/models/fixtures/action.yml
@@ -0,0 +1,22 @@
+-
+  id: 1
+  user_id: 2
+  op_type: 12 # close issue
+  act_user_id: 2
+  act_user_name: user2
+  repo_id: 2
+  repo_user_name: user2
+  repo_name: repo2
+  is_private: true
+
+-
+  id: 2
+  user_id: 3
+  op_type: 2 # rename repo
+  act_user_id: 3
+  act_user_name: user3
+  repo_id: 3
+  repo_user_name: user3
+  repo_name: repo3 # TODO old or new name?
+  is_private: false
+  content: oldRepoName
diff --git a/models/fixtures/user.yml b/models/fixtures/user.yml
index cb3b954a22..a38b4016e3 100644
--- a/models/fixtures/user.yml
+++ b/models/fixtures/user.yml
@@ -2,6 +2,7 @@
   id: 1
   lower_name: user1
   name: user1
+  full_name: User One
   email: user1@example.com
   passwd: password
   type: 0 # individual
@@ -15,6 +16,7 @@
   id: 2
   lower_name: user2
   name: user2
+  full_name: User Two
   email: user2@example.com
   passwd: password
   type: 0 # individual
@@ -28,6 +30,7 @@
   id: 3
   lower_name: user3
   name: user3
+  full_name: User Three
   email: user3@example.com
   passwd: password
   type: 1 # organization
@@ -41,6 +44,7 @@
   id: 4
   lower_name: user4
   name: user4
+  full_name: User Four
   email: user4@example.com
   passwd: password
   type: 1 # individual
@@ -54,6 +58,7 @@
   id: 5
   lower_name: user5
   name: user5
+  full_name: User Five
   email: user5@example.com
   passwd: password
   type: 1 # individual
diff --git a/models/setup_for_test.go b/models/setup_for_test.go
index cf88397c26..7d21768945 100644
--- a/models/setup_for_test.go
+++ b/models/setup_for_test.go
@@ -47,16 +47,27 @@ func PrepareTestDatabase() error {
 	return fixtures.Load()
 }
 
-// LoadFixture load a test fixture from the test database, failing if fixture
-// does not exist
-func LoadTestFixture(t *testing.T, fixture interface{}, conditions... interface{}) {
+func loadBeanIfExists(bean interface{}, conditions ...interface{}) (bool, error) {
 	sess := x.NewSession()
 	defer sess.Close()
 
 	for _, cond := range conditions {
 		sess = sess.Where(cond)
 	}
-	has, err := sess.Get(fixture)
-	assert.NoError(t, err)
-	assert.True(t, has)
+	return sess.Get(bean)
+}
+
+// AssertExistsAndLoadBean assert that a bean exists and load it from the test
+// database
+func AssertExistsAndLoadBean(t *testing.T, bean interface{}, conditions ...interface{}) {
+	exists, err := loadBeanIfExists(bean, conditions...)
+	assert.NoError(t, err)
+	assert.True(t, exists)
+}
+
+// AssertNotExistsBean assert that a bean does not exist in the test database
+func AssertNotExistsBean(t *testing.T, bean interface{}, conditions ...interface{}) {
+	exists, err := loadBeanIfExists(bean, conditions...)
+	assert.NoError(t, err)
+	assert.False(t, exists)
 }