Skip to content

Commit

Permalink
adsfasdfafds
Browse files Browse the repository at this point in the history
  • Loading branch information
dcbw committed Dec 2, 2022
1 parent cd5a90d commit 6812dbc
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 44 deletions.
58 changes: 45 additions & 13 deletions database/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ func TestMutateOp(t *testing.T) {
"baz": "quux",
"waldo": "fred",
},
FloodVLANs: []int{1, 2, 3},
}
bridgeInfo, err := dbModel.NewModelInfo(&bridge)
require.NoError(t, err)
Expand Down Expand Up @@ -383,6 +384,21 @@ func TestMutateOp(t *testing.T) {
assert.Equal(t, diffExternalIds, gotModify["external_ids"])
assert.Equal(t, oldExternalIds, gotOld["external_ids"])
assert.Equal(t, newExternalIds, gotNew["external_ids"])

// Test that attempting to mutate a set to exceed its allowed size results in an error
floodVLANsSchema := bridgeInfo.Metadata.TableSchema.Column("flood_vlans")
keyInsert, err := ovsdb.NewOvsSet(floodVLANsSchema.TypeObj.Key.Type, []int{33})
assert.Nil(t, err)
gotResult, gotUpdate, err = transaction.Mutate(
"Bridge",
[]ovsdb.Condition{
ovsdb.NewCondition("_uuid", ovsdb.ConditionEqual, ovsdb.UUID{GoUUID: bridgeUUID}),
},
[]ovsdb.Mutation{
*ovsdb.NewMutation("flood_vlans", ovsdb.MutateOperationInsert, keyInsert),
},
)
assert.Error(t, err)
}

func TestDiff(t *testing.T) {
Expand Down Expand Up @@ -627,10 +643,12 @@ func TestOvsdbServerUpdate(t *testing.T) {

halloween := MakeOvsSet(t, ovsdb.TypeString, []string{"halloween"})
emptySet := MakeOvsSet(t, ovsdb.TypeString, []string{})
floodVlanSet := MakeOvsSet(t, ovsdb.TypeInteger, []int{1, 2, 3, 4, 5, 6, 7})
tests := []struct {
name string
row ovsdb.Row
expected *ovsdb.RowUpdate2
name string
row ovsdb.Row
expected *ovsdb.RowUpdate2
expectErr bool
}{
{
"update single field",
Expand All @@ -640,6 +658,13 @@ func TestOvsdbServerUpdate(t *testing.T) {
"datapath_type": "waldo",
},
},
false,
},
{
"update single field with too-large array",
ovsdb.Row{"flood_vlans": floodVlanSet},
nil,
true,
},
{
"update single optional field, with direct value",
Expand All @@ -649,6 +674,7 @@ func TestOvsdbServerUpdate(t *testing.T) {
"datapath_id": halloween,
},
},
false,
},
{
"update single optional field, with set",
Expand All @@ -658,6 +684,7 @@ func TestOvsdbServerUpdate(t *testing.T) {
"datapath_id": halloween,
},
},
false,
},
{
"unset single optional field",
Expand All @@ -667,6 +694,7 @@ func TestOvsdbServerUpdate(t *testing.T) {
"datapath_id": emptySet,
},
},
false,
},
}
for _, tt := range tests {
Expand All @@ -676,16 +704,20 @@ func TestOvsdbServerUpdate(t *testing.T) {
[]ovsdb.Condition{{
Column: "_uuid", Function: ovsdb.ConditionEqual, Value: ovsdb.UUID{GoUUID: bridgeUUID},
}}, tt.row)
assert.NoError(t, err)
errs, err := ovsdb.CheckOperationResults([]ovsdb.OperationResult{res}, []ovsdb.Operation{{Op: "update"}})
require.NoErrorf(t, err, "%+v", errs)

bridge.UUID = bridgeUUID
row, err := db.Get("Open_vSwitch", "Bridge", bridgeUUID)
assert.NoError(t, err)
br := row.(*BridgeType)
assert.NotEqual(t, br, bridgeRow)
assert.Equal(t, tt.expected.Modify, updates["Bridge"][bridgeUUID].Modify)
if tt.expectErr {
require.Error(t, err)
} else {
assert.NoError(t, err)
errs, err := ovsdb.CheckOperationResults([]ovsdb.OperationResult{res}, []ovsdb.Operation{{Op: "update"}})
require.NoErrorf(t, err, "%+v", errs)

bridge.UUID = bridgeUUID
row, err := db.Get("Open_vSwitch", "Bridge", bridgeUUID)
assert.NoError(t, err)
br := row.(*BridgeType)
assert.NotEqual(t, br, bridgeRow)
assert.Equal(t, tt.expected.Modify, updates["Bridge"][bridgeUUID].Modify)
}
})
}
}
Expand Down
15 changes: 3 additions & 12 deletions mapper/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,11 @@ func (i *Info) SetField(column string, value interface{}) error {
if colSchema == nil {
return fmt.Errorf("SetField: column %s schema not found", column)
}

// Validate set length requirements
newVal := reflect.ValueOf(value)
if colSchema.Type == ovsdb.TypeSet || colSchema.Type == ovsdb.TypeEnum {
maxVal := colSchema.TypeObj.Max()
minVal := colSchema.TypeObj.Min()
if maxVal > 1 && newVal.Len() > maxVal {
return fmt.Errorf("SetField: column %s overflow: %d new elements but max is %d", column, newVal.Len(), maxVal)
} else if minVal > 0 && newVal.Len() < minVal {
return fmt.Errorf("SetField: column %s underflow: %d new elements but min is %d", column, newVal.Len(), minVal)
}
if err := ovsdb.ValidateColumnConstraints(colSchema, value); err != nil {
return fmt.Errorf("SetField: column %s failed validation: %v", column, err)
}

fieldValue.Set(newVal)
fieldValue.Set(reflect.ValueOf(value))
return nil
}

Expand Down
3 changes: 3 additions & 0 deletions mapper/mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ func (m Mapper) NewRow(data *Info, fields ...interface{}) (ovsdb.Row, error) {
if len(fields) == 0 && ovsdb.IsDefaultValue(column, nativeElem) {
continue
}
if err := ovsdb.ValidateColumnConstraints(column, nativeElem); err != nil {
return nil, fmt.Errorf("column %s assignment failed: %w", column, err)
}
ovsElem, err := ovsdb.NativeToOvs(column, nativeElem)
if err != nil {
return nil, fmt.Errorf("table %s, column %s: failed to generate ovs element. %s", data.Metadata.TableName, name, err.Error())
Expand Down
61 changes: 46 additions & 15 deletions mapper/mapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ var (
42.0,
}

aFloatSetTooBig = []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0}

aMap = map[string]string{
"key1": "value1",
"key2": "value2",
Expand Down Expand Up @@ -115,7 +117,7 @@ var testSchema = []byte(`{
"type": "real"
},
"min": 0,
"max": 10
"max": 5
}
},
"aEmptySet": {
Expand Down Expand Up @@ -216,28 +218,49 @@ func TestMapperGetData(t *testing.T) {
NonTagged: "something",
}

ovsRow := getOvsTestRow(t)
/* Code under test */
var schema ovsdb.DatabaseSchema
if err := json.Unmarshal(testSchema, &schema); err != nil {
t.Error(err)
}

mapper := NewMapper(schema)
test := ormTestType{
NonTagged: "something",
}
testInfo, err := NewInfo("TestTable", schema.Table("TestTable"), &test)
assert.NoError(t, err)

err = mapper.GetRowData(&ovsRow, testInfo)
assert.NoError(t, err)
/*End code under test*/
tests := []struct {
name string
setup func() ovsdb.Row
expectErr bool
}{{
name: "basic",
setup: func() ovsdb.Row {
return getOvsTestRow(t)
},
}, {
name: "too big array",
setup: func() ovsdb.Row {
testRow := getOvsTestRow(t)
testRow["aFloatSet"] = test.MakeOvsSet(t, ovsdb.TypeReal, aFloatSetTooBig)
return testRow
},
expectErr: true,
}}
for _, test := range tests {
t.Run(fmt.Sprintf("GetData: %s", test.name), func(t *testing.T) {
mapper := NewMapper(schema)
tt := ormTestType{
NonTagged: "something",
}
testInfo, err := NewInfo("TestTable", schema.Table("TestTable"), &tt)
assert.NoError(t, err)

if err != nil {
t.Error(err)
ovsRow := test.setup()
err = mapper.GetRowData(&ovsRow, testInfo)
if test.expectErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, expected, tt)
}
})
}
assert.Equal(t, expected, test)
}

func TestMapperNewRow(t *testing.T) {
Expand Down Expand Up @@ -315,6 +338,14 @@ func TestMapperNewRow(t *testing.T) {
MyFloatSet: aFloatSet,
},
expectedRow: ovsdb.Row(map[string]interface{}{"aFloatSet": test.MakeOvsSet(t, ovsdb.TypeReal, aFloatSet)}),
}, {
name: "aFloatSet too big",
objInput: &struct {
MyFloatSet []float64 `ovsdb:"aFloatSet"`
}{
MyFloatSet: aFloatSetTooBig,
},
shoulderr: true,
}, {
name: "Enum",
objInput: &struct {
Expand Down
18 changes: 18 additions & 0 deletions ovsdb/bindings.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,3 +399,21 @@ func isDefaultBaseValue(elem interface{}, etype ExtendedType) bool {
return false
}
}

// ValidateColumnConstraints validates the native value against any constraints
// of a given column.
func ValidateColumnConstraints(column *ColumnSchema, nativeValue interface{}) error {
switch column.Type {
case TypeSet, TypeEnum:
// Validate set length requirements
newVal := reflect.ValueOf(nativeValue)
maxVal := column.TypeObj.Max()
minVal := column.TypeObj.Min()
if maxVal > 1 && newVal.Len() > maxVal {
return fmt.Errorf("slice would overflow (%d elements but %d allowed)", newVal.Len(), maxVal)
} else if minVal > 0 && newVal.Len() < minVal {
return fmt.Errorf("slice would underflow (%d elements but %d required)", newVal.Len(), minVal)
}
}
return nil
}
2 changes: 1 addition & 1 deletion ovsdb/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ type ConstraintViolation struct {
}

// Error implements the error interface
func (e *ConstraintViolation) Error() string {
func (e ConstraintViolation) Error() string {
msg := constraintViolation
if e.details != "" {
msg += ": " + e.details
Expand Down
15 changes: 12 additions & 3 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,10 @@ func (o *OvsdbServer) Monitor(client *rpc2.Client, args []json.RawMessage, reply

tableUpdates := make(ovsdb.TableUpdates)
for t, request := range request {
rows := transaction.Select(t, nil, request.Columns)
rows, err := transaction.Select(t, nil, request.Columns)
if err != nil {
return err
}
for i := range rows.Rows {
tu := make(ovsdb.TableUpdate)
uuid := rows.Rows[i]["_uuid"].(ovsdb.UUID).GoUUID
Expand Down Expand Up @@ -345,7 +348,10 @@ func (o *OvsdbServer) MonitorCond(client *rpc2.Client, args []json.RawMessage, r

tableUpdates := make(ovsdb.TableUpdates2)
for t, request := range request {
rows := transaction.Select(t, nil, request.Columns)
rows, err := transaction.Select(t, nil, request.Columns)
if err != nil {
return err
}
for i := range rows.Rows {
tu := make(ovsdb.TableUpdate2)
uuid := rows.Rows[i]["_uuid"].(ovsdb.UUID).GoUUID
Expand Down Expand Up @@ -392,7 +398,10 @@ func (o *OvsdbServer) MonitorCondSince(client *rpc2.Client, args []json.RawMessa

tableUpdates := make(ovsdb.TableUpdates2)
for t, request := range request {
rows := transaction.Select(t, nil, request.Columns)
rows, err := transaction.Select(t, nil, request.Columns)
if err != nil {
return err
}
for i := range rows.Rows {
tu := make(ovsdb.TableUpdate2)
uuid := rows.Rows[i]["_uuid"].(ovsdb.UUID).GoUUID
Expand Down
12 changes: 12 additions & 0 deletions test/test_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ const schema = `
"min": 0,
"max": "unlimited"
}
},
"flood_vlans": {
"type": {
"key": {
"type": "integer",
"minInteger": 0,
"maxInteger": 4095
},
"min": 0,
"max": 3
}
}
},
"indexes": [
Expand Down Expand Up @@ -140,6 +151,7 @@ type BridgeType struct {
ExternalIds map[string]string `ovsdb:"external_ids"`
Ports []string `ovsdb:"ports"`
Status map[string]string `ovsdb:"status"`
FloodVLANs []int `ovsdb:"flood_vlans"`
}

// OvsType is the simplified ORM model of the Bridge table
Expand Down

0 comments on commit 6812dbc

Please sign in to comment.