- revise testing of simulators

- add validators for simulators
- clean up testdata, serializers and responses
- update documentation for swaggo
This commit is contained in:
Sonja Happ 2019-09-05 12:23:44 +02:00
parent 7bc94c1131
commit a55d039ee7
8 changed files with 647 additions and 287 deletions

View file

@ -12,18 +12,6 @@ type SimulationModelResponse struct {
StartParameters postgres.Jsonb `json:"startParameters"`
}
type SimulatorResponse struct {
ID uint `json:"id"`
UUID string `json:"uuid"`
Host string `json:"host"`
Modeltype string `json:"modelType"`
Uptime int `json:"uptime"`
State string `json:"state"`
StateUpdateAt string `json:"stateUpdateAt"`
Properties postgres.Jsonb `json:"properties"`
RawProperties postgres.Jsonb `json:"rawProperties"`
}
type DashboardResponse struct {
ID uint `json:"id"`
Name string `json:"name"`
@ -105,14 +93,6 @@ type ResponseMsgWidget struct {
Widget WidgetResponse `json:"widget"`
}
type ResponseMsgSimulators struct {
Simulators []SimulatorResponse `json:"simulators"`
}
type ResponseMsgSimulator struct {
Simulator SimulatorResponse `json:"simulator"`
}
type ResponseMsgFiles struct {
Files []FileResponse `json:"files"`
}

View file

@ -38,43 +38,6 @@ func (self *SimulationModelSerializer) Response() SimulationModelResponse {
return response
}
// Simulator/s Serializers
type SimulatorsSerializer struct {
Ctx *gin.Context
Simulators []Simulator
}
func (self *SimulatorsSerializer) Response() []SimulatorResponse {
response := []SimulatorResponse{}
for _, simulator := range self.Simulators {
serializer := SimulatorSerializer{self.Ctx, simulator}
response = append(response, serializer.Response())
}
return response
}
type SimulatorSerializer struct {
Ctx *gin.Context
Simulator
}
func (self *SimulatorSerializer) Response() SimulatorResponse {
response := SimulatorResponse{
ID: self.ID,
UUID: self.UUID,
Host: self.Host,
Modeltype: self.Modeltype,
Uptime: self.Uptime,
State: self.State,
StateUpdateAt: self.StateUpdateAt,
Properties: self.Properties,
RawProperties: self.RawProperties,
}
return response
}
// Dashboard/s Serializers
type DashboardsSerializer struct {

View file

@ -57,8 +57,6 @@ var UserBCredentials = Credentials{
var propertiesA = json.RawMessage(`{"name" : "TestNameA", "category" : "CategoryA", "location" : "anywhere on earth", "type": "dummy"}`)
var propertiesB = json.RawMessage(`{"name" : "TestNameB", "category" : "CategoryB", "location" : "where ever you want", "type": "generic"}`)
var propertiesC = json.RawMessage(`{"name" : "TestNameC", "category" : "CategoryC", "location" : "my desk", "type": "blubb"}`)
var propertiesCupdated = json.RawMessage(`{"name" : "TestNameCUpdate", "category" : "CategoryC", "location" : "my desk", "type": "blubb"}`)
var SimulatorA = Simulator{
UUID: "4854af30-325f-44a5-ad59-b67b2597de68",
@ -71,18 +69,6 @@ var SimulatorA = Simulator{
RawProperties: postgres.Jsonb{propertiesA},
}
var SimulatorA_response = SimulatorResponse{
ID: 1,
UUID: SimulatorA.UUID,
Host: SimulatorA.Host,
Modeltype: SimulatorA.Modeltype,
Uptime: SimulatorA.Uptime,
State: SimulatorA.State,
StateUpdateAt: SimulatorA.StateUpdateAt,
Properties: SimulatorA.Properties,
RawProperties: SimulatorA.RawProperties,
}
var SimulatorB = Simulator{
UUID: "7be0322d-354e-431e-84bd-ae4c9633138b",
Host: "Host_B",
@ -94,72 +80,22 @@ var SimulatorB = Simulator{
RawProperties: postgres.Jsonb{propertiesB},
}
var SimulatorB_response = SimulatorResponse{
ID: 2,
UUID: SimulatorB.UUID,
Host: SimulatorB.Host,
Modeltype: SimulatorB.Modeltype,
Uptime: SimulatorB.Uptime,
State: SimulatorB.State,
StateUpdateAt: SimulatorB.StateUpdateAt,
Properties: SimulatorB.Properties,
RawProperties: SimulatorB.RawProperties,
}
var SimulatorC = Simulator{
UUID: "6d9776bf-b693-45e8-97b6-4c13d151043f",
Host: "Host_C",
Modeltype: "ModelTypeC",
Uptime: 0,
State: "idle",
StateUpdateAt: time.Now().String(),
Properties: postgres.Jsonb{propertiesC},
RawProperties: postgres.Jsonb{propertiesC},
}
var SimulatorC_response = SimulatorResponse{
ID: 3,
UUID: SimulatorC.UUID,
Host: SimulatorC.Host,
Modeltype: SimulatorC.Modeltype,
Uptime: SimulatorC.Uptime,
State: SimulatorC.State,
StateUpdateAt: SimulatorC.StateUpdateAt,
Properties: SimulatorC.Properties,
RawProperties: SimulatorC.RawProperties,
}
var SimulatorCUpdated = Simulator{
UUID: SimulatorC.UUID,
Host: "Host_Cupdated",
Modeltype: "ModelTypeCUpdated",
Uptime: SimulatorC.Uptime,
State: "running",
StateUpdateAt: time.Now().String(),
Properties: postgres.Jsonb{propertiesCupdated},
RawProperties: postgres.Jsonb{propertiesCupdated},
}
var SimulatorCUpdated_response = SimulatorResponse{
ID: 3,
UUID: SimulatorCUpdated.UUID,
Host: SimulatorCUpdated.Host,
Modeltype: SimulatorCUpdated.Modeltype,
Uptime: SimulatorCUpdated.Uptime,
State: SimulatorCUpdated.State,
StateUpdateAt: SimulatorCUpdated.StateUpdateAt,
Properties: SimulatorCUpdated.Properties,
RawProperties: SimulatorCUpdated.RawProperties,
}
// Scenarios
var startParametersA = json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`)
var startParametersB = json.RawMessage(`{"parameter1" : "testValue1B", "parameter2" : "testValue2B", "parameter3" : 43}`)
var startParametersC = json.RawMessage(`{"parameter1" : "testValue1C", "parameter2" : "testValue2C", "parameter3" : 44}`)
var ScenarioA = Scenario{Name: "Scenario_A", Running: true, StartParameters: postgres.Jsonb{startParametersA}}
var ScenarioB = Scenario{Name: "Scenario_B", Running: false, StartParameters: postgres.Jsonb{startParametersB}}
var ScenarioA = Scenario{
Name: "Scenario_A",
Running: true,
StartParameters: postgres.Jsonb{startParametersA},
}
var ScenarioB = Scenario{
Name: "Scenario_B",
Running: false,
StartParameters: postgres.Jsonb{startParametersB},
}
// Simulation Models

View file

@ -40,3 +40,11 @@ type ResponseScenarios struct {
type ResponseScenario struct {
scenario common.Scenario
}
type ResponseSimulationModels struct {
models []common.SimulationModel
}
type ResponseSimulationModel struct {
model common.SimulationModel
}

View file

@ -3,7 +3,6 @@ package simulator
import (
"fmt"
"net/http"
"strconv"
"time"
"github.com/gin-gonic/gin"
@ -29,17 +28,19 @@ func RegisterSimulatorEndpoints(r *gin.RouterGroup) {
// @ID getSimulators
// @Tags simulators
// @Produce json
// @Success 200 {array} common.ResponseMsgSimulators "Simulator parameters requested by user"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Success 200 {object} docs.ResponseSimulators "Simulators requested"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Router /simulators [get]
func getSimulators(c *gin.Context) {
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
c.JSON(http.StatusUnprocessableEntity, gin.H{
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
@ -49,9 +50,9 @@ func getSimulators(c *gin.Context) {
if common.ProvideErrorResponse(c, err) {
return
}
serializer := common.SimulatorsSerializer{c, simulators}
c.JSON(http.StatusOK, gin.H{
"simulators": serializer.Response(),
"simulators": simulators,
})
}
@ -61,48 +62,57 @@ func getSimulators(c *gin.Context) {
// @Accept json
// @Produce json
// @Tags simulators
// @Param inputSimulator body common.ResponseMsgSimulator true "Simulator to be added"
// @Success 200 "OK."
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Param inputSimulator body simulator.validNewSimulator true "Simulator to be added"
// @Success 200 {object} docs.ResponseSimulator "Simulator that was added"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Router /simulators [post]
func addSimulator(c *gin.Context) {
err := common.ValidateRole(c, common.ModelSimulator, common.Create)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
c.JSON(http.StatusUnprocessableEntity, gin.H{
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
var newSimulatorData common.ResponseMsgSimulator
err = c.BindJSON(&newSimulatorData)
var req addSimulatorRequest
err = c.BindJSON(&req)
if err != nil {
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": errormsg,
})
return
}
var newSimulator Simulator
newSimulator.ID = newSimulatorData.Simulator.ID
newSimulator.State = newSimulatorData.Simulator.State
newSimulator.StateUpdateAt = newSimulatorData.Simulator.StateUpdateAt
newSimulator.Modeltype = newSimulatorData.Simulator.Modeltype
newSimulator.UUID = newSimulatorData.Simulator.UUID
newSimulator.Uptime = newSimulatorData.Simulator.Uptime
newSimulator.Host = newSimulatorData.Simulator.Host
newSimulator.RawProperties = newSimulatorData.Simulator.RawProperties
newSimulator.Properties = newSimulatorData.Simulator.Properties
err = newSimulator.save()
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
// Validate the request
if err = req.validate(); err != nil {
c.JSON(http.StatusUnprocessableEntity, gin.H{
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
// Create the new simulator from the request
newSimulator := req.createSimulator()
// Save new simulator to DB
err = newSimulator.save()
if err != nil {
common.ProvideErrorResponse(c, err)
return
}
c.JSON(http.StatusOK, gin.H{
"simulator": newSimulator.Simulator,
})
}
// updateSimulator godoc
@ -111,53 +121,80 @@ func addSimulator(c *gin.Context) {
// @Tags simulators
// @Accept json
// @Produce json
// @Param inputSimulator body common.ResponseMsgSimulator true "Simulator to be updated"
// @Success 200 "OK."
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Param inputSimulator body simulator.validUpdatedSimulator true "Simulator to be updated"
// @Success 200 {object} docs.ResponseSimulator "Simulator that was updated"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param simulatorID path int true "Simulator ID"
// @Router /simulators/{simulatorID} [put]
func updateSimulator(c *gin.Context) {
err := common.ValidateRole(c, common.ModelSimulator, common.Update)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
return
}
var modifiedSimulator common.ResponseMsgSimulator
err = c.BindJSON(&modifiedSimulator)
if err != nil {
errormsg := "Bad request. Error unmarshalling data to JSON: " + err.Error()
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
c.JSON(http.StatusUnprocessableEntity, gin.H{
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
var req updateSimulatorRequest
err = c.BindJSON(&req)
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": "Bad request. Error binding form data to JSON: " + err.Error(),
})
return
}
var s Simulator
err = s.ByID(uint(simulatorID))
// Validate the request
if err = req.validate(); err != nil {
c.JSON(http.StatusUnprocessableEntity, gin.H{
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
// Get the ID of the simulator to be updated from the context
toBeUpdatedID, err := common.UintParamFromCtx(c, "simulatorID")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": fmt.Sprintf("Could not get simulator's ID from context"),
})
return
}
var oldSimulator Simulator
err = oldSimulator.ByID(toBeUpdatedID)
if common.ProvideErrorResponse(c, err) {
return
}
err = s.update(modifiedSimulator.Simulator)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
// Create the updatedSimulator from oldSimulator
updatedSimulator, err := req.updatedSimulator(oldSimulator)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
// Finally update the simulator in the DB
err = oldSimulator.update(updatedSimulator)
if err != nil {
common.ProvideErrorResponse(c, err)
return
}
c.JSON(http.StatusOK, gin.H{
"simulator": updatedSimulator.Simulator,
})
}
// getSimulator godoc
@ -165,39 +202,42 @@ func updateSimulator(c *gin.Context) {
// @ID getSimulator
// @Produce json
// @Tags simulators
// @Success 200 {object} common.ResponseMsgSimulator "Simulator requested by user"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Success 200 {object} docs.ResponseSimulator "Simulator that was requested"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param simulatorID path int true "Simulator ID"
// @Router /simulators/{simulatorID} [get]
func getSimulator(c *gin.Context) {
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
c.JSON(http.StatusUnprocessableEntity, gin.H{
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
// Get the ID of the simulator from the context
simulatorID, err := common.UintParamFromCtx(c, "simulatorID")
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("Could not get simulator's ID from context"),
})
return
}
var s Simulator
err = s.ByID(uint(simulatorID))
err = s.ByID(simulatorID)
if common.ProvideErrorResponse(c, err) {
return
}
serializer := common.SimulatorSerializer{c, s.Simulator}
c.JSON(http.StatusOK, gin.H{
"simulator": serializer.Response(),
"simulator": s.Simulator,
})
}
@ -206,43 +246,48 @@ func getSimulator(c *gin.Context) {
// @ID deleteSimulator
// @Tags simulators
// @Produce json
// @Success 200 "OK."
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Success 200 {object} docs.ResponseSimulator "Simulator that was deleted"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param simulatorID path int true "Simulator ID"
// @Router /simulators/{simulatorID} [delete]
func deleteSimulator(c *gin.Context) {
err := common.ValidateRole(c, common.ModelSimulator, common.Delete)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
c.JSON(http.StatusUnprocessableEntity, gin.H{
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
// Get the ID of the simulator from the context
simulatorID, err := common.UintParamFromCtx(c, "simulatorID")
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("Could not get simulator's ID from context"),
})
return
}
var s Simulator
err = s.ByID(uint(simulatorID))
err = s.ByID(simulatorID)
if common.ProvideErrorResponse(c, err) {
return
}
// Delete the simulator
err = s.delete()
if common.ProvideErrorResponse(c, err) {
return
}
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
"simulator": s.Simulator,
})
}
@ -251,32 +296,36 @@ func deleteSimulator(c *gin.Context) {
// @ID getModelsOfSimulator
// @Tags simulators
// @Produce json
// @Success 200 {object} common.ResponseMsgSimulationModels "Simulation models requested by user"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Success 200 {object} docs.ResponseSimulationModels "Simulation models requested by user"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param simulatorID path int true "Simulator ID"
// @Router /simulators/{simulatorID}/models [get]
func getModelsOfSimulator(c *gin.Context) {
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
c.JSON(http.StatusUnprocessableEntity, gin.H{
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
// Get the ID of the simulator from the context
simulatorID, err := common.UintParamFromCtx(c, "simulatorID")
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("Could not get simulator's ID from context"),
})
return
}
var s Simulator
err = s.ByID(uint(simulatorID))
err = s.ByID(simulatorID)
if common.ProvideErrorResponse(c, err) {
return
}
@ -287,11 +336,9 @@ func getModelsOfSimulator(c *gin.Context) {
return
}
serializer := common.SimulationModelsSerializer{c, allModels}
c.JSON(http.StatusOK, gin.H{
"models": serializer.Response(),
"models": allModels,
})
}
// sendActionToSimulator godoc
@ -300,26 +347,30 @@ func getModelsOfSimulator(c *gin.Context) {
// @Tags simulators
// @Produce json
// @Param inputAction query string true "Action for simulator"
// @Success 200 "OK."
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Success 200 {object} docs.ResponseError "Action sent successfully"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param simulatorID path int true "Simulator ID"
// @Router /simulators/{simulatorID}/action [post]
func sendActionToSimulator(c *gin.Context) {
err := common.ValidateRole(c, common.ModelSimulatorAction, common.Update)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
c.JSON(http.StatusUnprocessableEntity, gin.H{
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
// Get the ID of the simulator from the context
simulatorID, err := common.UintParamFromCtx(c, "simulatorID")
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("Could not get simulator's ID from context"),
})
return
}
@ -358,6 +409,7 @@ func sendActionToSimulator(c *gin.Context) {
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "OK.",
})
}

View file

@ -25,13 +25,12 @@ func (s *Simulator) ByID(id uint) error {
return nil
}
func (s *Simulator) update(modifiedSimulator common.SimulatorResponse) error {
func (s *Simulator) update(updatedSimulator Simulator) error {
db := common.GetDB()
err := db.Model(s).Updates(modifiedSimulator).Error
err := db.Model(s).Updates(updatedSimulator).Error
return err
}
func (s *Simulator) delete() error {

View file

@ -1,7 +1,11 @@
package simulator
import (
"encoding/json"
"fmt"
"github.com/jinzhu/gorm"
"github.com/jinzhu/gorm/dialects/postgres"
"github.com/stretchr/testify/assert"
"os"
"testing"
"github.com/gin-gonic/gin"
@ -10,62 +14,398 @@ import (
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/user"
)
// Test /simulator endpoints
func TestSimulatorEndpoints(t *testing.T) {
var router *gin.Engine
var db *gorm.DB
var token string
type SimulatorRequest struct {
UUID string `json:"uuid,omitempty"`
Host string `json:"host,omitempty"`
Modeltype string `json:"modelType,omitempty"`
State string `json:"state,omitempty"`
Properties postgres.Jsonb `json:"properties,omitempty"`
}
var myModels = []common.SimulationModelResponse{common.SimulationModelA_response, common.SimulationModelB_response}
var msgModels = common.ResponseMsgSimulationModels{SimulationModels: myModels}
var simulatorC_msg = common.ResponseMsgSimulator{Simulator: common.SimulatorC_response}
var simulatorCupdated_msg = common.ResponseMsgSimulator{Simulator: common.SimulatorCUpdated_response}
var mySimulators = []common.SimulatorResponse{common.SimulatorA_response, common.SimulatorB_response}
var msgSimulators = common.ResponseMsgSimulators{Simulators: mySimulators}
func TestMain(m *testing.M) {
db := common.DummyInitDB()
db = common.DummyInitDB()
defer db.Close()
common.DummyPopulateDB(db)
router := gin.Default()
router = gin.Default()
api := router.Group("/api")
// All endpoints require authentication except when someone wants to
// login (POST /authenticate)
user.RegisterAuthenticate(api.Group("/authenticate"))
api.Use(user.Authentication(true))
RegisterSimulatorEndpoints(api.Group("/simulators"))
credjson, _ := json.Marshal(common.CredAdmin)
msgOKjson, _ := json.Marshal(common.MsgOK)
msgModelsjson, _ := json.Marshal(msgModels)
msgSimulatorsjson, _ := json.Marshal(msgSimulators)
msgSimulatorjson, _ := json.Marshal(simulatorC_msg)
simulatorCjson, _ := json.Marshal(simulatorC_msg)
simulatorCupdatedjson, _ := json.Marshal(simulatorCupdated_msg)
token = common.AuthenticateForTest(t, router, "/api/authenticate", "POST", credjson, 200)
// test GET simulators/
common.TestEndpoint(t, router, token, "/api/simulators", "GET", nil, 200, msgSimulatorsjson)
// test POST simulators/
common.TestEndpoint(t, router, token, "/api/simulators", "POST", simulatorCjson, 200, msgOKjson)
// test GET simulators/:SimulatorID
common.TestEndpoint(t, router, token, "/api/simulators/3", "GET", nil, 200, msgSimulatorjson)
// test PUT simulators/:SimulatorID
common.TestEndpoint(t, router, token, "/api/simulators/3", "PUT", simulatorCupdatedjson, 200, msgOKjson)
common.TestEndpoint(t, router, token, "/api/simulators/3", "GET", nil, 200, simulatorCupdatedjson)
// test DELETE simulators/:SimulatorID
common.TestEndpoint(t, router, token, "/api/simulators/3", "DELETE", nil, 200, msgOKjson)
common.TestEndpoint(t, router, token, "/api/simulators", "GET", nil, 200, msgSimulatorsjson)
// test GET simulators/:SimulatorID/models
common.TestEndpoint(t, router, token, "/api/simulators/1/models", "GET", nil, 200, msgModelsjson)
// TODO add tests for other return codes
os.Exit(m.Run())
}
func TestAddSimulatorAsAdmin(t *testing.T) {
common.DropTables(db)
common.MigrateModels(db)
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
// authenticate as admin
token, err := common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.AdminCredentials)
assert.NoError(t, err)
// test POST simulators/ $newSimulator
newSimulator := SimulatorRequest{
UUID: common.SimulatorA.UUID,
Host: common.SimulatorA.Host,
Modeltype: common.SimulatorA.Modeltype,
State: common.SimulatorA.State,
Properties: common.SimulatorA.Properties,
}
code, resp, err := common.NewTestEndpoint(router, token,
"/api/simulators", "POST", common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Compare POST's response with the newSimulator
err = common.CompareResponse(resp, common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
// Read newSimulator's ID from the response
newSimulatorID, err := common.GetResponseID(resp)
assert.NoError(t, err)
// Get the newSimulator
code, resp, err = common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/simulators/%v", newSimulatorID), "GET", nil)
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Compare GET's response with the newSimulator
err = common.CompareResponse(resp, common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
}
func TestAddSimulatorAsUser(t *testing.T) {
common.DropTables(db)
common.MigrateModels(db)
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
// authenticate as user
token, err := common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.UserACredentials)
assert.NoError(t, err)
// test POST simulators/ $newSimulator
newSimulator := SimulatorRequest{
UUID: common.SimulatorA.UUID,
Host: common.SimulatorA.Host,
Modeltype: common.SimulatorA.Modeltype,
State: common.SimulatorA.State,
Properties: common.SimulatorA.Properties,
}
// This should fail with unprocessable entity 422 error code
// Normal users are not allowed to add simulators
code, resp, err := common.NewTestEndpoint(router, token,
"/api/simulators", "POST", common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
}
func TestUpdateSimulatorAsAdmin(t *testing.T) {
common.DropTables(db)
common.MigrateModels(db)
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
// authenticate as admin
token, err := common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.AdminCredentials)
assert.NoError(t, err)
// test POST simulators/ $newSimulator
newSimulator := SimulatorRequest{
UUID: common.SimulatorA.UUID,
Host: common.SimulatorA.Host,
Modeltype: common.SimulatorA.Modeltype,
State: common.SimulatorA.State,
Properties: common.SimulatorA.Properties,
}
code, resp, err := common.NewTestEndpoint(router, token,
"/api/simulators", "POST", common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Compare POST's response with the newSimulator
err = common.CompareResponse(resp, common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
// Read newSimulator's ID from the response
newSimulatorID, err := common.GetResponseID(resp)
assert.NoError(t, err)
// Test PUT simulators
newSimulator.Host = "ThisIsMyNewHost"
code, resp, err = common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/simulators/%v", newSimulatorID), "PUT", common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Compare PUT's response with the updated newSimulator
err = common.CompareResponse(resp, common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
// Get the updated newSimulator
code, resp, err = common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/simulators/%v", newSimulatorID), "GET", nil)
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Compare GET's response with the updated newSimulator
err = common.CompareResponse(resp, common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
}
func TestUpdateSimulatorAsUser(t *testing.T) {
common.DropTables(db)
common.MigrateModels(db)
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
// authenticate as admin
token, err := common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.AdminCredentials)
assert.NoError(t, err)
// test POST simulators/ $newSimulator
newSimulator := SimulatorRequest{
UUID: common.SimulatorA.UUID,
Host: common.SimulatorA.Host,
Modeltype: common.SimulatorA.Modeltype,
State: common.SimulatorA.State,
Properties: common.SimulatorA.Properties,
}
code, resp, err := common.NewTestEndpoint(router, token,
"/api/simulators", "POST", common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Read newSimulator's ID from the response
newSimulatorID, err := common.GetResponseID(resp)
assert.NoError(t, err)
// authenticate as user
token, err = common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.UserACredentials)
assert.NoError(t, err)
// Test PUT simulators
// This should fail with unprocessable entity status code 422
newSimulator.Host = "ThisIsMyNewHost"
code, resp, err = common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/simulators/%v", newSimulatorID), "PUT", common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
}
func TestDeleteSimulatorAsAdmin(t *testing.T) {
common.DropTables(db)
common.MigrateModels(db)
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
// authenticate as admin
token, err := common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.AdminCredentials)
assert.NoError(t, err)
// test POST simulators/ $newSimulator
newSimulator := SimulatorRequest{
UUID: common.SimulatorA.UUID,
Host: common.SimulatorA.Host,
Modeltype: common.SimulatorA.Modeltype,
State: common.SimulatorA.State,
Properties: common.SimulatorA.Properties,
}
code, resp, err := common.NewTestEndpoint(router, token,
"/api/simulators", "POST", common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Read newSimulator's ID from the response
newSimulatorID, err := common.GetResponseID(resp)
assert.NoError(t, err)
// Count the number of all the simulators returned for admin
initialNumber, err := common.LengthOfResponse(router, token,
"/api/simulators", "GET", nil)
assert.NoError(t, err)
// Delete the added newSimulator
code, resp, err = common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/simulators/%v", newSimulatorID), "DELETE", nil)
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Compare DELETE's response with the newSimulator
err = common.CompareResponse(resp, common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
// Again count the number of all the simulators returned
finalNumber, err := common.LengthOfResponse(router, token,
"/api/simulators", "GET", nil)
assert.NoError(t, err)
assert.Equal(t, finalNumber, initialNumber-1)
}
func TestDeleteSimulatorAsUser(t *testing.T) {
common.DropTables(db)
common.MigrateModels(db)
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
// authenticate as admin
token, err := common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.AdminCredentials)
assert.NoError(t, err)
// test POST simulators/ $newSimulator
newSimulator := SimulatorRequest{
UUID: common.SimulatorA.UUID,
Host: common.SimulatorA.Host,
Modeltype: common.SimulatorA.Modeltype,
State: common.SimulatorA.State,
Properties: common.SimulatorA.Properties,
}
code, resp, err := common.NewTestEndpoint(router, token,
"/api/simulators", "POST", common.KeyModels{"simulator": newSimulator})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Read newSimulator's ID from the response
newSimulatorID, err := common.GetResponseID(resp)
assert.NoError(t, err)
// authenticate as user
token, err = common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.UserACredentials)
assert.NoError(t, err)
// Test DELETE simulators
// This should fail with unprocessable entity status code 422
newSimulator.Host = "ThisIsMyNewHost"
code, resp, err = common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/simulators/%v", newSimulatorID), "DELETE", nil)
assert.NoError(t, err)
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
}
func TestGetAllSimulators(t *testing.T) {
common.DropTables(db)
common.MigrateModels(db)
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
// authenticate as admin
token, err := common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.AdminCredentials)
assert.NoError(t, err)
// get the length of the GET all simulators response for user
initialNumber, err := common.LengthOfResponse(router, token,
"/api/simulators", "GET", nil)
assert.NoError(t, err)
// test POST simulators/ $newSimulatorA
newSimulatorA := SimulatorRequest{
UUID: common.SimulatorA.UUID,
Host: common.SimulatorA.Host,
Modeltype: common.SimulatorA.Modeltype,
State: common.SimulatorA.State,
Properties: common.SimulatorA.Properties,
}
code, resp, err := common.NewTestEndpoint(router, token,
"/api/simulators", "POST", common.KeyModels{"simulator": newSimulatorA})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// test POST simulators/ $newSimulatorB
newSimulatorB := SimulatorRequest{
UUID: common.SimulatorB.UUID,
Host: common.SimulatorB.Host,
Modeltype: common.SimulatorB.Modeltype,
State: common.SimulatorB.State,
Properties: common.SimulatorB.Properties,
}
code, resp, err = common.NewTestEndpoint(router, token,
"/api/simulators", "POST", common.KeyModels{"simulator": newSimulatorB})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// get the length of the GET all simulators response again
finalNumber, err := common.LengthOfResponse(router, token,
"/api/simulators", "GET", nil)
assert.NoError(t, err)
assert.Equal(t, finalNumber, initialNumber+2)
// authenticate as normal user
token, err = common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.UserACredentials)
assert.NoError(t, err)
// get the length of the GET all simulators response again
finalNumber2, err := common.LengthOfResponse(router, token,
"/api/simulators", "GET", nil)
assert.NoError(t, err)
assert.Equal(t, finalNumber2, initialNumber+2)
}
func TestGetSimulationModelsOfSimulator(t *testing.T) {
common.DropTables(db)
common.MigrateModels(db)
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
// authenticate as admin
token, err := common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.AdminCredentials)
assert.NoError(t, err)
// test POST simulators/ $newSimulatorA
newSimulatorA := SimulatorRequest{
UUID: common.SimulatorA.UUID,
Host: common.SimulatorA.Host,
Modeltype: common.SimulatorA.Modeltype,
State: common.SimulatorA.State,
Properties: common.SimulatorA.Properties,
}
code, resp, err := common.NewTestEndpoint(router, token,
"/api/simulators", "POST", common.KeyModels{"simulator": newSimulatorA})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Read newSimulator's ID from the response
newSimulatorID, err := common.GetResponseID(resp)
assert.NoError(t, err)
// test GET simulators/ID/models
// TODO how to properly test this without using simulation model endpoints?
numberOfModels, err := common.LengthOfResponse(router, token,
fmt.Sprintf("/api/simulators/%v/models", newSimulatorID), "GET", nil)
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
assert.Equal(t, 0, numberOfModels)
// authenticate as normal user
token, err = common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.UserACredentials)
assert.NoError(t, err)
// test GET simulators/ID/models
// TODO how to properly test this without using simulation model endpoints?
numberOfModels, err = common.LengthOfResponse(router, token,
fmt.Sprintf("/api/simulators/%v/models", newSimulatorID), "GET", nil)
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
assert.Equal(t, 0, numberOfModels)
}

View file

@ -0,0 +1,82 @@
package simulator
import (
"github.com/jinzhu/gorm/dialects/postgres"
"gopkg.in/go-playground/validator.v9"
)
var validate *validator.Validate
type validNewSimulator struct {
UUID string `form:"UUID" validate:"required"`
Host string `form:"Host" validate:"required"`
Modeltype string `form:"Modeltype" validate:"required"`
Properties postgres.Jsonb `form:"Properties" validate:"required"`
State string `form:"State"`
}
type validUpdatedSimulator struct {
UUID string `form:"UUID" validate:"omitempty"`
Host string `form:"Host" validate:"omitempty"`
Modeltype string `form:"Modeltype" validate:"omitempty"`
Properties postgres.Jsonb `form:"Properties" validate:"omitempty"`
State string `form:"State" validate:"omitempty"`
}
type addSimulatorRequest struct {
validNewSimulator `json:"simulator"`
}
type updateSimulatorRequest struct {
validUpdatedSimulator `json:"simulator"`
}
func (r *addSimulatorRequest) validate() error {
validate = validator.New()
errs := validate.Struct(r)
return errs
}
func (r *validUpdatedSimulator) validate() error {
validate = validator.New()
errs := validate.Struct(r)
return errs
}
func (r *addSimulatorRequest) createSimulator() Simulator {
var s Simulator
s.UUID = r.UUID
s.Host = r.Host
s.Modeltype = r.Modeltype
s.Properties = r.Properties
if r.State != "" {
s.State = r.State
}
return s
}
func (r *updateSimulatorRequest) updatedSimulator(oldSimulator Simulator) (Simulator, error) {
// Use the old Simulator as a basis for the updated Simulator `s`
s := oldSimulator
if r.UUID != "" {
s.UUID = r.UUID
}
if r.Host != "" {
s.Host = r.Host
}
if r.Modeltype != "" {
s.Modeltype = r.Modeltype
}
if r.State != "" {
s.State = r.State
}
// TODO check for empty properties?
s.Properties = r.Properties
return s, nil
}