Skip to content

Commit

Permalink
Merge branch 'main' into feat491-breakers
Browse files Browse the repository at this point in the history
  • Loading branch information
helderbetiol committed Jul 11, 2024
2 parents 1d8a410 + 7d102a1 commit 07514b5
Show file tree
Hide file tree
Showing 16 changed files with 508 additions and 267 deletions.
40 changes: 37 additions & 3 deletions API/models/attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"go.mongodb.org/mongo-driver/bson/primitive"
)

const RACKUNIT = 0.04445 //meter

func validateAttributes(entity int, data, parent map[string]any) *u.Error {
attributes := data["attributes"].(map[string]any)
switch entity {
Expand All @@ -21,8 +23,11 @@ func validateAttributes(entity int, data, parent map[string]any) *u.Error {
return err
}
case u.DEVICE:
var deviceSlots []string
var err *u.Error
if err = checkSizeUAndHeight(attributes); err != nil {
return err
}
var deviceSlots []string
if deviceSlots, err = slotToValidSlice(attributes); err != nil {
return err
}
Expand Down Expand Up @@ -67,8 +72,6 @@ func validateDeviceSlots(deviceSlots []string, deviceName, deviceParentd string)
Message: "Invalid slot: one or more requested slots are already in use"}
}
}
} else {
// fmt.Println(err)
}
}
return nil
Expand Down Expand Up @@ -152,3 +155,34 @@ func setCorridorColor(attributes map[string]any) {
attributes["color"] = "000099"
}
}

// Check if sizeU and height are coherents
func checkSizeUAndHeight(attributes map[string]any) *u.Error {
if attributes["sizeU"] == nil || attributes["height"] == nil {
return nil
}

sizeU, err := u.GetFloat(attributes["sizeU"])
if err != nil {
return &u.Error{
Type: u.ErrBadFormat,
Message: err.Error(),
}
}
height := attributes["height"]
h := sizeU * RACKUNIT
switch heightUnit := attributes["heightUnit"]; heightUnit {
case "cm":
h *= 100
case "mm":
h *= 1000
}
if height == h {
return nil
} else {
return &u.Error{
Type: u.ErrBadFormat,
Message: "sizeU and height are not consistent",
}
}
}
77 changes: 77 additions & 0 deletions API/models/update_object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,23 @@ import (
"github.com/stretchr/testify/assert"
)

var device map[string]any

func init() {
siName := "site"
bdName := siName + ".building"
roName := bdName + ".room"
rkName := roName + ".rack"

integration.RequireCreateSite(siName)
integration.RequireCreateBuilding(siName, "building")
integration.RequireCreateRoom(bdName, "room")
integration.RequireCreateRack(roName, "rack")
device = integration.RequireCreateDevice(rkName, "device")
}

// region generic

func TestUpdateGenericWorks(t *testing.T) {
generic := integration.RequireCreateGeneric("", "update-object-1")

Expand All @@ -26,3 +43,63 @@ func TestUpdateGenericWorks(t *testing.T) {
)
assert.Nil(t, err)
}

// endregion generic

// region device's sizeU & height

func TestUpdateDeviceSizeUAndHeightmm(t *testing.T) {
_, err := models.UpdateObject(
u.EntityToString(u.DEVICE),
device["id"].(string),
map[string]any{
"attributes": map[string]any{
"sizeU": 1,
"height": 44.45,
"heightUnit": "mm",
},
},
true,
integration.ManagerUserRoles,
false,
)
assert.Nil(t, err)
}
func TestUpdateDeviceSizeUAndHeightcm(t *testing.T) {
_, err := models.UpdateObject(
u.EntityToString(u.DEVICE),
device["id"].(string),
map[string]any{
"attributes": map[string]any{
"sizeU": 1,
"height": 4.445,
"heightUnit": "cm",
},
},
true,
integration.ManagerUserRoles,
false,
)
assert.Nil(t, err)
}

func TestUpdateDeviceSizeUAndHeightmmError(t *testing.T) {
_, err := models.UpdateObject(
u.EntityToString(u.DEVICE),
device["id"].(string),
map[string]any{
"attributes": map[string]any{
"sizeU": 12,
"height": 44.45,
"heightUnit": "mm",
},
},
true,
integration.ManagerUserRoles,
false,
)
assert.NotNil(t, err)
assert.ErrorContains(t, err, "sizeU and height are not consistent")
}

// endregion device's sizeU & height
13 changes: 13 additions & 0 deletions API/utils/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"encoding/json"
"flag"
"fmt"
"log"
"net/http"
"net/url"
Expand Down Expand Up @@ -507,3 +508,15 @@ func StrSliceContains(slice []string, elem string) bool {
}
return false
}

var floatType = reflect.TypeOf(float64(0))

func GetFloat(unk interface{}) (float64, error) {
v := reflect.ValueOf(unk)
v = reflect.Indirect(v)
if !v.Type().ConvertibleTo(floatType) {
return 0, fmt.Errorf("cannot convert %v to float64", v.Type())
}
fv := v.Convert(floatType)
return fv.Float(), nil
}
2 changes: 1 addition & 1 deletion CLI/controllers/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ func TestCreateDeviceWithSizeU(t *testing.T) {

mockGetResponse := test_utils.GetEntity("rack", "A01", "BASIC.A.R1", "test-domain")
sizeU := float64(2)
height := sizeU * 44.5
height := sizeU * models.RACKUNIT * 1000
mockCreateResponse := map[string]any{
"category": "device",
"id": "BASIC.A.R1.A01.D1",
Expand Down
2 changes: 1 addition & 1 deletion CLI/controllers/link_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func TestLinkObjectWithInvalidSlots(t *testing.T) {
}
err := controller.LinkObject(models.StrayPath+"chT", models.PhysicalPath+"BASIC/A/R1/A01", attributes, values, slots)
assert.NotNil(t, err)
assert.Equal(t, "Invalid device syntax: .. can only be used in a single element vector", err.Error())
assert.Equal(t, "invalid device syntax: .. can only be used in a single element vector", err.Error())
}

func TestLinkObjectWithValidSlots(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions CLI/controllers/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ func (controller Controller) ApplyTemplate(attr, data map[string]interface{}, en
if t == "chassis" || t == "server" {
res := 0
if val, ok := sizeInf[2].(float64); ok {
res = int((val / 1000) / RACKUNIT)
res = int((val / 1000) / models.RACKUNIT)
} else if val, ok := sizeInf[2].(int); ok {
res = int((float64(val) / 1000) / RACKUNIT)
res = int((float64(val) / 1000) / models.RACKUNIT)
} else {
return errors.New("invalid size vector on given template")
}
Expand Down
3 changes: 1 addition & 2 deletions CLI/controllers/template_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package controllers_test

import (
"cli/controllers"
"cli/models"
test_utils "cli/test"
"maps"
Expand Down Expand Up @@ -44,7 +43,7 @@ func TestApplyTemplateOfTypeDeviceWorks(t *testing.T) {

test_utils.MockGetObjTemplate(mockAPI, template)

sizeU := int((float64(template["sizeWDHmm"].([]any)[2].(int)) / 1000) / controllers.RACKUNIT)
sizeU := int((float64(template["sizeWDHmm"].([]any)[2].(int)) / 1000) / models.RACKUNIT)
err := controller.ApplyTemplate(attributes, device, models.DEVICE)
assert.Nil(t, err)

Expand Down
65 changes: 5 additions & 60 deletions CLI/controllers/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ func (controller Controller) PatchObj(pathStr string, data map[string]any, withR
category = obj["category"].(string)
}

if category == models.EntityToString(models.DEVICE) {
models.ComputeSizeUAndHeight(obj, data)
}

url, err := controller.ObjectUrl(pathStr, 0)
if err != nil {
return nil, err
Expand All @@ -76,72 +80,13 @@ func (controller Controller) PatchObj(pathStr string, data map[string]any, withR
return nil, err
}

//Determine if Unity requires the message as
//Interact or Modify
entityType := models.EntityStrToInt(category)
if models.IsTag(pathStr) {
entityType = models.TAG
} else if models.IsLayer(pathStr) {
if models.IsLayer(pathStr) {
// For layers, update the object to the hierarchy in order to be cached
data := resp.Body["data"].(map[string]any)
_, err = State.Hierarchy.AddObjectInPath(data, pathStr)
if err != nil {
return nil, err
}
entityType = models.LAYER
}

message := map[string]any{}
var key string

if entityType == models.ROOM && (data["tilesName"] != nil || data["tilesColor"] != nil) {
println("Room modifier detected")
Disp(data)

//Get the interactive key
key = determineStrKey(data, []string{"tilesName", "tilesColor"})

message["type"] = "interact"
message["data"] = map[string]any{
"id": obj["id"],
"param": key,
"value": data[key],
}
} else if entityType == models.RACK && data["U"] != nil {
message["type"] = "interact"
message["data"] = map[string]any{
"id": obj["id"],
"param": "U",
"value": data["U"],
}
} else if (entityType == models.DEVICE || entityType == models.RACK) &&
(data["alpha"] != nil || data["slots"] != nil || data["localCS"] != nil) {

//Get interactive key
key = determineStrKey(data, []string{"alpha", "U", "slots", "localCS"})

message["type"] = "interact"
message["data"] = map[string]any{
"id": obj["id"],
"param": key,
"value": data[key],
}
} else if entityType == models.GROUP && data["content"] != nil {
message["type"] = "interact"
message["data"] = map[string]any{
"id": obj["id"],
"param": "content",
"value": data["content"],
}
} else {
return resp.Body, nil
}

if IsEntityTypeForOGrEE3D(entityType) {
err := controller.Ogree3D.InformOptional("UpdateObj", entityType, message)
if err != nil {
return nil, err
}
}

return resp.Body, nil
Expand Down
Loading

0 comments on commit 07514b5

Please sign in to comment.