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 signal endpoints
- revise documentation for swaggo - clean up testdata, serializers and responses - add validators for signal endpoints - revise signal endpoint implementations
This commit is contained in:
parent
8882f6069c
commit
7544c863de
9 changed files with 548 additions and 218 deletions
|
@ -12,28 +12,12 @@ type FileResponse struct {
|
||||||
SimulationModelID uint `json:"simulationModelID"`
|
SimulationModelID uint `json:"simulationModelID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SignalResponse struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Unit string `json:"unit"`
|
|
||||||
Index uint `json:"index"`
|
|
||||||
Direction string `json:"direction"`
|
|
||||||
SimulationModelID uint `json:"simulationModelID"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response messages
|
// Response messages
|
||||||
|
|
||||||
type ResponseMsg struct {
|
type ResponseMsg struct {
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseMsgSignals struct {
|
|
||||||
Signals []SignalResponse `json:"signals"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResponseMsgSignal struct {
|
|
||||||
Signal SignalResponse `json:"signal"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResponseMsgFiles struct {
|
type ResponseMsgFiles struct {
|
||||||
Files []FileResponse `json:"files"`
|
Files []FileResponse `json:"files"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,35 +40,3 @@ func (self *FileSerializerNoAssoc) Response() FileResponse {
|
||||||
}
|
}
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signal/s Serializers
|
|
||||||
type SignalsSerializer struct {
|
|
||||||
Ctx *gin.Context
|
|
||||||
Signals []Signal
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *SignalsSerializer) Response() []SignalResponse {
|
|
||||||
response := []SignalResponse{}
|
|
||||||
for _, s := range self.Signals {
|
|
||||||
serializer := SignalSerializer{self.Ctx, s}
|
|
||||||
response = append(response, serializer.Response())
|
|
||||||
}
|
|
||||||
return response
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type SignalSerializer struct {
|
|
||||||
Ctx *gin.Context
|
|
||||||
Signal
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *SignalSerializer) Response() SignalResponse {
|
|
||||||
response := SignalResponse{
|
|
||||||
Name: self.Name,
|
|
||||||
Unit: self.Unit,
|
|
||||||
Direction: self.Direction,
|
|
||||||
SimulationModelID: self.SimulationModelID,
|
|
||||||
Index: self.Index,
|
|
||||||
}
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
|
@ -117,13 +117,6 @@ var OutSignalA = Signal{
|
||||||
Unit: "V",
|
Unit: "V",
|
||||||
}
|
}
|
||||||
|
|
||||||
var OutSignalA_response = SignalResponse{
|
|
||||||
Name: OutSignalA.Name,
|
|
||||||
Direction: OutSignalA.Direction,
|
|
||||||
Index: OutSignalA.Index,
|
|
||||||
Unit: OutSignalA.Unit,
|
|
||||||
}
|
|
||||||
|
|
||||||
var OutSignalB = Signal{
|
var OutSignalB = Signal{
|
||||||
Name: "outSignal_B",
|
Name: "outSignal_B",
|
||||||
Direction: "out",
|
Direction: "out",
|
||||||
|
@ -131,13 +124,6 @@ var OutSignalB = Signal{
|
||||||
Unit: "V",
|
Unit: "V",
|
||||||
}
|
}
|
||||||
|
|
||||||
var OutSignalB_response = SignalResponse{
|
|
||||||
Name: OutSignalB.Name,
|
|
||||||
Direction: OutSignalB.Direction,
|
|
||||||
Index: OutSignalB.Index,
|
|
||||||
Unit: OutSignalB.Unit,
|
|
||||||
}
|
|
||||||
|
|
||||||
var InSignalA = Signal{
|
var InSignalA = Signal{
|
||||||
Name: "inSignal_A",
|
Name: "inSignal_A",
|
||||||
Direction: "in",
|
Direction: "in",
|
||||||
|
@ -145,13 +131,6 @@ var InSignalA = Signal{
|
||||||
Unit: "A",
|
Unit: "A",
|
||||||
}
|
}
|
||||||
|
|
||||||
var InSignalA_response = SignalResponse{
|
|
||||||
Name: InSignalA.Name,
|
|
||||||
Direction: InSignalA.Direction,
|
|
||||||
Index: InSignalA.Index,
|
|
||||||
Unit: InSignalA.Unit,
|
|
||||||
}
|
|
||||||
|
|
||||||
var InSignalB = Signal{
|
var InSignalB = Signal{
|
||||||
Name: "inSignal_B",
|
Name: "inSignal_B",
|
||||||
Direction: "in",
|
Direction: "in",
|
||||||
|
@ -159,41 +138,6 @@ var InSignalB = Signal{
|
||||||
Unit: "A",
|
Unit: "A",
|
||||||
}
|
}
|
||||||
|
|
||||||
var InSignalB_response = SignalResponse{
|
|
||||||
Name: InSignalB.Name,
|
|
||||||
Direction: InSignalB.Direction,
|
|
||||||
Index: InSignalB.Index,
|
|
||||||
Unit: InSignalB.Unit,
|
|
||||||
}
|
|
||||||
|
|
||||||
var InSignalC = Signal{
|
|
||||||
Name: "inSignal_C",
|
|
||||||
Direction: "in",
|
|
||||||
Index: 2,
|
|
||||||
Unit: "A",
|
|
||||||
}
|
|
||||||
|
|
||||||
var InSignalC_response = SignalResponse{
|
|
||||||
Name: InSignalC.Name,
|
|
||||||
Direction: InSignalC.Direction,
|
|
||||||
Index: InSignalC.Index,
|
|
||||||
Unit: InSignalC.Unit,
|
|
||||||
}
|
|
||||||
|
|
||||||
var InSignalCUpdated = Signal{
|
|
||||||
Name: "inSignalupdated_C",
|
|
||||||
Direction: InSignalC.Direction,
|
|
||||||
Index: InSignalC.Index,
|
|
||||||
Unit: "Ohm",
|
|
||||||
}
|
|
||||||
|
|
||||||
var InSignalCUpdated_response = SignalResponse{
|
|
||||||
Name: InSignalCUpdated.Name,
|
|
||||||
Direction: InSignalCUpdated.Direction,
|
|
||||||
Index: InSignalCUpdated.Index,
|
|
||||||
Unit: InSignalCUpdated.Unit,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dashboards
|
// Dashboards
|
||||||
|
|
||||||
var DashboardA = Dashboard{
|
var DashboardA = Dashboard{
|
||||||
|
|
|
@ -64,3 +64,11 @@ type ResponseWidgets struct {
|
||||||
type ResponseWidget struct {
|
type ResponseWidget struct {
|
||||||
widget common.Widget
|
widget common.Widget
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResponseSignals struct {
|
||||||
|
signals []common.Signal
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResponseSignal struct {
|
||||||
|
signal common.Signal
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package signal
|
package signal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -24,11 +25,10 @@ func RegisterSignalEndpoints(r *gin.RouterGroup) {
|
||||||
// @Tags signals
|
// @Tags signals
|
||||||
// @Param direction query string true "Direction of signal (in or out)"
|
// @Param direction query string true "Direction of signal (in or out)"
|
||||||
// @Param modelID query string true "Model ID of signals to be obtained"
|
// @Param modelID query string true "Model ID of signals to be obtained"
|
||||||
// @Success 200 {array} common.Signal "Requested signals."
|
// @Success 200 {object} docs.ResponseSignals "Signals which belong to simulation model"
|
||||||
// @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 /signals [get]
|
// @Router /signals [get]
|
||||||
func getSignals(c *gin.Context) {
|
func getSignals(c *gin.Context) {
|
||||||
|
|
||||||
|
@ -44,9 +44,9 @@ func getSignals(c *gin.Context) {
|
||||||
} else if direction == "out" {
|
} else if direction == "out" {
|
||||||
mapping = "OutputMapping"
|
mapping = "OutputMapping"
|
||||||
} else {
|
} else {
|
||||||
errormsg := "Bad request. Direction has to be in or out"
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": errormsg,
|
"success": false,
|
||||||
|
"error": "Bad request. Direction has to be in or out",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -58,9 +58,8 @@ func getSignals(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
serializer := common.SignalsSerializer{c, sigs}
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"signals": serializer.Response(),
|
"signals": sigs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,31 +69,35 @@ func getSignals(c *gin.Context) {
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Tags signals
|
// @Tags signals
|
||||||
// @Param inputSignal body common.ResponseMsgSignal true "A signal to be added to the model incl. direction and model ID to which signal shall be added"
|
// @Param inputSignal body signal.validNewSignal true "A signal to be added to the model incl. direction and model ID to which signal shall be added"
|
||||||
// @Success 200 "OK."
|
// @Success 200 {object} docs.ResponseSignal "Signal 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 /signals [post]
|
// @Router /signals [post]
|
||||||
func addSignal(c *gin.Context) {
|
func addSignal(c *gin.Context) {
|
||||||
|
|
||||||
var newSignalData common.ResponseMsgSignal
|
var req addSignalRequest
|
||||||
err := c.BindJSON(&newSignalData)
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
if err != nil {
|
|
||||||
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": fmt.Sprintf("%v", err),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var newSignal Signal
|
// Validate the request
|
||||||
newSignal.Index = newSignalData.Signal.Index
|
if err := req.validate(); err != nil {
|
||||||
newSignal.SimulationModelID = newSignalData.Signal.SimulationModelID
|
c.JSON(http.StatusUnprocessableEntity, gin.H{
|
||||||
newSignal.Direction = newSignalData.Signal.Direction
|
"success": false,
|
||||||
newSignal.Unit = newSignalData.Signal.Unit
|
"message": fmt.Sprintf("%v", err),
|
||||||
newSignal.Name = newSignalData.Signal.Name
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the new signal from the request
|
||||||
|
newSignal := req.createSignal()
|
||||||
|
|
||||||
ok, _ := simulationmodel.CheckPermissions(c, common.Update, "body", int(newSignal.SimulationModelID))
|
ok, _ := simulationmodel.CheckPermissions(c, common.Update, "body", int(newSignal.SimulationModelID))
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -102,12 +105,15 @@ func addSignal(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add signal to model
|
// Add signal to model
|
||||||
err = newSignal.addToSimulationModel()
|
err := newSignal.addToSimulationModel()
|
||||||
if common.ProvideErrorResponse(c, err) == false {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
common.ProvideErrorResponse(c, err)
|
||||||
"message": "OK.",
|
return
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"signal": newSignal.Signal,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateSignal godoc
|
// updateSignal godoc
|
||||||
|
@ -115,35 +121,58 @@ func addSignal(c *gin.Context) {
|
||||||
// @ID updateSignal
|
// @ID updateSignal
|
||||||
// @Tags signals
|
// @Tags signals
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 "OK."
|
// @Param inputSignal body signal.validUpdatedSignal true "A signal to be updated"
|
||||||
// @Failure 401 "Unauthorized Access"
|
// @Success 200 {object} docs.ResponseSignal "Signal that was updated"
|
||||||
// @Failure 403 "Access forbidden."
|
// @Failure 400 {object} docs.ResponseError "Bad request"
|
||||||
// @Failure 404 "Not found"
|
// @Failure 404 {object} docs.ResponseError "Not found"
|
||||||
// @Failure 500 "Internal server error"
|
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
|
||||||
|
// @Failure 500 {object} docs.ResponseError "Internal server error"
|
||||||
// @Param signalID path int true "ID of signal to be updated"
|
// @Param signalID path int true "ID of signal to be updated"
|
||||||
// @Router /signals/{signalID} [put]
|
// @Router /signals/{signalID} [put]
|
||||||
func updateSignal(c *gin.Context) {
|
func updateSignal(c *gin.Context) {
|
||||||
ok, sig := checkPermissions(c, common.Delete)
|
ok, oldSignal := checkPermissions(c, common.Delete)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var modifiedSignal common.ResponseMsgSignal
|
var req updateSignalRequest
|
||||||
err := c.BindJSON(&modifiedSignal)
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
if err != nil {
|
|
||||||
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": fmt.Sprintf("%v", err),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sig.update(modifiedSignal.Signal)
|
// Validate the request
|
||||||
if common.ProvideErrorResponse(c, err) == false {
|
if err := req.validate(); err != nil {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"message": "OK.",
|
"success": false,
|
||||||
|
"message": fmt.Sprintf("%v", err),
|
||||||
})
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the updatedSignal from oldDashboard
|
||||||
|
updatedSignal, err := req.updatedSignal(oldSignal)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"success": false,
|
||||||
|
"message": fmt.Sprintf("%v", err),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the signal in the DB
|
||||||
|
err = oldSignal.update(updatedSignal)
|
||||||
|
if err != nil {
|
||||||
|
common.ProvideErrorResponse(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"signal": updatedSignal.Signal,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// getSignal godoc
|
// getSignal godoc
|
||||||
|
@ -151,11 +180,11 @@ func updateSignal(c *gin.Context) {
|
||||||
// @ID getSignal
|
// @ID getSignal
|
||||||
// @Tags signals
|
// @Tags signals
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 "OK."
|
// @Success 200 {object} docs.ResponseSignal "Signal 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 signalID path int true "ID of signal to be obtained"
|
// @Param signalID path int true "ID of signal to be obtained"
|
||||||
// @Router /signals/{signalID} [get]
|
// @Router /signals/{signalID} [get]
|
||||||
func getSignal(c *gin.Context) {
|
func getSignal(c *gin.Context) {
|
||||||
|
@ -164,9 +193,8 @@ func getSignal(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
serializer := common.SignalSerializer{c, sig.Signal}
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"signal": serializer.Response(),
|
"signal": sig.Signal,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,11 +203,11 @@ func getSignal(c *gin.Context) {
|
||||||
// @ID deleteSignal
|
// @ID deleteSignal
|
||||||
// @Tags signals
|
// @Tags signals
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 "OK."
|
// @Success 200 {object} docs.ResponseSignal "Signal 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 signalID path int true "ID of signal to be deleted"
|
// @Param signalID path int true "ID of signal to be deleted"
|
||||||
// @Router /signals/{signalID} [delete]
|
// @Router /signals/{signalID} [delete]
|
||||||
func deleteSignal(c *gin.Context) {
|
func deleteSignal(c *gin.Context) {
|
||||||
|
@ -190,10 +218,12 @@ func deleteSignal(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
err := sig.delete()
|
err := sig.delete()
|
||||||
if common.ProvideErrorResponse(c, err) == false {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
common.ProvideErrorResponse(c, err)
|
||||||
"message": "OK.",
|
return
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"signal": sig.Signal,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package signal
|
package signal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulationmodel"
|
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulationmodel"
|
||||||
)
|
)
|
||||||
|
@ -21,7 +19,7 @@ func (s *Signal) byID(id uint) error {
|
||||||
db := common.GetDB()
|
db := common.GetDB()
|
||||||
err := db.Find(s, id).Error
|
err := db.Find(s, id).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Signal with id=%v does not exist", id)
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -64,7 +62,7 @@ func (s *Signal) addToSimulationModel() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Signal) update(modifiedSignal common.SignalResponse) error {
|
func (s *Signal) update(modifiedSignal Signal) error {
|
||||||
db := common.GetDB()
|
db := common.GetDB()
|
||||||
|
|
||||||
err := db.Model(s).Updates(map[string]interface{}{
|
err := db.Model(s).Updates(map[string]interface{}{
|
||||||
|
|
|
@ -17,15 +17,18 @@ func checkPermissions(c *gin.Context, operation common.CRUD) (bool, Signal) {
|
||||||
|
|
||||||
err := common.ValidateRole(c, common.ModelSignal, operation)
|
err := common.ValidateRole(c, common.ModelSignal, operation)
|
||||||
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("Access denied (role validation failed): %v", err),
|
||||||
|
})
|
||||||
return false, sig
|
return false, sig
|
||||||
}
|
}
|
||||||
|
|
||||||
signalID, err := strconv.Atoi(c.Param("signalID"))
|
signalID, err := strconv.Atoi(c.Param("signalID"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errormsg := fmt.Sprintf("Bad request. No or incorrect format of signalID path parameter")
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": errormsg,
|
"success": false,
|
||||||
|
"error": fmt.Sprintf("Bad request. No or incorrect format of signalID path parameter"),
|
||||||
})
|
})
|
||||||
return false, sig
|
return false, sig
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,73 +1,395 @@
|
||||||
package signal
|
package signal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"fmt"
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
|
|
||||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||||
|
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/scenario"
|
||||||
|
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulationmodel"
|
||||||
|
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulator"
|
||||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/user"
|
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/user"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
|
"github.com/jinzhu/gorm/dialects/postgres"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Test /models endpoints
|
var router *gin.Engine
|
||||||
func TestSignalEndpoints(t *testing.T) {
|
var db *gorm.DB
|
||||||
|
|
||||||
var token string
|
type SignalRequest struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Unit string `json:"unit,omitempty"`
|
||||||
|
Index uint `json:"index,omitempty"`
|
||||||
|
Direction string `json:"direction,omitempty"`
|
||||||
|
SimulationModelID uint `json:"simulationModelID,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
var myInSignals = []common.SignalResponse{common.InSignalA_response, common.InSignalB_response}
|
type SimulationModelRequest struct {
|
||||||
var myOutSignals = []common.SignalResponse{common.OutSignalA_response, common.OutSignalB_response}
|
Name string `json:"name,omitempty"`
|
||||||
var msgInSignals = common.ResponseMsgSignals{Signals: myInSignals}
|
ScenarioID uint `json:"scenarioID,omitempty"`
|
||||||
var msgInSignalC = common.ResponseMsgSignal{Signal: common.InSignalC_response}
|
SimulatorID uint `json:"simulatorID,omitempty"`
|
||||||
var msgInSignalCupdated = common.ResponseMsgSignal{Signal: common.InSignalCUpdated_response}
|
StartParameters postgres.Jsonb `json:"startParameters,omitempty"`
|
||||||
var msgOutSignals = common.ResponseMsgSignals{Signals: myOutSignals}
|
}
|
||||||
|
|
||||||
db := common.DummyInitDB()
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ScenarioRequest struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Running bool `json:"running,omitempty"`
|
||||||
|
StartParameters postgres.Jsonb `json:"startParameters,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func addScenarioAndSimulatorAndSimulationModel() (scenarioID uint, simulatorID uint, simulationModelID uint) {
|
||||||
|
|
||||||
|
// authenticate as admin
|
||||||
|
token, _ := common.NewAuthenticateForTest(router,
|
||||||
|
"/api/authenticate", "POST", common.AdminCredentials)
|
||||||
|
|
||||||
|
// POST $newSimulatorA
|
||||||
|
newSimulatorA := SimulatorRequest{
|
||||||
|
UUID: common.SimulatorA.UUID,
|
||||||
|
Host: common.SimulatorA.Host,
|
||||||
|
Modeltype: common.SimulatorA.Modeltype,
|
||||||
|
State: common.SimulatorA.State,
|
||||||
|
Properties: common.SimulatorA.Properties,
|
||||||
|
}
|
||||||
|
_, resp, _ := common.NewTestEndpoint(router, token,
|
||||||
|
"/api/simulators", "POST", common.KeyModels{"simulator": newSimulatorA})
|
||||||
|
|
||||||
|
// Read newSimulator's ID from the response
|
||||||
|
newSimulatorID, _ := common.GetResponseID(resp)
|
||||||
|
|
||||||
|
// authenticate as normal user
|
||||||
|
token, _ = common.NewAuthenticateForTest(router,
|
||||||
|
"/api/authenticate", "POST", common.UserACredentials)
|
||||||
|
|
||||||
|
// POST $newScenario
|
||||||
|
newScenario := ScenarioRequest{
|
||||||
|
Name: common.ScenarioA.Name,
|
||||||
|
Running: common.ScenarioA.Running,
|
||||||
|
StartParameters: common.ScenarioA.StartParameters,
|
||||||
|
}
|
||||||
|
_, resp, _ = common.NewTestEndpoint(router, token,
|
||||||
|
"/api/scenarios", "POST", common.KeyModels{"scenario": newScenario})
|
||||||
|
|
||||||
|
// Read newScenario's ID from the response
|
||||||
|
newScenarioID, _ := common.GetResponseID(resp)
|
||||||
|
|
||||||
|
// test POST models/ $newSimulationModel
|
||||||
|
newSimulationModel := SimulationModelRequest{
|
||||||
|
Name: common.SimulationModelA.Name,
|
||||||
|
ScenarioID: uint(newScenarioID),
|
||||||
|
SimulatorID: uint(newSimulatorID),
|
||||||
|
StartParameters: common.SimulationModelA.StartParameters,
|
||||||
|
}
|
||||||
|
_, resp, _ = common.NewTestEndpoint(router, token,
|
||||||
|
"/api/models", "POST", common.KeyModels{"model": newSimulationModel})
|
||||||
|
|
||||||
|
// Read newSimulationModel's ID from the response
|
||||||
|
newSimulationModelID, _ := common.GetResponseID(resp)
|
||||||
|
|
||||||
|
return uint(newScenarioID), uint(newSimulatorID), uint(newSimulationModelID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
|
||||||
|
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))
|
||||||
|
// simulationmodel endpoints required here to first add a simulation to the DB
|
||||||
|
// that can be associated with a new signal model
|
||||||
|
simulationmodel.RegisterSimulationModelEndpoints(api.Group("/models"))
|
||||||
|
// scenario endpoints required here to first add a scenario to the DB
|
||||||
|
// that can be associated with a new simulation model
|
||||||
|
scenario.RegisterScenarioEndpoints(api.Group("/scenarios"))
|
||||||
|
// simulator endpoints required here to first add a simulator to the DB
|
||||||
|
// that can be associated with a new simulation model
|
||||||
|
simulator.RegisterSimulatorEndpoints(api.Group("/simulators"))
|
||||||
RegisterSignalEndpoints(api.Group("/signals"))
|
RegisterSignalEndpoints(api.Group("/signals"))
|
||||||
|
|
||||||
credjson, _ := json.Marshal(common.CredUser)
|
os.Exit(m.Run())
|
||||||
msgOKjson, _ := json.Marshal(common.MsgOK)
|
}
|
||||||
msgInSignalsjson, _ := json.Marshal(msgInSignals)
|
|
||||||
msgOutSignalsjson, _ := json.Marshal(msgOutSignals)
|
|
||||||
inSignalCjson, _ := json.Marshal(msgInSignalC)
|
|
||||||
inSignalCupdatedjson, _ := json.Marshal(msgInSignalCupdated)
|
|
||||||
|
|
||||||
token = common.AuthenticateForTest(t, router, "/api/authenticate", "POST", credjson, 200)
|
func TestAddSignal(t *testing.T) {
|
||||||
|
common.DropTables(db)
|
||||||
|
common.MigrateModels(db)
|
||||||
|
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
|
||||||
|
|
||||||
// test GET signals
|
// prepare the content of the DB for testing
|
||||||
common.TestEndpoint(t, router, token, "/api/signals?modelID=1&direction=in", "GET", nil, 200, msgInSignalsjson)
|
// by adding a scenario and a simulator to the DB
|
||||||
common.TestEndpoint(t, router, token, "/api/signals?modelID=1&direction=out", "GET", nil, 200, msgOutSignalsjson)
|
// using the respective endpoints of the API
|
||||||
|
_, _, simulationModelID := addScenarioAndSimulatorAndSimulationModel()
|
||||||
|
|
||||||
// test POST signals
|
// authenticate as normal user
|
||||||
common.TestEndpoint(t, router, token, "/api/signals", "POST", inSignalCjson, 200, msgOKjson)
|
token, err := common.NewAuthenticateForTest(router,
|
||||||
|
"/api/authenticate", "POST", common.UserACredentials)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// test GET signals/:signalID
|
// test POST signals/ $newSignal
|
||||||
common.TestEndpoint(t, router, token, "/api/signals/5", "GET", nil, 200, inSignalCjson)
|
newSignal := SignalRequest{
|
||||||
|
Name: common.InSignalA.Name,
|
||||||
|
Unit: common.InSignalA.Unit,
|
||||||
|
Direction: common.InSignalA.Direction,
|
||||||
|
Index: 1,
|
||||||
|
SimulationModelID: simulationModelID,
|
||||||
|
}
|
||||||
|
code, resp, err := common.NewTestEndpoint(router, token,
|
||||||
|
"/api/signals", "POST", common.KeyModels{"signal": newSignal})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||||
|
|
||||||
// test PUT signals/:signalID
|
// Compare POST's response with the newSignal
|
||||||
common.TestEndpoint(t, router, token, "/api/signals/5", "PUT", inSignalCupdatedjson, 200, msgOKjson)
|
err = common.CompareResponse(resp, common.KeyModels{"signal": newSignal})
|
||||||
common.TestEndpoint(t, router, token, "/api/signals/5", "GET", nil, 200, inSignalCupdatedjson)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// test DELETE signals/:signalID
|
// Read newSignal's ID from the response
|
||||||
common.TestEndpoint(t, router, token, "/api/signals/5", "DELETE", nil, 200, msgOKjson)
|
newSignalID, err := common.GetResponseID(resp)
|
||||||
common.TestEndpoint(t, router, token, "/api/signals?modelID=1&direction=in", "GET", nil, 200, msgInSignalsjson)
|
assert.NoError(t, err)
|
||||||
common.TestEndpoint(t, router, token, "/api/signals?modelID=1&direction=out", "GET", nil, 200, msgOutSignalsjson)
|
|
||||||
|
|
||||||
// TODO test GET models/:ModelID to check if POST and DELETE adapt InputLength correctly??
|
// Get the newSignal
|
||||||
//common.TestEndpoint(t, router, token, "/api/models/1", "GET", nil, 200, string(msgModelAUpdated2json))
|
code, resp, err = common.NewTestEndpoint(router, token,
|
||||||
|
fmt.Sprintf("/api/signals/%v", newSignalID), "GET", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||||
|
|
||||||
// TODO add testing for other return codes
|
// Compare GET's response with the newSSignal
|
||||||
|
err = common.CompareResponse(resp, common.KeyModels{"signal": newSignal})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// try to POST a malformed signal
|
||||||
|
// Required fields are missing
|
||||||
|
malformedNewSignal := SignalRequest{
|
||||||
|
Name: "ThisIsAMalformedRequest",
|
||||||
|
}
|
||||||
|
// this should NOT work and return a unprocessable entity 442 status code
|
||||||
|
code, resp, err = common.NewTestEndpoint(router, token,
|
||||||
|
"/api/signals", "POST", common.KeyModels{"model": malformedNewSignal})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateSignal(t *testing.T) {
|
||||||
|
common.DropTables(db)
|
||||||
|
common.MigrateModels(db)
|
||||||
|
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
|
||||||
|
|
||||||
|
// prepare the content of the DB for testing
|
||||||
|
// by adding a scenario and a simulator to the DB
|
||||||
|
// using the respective endpoints of the API
|
||||||
|
_, _, simulationModelID := addScenarioAndSimulatorAndSimulationModel()
|
||||||
|
|
||||||
|
// authenticate as normal user
|
||||||
|
token, err := common.NewAuthenticateForTest(router,
|
||||||
|
"/api/authenticate", "POST", common.UserACredentials)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// test POST signals/ $newSignal
|
||||||
|
newSignal := SignalRequest{
|
||||||
|
Name: common.InSignalA.Name,
|
||||||
|
Unit: common.InSignalA.Unit,
|
||||||
|
Direction: common.InSignalA.Direction,
|
||||||
|
Index: 1,
|
||||||
|
SimulationModelID: simulationModelID,
|
||||||
|
}
|
||||||
|
code, resp, err := common.NewTestEndpoint(router, token,
|
||||||
|
"/api/signals", "POST", common.KeyModels{"signal": newSignal})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||||
|
|
||||||
|
// Read newSignal's ID from the response
|
||||||
|
newSignalID, err := common.GetResponseID(resp)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
updatedSignal := SignalRequest{
|
||||||
|
Name: common.InSignalB.Name,
|
||||||
|
Unit: common.InSignalB.Unit,
|
||||||
|
Index: 1,
|
||||||
|
}
|
||||||
|
code, resp, err = common.NewTestEndpoint(router, token,
|
||||||
|
fmt.Sprintf("/api/signals/%v", newSignalID), "PUT", common.KeyModels{"signal": updatedSignal})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||||
|
|
||||||
|
// Compare PUT's response with the updatedSignal
|
||||||
|
err = common.CompareResponse(resp, common.KeyModels{"signal": updatedSignal})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Get the updatedSignal
|
||||||
|
code, resp, err = common.NewTestEndpoint(router, token,
|
||||||
|
fmt.Sprintf("/api/signals/%v", newSignalID), "GET", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||||
|
|
||||||
|
// Compare GET's response with the updatedSignal
|
||||||
|
err = common.CompareResponse(resp, common.KeyModels{"signal": updatedSignal})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// try to update a signal that does not exist (should return not found 404 status code)
|
||||||
|
code, resp, err = common.NewTestEndpoint(router, token,
|
||||||
|
fmt.Sprintf("/api/signals/%v", newSignalID+1), "PUT", common.KeyModels{"signal": updatedSignal})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 404, code, "Response body: \n%v\n", resp)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteSignal(t *testing.T) {
|
||||||
|
common.DropTables(db)
|
||||||
|
common.MigrateModels(db)
|
||||||
|
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
|
||||||
|
|
||||||
|
// prepare the content of the DB for testing
|
||||||
|
// by adding a scenario and a simulator to the DB
|
||||||
|
// using the respective endpoints of the API
|
||||||
|
_, _, simulationModelID := addScenarioAndSimulatorAndSimulationModel()
|
||||||
|
|
||||||
|
// authenticate as normal user
|
||||||
|
token, err := common.NewAuthenticateForTest(router,
|
||||||
|
"/api/authenticate", "POST", common.UserACredentials)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// test POST signals/ $newSignal
|
||||||
|
newSignal := SignalRequest{
|
||||||
|
Name: common.InSignalA.Name,
|
||||||
|
Unit: common.InSignalA.Unit,
|
||||||
|
Direction: common.InSignalA.Direction,
|
||||||
|
Index: 1,
|
||||||
|
SimulationModelID: simulationModelID,
|
||||||
|
}
|
||||||
|
code, resp, err := common.NewTestEndpoint(router, token,
|
||||||
|
"/api/signals", "POST", common.KeyModels{"signal": newSignal})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||||
|
|
||||||
|
// Read newSignal's ID from the response
|
||||||
|
newSignalID, err := common.GetResponseID(resp)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Count the number of all the input signals returned for simulation model
|
||||||
|
initialNumber, err := common.LengthOfResponse(router, token,
|
||||||
|
fmt.Sprintf("/api/signals?modelID=%v&direction=in", simulationModelID), "GET", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// add an output signal to make sure that counting of input signals works
|
||||||
|
newSignalout := SignalRequest{
|
||||||
|
Name: common.OutSignalA.Name,
|
||||||
|
Unit: common.OutSignalA.Unit,
|
||||||
|
Direction: common.OutSignalA.Direction,
|
||||||
|
Index: 1,
|
||||||
|
SimulationModelID: simulationModelID,
|
||||||
|
}
|
||||||
|
code, resp, err = common.NewTestEndpoint(router, token,
|
||||||
|
"/api/signals", "POST", common.KeyModels{"signal": newSignalout})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||||
|
|
||||||
|
// Delete the added newSignal
|
||||||
|
code, resp, err = common.NewTestEndpoint(router, token,
|
||||||
|
fmt.Sprintf("/api/signals/%v", newSignalID), "DELETE", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||||
|
|
||||||
|
// Compare DELETE's response with the newSignal
|
||||||
|
err = common.CompareResponse(resp, common.KeyModels{"signal": newSignal})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Again count the number of all the input signals returned for simulation model
|
||||||
|
finalNumber, err := common.LengthOfResponse(router, token,
|
||||||
|
fmt.Sprintf("/api/signals?modelID=%v&direction=in", simulationModelID), "GET", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, initialNumber-1, finalNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetAllInputSignalsOfSimulationModel(t *testing.T) {
|
||||||
|
common.DropTables(db)
|
||||||
|
common.MigrateModels(db)
|
||||||
|
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
|
||||||
|
|
||||||
|
// prepare the content of the DB for testing
|
||||||
|
// by adding a scenario and a simulator to the DB
|
||||||
|
// using the respective endpoints of the API
|
||||||
|
_, _, simulationModelID := addScenarioAndSimulatorAndSimulationModel()
|
||||||
|
|
||||||
|
// authenticate as normal user
|
||||||
|
token, err := common.NewAuthenticateForTest(router,
|
||||||
|
"/api/authenticate", "POST", common.UserACredentials)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Count the number of all the input signals returned for simulation model
|
||||||
|
initialNumber, err := common.LengthOfResponse(router, token,
|
||||||
|
fmt.Sprintf("/api/signals?modelID=%v&direction=in", simulationModelID), "GET", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// test POST signals/ $newSignal
|
||||||
|
newSignalA := SignalRequest{
|
||||||
|
Name: common.InSignalA.Name,
|
||||||
|
Unit: common.InSignalA.Unit,
|
||||||
|
Direction: common.InSignalA.Direction,
|
||||||
|
Index: 1,
|
||||||
|
SimulationModelID: simulationModelID,
|
||||||
|
}
|
||||||
|
code, resp, err := common.NewTestEndpoint(router, token,
|
||||||
|
"/api/signals", "POST", common.KeyModels{"signal": newSignalA})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||||
|
|
||||||
|
// add a second input signal
|
||||||
|
newSignalB := SignalRequest{
|
||||||
|
Name: common.InSignalB.Name,
|
||||||
|
Unit: common.InSignalB.Unit,
|
||||||
|
Direction: common.InSignalB.Direction,
|
||||||
|
Index: 2,
|
||||||
|
SimulationModelID: simulationModelID,
|
||||||
|
}
|
||||||
|
code, resp, err = common.NewTestEndpoint(router, token,
|
||||||
|
"/api/signals", "POST", common.KeyModels{"signal": newSignalB})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||||
|
|
||||||
|
// add an output signal
|
||||||
|
newSignalAout := SignalRequest{
|
||||||
|
Name: common.OutSignalA.Name,
|
||||||
|
Unit: common.OutSignalA.Unit,
|
||||||
|
Direction: common.OutSignalA.Direction,
|
||||||
|
Index: 1,
|
||||||
|
SimulationModelID: simulationModelID,
|
||||||
|
}
|
||||||
|
code, resp, err = common.NewTestEndpoint(router, token,
|
||||||
|
"/api/signals", "POST", common.KeyModels{"signal": newSignalAout})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||||
|
|
||||||
|
// add a second output signal
|
||||||
|
newSignalBout := SignalRequest{
|
||||||
|
Name: common.OutSignalB.Name,
|
||||||
|
Unit: common.OutSignalB.Unit,
|
||||||
|
Direction: common.OutSignalB.Direction,
|
||||||
|
Index: 1,
|
||||||
|
SimulationModelID: simulationModelID,
|
||||||
|
}
|
||||||
|
code, resp, err = common.NewTestEndpoint(router, token,
|
||||||
|
"/api/signals", "POST", common.KeyModels{"signal": newSignalBout})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||||
|
|
||||||
|
// Again count the number of all the input signals returned for simulation model
|
||||||
|
finalNumber, err := common.LengthOfResponse(router, token,
|
||||||
|
fmt.Sprintf("/api/signals?modelID=%v&direction=in", simulationModelID), "GET", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, initialNumber+2, finalNumber)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
73
routes/signal/signal_validators.go
Normal file
73
routes/signal/signal_validators.go
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
package signal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gopkg.in/go-playground/validator.v9"
|
||||||
|
)
|
||||||
|
|
||||||
|
var validate *validator.Validate
|
||||||
|
|
||||||
|
type validNewSignal struct {
|
||||||
|
Name string `form:"Name" validate:"required"`
|
||||||
|
Unit string `form:"unit" validate:"omitempty"`
|
||||||
|
Index uint `form:"index" validate:"required"`
|
||||||
|
Direction string `form:"direction" validate:"required,oneof=in out"`
|
||||||
|
SimulationModelID uint `form:"simulationModelID" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type validUpdatedSignal struct {
|
||||||
|
Name string `form:"Name" validate:"omitempty"`
|
||||||
|
Unit string `form:"unit" validate:"omitempty"`
|
||||||
|
Index uint `form:"index" validate:"omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type addSignalRequest struct {
|
||||||
|
validNewSignal `json:"signal"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type updateSignalRequest struct {
|
||||||
|
validUpdatedSignal `json:"signal"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *addSignalRequest) validate() error {
|
||||||
|
validate = validator.New()
|
||||||
|
errs := validate.Struct(r)
|
||||||
|
return errs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *validUpdatedSignal) validate() error {
|
||||||
|
validate = validator.New()
|
||||||
|
errs := validate.Struct(r)
|
||||||
|
return errs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *addSignalRequest) createSignal() Signal {
|
||||||
|
var s Signal
|
||||||
|
|
||||||
|
s.Name = r.Name
|
||||||
|
s.Unit = r.Unit
|
||||||
|
s.Index = r.Index
|
||||||
|
s.Direction = r.Direction
|
||||||
|
s.SimulationModelID = r.SimulationModelID
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *updateSignalRequest) updatedSignal(oldSignal Signal) (Signal, error) {
|
||||||
|
// Use the old Signal as a basis for the updated Signal `s`
|
||||||
|
s := oldSignal
|
||||||
|
|
||||||
|
if r.Name != "" {
|
||||||
|
s.Name = r.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Index != 0 {
|
||||||
|
// TODO this implies that we start indexing at 1
|
||||||
|
s.Index = r.Index
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Unit != "" {
|
||||||
|
s.Unit = r.Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue