Adds models, handlers, and tests for tagClass, tag, and TagValue classes
This commit is contained in:
18
app.go
18
app.go
@@ -85,6 +85,24 @@ func (a *App) initializeRoutes() {
|
||||
a.Router.HandleFunc("/api/v1/file/{id:[0-9]+}", a.updateFile).Methods("PUT")
|
||||
a.Router.HandleFunc("/api/v1/file/{id:[0-9]+}", a.deleteFile).Methods("DELETE")
|
||||
|
||||
a.Router.HandleFunc("/api/v1/tagClasses", a.getTagClasses).Methods("GET")
|
||||
a.Router.HandleFunc("/api/v1/tagClass", a.createTagClass).Methods("POST")
|
||||
a.Router.HandleFunc("/api/v1/tagClass/{id:[0-9]+}", a.getTagClass).Methods("GET")
|
||||
a.Router.HandleFunc("/api/v1/tagClass/{id:[0-9]+}", a.updateTagClass).Methods("PUT")
|
||||
a.Router.HandleFunc("/api/v1/tagClass/{id:[0-9]+}", a.deleteTagClass).Methods("DELETE")
|
||||
|
||||
a.Router.HandleFunc("/api/v1/tags", a.getTags).Methods("GET")
|
||||
a.Router.HandleFunc("/api/v1/tag", a.createTag).Methods("POST")
|
||||
a.Router.HandleFunc("/api/v1/tag/{id:[0-9]+}", a.getTag).Methods("GET")
|
||||
a.Router.HandleFunc("/api/v1/tag/{id:[0-9]+}", a.updateTag).Methods("PUT")
|
||||
a.Router.HandleFunc("/api/v1/tag/{id:[0-9]+}", a.deleteTag).Methods("DELETE")
|
||||
|
||||
a.Router.HandleFunc("/api/v1/tagValues", a.getTagValues).Methods("GET")
|
||||
a.Router.HandleFunc("/api/v1/tagValue", a.createTagValue).Methods("POST")
|
||||
a.Router.HandleFunc("/api/v1/tagValue/{id:[0-9]+}", a.getTagValue).Methods("GET")
|
||||
a.Router.HandleFunc("/api/v1/tagValue/{id:[0-9]+}", a.updateTagValue).Methods("PUT")
|
||||
a.Router.HandleFunc("/api/v1/tagValue/{id:[0-9]+}", a.deleteTagValue).Methods("DELETE")
|
||||
|
||||
//Serve public files
|
||||
var dir string
|
||||
flag.StringVar(&dir, "dir", "./public", "the directory to serve files from. Defaults to the current dir")
|
||||
|
||||
14
db.sql
Normal file
14
db.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS lumberjack ;
|
||||
|
||||
USE lumberjack;
|
||||
CREATE USER 'website'@'localhost' IDENTIFIED BY 'henrypump';
|
||||
GRANT ALL ON *.* TO 'website'@'localhost';
|
||||
CREATE USER 'website'@'127.0.0.1' IDENTIFIED BY 'henrypump';
|
||||
GRANT ALL ON *.* TO 'website'@'127.0.0.1';
|
||||
CREATE USER 'admin'@'localhost' IDENTIFIED BY 'henrypump';
|
||||
GRANT ALL ON *.* to 'admin'@'localhost';
|
||||
CREATE USER 'admin'@'%' IDENTIFIED BY 'henrypump';
|
||||
GRANT ALL ON *.* to 'admin'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
110
handler_tag.go
Normal file
110
handler_tag.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func (a *App) getTag(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid tag ID")
|
||||
return
|
||||
}
|
||||
|
||||
c := Tag{ID: id}
|
||||
if err := c.getTag(a.DB); err != nil {
|
||||
switch err {
|
||||
case sql.ErrNoRows:
|
||||
respondWithError(w, http.StatusNotFound, "Tag not found")
|
||||
default:
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusOK, c)
|
||||
}
|
||||
|
||||
func (a *App) getTags(w http.ResponseWriter, r *http.Request) {
|
||||
count, _ := strconv.Atoi(r.FormValue("count"))
|
||||
start, _ := strconv.Atoi(r.FormValue("start"))
|
||||
|
||||
if count > 10 || count < 1 {
|
||||
count = 10
|
||||
}
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
|
||||
tags, err := getTags(a.DB, start, count)
|
||||
if err != nil {
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusOK, tags)
|
||||
}
|
||||
|
||||
func (a *App) createTag(w http.ResponseWriter, r *http.Request) {
|
||||
var c Tag
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
if err := decoder.Decode(&c); err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid request payload")
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
if err := c.createTag(a.DB); err != nil {
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusCreated, c)
|
||||
}
|
||||
|
||||
func (a *App) updateTag(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid tag ID")
|
||||
return
|
||||
}
|
||||
|
||||
var c Tag
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
if err := decoder.Decode(&c); err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid request payload")
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
c.ID = id
|
||||
|
||||
if err := c.updateTag(a.DB); err != nil {
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusOK, c)
|
||||
}
|
||||
|
||||
func (a *App) deleteTag(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid Tag ID")
|
||||
return
|
||||
}
|
||||
|
||||
c := Tag{ID: id}
|
||||
if err := c.deleteTag(a.DB); err != nil {
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusOK, map[string]string{"result": "success"})
|
||||
}
|
||||
110
handler_tagclass.go
Normal file
110
handler_tagclass.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func (a *App) getTagClass(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid config ID")
|
||||
return
|
||||
}
|
||||
|
||||
c := TagClass{ID: id}
|
||||
if err := c.getTagClass(a.DB); err != nil {
|
||||
switch err {
|
||||
case sql.ErrNoRows:
|
||||
respondWithError(w, http.StatusNotFound, "TagClass not found")
|
||||
default:
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusOK, c)
|
||||
}
|
||||
|
||||
func (a *App) getTagClasses(w http.ResponseWriter, r *http.Request) {
|
||||
count, _ := strconv.Atoi(r.FormValue("count"))
|
||||
start, _ := strconv.Atoi(r.FormValue("start"))
|
||||
|
||||
if count > 10 || count < 1 {
|
||||
count = 10
|
||||
}
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
|
||||
configs, err := getTagClasses(a.DB, start, count)
|
||||
if err != nil {
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusOK, configs)
|
||||
}
|
||||
|
||||
func (a *App) createTagClass(w http.ResponseWriter, r *http.Request) {
|
||||
var c TagClass
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
if err := decoder.Decode(&c); err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid request payload")
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
if err := c.createTagClass(a.DB); err != nil {
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusCreated, c)
|
||||
}
|
||||
|
||||
func (a *App) updateTagClass(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid TagClass ID")
|
||||
return
|
||||
}
|
||||
|
||||
var c TagClass
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
if err := decoder.Decode(&c); err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid request payload")
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
c.ID = id
|
||||
|
||||
if err := c.updateTagClass(a.DB); err != nil {
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusOK, c)
|
||||
}
|
||||
|
||||
func (a *App) deleteTagClass(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid TagClass ID")
|
||||
return
|
||||
}
|
||||
|
||||
c := TagClass{ID: id}
|
||||
if err := c.deleteTagClass(a.DB); err != nil {
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusOK, map[string]string{"result": "success"})
|
||||
}
|
||||
110
handler_tagvalue.go
Normal file
110
handler_tagvalue.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func (a *App) getTagValue(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid tagValue ID")
|
||||
return
|
||||
}
|
||||
|
||||
c := TagValue{ID: id}
|
||||
if err := c.getTagValue(a.DB); err != nil {
|
||||
switch err {
|
||||
case sql.ErrNoRows:
|
||||
respondWithError(w, http.StatusNotFound, "TagValue not found")
|
||||
default:
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusOK, c)
|
||||
}
|
||||
|
||||
func (a *App) getTagValues(w http.ResponseWriter, r *http.Request) {
|
||||
count, _ := strconv.Atoi(r.FormValue("count"))
|
||||
start, _ := strconv.Atoi(r.FormValue("start"))
|
||||
|
||||
if count > 10 || count < 1 {
|
||||
count = 10
|
||||
}
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
|
||||
tagValues, err := getTagValues(a.DB, start, count)
|
||||
if err != nil {
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusOK, tagValues)
|
||||
}
|
||||
|
||||
func (a *App) createTagValue(w http.ResponseWriter, r *http.Request) {
|
||||
var c TagValue
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
if err := decoder.Decode(&c); err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid request payload")
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
if err := c.createTagValue(a.DB); err != nil {
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusCreated, c)
|
||||
}
|
||||
|
||||
func (a *App) updateTagValue(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid tagValue ID")
|
||||
return
|
||||
}
|
||||
|
||||
var c TagValue
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
if err := decoder.Decode(&c); err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid request payload")
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
c.ID = id
|
||||
|
||||
if err := c.updateTagValue(a.DB); err != nil {
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusOK, c)
|
||||
}
|
||||
|
||||
func (a *App) deleteTagValue(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
respondWithError(w, http.StatusBadRequest, "Invalid TagValue ID")
|
||||
return
|
||||
}
|
||||
|
||||
c := TagValue{ID: id}
|
||||
if err := c.deleteTagValue(a.DB); err != nil {
|
||||
respondWithError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
respondWithJSON(w, http.StatusOK, map[string]string{"result": "success"})
|
||||
}
|
||||
6
main.go
6
main.go
@@ -15,8 +15,14 @@ func main() {
|
||||
ensureDeviceTypeTableExists(a.DB)
|
||||
ensureDeviceTableExists(a.DB)
|
||||
ensureFileTableExists(a.DB)
|
||||
ensureTagClassTableExists(a.DB)
|
||||
ensureTagTableExists(a.DB)
|
||||
|
||||
seedDeviceTypeData(a.DB)
|
||||
seedDataTypeData(a.DB)
|
||||
seedTagClassData(a.DB)
|
||||
|
||||
seedDeviceData(a.DB)
|
||||
|
||||
a.Run(":8080")
|
||||
}
|
||||
|
||||
@@ -33,6 +33,20 @@ func ensureDataTypeTableExists(db *sql.DB) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
func seedDataTypeData(db *sql.DB) {
|
||||
sqlQuery := `INSERT INTO dataTypes VALUES
|
||||
(1,'Floating Point','REAL','2016-10-13 15:05:32','2016-10-13 15:05:32'),
|
||||
(2,'Integer','INT','2016-10-13 15:05:32','2016-10-13 15:05:32'),
|
||||
(3,'Boolean','BOOL','2016-10-13 15:05:32','2016-10-13 15:05:32');`
|
||||
insStmt, insErr := db.Prepare(sqlQuery)
|
||||
|
||||
if insErr != nil {
|
||||
panic(insErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer insStmt.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
insStmt.Exec()
|
||||
}
|
||||
|
||||
// getDataType : used during GET command
|
||||
func (c *DataType) getDataType(db *sql.DB) error {
|
||||
|
||||
@@ -37,6 +37,19 @@ func ensureDeviceTableExists(db *sql.DB) {
|
||||
}
|
||||
}
|
||||
|
||||
func seedDeviceData(db *sql.DB) {
|
||||
sqlQuery := `INSERT INTO devices VALUES
|
||||
(1,'Default PLC',1,'192.168.1.10','2016-10-13 15:05:32','2016-10-13 15:05:32');`
|
||||
insStmt, insErr := db.Prepare(sqlQuery)
|
||||
|
||||
if insErr != nil {
|
||||
panic(insErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer insStmt.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
insStmt.Exec()
|
||||
}
|
||||
|
||||
// getDevice : used during GET command
|
||||
func (d *Device) getDevice(db *sql.DB) error {
|
||||
sqlQuery := `SELECT
|
||||
|
||||
289
model_tag.go
289
model_tag.go
@@ -1,15 +1,22 @@
|
||||
package main
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Tag : holds information about a specific Tag
|
||||
type Tag struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
TagClassID int `json:"tagClassId"`
|
||||
TagClass TagClass `json:"tagClass"`
|
||||
Tag string `json:"tag"`
|
||||
TagName string `json:"tagName"`
|
||||
DeviceID int `json:"deviceId"`
|
||||
Device Device `json:"device"`
|
||||
Description string `json:"description"`
|
||||
DataTypeID int `json:"dataTypeId"`
|
||||
DataType DataType `json:"dataType"`
|
||||
ChangeThreshold float32 `json:"changeThreshold"`
|
||||
GuaranteeSec int `json:"guaranteeSec"`
|
||||
@@ -23,3 +30,281 @@ type Tag struct {
|
||||
|
||||
// Tags : a list of Tag items
|
||||
type Tags []Tag
|
||||
|
||||
const tagTableCreationQuery = `CREATE TABLE IF NOT EXISTS tags (
|
||||
id int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
name varchar(255),
|
||||
tagName varchar(255),
|
||||
tagClassId int(10) unsigned,
|
||||
deviceId int(10) unsigned,
|
||||
description varchar(255),
|
||||
dataTypeId int(10) unsigned,
|
||||
changeThreshold float,
|
||||
guaranteeSec int(10) unsigned,
|
||||
mapFunction varchar(255),
|
||||
units varchar(255),
|
||||
minExpected float,
|
||||
maxExpected float,
|
||||
createdAt datetime,
|
||||
updatedAt datetime,
|
||||
PRIMARY KEY (id),
|
||||
CONSTRAINT fk_tagclass FOREIGN KEY (tagClassId) REFERENCES tagClasses(id),
|
||||
CONSTRAINT fk_device FOREIGN KEY (deviceId) REFERENCES devices(id),
|
||||
CONSTRAINT fk_datatype FOREIGN KEY (dataTypeId) REFERENCES dataTypes(id)
|
||||
);`
|
||||
|
||||
func ensureTagTableExists(db *sql.DB) {
|
||||
if _, err := db.Exec(tagTableCreationQuery); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// getTag : used during GET command
|
||||
func (t *Tag) getTag(db *sql.DB) error {
|
||||
sqlQuery := `SELECT
|
||||
tags.name,
|
||||
tags.tagName,
|
||||
tags.tagClassId,
|
||||
tagClasses.id,
|
||||
tagClasses.classType,
|
||||
tagClasses.description,
|
||||
tagClasses.updatedAt,
|
||||
tagClasses.createdAt,
|
||||
tags.deviceId,
|
||||
devices.id,
|
||||
devices.name,
|
||||
devices.deviceTypeId,
|
||||
deviceTypes.id,
|
||||
deviceTypes.name,
|
||||
deviceTypes.createdAt,
|
||||
deviceTypes.updatedAt,
|
||||
devices.address,
|
||||
devices.createdAt,
|
||||
devices.updatedAt,
|
||||
tags.description,
|
||||
tags.dataTypeId,
|
||||
dataTypes.id,
|
||||
dataTypes.dataType,
|
||||
dataTypes.plcType,
|
||||
dataTypes.updatedAt,
|
||||
dataTypes.createdAt,
|
||||
tags.changeThreshold,
|
||||
tags.guaranteeSec,
|
||||
tags.mapFunction,
|
||||
tags.units,
|
||||
tags.maxExpected,
|
||||
tags.minExpected,
|
||||
tags.createdAt,
|
||||
tags.updatedAt
|
||||
FROM tags
|
||||
JOIN tagClasses ON tags.tagClassId = tagClasses.id
|
||||
JOIN devices ON tags.deviceId = devices.id
|
||||
JOIN deviceTypes ON devices.deviceTypeId = deviceTypes.id
|
||||
JOIN dataTypes ON tags.dataTypeId = dataTypes.id
|
||||
WHERE tags.id=?`
|
||||
return db.QueryRow(sqlQuery, t.ID).Scan(
|
||||
&t.Name,
|
||||
&t.TagName,
|
||||
&t.TagClassID,
|
||||
&t.TagClass.ID,
|
||||
&t.TagClass.ClassType,
|
||||
&t.TagClass.Description,
|
||||
&t.TagClass.UpdatedAt,
|
||||
&t.TagClass.UpdatedAt,
|
||||
&t.DeviceID,
|
||||
&t.Device.ID,
|
||||
&t.Device.Name,
|
||||
&t.Device.DeviceTypeID,
|
||||
&t.Device.DeviceType.ID,
|
||||
&t.Device.DeviceType.Name,
|
||||
&t.Device.DeviceType.CreatedAt,
|
||||
&t.Device.DeviceType.UpdatedAt,
|
||||
&t.Device.Address,
|
||||
&t.Device.CreatedAt,
|
||||
&t.Device.UpdatedAt,
|
||||
&t.Description,
|
||||
&t.DataTypeID,
|
||||
&t.DataType.ID,
|
||||
&t.DataType.DataType,
|
||||
&t.DataType.PlcType,
|
||||
&t.DataType.UpdatedAt,
|
||||
&t.DataType.CreatedAt,
|
||||
&t.ChangeThreshold,
|
||||
&t.GuaranteeSec,
|
||||
&t.MapFunction,
|
||||
&t.Units,
|
||||
&t.MaxExpected,
|
||||
&t.MinExpected,
|
||||
&t.CreatedAt,
|
||||
&t.UpdatedAt)
|
||||
}
|
||||
|
||||
// updateTag : used during PUT command
|
||||
func (t *Tag) updateTag(db *sql.DB) error {
|
||||
sqlQuery := `UPDATE tags SET
|
||||
name=?,
|
||||
tagName=?,
|
||||
tagClassId=?,
|
||||
deviceId=?,
|
||||
description=?,
|
||||
dataTypeId=?,
|
||||
changeThreshold=?,
|
||||
guaranteeSec=?,
|
||||
mapFunction=?,
|
||||
units=?,
|
||||
minExpected=?,
|
||||
maxExpected=?,
|
||||
updatedAt=?
|
||||
WHERE id=?`
|
||||
updStmt, updErr := db.Prepare(sqlQuery)
|
||||
if updErr != nil {
|
||||
panic(updErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer updStmt.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
_, err := updStmt.Exec(t.Name, t.TagName, t.TagClassID, t.DeviceID,
|
||||
t.Description, t.DataTypeID, t.ChangeThreshold, t.GuaranteeSec,
|
||||
t.MapFunction, t.Units, t.MinExpected, t.MaxExpected, time.Now(), t.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// deleteTag : used during DELETE command
|
||||
func (t *Tag) deleteTag(db *sql.DB) error {
|
||||
_, err := db.Exec("DELETE FROM tags WHERE id=?", t.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// createTag : used during PUSH command
|
||||
func (t *Tag) createTag(db *sql.DB) error {
|
||||
sqlQuery := `INSERT INTO tags (
|
||||
name,
|
||||
tagName,
|
||||
tagClassId,
|
||||
deviceId,
|
||||
description,
|
||||
dataTypeId,
|
||||
changeThreshold,
|
||||
guaranteeSec,
|
||||
mapFunction,
|
||||
units,
|
||||
minExpected,
|
||||
maxExpected,
|
||||
createdAt,
|
||||
updatedAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
stmtIns, insErr := db.Prepare(sqlQuery)
|
||||
if insErr != nil {
|
||||
panic(insErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer stmtIns.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
_, err := stmtIns.Exec(t.Name, t.TagName, t.TagClassID, t.DeviceID,
|
||||
t.Description, t.DataTypeID, t.ChangeThreshold, t.GuaranteeSec,
|
||||
t.MapFunction, t.Units, t.MinExpected, t.MaxExpected, time.Now(), time.Now())
|
||||
return err
|
||||
}
|
||||
|
||||
// getTags : used during GET command for all
|
||||
func getTags(db *sql.DB, start, count int) (Tags, error) {
|
||||
sqlQuery := `SELECT
|
||||
tags.ID,
|
||||
tags.name,
|
||||
tags.tagName,
|
||||
tags.tagClassId,
|
||||
tagClasses.id,
|
||||
tagClasses.classType,
|
||||
tagClasses.description,
|
||||
tagClasses.updatedAt,
|
||||
tagClasses.createdAt,
|
||||
tags.deviceId,
|
||||
devices.id,
|
||||
devices.name,
|
||||
devices.deviceTypeId,
|
||||
deviceTypes.id,
|
||||
deviceTypes.name,
|
||||
deviceTypes.createdAt,
|
||||
deviceTypes.updatedAt,
|
||||
devices.address,
|
||||
devices.createdAt,
|
||||
devices.updatedAt,
|
||||
tags.description,
|
||||
tags.dataTypeId,
|
||||
dataTypes.id,
|
||||
dataTypes.dataType,
|
||||
dataTypes.plcType,
|
||||
dataTypes.updatedAt,
|
||||
dataTypes.createdAt,
|
||||
tags.changeThreshold,
|
||||
tags.guaranteeSec,
|
||||
tags.mapFunction,
|
||||
tags.units,
|
||||
tags.maxExpected,
|
||||
tags.minExpected,
|
||||
tags.createdAt,
|
||||
tags.updatedAt
|
||||
FROM tags
|
||||
JOIN tagClasses ON tags.tagClassId = tagClasses.id
|
||||
JOIN devices ON tags.deviceId = devices.id
|
||||
JOIN deviceTypes ON devices.deviceTypeId = deviceTypes.id
|
||||
JOIN dataTypes ON tags.dataTypeId = dataTypes.id
|
||||
LIMIT ? OFFSET ?;`
|
||||
|
||||
getStmt, prepErr := db.Prepare(sqlQuery)
|
||||
if prepErr != nil {
|
||||
panic(prepErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer getStmt.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
rows, err := getStmt.Query(count, start)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
tags := Tags{}
|
||||
|
||||
for rows.Next() {
|
||||
var t Tag
|
||||
if err := rows.Scan(&t.ID,
|
||||
&t.Name,
|
||||
&t.TagName,
|
||||
&t.TagClassID,
|
||||
&t.TagClass.ID,
|
||||
&t.TagClass.ClassType,
|
||||
&t.TagClass.Description,
|
||||
&t.TagClass.UpdatedAt,
|
||||
&t.TagClass.UpdatedAt,
|
||||
&t.DeviceID,
|
||||
&t.Device.ID,
|
||||
&t.Device.Name,
|
||||
&t.Device.DeviceTypeID,
|
||||
&t.Device.DeviceType.ID,
|
||||
&t.Device.DeviceType.Name,
|
||||
&t.Device.DeviceType.CreatedAt,
|
||||
&t.Device.DeviceType.UpdatedAt,
|
||||
&t.Device.Address,
|
||||
&t.Device.CreatedAt,
|
||||
&t.Device.UpdatedAt,
|
||||
&t.Description,
|
||||
&t.DataTypeID,
|
||||
&t.DataType.ID,
|
||||
&t.DataType.DataType,
|
||||
&t.DataType.PlcType,
|
||||
&t.DataType.UpdatedAt,
|
||||
&t.DataType.CreatedAt,
|
||||
&t.ChangeThreshold,
|
||||
&t.GuaranteeSec,
|
||||
&t.MapFunction,
|
||||
&t.Units,
|
||||
&t.MaxExpected,
|
||||
&t.MinExpected,
|
||||
&t.CreatedAt,
|
||||
&t.UpdatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tags = append(tags, t)
|
||||
}
|
||||
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package main
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TagClass : holds information about a specific TagClass
|
||||
type TagClass struct {
|
||||
@@ -13,3 +17,93 @@ type TagClass struct {
|
||||
|
||||
// TagClasses : a list of TagClass items
|
||||
type TagClasses []TagClass
|
||||
|
||||
const tagClassTableCreationQuery = `CREATE TABLE IF NOT EXISTS tagClasses (
|
||||
id int(10) unsigned AUTO_INCREMENT,
|
||||
classType varchar(255),
|
||||
description varchar(255),
|
||||
createdAt datetime,
|
||||
updatedAt datetime,
|
||||
UNIQUE KEY classType (classType),
|
||||
PRIMARY KEY (id)
|
||||
)`
|
||||
|
||||
func ensureTagClassTableExists(db *sql.DB) {
|
||||
if _, err := db.Exec(tagClassTableCreationQuery); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func seedTagClassData(db *sql.DB) {
|
||||
sqlQuery := `INSERT INTO tagClasses VALUES
|
||||
(1,'normal','Historical Data','2016-10-13 15:05:32','2016-10-13 15:05:32'),
|
||||
(2,'handshake','PLC Handshake','2016-10-13 15:05:32','2016-10-13 15:05:32');`
|
||||
insStmt, insErr := db.Prepare(sqlQuery)
|
||||
|
||||
if insErr != nil {
|
||||
panic(insErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer insStmt.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
insStmt.Exec()
|
||||
}
|
||||
|
||||
// getTagClass : used during GET command
|
||||
func (c *TagClass) getTagClass(db *sql.DB) error {
|
||||
return db.QueryRow("SELECT classType, description, createdAt, updatedAt FROM tagClasses WHERE id=?", c.ID).Scan(&c.ClassType, &c.Description, &c.CreatedAt, &c.UpdatedAt)
|
||||
}
|
||||
|
||||
// updateTagClass : used during PUT command
|
||||
func (c *TagClass) updateTagClass(db *sql.DB) error {
|
||||
updStmt, updErr := db.Prepare("UPDATE tagClasses SET classType=?, description=?, updatedAt=? WHERE id=?")
|
||||
if updErr != nil {
|
||||
panic(updErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer updStmt.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
_, err := updStmt.Exec(c.ClassType, c.Description, time.Now(), c.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// deleteTagClass : used during DELETE command
|
||||
func (c *TagClass) deleteTagClass(db *sql.DB) error {
|
||||
_, err := db.Exec("DELETE FROM tagClasses WHERE id=?", c.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// createTagClass : used during PUSH command
|
||||
func (c *TagClass) createTagClass(db *sql.DB) error {
|
||||
stmtIns, insErr := db.Prepare("INSERT INTO tagClasses (classType, description, createdAt, updatedAt) VALUES (?, ?, ?, ?);")
|
||||
if insErr != nil {
|
||||
panic(insErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer stmtIns.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
_, err := stmtIns.Exec(c.ClassType, c.Description, time.Now(), time.Now())
|
||||
return err
|
||||
}
|
||||
|
||||
// getTagClasses : used during GET command for all
|
||||
func getTagClasses(db *sql.DB, start, count int) (TagClasses, error) {
|
||||
rows, err := db.Query(
|
||||
"SELECT id, classType, description, createdAt, updatedAt FROM tagClasses LIMIT ? OFFSET ?",
|
||||
count, start)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
tagClasses := TagClasses{}
|
||||
|
||||
for rows.Next() {
|
||||
var c TagClass
|
||||
if err := rows.Scan(&c.ID, &c.ClassType, &c.Description, &c.CreatedAt, &c.UpdatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tagClasses = append(tagClasses, c)
|
||||
}
|
||||
|
||||
return tagClasses, nil
|
||||
}
|
||||
|
||||
121
model_tagvalue.go
Normal file
121
model_tagvalue.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TagValue : holds information about a specific TagValue
|
||||
type TagValue struct {
|
||||
ID int `json:"id"`
|
||||
TagID int `json:"tagId"`
|
||||
Val string `json:"val"`
|
||||
TagName int `json:"tagName"`
|
||||
Units int `json:"units"`
|
||||
DataType string `json:"dataType"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
// TagValues : a list of TagValue items
|
||||
type TagValues []TagValue
|
||||
|
||||
const tagValueTableCreationQuery = `CREATE TABLE IF NOT EXISTS tagValues (
|
||||
id int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
tagId int(10) unsigned,
|
||||
val varchar(64),
|
||||
createdAt datetime,
|
||||
updatedAt datetime,
|
||||
PRIMARY KEY (id),
|
||||
CONSTRAINT fk_tag FOREIGN KEY (tagId) REFERENCES tags(id)
|
||||
)`
|
||||
|
||||
func ensureTagValueTableExists(db *sql.DB) {
|
||||
if _, err := db.Exec(tagValueTableCreationQuery); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// getTagValue : used during GET command
|
||||
func (t *TagValue) getTagValue(db *sql.DB) error {
|
||||
sqlQuery := `SELECT
|
||||
tagValues.tagId,
|
||||
tagValues.val,
|
||||
tags.name,
|
||||
tags.units,
|
||||
dataTypes.dataType,
|
||||
tagValues.createdAt,
|
||||
tagValues.updatedAt
|
||||
FROM tagValues
|
||||
JOIN tags ON tagValues.tagId = tags.id
|
||||
JOIN dataTypes ON tags.dataTypeId = dataTypes.id
|
||||
WHERE tagValues.id=?`
|
||||
return db.QueryRow(sqlQuery, t.ID).Scan(&t.TagID, &t.Val, &t.TagName, &t.Units, &t.DataType, &t.CreatedAt, &t.UpdatedAt)
|
||||
}
|
||||
|
||||
// updateTagValue : used during PUT command
|
||||
func (t *TagValue) updateTagValue(db *sql.DB) error {
|
||||
updStmt, updErr := db.Prepare("UPDATE tagValues SET tagId=?, val=?, updatedAt=? WHERE id=?")
|
||||
if updErr != nil {
|
||||
panic(updErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer updStmt.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
_, err := updStmt.Exec(t.TagID, t.Val, time.Now(), t.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// deleteTagValue : used during DELETE command
|
||||
func (t *TagValue) deleteTagValue(db *sql.DB) error {
|
||||
_, err := db.Exec("DELETE FROM tagValues WHERE id=?", t.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// createTagValue : used during PUSH command
|
||||
func (t *TagValue) createTagValue(db *sql.DB) error {
|
||||
stmtIns, insErr := db.Prepare("INSERT INTO tagValues (tagId, val, createdAt, updatedAt) VALUES (?, ?, ?, ?);")
|
||||
if insErr != nil {
|
||||
panic(insErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer stmtIns.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
_, err := stmtIns.Exec(t.TagID, t.Val, time.Now(), time.Now())
|
||||
return err
|
||||
}
|
||||
|
||||
// getTagValues : used during GET command for all
|
||||
func getTagValues(db *sql.DB, start, count int) (TagValues, error) {
|
||||
sqlQuery := `SELECT
|
||||
tagValues.id,
|
||||
tagValues.tagId,
|
||||
tagValues.val,
|
||||
tags.name,
|
||||
tags.units,
|
||||
dataTypes.dataType,
|
||||
tagValues.createdAt,
|
||||
tagValues.updatedAt
|
||||
FROM tagValues
|
||||
JOIN tags ON tagValues.tagId = tags.id
|
||||
JOIN dataTypes ON tags.dataTypeId = dataTypes.id
|
||||
LIMIT ? OFFSET ?`
|
||||
rows, err := db.Query(sqlQuery, count, start)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
tagValues := TagValues{}
|
||||
|
||||
for rows.Next() {
|
||||
var t TagValue
|
||||
if err := rows.Scan(&t.ID, &t.TagID, &t.Val, &t.TagName, &t.Units, &t.DataType, &t.CreatedAt, &t.UpdatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tagValues = append(tagValues, t)
|
||||
}
|
||||
|
||||
return tagValues, nil
|
||||
}
|
||||
@@ -21,6 +21,9 @@ func TestMain(m *testing.M) {
|
||||
ensureDeviceTypeTableExists(a.DB)
|
||||
ensureDeviceTableExists(a.DB)
|
||||
ensureFileTableExists(a.DB)
|
||||
ensureTagClassTableExists(a.DB)
|
||||
ensureTagTableExists(a.DB)
|
||||
ensureTagValueTableExists(a.DB)
|
||||
|
||||
code := m.Run()
|
||||
|
||||
@@ -29,6 +32,9 @@ func TestMain(m *testing.M) {
|
||||
clearDeviceTypeTable()
|
||||
clearDeviceTable()
|
||||
clearFileTable()
|
||||
clearTagClassTable()
|
||||
clearTagTable()
|
||||
clearTagValueTable()
|
||||
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
230
testtag_test.go
Normal file
230
testtag_test.go
Normal file
@@ -0,0 +1,230 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func clearTagTable() {
|
||||
a.DB.Exec("DELETE FROM tags")
|
||||
a.DB.Exec("ALTER TABLE tags AUTO_INCREMENT = 1")
|
||||
}
|
||||
|
||||
func TestEmptyTagTable(t *testing.T) {
|
||||
clearTagTable()
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tags", nil)
|
||||
response := executeRequest(req)
|
||||
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
|
||||
if body := response.Body.String(); body != "[]" {
|
||||
t.Errorf("Expected an empty array. Got %s", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetNonExistentTag(t *testing.T) {
|
||||
clearTagTable()
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tag/11", nil)
|
||||
response := executeRequest(req)
|
||||
|
||||
checkResponseCode(t, http.StatusNotFound, response.Code)
|
||||
|
||||
var m map[string]string
|
||||
json.Unmarshal(response.Body.Bytes(), &m)
|
||||
if m["error"] != "Tag not found" {
|
||||
t.Errorf("Expected the 'error' key of the response to be set to 'Tag not found'. Got '%s'", m["error"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateTag(t *testing.T) {
|
||||
clearTagTable()
|
||||
seedDataTypeData(a.DB)
|
||||
seedDeviceTypeData(a.DB)
|
||||
seedTagClassData(a.DB)
|
||||
seedDeviceData(a.DB)
|
||||
|
||||
payload := []byte(`{"name":"TestTag","tagName":"testTag","tagClassId":1,"deviceId":1,"description":"This is a test tag","dataTypeId":1,"changeThreshold":4.5,"guaranteeSec":600,"mapFunction":"double","units":"in.","minExpected":0.0,"maxExpected":1000.0}`)
|
||||
|
||||
req, _ := http.NewRequest("POST", "/api/v1/tag", bytes.NewBuffer(payload))
|
||||
response := executeRequest(req)
|
||||
checkResponseCode(t, http.StatusCreated, response.Code)
|
||||
|
||||
var m map[string]interface{}
|
||||
json.Unmarshal(response.Body.Bytes(), &m)
|
||||
|
||||
if m["name"] != "TestTag" {
|
||||
t.Errorf("Expected tag name to be 'TestTag'. Got '%v'", m["name"])
|
||||
}
|
||||
if m["tagName"] != "testTag" {
|
||||
t.Errorf("Expected tag tagName to be 'testTag'. Got '%v'", m["tagName"])
|
||||
}
|
||||
if m["tagClassId"] != 1.0 {
|
||||
t.Errorf("Expected tag tagClassId to be '1'. Got '%v'", m["tagClassId"])
|
||||
}
|
||||
if m["deviceId"] != 1.0 {
|
||||
t.Errorf("Expected tag deviceId to be '1'. Got '%v'", m["deviceId"])
|
||||
}
|
||||
if m["description"] != "This is a test tag" {
|
||||
t.Errorf("Expected tag description to be 'This is a test tag'. Got '%v'", m["description"])
|
||||
}
|
||||
if m["dataTypeId"] != 1.0 {
|
||||
t.Errorf("Expected tag dataTypeId to be 'testTag'. Got '%v'", m["dataTypeId"])
|
||||
}
|
||||
if m["changeThreshold"] != 4.5 {
|
||||
t.Errorf("Expected tag changeThreshold to be '4.5'. Got '%v'", m["changeThreshold"])
|
||||
}
|
||||
if m["guaranteeSec"] != 600.0 {
|
||||
t.Errorf("Expected tag guaranteeSec to be '600'. Got '%v'", m["guaranteeSec"])
|
||||
}
|
||||
if m["mapFunction"] != "double" {
|
||||
t.Errorf("Expected tag mapFunction to be 'double'. Got '%v'", m["mapFunction"])
|
||||
}
|
||||
if m["units"] != "in." {
|
||||
t.Errorf("Expected tag units to be 'in.'. Got '%v'", m["units"])
|
||||
}
|
||||
if m["minExpected"] != 0.0 {
|
||||
t.Errorf("Expected tag minExpected to be '0.0'. Got '%v'", m["minExpected"])
|
||||
}
|
||||
if m["maxExpected"] != 1000.0 {
|
||||
t.Errorf("Expected tag maxExpected to be '1000.0'. Got '%v'", m["maxExpected"])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetTag(t *testing.T) {
|
||||
clearTagTable()
|
||||
addTags(1)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tag/1", nil)
|
||||
response := executeRequest(req)
|
||||
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
}
|
||||
|
||||
func addTags(count int) {
|
||||
if count < 1 {
|
||||
count = 1
|
||||
}
|
||||
sqlQuery := `INSERT INTO tags (
|
||||
name,
|
||||
tagName,
|
||||
tagClassId,
|
||||
deviceId,
|
||||
description,
|
||||
dataTypeId,
|
||||
changeThreshold,
|
||||
guaranteeSec,
|
||||
mapFunction,
|
||||
units,
|
||||
minExpected,
|
||||
maxExpected,
|
||||
createdAt,
|
||||
updatedAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
insStmt, insErr := a.DB.Prepare(sqlQuery)
|
||||
if insErr != nil {
|
||||
panic(insErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer insStmt.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
insStmt.Exec("Name"+strconv.Itoa(i), "tag"+strconv.Itoa(i), 1, 1,
|
||||
"Description"+strconv.Itoa(i), 1, i*100.0, 600,
|
||||
"mapFn"+strconv.Itoa(i), "in.", 0.0, 1000.0, time.Now(), time.Now())
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTag(t *testing.T) {
|
||||
clearTagTable()
|
||||
addTags(1)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tag/1", nil)
|
||||
response := executeRequest(req)
|
||||
var originalTag map[string]interface{}
|
||||
json.Unmarshal(response.Body.Bytes(), &originalTag)
|
||||
|
||||
payload := []byte(`{"name":"TestTag","tagName":"testTag","tagClassId":1,"deviceId":1,"description":"This is a test tag","dataTypeId":1,"changeThreshold":4.5,"guaranteeSec":600,"mapFunction":"double","units":"in.2","minExpected":1.0,"maxExpected":1001.0}`)
|
||||
|
||||
req, _ = http.NewRequest("PUT", "/api/v1/tag/1", bytes.NewBuffer(payload))
|
||||
response = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
|
||||
var m map[string]interface{}
|
||||
json.Unmarshal(response.Body.Bytes(), &m)
|
||||
|
||||
if m["id"] != originalTag["id"] {
|
||||
t.Errorf("Expected the id to remain the same (%v). Got %v", originalTag["id"], m["id"])
|
||||
}
|
||||
|
||||
if m["name"] == originalTag["name"] {
|
||||
t.Errorf("Expected the name to change from '%v' to '%v'. Got '%v'", originalTag["name"], m["name"], m["name"])
|
||||
}
|
||||
|
||||
if m["tagName"] == originalTag["tagName"] {
|
||||
t.Errorf("Expected the tagName to change from '%v' to '%v'. Got '%v'", originalTag["tagName"], m["tagName"], m["tagName"])
|
||||
}
|
||||
|
||||
if int(m["tagClassId"].(float64)) == originalTag["tagClassId"] {
|
||||
t.Errorf("Expected the tagClassId to change from '%v' to '%v'. Got '%v'", originalTag["tagClassId"], m["tagClassId"], m["tagClassId"])
|
||||
}
|
||||
|
||||
if int(m["deviceId"].(float64)) == originalTag["deviceId"] {
|
||||
t.Errorf("Expected the deviceId to change from '%v' to '%v'. Got '%v'", originalTag["deviceId"], m["deviceId"], m["deviceId"])
|
||||
}
|
||||
|
||||
if m["description"] == originalTag["description"] {
|
||||
t.Errorf("Expected the description to change from '%v' to '%v'. Got '%v'", originalTag["description"], m["description"], m["description"])
|
||||
}
|
||||
|
||||
if int(m["dataTypeId"].(float64)) == originalTag["dataTypeId"] {
|
||||
t.Errorf("Expected the dataTypeId to change from '%v' to '%v'. Got '%v'", originalTag["dataTypeId"], m["dataTypeId"], m["dataTypeId"])
|
||||
}
|
||||
|
||||
if m["changeThreshold"] == originalTag["changeThreshold"] {
|
||||
t.Errorf("Expected the changeThreshold to change from '%v' to '%v'. Got '%v'", originalTag["changeThreshold"], m["changeThreshold"], m["changeThreshold"])
|
||||
}
|
||||
|
||||
if int(m["guaranteeSec"].(float64)) == originalTag["guaranteeSec"] {
|
||||
t.Errorf("Expected the guaranteeSec to change from '%v' to '%v'. Got '%v'", originalTag["guaranteeSec"], m["guaranteeSec"], m["guaranteeSec"])
|
||||
}
|
||||
|
||||
if m["mapFunction"] == originalTag["mapFunction"] {
|
||||
t.Errorf("Expected the mapFunction to change from '%v' to '%v'. Got '%v'", originalTag["changeThreshold"], m["changeThreshold"], m["changeThreshold"])
|
||||
}
|
||||
|
||||
if m["units"] == originalTag["units"] {
|
||||
t.Errorf("Expected the units to change from '%v' to '%v'. Got '%v'", reflect.TypeOf(originalTag["units"]), reflect.TypeOf(m["units"]), reflect.TypeOf(m["units"]))
|
||||
}
|
||||
|
||||
if m["minExpected"] == originalTag["minExpected"] {
|
||||
t.Errorf("Expected the minExpected to change from '%v' to '%v'. Got '%v'", originalTag["minExpected"], m["minExpected"], m["minExpected"])
|
||||
}
|
||||
|
||||
if m["maxExpected"] == originalTag["maxExpected"] {
|
||||
t.Errorf("Expected the maxExpected to change from '%v' to '%v'. Got '%v'", originalTag["maxExpected"], m["maxExpected"], m["maxExpected"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteTag(t *testing.T) {
|
||||
clearTagTable()
|
||||
addTags(1)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tag/1", nil)
|
||||
response := executeRequest(req)
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
|
||||
req, _ = http.NewRequest("DELETE", "/api/v1/tag/1", nil)
|
||||
response = executeRequest(req)
|
||||
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
|
||||
req, _ = http.NewRequest("GET", "/api/v1/tag/1", nil)
|
||||
response = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusNotFound, response.Code)
|
||||
}
|
||||
139
testtagclass_test.go
Normal file
139
testtagclass_test.go
Normal file
@@ -0,0 +1,139 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func clearTagClassTable() {
|
||||
a.DB.Exec("DELETE FROM tagClasses")
|
||||
a.DB.Exec("ALTER TABLE tagClasses AUTO_INCREMENT = 1")
|
||||
}
|
||||
|
||||
func TestEmptyTagClassTable(t *testing.T) {
|
||||
clearTagClassTable()
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tagClasses", nil)
|
||||
response := executeRequest(req)
|
||||
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
|
||||
if body := response.Body.String(); body != "[]" {
|
||||
t.Errorf("Expected an empty array. Got %s", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetNonExistentTagClass(t *testing.T) {
|
||||
clearTagClassTable()
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tagClass/11", nil)
|
||||
response := executeRequest(req)
|
||||
|
||||
checkResponseCode(t, http.StatusNotFound, response.Code)
|
||||
|
||||
var m map[string]string
|
||||
json.Unmarshal(response.Body.Bytes(), &m)
|
||||
if m["error"] != "TagClass not found" {
|
||||
t.Errorf("Expected the 'error' key of the response to be set to 'TagClass not found'. Got '%s'", m["error"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateTagClass(t *testing.T) {
|
||||
clearTagClassTable()
|
||||
|
||||
payload := []byte(`{"classType":"Normal","description":"Historical Data"}`)
|
||||
|
||||
req, _ := http.NewRequest("POST", "/api/v1/tagClass", bytes.NewBuffer(payload))
|
||||
response := executeRequest(req)
|
||||
|
||||
checkResponseCode(t, http.StatusCreated, response.Code)
|
||||
|
||||
var m map[string]interface{}
|
||||
json.Unmarshal(response.Body.Bytes(), &m)
|
||||
|
||||
if m["classType"] != "Normal" {
|
||||
t.Errorf("Expected tagClass classType to be 'Normal'. Got '%v'", m["classType"])
|
||||
}
|
||||
|
||||
if m["description"] != "Historical Data" {
|
||||
t.Errorf("Expected tagClass description to be 'Historical Data'. Got '%v'", m["description"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTagClass(t *testing.T) {
|
||||
clearTagClassTable()
|
||||
addTagClasses(1)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tagClass/1", nil)
|
||||
response := executeRequest(req)
|
||||
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
}
|
||||
|
||||
func addTagClasses(count int) {
|
||||
if count < 1 {
|
||||
count = 1
|
||||
}
|
||||
insStmt, insErr := a.DB.Prepare("INSERT INTO tagClasses(classType, description, createdAt, updatedAt) VALUES(?, ?, ?, ?)")
|
||||
if insErr != nil {
|
||||
panic(insErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer insStmt.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
insStmt.Exec("TESTTYPE"+strconv.Itoa(i), "TESTDESCRIPTION"+strconv.Itoa(i), time.Now(), time.Now())
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTagClass(t *testing.T) {
|
||||
clearTagClassTable()
|
||||
addTagClasses(1)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tagClass/1", nil)
|
||||
response := executeRequest(req)
|
||||
var originalTagClass map[string]interface{}
|
||||
json.Unmarshal(response.Body.Bytes(), &originalTagClass)
|
||||
|
||||
payload := []byte(`{"classType":"handshake","description":"PLC Handshake"}`)
|
||||
|
||||
req, _ = http.NewRequest("PUT", "/api/v1/tagClass/1", bytes.NewBuffer(payload))
|
||||
response = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
|
||||
var m map[string]interface{}
|
||||
json.Unmarshal(response.Body.Bytes(), &m)
|
||||
|
||||
if m["id"] != originalTagClass["id"] {
|
||||
t.Errorf("Expected the id to remain the same (%v). Got %v", originalTagClass["id"], m["id"])
|
||||
}
|
||||
|
||||
if m["classType"] == originalTagClass["tagClass"] {
|
||||
t.Errorf("Expected the classType to change from '%v' to '%v'. Got '%v'", originalTagClass["classType"], m["classType"], m["classType"])
|
||||
}
|
||||
|
||||
if m["description"] == originalTagClass["description"] {
|
||||
t.Errorf("Expected the description to change from '%v' to '%v'. Got '%v'", originalTagClass["description"], m["description"], m["description"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteTagClass(t *testing.T) {
|
||||
clearTagClassTable()
|
||||
addTagClasses(1)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tagClass/1", nil)
|
||||
response := executeRequest(req)
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
|
||||
req, _ = http.NewRequest("DELETE", "/api/v1/tagClass/1", nil)
|
||||
response = executeRequest(req)
|
||||
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
|
||||
req, _ = http.NewRequest("GET", "/api/v1/tagClass/1", nil)
|
||||
response = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusNotFound, response.Code)
|
||||
}
|
||||
141
testtagvalue_test.go
Normal file
141
testtagvalue_test.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func clearTagValueTable() {
|
||||
a.DB.Exec("DELETE FROM tagValues")
|
||||
a.DB.Exec("ALTER TABLE tagValues AUTO_INCREMENT = 1")
|
||||
}
|
||||
|
||||
func TestEmptyTagValueTable(t *testing.T) {
|
||||
clearTagValueTable()
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tagValues", nil)
|
||||
response := executeRequest(req)
|
||||
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
|
||||
if body := response.Body.String(); body != "[]" {
|
||||
t.Errorf("Expected an empty array. Got %s", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetNonExistentTagValue(t *testing.T) {
|
||||
clearTagValueTable()
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tagValue/11", nil)
|
||||
response := executeRequest(req)
|
||||
|
||||
checkResponseCode(t, http.StatusNotFound, response.Code)
|
||||
|
||||
var m map[string]string
|
||||
json.Unmarshal(response.Body.Bytes(), &m)
|
||||
if m["error"] != "TagValue not found" {
|
||||
t.Errorf("Expected the 'error' key of the response to be set to 'TagValue not found'. Got '%s'", m["error"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateTagValue(t *testing.T) {
|
||||
clearTagValueTable()
|
||||
addTags(1)
|
||||
|
||||
payload := []byte(`{"tagId":1,"val":"1234.56"}`)
|
||||
|
||||
req, _ := http.NewRequest("POST", "/api/v1/tagValue", bytes.NewBuffer(payload))
|
||||
response := executeRequest(req)
|
||||
fmt.Printf("\n\n%s\n\n", response.Body)
|
||||
checkResponseCode(t, http.StatusCreated, response.Code)
|
||||
|
||||
var m map[string]interface{}
|
||||
json.Unmarshal(response.Body.Bytes(), &m)
|
||||
|
||||
if m["tagId"] != 1.0 {
|
||||
t.Errorf("Expected tagValue name to be '1'. Got '%v'", m["name"])
|
||||
}
|
||||
if m["val"] != "1234.56" {
|
||||
t.Errorf("Expected tagValue address to be '1234.56'. Got '%v'", m["address"])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetTagValue(t *testing.T) {
|
||||
clearTagValueTable()
|
||||
addTagValues(1)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tagValue/1", nil)
|
||||
response := executeRequest(req)
|
||||
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
}
|
||||
|
||||
func addTagValues(count int) {
|
||||
if count < 1 {
|
||||
count = 1
|
||||
}
|
||||
insStmt, insErr := a.DB.Prepare("INSERT INTO tagValues(tagId, val, createdAt, updatedAt) VALUES(?, ?, ?, ?)")
|
||||
if insErr != nil {
|
||||
panic(insErr.Error()) // proper error handling instead of panic in your app
|
||||
}
|
||||
defer insStmt.Close() // Close the statement when we leave main() / the program terminates
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
insStmt.Exec(1, strconv.Itoa(i*10), time.Now(), time.Now())
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTagValue(t *testing.T) {
|
||||
clearTagValueTable()
|
||||
addTagValues(1)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tagValue/1", nil)
|
||||
response := executeRequest(req)
|
||||
var originalTagValue map[string]interface{}
|
||||
json.Unmarshal(response.Body.Bytes(), &originalTagValue)
|
||||
|
||||
payload := []byte(`{"tagId":1,"val":"111.111"}`)
|
||||
|
||||
req, _ = http.NewRequest("PUT", "/api/v1/tagValue/1", bytes.NewBuffer(payload))
|
||||
response = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
|
||||
var m map[string]interface{}
|
||||
json.Unmarshal(response.Body.Bytes(), &m)
|
||||
|
||||
if m["id"] != originalTagValue["id"] {
|
||||
t.Errorf("Expected the id to remain the same (%v). Got %v", originalTagValue["id"], m["id"])
|
||||
}
|
||||
|
||||
if m["tagId"] != originalTagValue["tagId"] {
|
||||
t.Errorf("Expected the id to remain the same (%v). Got %v", originalTagValue["tagId"], m["tagId"])
|
||||
}
|
||||
|
||||
if m["val"] == originalTagValue["val"] {
|
||||
t.Errorf("Expected the val to change from '%v' to '%v'. Got '%v'", originalTagValue["val"], m["val"], m["val"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteTagValue(t *testing.T) {
|
||||
clearTagValueTable()
|
||||
addTagValues(1)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/v1/tagValue/1", nil)
|
||||
response := executeRequest(req)
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
|
||||
req, _ = http.NewRequest("DELETE", "/api/v1/tagValue/1", nil)
|
||||
response = executeRequest(req)
|
||||
|
||||
checkResponseCode(t, http.StatusOK, response.Code)
|
||||
|
||||
req, _ = http.NewRequest("GET", "/api/v1/tagValue/1", nil)
|
||||
response = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusNotFound, response.Code)
|
||||
}
|
||||
Reference in New Issue
Block a user