Support connecting to multiple OpenFlow controllers
Change-Id: I0989d5031fb2d4f5aa78ba0e4576e465f826a419
diff --git a/internal/pkg/openflow/role_test.go b/internal/pkg/openflow/role_test.go
new file mode 100644
index 0000000..5eb3ba5
--- /dev/null
+++ b/internal/pkg/openflow/role_test.go
@@ -0,0 +1,160 @@
+/*
+ Copyright 2020 the original author or authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package openflow
+
+import (
+ ofp "github.com/donNewtonAlpha/goloxi/of13"
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+type testRoleManager struct {
+ role ofp.ControllerRole
+ generationId uint64
+ from string
+
+ generateError bool
+}
+
+func (trm *testRoleManager) UpdateRoles(from string, request *ofp.RoleRequest) bool {
+ trm.from = from
+ trm.role = request.Role
+ trm.generationId = request.GenerationId
+
+ return !trm.generateError
+}
+
+func createOFClient() *OFClient {
+ endpoints := []string{"e1", "e2", "e3"}
+
+ // create a client object
+ ofclient := &OFClient{
+ OFControllerEndPoints: endpoints,
+ connections: make(map[string]*OFConnection),
+ }
+
+ // create a connection object for each endpoint
+ for _, ep := range endpoints {
+ conn := &OFConnection{OFControllerEndPoint: ep, role: ofcRoleNone}
+ ofclient.connections[ep] = conn
+ }
+
+ return ofclient
+}
+
+func createRoleRequest(role ofp.ControllerRole, genId uint64) *ofp.RoleRequest {
+ rr := ofp.NewRoleRequest()
+ rr.Role = role
+ rr.GenerationId = genId
+ return rr
+}
+
+func TestRoleChange(t *testing.T) {
+ endpoints := []string{"e1", "e2", "e3"}
+ ofclient := &OFClient{
+ OFControllerEndPoints: endpoints, connections: make(map[string]*OFConnection),
+ }
+
+ for _, ep := range endpoints {
+ conn := &OFConnection{OFControllerEndPoint: ep, role: ofcRoleNone}
+ ofclient.connections[ep] = conn
+ }
+
+ assert.Equal(t, ofclient.connections["e1"].role, ofcRoleNone)
+
+ // change role of e1 to master
+ rr := createRoleRequest(ofp.OFPCRRoleMaster, 1)
+
+ ok := ofclient.UpdateRoles("e1", rr)
+ assert.True(t, ok)
+ assert.Equal(t, ofclient.connections["e1"].role, ofcRoleMaster)
+
+ // change role of e2 to master
+ ok = ofclient.UpdateRoles("e2", rr)
+ assert.True(t, ok)
+ assert.Equal(t, ofclient.connections["e2"].role, ofcRoleMaster)
+ // e1 should now have reverted to slave
+ assert.Equal(t, ofclient.connections["e1"].role, ofcRoleSlave)
+
+ // change role of e2 to slave
+ rr = createRoleRequest(ofp.OFPCRRoleSlave, 1)
+
+ ok = ofclient.UpdateRoles("e2", rr)
+ assert.True(t, ok)
+ assert.Equal(t, ofclient.connections["e2"].role, ofcRoleSlave)
+}
+
+func TestStaleRoleRequest(t *testing.T) {
+ ofclient := createOFClient()
+
+ rr1 := createRoleRequest(ofp.OFPCRRoleMaster, 2)
+
+ ok := ofclient.UpdateRoles("e1", rr1)
+ assert.True(t, ok)
+ assert.Equal(t, ofclient.connections["e1"].role, ofcRoleMaster)
+
+ // 'stale' role request
+ rr2 := createRoleRequest(ofp.OFPCRRoleSlave, 1)
+
+ ok = ofclient.UpdateRoles("e1", rr2)
+ // should not have succeeded
+ assert.False(t, ok)
+ // role should remain master
+ assert.Equal(t, ofclient.connections["e1"].role, ofcRoleMaster)
+}
+
+func TestHandleRoleRequest(t *testing.T) {
+
+ trm := &testRoleManager{}
+
+ connection := &OFConnection{
+ OFControllerEndPoint: "e1",
+ roleManager: trm,
+ sendChannel: make(chan Message, 10),
+ }
+
+ rr := createRoleRequest(ofp.OFPCRRoleMaster, 1)
+
+ connection.handleRoleRequest(rr)
+
+ assert.Equal(t, "e1", trm.from)
+ assert.EqualValues(t, ofp.OFPCRRoleMaster, trm.role)
+ assert.EqualValues(t, 1, trm.generationId)
+
+ resp := (<-connection.sendChannel).(*ofp.RoleReply)
+
+ assert.EqualValues(t, resp.Role, ofp.OFPCRRoleMaster)
+}
+
+func TestHandleRoleRequestError(t *testing.T) {
+
+ trm := &testRoleManager{generateError: true}
+
+ connection := &OFConnection{
+ OFControllerEndPoint: "e1",
+ roleManager: trm,
+ sendChannel: make(chan Message, 10),
+ }
+
+ rr := createRoleRequest(ofp.OFPCRRoleMaster, 1)
+
+ connection.handleRoleRequest(rr)
+
+ resp := (<-connection.sendChannel).(*ofp.RoleRequestFailedErrorMsg)
+
+ assert.EqualValues(t, resp.Code, ofp.OFPRRFCStale)
+}