mirror of
https://git.rwth-aachen.de/acs/public/villas/web-backend-go/
synced 2025-03-30 00:00:12 +01:00
- revise testing of simulators
- add validators for simulators - clean up testdata, serializers and responses - update documentation for swaggo
This commit is contained in:
parent
7bc94c1131
commit
a55d039ee7
8 changed files with 647 additions and 287 deletions
|
@ -12,18 +12,6 @@ type SimulationModelResponse struct {
|
||||||
StartParameters postgres.Jsonb `json:"startParameters"`
|
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 {
|
type DashboardResponse struct {
|
||||||
ID uint `json:"id"`
|
ID uint `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
@ -105,14 +93,6 @@ type ResponseMsgWidget struct {
|
||||||
Widget WidgetResponse `json:"widget"`
|
Widget WidgetResponse `json:"widget"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseMsgSimulators struct {
|
|
||||||
Simulators []SimulatorResponse `json:"simulators"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResponseMsgSimulator struct {
|
|
||||||
Simulator SimulatorResponse `json:"simulator"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResponseMsgFiles struct {
|
type ResponseMsgFiles struct {
|
||||||
Files []FileResponse `json:"files"`
|
Files []FileResponse `json:"files"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,43 +38,6 @@ func (self *SimulationModelSerializer) Response() SimulationModelResponse {
|
||||||
return response
|
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
|
// Dashboard/s Serializers
|
||||||
|
|
||||||
type DashboardsSerializer struct {
|
type DashboardsSerializer struct {
|
||||||
|
|
|
@ -57,8 +57,6 @@ var UserBCredentials = Credentials{
|
||||||
|
|
||||||
var propertiesA = json.RawMessage(`{"name" : "TestNameA", "category" : "CategoryA", "location" : "anywhere on earth", "type": "dummy"}`)
|
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 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{
|
var SimulatorA = Simulator{
|
||||||
UUID: "4854af30-325f-44a5-ad59-b67b2597de68",
|
UUID: "4854af30-325f-44a5-ad59-b67b2597de68",
|
||||||
|
@ -71,18 +69,6 @@ var SimulatorA = Simulator{
|
||||||
RawProperties: postgres.Jsonb{propertiesA},
|
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{
|
var SimulatorB = Simulator{
|
||||||
UUID: "7be0322d-354e-431e-84bd-ae4c9633138b",
|
UUID: "7be0322d-354e-431e-84bd-ae4c9633138b",
|
||||||
Host: "Host_B",
|
Host: "Host_B",
|
||||||
|
@ -94,72 +80,22 @@ var SimulatorB = Simulator{
|
||||||
RawProperties: postgres.Jsonb{propertiesB},
|
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
|
// Scenarios
|
||||||
|
|
||||||
var startParametersA = json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`)
|
var startParametersA = json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`)
|
||||||
var startParametersB = json.RawMessage(`{"parameter1" : "testValue1B", "parameter2" : "testValue2B", "parameter3" : 43}`)
|
var startParametersB = json.RawMessage(`{"parameter1" : "testValue1B", "parameter2" : "testValue2B", "parameter3" : 43}`)
|
||||||
var startParametersC = json.RawMessage(`{"parameter1" : "testValue1C", "parameter2" : "testValue2C", "parameter3" : 44}`)
|
var startParametersC = json.RawMessage(`{"parameter1" : "testValue1C", "parameter2" : "testValue2C", "parameter3" : 44}`)
|
||||||
|
|
||||||
var ScenarioA = Scenario{Name: "Scenario_A", Running: true, StartParameters: postgres.Jsonb{startParametersA}}
|
var ScenarioA = Scenario{
|
||||||
var ScenarioB = Scenario{Name: "Scenario_B", Running: false, StartParameters: postgres.Jsonb{startParametersB}}
|
Name: "Scenario_A",
|
||||||
|
Running: true,
|
||||||
|
StartParameters: postgres.Jsonb{startParametersA},
|
||||||
|
}
|
||||||
|
var ScenarioB = Scenario{
|
||||||
|
Name: "Scenario_B",
|
||||||
|
Running: false,
|
||||||
|
StartParameters: postgres.Jsonb{startParametersB},
|
||||||
|
}
|
||||||
|
|
||||||
// Simulation Models
|
// Simulation Models
|
||||||
|
|
||||||
|
|
|
@ -40,3 +40,11 @@ type ResponseScenarios struct {
|
||||||
type ResponseScenario struct {
|
type ResponseScenario struct {
|
||||||
scenario common.Scenario
|
scenario common.Scenario
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResponseSimulationModels struct {
|
||||||
|
models []common.SimulationModel
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResponseSimulationModel struct {
|
||||||
|
model common.SimulationModel
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package simulator
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -29,17 +28,19 @@ func RegisterSimulatorEndpoints(r *gin.RouterGroup) {
|
||||||
// @ID getSimulators
|
// @ID getSimulators
|
||||||
// @Tags simulators
|
// @Tags simulators
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {array} common.ResponseMsgSimulators "Simulator parameters requested by user"
|
// @Success 200 {object} docs.ResponseSimulators "Simulators requested"
|
||||||
// @Failure 401 "Unauthorized Access"
|
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||||
// @Failure 403 "Access forbidden."
|
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||||
// @Failure 404 "Not found"
|
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||||
// @Failure 500 "Internal server error"
|
|
||||||
// @Router /simulators [get]
|
// @Router /simulators [get]
|
||||||
func getSimulators(c *gin.Context) {
|
func getSimulators(c *gin.Context) {
|
||||||
|
|
||||||
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
|
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +50,9 @@ func getSimulators(c *gin.Context) {
|
||||||
if common.ProvideErrorResponse(c, err) {
|
if common.ProvideErrorResponse(c, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
serializer := common.SimulatorsSerializer{c, simulators}
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"simulators": serializer.Response(),
|
"simulators": simulators,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,48 +62,57 @@ func getSimulators(c *gin.Context) {
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Tags simulators
|
// @Tags simulators
|
||||||
// @Param inputSimulator body common.ResponseMsgSimulator true "Simulator to be added"
|
// @Param inputSimulator body simulator.validNewSimulator true "Simulator to be added"
|
||||||
// @Success 200 "OK."
|
// @Success 200 {object} docs.ResponseSimulator "Simulator that was added"
|
||||||
// @Failure 401 "Unauthorized Access"
|
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||||
// @Failure 403 "Access forbidden."
|
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||||
// @Failure 404 "Not found"
|
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||||
// @Failure 500 "Internal server error"
|
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||||
// @Router /simulators [post]
|
// @Router /simulators [post]
|
||||||
func addSimulator(c *gin.Context) {
|
func addSimulator(c *gin.Context) {
|
||||||
|
|
||||||
err := common.ValidateRole(c, common.ModelSimulator, common.Create)
|
err := common.ValidateRole(c, common.ModelSimulator, common.Create)
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var newSimulatorData common.ResponseMsgSimulator
|
var req addSimulatorRequest
|
||||||
err = c.BindJSON(&newSimulatorData)
|
err = c.BindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
|
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": errormsg,
|
"success": false,
|
||||||
|
"message": errormsg,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var newSimulator Simulator
|
// Validate the request
|
||||||
newSimulator.ID = newSimulatorData.Simulator.ID
|
if err = req.validate(); err != nil {
|
||||||
newSimulator.State = newSimulatorData.Simulator.State
|
c.JSON(http.StatusUnprocessableEntity, gin.H{
|
||||||
newSimulator.StateUpdateAt = newSimulatorData.Simulator.StateUpdateAt
|
"success": false,
|
||||||
newSimulator.Modeltype = newSimulatorData.Simulator.Modeltype
|
"message": fmt.Sprintf("%v", err),
|
||||||
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.",
|
|
||||||
})
|
})
|
||||||
|
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
|
// updateSimulator godoc
|
||||||
|
@ -111,53 +121,80 @@ func addSimulator(c *gin.Context) {
|
||||||
// @Tags simulators
|
// @Tags simulators
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param inputSimulator body common.ResponseMsgSimulator true "Simulator to be updated"
|
// @Param inputSimulator body simulator.validUpdatedSimulator true "Simulator to be updated"
|
||||||
// @Success 200 "OK."
|
// @Success 200 {object} docs.ResponseSimulator "Simulator that was updated"
|
||||||
// @Failure 401 "Unauthorized Access"
|
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||||
// @Failure 403 "Access forbidden."
|
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||||
// @Failure 404 "Not found"
|
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||||
// @Failure 500 "Internal server error"
|
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||||
// @Param simulatorID path int true "Simulator ID"
|
// @Param simulatorID path int true "Simulator ID"
|
||||||
// @Router /simulators/{simulatorID} [put]
|
// @Router /simulators/{simulatorID} [put]
|
||||||
func updateSimulator(c *gin.Context) {
|
func updateSimulator(c *gin.Context) {
|
||||||
err := common.ValidateRole(c, common.ModelSimulator, common.Update)
|
err := common.ValidateRole(c, common.ModelSimulator, common.Update)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
|
c.JSON(http.StatusUnprocessableEntity, gin.H{
|
||||||
return
|
"success": false,
|
||||||
}
|
"message": fmt.Sprintf("%v", err),
|
||||||
|
|
||||||
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,
|
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
simulatorID, err := strconv.Atoi(c.Param("simulatorID"))
|
var req updateSimulatorRequest
|
||||||
|
err = c.BindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": errormsg,
|
"success": false,
|
||||||
|
"message": "Bad request. Error binding form data to JSON: " + err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var s Simulator
|
// Validate the request
|
||||||
err = s.ByID(uint(simulatorID))
|
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) {
|
if common.ProvideErrorResponse(c, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.update(modifiedSimulator.Simulator)
|
// Create the updatedSimulator from oldSimulator
|
||||||
if common.ProvideErrorResponse(c, err) == false {
|
updatedSimulator, err := req.updatedSimulator(oldSimulator)
|
||||||
c.JSON(http.StatusOK, gin.H{
|
if err != nil {
|
||||||
"message": "OK.",
|
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
|
// getSimulator godoc
|
||||||
|
@ -165,39 +202,42 @@ func updateSimulator(c *gin.Context) {
|
||||||
// @ID getSimulator
|
// @ID getSimulator
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Tags simulators
|
// @Tags simulators
|
||||||
// @Success 200 {object} common.ResponseMsgSimulator "Simulator requested by user"
|
// @Success 200 {object} docs.ResponseSimulator "Simulator that was requested"
|
||||||
// @Failure 401 "Unauthorized Access"
|
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||||
// @Failure 403 "Access forbidden."
|
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||||
// @Failure 404 "Not found"
|
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||||
// @Failure 500 "Internal server error"
|
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||||
// @Param simulatorID path int true "Simulator ID"
|
// @Param simulatorID path int true "Simulator ID"
|
||||||
// @Router /simulators/{simulatorID} [get]
|
// @Router /simulators/{simulatorID} [get]
|
||||||
func getSimulator(c *gin.Context) {
|
func getSimulator(c *gin.Context) {
|
||||||
|
|
||||||
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
|
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
|
||||||
if err != nil {
|
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
|
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 {
|
if err != nil {
|
||||||
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": errormsg,
|
"success": false,
|
||||||
|
"message": fmt.Sprintf("Could not get simulator's ID from context"),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var s Simulator
|
var s Simulator
|
||||||
err = s.ByID(uint(simulatorID))
|
err = s.ByID(simulatorID)
|
||||||
if common.ProvideErrorResponse(c, err) {
|
if common.ProvideErrorResponse(c, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
serializer := common.SimulatorSerializer{c, s.Simulator}
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"simulator": serializer.Response(),
|
"simulator": s.Simulator,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,43 +246,48 @@ func getSimulator(c *gin.Context) {
|
||||||
// @ID deleteSimulator
|
// @ID deleteSimulator
|
||||||
// @Tags simulators
|
// @Tags simulators
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 "OK."
|
// @Success 200 {object} docs.ResponseSimulator "Simulator that was deleted"
|
||||||
// @Failure 401 "Unauthorized Access"
|
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||||
// @Failure 403 "Access forbidden."
|
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||||
// @Failure 404 "Not found"
|
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||||
// @Failure 500 "Internal server error"
|
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||||
// @Param simulatorID path int true "Simulator ID"
|
// @Param simulatorID path int true "Simulator ID"
|
||||||
// @Router /simulators/{simulatorID} [delete]
|
// @Router /simulators/{simulatorID} [delete]
|
||||||
func deleteSimulator(c *gin.Context) {
|
func deleteSimulator(c *gin.Context) {
|
||||||
|
|
||||||
err := common.ValidateRole(c, common.ModelSimulator, common.Delete)
|
err := common.ValidateRole(c, common.ModelSimulator, common.Delete)
|
||||||
if err != nil {
|
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
|
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 {
|
if err != nil {
|
||||||
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": errormsg,
|
"success": false,
|
||||||
|
"message": fmt.Sprintf("Could not get simulator's ID from context"),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var s Simulator
|
var s Simulator
|
||||||
err = s.ByID(uint(simulatorID))
|
err = s.ByID(simulatorID)
|
||||||
if common.ProvideErrorResponse(c, err) {
|
if common.ProvideErrorResponse(c, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete the simulator
|
||||||
err = s.delete()
|
err = s.delete()
|
||||||
if common.ProvideErrorResponse(c, err) {
|
if common.ProvideErrorResponse(c, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"message": "OK.",
|
"simulator": s.Simulator,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,32 +296,36 @@ func deleteSimulator(c *gin.Context) {
|
||||||
// @ID getModelsOfSimulator
|
// @ID getModelsOfSimulator
|
||||||
// @Tags simulators
|
// @Tags simulators
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} common.ResponseMsgSimulationModels "Simulation models requested by user"
|
// @Success 200 {object} docs.ResponseSimulationModels "Simulation models requested by user"
|
||||||
// @Failure 401 "Unauthorized Access"
|
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||||
// @Failure 403 "Access forbidden."
|
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||||
// @Failure 404 "Not found"
|
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||||
// @Failure 500 "Internal server error"
|
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||||
// @Param simulatorID path int true "Simulator ID"
|
// @Param simulatorID path int true "Simulator ID"
|
||||||
// @Router /simulators/{simulatorID}/models [get]
|
// @Router /simulators/{simulatorID}/models [get]
|
||||||
func getModelsOfSimulator(c *gin.Context) {
|
func getModelsOfSimulator(c *gin.Context) {
|
||||||
|
|
||||||
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
|
err := common.ValidateRole(c, common.ModelSimulator, common.Read)
|
||||||
if err != nil {
|
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
|
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 {
|
if err != nil {
|
||||||
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": errormsg,
|
"success": false,
|
||||||
|
"message": fmt.Sprintf("Could not get simulator's ID from context"),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var s Simulator
|
var s Simulator
|
||||||
err = s.ByID(uint(simulatorID))
|
err = s.ByID(simulatorID)
|
||||||
if common.ProvideErrorResponse(c, err) {
|
if common.ProvideErrorResponse(c, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -287,11 +336,9 @@ func getModelsOfSimulator(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
serializer := common.SimulationModelsSerializer{c, allModels}
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"models": serializer.Response(),
|
"models": allModels,
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendActionToSimulator godoc
|
// sendActionToSimulator godoc
|
||||||
|
@ -300,26 +347,30 @@ func getModelsOfSimulator(c *gin.Context) {
|
||||||
// @Tags simulators
|
// @Tags simulators
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param inputAction query string true "Action for simulator"
|
// @Param inputAction query string true "Action for simulator"
|
||||||
// @Success 200 "OK."
|
// @Success 200 {object} docs.ResponseError "Action sent successfully"
|
||||||
// @Failure 401 "Unauthorized Access"
|
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||||
// @Failure 403 "Access forbidden."
|
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||||
// @Failure 404 "Not found"
|
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||||
// @Failure 500 "Internal server error"
|
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||||
// @Param simulatorID path int true "Simulator ID"
|
// @Param simulatorID path int true "Simulator ID"
|
||||||
// @Router /simulators/{simulatorID}/action [post]
|
// @Router /simulators/{simulatorID}/action [post]
|
||||||
func sendActionToSimulator(c *gin.Context) {
|
func sendActionToSimulator(c *gin.Context) {
|
||||||
|
|
||||||
err := common.ValidateRole(c, common.ModelSimulatorAction, common.Update)
|
err := common.ValidateRole(c, common.ModelSimulatorAction, common.Update)
|
||||||
if err != nil {
|
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
|
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 {
|
if err != nil {
|
||||||
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulatorID path parameter")
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": errormsg,
|
"success": false,
|
||||||
|
"message": fmt.Sprintf("Could not get simulator's ID from context"),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -358,6 +409,7 @@ func sendActionToSimulator(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"success": true,
|
||||||
"message": "OK.",
|
"message": "OK.",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,13 +25,12 @@ func (s *Simulator) ByID(id uint) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Simulator) update(modifiedSimulator common.SimulatorResponse) error {
|
func (s *Simulator) update(updatedSimulator Simulator) error {
|
||||||
|
|
||||||
db := common.GetDB()
|
db := common.GetDB()
|
||||||
err := db.Model(s).Updates(modifiedSimulator).Error
|
err := db.Model(s).Updates(updatedSimulator).Error
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Simulator) delete() error {
|
func (s *Simulator) delete() error {
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package simulator
|
package simulator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"fmt"
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
|
"github.com/jinzhu/gorm/dialects/postgres"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -10,62 +14,398 @@ import (
|
||||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/user"
|
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Test /simulator endpoints
|
var router *gin.Engine
|
||||||
func TestSimulatorEndpoints(t *testing.T) {
|
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}
|
func TestMain(m *testing.M) {
|
||||||
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}
|
|
||||||
|
|
||||||
db := common.DummyInitDB()
|
db = common.DummyInitDB()
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
common.DummyPopulateDB(db)
|
|
||||||
|
|
||||||
router := gin.Default()
|
router = gin.Default()
|
||||||
api := router.Group("/api")
|
api := router.Group("/api")
|
||||||
|
|
||||||
// All endpoints require authentication except when someone wants to
|
|
||||||
// login (POST /authenticate)
|
|
||||||
user.RegisterAuthenticate(api.Group("/authenticate"))
|
user.RegisterAuthenticate(api.Group("/authenticate"))
|
||||||
|
|
||||||
api.Use(user.Authentication(true))
|
api.Use(user.Authentication(true))
|
||||||
|
|
||||||
RegisterSimulatorEndpoints(api.Group("/simulators"))
|
RegisterSimulatorEndpoints(api.Group("/simulators"))
|
||||||
|
|
||||||
credjson, _ := json.Marshal(common.CredAdmin)
|
os.Exit(m.Run())
|
||||||
msgOKjson, _ := json.Marshal(common.MsgOK)
|
}
|
||||||
msgModelsjson, _ := json.Marshal(msgModels)
|
|
||||||
msgSimulatorsjson, _ := json.Marshal(msgSimulators)
|
func TestAddSimulatorAsAdmin(t *testing.T) {
|
||||||
msgSimulatorjson, _ := json.Marshal(simulatorC_msg)
|
common.DropTables(db)
|
||||||
simulatorCjson, _ := json.Marshal(simulatorC_msg)
|
common.MigrateModels(db)
|
||||||
simulatorCupdatedjson, _ := json.Marshal(simulatorCupdated_msg)
|
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
|
||||||
|
|
||||||
token = common.AuthenticateForTest(t, router, "/api/authenticate", "POST", credjson, 200)
|
// authenticate as admin
|
||||||
|
token, err := common.NewAuthenticateForTest(router,
|
||||||
// test GET simulators/
|
"/api/authenticate", "POST", common.AdminCredentials)
|
||||||
common.TestEndpoint(t, router, token, "/api/simulators", "GET", nil, 200, msgSimulatorsjson)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// test POST simulators/
|
// test POST simulators/ $newSimulator
|
||||||
common.TestEndpoint(t, router, token, "/api/simulators", "POST", simulatorCjson, 200, msgOKjson)
|
newSimulator := SimulatorRequest{
|
||||||
|
UUID: common.SimulatorA.UUID,
|
||||||
// test GET simulators/:SimulatorID
|
Host: common.SimulatorA.Host,
|
||||||
common.TestEndpoint(t, router, token, "/api/simulators/3", "GET", nil, 200, msgSimulatorjson)
|
Modeltype: common.SimulatorA.Modeltype,
|
||||||
|
State: common.SimulatorA.State,
|
||||||
// test PUT simulators/:SimulatorID
|
Properties: common.SimulatorA.Properties,
|
||||||
common.TestEndpoint(t, router, token, "/api/simulators/3", "PUT", simulatorCupdatedjson, 200, msgOKjson)
|
}
|
||||||
common.TestEndpoint(t, router, token, "/api/simulators/3", "GET", nil, 200, simulatorCupdatedjson)
|
code, resp, err := common.NewTestEndpoint(router, token,
|
||||||
|
"/api/simulators", "POST", common.KeyModels{"simulator": newSimulator})
|
||||||
// test DELETE simulators/:SimulatorID
|
assert.NoError(t, err)
|
||||||
common.TestEndpoint(t, router, token, "/api/simulators/3", "DELETE", nil, 200, msgOKjson)
|
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||||
common.TestEndpoint(t, router, token, "/api/simulators", "GET", nil, 200, msgSimulatorsjson)
|
|
||||||
|
// Compare POST's response with the newSimulator
|
||||||
// test GET simulators/:SimulatorID/models
|
err = common.CompareResponse(resp, common.KeyModels{"simulator": newSimulator})
|
||||||
common.TestEndpoint(t, router, token, "/api/simulators/1/models", "GET", nil, 200, msgModelsjson)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// TODO add tests for other return codes
|
// 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)
|
||||||
}
|
}
|
||||||
|
|
82
routes/simulator/simulator_validators.go
Normal file
82
routes/simulator/simulator_validators.go
Normal 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
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue