unit tests

This commit is contained in:
2021-04-08 11:40:40 +02:00
parent 6c2f8c286b
commit e48cbd396b
9 changed files with 147 additions and 24 deletions

2
.gitignore vendored
View File

@ -16,3 +16,5 @@
# vendor/
.idea
secrets.json
test
secrets_test.json

View File

@ -1,5 +1,6 @@
{
"createGiteaAccount": false,
"port": 8080,
"rootUrl": "http://localhost:8080"
"rootUrl": "http://localhost:8080",
"databaseType": "mysql"
}

6
config_test.json Normal file
View File

@ -0,0 +1,6 @@
{
"createGiteaAccount": false,
"port": 8080,
"rootUrl": "http://localhost:8080",
"databaseType": "sqlite3"
}

1
go.mod
View File

@ -11,6 +11,7 @@ require (
github.com/go-sql-driver/mysql v1.5.0
github.com/golang/protobuf v1.4.3 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/mattn/go-sqlite3 v1.14.6
github.com/zaddok/moodle v0.6.6
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect

2
go.sum
View File

@ -46,6 +46,8 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=

View File

@ -14,7 +14,7 @@ const sessionTimeout time.Duration = 10 * 24 * time.Hour
func login(w http.ResponseWriter, r *http.Request) {
var redirectUrl = r.FormValue("redirecturl")
if redirectUrl == "" {
redirectUrl = "dash"
redirectUrl = "/"
}
loginStruct := loginStruct{}
var login bool = false
@ -36,7 +36,6 @@ func login(w http.ResponseWriter, r *http.Request) {
cookie := http.Cookie{
Name: sessionName,
Value: key,
Domain: "redstoneunion.de",
Expires: time.Now().Add(sessionTimeout),
HttpOnly: true,
Secure: true,

View File

@ -7,6 +7,7 @@ import (
"github.com/bwmarrin/discordgo"
"github.com/dlclark/regexp2"
_ "github.com/go-sql-driver/mysql"
_ "github.com/mattn/go-sqlite3"
"github.com/zaddok/moodle"
"html/template"
"io/ioutil"
@ -24,6 +25,7 @@ var registerTmpl *template.Template
var submitTmpl *template.Template
var loginTmpl *template.Template
var stmtCreateAccount *sql.Stmt
var isTest bool
type secrets_json struct {
DiscordToken string `json:"discordToken"`
MysqlIndentify string `json:"mysqlIndentify"`
@ -31,17 +33,22 @@ type secrets_json struct {
MoodleToken string `json:"moodleToken"`
GiteaToken string `json:"giteaToken"`
ApiToken string `json:"apiToken"`
DiscordTestUser string `json:"discordTestUser"`
DiscordTestUserEmail string `json:"discordTestUserEmail"`
DiscordTestUserPassword string `json:"discordTestUserpassword"`
DiscordBotUserId string `json:"discordBotUserId"`
}
type config_json struct {
CreateGiteaAccount bool `json:"createGiteaAccount"`
Port uint16 `json:"port"`
RootUrl string `json:"rootUrl"`
DatabaseType string `json:"databaseType"`
}
func main() {
var err error
var jsonfile *os.File
jsonfile, err = os.Open("secrets.json")
jsonfile, err = os.Open("secrets" + testFilename() + ".json")
log(err)
var jsondata []byte
jsondata, err = ioutil.ReadAll(jsonfile)
@ -49,19 +56,23 @@ func main() {
err = json.Unmarshal(jsondata, &secret)
log(err)
jsonfile.Close()
jsonfile, err = os.Open("config.json")
jsonfile, err = os.Open("config" + testFilename() + ".json")
log(err)
jsondata, err = ioutil.ReadAll(jsonfile)
log(err)
err = json.Unmarshal(jsondata, &config)
log(err)
jsonfile.Close()
if(config.DatabaseType != "mysql" && config.DatabaseType != "sqlite3") {
fmt.Println("Unknown database type. Use mysql or sqlite3")
os.Exit(1)
}
discordgo.MakeIntent(discordgo.IntentsAll)
discord, err = discordgo.New("Bot " + secret.DiscordToken)
log(err)
err = discord.Open()
log(err)
db, err = sql.Open("mysql", secret.MysqlIndentify)
db, err = sql.Open(config.DatabaseType, secret.MysqlIndentify)
log(err)
_, err = db.Exec("CREATE TABLE IF NOT EXISTS account(" +
"username varchar(40) NOT NULL, " +
@ -88,5 +99,14 @@ func main() {
http.HandleFunc("/login", login)
http.HandleFunc("/api/accountinfo", accountApi)
http.ListenAndServe(":" + fmt.Sprint(config.Port), nil)
if(!isTest) {
http.ListenAndServe(":" + fmt.Sprint(config.Port), nil)
}
}
func testFilename() string {
if(isTest) {
return "_test"
}
return ""
}

92
src/main_test.go Normal file
View File

@ -0,0 +1,92 @@
package main
import (
"testing"
"net/http"
"net/http/httptest"
"net/url"
"bytes"
"strings"
"github.com/bwmarrin/discordgo"
"github.com/dlclark/regexp2"
"html/template"
"io"
)
var testPassword = "*#566jgjgJJf"
var testUsername = "ausername"
var testSession string
func TestOrder(test *testing.T) {
isTest = true
main()
test.Run("register", testRegister)
test.Run("submit", testSubmit)
test.Run("login", testLogin)
}
func testSetUsernamePassword(form url.Values) {
form.Set("username", testUsername)
form.Set("password", testPassword)
}
func testForm(test *testing.T, url string, statusCode int, handler http.HandlerFunc, form url.Values) *http.Response {
request := httptest.NewRequest("POST", url, strings.NewReader(form.Encode()))
request.Form = form
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, request)
if recorder.Code != statusCode {
test.Errorf("handler returned wrong status code: got %v want %v", recorder.Code, http.StatusOK)
}
return recorder.Result()
}
func checkBodyByTemplate(test *testing.T, response *http.Response, template *template.Template, templateData interface{}) {
var expectedResponse bytes.Buffer
template.Execute(&expectedResponse, templateData)
checkBody(test, response, expectedResponse.Bytes())
}
func checkBody(test *testing.T, response *http.Response, expectedResponse []byte) {
responseBody, _ := io.ReadAll(response.Body)
if bytes.Equal(expectedResponse, responseBody) {
test.Errorf("unexpected body:\n%v", string(responseBody))
}
}
func testRegister(test *testing.T) {
form := url.Values{}
testSetUsernamePassword(form)
form.Set("email", "jffg@fv.com")
form.Set("discordUser", secret.DiscordTestUser)
response := testForm(test, "/register", http.StatusOK, register, form)
checkBodyByTemplate(test, response, registerTmpl, registerStruct{Success: true})
}
func testSubmit(test *testing.T) {
discordClient, err := discordgo.New()
log(err)
err = discordClient.Login(secret.DiscordTestUserEmail, secret.DiscordTestUserPassword)
log(err)
err = discordClient.Open()
log(err)
channel, err := discordClient.UserChannelCreate(secret.DiscordBotUserId)
log(err)
msg, err := discordClient.ChannelMessages(channel.ID, 1, "", "", channel.LastMessageID)
log(err)
re := regexp2.MustCompile(`(?<=\?token\=)[^>]*`, 0)
match, _ := re.FindStringMatch(msg[0].Content)
if match == nil {
test.Error("The submit link was not send")
}
form := url.Values{}
form.Set("token", match.String())
response := testForm(test, "/submit", http.StatusOK, submit, form)
checkBodyByTemplate(test, response, submitTmpl, submitStruct{Success: true})
}
func testLogin(test *testing.T) {
form := url.Values{}
testSetUsernamePassword(form)
testForm(test, "/login", http.StatusSeeOther, login, form)
}

View File

@ -24,7 +24,7 @@ type WrongAccount struct {
Email bool
DiscordUser bool
}
type registertmpl struct {
type registerStruct struct {
Success bool
WrongAccount WrongAccount
AlreadyEsitsInDatabase struct{
@ -32,7 +32,7 @@ type registertmpl struct {
DiscordUsername bool
}
}
type SubmitStruct struct {
type submitStruct struct {
Success bool
}
var cacheAccounts hashmap.HashMap
@ -40,7 +40,7 @@ var rusername *regexp.Regexp
var remail *regexp2.Regexp
var rpassword *regexp2.Regexp
func register(w http.ResponseWriter, r *http.Request) {
registerstruct := registertmpl{}
registerStruct := registerStruct{}
if r.Method == http.MethodPost {
var newAccount account
var newRbuMember *discordgo.Member
@ -54,24 +54,24 @@ func register(w http.ResponseWriter, r *http.Request) {
newAccount.discordUsername = split[0]
newAccount.discordTag = split[1]
}
registerstruct.WrongAccount.Email, _ = remail.MatchString(newAccount.email)
registerstruct.WrongAccount.Email = !registerstruct.WrongAccount.Email
registerstruct.WrongAccount.User = !rusername.MatchString(newAccount.username)
registerstruct.WrongAccount.Pass, _ = rpassword.MatchString(newAccount.password)
registerstruct.WrongAccount.Pass = !registerstruct.WrongAccount.Pass
newRbuMember, registerstruct.WrongAccount.DiscordUser = getRbuMember(newAccount.discordUsername, newAccount.discordTag)
registerstruct.WrongAccount.DiscordUser = !registerstruct.WrongAccount.DiscordUser
if registerstruct.WrongAccount.DiscordUser {
registerStruct.WrongAccount.Email, _ = remail.MatchString(newAccount.email)
registerStruct.WrongAccount.Email = !registerStruct.WrongAccount.Email
registerStruct.WrongAccount.User = !rusername.MatchString(newAccount.username)
registerStruct.WrongAccount.Pass, _ = rpassword.MatchString(newAccount.password)
registerStruct.WrongAccount.Pass = !registerStruct.WrongAccount.Pass
newRbuMember, registerStruct.WrongAccount.DiscordUser = getRbuMember(newAccount.discordUsername, newAccount.discordTag)
registerStruct.WrongAccount.DiscordUser = !registerStruct.WrongAccount.DiscordUser
if registerStruct.WrongAccount.DiscordUser {
goto registerReturn
}
newAccount.discordId = newRbuMember.User.ID
{
var username string
registerstruct.AlreadyEsitsInDatabase.Username = db.QueryRow("SELECT username FROM account WHERE username = ?", newAccount.username).Scan(&username) == nil || UsernameExistsInMem(newAccount.username) // check if username exits
registerstruct.AlreadyEsitsInDatabase.DiscordUsername = db.QueryRow("SELECT username FROM account WHERE discordUserId = ?", newAccount.discordId).Scan(&username) == nil || discordUsernameExistsInMem(newAccount.discordId)
registerStruct.AlreadyEsitsInDatabase.Username = db.QueryRow("SELECT username FROM account WHERE username = ?", newAccount.username).Scan(&username) == nil || UsernameExistsInMem(newAccount.username) // check if username exits
registerStruct.AlreadyEsitsInDatabase.DiscordUsername = db.QueryRow("SELECT username FROM account WHERE discordUserId = ?", newAccount.discordId).Scan(&username) == nil || discordUsernameExistsInMem(newAccount.discordId)
}
registerstruct.Success = !registerstruct.WrongAccount.User && !registerstruct.WrongAccount.Pass && !registerstruct.WrongAccount.Email && !registerstruct.WrongAccount.DiscordUser && !registerstruct.AlreadyEsitsInDatabase.DiscordUsername && !registerstruct.AlreadyEsitsInDatabase.Username
if !registerstruct.Success {
registerStruct.Success = !registerStruct.WrongAccount.User && !registerStruct.WrongAccount.Pass && !registerStruct.WrongAccount.Email && !registerStruct.WrongAccount.DiscordUser && !registerStruct.AlreadyEsitsInDatabase.DiscordUsername && !registerStruct.AlreadyEsitsInDatabase.Username
if !registerStruct.Success {
goto registerReturn
}
token, err := GenerateRandomStringURLSafe(64)
@ -82,11 +82,11 @@ func register(w http.ResponseWriter, r *http.Request) {
discord.ChannelMessageSend(dmChannel.ID, "Bitte klicke auf den Link, um die Erstellung des Accounts abzuschließen.\n<" + config.RootUrl + "/submit?token=" + token + ">")
cacheAccounts.Set(token, newAccount)
}
registerReturn: runTemplate(w, registerTmpl, registerstruct)
registerReturn: runTemplate(w, registerTmpl, registerStruct)
}
func submit(w http.ResponseWriter, r *http.Request) {
var err error
var submitStruct SubmitStruct
var submitStruct submitStruct
token := r.FormValue("token")
var accInter interface{}
accInter, submitStruct.Success = cacheAccounts.GetStringKey(token)