diff --git a/protocols/bgp/server/BUILD.bazel b/protocols/bgp/server/BUILD.bazel index 345c18806a64e01267a63dc585e74864867db36a..183cb1c9a288ac66a0713c1438ebe4baf4c7d8ae 100644 --- a/protocols/bgp/server/BUILD.bazel +++ b/protocols/bgp/server/BUILD.bazel @@ -56,6 +56,7 @@ go_test( "//routingtable:go_default_library", "//routingtable/filter:go_default_library", "//routingtable/locRIB:go_default_library", + "//testing:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", ], ) diff --git a/protocols/bgp/server/fsm_open_sent.go b/protocols/bgp/server/fsm_open_sent.go index 848c76697fb3a415b7e56131b67d3576d0e01722..121ea883a1c4d2de0e9384e275c394608b8665b7 100644 --- a/protocols/bgp/server/fsm_open_sent.go +++ b/protocols/bgp/server/fsm_open_sent.go @@ -134,7 +134,8 @@ func (s *openSentState) handleOpenMessage(openMsg *packet.BGPOpen) (state, strin s.processOpenOptions(openMsg.OptParams) if s.peerASNRcvd != s.fsm.peer.peerASN { - return newCeaseState(), fmt.Sprintf("Expected session from %d, got open message with ASN %d", s.fsm.peer.peerASN, s.peerASNRcvd) + s.fsm.sendNotification(packet.OpenMessageError, packet.BadPeerAS) + return newCeaseState(), fmt.Sprintf("Bad Peer AS %d, expected: %d", s.peerASNRcvd, s.fsm.peer.peerASN) } return newOpenConfirmState(s.fsm), "Received OPEN message" diff --git a/protocols/bgp/server/fsm_open_sent_test.go b/protocols/bgp/server/fsm_open_sent_test.go index 39057c6480f84c21d025e335cd95b2c7b34b2b08..fe34eede357c762de2674701132ddfa91bf170b9 100644 --- a/protocols/bgp/server/fsm_open_sent_test.go +++ b/protocols/bgp/server/fsm_open_sent_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/bio-routing/bio-rd/protocols/bgp/packet" + btesting "github.com/bio-routing/bio-rd/testing" "github.com/stretchr/testify/assert" ) @@ -68,6 +69,7 @@ func TestOpenMsgReceived(t *testing.T) { fsm := newFSM2(&peer{ peerASN: test.asn, }) + fsm.con = &btesting.MockConn{} s := &openSentState{ fsm: fsm, diff --git a/routingtable/adjRIBOut/path_id_manager.go b/routingtable/adjRIBOut/path_id_manager.go index 795d5f96b224681cbb05af56b69fa465b1ce5243..78054e3ec0294a7ba472e6de3928e2705c5ed536 100644 --- a/routingtable/adjRIBOut/path_id_manager.go +++ b/routingtable/adjRIBOut/path_id_manager.go @@ -65,6 +65,7 @@ func (fm *pathIDManager) releasePath(p *route.Path) (uint32, error) { delete(fm.ids, fm.idByPath[hash]) delete(fm.idByPath, hash) } + fm.used-- return id, nil } diff --git a/routingtable/adjRIBOut/path_id_manager_test.go b/routingtable/adjRIBOut/path_id_manager_test.go new file mode 100644 index 0000000000000000000000000000000000000000..e4ac49466587f0f11af3910d5fd2785e030e7cca --- /dev/null +++ b/routingtable/adjRIBOut/path_id_manager_test.go @@ -0,0 +1,173 @@ +package adjRIBOut + +import ( + "testing" + + "github.com/bio-routing/bio-rd/route" + "github.com/stretchr/testify/assert" +) + +func TestAddPath(t *testing.T) { + tests := []struct { + name string + maxIDs uint32 + count int + wantFail bool + }{ + { + name: "Out of path IDs", + maxIDs: 10, + count: 11, + wantFail: true, + }, + { + name: "Success", + maxIDs: 10, + count: 10, + wantFail: false, + }, + } + +X: + for _, test := range tests { + maxUint32 = test.maxIDs + m := newPathIDManager() + for i := 0; i < test.count; i++ { + _, err := m.addPath(&route.Path{BGPPath: &route.BGPPath{LocalPref: uint32(i)}}) + if err != nil { + if test.wantFail { + continue X + } + + t.Errorf("Unexpected failure for test %q: %v", test.name, err) + continue X + } + } + + if test.wantFail { + t.Errorf("Unexpected success for test %q", test.name) + continue + } + } + +} + +func TestReleasePath(t *testing.T) { + tests := []struct { + name string + pm *pathIDManager + release *route.Path + expected *pathIDManager + wantFail bool + }{ + { + name: "Release existent", + pm: &pathIDManager{ + ids: map[uint32]uint64{ + 0: 1, + 1: 1, + 2: 1, + }, + idByPath: map[route.BGPPath]uint32{ + route.BGPPath{ + LocalPref: 0, + }: 0, + route.BGPPath{ + LocalPref: 1, + }: 1, + route.BGPPath{ + LocalPref: 2, + }: 2, + }, + last: 2, + used: 3, + }, + release: &route.Path{BGPPath: &route.BGPPath{ + LocalPref: 2, + }}, + expected: &pathIDManager{ + ids: map[uint32]uint64{ + 0: 1, + 1: 1, + }, + idByPath: map[route.BGPPath]uint32{ + route.BGPPath{ + LocalPref: 0, + }: 0, + route.BGPPath{ + LocalPref: 1, + }: 1, + }, + last: 2, + used: 2, + }, + }, + { + name: "Release non-existent", + pm: &pathIDManager{ + ids: map[uint32]uint64{ + 0: 1, + 1: 1, + 2: 1, + }, + idByPath: map[route.BGPPath]uint32{ + route.BGPPath{ + LocalPref: 0, + }: 0, + route.BGPPath{ + LocalPref: 1, + }: 1, + route.BGPPath{ + LocalPref: 2, + }: 2, + }, + last: 2, + used: 3, + }, + release: &route.Path{BGPPath: &route.BGPPath{ + LocalPref: 4, + }}, + expected: &pathIDManager{ + ids: map[uint32]uint64{ + 0: 1, + 1: 1, + 2: 1, + }, + idByPath: map[route.BGPPath]uint32{ + route.BGPPath{ + LocalPref: 0, + }: 0, + route.BGPPath{ + LocalPref: 1, + }: 1, + route.BGPPath{ + LocalPref: 2, + }: 2, + }, + last: 2, + used: 3, + }, + wantFail: true, + }, + } + + for _, test := range tests { + _, err := test.pm.releasePath(test.release) + if err != nil { + if test.wantFail { + continue + } + + t.Errorf("Unexpected failure for test %q: %v", test.name, err) + continue + } + + if test.wantFail { + t.Errorf("Unexpected success for test %q", test.name) + continue + } + + assert.Equalf(t, test.expected, test.pm, "%s", test.name) + } +} + diff --git a/routingtable/filter/filter_test.go b/routingtable/filter/filter_test.go index 2f4aace7637f30095d106520495d12a2d3ad9626..273e986d29dc4e25a6788bfb8f750e54bff6beb4 100644 --- a/routingtable/filter/filter_test.go +++ b/routingtable/filter/filter_test.go @@ -1,85 +1,21 @@ package filter -/*func TestAddPath(t *testing.T) { - tests := []struct { - name string - prefix net.Prefix - path *route.Path - term *Term - exptectCalled bool - expectModified bool - }{ - { - name: "accept", - prefix: net.NewPfx(0, 0), - path: &route.Path{}, - term: &Term{ - then: []FilterAction{ - &actions.AcceptAction{}, - }, - }, - exptectCalled: true, - expectModified: false, - }, - { - name: "reject", - prefix: net.NewPfx(0, 0), - path: &route.Path{}, - term: &Term{ - then: []FilterAction{ - &actions.RejectAction{}, - }, - }, - exptectCalled: false, - expectModified: false, - }, - { - name: "modified", - prefix: net.NewPfx(0, 0), - path: &route.Path{}, - term: &Term{ - then: []FilterAction{ - &mockAction{}, - &actions.AcceptAction{}, - }, - }, - exptectCalled: true, - expectModified: true, - }, - } - - for _, test := range tests { - t.Run(test.name, func(te *testing.T) { - m := newClientMock() - - f := NewFilter([]*Term{test.term}) - f.Register(m) +import ( + "testing" - f.AddPath(test.prefix, test.path) - assert.Equal(te, test.exptectCalled, m.addPathCalled, "called") + "github.com/bio-routing/bio-rd/net" + "github.com/bio-routing/bio-rd/route" + "github.com/bio-routing/bio-rd/routingtable/filter/actions" + "github.com/stretchr/testify/assert" +) - if !test.exptectCalled { - return - } - - if m.path != test.path && !test.expectModified { - te.Fatal("expected path to be not modified but was") - } - - if m.path == test.path && test.expectModified { - te.Fatal("expected path to be modified but was same reference") - } - }) - } -} - -func TestRemovePath(t *testing.T) { +func TestProcessTerms(t *testing.T) { tests := []struct { name string prefix net.Prefix path *route.Path term *Term - exptectCalled bool + exptectAccept bool expectModified bool }{ { @@ -91,7 +27,7 @@ func TestRemovePath(t *testing.T) { &actions.AcceptAction{}, }, }, - exptectCalled: true, + exptectAccept: true, expectModified: false, }, { @@ -103,7 +39,7 @@ func TestRemovePath(t *testing.T) { &actions.RejectAction{}, }, }, - exptectCalled: false, + exptectAccept: false, expectModified: false, }, { @@ -116,32 +52,21 @@ func TestRemovePath(t *testing.T) { &actions.AcceptAction{}, }, }, - exptectCalled: true, + exptectAccept: true, expectModified: true, }, } for _, test := range tests { t.Run(test.name, func(te *testing.T) { - m := newClientMock() - f := NewFilter([]*Term{test.term}) - f.Register(m) + p, reject := f.ProcessTerms(test.prefix, test.path) - f.RemovePath(test.prefix, test.path) - assert.Equal(te, test.exptectCalled, m.removePathCalled, "called") - - if !test.exptectCalled { - return - } + assert.Equal(t, test.exptectAccept, !reject) - if m.path != test.path && !test.expectModified { - te.Fatal("expected path to be not modified but was") - } - - if m.path == test.path && test.expectModified { - te.Fatal("expected path to be modified but was same reference") + if test.expectModified { + assert.NotEqual(t, test.path, p) } }) } -}*/ +} diff --git a/routingtable/filter/helper_test.go b/routingtable/filter/helper_test.go index 5d82727a9f2b5b5e0f692a980d9d7515ccd4c71d..19a444d4a5c8d656534cfb415f2b401a11ae4c57 100644 --- a/routingtable/filter/helper_test.go +++ b/routingtable/filter/helper_test.go @@ -1,27 +1,23 @@ package filter -/*func TestNewAcceptAllFilter(t *testing.T) { - f := NewAcceptAllFilter() +import ( + "testing" - m := &clientMock{} - f.Register(m) + "github.com/bio-routing/bio-rd/net" + "github.com/bio-routing/bio-rd/route" + "github.com/stretchr/testify/assert" +) - f.AddPath(net.NewPfx(0, 0), &route.Path{}) +func TestNewAcceptAllFilter(t *testing.T) { + f := NewAcceptAllFilter() - if !m.addPathCalled { - t.Fatalf("expected accepted, but was filtered") - } + _, reject := f.ProcessTerms(net.NewPfx(0, 0), &route.Path{}) + assert.Equal(t, false, reject) } func TestNewDrainFilter(t *testing.T) { f := NewDrainFilter() - m := &clientMock{} - f.Register(m) - - f.AddPath(net.NewPfx(0, 0), &route.Path{}) - - if m.addPathCalled { - t.Fatalf("expected filtered, but was accepted") - } -}*/ + _, reject := f.ProcessTerms(net.NewPfx(0, 0), &route.Path{}) + assert.Equal(t, true, reject) +} diff --git a/testing/BUILD.bazel b/testing/BUILD.bazel new file mode 100644 index 0000000000000000000000000000000000000000..3071b82f935eeb1d0f3f722214b282c98763245d --- /dev/null +++ b/testing/BUILD.bazel @@ -0,0 +1,8 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["conn_mock.go"], + importpath = "github.com/bio-routing/bio-rd/testing", + visibility = ["//visibility:public"], +) diff --git a/testing/conn_mock.go b/testing/conn_mock.go new file mode 100644 index 0000000000000000000000000000000000000000..86e8e1ae7d1c91eaa6efce317d34e8b08212c825 --- /dev/null +++ b/testing/conn_mock.go @@ -0,0 +1,32 @@ +package testing + +import "net" + +// MockConn mock an connection +type MockConn struct { + net.Conn + + // Bytes are the bytes writen + Bytes []byte +} + +func NewMockConn() *MockConn { + return &MockConn{ + Bytes: make([]byte, 0), + } +} + +func (m *MockConn) Write(b []byte) (int, error) { + m.Bytes = append(m.Bytes, b...) + return len(b), nil +} + +func (m *MockConn) Read(b []byte) (n int, err error) { + count := len(b) + if count > len(m.Bytes) { + count = len(m.Bytes) + } + + copy(m.Bytes[0:count], b) + return count, nil +}