summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEthan Koenig <etk39@cornell.edu>2017-02-04 07:37:26 -0500
committerLunny Xiao <xiaolunwen@gmail.com>2017-02-04 20:37:26 +0800
commitd0960b80354c0c8326063c8408d2274adb50dec1 (patch)
tree7c082f5d30bee7a526c42a33031981b247eb537e
parentd4035d1cb143a758463f2e3ee9d037fd5dab72f9 (diff)
downloadgitea-d0960b80354c0c8326063c8408d2274adb50dec1.tar.gz
gitea-d0960b80354c0c8326063c8408d2274adb50dec1.zip
Move IssueUser code to separate file (#836)
Also add unit tests
-rw-r--r--models/fixtures/issue.yml1
-rw-r--r--models/fixtures/issue_user.yml23
-rw-r--r--models/issue.go125
-rw-r--r--models/issue_user.go113
-rw-r--r--models/issue_user_test.go74
-rw-r--r--models/setup_for_test.go16
6 files changed, 226 insertions, 126 deletions
diff --git a/models/fixtures/issue.yml b/models/fixtures/issue.yml
index 8bcadb0aae..662f2235d7 100644
--- a/models/fixtures/issue.yml
+++ b/models/fixtures/issue.yml
@@ -3,6 +3,7 @@
repo_id: 1
index: 1
poster_id: 1
+ assignee_id: 1
name: issue1
content: content1
is_closed: false
diff --git a/models/fixtures/issue_user.yml b/models/fixtures/issue_user.yml
new file mode 100644
index 0000000000..b3f98a71d3
--- /dev/null
+++ b/models/fixtures/issue_user.yml
@@ -0,0 +1,23 @@
+-
+ id: 1
+ uid: 1
+ issue_id: 1
+ is_read: true
+ is_assigned: true
+ is_mentioned: false
+
+-
+ id: 2
+ uid: 2
+ issue_id: 1
+ is_read: true
+ is_assigned: false
+ is_mentioned: false
+
+-
+ id: 3
+ uid: 4
+ issue_id: 1
+ is_read: false
+ is_assigned: false
+ is_mentioned: false
diff --git a/models/issue.go b/models/issue.go
index 7d7591837e..2f4c157920 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -1106,70 +1106,6 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
return issues, nil
}
-// .___ ____ ___
-// | | ______ ________ __ ____ | | \______ ___________
-// | |/ ___// ___/ | \_/ __ \| | / ___// __ \_ __ \
-// | |\___ \ \___ \| | /\ ___/| | /\___ \\ ___/| | \/
-// |___/____ >____ >____/ \___ >______//____ >\___ >__|
-// \/ \/ \/ \/ \/
-
-// IssueUser represents an issue-user relation.
-type IssueUser struct {
- ID int64 `xorm:"pk autoincr"`
- UID int64 `xorm:"INDEX"` // User ID.
- IssueID int64
- IsRead bool
- IsAssigned bool
- IsMentioned bool
-}
-
-func newIssueUsers(e *xorm.Session, repo *Repository, issue *Issue) error {
- assignees, err := repo.getAssignees(e)
- if err != nil {
- return fmt.Errorf("getAssignees: %v", err)
- }
-
- // Poster can be anyone, append later if not one of assignees.
- isPosterAssignee := false
-
- // Leave a seat for poster itself to append later, but if poster is one of assignee
- // and just waste 1 unit is cheaper than re-allocate memory once.
- issueUsers := make([]*IssueUser, 0, len(assignees)+1)
- for _, assignee := range assignees {
- issueUsers = append(issueUsers, &IssueUser{
- IssueID: issue.ID,
- UID: assignee.ID,
- IsAssigned: assignee.ID == issue.AssigneeID,
- })
- isPosterAssignee = isPosterAssignee || assignee.ID == issue.PosterID
- }
- if !isPosterAssignee {
- issueUsers = append(issueUsers, &IssueUser{
- IssueID: issue.ID,
- UID: issue.PosterID,
- })
- }
-
- if _, err = e.Insert(issueUsers); err != nil {
- return err
- }
- return nil
-}
-
-// NewIssueUsers adds new issue-user relations for new issue of repository.
-func NewIssueUsers(repo *Repository, issue *Issue) (err error) {
- sess := x.NewSession()
- defer sessionRelease(sess)
- if err = sess.Begin(); err != nil {
- return err
- }
-
- if err = newIssueUsers(sess, repo, issue); err != nil {
- return err
- }
-
- return sess.Commit()
-}
// UpdateIssueMentions extracts mentioned people from content and
// updates issue-user relations for them.
@@ -1400,67 +1336,6 @@ func UpdateIssue(issue *Issue) error {
return updateIssue(x, issue)
}
-func updateIssueUserByAssignee(e *xorm.Session, issue *Issue) (err error) {
- if _, err = e.Exec("UPDATE `issue_user` SET is_assigned = ? WHERE issue_id = ?", false, issue.ID); err != nil {
- return err
- }
-
- // Assignee ID equals to 0 means clear assignee.
- if issue.AssigneeID > 0 {
- if _, err = e.Exec("UPDATE `issue_user` SET is_assigned = ? WHERE uid = ? AND issue_id = ?", true, issue.AssigneeID, issue.ID); err != nil {
- return err
- }
- }
-
- return updateIssue(e, issue)
-}
-
-// UpdateIssueUserByAssignee updates issue-user relation for assignee.
-func UpdateIssueUserByAssignee(issue *Issue) (err error) {
- sess := x.NewSession()
- defer sessionRelease(sess)
- if err = sess.Begin(); err != nil {
- return err
- }
-
- if err = updateIssueUserByAssignee(sess, issue); err != nil {
- return err
- }
-
- return sess.Commit()
-}
-
-// UpdateIssueUserByRead updates issue-user relation for reading.
-func UpdateIssueUserByRead(uid, issueID int64) error {
- _, err := x.Exec("UPDATE `issue_user` SET is_read=? WHERE uid=? AND issue_id=?", true, uid, issueID)
- return err
-}
-
-// UpdateIssueUsersByMentions updates issue-user pairs by mentioning.
-func UpdateIssueUsersByMentions(e Engine, issueID int64, uids []int64) error {
- for _, uid := range uids {
- iu := &IssueUser{
- UID: uid,
- IssueID: issueID,
- }
- has, err := e.Get(iu)
- if err != nil {
- return err
- }
-
- iu.IsMentioned = true
- if has {
- _, err = e.Id(iu.ID).AllCols().Update(iu)
- } else {
- _, err = e.Insert(iu)
- }
- if err != nil {
- return err
- }
- }
- return nil
-}
-
// _____ .__.__ __
// / \ |__| | ____ _______/ |_ ____ ____ ____
// / \ / \| | | _/ __ \ / ___/\ __\/ _ \ / \_/ __ \
diff --git a/models/issue_user.go b/models/issue_user.go
new file mode 100644
index 0000000000..cb11a8a076
--- /dev/null
+++ b/models/issue_user.go
@@ -0,0 +1,113 @@
+// Copyright 2017 The Gogs 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 (
+ "fmt"
+)
+
+// IssueUser represents an issue-user relation.
+type IssueUser struct {
+ ID int64 `xorm:"pk autoincr"`
+ UID int64 `xorm:"INDEX"` // User ID.
+ IssueID int64
+ IsRead bool
+ IsAssigned bool
+ IsMentioned bool
+}
+
+func newIssueUsers(e Engine, repo *Repository, issue *Issue) error {
+ assignees, err := repo.getAssignees(e)
+ if err != nil {
+ return fmt.Errorf("getAssignees: %v", err)
+ }
+
+ // Poster can be anyone, append later if not one of assignees.
+ isPosterAssignee := false
+
+ // Leave a seat for poster itself to append later, but if poster is one of assignee
+ // and just waste 1 unit is cheaper than re-allocate memory once.
+ issueUsers := make([]*IssueUser, 0, len(assignees)+1)
+ for _, assignee := range assignees {
+ issueUsers = append(issueUsers, &IssueUser{
+ IssueID: issue.ID,
+ UID: assignee.ID,
+ IsAssigned: assignee.ID == issue.AssigneeID,
+ })
+ isPosterAssignee = isPosterAssignee || assignee.ID == issue.PosterID
+ }
+ if !isPosterAssignee {
+ issueUsers = append(issueUsers, &IssueUser{
+ IssueID: issue.ID,
+ UID: issue.PosterID,
+ })
+ }
+
+ if _, err = e.Insert(issueUsers); err != nil {
+ return err
+ }
+ return nil
+}
+
+func updateIssueUserByAssignee(e Engine, issue *Issue) (err error) {
+ if _, err = e.Exec("UPDATE `issue_user` SET is_assigned = ? WHERE issue_id = ?", false, issue.ID); err != nil {
+ return err
+ }
+
+ // Assignee ID equals to 0 means clear assignee.
+ if issue.AssigneeID > 0 {
+ if _, err = e.Exec("UPDATE `issue_user` SET is_assigned = ? WHERE uid = ? AND issue_id = ?", true, issue.AssigneeID, issue.ID); err != nil {
+ return err
+ }
+ }
+
+ return updateIssue(e, issue)
+}
+
+// UpdateIssueUserByAssignee updates issue-user relation for assignee.
+func UpdateIssueUserByAssignee(issue *Issue) (err error) {
+ sess := x.NewSession()
+ defer sessionRelease(sess)
+ if err = sess.Begin(); err != nil {
+ return err
+ }
+
+ if err = updateIssueUserByAssignee(sess, issue); err != nil {
+ return err
+ }
+
+ return sess.Commit()
+}
+
+// UpdateIssueUserByRead updates issue-user relation for reading.
+func UpdateIssueUserByRead(uid, issueID int64) error {
+ _, err := x.Exec("UPDATE `issue_user` SET is_read=? WHERE uid=? AND issue_id=?", true, uid, issueID)
+ return err
+}
+
+// UpdateIssueUsersByMentions updates issue-user pairs by mentioning.
+func UpdateIssueUsersByMentions(e Engine, issueID int64, uids []int64) error {
+ for _, uid := range uids {
+ iu := &IssueUser{
+ UID: uid,
+ IssueID: issueID,
+ }
+ has, err := e.Get(iu)
+ if err != nil {
+ return err
+ }
+
+ iu.IsMentioned = true
+ if has {
+ _, err = e.Id(iu.ID).AllCols().Update(iu)
+ } else {
+ _, err = e.Insert(iu)
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/models/issue_user_test.go b/models/issue_user_test.go
new file mode 100644
index 0000000000..e3ebfa8fa2
--- /dev/null
+++ b/models/issue_user_test.go
@@ -0,0 +1,74 @@
+// Copyright 2017 The Gogs 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 (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func Test_newIssueUsers(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+
+ repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
+ newIssue := &Issue{
+ RepoID: repo.ID,
+ PosterID: 4,
+ Index: 5,
+ Title: "newTestIssueTitle",
+ Content: "newTestIssueContent",
+ }
+
+ // artificially insert new issue
+ AssertSuccessfulInsert(t, newIssue)
+
+ assert.NoError(t, newIssueUsers(x, repo, newIssue))
+
+ // issue_user table should now have entries for new issue
+ AssertExistsAndLoadBean(t, &IssueUser{IssueID: newIssue.ID, UID: newIssue.PosterID})
+ AssertExistsAndLoadBean(t, &IssueUser{IssueID: newIssue.ID, UID: repo.OwnerID})
+}
+
+func TestUpdateIssueUserByAssignee(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+ issue := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
+
+ // artificially change assignee in issue_user table
+ AssertSuccessfulInsert(t, &IssueUser{IssueID: issue.ID, UID: 5, IsAssigned: true})
+ _, err := x.Cols("is_assigned").
+ Update(&IssueUser{IsAssigned: false}, &IssueUser{IssueID: issue.ID, UID: issue.AssigneeID})
+ assert.NoError(t, err)
+
+ assert.NoError(t, UpdateIssueUserByAssignee(issue))
+
+ // issue_user table should now be correct again
+ AssertExistsAndLoadBean(t, &IssueUser{IssueID: issue.ID, UID: issue.AssigneeID}, "is_assigned=1")
+ AssertExistsAndLoadBean(t, &IssueUser{IssueID: issue.ID, UID: 5}, "is_assigned=0")
+}
+
+func TestUpdateIssueUserByRead(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+ issue := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
+
+ assert.NoError(t, UpdateIssueUserByRead(4, issue.ID))
+ AssertExistsAndLoadBean(t, &IssueUser{IssueID: issue.ID, UID: 4}, "is_read=1")
+
+ assert.NoError(t, UpdateIssueUserByRead(4, issue.ID))
+ AssertExistsAndLoadBean(t, &IssueUser{IssueID: issue.ID, UID: 4}, "is_read=1")
+
+ assert.NoError(t, UpdateIssueUserByRead(NonexistentID, NonexistentID))
+}
+
+func TestUpdateIssueUsersByMentions(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+ issue := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
+
+ uids := []int64{2, 5}
+ assert.NoError(t, UpdateIssueUsersByMentions(x, issue.ID, uids))
+ for _, uid := range uids {
+ AssertExistsAndLoadBean(t, &IssueUser{IssueID: issue.ID, UID: uid}, "is_mentioned=1")
+ }
+}
diff --git a/models/setup_for_test.go b/models/setup_for_test.go
index fd5a180aec..651e36e822 100644
--- a/models/setup_for_test.go
+++ b/models/setup_for_test.go
@@ -51,6 +51,7 @@ func CreateTestEngine() error {
if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil {
return err
}
+
fixtures, err = testfixtures.NewFolder(x.DB().DB, &testfixtures.SQLite{}, "fixtures/")
return err
}
@@ -82,7 +83,8 @@ func BeanExists(t *testing.T, bean interface{}, conditions ...interface{}) bool
func AssertExistsAndLoadBean(t *testing.T, bean interface{}, conditions ...interface{}) interface{} {
exists, err := loadBeanIfExists(bean, conditions...)
assert.NoError(t, err)
- assert.True(t, exists)
+ assert.True(t, exists,
+ "Expected to find %+v (with conditions %+v), but did not", bean, conditions)
return bean
}
@@ -92,3 +94,15 @@ func AssertNotExistsBean(t *testing.T, bean interface{}, conditions ...interface
assert.NoError(t, err)
assert.False(t, exists)
}
+
+// AssertSuccessfulInsert assert that beans is successfully inserted
+func AssertSuccessfulInsert(t *testing.T, beans ...interface{}) {
+ _, err := x.Insert(beans...)
+ assert.NoError(t, err)
+}
+
+// AssertSuccessfulUpdate assert that bean is successfully updated
+func AssertSuccessfulUpdate(t *testing.T, bean interface{}, conditions ...interface{}) {
+ _, err := x.Update(bean, conditions...)
+ assert.NoError(t, err)
+}