mirror of
https://github.com/pushbits/server.git
synced 2025-06-05 20:22:01 +02:00
Merge pull request #32 from CubicrootXYZ/testing
Add testing to PushBits
This commit is contained in:
commit
cdf4a47c07
18 changed files with 972 additions and 35 deletions
28
README.md
28
README.md
|
@ -169,3 +169,31 @@ git clone https://github.com/pushbits/server.git
|
|||
```
|
||||
|
||||
[](https://starchart.cc/pushbits/server)
|
||||
|
||||
### Testing
|
||||
|
||||
Testing is essential for deliviering a good and reliable software. PushBits uses golangs integrated test features. Unfortunately writing tests is quite time consuming and therefore not every feature and every line of code is automatically tested. Feel free to help us improve our tests.
|
||||
|
||||
To run tests for a single (sub)module you can simply execute the following command in the modules folder.
|
||||
|
||||
```bash
|
||||
go test
|
||||
```
|
||||
|
||||
To get the testing coverage for a module use the `-cover` flag.
|
||||
|
||||
```bash
|
||||
go test -cover
|
||||
```
|
||||
|
||||
To execute a single test use the `-run` flag.
|
||||
|
||||
```bash
|
||||
go test -run "TestApi_getUser"
|
||||
```
|
||||
|
||||
Running tests for all PushBits module is done like this:
|
||||
|
||||
```bash
|
||||
make test
|
||||
```
|
5
go.mod
5
go.mod
|
@ -18,10 +18,11 @@ require (
|
|||
github.com/mattn/go-sqlite3 v1.14.6 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/ugorji/go v1.2.4 // indirect
|
||||
golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 // indirect
|
||||
golang.org/x/tools v0.1.3 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gorm.io/driver/mysql v1.0.4
|
||||
gorm.io/driver/sqlite v1.1.4
|
||||
gorm.io/gorm v1.20.12
|
||||
|
|
18
go.sum
18
go.sum
|
@ -19,13 +19,11 @@ github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8c
|
|||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-playground/validator/v10 v10.3.0 h1:nZU+7q+yJoFmwvNgv/LnPUkwPal62+b2xXj0AU1Es7o=
|
||||
github.com/go-playground/validator/v10 v10.3.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
|
@ -48,11 +46,9 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
|||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
|
||||
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
|
@ -63,11 +59,9 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
|
|||
github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||
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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
|
@ -75,15 +69,13 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go v1.2.4 h1:cTciPbZ/VSOzCLKclmssnfQ/jyoVyOcJ3aoJyUV1Urc=
|
||||
github.com/ugorji/go v1.2.4/go.mod h1:EuaSCk8iZMdIspsu6HXH7X2UGKw1ezO4wCfGszGmmo4=
|
||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ugorji/go/codec v1.2.4 h1:C5VurWRRCKjuENsbM6GYVw8W++WVW9rSxoACKIvxzz8=
|
||||
github.com/ugorji/go/codec v1.2.4/go.mod h1:bWBu1+kIRWcF8uMklKaJrR6fTWQOwAlrIzX22pHwryA=
|
||||
|
@ -120,19 +112,14 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 h1:C+AwYEtBp/VQwoLntUmQ/yx3MS9vmZaKNdw5eOpoQe8=
|
||||
golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.3 h1:L69ShwSZEyCsLKoAxDKeMvLDZkumEe8gXUZAjab0tX8=
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -146,7 +133,6 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
|||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
|
|
|
@ -114,6 +114,7 @@ func (h *ApplicationHandler) CreateApplication(ctx *gin.Context) {
|
|||
var createApplication model.CreateApplication
|
||||
|
||||
if err := ctx.Bind(&createApplication); err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
348
internal/api/application_test.go
Normal file
348
internal/api/application_test.go
Normal file
|
@ -0,0 +1,348 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pushbits/server/internal/configuration"
|
||||
"github.com/pushbits/server/internal/database"
|
||||
"github.com/pushbits/server/internal/model"
|
||||
"github.com/pushbits/server/tests"
|
||||
"github.com/pushbits/server/tests/mockups"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var TestApplicationHandler *ApplicationHandler
|
||||
var TestUsers []*model.User
|
||||
var TestDatabase *database.Database
|
||||
|
||||
// Collect all created applications to check & delete them later
|
||||
var SuccessAplications map[uint][]model.Application
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
// Get main config and adapt
|
||||
config := &configuration.Configuration{}
|
||||
|
||||
config.Database.Connection = "pushbits-test.db"
|
||||
config.Database.Dialect = "sqlite3"
|
||||
config.Crypto.Argon2.Iterations = 4
|
||||
config.Crypto.Argon2.Parallelism = 4
|
||||
config.Crypto.Argon2.Memory = 131072
|
||||
config.Crypto.Argon2.SaltLength = 16
|
||||
config.Crypto.Argon2.KeyLength = 32
|
||||
|
||||
// Set up test environment
|
||||
db, err := mockups.GetEmptyDatabase(config.Crypto)
|
||||
if err != nil {
|
||||
cleanUp()
|
||||
log.Println("Can not set up database: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
TestDatabase = db
|
||||
|
||||
appHandler, err := getApplicationHandler(config)
|
||||
if err != nil {
|
||||
cleanUp()
|
||||
log.Println("Can not set up application handler: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
TestApplicationHandler = appHandler
|
||||
TestUsers = mockups.GetUsers(config)
|
||||
SuccessAplications = make(map[uint][]model.Application)
|
||||
|
||||
// Run
|
||||
m.Run()
|
||||
cleanUp()
|
||||
}
|
||||
|
||||
func TestApi_RegisterApplicationWithoutUser(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
reqWoUser := tests.Request{Name: "Invalid JSON Data", Method: "POST", Endpoint: "/application", Data: `{"name": "test1", "strict_compatibility": true}`, Headers: map[string]string{"Content-Type": "application/json"}}
|
||||
_, c, err := reqWoUser.GetRequest()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
assert.Panicsf(func() { TestApplicationHandler.CreateApplication(c) }, "CreateApplication did not panic altough user is not in context")
|
||||
|
||||
}
|
||||
|
||||
func TestApi_RegisterApplication(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
testCases := make([]tests.Request, 0)
|
||||
testCases = append(testCases, tests.Request{Name: "Invalid Form Data", Method: "POST", Endpoint: "/application", Data: "k=1&v=abc", ShouldStatus: 400})
|
||||
testCases = append(testCases, tests.Request{Name: "Invalid JSON Data", Method: "POST", Endpoint: "/application", Data: `{"name": "test1", "strict_compatibility": "oh yes"}`, Headers: map[string]string{"Content-Type": "application/json"}, ShouldStatus: 400})
|
||||
testCases = append(testCases, tests.Request{Name: "Valid JSON Data", Method: "POST", Endpoint: "/application", Data: `{"name": "test2", "strict_compatibility": true}`, Headers: map[string]string{"Content-Type": "application/json"}, ShouldStatus: 200})
|
||||
|
||||
for _, user := range TestUsers {
|
||||
SuccessAplications[user.ID] = make([]model.Application, 0)
|
||||
for _, req := range testCases {
|
||||
var application model.Application
|
||||
w, c, err := req.GetRequest()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
c.Set("user", user)
|
||||
TestApplicationHandler.CreateApplication(c)
|
||||
|
||||
// Parse body only for successful requests
|
||||
if req.ShouldStatus >= 200 && req.ShouldStatus < 300 {
|
||||
body, err := ioutil.ReadAll(w.Body)
|
||||
assert.NoErrorf(err, "Can not read request body")
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
err = json.Unmarshal(body, &application)
|
||||
assert.NoErrorf(err, "Can not unmarshal request body")
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
SuccessAplications[user.ID] = append(SuccessAplications[user.ID], application)
|
||||
}
|
||||
|
||||
assert.Equalf(w.Code, req.ShouldStatus, "CreateApplication (Test case: \"%s\") should return status code %v but is %v.", req.Name, req.ShouldStatus, w.Code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestApi_GetApplications(t *testing.T) {
|
||||
var applications []model.Application
|
||||
|
||||
assert := assert.New(t)
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
testCases := make([]tests.Request, 0)
|
||||
testCases = append(testCases, tests.Request{Name: "Valid Request", Method: "GET", Endpoint: "/application", ShouldStatus: 200})
|
||||
|
||||
for _, user := range TestUsers {
|
||||
for _, req := range testCases {
|
||||
w, c, err := req.GetRequest()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
c.Set("user", user)
|
||||
TestApplicationHandler.GetApplications(c)
|
||||
|
||||
// Parse body only for successful requests
|
||||
if req.ShouldStatus >= 200 && req.ShouldStatus < 300 {
|
||||
body, err := ioutil.ReadAll(w.Body)
|
||||
assert.NoErrorf(err, "Can not read request body")
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
err = json.Unmarshal(body, &applications)
|
||||
assert.NoErrorf(err, "Can not unmarshal request body")
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
assert.Truef(validateAllApplications(user, applications), "Did not find application created previously")
|
||||
assert.Equalf(len(applications), len(SuccessAplications[user.ID]), "Created %d application(s) but got %d back", len(SuccessAplications[user.ID]), len(applications))
|
||||
}
|
||||
|
||||
assert.Equalf(w.Code, req.ShouldStatus, "GetApplications (Test case: \"%s\") should return status code %v but is %v.", req.Name, req.ShouldStatus, w.Code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestApi_GetApplicationsWithoutUser(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
testCase := tests.Request{Name: "Valid Request", Method: "GET", Endpoint: "/application"}
|
||||
|
||||
_, c, err := testCase.GetRequest()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
assert.Panicsf(func() { TestApplicationHandler.GetApplications(c) }, "GetApplications did not panic altough user is not in context")
|
||||
|
||||
}
|
||||
|
||||
func TestApi_GetApplicationErrors(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
// Arbitrary test cases
|
||||
testCases := make(map[uint]tests.Request)
|
||||
testCases[0] = tests.Request{Name: "Requesting unknown application 0", Method: "GET", Endpoint: "/application/0", ShouldStatus: 404}
|
||||
testCases[5555] = tests.Request{Name: "Requesting unknown application 5555", Method: "GET", Endpoint: "/application/5555", ShouldStatus: 404}
|
||||
testCases[99999999999999999] = tests.Request{Name: "Requesting unknown application 99999999999999999", Method: "GET", Endpoint: "/application/99999999999999999", ShouldStatus: 404}
|
||||
|
||||
for _, user := range TestUsers {
|
||||
for id, req := range testCases {
|
||||
w, c, err := req.GetRequest()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
c.Set("user", user)
|
||||
c.Set("id", id)
|
||||
TestApplicationHandler.GetApplication(c)
|
||||
|
||||
assert.Equalf(w.Code, req.ShouldStatus, "GetApplication (Test case: \"%s\") should return status code %v but is %v.", req.Name, req.ShouldStatus, w.Code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestApi_GetApplication(t *testing.T) {
|
||||
var application model.Application
|
||||
|
||||
assert := assert.New(t)
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
// Previously generated applications
|
||||
for _, user := range TestUsers {
|
||||
for _, app := range SuccessAplications[user.ID] {
|
||||
req := tests.Request{Name: fmt.Sprintf("Requesting application %s (%d)", app.Name, app.ID), Method: "GET", Endpoint: fmt.Sprintf("/application/%d", app.ID), ShouldStatus: 200}
|
||||
|
||||
w, c, err := req.GetRequest()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
c.Set("user", user)
|
||||
c.Set("id", app.ID)
|
||||
TestApplicationHandler.GetApplication(c)
|
||||
|
||||
// Parse body only for successful requests
|
||||
if req.ShouldStatus >= 200 && req.ShouldStatus < 300 {
|
||||
body, err := ioutil.ReadAll(w.Body)
|
||||
assert.NoErrorf(err, "Can not read request body")
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
err = json.Unmarshal(body, &application)
|
||||
assert.NoErrorf(err, "Can not unmarshal request body: %v", err)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
assert.Equalf(application.ID, app.ID, "Application ID should be %d but is %d", app.ID, application.ID)
|
||||
assert.Equalf(application.Name, app.Name, "Application Name should be %s but is %s", app.Name, application.Name)
|
||||
assert.Equalf(application.UserID, app.UserID, "Application user ID should be %d but is %d", app.UserID, application.UserID)
|
||||
|
||||
}
|
||||
|
||||
assert.Equalf(w.Code, req.ShouldStatus, "GetApplication (Test case: \"%s\") should return status code %v but is %v.", req.Name, req.ShouldStatus, w.Code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestApi_UpdateApplication(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
for _, user := range TestUsers {
|
||||
testCases := make(map[uint]tests.Request)
|
||||
// Previously generated applications
|
||||
for _, app := range SuccessAplications[user.ID] {
|
||||
newName := app.Name + "-new_name"
|
||||
updateApp := model.UpdateApplication{
|
||||
Name: &newName,
|
||||
}
|
||||
updateAppBytes, err := json.Marshal(updateApp)
|
||||
assert.NoErrorf(err, "Error on marshaling updateApplication struct")
|
||||
|
||||
// Valid
|
||||
testCases[app.ID] = tests.Request{Name: fmt.Sprintf("Update application (valid) %s (%d)", app.Name, app.ID), Method: "PUT", Endpoint: fmt.Sprintf("/application/%d", app.ID), ShouldStatus: 200, Data: string(updateAppBytes), Headers: map[string]string{"Content-Type": "application/json"}}
|
||||
// Invalid
|
||||
testCases[app.ID] = tests.Request{Name: fmt.Sprintf("Update application (invalid) %s (%d)", app.Name, app.ID), Method: "PUT", Endpoint: fmt.Sprintf("/application/%d", app.ID), ShouldStatus: 200, Data: "{}", Headers: map[string]string{"Content-Type": "application/json"}}
|
||||
}
|
||||
// Arbitrary test cases
|
||||
testCases[5555] = tests.Request{Name: "Update application 5555", Method: "PUT", Endpoint: "/application/5555", ShouldStatus: 404, Data: "random data"}
|
||||
testCases[5556] = tests.Request{Name: "Update application 5556", Method: "PUT", Endpoint: "/application/5556", ShouldStatus: 404, Data: `{"new_name": "new name"}`, Headers: map[string]string{"Content-Type": "application/json"}}
|
||||
|
||||
for id, req := range testCases {
|
||||
w, c, err := req.GetRequest()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
c.Set("user", user)
|
||||
c.Set("id", id)
|
||||
TestApplicationHandler.UpdateApplication(c)
|
||||
|
||||
assert.Equalf(w.Code, req.ShouldStatus, "UpdateApplication (Test case: \"%s\") should return status code %v but is %v.", req.Name, req.ShouldStatus, w.Code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestApi_DeleteApplication(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
for _, user := range TestUsers {
|
||||
testCases := make(map[uint]tests.Request)
|
||||
// Previously generated applications
|
||||
for _, app := range SuccessAplications[user.ID] {
|
||||
testCases[app.ID] = tests.Request{Name: fmt.Sprintf("Delete application %s (%d)", app.Name, app.ID), Method: "DELETE", Endpoint: fmt.Sprintf("/application/%d", app.ID), ShouldStatus: 200}
|
||||
}
|
||||
// Arbitrary test cases
|
||||
testCases[5555] = tests.Request{Name: "Delete application 5555", Method: "DELETE", Endpoint: "/application/5555", ShouldStatus: 404}
|
||||
|
||||
for id, req := range testCases {
|
||||
w, c, err := req.GetRequest()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
c.Set("user", user)
|
||||
c.Set("id", id)
|
||||
TestApplicationHandler.DeleteApplication(c)
|
||||
|
||||
assert.Equalf(w.Code, req.ShouldStatus, "DeleteApplication (Test case: \"%s\") should return status code %v but is %v.", req.Name, req.ShouldStatus, w.Code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetApplicationHandler creates and returns an application handler
|
||||
func getApplicationHandler(c *configuration.Configuration) (*ApplicationHandler, error) {
|
||||
dispatcher := &mockups.MockDispatcher{}
|
||||
|
||||
return &ApplicationHandler{
|
||||
DB: TestDatabase,
|
||||
DP: dispatcher,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// True if all created applications are in list
|
||||
func validateAllApplications(user *model.User, apps []model.Application) bool {
|
||||
if _, ok := SuccessAplications[user.ID]; !ok {
|
||||
return len(apps) == 0
|
||||
}
|
||||
|
||||
for _, successApp := range SuccessAplications[user.ID] {
|
||||
foundApp := false
|
||||
for _, app := range apps {
|
||||
if app.ID == successApp.ID {
|
||||
foundApp = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !foundApp {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func cleanUp() {
|
||||
os.Remove("pushbits-test.db")
|
||||
}
|
117
internal/api/context_test.go
Normal file
117
internal/api/context_test.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pushbits/server/internal/model"
|
||||
"github.com/pushbits/server/tests"
|
||||
"github.com/pushbits/server/tests/mockups"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestApi_getID(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
gin.SetMode(gin.TestMode)
|
||||
testValue := uint(1337)
|
||||
|
||||
testCases := make(map[interface{}]tests.Request)
|
||||
testCases[-1] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 500}
|
||||
testCases[uint(1)] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 200}
|
||||
testCases[uint(0)] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 200}
|
||||
testCases[uint(500)] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 200}
|
||||
testCases[500] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 500}
|
||||
testCases["test"] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 500}
|
||||
testCases[model.Application{}] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 500}
|
||||
testCases[&model.Application{}] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 500}
|
||||
testCases[&testValue] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 500}
|
||||
|
||||
for id, req := range testCases {
|
||||
w, c, err := req.GetRequest()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
c.Set("id", id)
|
||||
idReturned, err := getID(c)
|
||||
|
||||
if req.ShouldStatus >= 200 && req.ShouldStatus < 300 {
|
||||
idUint, ok := id.(uint)
|
||||
if ok {
|
||||
assert.Equalf(idReturned, idUint, "getApi id was set to %d but result is %d", idUint, idReturned)
|
||||
}
|
||||
assert.NoErrorf(err, "getId with id %v (%t) returned an error altough it should not: %v", id, id, err)
|
||||
} else {
|
||||
assert.Errorf(err, "getId with id %v (%t) returned no error altough it should", id, id)
|
||||
}
|
||||
|
||||
assert.Equalf(w.Code, req.ShouldStatus, "getApi id was set to %v (%T) and should result in status code %d but code is %d", id, id, req.ShouldStatus, w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApi_getApplication(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
applications := mockups.GetAllApplications()
|
||||
mockups.AddApplicationsToDb(TestDatabase, applications)
|
||||
|
||||
// No testing of invalid ids as that is tested in TestApi_getID already
|
||||
testCases := make(map[uint]tests.Request)
|
||||
testCases[500] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 404}
|
||||
testCases[1] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 200}
|
||||
testCases[2] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 200}
|
||||
|
||||
for id, req := range testCases {
|
||||
w, c, err := req.GetRequest()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
c.Set("id", id)
|
||||
app, err := getApplication(c, TestDatabase)
|
||||
|
||||
if req.ShouldStatus >= 200 && req.ShouldStatus < 300 {
|
||||
assert.Equalf(app.ID, id, "getApplication id was set to %d but resulting app id is %d", id, app.ID)
|
||||
assert.NoErrorf(err, "getApplication with id %v (%t) returned an error altough it should not: %v", id, id, err)
|
||||
} else {
|
||||
assert.Errorf(err, "getApplication with id %v (%t) returned no error altough it should", id, id)
|
||||
}
|
||||
|
||||
assert.Equalf(w.Code, req.ShouldStatus, "getApplication id was set to %v (%T) and should result in status code %d but code is %d", id, id, req.ShouldStatus, w.Code)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestApi_getUser(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
_, err := mockups.AddUsersToDb(TestDatabase, TestUsers)
|
||||
assert.NoErrorf(err, "Adding users to database failed: %v", err)
|
||||
|
||||
// No testing of invalid ids as that is tested in TestApi_getID already
|
||||
testCases := make(map[uint]tests.Request)
|
||||
testCases[500] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 404}
|
||||
testCases[1] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 200}
|
||||
testCases[2] = tests.Request{Name: "-", Method: "GET", Endpoint: "/", Data: "", ShouldStatus: 200}
|
||||
|
||||
for id, req := range testCases {
|
||||
w, c, err := req.GetRequest()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
c.Set("id", id)
|
||||
user, err := getUser(c, TestDatabase)
|
||||
|
||||
if req.ShouldStatus >= 200 && req.ShouldStatus < 300 {
|
||||
assert.Equalf(user.ID, id, "getUser id was set to %d but resulting app id is %d", id, user.ID)
|
||||
assert.NoErrorf(err, "getUser with id %v (%t) returned an error altough it should not: %v", id, id, err)
|
||||
} else {
|
||||
assert.Errorf(err, "getUser with id %v (%t) returned no error altough it should", id, id)
|
||||
}
|
||||
|
||||
assert.Equalf(w.Code, req.ShouldStatus, "getUser id was set to %v (%T) and should result in status code %d but code is %d", id, id, req.ShouldStatus, w.Code)
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
package api
|
||||
|
||||
import "errors"
|
||||
|
||||
var ErrorMessageNotFound = errors.New("message not found")
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/pushbits/server/internal/authentication"
|
||||
"github.com/pushbits/server/internal/pberrors"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
@ -13,7 +14,7 @@ func successOrAbort(ctx *gin.Context, code int, err error) bool {
|
|||
if err != nil {
|
||||
// If we know the error force error code
|
||||
switch err {
|
||||
case ErrorMessageNotFound:
|
||||
case pberrors.ErrorMessageNotFound:
|
||||
ctx.AbortWithError(http.StatusNotFound, err)
|
||||
default:
|
||||
ctx.AbortWithError(code, err)
|
||||
|
|
|
@ -4,6 +4,9 @@ import (
|
|||
"github.com/jinzhu/configor"
|
||||
)
|
||||
|
||||
// testMode indicates if the package is run in test mode
|
||||
var testMode bool
|
||||
|
||||
// Argon2Config holds the parameters used for creating hashes with Argon2.
|
||||
type Argon2Config struct {
|
||||
Memory uint32 `default:"131072"`
|
||||
|
@ -23,6 +26,13 @@ type Formatting struct {
|
|||
ColoredTitle bool `default:"false"`
|
||||
}
|
||||
|
||||
// Matrix holds credentials for a matrix account
|
||||
type Matrix struct {
|
||||
Homeserver string `default:"https://matrix.org"`
|
||||
Username string `required:"true"`
|
||||
Password string `required:"true"`
|
||||
}
|
||||
|
||||
// Configuration holds values that can be configured by the user.
|
||||
type Configuration struct {
|
||||
Debug bool `default:"false"`
|
||||
|
@ -39,11 +49,7 @@ type Configuration struct {
|
|||
Password string `default:"admin"`
|
||||
MatrixID string `required:"true"`
|
||||
}
|
||||
Matrix struct {
|
||||
Homeserver string `default:"https://matrix.org"`
|
||||
Username string `required:"true"`
|
||||
Password string `required:"true"`
|
||||
}
|
||||
Matrix Matrix
|
||||
Security struct {
|
||||
CheckHIBP bool `default:"false"`
|
||||
}
|
||||
|
@ -52,6 +58,9 @@ type Configuration struct {
|
|||
}
|
||||
|
||||
func configFiles() []string {
|
||||
if testMode {
|
||||
return []string{"config_unittest.yml"}
|
||||
}
|
||||
return []string{"config.yml"}
|
||||
}
|
||||
|
||||
|
|
205
internal/configuration/configuration_test.go
Normal file
205
internal/configuration/configuration_test.go
Normal file
|
@ -0,0 +1,205 @@
|
|||
package configuration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/jinzhu/configor"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type Pair struct {
|
||||
Is interface{}
|
||||
Should interface{}
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testMode = true
|
||||
m.Run()
|
||||
cleanUp()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func TestConfiguration_GetMinimal(t *testing.T) {
|
||||
err := writeMinimalConfig()
|
||||
if err != nil {
|
||||
fmt.Println("Could not write minimal config: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
validateConfig(t)
|
||||
}
|
||||
|
||||
func TestConfiguration_GetValid(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
err := writeValidConfig()
|
||||
if err != nil {
|
||||
fmt.Println("Could not write valid config: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
validateConfig(t)
|
||||
|
||||
config := Get()
|
||||
|
||||
expectedValues := make(map[string]Pair)
|
||||
expectedValues["config.Admin.MatrixID"] = Pair{config.Admin.MatrixID, "000000"}
|
||||
expectedValues["config.Matrix.Username"] = Pair{config.Matrix.Username, "default-username"}
|
||||
expectedValues["config.Matrix.Password"] = Pair{config.Matrix.Password, "default-password"}
|
||||
|
||||
for name, pair := range expectedValues {
|
||||
assert.Equalf(pair.Is, pair.Should, fmt.Sprintf("%s should be %v but is %v", name, pair.Should, pair.Is))
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguration_GetEmpty(t *testing.T) {
|
||||
err := writeEmptyConfig()
|
||||
if err != nil {
|
||||
fmt.Println("Could not write empty config: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
assert.Panicsf(t, func() { Get() }, "Get() did not panic altough config is empty")
|
||||
}
|
||||
|
||||
func TestConfiguration_GetInvalid(t *testing.T) {
|
||||
err := writeInvalidConfig()
|
||||
if err != nil {
|
||||
fmt.Println("Could not write empty config: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
assert.Panicsf(t, func() { Get() }, "Get() did not panic altough config is empty")
|
||||
}
|
||||
|
||||
func TestConfiguaration_ConfigFiles(t *testing.T) {
|
||||
files := configFiles()
|
||||
|
||||
assert.Greater(t, len(files), 0)
|
||||
for _, file := range files {
|
||||
assert.Truef(t, strings.HasSuffix(file, ".yml"), "%s is no yaml file", file)
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if the values in the configuration are plausible
|
||||
func validateConfig(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
assert.NotPanicsf(func() { Get() }, "Get configuration should not panic")
|
||||
|
||||
config := Get()
|
||||
asGreater := make(map[string]Pair)
|
||||
asGreater["config.Crypto.Argon2.Memory"] = Pair{config.Crypto.Argon2.Memory, uint32(0)}
|
||||
asGreater["config.Crypto.Argon2.Iterations"] = Pair{config.Crypto.Argon2.Iterations, uint32(0)}
|
||||
asGreater["config.Crypto.Argon2.SaltLength"] = Pair{config.Crypto.Argon2.SaltLength, uint32(0)}
|
||||
asGreater["config.Crypto.Argon2.KeyLength"] = Pair{config.Crypto.Argon2.KeyLength, uint32(0)}
|
||||
asGreater["config.Crypto.Argon2.Parallelism"] = Pair{config.Crypto.Argon2.Parallelism, uint8(0)}
|
||||
asGreater["config.HTTP.Port"] = Pair{config.HTTP.Port, 0}
|
||||
for name, pair := range asGreater {
|
||||
assert.Greaterf(pair.Is, pair.Should, fmt.Sprintf("%s should be > %v but is %v", name, pair.Should, pair.Is))
|
||||
}
|
||||
|
||||
asFalse := make(map[string]bool)
|
||||
asFalse["config.Formatting.ColoredTitle"] = config.Formatting.ColoredTitle
|
||||
asFalse["config.Debug"] = config.Debug
|
||||
asFalse["config.Security.CheckHIBP"] = config.Security.CheckHIBP
|
||||
for name, value := range asFalse {
|
||||
assert.Falsef(value, fmt.Sprintf("%s should be false but is %t", name, value))
|
||||
}
|
||||
}
|
||||
|
||||
type MinimalConfiguration struct {
|
||||
Admin struct {
|
||||
MatrixID string
|
||||
}
|
||||
Matrix struct {
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
}
|
||||
|
||||
type InvalidConfiguration struct {
|
||||
Debug int
|
||||
HTTP struct {
|
||||
ListenAddress bool
|
||||
}
|
||||
Admin struct {
|
||||
Name int
|
||||
}
|
||||
Formatting string
|
||||
}
|
||||
|
||||
// Writes a minimal config to config.yml
|
||||
func writeMinimalConfig() error {
|
||||
cleanUp()
|
||||
config := MinimalConfiguration{}
|
||||
config.Admin.MatrixID = "000000"
|
||||
config.Matrix.Username = "default-username"
|
||||
config.Matrix.Password = "default-password"
|
||||
|
||||
configString, err := yaml.Marshal(&config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile("config_unittest.yml", configString, 0644)
|
||||
}
|
||||
|
||||
// Writes a config with default values to config.yml
|
||||
func writeValidConfig() error {
|
||||
cleanUp()
|
||||
|
||||
// Load minimal config to get default values
|
||||
writeMinimalConfig()
|
||||
config := &Configuration{}
|
||||
err := configor.New(&configor.Config{
|
||||
Environment: "production",
|
||||
ENVPrefix: "PUSHBITS",
|
||||
ErrorOnUnmatchedKeys: true,
|
||||
}).Load(config, "config_unittest.yml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.Admin.MatrixID = "000000"
|
||||
config.Matrix.Username = "default-username"
|
||||
config.Matrix.Password = "default-password"
|
||||
|
||||
configString, err := yaml.Marshal(&config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile("config_unittest.yml", configString, 0644)
|
||||
}
|
||||
|
||||
// Writes a config that is empty
|
||||
func writeEmptyConfig() error {
|
||||
cleanUp()
|
||||
return ioutil.WriteFile("config_unittest.yml", []byte(""), 0644)
|
||||
}
|
||||
|
||||
// Writes a config with invalid entries
|
||||
func writeInvalidConfig() error {
|
||||
cleanUp()
|
||||
config := InvalidConfiguration{}
|
||||
config.Debug = 1337
|
||||
config.HTTP.ListenAddress = true
|
||||
config.Admin.Name = 23
|
||||
config.Formatting = "Nice"
|
||||
|
||||
configString, err := yaml.Marshal(&config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile("config_unittest.yml", configString, 0644)
|
||||
}
|
||||
|
||||
func cleanUp() error {
|
||||
return os.Remove("config_unittest.yml")
|
||||
}
|
|
@ -8,8 +8,8 @@ import (
|
|||
|
||||
"github.com/gomarkdown/markdown"
|
||||
"github.com/matrix-org/gomatrix"
|
||||
"github.com/pushbits/server/internal/api"
|
||||
"github.com/pushbits/server/internal/model"
|
||||
"github.com/pushbits/server/internal/pberrors"
|
||||
)
|
||||
|
||||
// MessageFormat is a matrix message format
|
||||
|
@ -77,7 +77,7 @@ func (d *Dispatcher) DeleteNotification(a *model.Application, n *model.DeleteNot
|
|||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return api.ErrorMessageNotFound
|
||||
return pberrors.ErrorMessageNotFound
|
||||
}
|
||||
|
||||
oldBody, oldFormattedBody, err = bodiesFromMessage(deleteMessage)
|
||||
|
@ -182,7 +182,7 @@ func (d *Dispatcher) getMessage(a *model.Application, id string) (gomatrix.Event
|
|||
}
|
||||
start = messages.End
|
||||
}
|
||||
return gomatrix.Event{}, api.ErrorMessageNotFound
|
||||
return gomatrix.Event{}, pberrors.ErrorMessageNotFound
|
||||
}
|
||||
|
||||
// Replaces the content of a matrix message
|
||||
|
@ -254,19 +254,19 @@ func bodiesFromMessage(message gomatrix.Event) (body, formattedBody string, err
|
|||
body, ok := val.(string)
|
||||
|
||||
if !ok {
|
||||
return "", "", api.ErrorMessageNotFound
|
||||
return "", "", pberrors.ErrorMessageNotFound
|
||||
}
|
||||
|
||||
formattedBody = body
|
||||
|
||||
} else {
|
||||
return "", "", api.ErrorMessageNotFound
|
||||
return "", "", pberrors.ErrorMessageNotFound
|
||||
}
|
||||
|
||||
if val, ok := message.Content["formatted_body"]; ok {
|
||||
body, ok := val.(string)
|
||||
if !ok {
|
||||
return "", "", api.ErrorMessageNotFound
|
||||
return "", "", pberrors.ErrorMessageNotFound
|
||||
}
|
||||
|
||||
formattedBody = body
|
||||
|
|
6
internal/pberrors/errors.go
Normal file
6
internal/pberrors/errors.go
Normal file
|
@ -0,0 +1,6 @@
|
|||
package pberrors
|
||||
|
||||
import "errors"
|
||||
|
||||
// ErrorMessageNotFound indicates that a message does not exist
|
||||
var ErrorMessageNotFound = errors.New("message not found")
|
32
tests/mockups/application.go
Normal file
32
tests/mockups/application.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
package mockups
|
||||
|
||||
import "github.com/pushbits/server/internal/model"
|
||||
|
||||
// GetApplication1 returns an application with id 1
|
||||
func GetApplication1() *model.Application {
|
||||
return &model.Application{
|
||||
ID: 1,
|
||||
Token: "1234567890abcdefghijklmn",
|
||||
UserID: 1,
|
||||
Name: "App1",
|
||||
}
|
||||
}
|
||||
|
||||
// GetApplication2 returns an application with id 2
|
||||
func GetApplication2() *model.Application {
|
||||
return &model.Application{
|
||||
ID: 2,
|
||||
Token: "0987654321xyzabcdefghij",
|
||||
UserID: 1,
|
||||
Name: "App2",
|
||||
}
|
||||
}
|
||||
|
||||
// GetAllApplications returns all mock-applications as a list
|
||||
func GetAllApplications() []*model.Application {
|
||||
applications := make([]*model.Application, 0)
|
||||
applications = append(applications, GetApplication1())
|
||||
applications = append(applications, GetApplication2())
|
||||
|
||||
return applications
|
||||
}
|
43
tests/mockups/config.go
Normal file
43
tests/mockups/config.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
package mockups
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/pushbits/server/internal/configuration"
|
||||
)
|
||||
|
||||
// ReadConfig copies the given filename to the current folder and parses it as a config file. RemoveFile indicates whether to remove the copied file or not
|
||||
func ReadConfig(filename string, removeFile bool) (config *configuration.Configuration, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Println(r)
|
||||
err = errors.New("paniced while reading config")
|
||||
}
|
||||
}()
|
||||
|
||||
if filename == "" {
|
||||
return nil, errors.New("empty filename")
|
||||
}
|
||||
|
||||
file, err := ioutil.ReadFile(filename)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile("config.yml", file, 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config = configuration.Get()
|
||||
|
||||
if removeFile {
|
||||
os.Remove("config.yml")
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
52
tests/mockups/database.go
Normal file
52
tests/mockups/database.go
Normal file
|
@ -0,0 +1,52 @@
|
|||
package mockups
|
||||
|
||||
import (
|
||||
"github.com/pushbits/server/internal/authentication/credentials"
|
||||
"github.com/pushbits/server/internal/configuration"
|
||||
"github.com/pushbits/server/internal/database"
|
||||
"github.com/pushbits/server/internal/model"
|
||||
)
|
||||
|
||||
// GetEmptyDatabase returns an empty sqlite database object
|
||||
func GetEmptyDatabase(confCrypto configuration.CryptoConfig) (*database.Database, error) {
|
||||
cm := credentials.CreateManager(false, confCrypto)
|
||||
return database.Create(cm, "sqlite3", "pushbits-test.db")
|
||||
}
|
||||
|
||||
// AddApplicationsToDb inserts the applications apps into the database db
|
||||
func AddApplicationsToDb(db *database.Database, apps []*model.Application) error {
|
||||
for _, app := range apps {
|
||||
err := db.CreateApplication(app)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddUsersToDb adds the users to the database and sets their username as a password, returns list of added users
|
||||
func AddUsersToDb(db *database.Database, users []*model.User) ([]*model.User, error) {
|
||||
addedUsers := make([]*model.User, 0)
|
||||
|
||||
for _, user := range users {
|
||||
extUser := model.ExternalUser{
|
||||
ID: user.ID,
|
||||
Name: user.Name,
|
||||
IsAdmin: user.IsAdmin,
|
||||
MatrixID: user.MatrixID,
|
||||
}
|
||||
credentials := model.UserCredentials{
|
||||
Password: user.Name,
|
||||
}
|
||||
createUser := model.CreateUser{ExternalUser: extUser, UserCredentials: credentials}
|
||||
|
||||
newUser, err := db.CreateUser(createUser)
|
||||
addedUsers = append(addedUsers, newUser)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return addedUsers, nil
|
||||
}
|
23
tests/mockups/dispatcher.go
Normal file
23
tests/mockups/dispatcher.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package mockups
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pushbits/server/internal/model"
|
||||
)
|
||||
|
||||
// MockDispatcher is a dispatcher used for testing - it does not need any storage interface
|
||||
type MockDispatcher struct {
|
||||
}
|
||||
|
||||
func (d *MockDispatcher) RegisterApplication(id uint, name, token, user string) (string, error) {
|
||||
return fmt.Sprintf("%d-%s", id, name), nil
|
||||
}
|
||||
|
||||
func (d *MockDispatcher) DeregisterApplication(a *model.Application, u *model.User) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *MockDispatcher) UpdateApplication(a *model.Application) error {
|
||||
return nil
|
||||
}
|
43
tests/mockups/user.go
Normal file
43
tests/mockups/user.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
package mockups
|
||||
|
||||
import (
|
||||
"github.com/pushbits/server/internal/authentication/credentials"
|
||||
"github.com/pushbits/server/internal/configuration"
|
||||
"github.com/pushbits/server/internal/model"
|
||||
)
|
||||
|
||||
// GetAdminUser returns an admin user
|
||||
func GetAdminUser(c *configuration.Configuration) *model.User {
|
||||
credentialsManager := credentials.CreateManager(false, c.Crypto)
|
||||
hash, _ := credentialsManager.CreatePasswordHash(c.Admin.Password)
|
||||
|
||||
return &model.User{
|
||||
ID: 1,
|
||||
Name: c.Admin.Name,
|
||||
PasswordHash: hash,
|
||||
IsAdmin: true,
|
||||
MatrixID: c.Admin.MatrixID,
|
||||
}
|
||||
}
|
||||
|
||||
// GetUser returns an user
|
||||
func GetUser(c *configuration.Configuration) *model.User {
|
||||
credentialsManager := credentials.CreateManager(false, c.Crypto)
|
||||
hash, _ := credentialsManager.CreatePasswordHash(c.Admin.Password)
|
||||
|
||||
return &model.User{
|
||||
ID: 2,
|
||||
Name: c.Admin.Name + "-normalo",
|
||||
PasswordHash: hash,
|
||||
IsAdmin: false,
|
||||
MatrixID: c.Admin.MatrixID,
|
||||
}
|
||||
}
|
||||
|
||||
// GetUsers returns a list of users
|
||||
func GetUsers(c *configuration.Configuration) []*model.User {
|
||||
var users []*model.User
|
||||
users = append(users, GetAdminUser(c))
|
||||
users = append(users, GetUser(c))
|
||||
return users
|
||||
}
|
47
tests/request.go
Normal file
47
tests/request.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
package tests
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Request holds information for a HTTP request
|
||||
type Request struct {
|
||||
Name string
|
||||
Method string
|
||||
Endpoint string
|
||||
Data interface{}
|
||||
Headers map[string]string
|
||||
ShouldStatus int
|
||||
}
|
||||
|
||||
// GetRequest returns a ResponseRecorder and gin context according to the data set in the Request.
|
||||
// String data is passed as is, all other data types are marshaled before.
|
||||
func (r *Request) GetRequest() (w *httptest.ResponseRecorder, c *gin.Context, err error) {
|
||||
var body io.Reader
|
||||
w = httptest.NewRecorder()
|
||||
|
||||
switch r.Data.(type) {
|
||||
case string:
|
||||
body = strings.NewReader(r.Data.(string))
|
||||
default:
|
||||
dataMarshaled, err := json.Marshal(r.Data)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body = strings.NewReader(string(dataMarshaled))
|
||||
}
|
||||
|
||||
c, _ = gin.CreateTestContext(w)
|
||||
c.Request = httptest.NewRequest(r.Method, r.Endpoint, body)
|
||||
|
||||
for name, value := range r.Headers {
|
||||
c.Request.Header.Set(name, value)
|
||||
}
|
||||
|
||||
return w, c, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue