add openhack files
This commit is contained in:
140
apis/trips/tripsgo/dataAccess.go
Normal file
140
apis/trips/tripsgo/dataAccess.go
Normal file
@ -0,0 +1,140 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
//load .env locally for integration tests
|
||||
//System Environment variables take precedence
|
||||
var dbEnv = godotenv.Load()
|
||||
|
||||
func getEnv(key, fallback string) string {
|
||||
if value, ok := os.LookupEnv(key); ok {
|
||||
return value
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
var (
|
||||
debug = flag.Bool("debug", false, "enable debugging")
|
||||
password = flag.String("password", getEnv("SQL_PASSWORD", "changeme"), "the database password")
|
||||
port = flag.Int("port", 1433, "the database port")
|
||||
server = flag.String("server", getEnv("SQL_SERVER", "changeme.database.windows.net"), "the database server")
|
||||
user = flag.String("user", getEnv("SQL_USER", "YourUserName"), "the database user")
|
||||
database = flag.String("d", getEnv("SQL_DBNAME", "mydrivingDB"), "db_name")
|
||||
driver = flag.String("driver", getEnv("SQL_DRIVER", "mssql"), "db driver")
|
||||
)
|
||||
|
||||
func RebindDataAccessEnvironmentVariables() {
|
||||
s := getEnv("SQL_SERVER", "changeme.database.windows.net")
|
||||
server = &s
|
||||
|
||||
dr := getEnv("SQL_DRIVER", "mssql")
|
||||
driver = &dr
|
||||
}
|
||||
|
||||
// ExecuteNonQuery - Execute a SQL query that has no records returned (Ex. Delete)
|
||||
func ExecuteNonQuery(query string) (string, error) {
|
||||
connString := fmt.Sprintf("server=%s;database=%s;user id=%s;password=%s;port=%d", *server, *database, *user, *password, *port)
|
||||
|
||||
if *debug {
|
||||
message := fmt.Sprintf("connString:%s\n", connString)
|
||||
logMessage(message)
|
||||
}
|
||||
|
||||
conn, err := sql.Open(*driver, connString)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
statement, err := conn.Prepare(query)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer statement.Close()
|
||||
|
||||
result, err := statement.Exec()
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
serializedResult, _ := json.Marshal(result)
|
||||
|
||||
return string(serializedResult), nil
|
||||
}
|
||||
|
||||
// ExecuteQuery - Executes a query and returns the result set
|
||||
func ExecuteQuery(query string) (*sql.Rows, error) {
|
||||
connString := fmt.Sprintf("server=%s;database=%s;user id=%s;password=%s;port=%d", *server, *database, *user, *password, *port)
|
||||
|
||||
conn, err := sql.Open(*driver, connString)
|
||||
|
||||
if err != nil {
|
||||
logError(err, "Failed to connect to database.")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
statement, err := conn.Prepare(query)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// log.Fatal("Failed to query a trip: ", err.Error())
|
||||
}
|
||||
|
||||
defer statement.Close()
|
||||
|
||||
rows, err := statement.Query()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// log.Fatal("Error while running the query: ", err.Error())
|
||||
}
|
||||
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// FirstOrDefault - returns the first row of the result set.
|
||||
func FirstOrDefault(query string) (*sql.Row, error) {
|
||||
connString := fmt.Sprintf("server=%s;database=%s;user id=%s;password=%s;port=%d", *server, *database, *user, *password, *port)
|
||||
|
||||
if *debug {
|
||||
message := fmt.Sprintf("connString:%s\n", connString)
|
||||
logMessage(message)
|
||||
}
|
||||
|
||||
conn, err := sql.Open(*driver, connString)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// log.Fatal("Failed to connect to the database: ", err.Error())
|
||||
}
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
statement, err := conn.Prepare(query)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// log.Fatal("Failed to query a trip: ", err.Error())
|
||||
}
|
||||
|
||||
defer statement.Close()
|
||||
|
||||
row := statement.QueryRow()
|
||||
|
||||
return row, nil
|
||||
}
|
170
apis/trips/tripsgo/dataAccess_test.go
Normal file
170
apis/trips/tripsgo/dataAccess_test.go
Normal file
@ -0,0 +1,170 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestExecuteQueryInvalidDriverReturnsErr(t *testing.T) {
|
||||
defer t.Cleanup(resetDataAccessEnvVars)
|
||||
//arrange
|
||||
InitLogging(os.Stdout, os.Stdout, os.Stdout)
|
||||
os.Setenv("SQL_DRIVER", "not_a_real_driver")
|
||||
RebindDataAccessEnvironmentVariables()
|
||||
//act
|
||||
var query = SelectAllTripsForUserQuery("someUser")
|
||||
|
||||
_, err := ExecuteQuery(query)
|
||||
|
||||
//assert
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
func TestExecuteQueryConnectionSuccess(t *testing.T) {
|
||||
//act
|
||||
var query = SelectAllTripsForUserQuery("someUser")
|
||||
trips, err := ExecuteQuery(query)
|
||||
|
||||
//assert
|
||||
assert.NotNil(t, trips)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestExecuteQueryInvalidSqlReturnsErr(t *testing.T) {
|
||||
//arrange
|
||||
InitLogging(os.Stdout, os.Stdout, os.Stdout)
|
||||
|
||||
//act
|
||||
var invalidSql = "Select Trips From *"
|
||||
_, err := ExecuteQuery(invalidSql)
|
||||
|
||||
//assert
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestExecuteQueryInvalidServerReturnsErr(t *testing.T) {
|
||||
defer t.Cleanup(resetDataAccessEnvVars)
|
||||
|
||||
//arrange
|
||||
InitLogging(os.Stdout, os.Stdout, os.Stdout)
|
||||
os.Setenv("SQL_SERVER", "not_a_real_driver")
|
||||
RebindDataAccessEnvironmentVariables()
|
||||
|
||||
//act
|
||||
_, err := ExecuteQuery("SELECT TOP 1 ID FROM Trips")
|
||||
|
||||
//assert
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestExecuteNonQueryInvalidDriverReturnsErr(t *testing.T) {
|
||||
defer t.Cleanup(resetDataAccessEnvVars)
|
||||
//arrange
|
||||
InitLogging(os.Stdout, os.Stdout, os.Stdout)
|
||||
os.Setenv("SQL_DRIVER", "not_a_real_driver")
|
||||
RebindDataAccessEnvironmentVariables()
|
||||
|
||||
//act
|
||||
_, err := ExecuteNonQuery("fake non query sql")
|
||||
|
||||
//assert
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestExecuteNonQueryConnectionSuccess(t *testing.T) {
|
||||
//act
|
||||
_, err := ExecuteNonQuery("SELECT TOP 1 ID FROM Trips")
|
||||
|
||||
//assert
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestExecuteNonQueryInvalidServerReturnsErr(t *testing.T) {
|
||||
defer t.Cleanup(resetDataAccessEnvVars)
|
||||
|
||||
//arrange
|
||||
InitLogging(os.Stdout, os.Stdout, os.Stdout)
|
||||
os.Setenv("SQL_SERVER", "not_a_real_server")
|
||||
RebindDataAccessEnvironmentVariables()
|
||||
|
||||
//act
|
||||
_, err := ExecuteNonQuery("SELECT TOP 1 ID FROM Trips")
|
||||
|
||||
//assert
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestFirstOrDefaultInvalidDriverReturnsErr(t *testing.T) {
|
||||
defer t.Cleanup(resetDataAccessEnvVars)
|
||||
//arrange
|
||||
InitLogging(os.Stdout, os.Stdout, os.Stdout)
|
||||
os.Setenv("SQL_DRIVER", "not_a_real_driver")
|
||||
RebindDataAccessEnvironmentVariables()
|
||||
|
||||
//act
|
||||
_, err := FirstOrDefault("fake non query sql")
|
||||
|
||||
//assert
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestFirstOrDefaultConnectionSuccess(t *testing.T) {
|
||||
//act
|
||||
RebindDataAccessEnvironmentVariables()
|
||||
_, err := FirstOrDefault("SELECT TOP 1 ID FROM Trips")
|
||||
|
||||
//assert
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestFirstOrDefaultInvalidServerReturnsErr(t *testing.T) {
|
||||
defer t.Cleanup(resetDataAccessEnvVars)
|
||||
|
||||
//arrange
|
||||
InitLogging(os.Stdout, os.Stdout, os.Stdout)
|
||||
os.Setenv("SQL_SERVER", "not_a_real_server")
|
||||
RebindDataAccessEnvironmentVariables()
|
||||
|
||||
//act
|
||||
_, err := FirstOrDefault("SELECT TOP 1 ID FROM Trips")
|
||||
|
||||
//assert
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestExecuteNonQueryWritesLogIfDebugTrue(t *testing.T) {
|
||||
defer t.Cleanup(resetDataAccessEnvVars)
|
||||
|
||||
//arrange
|
||||
info := new(bytes.Buffer)
|
||||
InitLogging(info, os.Stdout, os.Stdout)
|
||||
var tr bool = true
|
||||
debug = &tr
|
||||
|
||||
//act
|
||||
ExecuteNonQuery("SELECT TOP 1 ID FROM Trips")
|
||||
|
||||
//assert
|
||||
actual := fmt.Sprint(info)
|
||||
assert.True(t, actual != "")
|
||||
}
|
||||
|
||||
func TestFirstOrDefaultWritesLogIfDebugTrue(t *testing.T) {
|
||||
defer t.Cleanup(resetDataAccessEnvVars)
|
||||
|
||||
//arrange
|
||||
info := new(bytes.Buffer)
|
||||
InitLogging(info, os.Stdout, os.Stdout)
|
||||
var tr bool = true
|
||||
debug = &tr
|
||||
|
||||
//act
|
||||
FirstOrDefault("SELECT TOP 1 ID FROM Trips")
|
||||
|
||||
//assert
|
||||
actual := fmt.Sprint(info)
|
||||
assert.True(t, actual != "")
|
||||
}
|
24
apis/trips/tripsgo/errorMessage.go
Normal file
24
apis/trips/tripsgo/errorMessage.go
Normal file
@ -0,0 +1,24 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SerializeError - Serialize Error information to JSON format.
|
||||
func SerializeError(e error, customMessage string) string {
|
||||
var errorMessage struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
if customMessage != "" {
|
||||
message := []string{customMessage, e.Error()}
|
||||
errorMessage.Message = strings.Join(message, ": ")
|
||||
} else {
|
||||
errorMessage.Message = e.Error()
|
||||
}
|
||||
|
||||
serializedError, _ := json.Marshal(errorMessage)
|
||||
|
||||
return string(serializedError)
|
||||
}
|
28
apis/trips/tripsgo/errorMessage_test.go
Normal file
28
apis/trips/tripsgo/errorMessage_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSerializeErrorReturnsJsonIncludesErrorMessageUnit(t *testing.T) {
|
||||
//arrange
|
||||
expected := "{\"Message\":\"This is a fake error\"}"
|
||||
err := errors.New("This is a fake error")
|
||||
//act
|
||||
actual := SerializeError(err, "")
|
||||
//assert
|
||||
assert.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestSerializeErrorReturnsJsonIncludesCustomMessageUnit(t *testing.T) {
|
||||
//arrange
|
||||
expected := "{\"Message\":\"more data: This is a fake error\"}"
|
||||
err := errors.New("This is a fake error")
|
||||
//act
|
||||
actual := SerializeError(err, "more data")
|
||||
//assert
|
||||
assert.Equal(t, expected, actual)
|
||||
}
|
11
apis/trips/tripsgo/error_response_default.go
Normal file
11
apis/trips/tripsgo/error_response_default.go
Normal file
@ -0,0 +1,11 @@
|
||||
package tripsgo
|
||||
|
||||
// ErrorResponseDefault - Structure to return error information to service caller.
|
||||
type ErrorResponseDefault struct {
|
||||
|
||||
// Error code (if available)
|
||||
Status int32 `json:"status,omitempty"`
|
||||
|
||||
// Error Message
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
15
apis/trips/tripsgo/healthCheckService.go
Normal file
15
apis/trips/tripsgo/healthCheckService.go
Normal file
@ -0,0 +1,15 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func healthcheckGet(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
hc := &Healthcheck{Message: "Trip Service Healthcheck", Status: "Healthy"}
|
||||
|
||||
json.NewEncoder(w).Encode(hc)
|
||||
}
|
31
apis/trips/tripsgo/healthCheckService_test.go
Normal file
31
apis/trips/tripsgo/healthCheckService_test.go
Normal file
@ -0,0 +1,31 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var healthRouteTests = []APITestCase{
|
||||
{
|
||||
Tag: "t0 - healthcheck",
|
||||
Method: "GET",
|
||||
URL: "/api/healthcheck/trips",
|
||||
Status: 200,
|
||||
ExpectedResponse: `{"message": "Trip Service Healthcheck","status": "Healthy"}`,
|
||||
},
|
||||
}
|
||||
|
||||
func TestHealthRouteUnit(t *testing.T) {
|
||||
router := NewRouter()
|
||||
var debug, present = os.LookupEnv("DEBUG_LOGGING")
|
||||
|
||||
if present && debug == "true" {
|
||||
InitLogging(os.Stdout, os.Stdout, os.Stdout)
|
||||
} else {
|
||||
// if debug env is not present or false, do not log debug output to console
|
||||
InitLogging(os.Stdout, ioutil.Discard, os.Stdout)
|
||||
}
|
||||
RunAPITests(t, router, healthRouteTests[0:1])
|
||||
|
||||
}
|
11
apis/trips/tripsgo/healthcheck.go
Normal file
11
apis/trips/tripsgo/healthcheck.go
Normal file
@ -0,0 +1,11 @@
|
||||
package tripsgo
|
||||
|
||||
// Healthcheck - Structure for healthcheck response body
|
||||
type Healthcheck struct {
|
||||
|
||||
//
|
||||
Message string `json:"message,omitempty"`
|
||||
|
||||
//
|
||||
Status string `json:"status,omitempty"`
|
||||
}
|
61
apis/trips/tripsgo/logger.go
Normal file
61
apis/trips/tripsgo/logger.go
Normal file
@ -0,0 +1,61 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
//
|
||||
var (
|
||||
Info *log.Logger
|
||||
Debug *log.Logger
|
||||
Fatal *log.Logger
|
||||
)
|
||||
|
||||
// InitLogging - Initialize logging for trips api
|
||||
func InitLogging(
|
||||
infoHandle io.Writer,
|
||||
debugHandle io.Writer,
|
||||
fatalHandle io.Writer) {
|
||||
|
||||
Info = log.New(infoHandle,
|
||||
"INFO: ",
|
||||
log.Ldate|log.Ltime|log.Lshortfile)
|
||||
|
||||
Debug = log.New(debugHandle,
|
||||
"DEBUG: ",
|
||||
log.Ldate|log.Ltime|log.Lshortfile)
|
||||
|
||||
Fatal = log.New(fatalHandle,
|
||||
"FATAL: ",
|
||||
log.Ldate|log.Ltime|log.Lshortfile)
|
||||
}
|
||||
|
||||
// Logger - basic console logger that writes request info to stdout
|
||||
func Logger(inner http.Handler, name string) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
|
||||
inner.ServeHTTP(w, r)
|
||||
|
||||
Info.Println(fmt.Sprintf(
|
||||
"%s %s %s %s",
|
||||
r.Method,
|
||||
r.RequestURI,
|
||||
name,
|
||||
time.Since(start),
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
func logMessage(msg string) {
|
||||
Info.Println(msg)
|
||||
}
|
||||
|
||||
func logError(err error, msg string) {
|
||||
Info.Println(msg)
|
||||
Debug.Println(err.Error())
|
||||
}
|
58
apis/trips/tripsgo/logger_test.go
Normal file
58
apis/trips/tripsgo/logger_test.go
Normal file
@ -0,0 +1,58 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLogMessagePrintToInfoLogUnit(t *testing.T) {
|
||||
//arrange
|
||||
info := new(bytes.Buffer)
|
||||
debug := new(bytes.Buffer)
|
||||
fatal := new(bytes.Buffer)
|
||||
InitLogging(info, debug, fatal)
|
||||
errorMessage := "This is a test message"
|
||||
//act
|
||||
logMessage(errorMessage)
|
||||
|
||||
//assert
|
||||
actual := fmt.Sprint(info)
|
||||
assert.True(t, strings.Contains(actual, errorMessage))
|
||||
}
|
||||
|
||||
func TestLogErrorPrintsMsgToInfoUnit(t *testing.T) {
|
||||
//arrange
|
||||
info := new(bytes.Buffer)
|
||||
debug := new(bytes.Buffer)
|
||||
fatal := new(bytes.Buffer)
|
||||
InitLogging(info, debug, fatal)
|
||||
errorMessage := "This is a test message"
|
||||
err := errors.New("This is a fake error")
|
||||
//act
|
||||
logError(err, errorMessage)
|
||||
|
||||
//assert
|
||||
actual := fmt.Sprint(info)
|
||||
assert.True(t, strings.Contains(actual, errorMessage))
|
||||
}
|
||||
|
||||
func TestLogErrorPrintsErrMessageToDebugUnit(t *testing.T) {
|
||||
//arrange
|
||||
info := new(bytes.Buffer)
|
||||
debug := new(bytes.Buffer)
|
||||
fatal := new(bytes.Buffer)
|
||||
InitLogging(info, debug, fatal)
|
||||
errorMessage := "This is a test message"
|
||||
err := errors.New("This is a fake error")
|
||||
//act
|
||||
logError(err, errorMessage)
|
||||
|
||||
//assert
|
||||
actual := fmt.Sprint(debug)
|
||||
assert.True(t, strings.Contains(actual, "This is a fake error"))
|
||||
}
|
393
apis/trips/tripsgo/queries.go
Normal file
393
apis/trips/tripsgo/queries.go
Normal file
@ -0,0 +1,393 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// SelectTripByIDQuery - REQUIRED tripID value
|
||||
func SelectTripByIDQuery(tripID string) string {
|
||||
return `SELECT
|
||||
Id,
|
||||
Name,
|
||||
UserId,
|
||||
RecordedTimeStamp,
|
||||
EndTimeStamp,
|
||||
Rating,
|
||||
IsComplete,
|
||||
HasSimulatedOBDData,
|
||||
AverageSpeed,
|
||||
FuelUsed,
|
||||
HardStops,
|
||||
HardAccelerations,
|
||||
Distance,
|
||||
CreatedAt,
|
||||
UpdatedAt
|
||||
FROM Trips
|
||||
WHERE Id = '` + tripID + `'
|
||||
AND Deleted = 0`
|
||||
}
|
||||
|
||||
var SelectAllTripsQuery = selectAllTripsQuery
|
||||
|
||||
// SelectAllTripsQuery - select all trips
|
||||
func selectAllTripsQuery() string {
|
||||
return `SELECT
|
||||
Id,
|
||||
Name,
|
||||
UserId,
|
||||
RecordedTimeStamp,
|
||||
EndTimeStamp,
|
||||
Rating,
|
||||
IsComplete,
|
||||
HasSimulatedOBDData,
|
||||
AverageSpeed,
|
||||
FuelUsed,
|
||||
HardStops,
|
||||
HardAccelerations,
|
||||
Distance,
|
||||
CreatedAt,
|
||||
UpdatedAt
|
||||
FROM Trips
|
||||
WHERE Deleted = 0`
|
||||
}
|
||||
|
||||
// SelectAllTripsForUserQuery REQUIRED userID
|
||||
var SelectAllTripsForUserQuery = selectAllTripsForUserQuery
|
||||
|
||||
func selectAllTripsForUserQuery(userID string) string {
|
||||
return `SELECT
|
||||
Id,
|
||||
Name,
|
||||
UserId,
|
||||
RecordedTimeStamp,
|
||||
EndTimeStamp,
|
||||
Rating,
|
||||
IsComplete,
|
||||
HasSimulatedOBDData,
|
||||
AverageSpeed,
|
||||
FuelUsed,
|
||||
HardStops,
|
||||
HardAccelerations,
|
||||
Distance,
|
||||
CreatedAt,
|
||||
UpdatedAt
|
||||
FROM Trips
|
||||
WHERE UserId ='` + userID + `'
|
||||
AND Deleted = 0`
|
||||
}
|
||||
|
||||
// DeleteTripPointsForTripQuery - REQUIRED tripID
|
||||
func DeleteTripPointsForTripQuery(tripID string) string {
|
||||
return fmt.Sprintf("UPDATE TripPoints SET Deleted = 1 WHERE TripId = '%s'", tripID)
|
||||
}
|
||||
|
||||
// DeleteTripQuery - REQUIRED tripID
|
||||
func DeleteTripQuery(tripID string) string {
|
||||
return fmt.Sprintf("UPDAte Trips SET Deleted = 1 WHERE Id = '%s'", tripID)
|
||||
}
|
||||
|
||||
// UpdateTripQuery - REQUIRED trip object and tripID
|
||||
func UpdateTripQuery(trip Trip) string {
|
||||
var query = `UPDATE Trips SET
|
||||
Name = '%s',
|
||||
UserId = '%s',
|
||||
RecordedTimeStamp = '%s',
|
||||
EndTimeStamp = '%s',
|
||||
Rating = %d,
|
||||
IsComplete = '%s',
|
||||
HasSimulatedOBDData = '%s',
|
||||
AverageSpeed = %g,
|
||||
FuelUsed = %g,
|
||||
HardStops = %d,
|
||||
HardAccelerations = %d,
|
||||
Distance = %g,
|
||||
UpdatedAt = GETDATE()
|
||||
WHERE Id = '%s'`
|
||||
|
||||
var formattedQuery = fmt.Sprintf(
|
||||
query,
|
||||
trip.Name,
|
||||
trip.UserID,
|
||||
trip.RecordedTimeStamp,
|
||||
trip.EndTimeStamp,
|
||||
trip.Rating,
|
||||
strconv.FormatBool(trip.IsComplete),
|
||||
strconv.FormatBool(trip.HasSimulatedOBDData),
|
||||
trip.AverageSpeed,
|
||||
trip.FuelUsed,
|
||||
trip.HardStops,
|
||||
trip.HardAccelerations,
|
||||
trip.Distance,
|
||||
trip.ID)
|
||||
|
||||
Debug.Println("updateTripQuery: " + formattedQuery)
|
||||
|
||||
return formattedQuery
|
||||
}
|
||||
|
||||
func createTripQuery(trip Trip) string {
|
||||
var query = `DECLARE @tempReturn
|
||||
TABLE (TripId NVARCHAR(128));
|
||||
INSERT INTO Trips (
|
||||
Name,
|
||||
UserId,
|
||||
RecordedTimeStamp,
|
||||
EndTimeStamp,
|
||||
Rating,
|
||||
IsComplete,
|
||||
HasSimulatedOBDData,
|
||||
AverageSpeed,
|
||||
FuelUsed,
|
||||
HardStops,
|
||||
HardAccelerations,
|
||||
Distance,
|
||||
UpdatedAt,
|
||||
Deleted)
|
||||
OUTPUT Inserted.ID
|
||||
INTO @tempReturn
|
||||
VALUES (
|
||||
'%s',
|
||||
'%s',
|
||||
'%s',
|
||||
'%s',
|
||||
%d,
|
||||
'%s',
|
||||
'%s',
|
||||
%g,
|
||||
%g,
|
||||
%d,
|
||||
%d,
|
||||
%g,
|
||||
GETDATE(),
|
||||
'false');
|
||||
SELECT TripId FROM @tempReturn`
|
||||
|
||||
var formattedQuery = fmt.Sprintf(
|
||||
query,
|
||||
trip.Name,
|
||||
trip.UserID,
|
||||
trip.RecordedTimeStamp,
|
||||
trip.EndTimeStamp,
|
||||
trip.Rating,
|
||||
strconv.FormatBool(trip.IsComplete),
|
||||
strconv.FormatBool(trip.HasSimulatedOBDData),
|
||||
trip.AverageSpeed,
|
||||
trip.FuelUsed,
|
||||
trip.HardStops,
|
||||
trip.HardAccelerations,
|
||||
trip.Distance)
|
||||
|
||||
Debug.Println("createTripQuery: " + formattedQuery)
|
||||
|
||||
return formattedQuery
|
||||
}
|
||||
|
||||
func selectTripPointsForTripQuery(tripID string) string {
|
||||
|
||||
var query = `SELECT
|
||||
[Id],
|
||||
[TripId],
|
||||
[Latitude],
|
||||
[Longitude],
|
||||
[Speed],
|
||||
[RecordedTimeStamp],
|
||||
[Sequence],
|
||||
[RPM],
|
||||
[ShortTermFuelBank],
|
||||
[LongTermFuelBank],
|
||||
[ThrottlePosition],
|
||||
[RelativeThrottlePosition],
|
||||
[Runtime],
|
||||
[DistanceWithMalfunctionLight],
|
||||
[EngineLoad],
|
||||
[EngineFuelRate],
|
||||
[VIN]
|
||||
FROM [dbo].[TripPoints]
|
||||
WHERE
|
||||
TripId = '%s'
|
||||
AND Deleted = 0`
|
||||
|
||||
var formattedQuery = fmt.Sprintf(
|
||||
query,
|
||||
tripID)
|
||||
|
||||
Debug.Println("selectTripPointsForTripQuery: " + formattedQuery)
|
||||
|
||||
return formattedQuery
|
||||
}
|
||||
|
||||
func selectTripPointsForTripPointIDQuery(tripPointID string) string {
|
||||
var query = `SELECT
|
||||
[Id],
|
||||
[TripId],
|
||||
[Latitude],
|
||||
[Longitude],
|
||||
[Speed],
|
||||
[RecordedTimeStamp],
|
||||
[Sequence],
|
||||
[RPM],
|
||||
[ShortTermFuelBank],
|
||||
[LongTermFuelBank],
|
||||
[ThrottlePosition],
|
||||
[RelativeThrottlePosition],
|
||||
[Runtime],
|
||||
[DistanceWithMalfunctionLight],
|
||||
[EngineLoad],
|
||||
[EngineFuelRate],
|
||||
[VIN]
|
||||
FROM TripPoints
|
||||
WHERE Id = '%s'
|
||||
AND Deleted = 0`
|
||||
|
||||
var formattedQuery = fmt.Sprintf(
|
||||
query,
|
||||
tripPointID)
|
||||
|
||||
Debug.Println("selectTripPointsForTripPointIDQuery: " + formattedQuery)
|
||||
|
||||
return formattedQuery
|
||||
}
|
||||
|
||||
func createTripPointQuery(tripPoint TripPoint, tripID string) string {
|
||||
var query = `DECLARE @tempReturn TABLE (TripPointId NVARCHAR(128));
|
||||
INSERT INTO TripPoints (
|
||||
[TripId],
|
||||
[Latitude],
|
||||
[Longitude],
|
||||
[Speed],
|
||||
[RecordedTimeStamp],
|
||||
[Sequence],
|
||||
[RPM],
|
||||
[ShortTermFuelBank],
|
||||
[LongTermFuelBank],
|
||||
[ThrottlePosition],
|
||||
[RelativeThrottlePosition],
|
||||
[Runtime],
|
||||
[DistanceWithMalfunctionLight],
|
||||
[EngineLoad],
|
||||
[EngineFuelRate],
|
||||
[MassFlowRate],
|
||||
[HasOBDData],
|
||||
[HasSimulatedOBDData],
|
||||
[VIN],
|
||||
[UpdatedAt],
|
||||
[Deleted])
|
||||
OUTPUT
|
||||
Inserted.ID
|
||||
INTO @tempReturn
|
||||
VALUES (
|
||||
'%s',
|
||||
%g,
|
||||
%g,
|
||||
%g,
|
||||
'%s',
|
||||
%d,
|
||||
%g,
|
||||
%g,
|
||||
%g,
|
||||
%g,
|
||||
%g,
|
||||
%g,
|
||||
%g,
|
||||
%g,
|
||||
%g,
|
||||
%g,
|
||||
'%s',
|
||||
'%s',
|
||||
'%s',
|
||||
GETDATE(),
|
||||
'false');
|
||||
SELECT TripPointId
|
||||
FROM @tempReturn`
|
||||
|
||||
var formattedQuery = fmt.Sprintf(
|
||||
query,
|
||||
tripID,
|
||||
tripPoint.Latitude,
|
||||
tripPoint.Longitude,
|
||||
tripPoint.Speed,
|
||||
tripPoint.RecordedTimeStamp,
|
||||
tripPoint.Sequence,
|
||||
tripPoint.RPM,
|
||||
tripPoint.ShortTermFuelBank,
|
||||
tripPoint.LongTermFuelBank,
|
||||
tripPoint.ThrottlePosition,
|
||||
tripPoint.RelativeThrottlePosition,
|
||||
tripPoint.Runtime,
|
||||
tripPoint.DistanceWithMalfunctionLight,
|
||||
tripPoint.EngineLoad,
|
||||
tripPoint.MassFlowRate,
|
||||
tripPoint.EngineFuelRate,
|
||||
strconv.FormatBool(tripPoint.HasOBDData),
|
||||
strconv.FormatBool(tripPoint.HasSimulatedOBDData),
|
||||
tripPoint.VIN)
|
||||
|
||||
Debug.Println("createTripPointQuery: " + formattedQuery)
|
||||
|
||||
return formattedQuery
|
||||
}
|
||||
|
||||
func updateTripPointQuery(tripPoint TripPoint) string {
|
||||
var query = `UPDATE [TripPoints]
|
||||
SET [TripId] = '%s',
|
||||
[Latitude] = '%s',
|
||||
[Longitude] = '%s',
|
||||
[Speed] = '%s',
|
||||
[RecordedTimeStamp] = '%s',
|
||||
[Sequence] = %d,[RPM] = '%s',
|
||||
[ShortTermFuelBank] = '%s',
|
||||
[LongTermFuelBank] = '%s',
|
||||
[ThrottlePosition] = '%s',
|
||||
[RelativeThrottlePosition] = '%s',
|
||||
[Runtime] = '%s',
|
||||
[DistanceWithMalfunctionLight] = '%s',
|
||||
[EngineLoad] = '%s',
|
||||
[MassFlowRate] = '%s',
|
||||
[EngineFuelRate] = '%s',
|
||||
[HasOBDData] = '%s',
|
||||
[HasSimulatedOBDData] = '%s',
|
||||
[VIN] = '%s'
|
||||
WHERE Id = '%s'`
|
||||
|
||||
var formattedQuery = fmt.Sprintf(
|
||||
query,
|
||||
tripPoint.TripID,
|
||||
tripPoint.Latitude,
|
||||
tripPoint.Longitude,
|
||||
tripPoint.Speed,
|
||||
tripPoint.RecordedTimeStamp,
|
||||
tripPoint.Sequence,
|
||||
tripPoint.RPM,
|
||||
tripPoint.ShortTermFuelBank,
|
||||
tripPoint.LongTermFuelBank,
|
||||
tripPoint.ThrottlePosition,
|
||||
tripPoint.RelativeThrottlePosition,
|
||||
tripPoint.Runtime,
|
||||
tripPoint.DistanceWithMalfunctionLight,
|
||||
tripPoint.EngineLoad,
|
||||
tripPoint.MassFlowRate,
|
||||
tripPoint.EngineFuelRate,
|
||||
strconv.FormatBool(tripPoint.HasOBDData),
|
||||
strconv.FormatBool(tripPoint.HasSimulatedOBDData),
|
||||
tripPoint.VIN,
|
||||
tripPoint.ID)
|
||||
|
||||
Debug.Println("updateTripPointQuery: " + formattedQuery)
|
||||
|
||||
return formattedQuery
|
||||
}
|
||||
|
||||
func deleteTripPointQuery(tripPointID string) string {
|
||||
var query = `UPDATE TripPoints
|
||||
SET Deleted = 1
|
||||
WHERE Id = '%s'`
|
||||
|
||||
var formattedQuery = fmt.Sprintf(
|
||||
query,
|
||||
tripPointID)
|
||||
|
||||
Debug.Println("deleteTripPointQuery: " + formattedQuery)
|
||||
|
||||
return formattedQuery
|
||||
}
|
416
apis/trips/tripsgo/queries_test.go
Normal file
416
apis/trips/tripsgo/queries_test.go
Normal file
@ -0,0 +1,416 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUnitdeleteTripPointQuery(t *testing.T) {
|
||||
//arrange
|
||||
var expected = `UPDATE TripPoints
|
||||
SET Deleted = 1
|
||||
WHERE Id = '1234'`
|
||||
//act
|
||||
query := deleteTripPointQuery("1234")
|
||||
//assert
|
||||
if query != expected {
|
||||
t.Errorf("Error \nExpected: %s \nGot: %s", expected, query)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnitupdateTripPointQuery(t *testing.T) {
|
||||
//arrange
|
||||
tripPoint := TripPoint{
|
||||
ID: "abcd",
|
||||
TripID: "a_trip",
|
||||
Latitude: 51.5244282,
|
||||
Longitude: -0.0784379,
|
||||
Speed: 185.2,
|
||||
RecordedTimeStamp: "a_timestamp",
|
||||
Sequence: 1,
|
||||
RPM: 4000,
|
||||
ShortTermFuelBank: 1,
|
||||
LongTermFuelBank: 2,
|
||||
ThrottlePosition: 3,
|
||||
RelativeThrottlePosition: 4,
|
||||
Runtime: 5,
|
||||
DistanceWithMalfunctionLight: 6,
|
||||
EngineLoad: 7,
|
||||
MassFlowRate: 8,
|
||||
EngineFuelRate: 9,
|
||||
HasOBDData: true,
|
||||
HasSimulatedOBDData: false,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
Deleted: false,
|
||||
}
|
||||
|
||||
var expected = `UPDATE [TripPoints]
|
||||
SET [TripId] = 'a_trip',
|
||||
[Latitude] = '%!s(float32=51.52443)',
|
||||
[Longitude] = '%!s(float32=-0.0784379)',
|
||||
[Speed] = '%!s(float32=185.2)',
|
||||
[RecordedTimeStamp] = 'a_timestamp',
|
||||
[Sequence] = 1,[RPM] = '%!s(float32=4000)',
|
||||
[ShortTermFuelBank] = '%!s(float32=1)',
|
||||
[LongTermFuelBank] = '%!s(float32=2)',
|
||||
[ThrottlePosition] = '%!s(float32=3)',
|
||||
[RelativeThrottlePosition] = '%!s(float32=4)',
|
||||
[Runtime] = '%!s(float32=5)',
|
||||
[DistanceWithMalfunctionLight] = '%!s(float32=6)',
|
||||
[EngineLoad] = '%!s(float32=7)',
|
||||
[MassFlowRate] = '%!s(float32=8)',
|
||||
[EngineFuelRate] = '%!s(float32=9)',
|
||||
[HasOBDData] = 'true',
|
||||
[HasSimulatedOBDData] = 'false',
|
||||
[VIN] = '{ %!s(bool=false)}'
|
||||
WHERE Id = 'abcd'`
|
||||
//act
|
||||
query := updateTripPointQuery(tripPoint)
|
||||
//assert
|
||||
assert.Equal(t, expected, query)
|
||||
}
|
||||
|
||||
func TestSelectAllTripsQueryUnit(t *testing.T) {
|
||||
//arrange
|
||||
var expected = `SELECT
|
||||
Id,
|
||||
Name,
|
||||
UserId,
|
||||
RecordedTimeStamp,
|
||||
EndTimeStamp,
|
||||
Rating,
|
||||
IsComplete,
|
||||
HasSimulatedOBDData,
|
||||
AverageSpeed,
|
||||
FuelUsed,
|
||||
HardStops,
|
||||
HardAccelerations,
|
||||
Distance,
|
||||
CreatedAt,
|
||||
UpdatedAt
|
||||
FROM Trips
|
||||
WHERE Deleted = 0`
|
||||
//act
|
||||
query := SelectAllTripsQuery()
|
||||
//assert
|
||||
assert.Equal(t, expected, query)
|
||||
}
|
||||
|
||||
func TestSelectAllTripsForUserQueryUnit(t *testing.T) {
|
||||
//arrange
|
||||
var expected = `SELECT
|
||||
Id,
|
||||
Name,
|
||||
UserId,
|
||||
RecordedTimeStamp,
|
||||
EndTimeStamp,
|
||||
Rating,
|
||||
IsComplete,
|
||||
HasSimulatedOBDData,
|
||||
AverageSpeed,
|
||||
FuelUsed,
|
||||
HardStops,
|
||||
HardAccelerations,
|
||||
Distance,
|
||||
CreatedAt,
|
||||
UpdatedAt
|
||||
FROM Trips
|
||||
WHERE UserId ='fake_user'
|
||||
AND Deleted = 0`
|
||||
//act
|
||||
query := SelectAllTripsForUserQuery("fake_user")
|
||||
//assert
|
||||
assert.Equal(t, expected, query)
|
||||
}
|
||||
|
||||
func TestDeleteTripPointsForTripQueryUnit(t *testing.T) {
|
||||
//arrange
|
||||
var expected = `UPDATE TripPoints SET Deleted = 1 WHERE TripId = 'trip_123'`
|
||||
//act
|
||||
query := DeleteTripPointsForTripQuery("trip_123")
|
||||
//assert
|
||||
assert.Equal(t, expected, query)
|
||||
}
|
||||
|
||||
func TestDeleteTripQueryUnit(t *testing.T) {
|
||||
//arrange
|
||||
var expected = `UPDAte Trips SET Deleted = 1 WHERE Id = 'trip_123'`
|
||||
//act
|
||||
query := DeleteTripQuery("trip_123")
|
||||
//assert
|
||||
assert.Equal(t, expected, query)
|
||||
}
|
||||
|
||||
func TestSelectTripByIDQueryUnit(t *testing.T) {
|
||||
//arrange
|
||||
var expected = `SELECT
|
||||
Id,
|
||||
Name,
|
||||
UserId,
|
||||
RecordedTimeStamp,
|
||||
EndTimeStamp,
|
||||
Rating,
|
||||
IsComplete,
|
||||
HasSimulatedOBDData,
|
||||
AverageSpeed,
|
||||
FuelUsed,
|
||||
HardStops,
|
||||
HardAccelerations,
|
||||
Distance,
|
||||
CreatedAt,
|
||||
UpdatedAt
|
||||
FROM Trips
|
||||
WHERE Id = 'trip_123'
|
||||
AND Deleted = 0`
|
||||
//act
|
||||
query := SelectTripByIDQuery("trip_123")
|
||||
//assert
|
||||
assert.Equal(t, expected, query)
|
||||
}
|
||||
|
||||
func TestSelectTripPointsForTripPointIDQueryUnit(t *testing.T) {
|
||||
//arrange
|
||||
var expected = `SELECT
|
||||
[Id],
|
||||
[TripId],
|
||||
[Latitude],
|
||||
[Longitude],
|
||||
[Speed],
|
||||
[RecordedTimeStamp],
|
||||
[Sequence],
|
||||
[RPM],
|
||||
[ShortTermFuelBank],
|
||||
[LongTermFuelBank],
|
||||
[ThrottlePosition],
|
||||
[RelativeThrottlePosition],
|
||||
[Runtime],
|
||||
[DistanceWithMalfunctionLight],
|
||||
[EngineLoad],
|
||||
[EngineFuelRate],
|
||||
[VIN]
|
||||
FROM TripPoints
|
||||
WHERE Id = 'point_ab'
|
||||
AND Deleted = 0`
|
||||
//act
|
||||
query := selectTripPointsForTripPointIDQuery("point_ab")
|
||||
//assert
|
||||
assert.Equal(t, expected, query)
|
||||
}
|
||||
|
||||
func TestUpdateTripQueryUnit(t *testing.T) {
|
||||
//arrange
|
||||
trip := Trip{
|
||||
ID: "abcd",
|
||||
Name: "fake Trip",
|
||||
UserID: "fake user",
|
||||
RecordedTimeStamp: "now",
|
||||
EndTimeStamp: "then",
|
||||
Rating: 1,
|
||||
IsComplete: false,
|
||||
HasSimulatedOBDData: false,
|
||||
AverageSpeed: 88,
|
||||
FuelUsed: 23.2,
|
||||
HardStops: 8,
|
||||
HardAccelerations: 12,
|
||||
Distance: 5,
|
||||
Created: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
Deleted: false,
|
||||
}
|
||||
var expected = `UPDATE Trips SET
|
||||
Name = 'fake Trip',
|
||||
UserId = 'fake user',
|
||||
RecordedTimeStamp = 'now',
|
||||
EndTimeStamp = 'then',
|
||||
Rating = 1,
|
||||
IsComplete = 'false',
|
||||
HasSimulatedOBDData = 'false',
|
||||
AverageSpeed = 88,
|
||||
FuelUsed = 23.2,
|
||||
HardStops = 8,
|
||||
HardAccelerations = 12,
|
||||
Distance = 5,
|
||||
UpdatedAt = GETDATE()
|
||||
WHERE Id = 'abcd'`
|
||||
//act
|
||||
query := UpdateTripQuery(trip)
|
||||
//assert
|
||||
assert.Equal(t, expected, query)
|
||||
}
|
||||
|
||||
func TestCreateTripQueryUnit(t *testing.T) {
|
||||
//arrange
|
||||
trip := Trip{
|
||||
ID: "abcd",
|
||||
Name: "fake Trip",
|
||||
UserID: "fake user",
|
||||
RecordedTimeStamp: "now",
|
||||
EndTimeStamp: "then",
|
||||
Rating: 1,
|
||||
IsComplete: false,
|
||||
HasSimulatedOBDData: false,
|
||||
AverageSpeed: 88,
|
||||
FuelUsed: 23.2,
|
||||
HardStops: 8,
|
||||
HardAccelerations: 12,
|
||||
Distance: 5,
|
||||
Created: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
Deleted: false,
|
||||
}
|
||||
var expected = `DECLARE @tempReturn
|
||||
TABLE (TripId NVARCHAR(128));
|
||||
INSERT INTO Trips (
|
||||
Name,
|
||||
UserId,
|
||||
RecordedTimeStamp,
|
||||
EndTimeStamp,
|
||||
Rating,
|
||||
IsComplete,
|
||||
HasSimulatedOBDData,
|
||||
AverageSpeed,
|
||||
FuelUsed,
|
||||
HardStops,
|
||||
HardAccelerations,
|
||||
Distance,
|
||||
UpdatedAt,
|
||||
Deleted)
|
||||
OUTPUT Inserted.ID
|
||||
INTO @tempReturn
|
||||
VALUES (
|
||||
'fake Trip',
|
||||
'fake user',
|
||||
'now',
|
||||
'then',
|
||||
1,
|
||||
'false',
|
||||
'false',
|
||||
88,
|
||||
23.2,
|
||||
8,
|
||||
12,
|
||||
5,
|
||||
GETDATE(),
|
||||
'false');
|
||||
SELECT TripId FROM @tempReturn`
|
||||
//act
|
||||
query := createTripQuery(trip)
|
||||
//assert
|
||||
assert.Equal(t, expected, query)
|
||||
}
|
||||
|
||||
func TestSelectTripPointsForTripQueryUnit(t *testing.T) {
|
||||
//arrange
|
||||
var expected = `SELECT
|
||||
[Id],
|
||||
[TripId],
|
||||
[Latitude],
|
||||
[Longitude],
|
||||
[Speed],
|
||||
[RecordedTimeStamp],
|
||||
[Sequence],
|
||||
[RPM],
|
||||
[ShortTermFuelBank],
|
||||
[LongTermFuelBank],
|
||||
[ThrottlePosition],
|
||||
[RelativeThrottlePosition],
|
||||
[Runtime],
|
||||
[DistanceWithMalfunctionLight],
|
||||
[EngineLoad],
|
||||
[EngineFuelRate],
|
||||
[VIN]
|
||||
FROM [dbo].[TripPoints]
|
||||
WHERE
|
||||
TripId = 'trip_zzyzx'
|
||||
AND Deleted = 0`
|
||||
//act
|
||||
query := selectTripPointsForTripQuery("trip_zzyzx")
|
||||
//assert
|
||||
assert.Equal(t, expected, query)
|
||||
}
|
||||
|
||||
func TestCreateTripPointQueryUnit(t *testing.T) {
|
||||
//arrange
|
||||
tripPoint := TripPoint{
|
||||
ID: "abcd",
|
||||
TripID: "a_trip",
|
||||
Latitude: 51.5244282,
|
||||
Longitude: -0.0784379,
|
||||
Speed: 185.2,
|
||||
RecordedTimeStamp: "a_timestamp",
|
||||
Sequence: 1,
|
||||
RPM: 4000,
|
||||
ShortTermFuelBank: 1,
|
||||
LongTermFuelBank: 2,
|
||||
ThrottlePosition: 3,
|
||||
RelativeThrottlePosition: 4,
|
||||
Runtime: 5,
|
||||
DistanceWithMalfunctionLight: 6,
|
||||
EngineLoad: 7,
|
||||
MassFlowRate: 8,
|
||||
EngineFuelRate: 9,
|
||||
HasOBDData: true,
|
||||
HasSimulatedOBDData: false,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
Deleted: false,
|
||||
}
|
||||
|
||||
var expected = `DECLARE @tempReturn TABLE (TripPointId NVARCHAR(128));
|
||||
INSERT INTO TripPoints (
|
||||
[TripId],
|
||||
[Latitude],
|
||||
[Longitude],
|
||||
[Speed],
|
||||
[RecordedTimeStamp],
|
||||
[Sequence],
|
||||
[RPM],
|
||||
[ShortTermFuelBank],
|
||||
[LongTermFuelBank],
|
||||
[ThrottlePosition],
|
||||
[RelativeThrottlePosition],
|
||||
[Runtime],
|
||||
[DistanceWithMalfunctionLight],
|
||||
[EngineLoad],
|
||||
[EngineFuelRate],
|
||||
[MassFlowRate],
|
||||
[HasOBDData],
|
||||
[HasSimulatedOBDData],
|
||||
[VIN],
|
||||
[UpdatedAt],
|
||||
[Deleted])
|
||||
OUTPUT
|
||||
Inserted.ID
|
||||
INTO @tempReturn
|
||||
VALUES (
|
||||
'fake_trip_id',
|
||||
51.52443,
|
||||
-0.0784379,
|
||||
185.2,
|
||||
'a_timestamp',
|
||||
1,
|
||||
4000,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
'true',
|
||||
'false',
|
||||
'{ %!s(bool=false)}',
|
||||
GETDATE(),
|
||||
'false');
|
||||
SELECT TripPointId
|
||||
FROM @tempReturn`
|
||||
//act
|
||||
query := createTripPointQuery(tripPoint, "fake_trip_id")
|
||||
//assert
|
||||
assert.Equal(t, expected, query)
|
||||
}
|
203
apis/trips/tripsgo/routers.go
Normal file
203
apis/trips/tripsgo/routers.go
Normal file
@ -0,0 +1,203 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/codemodus/swagui"
|
||||
"github.com/codemodus/swagui/suidata3"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
var (
|
||||
du = flag.String("du", getEnv("DOCS_URI", "http://localhost:8080"), "docs endpoint")
|
||||
wsbu = flag.String("wsbu", getEnv("WEB_SERVER_BASE_URI", "changeme"), "base portion of server uri")
|
||||
)
|
||||
|
||||
// Route - object representing a route handler
|
||||
type Route struct {
|
||||
Name string
|
||||
Method string
|
||||
Pattern string
|
||||
HandlerFunc http.HandlerFunc
|
||||
}
|
||||
|
||||
// Routes - Route handler collection
|
||||
type Routes []Route
|
||||
|
||||
// NewRouter - Constructor
|
||||
func NewRouter() *mux.Router {
|
||||
router := mux.NewRouter().StrictSlash(true)
|
||||
for _, route := range routes {
|
||||
CreateHandler(router, route)
|
||||
}
|
||||
|
||||
// add docs route
|
||||
CreateDocsHandler(router, docsRoute)
|
||||
|
||||
return router
|
||||
}
|
||||
|
||||
// Index - Default route handler for service base uri
|
||||
func Index(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Trips Service")
|
||||
}
|
||||
|
||||
// CreateHandler - Create router handler
|
||||
func CreateHandler(router *mux.Router, route Route) {
|
||||
var handler http.Handler
|
||||
handler = route.HandlerFunc
|
||||
handler = Logger(handler, route.Name)
|
||||
|
||||
router.
|
||||
Methods(route.Method).
|
||||
Path(route.Pattern).
|
||||
Name(route.Name).
|
||||
Handler(handler)
|
||||
}
|
||||
|
||||
// CreateDocsHandler - Create route handler for docs using SwagUI
|
||||
func CreateDocsHandler(router *mux.Router, route Route) {
|
||||
var def = "/api/json/swagger.json"
|
||||
|
||||
var provider = suidata3.New()
|
||||
|
||||
ui, err := swagui.New(http.NotFoundHandler(), provider)
|
||||
if err != nil {
|
||||
Info.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
router.
|
||||
Methods(route.Method).
|
||||
Name(route.Name).
|
||||
Handler(ui.Handler(def))
|
||||
|
||||
router.
|
||||
Methods(route.Method).
|
||||
Path("/api/docs/trips/{dir}/{fileName}").
|
||||
Name("*").
|
||||
Handler(ui.Handler(def))
|
||||
|
||||
router.
|
||||
Methods(route.Method).
|
||||
Path("/api/docs/trips/{fileName}").
|
||||
Name("Swagger UI JS").
|
||||
Handler(ui.Handler(def))
|
||||
}
|
||||
|
||||
var docsRoute = Route{
|
||||
"swagger-ui",
|
||||
"GET",
|
||||
"/api/docs/trips/",
|
||||
nil,
|
||||
}
|
||||
|
||||
var routes = Routes{
|
||||
Route{
|
||||
"Index",
|
||||
"GET",
|
||||
"/api/",
|
||||
Index,
|
||||
},
|
||||
|
||||
Route{
|
||||
"swagger-json",
|
||||
"GET",
|
||||
"/api/json/swagger.json",
|
||||
swaggerDocsJSON,
|
||||
},
|
||||
|
||||
Route{
|
||||
"CreateTrip",
|
||||
"POST",
|
||||
"/api/trips",
|
||||
createTrip,
|
||||
},
|
||||
|
||||
Route{
|
||||
"CreateTripPoint",
|
||||
"POST",
|
||||
"/api/trips/{tripID}/trippoints",
|
||||
createTripPoint,
|
||||
},
|
||||
|
||||
Route{
|
||||
"DeleteTrip",
|
||||
"DELETE",
|
||||
"/api/trips/{tripID}",
|
||||
deleteTrip,
|
||||
},
|
||||
|
||||
Route{
|
||||
"DeleteTripPoint",
|
||||
"DELETE",
|
||||
"/api/trips/{tripID}/trippoints/{tripPointID}",
|
||||
deleteTripPoint,
|
||||
},
|
||||
|
||||
Route{
|
||||
"GetAllTrips",
|
||||
"GET",
|
||||
"/api/trips",
|
||||
getAllTrips,
|
||||
},
|
||||
|
||||
Route{
|
||||
"GetAllTripsForUser",
|
||||
"GET",
|
||||
"/api/trips/user/{userID}",
|
||||
getAllTripsForUser,
|
||||
},
|
||||
|
||||
Route{
|
||||
"GetTripById",
|
||||
"GET",
|
||||
"/api/trips/{tripID}",
|
||||
getTripByID,
|
||||
},
|
||||
|
||||
Route{
|
||||
"GetTripPointByID",
|
||||
"GET",
|
||||
"/api/trips/{tripID}/trippoints/{tripPointID}",
|
||||
getTripPointByID,
|
||||
},
|
||||
|
||||
Route{
|
||||
"GetTripPoints",
|
||||
"GET",
|
||||
"/api/trips/{tripID}/trippoints",
|
||||
getTripPoints,
|
||||
},
|
||||
|
||||
Route{
|
||||
"HealthcheckGet",
|
||||
"GET",
|
||||
"/api/healthcheck/trips",
|
||||
healthcheckGet,
|
||||
},
|
||||
|
||||
Route{
|
||||
"UpdateTrip",
|
||||
"PATCH",
|
||||
"/api/trips/{tripID}",
|
||||
updateTrip,
|
||||
},
|
||||
|
||||
Route{
|
||||
"UpdateTripPoint",
|
||||
"PATCH",
|
||||
"/api/trips/{tripID}/trippoints/{tripPointID}",
|
||||
updateTripPoint,
|
||||
},
|
||||
|
||||
Route{
|
||||
"VersionGet",
|
||||
"GET",
|
||||
"/api/version/trips",
|
||||
versionGet,
|
||||
},
|
||||
}
|
28
apis/trips/tripsgo/swaggerService.go
Normal file
28
apis/trips/tripsgo/swaggerService.go
Normal file
@ -0,0 +1,28 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func getSwaggerJsonPath() string {
|
||||
if value, ok := os.LookupEnv("SWAGGER_JSON_PATH"); ok {
|
||||
return value
|
||||
}
|
||||
return "./api/swagger.json"
|
||||
}
|
||||
|
||||
func swaggerDocsJSON(w http.ResponseWriter, r *http.Request) {
|
||||
swaggerPath := getSwaggerJsonPath()
|
||||
fData, err := os.Open(swaggerPath)
|
||||
if err != nil {
|
||||
var msg = fmt.Sprintf("swaggerDocsJson - Unable to open and read swagger.json : %v", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
Info.Println(msg)
|
||||
http.Error(w, msg, -1)
|
||||
return
|
||||
}
|
||||
http.ServeContent(w, r, "swagger.json", time.Now(), fData)
|
||||
}
|
49
apis/trips/tripsgo/swaggerService_test.go
Normal file
49
apis/trips/tripsgo/swaggerService_test.go
Normal file
@ -0,0 +1,49 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSwaggerServiceSuccessUnit(t *testing.T) {
|
||||
router := NewRouter()
|
||||
os.Setenv("SWAGGER_JSON_PATH", "../api/swagger.json")
|
||||
var debug, present = os.LookupEnv("DEBUG_LOGGING")
|
||||
|
||||
if present && debug == "true" {
|
||||
InitLogging(os.Stdout, os.Stdout, os.Stdout)
|
||||
} else {
|
||||
// if debug env is not present or false, do not log debug output to console
|
||||
InitLogging(os.Stdout, ioutil.Discard, os.Stdout)
|
||||
}
|
||||
RunAPITests(t, router, []APITestCase{
|
||||
{
|
||||
Tag: "swaggerService",
|
||||
Method: "GET",
|
||||
URL: "/api/json/swagger.json",
|
||||
Status: 200,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestSwaggerServiceFailUnit(t *testing.T) {
|
||||
router := NewRouter()
|
||||
os.Unsetenv("SWAGGER_JSON_PATH")
|
||||
var debug, present = os.LookupEnv("DEBUG_LOGGING")
|
||||
|
||||
if present && debug == "true" {
|
||||
InitLogging(os.Stdout, os.Stdout, os.Stdout)
|
||||
} else {
|
||||
// if debug env is not present or false, do not log debug output to console
|
||||
InitLogging(os.Stdout, ioutil.Discard, os.Stdout)
|
||||
}
|
||||
RunAPITestsPlainText(t, router, []APITestCase{
|
||||
{
|
||||
Tag: "swaggerService",
|
||||
Method: "GET",
|
||||
URL: "/api/json/swagger.json",
|
||||
Status: 500,
|
||||
},
|
||||
})
|
||||
}
|
66
apis/trips/tripsgo/test_util.go
Normal file
66
apis/trips/tripsgo/test_util.go
Normal file
@ -0,0 +1,66 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// APITestCase needs to be exported to be accessed for test dir
|
||||
type APITestCase struct {
|
||||
Tag string
|
||||
Method string
|
||||
URL string
|
||||
Body string
|
||||
Status int
|
||||
ExpectedResponse string
|
||||
ActualResponse string
|
||||
}
|
||||
|
||||
func testAPI(router *mux.Router, method, URL, body string) *httptest.ResponseRecorder {
|
||||
req, _ := http.NewRequest(method, URL, bytes.NewBufferString(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
res := httptest.NewRecorder()
|
||||
router.ServeHTTP(res, req)
|
||||
return res
|
||||
}
|
||||
|
||||
// RunAPITests needs to be exported to be accessed for test dir
|
||||
func RunAPITests(t *testing.T, router *mux.Router, tests []APITestCase) {
|
||||
for i := 0; i < len(tests); i++ {
|
||||
res := testAPI(router, tests[i].Method, tests[i].URL, tests[i].Body)
|
||||
tests[i].ActualResponse = res.Body.String()
|
||||
Debug.Println(tests[i].Tag + " - " + tests[i].ActualResponse)
|
||||
assert.Equal(t, tests[i].Status, res.Code, tests[i].Tag)
|
||||
Info.Println(tests[i].Tag + "- Response Code:" + strconv.Itoa(res.Code))
|
||||
if tests[i].ExpectedResponse != "" {
|
||||
assert.JSONEq(t, tests[i].ExpectedResponse, res.Body.String(), tests[i].Tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func RunAPITestsPlainText(t *testing.T, router *mux.Router, tests []APITestCase) {
|
||||
for i := 0; i < len(tests); i++ {
|
||||
res := testAPI(router, tests[i].Method, tests[i].URL, tests[i].Body)
|
||||
tests[i].ActualResponse = res.Body.String()
|
||||
Debug.Println(tests[i].Tag + " - " + tests[i].ActualResponse)
|
||||
assert.Equal(t, tests[i].Status, res.Code, tests[i].Tag)
|
||||
Info.Println(tests[i].Tag + "- Response Code:" + strconv.Itoa(res.Code))
|
||||
if tests[i].ExpectedResponse != "" {
|
||||
assert.Equal(t, tests[i].ExpectedResponse, res.Body.String(), tests[i].Tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func resetDataAccessEnvVars() {
|
||||
var fls bool = false
|
||||
debug = &fls
|
||||
godotenv.Overload()
|
||||
RebindDataAccessEnvironmentVariables()
|
||||
}
|
43
apis/trips/tripsgo/trip.go
Normal file
43
apis/trips/tripsgo/trip.go
Normal file
@ -0,0 +1,43 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Trip - Represents a single trip by a user with its associated set of trip points.
|
||||
type Trip struct {
|
||||
|
||||
// Trip ID
|
||||
ID string `json:"Id"`
|
||||
|
||||
Name string `json:"Name"`
|
||||
|
||||
// User's unique identity
|
||||
UserID string `json:"UserId"`
|
||||
|
||||
RecordedTimeStamp string `json:"RecordedTimeStamp"`
|
||||
|
||||
EndTimeStamp string `json:"EndTimeStamp"`
|
||||
|
||||
Rating int32 `json:"Rating"`
|
||||
|
||||
IsComplete bool `json:"IsComplete"`
|
||||
|
||||
HasSimulatedOBDData bool `json:"HasSimulatedOBDData"`
|
||||
|
||||
AverageSpeed float32 `json:"AverageSpeed"`
|
||||
|
||||
FuelUsed float32 `json:"FuelUsed"`
|
||||
|
||||
HardStops int64 `json:"HardStops"`
|
||||
|
||||
HardAccelerations int64 `json:"HardAccelerations"`
|
||||
|
||||
Distance float32 `json:"Distance"`
|
||||
|
||||
Created time.Time `json:"Created"`
|
||||
|
||||
UpdatedAt time.Time `json:"UpdatedAt"`
|
||||
|
||||
Deleted bool `json:"Deleted,omitempty"`
|
||||
}
|
258
apis/trips/tripsgo/tripPointService.go
Normal file
258
apis/trips/tripsgo/tripPointService.go
Normal file
@ -0,0 +1,258 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// TripPoint Service Methods
|
||||
|
||||
func getTripPoints(w http.ResponseWriter, r *http.Request) {
|
||||
params := mux.Vars(r)
|
||||
|
||||
var tripID = params["tripID"]
|
||||
|
||||
var query = selectTripPointsForTripQuery(tripID)
|
||||
|
||||
statement, err := ExecuteQuery(query)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error while retrieving trip points from database"
|
||||
logError(err, msg)
|
||||
fmt.Fprintf(w, SerializeError(err, msg))
|
||||
return
|
||||
}
|
||||
|
||||
tripPointRows := []TripPoint{}
|
||||
|
||||
for statement.Next() {
|
||||
var tp TripPoint
|
||||
err := statement.Scan(
|
||||
&tp.ID,
|
||||
&tp.TripID,
|
||||
&tp.Latitude,
|
||||
&tp.Longitude,
|
||||
&tp.Speed,
|
||||
&tp.RecordedTimeStamp,
|
||||
&tp.Sequence,
|
||||
&tp.RPM,
|
||||
&tp.ShortTermFuelBank,
|
||||
&tp.LongTermFuelBank,
|
||||
&tp.ThrottlePosition,
|
||||
&tp.RelativeThrottlePosition,
|
||||
&tp.Runtime,
|
||||
&tp.DistanceWithMalfunctionLight,
|
||||
&tp.EngineLoad,
|
||||
&tp.EngineFuelRate,
|
||||
&tp.VIN)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error scanning Trip Points"
|
||||
logError(err, msg)
|
||||
fmt.Fprintf(w, SerializeError(err, msg))
|
||||
return
|
||||
}
|
||||
|
||||
tripPointRows = append(tripPointRows, tp)
|
||||
}
|
||||
|
||||
serializedReturn, _ := json.Marshal(tripPointRows)
|
||||
|
||||
fmt.Fprintf(w, string(serializedReturn))
|
||||
}
|
||||
|
||||
func getTripPointByID(w http.ResponseWriter, r *http.Request) {
|
||||
params := mux.Vars(r)
|
||||
|
||||
tripPointID := params["tripPointID"]
|
||||
|
||||
var query = selectTripPointsForTripPointIDQuery(tripPointID)
|
||||
|
||||
row, err := FirstOrDefault(query)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error while retrieving trip point from database"
|
||||
logError(err, msg)
|
||||
fmt.Fprintf(w, SerializeError(err, msg))
|
||||
return
|
||||
}
|
||||
|
||||
var tripPoint TripPoint
|
||||
|
||||
err = row.Scan(
|
||||
&tripPoint.ID,
|
||||
&tripPoint.TripID,
|
||||
&tripPoint.Latitude,
|
||||
&tripPoint.Longitude,
|
||||
&tripPoint.Speed,
|
||||
&tripPoint.RecordedTimeStamp,
|
||||
&tripPoint.Sequence,
|
||||
&tripPoint.RPM,
|
||||
&tripPoint.ShortTermFuelBank,
|
||||
&tripPoint.LongTermFuelBank,
|
||||
&tripPoint.ThrottlePosition,
|
||||
&tripPoint.RelativeThrottlePosition,
|
||||
&tripPoint.Runtime,
|
||||
&tripPoint.DistanceWithMalfunctionLight,
|
||||
&tripPoint.EngineLoad,
|
||||
&tripPoint.EngineFuelRate,
|
||||
&tripPoint.VIN)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Failed to scan a trip point"
|
||||
logError(err, msg)
|
||||
fmt.Fprintf(w, SerializeError(err, msg))
|
||||
return
|
||||
}
|
||||
|
||||
serializedTripPoint, _ := json.Marshal(tripPoint)
|
||||
|
||||
fmt.Fprintf(w, string(serializedTripPoint))
|
||||
}
|
||||
|
||||
func createTripPoint(w http.ResponseWriter, r *http.Request) {
|
||||
params := mux.Vars(r)
|
||||
|
||||
tripID := params["tripID"]
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
|
||||
var tripPoint TripPoint
|
||||
|
||||
err = json.Unmarshal(body, &tripPoint)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error while decoding json for trip point"
|
||||
logError(err, msg)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprintf(w, SerializeError(err, msg))
|
||||
return
|
||||
}
|
||||
|
||||
var query = createTripPointQuery(tripPoint, tripID)
|
||||
|
||||
result, err := ExecuteQuery(query)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error while inserting Trip Point into database"
|
||||
logError(err, msg)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprintf(w, SerializeError(err, msg))
|
||||
return
|
||||
}
|
||||
|
||||
for result.Next() {
|
||||
err = result.Scan(&tripPoint.ID)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error retrieving trip point id"
|
||||
logError(err, msg)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprintf(w, SerializeError(err, msg))
|
||||
}
|
||||
}
|
||||
|
||||
serializedTripPoint, _ := json.Marshal(tripPoint)
|
||||
|
||||
fmt.Fprintf(w, string(serializedTripPoint))
|
||||
}
|
||||
|
||||
func updateTripPoint(w http.ResponseWriter, r *http.Request) {
|
||||
params := mux.Vars(r)
|
||||
|
||||
tripPointID := params["tripPointID"]
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
|
||||
defer r.Body.Close()
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error while decoding json for trip point"
|
||||
logError(err, msg)
|
||||
fmt.Fprintf(w, SerializeError(err, msg))
|
||||
return
|
||||
}
|
||||
|
||||
var tripPoint TripPoint
|
||||
|
||||
err = json.Unmarshal(body, &tripPoint)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error while decoding json"
|
||||
logError(err, msg)
|
||||
fmt.Fprintf(w, SerializeError(err, msg))
|
||||
return
|
||||
}
|
||||
|
||||
tripPoint.ID = tripPointID
|
||||
|
||||
var query = updateTripPointQuery(tripPoint)
|
||||
|
||||
result, err := ExecuteNonQuery(query)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error while patching Trip Point on the database"
|
||||
logError(err, msg)
|
||||
fmt.Fprintf(w, SerializeError(err, msg))
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, string(result))
|
||||
}
|
||||
|
||||
func deleteTripPoint(w http.ResponseWriter, r *http.Request) {
|
||||
params := mux.Vars(r)
|
||||
|
||||
tripPointID := params["tripPointID"]
|
||||
|
||||
var query = deleteTripPointQuery(tripPointID)
|
||||
|
||||
result, err := ExecuteNonQuery(query)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error while deleting trip point from database"
|
||||
logError(err, msg)
|
||||
fmt.Fprintf(w, SerializeError(err, msg))
|
||||
return
|
||||
}
|
||||
|
||||
serializedResult, _ := json.Marshal(result)
|
||||
|
||||
fmt.Fprintf(w, string(serializedResult))
|
||||
}
|
||||
|
||||
// func getMaxSequence(w http.ResponseWriter, r *http.Request) {
|
||||
// tripID := r.FormValue("id")
|
||||
|
||||
// query := fmt.Sprintf("SELECT MAX(Sequence) as MaxSequence FROM TripPoints where tripid = '%s'", tripID)
|
||||
|
||||
// row, err := FirstOrDefault(query)
|
||||
|
||||
// if err != nil {
|
||||
// var msg = "Error while querying Max Sequence"
|
||||
// logError(err, msg)
|
||||
// fmt.Fprintf(w, SerializeError(err, msg))
|
||||
// return
|
||||
// }
|
||||
|
||||
// var MaxSequence string
|
||||
|
||||
// err = row.Scan(&MaxSequence)
|
||||
|
||||
// if err != nil {
|
||||
// var msg = "Error while obtaining max sequence"
|
||||
// logError(err, msg)
|
||||
// fmt.Fprintf(w, SerializeError(err, msg))
|
||||
// return
|
||||
// }
|
||||
|
||||
// fmt.Fprintf(w, MaxSequence)
|
||||
// }
|
||||
|
||||
type newTripPoint struct {
|
||||
ID string
|
||||
}
|
295
apis/trips/tripsgo/tripService.go
Normal file
295
apis/trips/tripsgo/tripService.go
Normal file
@ -0,0 +1,295 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
_ "github.com/denisenkom/go-mssqldb" //vscode deletes this import if it is not a blank import
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// Trip Service Methods
|
||||
|
||||
// getTripByID - gets a trip by its trip id
|
||||
func getTripByID(w http.ResponseWriter, r *http.Request) {
|
||||
params := mux.Vars(r)
|
||||
|
||||
//Build Query
|
||||
var query = SelectTripByIDQuery(params["tripID"])
|
||||
|
||||
//Execute Query
|
||||
row, err := FirstOrDefault(query)
|
||||
|
||||
if err != nil {
|
||||
var msg = "getTripsByID - Error while retrieving trip from database"
|
||||
logError(err, msg)
|
||||
http.Error(w, SerializeError(err, msg), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var trip Trip
|
||||
|
||||
errScan := row.Scan(
|
||||
&trip.ID,
|
||||
&trip.Name,
|
||||
&trip.UserID,
|
||||
&trip.RecordedTimeStamp,
|
||||
&trip.EndTimeStamp,
|
||||
&trip.Rating,
|
||||
&trip.IsComplete,
|
||||
&trip.HasSimulatedOBDData,
|
||||
&trip.AverageSpeed,
|
||||
&trip.FuelUsed,
|
||||
&trip.HardStops,
|
||||
&trip.HardAccelerations,
|
||||
&trip.Distance,
|
||||
&trip.Created,
|
||||
&trip.UpdatedAt)
|
||||
|
||||
if errScan != nil {
|
||||
var msg = fmt.Sprintf("No trip with ID '%s' found", params["tripID"])
|
||||
logMessage(msg)
|
||||
// fmt.Fprintf(w, msg)
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
serializedTrip, _ := json.Marshal(trip)
|
||||
|
||||
fmt.Fprintf(w, string(serializedTrip))
|
||||
}
|
||||
|
||||
// getAllTrips - get all trips
|
||||
func getAllTrips(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var query = SelectAllTripsQuery()
|
||||
|
||||
tripRows, err := ExecuteQuery(query)
|
||||
|
||||
if err != nil {
|
||||
var msg = "getAllTrips - Query Failed to Execute."
|
||||
logError(err, msg)
|
||||
http.Error(w, SerializeError(err, msg), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
trips := []Trip{}
|
||||
|
||||
for tripRows.Next() {
|
||||
var r Trip
|
||||
err := tripRows.Scan(
|
||||
&r.ID,
|
||||
&r.Name,
|
||||
&r.UserID,
|
||||
&r.RecordedTimeStamp,
|
||||
&r.EndTimeStamp,
|
||||
&r.Rating,
|
||||
&r.IsComplete,
|
||||
&r.HasSimulatedOBDData,
|
||||
&r.AverageSpeed,
|
||||
&r.FuelUsed,
|
||||
&r.HardStops,
|
||||
&r.HardAccelerations,
|
||||
&r.Distance,
|
||||
&r.Created,
|
||||
&r.UpdatedAt)
|
||||
|
||||
if err != nil {
|
||||
var msg = "GetAllTrips - Error scanning Trips"
|
||||
logError(err, msg)
|
||||
http.Error(w, SerializeError(err, msg), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
trips = append(trips, r)
|
||||
}
|
||||
|
||||
tripsJSON, _ := json.Marshal(trips)
|
||||
|
||||
fmt.Fprintf(w, string(tripsJSON))
|
||||
}
|
||||
|
||||
// getAllTripsForUser - get all trips for a given user
|
||||
func getAllTripsForUser(w http.ResponseWriter, r *http.Request) {
|
||||
params := mux.Vars(r)
|
||||
|
||||
var query = SelectAllTripsForUserQuery(params["userID"])
|
||||
|
||||
tripRows, err := ExecuteQuery(query)
|
||||
|
||||
if err != nil {
|
||||
var msg = "getAllTripsForUser - Error while retrieving trips from database"
|
||||
logError(err, msg)
|
||||
http.Error(w, SerializeError(err, msg), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
trips := []Trip{}
|
||||
|
||||
for tripRows.Next() {
|
||||
var r Trip
|
||||
err := tripRows.Scan(&r.ID,
|
||||
&r.Name,
|
||||
&r.UserID,
|
||||
&r.RecordedTimeStamp,
|
||||
&r.EndTimeStamp,
|
||||
&r.Rating,
|
||||
&r.IsComplete,
|
||||
&r.HasSimulatedOBDData,
|
||||
&r.AverageSpeed,
|
||||
&r.FuelUsed,
|
||||
&r.HardStops,
|
||||
&r.HardAccelerations,
|
||||
&r.Distance,
|
||||
&r.Created,
|
||||
&r.UpdatedAt)
|
||||
|
||||
if err != nil {
|
||||
var msg = "getAllTripsForUser - Error scanning Trips"
|
||||
logError(err, msg)
|
||||
http.Error(w, SerializeError(err, msg), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
trips = append(trips, r)
|
||||
}
|
||||
|
||||
tripsJSON, _ := json.Marshal(trips)
|
||||
|
||||
fmt.Fprintf(w, string(tripsJSON))
|
||||
}
|
||||
|
||||
// deleteTrip - deletes a single trip and its associated trip points for a user
|
||||
func deleteTrip(w http.ResponseWriter, r *http.Request) {
|
||||
params := mux.Vars(r)
|
||||
|
||||
var deleteTripPointsQuery = DeleteTripPointsForTripQuery(params["tripID"])
|
||||
var deleteTripsQuery = DeleteTripQuery(params["tripID"])
|
||||
|
||||
result, err := ExecuteNonQuery(deleteTripPointsQuery)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error while deleting trip points from database"
|
||||
logError(err, msg)
|
||||
http.Error(w, SerializeError(err, msg), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Debug.Println(fmt.Sprintln(`Deleted trip points for Trip '%s'`, params["tripID"]))
|
||||
|
||||
result, err = ExecuteNonQuery(deleteTripsQuery)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error while deleting trip from database"
|
||||
logError(err, msg)
|
||||
http.Error(w, SerializeError(err, msg), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Debug.Println(fmt.Sprintln("Deleted trip '%s'", params["tripID"]))
|
||||
|
||||
serializedResult, _ := json.Marshal(result)
|
||||
|
||||
fmt.Fprintf(w, string(serializedResult))
|
||||
}
|
||||
|
||||
// updateTrip - update a trip
|
||||
func updateTrip(w http.ResponseWriter, r *http.Request) {
|
||||
params := mux.Vars(r)
|
||||
|
||||
tripID := params["tripID"]
|
||||
|
||||
var trip Trip
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
|
||||
defer r.Body.Close()
|
||||
|
||||
if err != nil {
|
||||
var msg = "Update Trip - Error reading trip request body"
|
||||
logError(err, msg)
|
||||
http.Error(w, SerializeError(err, msg), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(body, &trip)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Update Trip - Error while decoding trip json"
|
||||
logError(err, msg)
|
||||
http.Error(w, SerializeError(err, msg), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
trip.ID = tripID
|
||||
|
||||
updateQuery := UpdateTripQuery(trip)
|
||||
|
||||
result, err := ExecuteNonQuery(updateQuery)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error updating trip on the database." + string(result)
|
||||
logError(err, msg)
|
||||
http.Error(w, SerializeError(err, msg), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
serializedTrip, _ := json.Marshal(trip)
|
||||
|
||||
fmt.Fprintf(w, string(serializedTrip))
|
||||
}
|
||||
|
||||
// createTrip - create a trip for a user. This method does not create the associated trip points, only the trip.
|
||||
func createTrip(w http.ResponseWriter, r *http.Request) {
|
||||
//params := mux.Vars(r)
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
|
||||
var trip Trip
|
||||
|
||||
err = json.Unmarshal(body, &trip)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error while decoding json"
|
||||
logError(err, msg)
|
||||
http.Error(w, SerializeError(err, msg), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
insertQuery := createTripQuery(trip)
|
||||
|
||||
var newTripID newTrip
|
||||
|
||||
result, err := ExecuteQuery(insertQuery)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error while inserting trip into database"
|
||||
logError(err, msg)
|
||||
http.Error(w, SerializeError(err, msg), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
for result.Next() {
|
||||
err = result.Scan(&newTripID.ID)
|
||||
|
||||
if err != nil {
|
||||
var msg = "Error while retrieving last id"
|
||||
logError(err, msg)
|
||||
http.Error(w, SerializeError(err, msg), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
trip.ID = newTripID.ID
|
||||
|
||||
serializedTrip, _ := json.Marshal(trip)
|
||||
|
||||
fmt.Fprintf(w, string(serializedTrip))
|
||||
}
|
||||
|
||||
type newTrip struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
// End of Trip Service Methods
|
436
apis/trips/tripsgo/tripService_test.go
Normal file
436
apis/trips/tripsgo/tripService_test.go
Normal file
@ -0,0 +1,436 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var tripID string
|
||||
|
||||
var apiTestList = []APITestCase{
|
||||
{
|
||||
Tag: "t1 - Get all trips",
|
||||
Method: "GET",
|
||||
URL: "/api/trips",
|
||||
Status: 200,
|
||||
},
|
||||
{
|
||||
Tag: "t2 - Get a nonexistent trip",
|
||||
Method: "GET",
|
||||
URL: "/api/trips/99999",
|
||||
Status: 404,
|
||||
},
|
||||
{
|
||||
Tag: "t3 - Create a Trip",
|
||||
Method: "POST",
|
||||
URL: "/api/trips",
|
||||
Body: `{
|
||||
"Name":"Trip CREATE TEST",
|
||||
"UserId":"GO_TEST",
|
||||
"RecordedTimeStamp": "2018-04-19T19:08:16.03Z",
|
||||
"EndTimeStamp": "2018-04-19T19:42:49.573Z",
|
||||
"Rating":95,
|
||||
"IsComplete":false,
|
||||
"HasSimulatedOBDData":true,
|
||||
"AverageSpeed":100,
|
||||
"FuelUsed":10.27193484,
|
||||
"HardStops":2,
|
||||
"HardAccelerations":4,
|
||||
"Distance":30.0275486,
|
||||
"CreatedAt":"2018-01-01T12:00:00Z",
|
||||
"UpdatedAt":"2001-01-01T12:00:00Z"
|
||||
}`,
|
||||
Status: 200,
|
||||
},
|
||||
{
|
||||
Tag: "t4 - Update a trip",
|
||||
Method: "PATCH",
|
||||
URL: "/api/trips/{tripID}",
|
||||
Body: `{
|
||||
"Name":"Trip UPDATE TEST",
|
||||
"UserId":"GO_TEST",
|
||||
"RecordedTimeStamp": "2018-04-19T19:08:16.03Z",
|
||||
"EndTimeStamp": "2018-04-19T19:42:49.573Z",
|
||||
"Rating":91005,
|
||||
"IsComplete":true,
|
||||
"HasSimulatedOBDData":true,
|
||||
"AverageSpeed":100,
|
||||
"FuelUsed":10.27193484,
|
||||
"HardStops":2,
|
||||
"HardAccelerations":4,
|
||||
"Distance":30.0275486,
|
||||
"CreatedAt":"2018-01-01T12:00:00Z",
|
||||
"UpdatedAt":"2001-01-01T12:00:00Z"
|
||||
}`,
|
||||
Status: 200,
|
||||
},
|
||||
{
|
||||
Tag: "t5 - Create Trip Point",
|
||||
Method: "POST",
|
||||
URL: "/api/trips/{tripID}/trippoints",
|
||||
Body: `{
|
||||
"TripId": "{tripID}",
|
||||
"Latitude": 47.67598,
|
||||
"Longitude": -122.10612,
|
||||
"Speed": -255,
|
||||
"RecordedTimeStamp": "2018-05-24T10:00:15.003Z",
|
||||
"Sequence": 2,
|
||||
"RPM": -255,
|
||||
"ShortTermFuelBank": -255,
|
||||
"LongTermFuelBank": -255,
|
||||
"ThrottlePosition": -255,
|
||||
"RelativeThrottlePosition": -255,
|
||||
"Runtime": -255,
|
||||
"DistanceWithMalfunctionLight": -255,
|
||||
"EngineLoad": -255,
|
||||
"EngineFuelRate": -255,
|
||||
"CreatedAt": "0001-01-01T00:00:00Z",
|
||||
"UpdatedAt": "0001-01-01T00:00:00Z"
|
||||
}`,
|
||||
Status: 200,
|
||||
},
|
||||
{
|
||||
Tag: "t6 - Update Trip Point",
|
||||
Method: "PATCH",
|
||||
URL: "/api/trips/{tripID}/trippoints/{tripPointID}",
|
||||
Body: `{
|
||||
"Id": "{tripPointID}",
|
||||
"TripId": "{tripID}",
|
||||
"Latitude": 47.67598,
|
||||
"Longitude": -122.10612,
|
||||
"Speed": -255,
|
||||
"RecordedTimeStamp": "2018-05-24T10:00:15.003Z",
|
||||
"Sequence": 2,
|
||||
"RPM": -255,
|
||||
"ShortTermFuelBank": -255,
|
||||
"LongTermFuelBank": -255,
|
||||
"ThrottlePosition": -255,
|
||||
"RelativeThrottlePosition": -255,
|
||||
"Runtime": -255,
|
||||
"DistanceWithMalfunctionLight": -255,
|
||||
"EngineLoad": -255,
|
||||
"EngineFuelRate": -255,
|
||||
"Created": "0001-01-01T00:00:00Z",
|
||||
"UpdatedAt": "0001-01-01T00:00:00Z"
|
||||
}`,
|
||||
ExpectedResponse: "",
|
||||
Status: 200,
|
||||
},
|
||||
{
|
||||
Tag: "t7 - Read Trip Points for Trip",
|
||||
Method: "GET",
|
||||
URL: "/api/trips/{tripID}/trippoints",
|
||||
Status: 200,
|
||||
},
|
||||
{
|
||||
Tag: "t8 - Read Trip Points By Trip Point ID",
|
||||
Method: "GET",
|
||||
URL: "/api/trips/{tripID}/trippoints/{tripPointID}",
|
||||
Status: 200,
|
||||
},
|
||||
{
|
||||
Tag: "t9 - Delete Trip Point",
|
||||
Method: "DELETE",
|
||||
URL: "/api/trips/{tripID}/trippoints/{tripPointID}",
|
||||
Status: 200,
|
||||
},
|
||||
{
|
||||
Tag: "t10 - Delete a Trip",
|
||||
Method: "DELETE",
|
||||
URL: "/api/trips/{tripID}",
|
||||
Status: 200,
|
||||
},
|
||||
{
|
||||
Tag: "t11 - Get All Trips for User",
|
||||
Method: "GET",
|
||||
URL: "/api/trips/user/SomeUser",
|
||||
Status: 200,
|
||||
},
|
||||
}
|
||||
|
||||
func TestTripApis(t *testing.T) {
|
||||
router := NewRouter()
|
||||
var debug, present = os.LookupEnv("DEBUG_LOGGING")
|
||||
|
||||
if present && debug == "true" {
|
||||
InitLogging(os.Stdout, os.Stdout, os.Stdout)
|
||||
} else {
|
||||
// if debug env is not present or false, do not log debug output to console
|
||||
InitLogging(os.Stdout, ioutil.Discard, os.Stdout)
|
||||
}
|
||||
RunAPITests(t, router, apiTestList[0:3])
|
||||
|
||||
// setup update trip test (URL, Body, expected Response)
|
||||
apiTestList[3].URL = strings.Replace(apiTestList[3].URL, "{tripID}", TripFromStr(apiTestList[2].ActualResponse).ID, 1)
|
||||
apiTestList[3].Body = GetUpdateTrip(apiTestList[2].ActualResponse, apiTestList[3].Body)
|
||||
apiTestList[3].ExpectedResponse = apiTestList[3].Body
|
||||
|
||||
// setup create trip point test
|
||||
apiTestList[4].URL = strings.Replace(apiTestList[4].URL, "{tripID}", TripFromStr(apiTestList[2].ActualResponse).ID, 1)
|
||||
apiTestList[4].Body = strings.Replace(apiTestList[4].Body, "{tripID}", TripFromStr(apiTestList[2].ActualResponse).ID, 1)
|
||||
|
||||
// run update trip and create trip point tests
|
||||
RunAPITests(t, router, apiTestList[3:5])
|
||||
|
||||
// setup update trip point test
|
||||
apiTestList[5].URL = strings.Replace(apiTestList[5].URL, "{tripID}", TripFromStr(apiTestList[2].ActualResponse).ID, 1)
|
||||
apiTestList[5].URL = strings.Replace(apiTestList[5].URL, "{tripPointID}", TripPointFromStr(apiTestList[4].ActualResponse).ID, 1)
|
||||
apiTestList[5].Body = GetUpdateTripPoint(apiTestList[4].ActualResponse, apiTestList[5].Body)
|
||||
|
||||
// setup read trip points for trip test
|
||||
apiTestList[6].URL = strings.Replace(apiTestList[6].URL, "{tripID}", TripFromStr(apiTestList[2].ActualResponse).ID, 1)
|
||||
|
||||
// // setup ready trip points by trip point id test
|
||||
apiTestList[7].URL = strings.Replace(apiTestList[7].URL, "{tripID}", TripFromStr(apiTestList[2].ActualResponse).ID, 1)
|
||||
apiTestList[7].URL = strings.Replace(apiTestList[7].URL, "{tripPointID}", TripPointFromStr(apiTestList[4].ActualResponse).ID, 1)
|
||||
|
||||
// //setup delete trip point test
|
||||
apiTestList[8].URL = strings.Replace(apiTestList[8].URL, "{tripID}", TripFromStr(apiTestList[2].ActualResponse).ID, 1)
|
||||
apiTestList[8].URL = strings.Replace(apiTestList[8].URL, "{tripPointID}", TripPointFromStr(apiTestList[4].ActualResponse).ID, 1)
|
||||
|
||||
// setup delete test (URL)
|
||||
apiTestList[9].URL = strings.Replace(apiTestList[9].URL, "{tripID}", TripFromStr(apiTestList[2].ActualResponse).ID, 1)
|
||||
// run update test
|
||||
RunAPITests(t, router, apiTestList[5:10])
|
||||
|
||||
RunAPITests(t, router, apiTestList[10:11])
|
||||
}
|
||||
|
||||
func TestGetAllTripsReturnsServerErrorIfBadDbConnection(t *testing.T) {
|
||||
defer t.Cleanup(resetDataAccessEnvVars)
|
||||
|
||||
//arrange
|
||||
os.Setenv("SQL_DRIVER", "not_a_real_driver")
|
||||
RebindDataAccessEnvironmentVariables()
|
||||
info := new(bytes.Buffer)
|
||||
InitLogging(info, os.Stdout, os.Stdout)
|
||||
var tr bool = true
|
||||
debug = &tr
|
||||
|
||||
//act
|
||||
router := NewRouter()
|
||||
RunAPITestsPlainText(t, router, []APITestCase{
|
||||
{
|
||||
Tag: "t1 - Get all trips",
|
||||
Method: "GET",
|
||||
URL: "/api/trips",
|
||||
Status: 500,
|
||||
},
|
||||
})
|
||||
|
||||
//assert
|
||||
actual := fmt.Sprint(info)
|
||||
assert.Contains(t, actual, "getAllTrips - Query Failed to Execute")
|
||||
}
|
||||
|
||||
func TestGetAllTripsReturnsErrorScanningTripsIfMissingSqlFields(t *testing.T) {
|
||||
defer t.Cleanup(resetDataAccessEnvVars)
|
||||
|
||||
//arrange
|
||||
//oldSelectAllTripsQuery := func(SelectAllTripsQuery)
|
||||
var OldSelectAllTripsQuery = SelectAllTripsQuery
|
||||
SelectAllTripsQuery = func() string {
|
||||
return `SELECT
|
||||
Id
|
||||
FROM Trips
|
||||
WHERE Deleted = 0`
|
||||
}
|
||||
defer func() { SelectAllTripsQuery = OldSelectAllTripsQuery }()
|
||||
|
||||
info := new(bytes.Buffer)
|
||||
InitLogging(info, os.Stdout, os.Stdout)
|
||||
var tr bool = true
|
||||
debug = &tr
|
||||
|
||||
//act
|
||||
router := NewRouter()
|
||||
RunAPITestsPlainText(t, router, []APITestCase{
|
||||
{
|
||||
Tag: "t1 - Get all trips",
|
||||
Method: "GET",
|
||||
URL: "/api/trips",
|
||||
Status: 500,
|
||||
},
|
||||
})
|
||||
|
||||
//assert
|
||||
actual := fmt.Sprint(info)
|
||||
assert.Contains(t, actual, "GetAllTrips - Error scanning Trips")
|
||||
}
|
||||
|
||||
func TestGetAllTripsForUsersReturnsServerErrorIfBadDbConnection(t *testing.T) {
|
||||
defer t.Cleanup(resetDataAccessEnvVars)
|
||||
|
||||
//arrange
|
||||
os.Setenv("SQL_DRIVER", "not_a_real_driver")
|
||||
RebindDataAccessEnvironmentVariables()
|
||||
info := new(bytes.Buffer)
|
||||
InitLogging(info, os.Stdout, os.Stdout)
|
||||
var tr bool = true
|
||||
debug = &tr
|
||||
|
||||
//act
|
||||
router := NewRouter()
|
||||
RunAPITestsPlainText(t, router, []APITestCase{
|
||||
{
|
||||
Tag: "t11 - Get All Trips for User",
|
||||
Method: "GET",
|
||||
URL: "/api/trips/user/SomeUser",
|
||||
Status: 500,
|
||||
},
|
||||
})
|
||||
|
||||
//assert
|
||||
actual := fmt.Sprint(info)
|
||||
assert.Contains(t, actual, "getAllTripsForUser - Error while retrieving trips from database")
|
||||
}
|
||||
|
||||
func TestGetAllTripsForUserReturnsErrorScanningTripsIfMissingSqlFields(t *testing.T) {
|
||||
defer t.Cleanup(resetDataAccessEnvVars)
|
||||
|
||||
//arrange
|
||||
//oldSelectAllTripsQuery := func(SelectAllTripsQuery)
|
||||
var OldSelectAllTripsForUserQuery = SelectAllTripsForUserQuery
|
||||
SelectAllTripsForUserQuery = func(userID string) string {
|
||||
return `SELECT
|
||||
Id
|
||||
FROM Trips
|
||||
WHERE UserId ='` + userID + `'
|
||||
AND Deleted = 0`
|
||||
}
|
||||
defer func() { SelectAllTripsForUserQuery = OldSelectAllTripsForUserQuery }()
|
||||
|
||||
info := new(bytes.Buffer)
|
||||
InitLogging(info, os.Stdout, os.Stdout)
|
||||
var tr bool = true
|
||||
debug = &tr
|
||||
|
||||
//act
|
||||
router := NewRouter()
|
||||
RunAPITestsPlainText(t, router, []APITestCase{
|
||||
{
|
||||
Tag: "t11 - Get All Trips for User",
|
||||
Method: "GET",
|
||||
URL: "/api/trips/user/SomeUser",
|
||||
Status: 500,
|
||||
},
|
||||
})
|
||||
|
||||
//assert
|
||||
actual := fmt.Sprint(info)
|
||||
assert.Contains(t, actual, "getAllTripsForUser - Error scanning Trips")
|
||||
}
|
||||
|
||||
func TestCreateTripReturnsErrorifInvalidJsonBody(t *testing.T) {
|
||||
info := new(bytes.Buffer)
|
||||
InitLogging(info, os.Stdout, os.Stdout)
|
||||
|
||||
//act
|
||||
router := NewRouter()
|
||||
RunAPITestsPlainText(t, router, []APITestCase{
|
||||
{
|
||||
Tag: "t3 - Create a Trip",
|
||||
Method: "POST",
|
||||
URL: "/api/trips",
|
||||
Body: `{
|
||||
"Name":"Trip CREATE TEST",
|
||||
"UserId":"GO_TEST",
|
||||
"RecordedTimeStamp": "2018-04-19T19:08:16.03Z",
|
||||
"EndTimeStamp": "2018-04-19T19:42:49.573Z",
|
||||
"Rating":95,
|
||||
"IsComplete":`,
|
||||
Status: 500,
|
||||
},
|
||||
})
|
||||
|
||||
//assert
|
||||
actual := fmt.Sprint(info)
|
||||
assert.Contains(t, actual, "Error while decoding json")
|
||||
}
|
||||
|
||||
func TestUpdateTripReturnsErrorifInvalidJsonBody(t *testing.T) {
|
||||
info := new(bytes.Buffer)
|
||||
InitLogging(info, os.Stdout, os.Stdout)
|
||||
|
||||
//act
|
||||
router := NewRouter()
|
||||
RunAPITestsPlainText(t, router, []APITestCase{
|
||||
{
|
||||
Tag: "t4 - Update a trip",
|
||||
Method: "PATCH",
|
||||
URL: "/api/trips/{tripID}",
|
||||
Body: `{
|
||||
"Name":"Trip UPDATE TEST",
|
||||
"UserId":"GO_TEST",
|
||||
"RecordedTimeStamp": "2018-04-19T19:08:16.03Z",
|
||||
"EndTimeStamp": "2018-04-19T19:42:49.573Z",
|
||||
"Rating":`,
|
||||
Status: 500,
|
||||
},
|
||||
})
|
||||
|
||||
//assert
|
||||
actual := fmt.Sprint(info)
|
||||
assert.Contains(t, actual, "Update Trip - Error while decoding trip json")
|
||||
}
|
||||
|
||||
func GetUpdateTrip(tripCreate string, tripUpdate string) string {
|
||||
tripC := TripFromStr(tripCreate)
|
||||
tripU := TripFromStr(tripUpdate)
|
||||
|
||||
tripU.ID = tripC.ID
|
||||
|
||||
serializedTripUpdate, _ := json.Marshal(tripU)
|
||||
|
||||
return string(serializedTripUpdate)
|
||||
}
|
||||
|
||||
func GetUpdateTripPoint(tripPointCreate string, tripPointUpdate string) string {
|
||||
tripPointC := TripPointFromStr(tripPointCreate)
|
||||
tripPointU := TripPointFromStr(tripPointUpdate)
|
||||
|
||||
tripPointU.ID = tripPointC.ID
|
||||
tripPointU.TripID = tripPointC.TripID
|
||||
|
||||
serializedTripUpdate, _ := json.Marshal(tripPointU)
|
||||
|
||||
return string(serializedTripUpdate)
|
||||
}
|
||||
|
||||
func TripFromStr(tripStr string) Trip {
|
||||
trip := Trip{}
|
||||
|
||||
Debug.Println("DEBUG: TripFromStr - " + tripStr)
|
||||
|
||||
errCreate := json.Unmarshal([]byte(tripStr), &trip)
|
||||
if errCreate != nil {
|
||||
log.Println("TripFromStr - Invalid trip string")
|
||||
log.Fatal(errCreate)
|
||||
}
|
||||
|
||||
return trip
|
||||
}
|
||||
|
||||
func TripPointFromStr(tripPointStr string) TripPoint {
|
||||
tripPoint := TripPoint{}
|
||||
|
||||
Debug.Println("DEBUG: TripPointFromStr - " + tripPointStr)
|
||||
|
||||
errCreate := json.Unmarshal([]byte(tripPointStr), &tripPoint)
|
||||
if errCreate != nil {
|
||||
log.Println("TripPointFromStr - Invalid trip point string")
|
||||
log.Fatal(errCreate)
|
||||
}
|
||||
|
||||
Debug.Println(tripPointStr)
|
||||
|
||||
return tripPoint
|
||||
}
|
58
apis/trips/tripsgo/trip_point.go
Normal file
58
apis/trips/tripsgo/trip_point.go
Normal file
@ -0,0 +1,58 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TripPoint - Represents a single point record in a trip
|
||||
type TripPoint struct {
|
||||
|
||||
// Trip Point ID
|
||||
ID string `json:"Id,omitempty"`
|
||||
|
||||
// Trip ID
|
||||
TripID string `json:"TripId,omitempty"`
|
||||
|
||||
Latitude float32 `json:"Latitude,omitempty"`
|
||||
|
||||
Longitude float32 `json:"Longitude,omitempty"`
|
||||
|
||||
Speed float32 `json:"Speed,omitempty"`
|
||||
|
||||
RecordedTimeStamp string `json:"RecordedTimeStamp,omitempty"`
|
||||
|
||||
Sequence int32 `json:"Sequence,omitempty"`
|
||||
|
||||
RPM float32 `json:"RPM,omitempty"`
|
||||
|
||||
ShortTermFuelBank float32 `json:"ShortTermFuelBank,omitempty"`
|
||||
|
||||
LongTermFuelBank float32 `json:"LongTermFuelBank,omitempty"`
|
||||
|
||||
ThrottlePosition float32 `json:"ThrottlePosition,omitempty"`
|
||||
|
||||
RelativeThrottlePosition float32 `json:"RelativeThrottlePosition,omitempty"`
|
||||
|
||||
Runtime float32 `json:"Runtime,omitempty"`
|
||||
|
||||
DistanceWithMalfunctionLight float32 `json:"DistanceWithMalfunctionLight,omitempty"`
|
||||
|
||||
EngineLoad float32 `json:"EngineLoad,omitempty"`
|
||||
|
||||
MassFlowRate float32 `json:"MassFlowRate,omitempty"`
|
||||
|
||||
EngineFuelRate float32 `json:"EngineFuelRate,omitempty"`
|
||||
|
||||
VIN sql.NullString `json:"VIN,omitempty"`
|
||||
|
||||
HasOBDData bool `json:"HasOBDData,omitempty"`
|
||||
|
||||
HasSimulatedOBDData bool `json:"HasSimulatedOBDData,omitempty"`
|
||||
|
||||
CreatedAt time.Time `json:"CreatedAt,omitempty"`
|
||||
|
||||
UpdatedAt time.Time `json:"UpdatedAt,omitempty"`
|
||||
|
||||
Deleted bool `json:"Deleted,omitempty"`
|
||||
}
|
15
apis/trips/tripsgo/versionService.go
Normal file
15
apis/trips/tripsgo/versionService.go
Normal file
@ -0,0 +1,15 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
func versionGet(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
version := os.Getenv("APP_VERSION")
|
||||
fmt.Fprintf(w, version)
|
||||
}
|
32
apis/trips/tripsgo/versionService_test.go
Normal file
32
apis/trips/tripsgo/versionService_test.go
Normal file
@ -0,0 +1,32 @@
|
||||
package tripsgo
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var versionRouteTests = []APITestCase{
|
||||
{
|
||||
Tag: "versionService",
|
||||
Method: "GET",
|
||||
URL: "/api/version/trips",
|
||||
Status: 200,
|
||||
ExpectedResponse: `test123`,
|
||||
},
|
||||
}
|
||||
|
||||
func TestVersionServiceUnit(t *testing.T) {
|
||||
router := NewRouter()
|
||||
os.Setenv("APP_VERSION", "test123")
|
||||
var debug, present = os.LookupEnv("DEBUG_LOGGING")
|
||||
|
||||
if present && debug == "true" {
|
||||
InitLogging(os.Stdout, os.Stdout, os.Stdout)
|
||||
} else {
|
||||
// if debug env is not present or false, do not log debug output to console
|
||||
InitLogging(os.Stdout, ioutil.Discard, os.Stdout)
|
||||
}
|
||||
RunAPITestsPlainText(t, router, versionRouteTests[0:1])
|
||||
|
||||
}
|
Reference in New Issue
Block a user