- revise testing of file endpoints

- revise documentation for swaggo
- clean up testdata
- delete serializers and responses files
- revise file endpoint implementations
This commit is contained in:
Sonja Happ 2019-09-06 17:04:40 +02:00
parent 7544c863de
commit f339c0d135
8 changed files with 478 additions and 300 deletions

View file

@ -1,27 +0,0 @@
package common
type FileResponse struct {
Name string `json:"name"`
ID uint `json:"id"`
Type string `json:"type"`
Size uint `json:"size"`
ImageWidth uint `json:"imageHeight"`
ImageHeight uint `json:"imageWidth"`
Date string `json:"date"`
WidgetID uint `json:"widgetID"`
SimulationModelID uint `json:"simulationModelID"`
}
// Response messages
type ResponseMsg struct {
Message string `json:"message"`
}
type ResponseMsgFiles struct {
Files []FileResponse `json:"files"`
}
type ResponseMsgFile struct {
File FileResponse `json:"file"`
}

View file

@ -1,42 +0,0 @@
package common
import (
"github.com/gin-gonic/gin"
)
// File/s Serializers
type FilesSerializerNoAssoc struct {
Ctx *gin.Context
Files []File
}
func (self *FilesSerializerNoAssoc) Response() []FileResponse {
response := []FileResponse{}
for _, files := range self.Files {
serializer := FileSerializerNoAssoc{self.Ctx, files}
response = append(response, serializer.Response())
}
return response
}
type FileSerializerNoAssoc struct {
Ctx *gin.Context
File
}
func (self *FileSerializerNoAssoc) Response() FileResponse {
response := FileResponse{
Name: self.Name,
ID: self.ID,
//Path: self.Path,
Type: self.Type,
Size: self.Size,
ImageHeight: self.ImageHeight,
ImageWidth: self.ImageWidth,
Date: self.Date,
WidgetID: self.WidgetID,
SimulationModelID: self.SimulationModelID,
}
return response
}

View file

@ -7,12 +7,6 @@ import (
"time"
)
// Generic
var MsgOK = ResponseMsg{
Message: "OK.",
}
// Users
var StrPassword0 = "xyz789"
var StrPasswordA = "abc123"
@ -160,16 +154,6 @@ var FileA = File{
Date: time.Now().String(),
}
var FileA_response = FileResponse{
ID: 1,
Name: FileA.Name,
Type: FileA.Type,
Size: FileA.Size,
ImageWidth: FileA.ImageWidth,
ImageHeight: FileA.ImageHeight,
Date: FileA.Date,
}
var FileB = File{
Name: "File_B",
Type: "text/plain",
@ -179,16 +163,6 @@ var FileB = File{
Date: time.Now().String(),
}
var FileB_response = FileResponse{
ID: 2,
Name: FileB.Name,
Type: FileB.Type,
Size: FileB.Size,
ImageWidth: FileB.ImageWidth,
ImageHeight: FileB.ImageHeight,
Date: FileB.Date,
}
var FileC = File{
Name: "File_C",
Type: "text/plain",

View file

@ -72,3 +72,11 @@ type ResponseSignals struct {
type ResponseSignal struct {
signal common.Signal
}
type ResponseFiles struct {
files []common.File
}
type ResponseFile struct {
file common.File
}

View file

@ -25,11 +25,10 @@ func RegisterFileEndpoints(r *gin.RouterGroup) {
// @ID getFiles
// @Tags files
// @Produce json
// @Success 200 {array} common.FileResponse "File parameters requested by user"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Success 200 {object} docs.ResponseFiles "Files which belong to simulation model or widget"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param objectType query string true "Set to model for files of model, set to widget for files of widget"
// @Param objectID query int true "ID of either model or widget of which files are requested"
// @Router /files [get]
@ -37,18 +36,18 @@ func getFiles(c *gin.Context) {
objectType := c.Request.URL.Query().Get("objectType")
if objectType != "model" && objectType != "widget" {
errormsg := fmt.Sprintf("Bad request. Object type not supported for files: %s", objectType)
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("Bad request. Object type not supported for files: %s", objectType),
})
return
}
objectID_s := c.Request.URL.Query().Get("objectID")
objectID, err := strconv.Atoi(objectID_s)
if err != nil {
errormsg := fmt.Sprintf("Bad request. Error on ID conversion: %s", err.Error())
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("Bad request. Error on ID conversion: %s", err.Error()),
})
return
}
@ -85,9 +84,8 @@ func getFiles(c *gin.Context) {
}
}
serializer := common.FilesSerializerNoAssoc{c, files}
c.JSON(http.StatusOK, gin.H{
"files": serializer.Response(),
"files": files,
})
}
@ -103,11 +101,11 @@ func getFiles(c *gin.Context) {
// @Accept gif
// @Accept model/x-cim
// @Accept model/x-cim.zip
// @Success 200 "OK"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Success 200 {object} docs.ResponseFile "File that was added"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param inputFile formData file true "File to be uploaded"
// @Param objectType query string true "Set to model for files of model, set to widget for files of widget"
// @Param objectID query int true "ID of either model or widget of which files are requested"
@ -116,18 +114,18 @@ func addFile(c *gin.Context) {
objectType := c.Request.URL.Query().Get("objectType")
if objectType != "model" && objectType != "widget" {
errormsg := fmt.Sprintf("Bad request. Object type not supported for files: %s", objectType)
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("Bad request. Object type not supported for files: %s", objectType),
})
return
}
objectID_s := c.Request.URL.Query().Get("objectID")
objectID, err := strconv.Atoi(objectID_s)
if err != nil {
errormsg := fmt.Sprintf("Bad request. Error on ID conversion: %s", err.Error())
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("Bad request. Error on ID conversion: %s", err.Error()),
})
return
}
@ -149,20 +147,23 @@ func addFile(c *gin.Context) {
// Extract file from POST request form
file_header, err := c.FormFile("file")
if err != nil {
errormsg := fmt.Sprintf("Bad request. Get form error: %s", err.Error())
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("Bad request. Get form error: %s", err.Error()),
})
return
}
var newFile File
err = newFile.register(file_header, objectType, uint(objectID))
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
})
if err != nil {
common.ProvideErrorResponse(c, err)
return
}
c.JSON(http.StatusOK, gin.H{
"file": newFile.File,
})
}
// getFile godoc
@ -175,11 +176,11 @@ func addFile(c *gin.Context) {
// @Produce gif
// @Produce model/x-cim
// @Produce model/x-cim.zip
// @Success 200 "OK"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Success 200 {object} docs.ResponseFile "File that was requested"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param fileID path int true "ID of the file to download"
// @Router /files/{fileID} [get]
func getFile(c *gin.Context) {
@ -191,9 +192,15 @@ func getFile(c *gin.Context) {
}
err := f.download(c)
if common.ProvideErrorResponse(c, err) {
if err != nil {
common.ProvideErrorResponse(c, err)
return
}
c.JSON(http.StatusOK, gin.H{
"file": f.File,
})
}
// updateFile godoc
@ -207,11 +214,11 @@ func getFile(c *gin.Context) {
// @Accept gif
// @Accept model/x-cim
// @Accept model/x-cim.zip
// @Success 200 "OK"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Success 200 {object} docs.ResponseFile "File that was updated"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param inputFile formData file true "File to be uploaded"
// @Param fileID path int true "ID of the file to update"
// @Router /files/{fileID} [put]
@ -226,28 +233,31 @@ func updateFile(c *gin.Context) {
// Extract file from PUT request form
err := c.Request.ParseForm()
if err != nil {
errormsg := fmt.Sprintf("Bad request. Get form error: %s", err.Error())
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("Bad request. Get form error: %s", err.Error()),
})
return
}
file_header, err := c.FormFile("file")
if err != nil {
errormsg := fmt.Sprintf("Bad request. Get form error: %s", err.Error())
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"error": fmt.Sprintf("Bad request. Get form error: %s", err.Error()),
})
return
}
err = f.update(file_header)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
})
if err != nil {
common.ProvideErrorResponse(c, err)
return
}
c.JSON(http.StatusOK, gin.H{
"file": f.File,
})
}
// deleteFile godoc
@ -255,11 +265,11 @@ func updateFile(c *gin.Context) {
// @ID deleteFile
// @Tags files
// @Produce json
// @Success 200 "OK"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Success 200 {object} docs.ResponseFile "File that was deleted"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param fileID path int true "ID of the file to update"
// @Router /files/{fileID} [delete]
func deleteFile(c *gin.Context) {
@ -271,9 +281,12 @@ func deleteFile(c *gin.Context) {
}
err := f.delete()
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
})
if err != nil {
common.ProvideErrorResponse(c, err)
return
}
c.JSON(http.StatusOK, gin.H{
"file": f.File,
})
}

View file

@ -22,7 +22,7 @@ func (f *File) byPath(path string) error {
db := common.GetDB()
err := db.Where("Path = ?", path).Find(f).Error
if err != nil {
return fmt.Errorf("File with path=%s does not exist", path)
return err
}
return err
}
@ -31,7 +31,7 @@ func (f *File) byID(id uint) error {
db := common.GetDB()
err := db.Find(f, id).Error
if err != nil {
return fmt.Errorf("File with id=%v does not exist", id)
return err
}
return nil
}
@ -137,7 +137,6 @@ func (f *File) update(fileHeader *multipart.FileHeader) error {
}
fileData, err := ioutil.ReadAll(fileContent)
fmt.Println("File content: ", string(fileData))
defer fileContent.Close()
db := common.GetDB()

View file

@ -16,15 +16,18 @@ func checkPermissions(c *gin.Context, operation common.CRUD) (bool, File) {
err := common.ValidateRole(c, common.ModelFile, operation)
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, f
}
fileID, err := strconv.Atoi(c.Param("fileID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of fileID path parameter")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"error": fmt.Sprintf("Bad request. No or incorrect format of fileID path parameter"),
})
return false, f
}

View file

@ -2,11 +2,15 @@ package file
import (
"bytes"
"encoding/json"
"fmt"
"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"
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
"github.com/jinzhu/gorm/dialects/postgres"
"github.com/stretchr/testify/assert"
"io"
"io/ioutil"
@ -17,185 +21,431 @@ import (
"testing"
)
// Test /files endpoints
func TestSignalEndpoints(t *testing.T) {
var router *gin.Engine
var db *gorm.DB
var token string
var filecontent = "This is my testfile"
var filecontent_update = "This is my updated testfile with a dot at the end."
var filename = "testfile.txt"
var filename_update = "testfileupdate.txt"
type SimulationModelRequest struct {
Name string `json:"name,omitempty"`
ScenarioID uint `json:"scenarioID,omitempty"`
SimulatorID uint `json:"simulatorID,omitempty"`
StartParameters postgres.Jsonb `json:"startParameters,omitempty"`
}
var myFiles = []common.FileResponse{common.FileA_response, common.FileB_response}
var msgFiles = common.ResponseMsgFiles{Files: myFiles}
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"`
}
db := common.DummyInitDB()
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()
common.DummyPopulateDB(db)
// create a testfile in local folder
c1 := []byte(filecontent)
c2 := []byte(filecontent_update)
err := ioutil.WriteFile(filename, c1, 0644)
if err != nil {
panic(err)
}
err = ioutil.WriteFile(filename_update, c2, 0644)
if err != nil {
panic(err)
}
router := gin.Default()
router = gin.Default()
api := router.Group("/api")
// All endpoints require authentication except when someone wants to
// login (POST /authenticate)
user.RegisterAuthenticate(api.Group("/authenticate"))
api.Use(user.Authentication(true))
// 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"))
RegisterFileEndpoints(api.Group("/files"))
credjson, err := json.Marshal(common.CredUser)
if err != nil {
panic(err)
}
os.Exit(m.Run())
}
msgOKjson, err := json.Marshal(common.MsgOK)
if err != nil {
panic(err)
}
func TestAddFile(t *testing.T) {
common.DropTables(db)
common.MigrateModels(db)
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
msgFilesjson, err := json.Marshal(msgFiles)
if err != nil {
panic(err)
}
// 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()
token = common.AuthenticateForTest(t, router, "/api/authenticate", "POST", credjson, 200)
// authenticate as normal user
token, err := common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.UserACredentials)
assert.NoError(t, err)
// test GET files
common.TestEndpoint(t, router, token, "/api/files?objectID=1&objectType=widget", "GET", nil, 200, msgFilesjson)
// create a testfile.txt in local folder
c1 := []byte("This is my testfile\n")
err = ioutil.WriteFile("testfile.txt", c1, 0644)
assert.NoError(t, err)
// test POST files
bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)
fileWriter, err := bodyWriter.CreateFormFile("file", "testuploadfile.txt")
if err != nil {
fmt.Println("error writing to buffer")
panic(err)
}
assert.NoError(t, err, "writing to buffer")
// open file handle
fh, err := os.Open(filename)
if err != nil {
fmt.Println("error opening file")
panic(err)
}
fh, err := os.Open("testfile.txt")
assert.NoError(t, err, "opening file")
defer fh.Close()
// io copy
_, err = io.Copy(fileWriter, fh)
if err != nil {
fmt.Println("error on IO copy")
panic(err)
}
assert.NoError(t, err, "IO copy")
contentType := bodyWriter.FormDataContentType()
bodyWriter.Close()
//req, err := http.NewRequest("POST", "/api/files?objectID=1&objectType=widget", bodyBuf)
// Create the request
w := httptest.NewRecorder()
req, err := http.NewRequest("POST", "/api/files?objectID=1&objectType=widget", bodyBuf)
req.Header.Add("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", contentType)
if err != nil {
fmt.Println("error creating post request")
panic(err)
}
req, err := http.NewRequest("POST", fmt.Sprintf("/api/files?objectID=%v&objectType=model", simulationModelID), bodyBuf)
assert.NoError(t, err, "create request")
req.Header.Set("Content-Type", contentType)
req.Header.Add("Authorization", "Bearer "+token)
router.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
fmt.Println(w.Body.String())
assert.Equal(t, string(msgOKjson), w.Body.String())
assert.Equalf(t, 200, w.Code, "Response body: \n%v\n", w.Body)
fmt.Println(w.Body)
// test GET files/:fileID
w2 := httptest.NewRecorder()
req2, _ := http.NewRequest("GET", "/api/files/5", nil)
req2.Header.Add("Authorization", "Bearer "+token)
router.ServeHTTP(w2, req2)
newFileID, err := common.GetResponseID(w.Body)
assert.NoError(t, err)
assert.Equal(t, 200, w2.Code)
fmt.Println(w2.Body.String())
assert.Equal(t, filecontent, w2.Body.String())
//common.TestEndpoint(t, router, token, "/api/files?objectID=1&objectType=widget", "GET", nil, 200, string(msgFilesjson))
// test PUT files/:fileID
bodyBuf_update := &bytes.Buffer{}
bodyWriter_update := multipart.NewWriter(bodyBuf_update)
fileWriter_update, err := bodyWriter_update.CreateFormFile("file", "testuploadfile.txt")
if err != nil {
fmt.Println("error writing to buffer")
panic(err)
}
// open file handle
fh_update, err := os.Open(filename_update)
if err != nil {
fmt.Println("error opening file")
panic(err)
}
defer fh_update.Close()
// io copy
_, err = io.Copy(fileWriter_update, fh_update)
if err != nil {
fmt.Println("error on IO copy")
panic(err)
}
contentType_update := bodyWriter_update.FormDataContentType()
bodyWriter_update.Close()
w_update := httptest.NewRecorder()
req_update, err := http.NewRequest("PUT", "/api/files/5", bodyBuf_update)
req_update.Header.Add("Authorization", "Bearer "+token)
req_update.Header.Set("Content-Type", contentType_update)
if err != nil {
fmt.Println("error creating post request")
panic(err)
}
router.ServeHTTP(w_update, req_update)
assert.Equal(t, 200, w_update.Code)
fmt.Println(w_update.Body.String())
assert.Equal(t, string(msgOKjson), w_update.Body.String())
// Test GET on updated file content
w3 := httptest.NewRecorder()
req3, _ := http.NewRequest("GET", "/api/files/5", nil)
req3.Header.Add("Authorization", "Bearer "+token)
router.ServeHTTP(w3, req3)
assert.Equal(t, 200, w3.Code)
fmt.Println(w3.Body.String())
assert.Equal(t, filecontent_update, w3.Body.String())
// test DELETE files/:fileID
common.TestEndpoint(t, router, token, "/api/files/5", "DELETE", nil, 200, msgOKjson)
common.TestEndpoint(t, router, token, "/api/files?objectID=1&objectType=widget", "GET", nil, 200, msgFilesjson)
// TODO add testing for other return codes
// clean up temporary file
err = os.Remove(filename)
if err != nil {
panic(err)
}
err = os.Remove(filename_update)
if err != nil {
panic(err)
}
// Get the new file
code, resp, err := common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/files/%v", newFileID), "GET", nil)
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
}
func TestUpdateFile(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)
// create a testfile.txt in local folder
c1 := []byte("This is my testfile\n")
err = ioutil.WriteFile("testfile.txt", c1, 0644)
assert.NoError(t, err)
bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)
fileWriter, err := bodyWriter.CreateFormFile("file", "testfile.txt")
assert.NoError(t, err, "writing to buffer")
// open file handle
fh, err := os.Open("testfile.txt")
assert.NoError(t, err, "opening file")
defer fh.Close()
// io copy
_, err = io.Copy(fileWriter, fh)
assert.NoError(t, err, "IO copy")
contentType := bodyWriter.FormDataContentType()
bodyWriter.Close()
//req, err := http.NewRequest("POST", "/api/files?objectID=1&objectType=widget", bodyBuf)
// Create the POST request
w := httptest.NewRecorder()
req, err := http.NewRequest("POST", fmt.Sprintf("/api/files?objectID=%v&objectType=model", simulationModelID), bodyBuf)
assert.NoError(t, err, "create request")
req.Header.Set("Content-Type", contentType)
req.Header.Add("Authorization", "Bearer "+token)
router.ServeHTTP(w, req)
assert.Equalf(t, 200, w.Code, "Response body: \n%v\n", w.Body)
fmt.Println(w.Body)
newFileID, err := common.GetResponseID(w.Body)
assert.NoError(t, err)
// Prepare update
// create a testfile_updated.txt in local folder
c2 := []byte("This is my updated testfile\n")
err = ioutil.WriteFile("testfileupdated.txt", c2, 0644)
assert.NoError(t, err)
bodyBufUpdated := &bytes.Buffer{}
bodyWriterUpdated := multipart.NewWriter(bodyBufUpdated)
fileWriterUpdated, err := bodyWriterUpdated.CreateFormFile("file", "testfileupdated.txt")
assert.NoError(t, err, "writing to buffer")
// open file handle for updated file
fh_updated, err := os.Open("testfileupdated.txt")
assert.NoError(t, err, "opening file")
defer fh_updated.Close()
// io copy
_, err = io.Copy(fileWriterUpdated, fh_updated)
assert.NoError(t, err, "IO copy")
contentType = bodyWriterUpdated.FormDataContentType()
bodyWriterUpdated.Close()
// Create the PUT request
w_updated := httptest.NewRecorder()
req, err = http.NewRequest("PUT", fmt.Sprintf("/api/files/%v", newFileID), bodyBufUpdated)
assert.NoError(t, err, "create request")
req.Header.Set("Content-Type", contentType)
req.Header.Add("Authorization", "Bearer "+token)
router.ServeHTTP(w_updated, req)
assert.Equalf(t, 200, w_updated.Code, "Response body: \n%v\n", w_updated.Body)
fmt.Println(w_updated.Body)
newFileIDUpdated, err := common.GetResponseID(w_updated.Body)
assert.Equal(t, newFileID, newFileIDUpdated)
// Get the updated file
code, resp, err := common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/files/%v", newFileIDUpdated), "GET", nil)
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
}
func TestDeleteFile(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)
// create a testfile.txt in local folder
c1 := []byte("This is my testfile\n")
err = ioutil.WriteFile("testfile.txt", c1, 0644)
assert.NoError(t, err)
// test POST files
bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)
fileWriter, err := bodyWriter.CreateFormFile("file", "testuploadfile.txt")
assert.NoError(t, err, "writing to buffer")
// open file handle
fh, err := os.Open("testfile.txt")
assert.NoError(t, err, "opening file")
defer fh.Close()
// io copy
_, err = io.Copy(fileWriter, fh)
assert.NoError(t, err, "IO copy")
contentType := bodyWriter.FormDataContentType()
bodyWriter.Close()
//req, err := http.NewRequest("POST", "/api/files?objectID=1&objectType=widget", bodyBuf)
// Create the request
w := httptest.NewRecorder()
req, err := http.NewRequest("POST", fmt.Sprintf("/api/files?objectID=%v&objectType=model", simulationModelID), bodyBuf)
assert.NoError(t, err, "create request")
req.Header.Set("Content-Type", contentType)
req.Header.Add("Authorization", "Bearer "+token)
router.ServeHTTP(w, req)
assert.Equalf(t, 200, w.Code, "Response body: \n%v\n", w.Body)
//fmt.Println(w.Body)
newFileID, err := common.GetResponseID(w.Body)
assert.NoError(t, err)
// Count the number of all files returned for simulation model
initialNumber, err := common.LengthOfResponse(router, token,
fmt.Sprintf("/api/files?objectID=%v&objectType=model", simulationModelID), "GET", nil)
assert.NoError(t, err)
// Delete the added file
code, resp, err := common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/files/%v", newFileID), "DELETE", nil)
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Again count the number of all the files returned for simulation model
finalNumber, err := common.LengthOfResponse(router, token,
fmt.Sprintf("/api/files?objectID=%v&objectType=model", simulationModelID), "GET", nil)
assert.NoError(t, err)
assert.Equal(t, initialNumber-1, finalNumber)
}
func TestGetAllFilesOfSimulationModel(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 files returned for simulation model
initialNumber, err := common.LengthOfResponse(router, token,
fmt.Sprintf("/api/files?objectID=%v&objectType=model", simulationModelID), "GET", nil)
assert.NoError(t, err)
// create a testfile.txt in local folder
c1 := []byte("This is my testfile\n")
err = ioutil.WriteFile("testfile.txt", c1, 0644)
assert.NoError(t, err)
// test POST files
bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)
fileWriter, err := bodyWriter.CreateFormFile("file", "testuploadfile.txt")
assert.NoError(t, err, "writing to buffer")
// open file handle
fh, err := os.Open("testfile.txt")
assert.NoError(t, err, "opening file")
defer fh.Close()
// io copy
_, err = io.Copy(fileWriter, fh)
assert.NoError(t, err, "IO copy")
contentType := bodyWriter.FormDataContentType()
bodyWriter.Close()
//req, err := http.NewRequest("POST", "/api/files?objectID=1&objectType=widget", bodyBuf)
// Create the request
w := httptest.NewRecorder()
req, err := http.NewRequest("POST", fmt.Sprintf("/api/files?objectID=%v&objectType=model", simulationModelID), bodyBuf)
assert.NoError(t, err, "create request")
req.Header.Set("Content-Type", contentType)
req.Header.Add("Authorization", "Bearer "+token)
router.ServeHTTP(w, req)
assert.Equalf(t, 200, w.Code, "Response body: \n%v\n", w.Body)
//fmt.Println(w.Body)
// POST a second file
bodyBuf2 := &bytes.Buffer{}
bodyWriter2 := multipart.NewWriter(bodyBuf2)
fileWriter2, err := bodyWriter2.CreateFormFile("file", "testuploadfile2.txt")
assert.NoError(t, err, "writing to buffer")
// open file handle
fh2, err := os.Open("testfile.txt")
assert.NoError(t, err, "opening file")
defer fh2.Close()
// io copy
_, err = io.Copy(fileWriter2, fh2)
assert.NoError(t, err, "IO copy")
contentType = bodyWriter2.FormDataContentType()
bodyWriter2.Close()
w2 := httptest.NewRecorder()
req, err = http.NewRequest("POST", fmt.Sprintf("/api/files?objectID=%v&objectType=model", simulationModelID), bodyBuf2)
assert.NoError(t, err, "create request")
req.Header.Set("Content-Type", contentType)
req.Header.Add("Authorization", "Bearer "+token)
router.ServeHTTP(w2, req)
assert.Equalf(t, 200, w2.Code, "Response body: \n%v\n", w2.Body)
// Again count the number of all the files returned for simulation model
finalNumber, err := common.LengthOfResponse(router, token,
fmt.Sprintf("/api/files?objectID=%v&objectType=model", simulationModelID), "GET", nil)
assert.NoError(t, err)
assert.Equal(t, initialNumber+2, finalNumber)
}