Commit 1de4d9c9 authored by Sonja Happ's avatar Sonja Happ
Browse files

Code base refactoring: no functional changes, improving test coverage

parent eb10488c
......@@ -25,6 +25,7 @@ import (
"encoding/json"
"fmt"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
"github.com/gin-gonic/gin"
"github.com/streadway/amqp"
"github.com/tidwall/gjson"
"log"
......@@ -203,3 +204,37 @@ func CheckConnection() error {
return nil
}
func StartAMQP(AMQPurl string, api *gin.RouterGroup) error {
if AMQPurl != "" {
log.Println("Starting AMQP client")
err := ConnectAMQP(AMQPurl)
if err != nil {
return err
}
// register IC action endpoint only if AMQP client is used
RegisterAMQPEndpoint(api.Group("/ic"))
// Periodically call the Ping function to check which ICs are still there
ticker := time.NewTicker(10 * time.Second)
go func() {
for {
select {
case <-ticker.C:
err = PingAMQP()
if err != nil {
log.Println("AMQP Error: ", err.Error())
}
}
}
}()
log.Printf("Connected AMQP client to %s", AMQPurl)
}
return nil
}
......@@ -23,10 +23,9 @@ package configuration
import (
"flag"
"github.com/zpatrick/go-config"
"log"
"os"
"github.com/zpatrick/go-config"
)
// Global configuration
......@@ -109,9 +108,48 @@ func InitConfig() error {
settings, _ := GolbalConfig.Settings()
log.Print("All settings:")
for key, val := range settings {
// TODO password settings should be excluded!
log.Printf(" %s = %s \n", key, val)
}
}
return nil
}
func ConfigureBackend() (string, string, string, string, string, string, string, error) {
err := InitConfig()
if err != nil {
log.Printf("Error during initialization of global configuration: %v, aborting.", err.Error())
return "", "", "", "", "", "", "", err
}
mode, err := GolbalConfig.String("mode")
if err != nil {
log.Printf("Error reading mode from global configuration: %v, aborting.", err.Error())
return "", "", "", "", "", "", "", err
}
baseHost, err := GolbalConfig.String("base.host")
if err != nil {
log.Printf("Error reading base.host from global configuration: %v, aborting.", err.Error())
return "", "", "", "", "", "", "", err
}
basePath, err := GolbalConfig.String("base.path")
if err != nil {
log.Printf("Error reading base.path from global configuration: %v, aborting.", err.Error())
return "", "", "", "", "", "", "", err
}
port, err := GolbalConfig.String("port")
if err != nil {
log.Printf("Error reading port from global configuration: %v, aborting.", err.Error())
return "", "", "", "", "", "", "", err
}
AMQPhost, _ := GolbalConfig.String("amqp.host")
AMQPuser, _ := GolbalConfig.String("amqp.user")
AMQPpass, _ := GolbalConfig.String("amqp.pass")
return mode, baseHost, basePath, port, AMQPhost, AMQPuser, AMQPpass, nil
}
......@@ -23,7 +23,7 @@ package database
import (
"fmt"
"log"
"github.com/zpatrick/go-config"
"os"
"testing"
......@@ -32,40 +32,77 @@ import (
)
func TestMain(m *testing.M) {
err := configuration.InitConfig()
if err != nil {
panic(m)
}
err = InitDB(configuration.GolbalConfig)
if err != nil {
panic(m)
}
// Verify that you can connect to the database
err = DBpool.DB().Ping()
if err != nil {
log.Panic("Error: DB must ping to run tests")
}
defer DBpool.Close()
os.Exit(m.Run())
}
func TestInitDB(t *testing.T) {
err := configuration.InitConfig()
assert.NoError(t, err)
static := map[string]string{}
mappings := map[string]string{}
defaults := config.NewStatic(static)
env := config.NewEnvironment(mappings)
ownconfig := config.NewConfig([]config.Provider{defaults, env})
err = InitDB(ownconfig)
assert.Error(t, err)
dbname, err := configuration.GolbalConfig.String("db.name")
assert.NoError(t, err)
static["db.name"] = dbname
ownconfig = config.NewConfig([]config.Provider{defaults, env})
err = InitDB(ownconfig)
assert.Error(t, err)
dbhost, err := configuration.GolbalConfig.String("db.host")
assert.NoError(t, err)
static["db.host"] = dbhost
ownconfig = config.NewConfig([]config.Provider{defaults, env})
err = InitDB(ownconfig)
assert.Error(t, err)
dbuser, err := configuration.GolbalConfig.String("db.user")
static["db.user"] = dbuser
ownconfig = config.NewConfig([]config.Provider{defaults, env})
err = InitDB(ownconfig)
assert.Error(t, err)
dbpass, err := configuration.GolbalConfig.String("db.pass")
static["db.pass"] = dbpass
ownconfig = config.NewConfig([]config.Provider{defaults, env})
err = InitDB(ownconfig)
assert.Error(t, err)
dbssl, err := configuration.GolbalConfig.String("db.ssl")
assert.NoError(t, err)
static["db.ssl"] = dbssl
ownconfig = config.NewConfig([]config.Provider{defaults, env})
err = InitDB(ownconfig)
assert.NoError(t, err)
// Verify that you can connect to the database
db := GetDB()
err = db.DB().Ping()
assert.NoError(t, err)
}
func TestUserAssociations(t *testing.T) {
DropTables()
MigrateModels()
// create copies of global test data
scenarioA := ScenarioA
scenarioB := ScenarioB
user0 := User0
userA := UserA
userB := UserB
// add three users to DB
assert.NoError(t, DBpool.Create(&user0).Error) // Admin
scenarioA := Scenario{}
scenarioB := Scenario{}
userA := User{Username: "abcdef"}
userB := User{Username: "ghijkl"}
// add users to DB
assert.NoError(t, DBpool.Create(&userA).Error) // Normal User
assert.NoError(t, DBpool.Create(&userB).Error) // Normal User
......@@ -78,11 +115,9 @@ func TestUserAssociations(t *testing.T) {
assert.NoError(t, DBpool.Model(&userA).Association("Scenarios").Append(&scenarioA).Error)
assert.NoError(t, DBpool.Model(&userA).Association("Scenarios").Append(&scenarioB).Error)
assert.NoError(t, DBpool.Model(&userB).Association("Scenarios").Append(&scenarioA).Error)
assert.NoError(t, DBpool.Model(&userB).Association("Scenarios").Append(&scenarioB).Error)
var usr1 User
assert.NoError(t, DBpool.Find(&usr1, "ID = ?", 2).Error, fmt.Sprintf("Find User with ID=2"))
assert.EqualValues(t, "User_A", usr1.Username)
assert.NoError(t, DBpool.Find(&usr1, "ID = ?", 1).Error, fmt.Sprintf("Find User with ID=1"))
// Get scenarios of usr1
var scenarios []Scenario
......@@ -99,22 +134,20 @@ func TestScenarioAssociations(t *testing.T) {
MigrateModels()
// create copies of global test data
scenarioA := ScenarioA
scenarioB := ScenarioB
user0 := User0
userA := UserA
userB := UserB
configA := ConfigA
configB := ConfigB
dashboardA := DashboardA
dashboardB := DashboardB
scenarioA := Scenario{}
scenarioB := Scenario{}
userA := User{Username: "abcdef"}
userB := User{Username: "ghijkl"}
configA := ComponentConfiguration{}
configB := ComponentConfiguration{}
dashboardA := Dashboard{}
dashboardB := Dashboard{}
// add scenarios to DB
assert.NoError(t, DBpool.Create(&scenarioA).Error)
assert.NoError(t, DBpool.Create(&scenarioB).Error)
// add users to DB
assert.NoError(t, DBpool.Create(&user0).Error) // Admin
assert.NoError(t, DBpool.Create(&userA).Error) // Normal User
assert.NoError(t, DBpool.Create(&userB).Error) // Normal User
......@@ -143,7 +176,6 @@ func TestScenarioAssociations(t *testing.T) {
var scenario1 Scenario
assert.NoError(t, DBpool.Find(&scenario1, 1).Error, fmt.Sprintf("Find Scenario with ID=1"))
assert.EqualValues(t, "Scenario_A", scenario1.Name)
// Get users of scenario1
var users []User
......@@ -176,10 +208,10 @@ func TestICAssociations(t *testing.T) {
MigrateModels()
// create copies of global test data
icA := ICA
icB := ICB
configA := ConfigA
configB := ConfigB
icA := InfrastructureComponent{}
icB := InfrastructureComponent{}
configA := ComponentConfiguration{}
configB := ComponentConfiguration{}
// add ICs to DB
assert.NoError(t, DBpool.Create(&icA).Error)
......@@ -195,7 +227,6 @@ func TestICAssociations(t *testing.T) {
var ic1 InfrastructureComponent
assert.NoError(t, DBpool.Find(&ic1, 1).Error, fmt.Sprintf("Find InfrastructureComponent with ID=1"))
assert.EqualValues(t, "xxx.yyy.zzz.aaa", ic1.Host)
// Get Component Configurations of ic1
var configs []ComponentConfiguration
......@@ -212,18 +243,18 @@ func TestComponentConfigurationAssociations(t *testing.T) {
MigrateModels()
// create copies of global test data
configA := ConfigA
configB := ConfigB
outSignalA := OutSignalA
outSignalB := OutSignalB
inSignalA := InSignalA
inSignalB := InSignalB
fileA := FileA
fileB := FileB
fileC := FileC
fileD := FileD
icA := ICA
icB := ICB
configA := ComponentConfiguration{}
configB := ComponentConfiguration{}
outSignalA := Signal{Direction: "out"}
outSignalB := Signal{Direction: "out"}
inSignalA := Signal{Direction: "in"}
inSignalB := Signal{Direction: "in"}
fileA := File{}
fileB := File{}
fileC := File{}
fileD := File{}
icA := InfrastructureComponent{}
icB := InfrastructureComponent{}
// add Component Configurations to DB
assert.NoError(t, DBpool.Create(&configA).Error)
......@@ -261,7 +292,6 @@ func TestComponentConfigurationAssociations(t *testing.T) {
var config1 ComponentConfiguration
assert.NoError(t, DBpool.Find(&config1, 1).Error, fmt.Sprintf("Find ComponentConfiguration with ID=1"))
assert.EqualValues(t, ConfigA.Name, config1.Name)
// Check IC ID
if config1.ICID != 1 {
......@@ -291,10 +321,10 @@ func TestDashboardAssociations(t *testing.T) {
MigrateModels()
// create copies of global test data
dashboardA := DashboardA
dashboardB := DashboardB
widgetA := WidgetA
widgetB := WidgetB
dashboardA := Dashboard{}
dashboardB := Dashboard{}
widgetA := Widget{}
widgetB := Widget{}
// add dashboards to DB
assert.NoError(t, DBpool.Create(&dashboardA).Error)
......@@ -310,7 +340,6 @@ func TestDashboardAssociations(t *testing.T) {
var dashboard1 Dashboard
assert.NoError(t, DBpool.Find(&dashboard1, 1).Error, fmt.Sprintf("Find Dashboard with ID=1"))
assert.EqualValues(t, "Dashboard_A", dashboard1.Name)
//Get widgets of dashboard1
var widgets []Widget
......@@ -327,12 +356,12 @@ func TestWidgetAssociations(t *testing.T) {
MigrateModels()
// create copies of global test data
widgetA := WidgetA
widgetB := WidgetB
fileA := FileA
fileB := FileB
fileC := FileC
fileD := FileD
widgetA := Widget{}
widgetB := Widget{}
fileA := File{}
fileB := File{}
fileC := File{}
fileD := File{}
// add widgets to DB
assert.NoError(t, DBpool.Create(&widgetA).Error)
......@@ -350,7 +379,6 @@ func TestWidgetAssociations(t *testing.T) {
var widget1 Widget
assert.NoError(t, DBpool.Find(&widget1, 1).Error, fmt.Sprintf("Find Widget with ID=1"))
assert.EqualValues(t, widgetA.Name, widget1.Name)
// Get files of widget
var files []File
......@@ -367,10 +395,10 @@ func TestFileAssociations(t *testing.T) {
MigrateModels()
// create copies of global test data
fileA := FileA
fileB := FileB
fileC := FileC
fileD := FileD
fileA := File{}
fileB := File{}
fileC := File{}
fileD := File{}
// add files to DB
assert.NoError(t, DBpool.Create(&fileA).Error)
......@@ -380,19 +408,4 @@ func TestFileAssociations(t *testing.T) {
var file1 File
assert.NoError(t, DBpool.Find(&file1, 1).Error, fmt.Sprintf("Find File with ID=1"))
assert.EqualValues(t, "File_A", file1.Name)
}
func TestAddAdmin(t *testing.T) {
DropTables()
MigrateModels()
assert.NoError(t, DBAddAdminUser())
}
func TestAddAdminAndUsers(t *testing.T) {
DropTables()
MigrateModels()
assert.NoError(t, DBAddAdminAndUserAndGuest())
}
/** Database package, test data.
/** Helper package, test data.
*
* @author Sonja Happ <sonja.happ@eonerc.rwth-aachen.de>
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
......@@ -19,21 +19,14 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
package database
package helper
import (
"bytes"
"encoding/json"
"fmt"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/helper"
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
"github.com/jinzhu/gorm/dialects/postgres"
"golang.org/x/crypto/bcrypt"
"io"
"mime/multipart"
"net/http"
"net/http/httptest"
"os"
"time"
)
......@@ -41,7 +34,7 @@ import (
// #################### Data used for testing ############################
// #######################################################################
// Users
// Credentials
var StrPassword0 = "xyz789"
var StrPasswordA = "abc123"
var StrPasswordB = "bcd234"
......@@ -54,13 +47,13 @@ var pwA, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordA), bcryptCost)
var pwB, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordB), bcryptCost)
var pwC, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordC), bcryptCost)
var User0 = User{Username: "User_0", Password: string(pw0),
var User0 = database.User{Username: "User_0", Password: string(pw0),
Role: "Admin", Mail: "User_0@example.com", Active: true}
var UserA = User{Username: "User_A", Password: string(pwA),
var UserA = database.User{Username: "User_A", Password: string(pwA),
Role: "User", Mail: "User_A@example.com", Active: true}
var UserB = User{Username: "User_B", Password: string(pwB),
var UserB = database.User{Username: "User_B", Password: string(pwB),
Role: "User", Mail: "User_B@example.com", Active: true}
var UserC = User{Username: "User_C", Password: string(pwC),
var UserC = database.User{Username: "User_C", Password: string(pwC),
Role: "Guest", Mail: "User_C@example.com", Active: true}
type UserRequest struct {
......@@ -72,21 +65,21 @@ type UserRequest struct {
Active string `json:"active,omitempty"`
}
var newUserA = UserRequest{
var NewUserA = UserRequest{
Username: UserA.Username,
Password: StrPasswordA,
Role: UserA.Role,
Mail: UserA.Mail,
}
var newUserB = UserRequest{
var NewUserB = UserRequest{
Username: UserB.Username,
Password: StrPasswordB,
Role: UserB.Role,
Mail: UserB.Mail,
}
var newUserC = UserRequest{
var NewUserC = UserRequest{
Username: UserC.Username,
Password: StrPasswordC,
Role: UserC.Role,
......@@ -98,7 +91,7 @@ var newUserC = UserRequest{
var propertiesA = json.RawMessage(`{"location" : "ACSlab"}`)
var propertiesB = json.RawMessage(`{"location" : "ACSlab"}`)
var ICA = InfrastructureComponent{
var ICA = database.InfrastructureComponent{
UUID: "4854af30-325f-44a5-ad59-b67b2597de68",
Host: "xxx.yyy.zzz.aaa",
Type: "DPsim",
......@@ -111,7 +104,7 @@ var ICA = InfrastructureComponent{
RawProperties: postgres.Jsonb{propertiesA},
}
var ICB = InfrastructureComponent{
var ICB = database.InfrastructureComponent{
UUID: "7be0322d-354e-431e-84bd-ae4c9633138b",
Host: "xxx.yyy.zzz.bbb",
Type: "VILLASnode",
......@@ -129,12 +122,12 @@ var ICB = InfrastructureComponent{
var startParametersA = json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`)
var startParametersB = json.RawMessage(`{"parameter1" : "testValue1B", "parameter2" : "testValue2B", "parameter3" : 43}`)
var ScenarioA = Scenario{
var ScenarioA = database.Scenario{
Name: "Scenario_A",
Running: true,
StartParameters: postgres.Jsonb{startParametersA},
}
var ScenarioB = Scenario{
var ScenarioB = database.Scenario{
Name: "Scenario_B",
Running: false,
StartParameters: postgres.Jsonb{startParametersB},
......@@ -142,13 +135,13 @@ var ScenarioB = Scenario{
// Component Configuration
var ConfigA = ComponentConfiguration{
var ConfigA = database.ComponentConfiguration{
Name: "Example simulation",
StartParameters: postgres.Jsonb{startParametersA},
SelectedFileID: 3,
}
var ConfigB = ComponentConfiguration{
var ConfigB = database.ComponentConfiguration{
Name: "VILLASnode gateway X",
StartParameters: postgres.Jsonb{startParametersB},
SelectedFileID: 4,
......@@ -156,28 +149,28 @@ var ConfigB = ComponentConfiguration{
// Signals
var OutSignalA = Signal{
var OutSignalA = database.Signal{
Name: "outSignal_A",
Direction: "out",
Index: 1,
Unit: "V",
}
var OutSignalB = Signal{
var OutSignalB = database.Signal{
Name: "outSignal_B",
Direction: "out",
Index: 2,
Unit: "V",
}
var InSignalA = Signal{
var InSignalA = database.Signal{
Name: "inSignal_A",
Direction: "in",
Index: 1,
Unit: "A",
}
var InSignalB = Signal{
var InSignalB = database.Signal{
Name: "inSignal_B",
Direction: "in",
Index: 2,
......@@ -186,38 +179,38 @@ var InSignalB = Signal{
// Dashboards
var DashboardA = Dashboard{
var DashboardA = database.Dashboard{
Name: "Dashboard_A",
Grid: 15,
}
var DashboardB = Dashboard{
var DashboardB = database.Dashboard{
Name: "Dashboard_B",
Grid: 10,
}
// Files
var FileA = File{
var FileA = database.File{
Name: "File_A",
Type: "text/plain",
Size: 42,
Date: time.Now().String(),
}
var FileB = File{
var FileB = database.File{
Name: "File_B",
Type: "text/plain",
Size: 1234,
Date: time.Now().String(),
}
var FileC = File{
var FileC = database.File{
Name: "File_C",
Type: "text/plain",
Size: 32,
Date: time.Now().String(),
}
var FileD = File{
var FileD = database.File{
Name: "File_D",
Type: "text/plain",
Size: 5000,
......@@ -234,7 +227,7 @@ var customPropertiesCustomActions = json.RawMessage(`{"actions" : "Value1", "ico
var customPropertiesGauge = json.RawMessage(`{ "valueMin": 0, "valueMax": 1}`)
var customPropertiesLamp = json.RawMessage(`{"signal" : 0, "on_color" : 4, "off_color": 2 , "threshold" : 0.5}`)
var WidgetA = Widget{
var WidgetA = database.Widget{
Name: "Label",