Loading go-packages/meep-postgis/db.go +440 −30 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import ( "strings" log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger" "github.com/lib/pq" _ "github.com/lib/pq" ) Loading @@ -34,6 +36,48 @@ const ( ) const dbMaxRetryCount int = 2 const ( PathModeLoop = "LOOP" PathModeReverse = "REVERSE" PathModeOnce = "ONCE" ) const ( UeTable = "ue" PoaTable = "poa" ComputeTable = "compute" ) type Ue struct { Id string Name string Position string Path string PathMode string PathVelocity float32 PathLength float32 PathIncrement float32 PathFraction float32 Poa string PoaDistance float32 PoaInRange []string } type Poa struct { Id string Name string SubType string Position string Radius float32 } type Compute struct { Id string Name string SubType string Position string } // Connector - Implements a Postgis SQL DB connector type Connector struct { name string Loading Loading @@ -78,7 +122,7 @@ func NewConnector(name, namespace, user, pwd, host, port string) (pc *Connector, // Ignore DB creation error in case it already exists. // Failure will occur at DB connection if DB was not successfully created. _ = pc.DbCreate(pc.dbName) _ = pc.CreateDb(pc.dbName) // Close connection to postgis DB pc.db.Close() Loading Loading @@ -128,8 +172,8 @@ func (pc *Connector) connectDB(dbName, user, pwd, host, port string) (db *sql.DB return db, nil } // DbCreate -- Create new DB with provided name func (pc *Connector) DbCreate(name string) (err error) { // CreateDb -- Create new DB with provided name func (pc *Connector) CreateDb(name string) (err error) { _, err = pc.db.Exec("CREATE DATABASE " + name) if err != nil { log.Error(err.Error()) Loading @@ -140,37 +184,403 @@ func (pc *Connector) DbCreate(name string) (err error) { return nil } // func DbDeleteTable(tableName string) (err error) { // _, err = db.Exec("DROP TABLE IF EXISTS " + tableName) // if err != nil { // log.Error(err.Error()) // return err // } // log.Info("Deleted table: " + tableName) // return nil // } func (pc *Connector) CreateTables() (err error) { _, err = pc.db.Exec("CREATE EXTENSION IF NOT EXISTS postgis") if err != nil { log.Error(err.Error()) return err } // func DbCreatePoaTable(tableName string) (err error) { // _, err = db.Exec("CREATE EXTENSION IF NOT EXISTS postgis") // if err != nil { // log.Error(err.Error()) // return err // } // UE Table _, err = pc.db.Exec(`CREATE TABLE ` + UeTable + ` ( id varchar(36) NOT NULL PRIMARY KEY, name varchar(100) NOT NULL UNIQUE, position geometry(POINT,4326) NOT NULL, path geometry(LINESTRING,4326), path_mode varchar(20) NOT NULL DEFAULT 'LOOP', path_velocity decimal(10,3) NOT NULL DEFAULT '0.000', path_length decimal(10,3) NOT NULL DEFAULT '0.000', path_increment decimal(10,3) NOT NULL DEFAULT '0.000', path_fraction decimal(10,3) NOT NULL DEFAULT '0.000', poa varchar(100) NOT NULL DEFAULT '', poa_distance decimal(10,6) NOT NULL DEFAULT '0.000000', poa_in_range varchar(100)[] NOT NULL DEFAULT array[]::varchar[], start_time timestamptz NOT NULL DEFAULT now() )`) if err != nil { log.Error(err.Error()) return err } log.Info("Created UE table: ", UeTable) // POA Table _, err = pc.db.Exec(`CREATE TABLE ` + PoaTable + ` ( id varchar(36) NOT NULL PRIMARY KEY, name varchar(100) NOT NULL UNIQUE, type varchar(20) NOT NULL DEFAULT '', radius decimal(10,1) NOT NULL DEFAULT '0.0', position geometry(POINT,4326) NOT NULL )`) if err != nil { log.Error(err.Error()) return err } log.Info("Created POA table: ", PoaTable) // Compute Table _, err = pc.db.Exec(`CREATE TABLE ` + ComputeTable + ` ( id varchar(36) NOT NULL PRIMARY KEY, name varchar(100) NOT NULL UNIQUE, type varchar(20) NOT NULL DEFAULT '', position geometry(POINT,4326) NOT NULL )`) if err != nil { log.Error(err.Error()) return err } log.Info("Created Edge table: ", ComputeTable) // _, err = db.Exec(`CREATE TABLE ` + tableName + ` ( // id varchar(36) NOT NULL PRIMARY KEY, // name varchar(100) NOT NULL UNIQUE, // lat decimal(10,6) NOT NULL DEFAULT '0.000000', // long decimal(10,6) NOT NULL DEFAULT '0.000000', // alt decimal(10,1) NOT NULL DEFAULT '0.0', // radius decimal(10,1) NOT NULL DEFAULT '0.0', // position geometry(POINTZ,4326) // )`) return nil } func (pc *Connector) DeleteTable(tableName string) (err error) { _, err = pc.db.Exec("DROP TABLE IF EXISTS " + tableName) if err != nil { log.Error(err.Error()) return err } log.Info("Deleted table: " + tableName) return nil } // func (pc *Connector) AssetExists(name string, assetType AssetType) (exists bool) { // count := 0 // rows, err := pc.db.Query(`select count(*) from `+getTableName(assetType)+` where name = ($1)`, name) // if err != nil { // log.Error(err.Error()) // return err // return false // } // defer rows.Close() // log.Info("Created table: ", tableName) // return nil // // Scan results // for rows.Next() { // err = rows.Scan(&count) // } // exists = (count != 0) // return exists // } // CreateUe - Create new UE func (pc *Connector) CreateUe(id string, name string, position string, path string, mode string, velocity float32) (err error) { // Validate input if id == "" { return errors.New("Missing ID") } if name == "" { return errors.New("Missing Name") } if position == "" { return errors.New("Missing Position") } if path != "" { // Validate Path parameters if mode == "" { return errors.New("Missing Path Mode") } // Create UE entry with path query := `INSERT INTO ` + UeTable + ` (id, name, position, path, path_mode, path_velocity) VALUES ($1, $2, ST_GeomFromGeoJSON('` + position + `'), ST_GeomFromGeoJSON('` + path + `'), $3, $4)` _, err = pc.db.Exec(query, id, name, mode, velocity) if err != nil { log.Error(err.Error()) return err } // Calculate UE path length & increment err = pc.refreshUePath(name) if err != nil { log.Error(err.Error()) return err } } else { // Create UE entry without path query := `INSERT INTO ` + UeTable + ` (id, name, position) VALUES ($1, $2, ST_GeomFromGeoJSON('` + position + `'))` _, err = pc.db.Exec(query, id, name) if err != nil { log.Error(err.Error()) return err } } // Refresh UE POA information err = pc.refreshUePoa(name) if err != nil { log.Error(err.Error()) return err } return nil } // CreatePoa - Create new POA func (pc *Connector) CreatePoa(id string, name string, subType string, position string, radius float32) (err error) { // Validate input if id == "" { return errors.New("Missing ID") } if name == "" { return errors.New("Missing Name") } if subType == "" { return errors.New("Missing Type") } if position == "" { return errors.New("Missing Position") } // Create POA entry query := `INSERT INTO ` + PoaTable + ` (id, name, type, position, radius) VALUES ($1, $2, $3, ST_GeomFromGeoJSON('` + position + `'), $4)` _, err = pc.db.Exec(query, id, name, subType, radius) if err != nil { log.Error(err.Error()) return err } return nil } // CreateCompute - Create new Compute func (pc *Connector) CreateCompute(id string, name string, subType string, position string) (err error) { // Validate input if id == "" { return errors.New("Missing ID") } if name == "" { return errors.New("Missing Name") } if subType == "" { return errors.New("Missing Type") } if position == "" { return errors.New("Missing Position") } // Create Compute entry query := `INSERT INTO ` + ComputeTable + ` (id, name, type, position) VALUES ($1, $2, $3, ST_GeomFromGeoJSON('` + position + `'))` _, err = pc.db.Exec(query, id, name, subType) if err != nil { log.Error(err.Error()) return err } return nil } // GetUe - Get UE information func (pc *Connector) GetUe(name string) (ue *Ue, err error) { // Validate input if name == "" { err = errors.New("Missing Name") return nil, err } // Get UE entry var rows *sql.Rows rows, err = pc.db.Query(` SELECT id, name, ST_AsGeoJSON(position), ST_AsGeoJSON(path), path_mode, path_velocity, path_length, path_increment, path_fraction, poa, poa_distance, poa_in_range FROM `+UeTable+` WHERE name = ($1)`, name) if err != nil { log.Error(err.Error()) return nil, err } defer rows.Close() ue = new(Ue) path := new(string) // Scan result rows.Next() err = rows.Scan(&ue.Id, &ue.Name, &ue.Position, &path, &ue.PathMode, &ue.PathVelocity, &ue.PathLength, &ue.PathIncrement, &ue.PathFraction, &ue.Poa, &ue.PoaDistance, pq.Array(&ue.PoaInRange)) if err != nil { log.Error(err.Error()) return nil, err } err = rows.Err() if err != nil { log.Error(err) } // Store path if path != nil { ue.Path = *path } return ue, nil } // GetPoa - Get POA information func (pc *Connector) GetPoa(name string) (poa *Poa, err error) { // Validate input if name == "" { err = errors.New("Missing Name") return nil, err } // Get Poa entry var rows *sql.Rows rows, err = pc.db.Query(` SELECT id, name, type, ST_AsGeoJSON(position), radius FROM `+PoaTable+` WHERE name = ($1)`, name) if err != nil { log.Error(err.Error()) return nil, err } defer rows.Close() poa = new(Poa) // Scan result rows.Next() err = rows.Scan(&poa.Id, &poa.Name, &poa.SubType, &poa.Position, &poa.Radius) if err != nil { log.Error(err.Error()) return nil, err } err = rows.Err() if err != nil { log.Error(err) } return poa, nil } // GetCompute - Get Compute information func (pc *Connector) GetCompute(name string) (compute *Compute, err error) { // Validate input if name == "" { err = errors.New("Missing Name") return nil, err } // Get Compute entry var rows *sql.Rows rows, err = pc.db.Query(` SELECT id, name, type, ST_AsGeoJSON(position) FROM `+ComputeTable+` WHERE name = ($1)`, name) if err != nil { log.Error(err.Error()) return nil, err } defer rows.Close() compute = new(Compute) // Scan result rows.Next() err = rows.Scan(&compute.Id, &compute.Name, &compute.SubType, &compute.Position) if err != nil { log.Error(err.Error()) return nil, err } err = rows.Err() if err != nil { log.Error(err) } return compute, nil } // Recalculate UE path length & increment func (pc *Connector) refreshUePath(name string) (err error) { query := `UPDATE ` + UeTable + ` SET path_length = selected_ue.path_len, path_increment = selected_ue.path_velocity / selected_ue.path_len, path_fraction = 0 FROM ( SELECT ST_Length(path::geography) AS path_len, path_velocity FROM ` + UeTable + ` WHERE name = ($1) ) AS selected_ue WHERE name = ($1)` _, err = pc.db.Exec(query, name) if err != nil { log.Error(err.Error()) return err } return nil } // Recalculate nearest POA & POAs in range for provided UE func (pc *Connector) refreshUePoa(name string) (err error) { // Calculate distance from provided UE to each POA and check if within range var rows *sql.Rows rows, err = pc.db.Query(` SELECT ue.name AS ue, poa.name as poa, ST_Distance(ue.position::geography, poa.position::geography) AS dist, ST_DWithin(ue.position::geography, poa.position::geography, poa.radius) AS in_range FROM `+UeTable+`, `+PoaTable+` WHERE ue.name = ($1)`, name) if err != nil { log.Error(err.Error()) return err } defer rows.Close() nearestPoa := "" distance := float32(0) poaInRange := []string{} // Scan results for rows.Next() { ue := "" poa := "" dist := float32(0) inRange := false err := rows.Scan(&ue, &poa, &dist, &inRange) if err != nil { log.Error(err.Error()) return err } // Add POA if in range if inRange { poaInRange = append(poaInRange, poa) } // Set nearest POA if nearestPoa == "" || dist < distance { nearestPoa = poa distance = dist } } err = rows.Err() if err != nil { log.Error(err) } // Update POA entries fro UE query := `UPDATE ` + UeTable + ` SET poa = $2, poa_distance = $3, poa_in_range = $4 WHERE name = ($1)` _, err = pc.db.Exec(query, name, nearestPoa, distance, pq.Array(&poaInRange)) if err != nil { log.Error(err.Error()) return err } return nil } go-packages/meep-postgis/db_test.go +393 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package postgisdb import ( "fmt" "sort" "testing" log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger" Loading @@ -30,12 +31,58 @@ const ( pcDBPwd = "pwd" pcDBHost = "localhost" pcDBPort = "30432" ue1Id = "ue1-id" ue1Name = "ue1" ue1Velocity = 5.0 ue2Id = "ue2-id" ue2Name = "ue2" ue2Velocity = 0.0 ue3Id = "ue3-id" ue3Name = "ue3" ue3Velocity = 25.0 poa1Id = "poa1-id" poa1Name = "poa1" poa1Type = "POA-CELLULAR" poa1Loc = "[7.418494,43.733449]" poa1Radius = 160.0 poa2Id = "poa2-id" poa2Name = "poa2" poa2Type = "POA" poa2Loc = "[7.421626,43.736983]" poa2Radius = 350.0 poa3Id = "poa3-id" poa3Name = "poa3" poa3Type = "POA-CELLULAR" poa3Loc = "[7.422239,43.732972]" poa3Radius = 220.0 compute1Id = "compute1-id" compute1Name = "compute1" compute1Type = "EDGE" compute2Id = "compute2-id" compute2Name = "compute2" compute2Type = "FOG" compute3Id = "compute3-id" compute3Name = "compute3" compute3Type = "EDGE" point1 = "[7.418522,43.734198]" point2 = "[7.421501,43.736978]" point3 = "[7.422441,43.732285]" point4 = "[7.418944,43.732591]" ) func TestPostgisConnectorNew(t *testing.T) { fmt.Println("--- ", t.Name()) log.MeepTextLogInit(t.Name()) // Invalid Connector fmt.Println("Invalid Postgis Connector") pc, err := NewConnector("", pcNamespace, pcDBUser, pcDBPwd, pcDBHost, pcDBPort) if err == nil || pc != nil { Loading @@ -54,11 +101,357 @@ func TestPostgisConnectorNew(t *testing.T) { t.Fatalf("DB connection should have failed") } // Valid Connector fmt.Println("Create valid Postgis Connector") pc, err = NewConnector(pcName, pcNamespace, pcDBUser, pcDBPwd, pcDBHost, pcDBPort) if err != nil || pc == nil { t.Fatalf("Unable to create postgis Connector") } // Cleanup _ = pc.DeleteTable(UeTable) _ = pc.DeleteTable(PoaTable) _ = pc.DeleteTable(ComputeTable) // Create tables fmt.Println("Create Tables") err = pc.CreateTables() if err != nil { t.Fatalf("Unable to create tables") } // Add Invalid UE fmt.Println("Create Invalid UEs") ueLoc := "{\"type\":\"Point\",\"coordinates\":[0,0]}" uePath := "{\"type\":\"LineString\",\"coordinates\":[[0,0],[1,1]]}" ueVelocity := float32(0) err = pc.CreateUe("", ue1Name, ueLoc, uePath, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } err = pc.CreateUe(ue1Id, "", ueLoc, uePath, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } err = pc.CreateUe(ue1Id, ue1Name, "", uePath, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } ueLocInvalid := "{\"type\":\"Invalid\",\"coordinates\":[0,0]}" err = pc.CreateUe(ue1Id, ue1Name, ueLocInvalid, uePath, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } ueLocInvalid = "{\"type\":\"Point\",\"coordinates\":[]}" err = pc.CreateUe(ue1Id, ue1Name, ueLocInvalid, uePath, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } uePathInvalid := "{\"type\":\"Invalid\",\"coordinates\":[[0,0],[1,1]]}" err = pc.CreateUe(ue1Id, ue1Name, ueLoc, uePathInvalid, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } uePathInvalid = "{\"type\":\"LineString\",\"coordinates\":[[0,0],[]]}" err = pc.CreateUe(ue1Id, ue1Name, ueLoc, uePathInvalid, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } // Make sure POAs don't exist fmt.Println("Verify no POAs present") poa, err := pc.GetPoa(poa1Name) if err == nil || poa != nil { t.Fatalf("POA Get should have failed") } poa, err = pc.GetPoa(poa2Name) if err == nil || poa != nil { t.Fatalf("POA Get should have failed") } poa, err = pc.GetPoa(poa3Name) if err == nil || poa != nil { t.Fatalf("POA Get should have failed") } // Make sure UEs don't exist fmt.Println("Verify no UEs present") ue, err := pc.GetUe(ue1Name) if err == nil || ue != nil { t.Fatalf("UE Get should have failed") } ue, err = pc.GetUe(ue2Name) if err == nil || ue != nil { t.Fatalf("UE Get should have failed") } ue, err = pc.GetUe(ue3Name) if err == nil || ue != nil { t.Fatalf("UE Get should have failed") } // Make sure Computes don't exist fmt.Println("Verify no Computes present") compute, err := pc.GetCompute(compute1Name) if err == nil || compute != nil { t.Fatalf("Computes Get should have failed") } compute, err = pc.GetCompute(compute2Name) if err == nil || compute != nil { t.Fatalf("Computes Get should have failed") } compute, err = pc.GetCompute(compute3Name) if err == nil || compute != nil { t.Fatalf("Computes Get should have failed") } // Add POA & Validate successfully added fmt.Println("Add POAs & Validate successfully added") poaLoc := "{\"type\":\"Point\",\"coordinates\":" + poa1Loc + "}" err = pc.CreatePoa(poa1Id, poa1Name, poa1Type, poaLoc, poa1Radius) if err != nil { t.Fatalf("Unable to create asset") } poa, err = pc.GetPoa(poa1Name) if err != nil || poa == nil { t.Fatalf("Failed to get POA") } if !validatePoa(poa, poa1Id, poa1Name, poa1Type, poaLoc, poa1Radius) { t.Fatalf("POA validation failed") } poaLoc = "{\"type\":\"Point\",\"coordinates\":" + poa2Loc + "}" err = pc.CreatePoa(poa2Id, poa2Name, poa2Type, poaLoc, poa2Radius) if err != nil { t.Fatalf("Unable to create asset") } poa, err = pc.GetPoa(poa2Name) if err != nil || poa == nil { t.Fatalf("Failed to get POA") } if !validatePoa(poa, poa2Id, poa2Name, poa2Type, poaLoc, poa2Radius) { t.Fatalf("POA validation failed") } poaLoc = "{\"type\":\"Point\",\"coordinates\":" + poa3Loc + "}" err = pc.CreatePoa(poa3Id, poa3Name, poa3Type, poaLoc, poa3Radius) if err != nil { t.Fatalf("Unable to create asset") } poa, err = pc.GetPoa(poa3Name) if err != nil || poa == nil { t.Fatalf("Failed to get POA") } if !validatePoa(poa, poa3Id, poa3Name, poa3Type, poaLoc, poa3Radius) { t.Fatalf("POA validation failed") } // Add UE & Validate successfully added fmt.Println("Add UEs & Validate successfully added") ueLoc = "{\"type\":\"Point\",\"coordinates\":" + point1 + "}" uePath = "{\"type\":\"LineString\",\"coordinates\":[" + point1 + "," + point2 + "," + point3 + "," + point4 + "," + point1 + "]}" err = pc.CreateUe(ue1Id, ue1Name, ueLoc, uePath, PathModeLoop, ue1Velocity) if err != nil { t.Fatalf("Unable to create asset") } ue, err = pc.GetUe(ue1Name) if err != nil || ue == nil { t.Fatalf("Failed to get UE") } if !validateUe(ue, ue1Id, ue1Name, ueLoc, uePath, PathModeLoop, ue1Velocity, 1383.59, 0.004, 0.000, poa1Name, 83.24975, []string{poa1Name}) { t.Fatalf("UE validation failed") } ueLoc = "{\"type\":\"Point\",\"coordinates\":" + point2 + "}" err = pc.CreateUe(ue2Id, ue2Name, ueLoc, "", "", ue2Velocity) if err != nil { t.Fatalf("Unable to create asset") } ue, err = pc.GetUe(ue2Name) if err != nil || ue == nil { t.Fatalf("Failed to get UE") } if !validateUe(ue, ue2Id, ue2Name, ueLoc, "", PathModeLoop, ue2Velocity, 0.000, 0.000, 0.000, poa2Name, 10.08527, []string{poa2Name}) { t.Fatalf("UE validation failed") } ueLoc = "{\"type\":\"Point\",\"coordinates\":" + point4 + "}" uePath = "{\"type\":\"LineString\",\"coordinates\":[" + point4 + "," + point3 + "," + point2 + "]}" err = pc.CreateUe(ue3Id, ue3Name, ueLoc, uePath, PathModeLoop, ue3Velocity) if err != nil { t.Fatalf("Unable to create asset") } ue, err = pc.GetUe(ue3Name) if err != nil || ue == nil { t.Fatalf("Failed to get UE") } fmt.Printf("%+v\n", ue) if !validateUe(ue, ue3Id, ue3Name, ueLoc, uePath, PathModeLoop, ue3Velocity, 810.678, 0.031, 0.000, poa1Name, 101.99091, []string{poa1Name}) { t.Fatalf("UE validation failed") } // Add Compute & Validate successfully added fmt.Println("Add Computes & Validate successfully added") computeLoc := "{\"type\":\"Point\",\"coordinates\":[0,0]}" err = pc.CreateCompute(compute1Id, compute1Name, compute1Type, computeLoc) if err != nil { t.Fatalf("Unable to create asset") } compute, err = pc.GetCompute(compute1Name) if err != nil || compute == nil { t.Fatalf("Failed to get Compute") } if !validateCompute(compute, compute1Id, compute1Name, compute1Type, computeLoc) { t.Fatalf("Compute validation failed") } computeLoc = "{\"type\":\"Point\",\"coordinates\":[0,2]}" err = pc.CreateCompute(compute2Id, compute2Name, compute2Type, computeLoc) if err != nil { t.Fatalf("Unable to create asset") } compute, err = pc.GetCompute(compute2Name) if err != nil || compute == nil { t.Fatalf("Failed to get Compute") } if !validateCompute(compute, compute2Id, compute2Name, compute2Type, computeLoc) { t.Fatalf("Compute validation failed") } computeLoc = "{\"type\":\"Point\",\"coordinates\":[2,2]}" err = pc.CreateCompute(compute3Id, compute3Name, compute3Type, computeLoc) if err != nil { t.Fatalf("Unable to create asset") } compute, err = pc.GetCompute(compute3Name) if err != nil || compute == nil { t.Fatalf("Failed to get Compute") } if !validateCompute(compute, compute3Id, compute3Name, compute3Type, computeLoc) { t.Fatalf("Compute validation failed") } // t.Fatalf("DONE") } func validateUe(ue *Ue, id string, name string, position string, path string, mode string, velocity float32, length float32, increment float32, fraction float32, poa string, distance float32, poaInRange []string) bool { if ue == nil { fmt.Println("ue == nil") return false } if ue.Id != id { fmt.Println("ue.Id != id") return false } if ue.Name != name { fmt.Println("ue.Name != name") return false } if ue.Position != position { fmt.Println("ue.Position != position") return false } if ue.Path != path { fmt.Println("ue.Path != path") return false } if ue.PathMode != mode { fmt.Println("ue.PathMode != mode") return false } if ue.PathVelocity != velocity { fmt.Println("ue.PathVelocity != velocity") return false } if ue.PathLength != length { fmt.Println("ue.PathLength != length") return false } if ue.PathIncrement != increment { fmt.Println("ue.PathIncrement != increment") return false } if ue.PathFraction != fraction { fmt.Println("ue.PathFraction != fraction") return false } if ue.Poa != poa { fmt.Println("ue.Poa != poa") return false } if ue.PoaDistance != distance { fmt.Println("ue.PoaDistance != distance") return false } if len(ue.PoaInRange) != len(poaInRange) { fmt.Println("len(ue.PoaInRange) != len(poaInRange)") return false } else { sort.Strings(ue.PoaInRange) sort.Strings(poaInRange) for i, poa := range ue.PoaInRange { if poa != poaInRange[i] { fmt.Println("poa != poaInRange[i]") return false } } } return true } func validatePoa(poa *Poa, id string, name string, subType string, position string, radius float32) bool { if poa == nil { fmt.Println("poa == nil") return false } if poa.Id != id { fmt.Println("poa.Id != id") return false } if poa.Name != name { fmt.Println("poa.Name != name") return false } if poa.SubType != subType { fmt.Println("poa.SubType != subType") return false } if poa.Position != position { fmt.Println("poa.Position != position") return false } if poa.Radius != radius { fmt.Println("poa.Radius != radius") return false } return true } func validateCompute(compute *Compute, id string, name string, subType string, position string) bool { if compute == nil { fmt.Println("compute == nil") return false } if compute.Id != id { fmt.Println("compute.Id != id") return false } if compute.Name != name { fmt.Println("compute.Name != name") return false } if compute.SubType != subType { fmt.Println("compute.SubType != subType") return false } if compute.Position != position { fmt.Println("compute.Position != position") return false } return true } Loading
go-packages/meep-postgis/db.go +440 −30 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import ( "strings" log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger" "github.com/lib/pq" _ "github.com/lib/pq" ) Loading @@ -34,6 +36,48 @@ const ( ) const dbMaxRetryCount int = 2 const ( PathModeLoop = "LOOP" PathModeReverse = "REVERSE" PathModeOnce = "ONCE" ) const ( UeTable = "ue" PoaTable = "poa" ComputeTable = "compute" ) type Ue struct { Id string Name string Position string Path string PathMode string PathVelocity float32 PathLength float32 PathIncrement float32 PathFraction float32 Poa string PoaDistance float32 PoaInRange []string } type Poa struct { Id string Name string SubType string Position string Radius float32 } type Compute struct { Id string Name string SubType string Position string } // Connector - Implements a Postgis SQL DB connector type Connector struct { name string Loading Loading @@ -78,7 +122,7 @@ func NewConnector(name, namespace, user, pwd, host, port string) (pc *Connector, // Ignore DB creation error in case it already exists. // Failure will occur at DB connection if DB was not successfully created. _ = pc.DbCreate(pc.dbName) _ = pc.CreateDb(pc.dbName) // Close connection to postgis DB pc.db.Close() Loading Loading @@ -128,8 +172,8 @@ func (pc *Connector) connectDB(dbName, user, pwd, host, port string) (db *sql.DB return db, nil } // DbCreate -- Create new DB with provided name func (pc *Connector) DbCreate(name string) (err error) { // CreateDb -- Create new DB with provided name func (pc *Connector) CreateDb(name string) (err error) { _, err = pc.db.Exec("CREATE DATABASE " + name) if err != nil { log.Error(err.Error()) Loading @@ -140,37 +184,403 @@ func (pc *Connector) DbCreate(name string) (err error) { return nil } // func DbDeleteTable(tableName string) (err error) { // _, err = db.Exec("DROP TABLE IF EXISTS " + tableName) // if err != nil { // log.Error(err.Error()) // return err // } // log.Info("Deleted table: " + tableName) // return nil // } func (pc *Connector) CreateTables() (err error) { _, err = pc.db.Exec("CREATE EXTENSION IF NOT EXISTS postgis") if err != nil { log.Error(err.Error()) return err } // func DbCreatePoaTable(tableName string) (err error) { // _, err = db.Exec("CREATE EXTENSION IF NOT EXISTS postgis") // if err != nil { // log.Error(err.Error()) // return err // } // UE Table _, err = pc.db.Exec(`CREATE TABLE ` + UeTable + ` ( id varchar(36) NOT NULL PRIMARY KEY, name varchar(100) NOT NULL UNIQUE, position geometry(POINT,4326) NOT NULL, path geometry(LINESTRING,4326), path_mode varchar(20) NOT NULL DEFAULT 'LOOP', path_velocity decimal(10,3) NOT NULL DEFAULT '0.000', path_length decimal(10,3) NOT NULL DEFAULT '0.000', path_increment decimal(10,3) NOT NULL DEFAULT '0.000', path_fraction decimal(10,3) NOT NULL DEFAULT '0.000', poa varchar(100) NOT NULL DEFAULT '', poa_distance decimal(10,6) NOT NULL DEFAULT '0.000000', poa_in_range varchar(100)[] NOT NULL DEFAULT array[]::varchar[], start_time timestamptz NOT NULL DEFAULT now() )`) if err != nil { log.Error(err.Error()) return err } log.Info("Created UE table: ", UeTable) // POA Table _, err = pc.db.Exec(`CREATE TABLE ` + PoaTable + ` ( id varchar(36) NOT NULL PRIMARY KEY, name varchar(100) NOT NULL UNIQUE, type varchar(20) NOT NULL DEFAULT '', radius decimal(10,1) NOT NULL DEFAULT '0.0', position geometry(POINT,4326) NOT NULL )`) if err != nil { log.Error(err.Error()) return err } log.Info("Created POA table: ", PoaTable) // Compute Table _, err = pc.db.Exec(`CREATE TABLE ` + ComputeTable + ` ( id varchar(36) NOT NULL PRIMARY KEY, name varchar(100) NOT NULL UNIQUE, type varchar(20) NOT NULL DEFAULT '', position geometry(POINT,4326) NOT NULL )`) if err != nil { log.Error(err.Error()) return err } log.Info("Created Edge table: ", ComputeTable) // _, err = db.Exec(`CREATE TABLE ` + tableName + ` ( // id varchar(36) NOT NULL PRIMARY KEY, // name varchar(100) NOT NULL UNIQUE, // lat decimal(10,6) NOT NULL DEFAULT '0.000000', // long decimal(10,6) NOT NULL DEFAULT '0.000000', // alt decimal(10,1) NOT NULL DEFAULT '0.0', // radius decimal(10,1) NOT NULL DEFAULT '0.0', // position geometry(POINTZ,4326) // )`) return nil } func (pc *Connector) DeleteTable(tableName string) (err error) { _, err = pc.db.Exec("DROP TABLE IF EXISTS " + tableName) if err != nil { log.Error(err.Error()) return err } log.Info("Deleted table: " + tableName) return nil } // func (pc *Connector) AssetExists(name string, assetType AssetType) (exists bool) { // count := 0 // rows, err := pc.db.Query(`select count(*) from `+getTableName(assetType)+` where name = ($1)`, name) // if err != nil { // log.Error(err.Error()) // return err // return false // } // defer rows.Close() // log.Info("Created table: ", tableName) // return nil // // Scan results // for rows.Next() { // err = rows.Scan(&count) // } // exists = (count != 0) // return exists // } // CreateUe - Create new UE func (pc *Connector) CreateUe(id string, name string, position string, path string, mode string, velocity float32) (err error) { // Validate input if id == "" { return errors.New("Missing ID") } if name == "" { return errors.New("Missing Name") } if position == "" { return errors.New("Missing Position") } if path != "" { // Validate Path parameters if mode == "" { return errors.New("Missing Path Mode") } // Create UE entry with path query := `INSERT INTO ` + UeTable + ` (id, name, position, path, path_mode, path_velocity) VALUES ($1, $2, ST_GeomFromGeoJSON('` + position + `'), ST_GeomFromGeoJSON('` + path + `'), $3, $4)` _, err = pc.db.Exec(query, id, name, mode, velocity) if err != nil { log.Error(err.Error()) return err } // Calculate UE path length & increment err = pc.refreshUePath(name) if err != nil { log.Error(err.Error()) return err } } else { // Create UE entry without path query := `INSERT INTO ` + UeTable + ` (id, name, position) VALUES ($1, $2, ST_GeomFromGeoJSON('` + position + `'))` _, err = pc.db.Exec(query, id, name) if err != nil { log.Error(err.Error()) return err } } // Refresh UE POA information err = pc.refreshUePoa(name) if err != nil { log.Error(err.Error()) return err } return nil } // CreatePoa - Create new POA func (pc *Connector) CreatePoa(id string, name string, subType string, position string, radius float32) (err error) { // Validate input if id == "" { return errors.New("Missing ID") } if name == "" { return errors.New("Missing Name") } if subType == "" { return errors.New("Missing Type") } if position == "" { return errors.New("Missing Position") } // Create POA entry query := `INSERT INTO ` + PoaTable + ` (id, name, type, position, radius) VALUES ($1, $2, $3, ST_GeomFromGeoJSON('` + position + `'), $4)` _, err = pc.db.Exec(query, id, name, subType, radius) if err != nil { log.Error(err.Error()) return err } return nil } // CreateCompute - Create new Compute func (pc *Connector) CreateCompute(id string, name string, subType string, position string) (err error) { // Validate input if id == "" { return errors.New("Missing ID") } if name == "" { return errors.New("Missing Name") } if subType == "" { return errors.New("Missing Type") } if position == "" { return errors.New("Missing Position") } // Create Compute entry query := `INSERT INTO ` + ComputeTable + ` (id, name, type, position) VALUES ($1, $2, $3, ST_GeomFromGeoJSON('` + position + `'))` _, err = pc.db.Exec(query, id, name, subType) if err != nil { log.Error(err.Error()) return err } return nil } // GetUe - Get UE information func (pc *Connector) GetUe(name string) (ue *Ue, err error) { // Validate input if name == "" { err = errors.New("Missing Name") return nil, err } // Get UE entry var rows *sql.Rows rows, err = pc.db.Query(` SELECT id, name, ST_AsGeoJSON(position), ST_AsGeoJSON(path), path_mode, path_velocity, path_length, path_increment, path_fraction, poa, poa_distance, poa_in_range FROM `+UeTable+` WHERE name = ($1)`, name) if err != nil { log.Error(err.Error()) return nil, err } defer rows.Close() ue = new(Ue) path := new(string) // Scan result rows.Next() err = rows.Scan(&ue.Id, &ue.Name, &ue.Position, &path, &ue.PathMode, &ue.PathVelocity, &ue.PathLength, &ue.PathIncrement, &ue.PathFraction, &ue.Poa, &ue.PoaDistance, pq.Array(&ue.PoaInRange)) if err != nil { log.Error(err.Error()) return nil, err } err = rows.Err() if err != nil { log.Error(err) } // Store path if path != nil { ue.Path = *path } return ue, nil } // GetPoa - Get POA information func (pc *Connector) GetPoa(name string) (poa *Poa, err error) { // Validate input if name == "" { err = errors.New("Missing Name") return nil, err } // Get Poa entry var rows *sql.Rows rows, err = pc.db.Query(` SELECT id, name, type, ST_AsGeoJSON(position), radius FROM `+PoaTable+` WHERE name = ($1)`, name) if err != nil { log.Error(err.Error()) return nil, err } defer rows.Close() poa = new(Poa) // Scan result rows.Next() err = rows.Scan(&poa.Id, &poa.Name, &poa.SubType, &poa.Position, &poa.Radius) if err != nil { log.Error(err.Error()) return nil, err } err = rows.Err() if err != nil { log.Error(err) } return poa, nil } // GetCompute - Get Compute information func (pc *Connector) GetCompute(name string) (compute *Compute, err error) { // Validate input if name == "" { err = errors.New("Missing Name") return nil, err } // Get Compute entry var rows *sql.Rows rows, err = pc.db.Query(` SELECT id, name, type, ST_AsGeoJSON(position) FROM `+ComputeTable+` WHERE name = ($1)`, name) if err != nil { log.Error(err.Error()) return nil, err } defer rows.Close() compute = new(Compute) // Scan result rows.Next() err = rows.Scan(&compute.Id, &compute.Name, &compute.SubType, &compute.Position) if err != nil { log.Error(err.Error()) return nil, err } err = rows.Err() if err != nil { log.Error(err) } return compute, nil } // Recalculate UE path length & increment func (pc *Connector) refreshUePath(name string) (err error) { query := `UPDATE ` + UeTable + ` SET path_length = selected_ue.path_len, path_increment = selected_ue.path_velocity / selected_ue.path_len, path_fraction = 0 FROM ( SELECT ST_Length(path::geography) AS path_len, path_velocity FROM ` + UeTable + ` WHERE name = ($1) ) AS selected_ue WHERE name = ($1)` _, err = pc.db.Exec(query, name) if err != nil { log.Error(err.Error()) return err } return nil } // Recalculate nearest POA & POAs in range for provided UE func (pc *Connector) refreshUePoa(name string) (err error) { // Calculate distance from provided UE to each POA and check if within range var rows *sql.Rows rows, err = pc.db.Query(` SELECT ue.name AS ue, poa.name as poa, ST_Distance(ue.position::geography, poa.position::geography) AS dist, ST_DWithin(ue.position::geography, poa.position::geography, poa.radius) AS in_range FROM `+UeTable+`, `+PoaTable+` WHERE ue.name = ($1)`, name) if err != nil { log.Error(err.Error()) return err } defer rows.Close() nearestPoa := "" distance := float32(0) poaInRange := []string{} // Scan results for rows.Next() { ue := "" poa := "" dist := float32(0) inRange := false err := rows.Scan(&ue, &poa, &dist, &inRange) if err != nil { log.Error(err.Error()) return err } // Add POA if in range if inRange { poaInRange = append(poaInRange, poa) } // Set nearest POA if nearestPoa == "" || dist < distance { nearestPoa = poa distance = dist } } err = rows.Err() if err != nil { log.Error(err) } // Update POA entries fro UE query := `UPDATE ` + UeTable + ` SET poa = $2, poa_distance = $3, poa_in_range = $4 WHERE name = ($1)` _, err = pc.db.Exec(query, name, nearestPoa, distance, pq.Array(&poaInRange)) if err != nil { log.Error(err.Error()) return err } return nil }
go-packages/meep-postgis/db_test.go +393 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package postgisdb import ( "fmt" "sort" "testing" log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger" Loading @@ -30,12 +31,58 @@ const ( pcDBPwd = "pwd" pcDBHost = "localhost" pcDBPort = "30432" ue1Id = "ue1-id" ue1Name = "ue1" ue1Velocity = 5.0 ue2Id = "ue2-id" ue2Name = "ue2" ue2Velocity = 0.0 ue3Id = "ue3-id" ue3Name = "ue3" ue3Velocity = 25.0 poa1Id = "poa1-id" poa1Name = "poa1" poa1Type = "POA-CELLULAR" poa1Loc = "[7.418494,43.733449]" poa1Radius = 160.0 poa2Id = "poa2-id" poa2Name = "poa2" poa2Type = "POA" poa2Loc = "[7.421626,43.736983]" poa2Radius = 350.0 poa3Id = "poa3-id" poa3Name = "poa3" poa3Type = "POA-CELLULAR" poa3Loc = "[7.422239,43.732972]" poa3Radius = 220.0 compute1Id = "compute1-id" compute1Name = "compute1" compute1Type = "EDGE" compute2Id = "compute2-id" compute2Name = "compute2" compute2Type = "FOG" compute3Id = "compute3-id" compute3Name = "compute3" compute3Type = "EDGE" point1 = "[7.418522,43.734198]" point2 = "[7.421501,43.736978]" point3 = "[7.422441,43.732285]" point4 = "[7.418944,43.732591]" ) func TestPostgisConnectorNew(t *testing.T) { fmt.Println("--- ", t.Name()) log.MeepTextLogInit(t.Name()) // Invalid Connector fmt.Println("Invalid Postgis Connector") pc, err := NewConnector("", pcNamespace, pcDBUser, pcDBPwd, pcDBHost, pcDBPort) if err == nil || pc != nil { Loading @@ -54,11 +101,357 @@ func TestPostgisConnectorNew(t *testing.T) { t.Fatalf("DB connection should have failed") } // Valid Connector fmt.Println("Create valid Postgis Connector") pc, err = NewConnector(pcName, pcNamespace, pcDBUser, pcDBPwd, pcDBHost, pcDBPort) if err != nil || pc == nil { t.Fatalf("Unable to create postgis Connector") } // Cleanup _ = pc.DeleteTable(UeTable) _ = pc.DeleteTable(PoaTable) _ = pc.DeleteTable(ComputeTable) // Create tables fmt.Println("Create Tables") err = pc.CreateTables() if err != nil { t.Fatalf("Unable to create tables") } // Add Invalid UE fmt.Println("Create Invalid UEs") ueLoc := "{\"type\":\"Point\",\"coordinates\":[0,0]}" uePath := "{\"type\":\"LineString\",\"coordinates\":[[0,0],[1,1]]}" ueVelocity := float32(0) err = pc.CreateUe("", ue1Name, ueLoc, uePath, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } err = pc.CreateUe(ue1Id, "", ueLoc, uePath, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } err = pc.CreateUe(ue1Id, ue1Name, "", uePath, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } ueLocInvalid := "{\"type\":\"Invalid\",\"coordinates\":[0,0]}" err = pc.CreateUe(ue1Id, ue1Name, ueLocInvalid, uePath, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } ueLocInvalid = "{\"type\":\"Point\",\"coordinates\":[]}" err = pc.CreateUe(ue1Id, ue1Name, ueLocInvalid, uePath, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } uePathInvalid := "{\"type\":\"Invalid\",\"coordinates\":[[0,0],[1,1]]}" err = pc.CreateUe(ue1Id, ue1Name, ueLoc, uePathInvalid, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } uePathInvalid = "{\"type\":\"LineString\",\"coordinates\":[[0,0],[]]}" err = pc.CreateUe(ue1Id, ue1Name, ueLoc, uePathInvalid, PathModeLoop, ueVelocity) if err == nil { t.Fatalf("UE creation should have failed") } // Make sure POAs don't exist fmt.Println("Verify no POAs present") poa, err := pc.GetPoa(poa1Name) if err == nil || poa != nil { t.Fatalf("POA Get should have failed") } poa, err = pc.GetPoa(poa2Name) if err == nil || poa != nil { t.Fatalf("POA Get should have failed") } poa, err = pc.GetPoa(poa3Name) if err == nil || poa != nil { t.Fatalf("POA Get should have failed") } // Make sure UEs don't exist fmt.Println("Verify no UEs present") ue, err := pc.GetUe(ue1Name) if err == nil || ue != nil { t.Fatalf("UE Get should have failed") } ue, err = pc.GetUe(ue2Name) if err == nil || ue != nil { t.Fatalf("UE Get should have failed") } ue, err = pc.GetUe(ue3Name) if err == nil || ue != nil { t.Fatalf("UE Get should have failed") } // Make sure Computes don't exist fmt.Println("Verify no Computes present") compute, err := pc.GetCompute(compute1Name) if err == nil || compute != nil { t.Fatalf("Computes Get should have failed") } compute, err = pc.GetCompute(compute2Name) if err == nil || compute != nil { t.Fatalf("Computes Get should have failed") } compute, err = pc.GetCompute(compute3Name) if err == nil || compute != nil { t.Fatalf("Computes Get should have failed") } // Add POA & Validate successfully added fmt.Println("Add POAs & Validate successfully added") poaLoc := "{\"type\":\"Point\",\"coordinates\":" + poa1Loc + "}" err = pc.CreatePoa(poa1Id, poa1Name, poa1Type, poaLoc, poa1Radius) if err != nil { t.Fatalf("Unable to create asset") } poa, err = pc.GetPoa(poa1Name) if err != nil || poa == nil { t.Fatalf("Failed to get POA") } if !validatePoa(poa, poa1Id, poa1Name, poa1Type, poaLoc, poa1Radius) { t.Fatalf("POA validation failed") } poaLoc = "{\"type\":\"Point\",\"coordinates\":" + poa2Loc + "}" err = pc.CreatePoa(poa2Id, poa2Name, poa2Type, poaLoc, poa2Radius) if err != nil { t.Fatalf("Unable to create asset") } poa, err = pc.GetPoa(poa2Name) if err != nil || poa == nil { t.Fatalf("Failed to get POA") } if !validatePoa(poa, poa2Id, poa2Name, poa2Type, poaLoc, poa2Radius) { t.Fatalf("POA validation failed") } poaLoc = "{\"type\":\"Point\",\"coordinates\":" + poa3Loc + "}" err = pc.CreatePoa(poa3Id, poa3Name, poa3Type, poaLoc, poa3Radius) if err != nil { t.Fatalf("Unable to create asset") } poa, err = pc.GetPoa(poa3Name) if err != nil || poa == nil { t.Fatalf("Failed to get POA") } if !validatePoa(poa, poa3Id, poa3Name, poa3Type, poaLoc, poa3Radius) { t.Fatalf("POA validation failed") } // Add UE & Validate successfully added fmt.Println("Add UEs & Validate successfully added") ueLoc = "{\"type\":\"Point\",\"coordinates\":" + point1 + "}" uePath = "{\"type\":\"LineString\",\"coordinates\":[" + point1 + "," + point2 + "," + point3 + "," + point4 + "," + point1 + "]}" err = pc.CreateUe(ue1Id, ue1Name, ueLoc, uePath, PathModeLoop, ue1Velocity) if err != nil { t.Fatalf("Unable to create asset") } ue, err = pc.GetUe(ue1Name) if err != nil || ue == nil { t.Fatalf("Failed to get UE") } if !validateUe(ue, ue1Id, ue1Name, ueLoc, uePath, PathModeLoop, ue1Velocity, 1383.59, 0.004, 0.000, poa1Name, 83.24975, []string{poa1Name}) { t.Fatalf("UE validation failed") } ueLoc = "{\"type\":\"Point\",\"coordinates\":" + point2 + "}" err = pc.CreateUe(ue2Id, ue2Name, ueLoc, "", "", ue2Velocity) if err != nil { t.Fatalf("Unable to create asset") } ue, err = pc.GetUe(ue2Name) if err != nil || ue == nil { t.Fatalf("Failed to get UE") } if !validateUe(ue, ue2Id, ue2Name, ueLoc, "", PathModeLoop, ue2Velocity, 0.000, 0.000, 0.000, poa2Name, 10.08527, []string{poa2Name}) { t.Fatalf("UE validation failed") } ueLoc = "{\"type\":\"Point\",\"coordinates\":" + point4 + "}" uePath = "{\"type\":\"LineString\",\"coordinates\":[" + point4 + "," + point3 + "," + point2 + "]}" err = pc.CreateUe(ue3Id, ue3Name, ueLoc, uePath, PathModeLoop, ue3Velocity) if err != nil { t.Fatalf("Unable to create asset") } ue, err = pc.GetUe(ue3Name) if err != nil || ue == nil { t.Fatalf("Failed to get UE") } fmt.Printf("%+v\n", ue) if !validateUe(ue, ue3Id, ue3Name, ueLoc, uePath, PathModeLoop, ue3Velocity, 810.678, 0.031, 0.000, poa1Name, 101.99091, []string{poa1Name}) { t.Fatalf("UE validation failed") } // Add Compute & Validate successfully added fmt.Println("Add Computes & Validate successfully added") computeLoc := "{\"type\":\"Point\",\"coordinates\":[0,0]}" err = pc.CreateCompute(compute1Id, compute1Name, compute1Type, computeLoc) if err != nil { t.Fatalf("Unable to create asset") } compute, err = pc.GetCompute(compute1Name) if err != nil || compute == nil { t.Fatalf("Failed to get Compute") } if !validateCompute(compute, compute1Id, compute1Name, compute1Type, computeLoc) { t.Fatalf("Compute validation failed") } computeLoc = "{\"type\":\"Point\",\"coordinates\":[0,2]}" err = pc.CreateCompute(compute2Id, compute2Name, compute2Type, computeLoc) if err != nil { t.Fatalf("Unable to create asset") } compute, err = pc.GetCompute(compute2Name) if err != nil || compute == nil { t.Fatalf("Failed to get Compute") } if !validateCompute(compute, compute2Id, compute2Name, compute2Type, computeLoc) { t.Fatalf("Compute validation failed") } computeLoc = "{\"type\":\"Point\",\"coordinates\":[2,2]}" err = pc.CreateCompute(compute3Id, compute3Name, compute3Type, computeLoc) if err != nil { t.Fatalf("Unable to create asset") } compute, err = pc.GetCompute(compute3Name) if err != nil || compute == nil { t.Fatalf("Failed to get Compute") } if !validateCompute(compute, compute3Id, compute3Name, compute3Type, computeLoc) { t.Fatalf("Compute validation failed") } // t.Fatalf("DONE") } func validateUe(ue *Ue, id string, name string, position string, path string, mode string, velocity float32, length float32, increment float32, fraction float32, poa string, distance float32, poaInRange []string) bool { if ue == nil { fmt.Println("ue == nil") return false } if ue.Id != id { fmt.Println("ue.Id != id") return false } if ue.Name != name { fmt.Println("ue.Name != name") return false } if ue.Position != position { fmt.Println("ue.Position != position") return false } if ue.Path != path { fmt.Println("ue.Path != path") return false } if ue.PathMode != mode { fmt.Println("ue.PathMode != mode") return false } if ue.PathVelocity != velocity { fmt.Println("ue.PathVelocity != velocity") return false } if ue.PathLength != length { fmt.Println("ue.PathLength != length") return false } if ue.PathIncrement != increment { fmt.Println("ue.PathIncrement != increment") return false } if ue.PathFraction != fraction { fmt.Println("ue.PathFraction != fraction") return false } if ue.Poa != poa { fmt.Println("ue.Poa != poa") return false } if ue.PoaDistance != distance { fmt.Println("ue.PoaDistance != distance") return false } if len(ue.PoaInRange) != len(poaInRange) { fmt.Println("len(ue.PoaInRange) != len(poaInRange)") return false } else { sort.Strings(ue.PoaInRange) sort.Strings(poaInRange) for i, poa := range ue.PoaInRange { if poa != poaInRange[i] { fmt.Println("poa != poaInRange[i]") return false } } } return true } func validatePoa(poa *Poa, id string, name string, subType string, position string, radius float32) bool { if poa == nil { fmt.Println("poa == nil") return false } if poa.Id != id { fmt.Println("poa.Id != id") return false } if poa.Name != name { fmt.Println("poa.Name != name") return false } if poa.SubType != subType { fmt.Println("poa.SubType != subType") return false } if poa.Position != position { fmt.Println("poa.Position != position") return false } if poa.Radius != radius { fmt.Println("poa.Radius != radius") return false } return true } func validateCompute(compute *Compute, id string, name string, subType string, position string) bool { if compute == nil { fmt.Println("compute == nil") return false } if compute.Id != id { fmt.Println("compute.Id != id") return false } if compute.Name != name { fmt.Println("compute.Name != name") return false } if compute.SubType != subType { fmt.Println("compute.SubType != subType") return false } if compute.Position != position { fmt.Println("compute.Position != position") return false } return true }