Renamed the *Store methods. Added more functionality to some of the DataStores. Added DataCache interfaces in addition to the DataStores to help curb their unrelenting growth and confusing APIs. Fixed a crash bug in the ForumStore getters. Fixed three tests. Added more tests. Temporary Group permissions should now be applied properly. Improved the Tempra Conflux theme. Moved the topic deletion logic into the TopicStore. Tweaked the permission checks on the member routes to make them more sensible.
388 lines
8.8 KiB
Go
388 lines
8.8 KiB
Go
package main
|
|
|
|
import "strconv"
|
|
import "testing"
|
|
|
|
// TODO: Generate a test database to work with rather than a live one
|
|
func TestUserStore(t *testing.T) {
|
|
if !gloinited {
|
|
err := gloinit()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if !pluginsInited {
|
|
initPlugins()
|
|
}
|
|
|
|
users = NewMemoryUserStore(config.UserCacheCapacity)
|
|
userStoreTest(t)
|
|
users = NewSQLUserStore()
|
|
userStoreTest(t)
|
|
}
|
|
func userStoreTest(t *testing.T) {
|
|
var user *User
|
|
var err error
|
|
|
|
_, err = users.Get(-1)
|
|
if err == nil {
|
|
t.Error("UID #-1 shouldn't exist")
|
|
} else if err != ErrNoRows {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = users.Get(0)
|
|
if err == nil {
|
|
t.Error("UID #0 shouldn't exist")
|
|
} else if err != ErrNoRows {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
user, err = users.Get(1)
|
|
if err == ErrNoRows {
|
|
t.Error("Couldn't find UID #1")
|
|
} else if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if user.ID != 1 {
|
|
t.Error("user.ID does not match the requested UID. Got '" + strconv.Itoa(user.ID) + "' instead.")
|
|
}
|
|
|
|
// TODO: Lock onto the specific error type. Is this even possible without sacrificing the detailed information in the error message?
|
|
var userList map[int]*User
|
|
userList, _ = users.BulkGetMap([]int{-1})
|
|
if len(userList) > 0 {
|
|
t.Error("There shouldn't be any results for UID #-1")
|
|
}
|
|
|
|
userList, _ = users.BulkGetMap([]int{0})
|
|
if len(userList) > 0 {
|
|
t.Error("There shouldn't be any results for UID #0")
|
|
}
|
|
|
|
userList, _ = users.BulkGetMap([]int{1})
|
|
if len(userList) == 0 {
|
|
t.Error("The returned map is empty for UID #1")
|
|
} else if len(userList) > 1 {
|
|
t.Error("Too many results were returned for UID #1")
|
|
}
|
|
|
|
user, ok := userList[1]
|
|
if !ok {
|
|
t.Error("We couldn't find UID #1 in the returned map")
|
|
t.Error("userList", userList)
|
|
}
|
|
|
|
if user.ID != 1 {
|
|
t.Error("user.ID does not match the requested UID. Got '" + strconv.Itoa(user.ID) + "' instead.")
|
|
}
|
|
|
|
ok = users.Exists(-1)
|
|
if ok {
|
|
t.Error("UID #-1 shouldn't exist")
|
|
}
|
|
|
|
ok = users.Exists(0)
|
|
if ok {
|
|
t.Error("UID #0 shouldn't exist")
|
|
}
|
|
|
|
ok = users.Exists(1)
|
|
if !ok {
|
|
t.Error("UID #1 should exist")
|
|
}
|
|
|
|
count := users.GetGlobalCount()
|
|
if count <= 0 {
|
|
t.Error("The number of users should be bigger than zero")
|
|
t.Error("count", count)
|
|
}
|
|
}
|
|
|
|
func TestTopicStore(t *testing.T) {
|
|
if !gloinited {
|
|
err := gloinit()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if !pluginsInited {
|
|
initPlugins()
|
|
}
|
|
|
|
topics = NewMemoryTopicStore(config.TopicCacheCapacity)
|
|
topicStoreTest(t)
|
|
topics = NewSQLTopicStore()
|
|
topicStoreTest(t)
|
|
}
|
|
func topicStoreTest(t *testing.T) {
|
|
var topic *Topic
|
|
var err error
|
|
|
|
_, err = topics.Get(-1)
|
|
if err == nil {
|
|
t.Error("TID #-1 shouldn't exist")
|
|
} else if err != ErrNoRows {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = topics.Get(0)
|
|
if err == nil {
|
|
t.Error("TID #0 shouldn't exist")
|
|
} else if err != ErrNoRows {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
topic, err = topics.Get(1)
|
|
if err == ErrNoRows {
|
|
t.Error("Couldn't find TID #1")
|
|
} else if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if topic.ID != 1 {
|
|
t.Error("topic.ID does not match the requested TID. Got '" + strconv.Itoa(topic.ID) + "' instead.")
|
|
}
|
|
|
|
// TODO: Add BulkGetMap() to the TopicStore
|
|
|
|
ok := topics.Exists(-1)
|
|
if ok {
|
|
t.Error("TID #-1 shouldn't exist")
|
|
}
|
|
|
|
ok = topics.Exists(0)
|
|
if ok {
|
|
t.Error("TID #0 shouldn't exist")
|
|
}
|
|
|
|
ok = topics.Exists(1)
|
|
if !ok {
|
|
t.Error("TID #1 should exist")
|
|
}
|
|
|
|
count := topics.GetGlobalCount()
|
|
if count <= 0 {
|
|
t.Error("The number of topics should be bigger than zero")
|
|
t.Error("count", count)
|
|
}
|
|
}
|
|
|
|
func TestForumStore(t *testing.T) {
|
|
if !gloinited {
|
|
gloinit()
|
|
}
|
|
if !pluginsInited {
|
|
initPlugins()
|
|
}
|
|
|
|
var forum *Forum
|
|
var err error
|
|
|
|
_, err = fstore.Get(-1)
|
|
if err == nil {
|
|
t.Error("FID #-1 shouldn't exist")
|
|
} else if err != ErrNoRows {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
forum, err = fstore.Get(0)
|
|
if err == ErrNoRows {
|
|
t.Error("Couldn't find FID #0")
|
|
} else if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if forum.ID != 0 {
|
|
t.Error("forum.ID doesn't not match the requested UID. Got '" + strconv.Itoa(forum.ID) + "' instead.")
|
|
}
|
|
if forum.Name != "Uncategorised" {
|
|
t.Error("FID #0 is named '" + forum.Name + "' and not 'Uncategorised'")
|
|
}
|
|
|
|
forum, err = fstore.Get(1)
|
|
if err == ErrNoRows {
|
|
t.Error("Couldn't find FID #1")
|
|
} else if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if forum.ID != 1 {
|
|
t.Error("forum.ID doesn't not match the requested FID. Got '" + strconv.Itoa(forum.ID) + "' instead.'")
|
|
}
|
|
if forum.Name != "Reports" {
|
|
t.Error("FID #0 is named '" + forum.Name + "' and not 'Reports'")
|
|
}
|
|
|
|
forum, err = fstore.Get(2)
|
|
if err == ErrNoRows {
|
|
t.Error("Couldn't find FID #2")
|
|
} else if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_ = forum
|
|
|
|
ok := fstore.Exists(-1)
|
|
if ok {
|
|
t.Error("FID #-1 shouldn't exist")
|
|
}
|
|
|
|
ok = fstore.Exists(0)
|
|
if !ok {
|
|
t.Error("FID #0 should exist")
|
|
}
|
|
|
|
ok = fstore.Exists(1)
|
|
if !ok {
|
|
t.Error("FID #1 should exist")
|
|
}
|
|
}
|
|
|
|
func TestGroupStore(t *testing.T) {
|
|
if !gloinited {
|
|
gloinit()
|
|
}
|
|
if !pluginsInited {
|
|
initPlugins()
|
|
}
|
|
|
|
var group *Group
|
|
var err error
|
|
|
|
_, err = gstore.Get(-1)
|
|
if err == nil {
|
|
t.Error("GID #-1 shouldn't exist")
|
|
} else if err != ErrNoRows {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
group, err = gstore.Get(0)
|
|
if err == ErrNoRows {
|
|
t.Error("Couldn't find GID #0")
|
|
} else if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if group.ID != 0 {
|
|
t.Error("group.ID doesn't not match the requested GID. Got '" + strconv.Itoa(group.ID) + "' instead.")
|
|
}
|
|
if group.Name != "Unknown" {
|
|
t.Error("GID #0 is named '" + group.Name + "' and not 'Unknown'")
|
|
}
|
|
|
|
// ? - What if they delete this group? x.x
|
|
// ? - Maybe, pick a random group ID? That would take an extra query, and I'm not sure if I want to be rewriting custom test queries. Possibly, a Random() method on the GroupStore? Seems useless for normal use, it might have some merit for the TopicStore though
|
|
group, err = gstore.Get(1)
|
|
if err == ErrNoRows {
|
|
t.Error("Couldn't find GID #1")
|
|
} else if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if group.ID != 1 {
|
|
t.Error("group.ID doesn't not match the requested GID. Got '" + strconv.Itoa(group.ID) + "' instead.'")
|
|
}
|
|
|
|
_ = group
|
|
|
|
ok := gstore.Exists(-1)
|
|
if ok {
|
|
t.Error("GID #-1 shouldn't exist")
|
|
}
|
|
|
|
ok = gstore.Exists(0)
|
|
if !ok {
|
|
t.Error("GID #0 should exist")
|
|
}
|
|
|
|
ok = gstore.Exists(1)
|
|
if !ok {
|
|
t.Error("GID #1 should exist")
|
|
}
|
|
}
|
|
|
|
func TestSlugs(t *testing.T) {
|
|
var res string
|
|
var msgList []MEPair
|
|
|
|
msgList = addMEPair(msgList, "Unknown", "unknown")
|
|
msgList = addMEPair(msgList, "Unknown2", "unknown2")
|
|
msgList = addMEPair(msgList, "Unknown ", "unknown")
|
|
msgList = addMEPair(msgList, "Unknown 2", "unknown-2")
|
|
msgList = addMEPair(msgList, "Unknown 2", "unknown-2")
|
|
msgList = addMEPair(msgList, "Admin Alice", "admin-alice")
|
|
msgList = addMEPair(msgList, "Admin_Alice", "adminalice")
|
|
msgList = addMEPair(msgList, "Admin_Alice-", "adminalice")
|
|
msgList = addMEPair(msgList, "-Admin_Alice-", "adminalice")
|
|
msgList = addMEPair(msgList, "-Admin@Alice-", "adminalice")
|
|
msgList = addMEPair(msgList, "-Admin😀Alice-", "adminalice")
|
|
msgList = addMEPair(msgList, "u", "u")
|
|
msgList = addMEPair(msgList, "", "untitled")
|
|
msgList = addMEPair(msgList, " ", "untitled")
|
|
msgList = addMEPair(msgList, "-", "untitled")
|
|
msgList = addMEPair(msgList, "--", "untitled")
|
|
msgList = addMEPair(msgList, "é", "é")
|
|
msgList = addMEPair(msgList, "-é-", "é")
|
|
|
|
for _, item := range msgList {
|
|
t.Log("Testing string '" + item.Msg + "'")
|
|
res = nameToSlug(item.Msg)
|
|
if res != item.Expects {
|
|
t.Error("Bad output:", "'"+res+"'")
|
|
t.Error("Expected:", item.Expects)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAuth(t *testing.T) {
|
|
// bcrypt likes doing stupid things, so this test will probably fail
|
|
var realPassword string
|
|
var hashedPassword string
|
|
var password string
|
|
var salt string
|
|
var err error
|
|
|
|
/* No extra salt tests, we might not need this extra salt, as bcrypt has it's own? */
|
|
realPassword = "Madame Cassandra's Mystic Orb"
|
|
t.Log("Set real_password to '" + realPassword + "'")
|
|
t.Log("Hashing the real password")
|
|
hashedPassword, err = BcryptGeneratePasswordNoSalt(realPassword)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
password = realPassword
|
|
t.Log("Testing password '" + password + "'")
|
|
t.Log("Testing salt '" + salt + "'")
|
|
err = CheckPassword(hashedPassword, password, salt)
|
|
if err == ErrMismatchedHashAndPassword {
|
|
t.Error("The two don't match")
|
|
} else if err == ErrPasswordTooLong {
|
|
t.Error("CheckPassword thinks the password is too long")
|
|
} else if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
password = "hahaha"
|
|
t.Log("Testing password '" + password + "'")
|
|
t.Log("Testing salt '" + salt + "'")
|
|
err = CheckPassword(hashedPassword, password, salt)
|
|
if err == ErrPasswordTooLong {
|
|
t.Error("CheckPassword thinks the password is too long")
|
|
} else if err == nil {
|
|
t.Error("The two shouldn't match!")
|
|
}
|
|
|
|
password = "Madame Cassandra's Mystic"
|
|
t.Log("Testing password '" + password + "'")
|
|
t.Log("Testing salt '" + salt + "'")
|
|
err = CheckPassword(hashedPassword, password, salt)
|
|
if err == ErrPasswordTooLong {
|
|
t.Error("CheckPassword thinks the password is too long")
|
|
} else if err == nil {
|
|
t.Error("The two shouldn't match!")
|
|
}
|
|
}
|