diff --git a/net/ip_test.go b/net/ip_test.go index e286ff88f56e1b324fcfd6236c85527b5f760fef..cd2b5954085989fa80e0b95741628a8523fc7712 100644 --- a/net/ip_test.go +++ b/net/ip_test.go @@ -497,14 +497,23 @@ func TestBitAtPosition(t *testing.T) { position: 1, expected: true, }, + { + name: "IPv4: invalid position", + input: IPv4(0), + position: 33, + expected: false, + }, + { + name: "IPv6: invalid position", + input: IPv6(0, 0), + position: 129, + expected: false, + }, } for _, test := range tests { b := test.input.BitAtPosition(test.position) - if b != test.expected { - t.Errorf("%s: Unexpected failure: Bit %d of %v is %v. Expected %v", - test.name, test.position, test.input, b, test.expected) - } + assert.Equal(t, test.expected, b, test.name) } } @@ -550,3 +559,26 @@ func TestIPFromString(t *testing.T) { }) } } + +func TestSizeBytes(t *testing.T) { + tests := []struct { + name string + input IP + expected uint8 + }{ + { + name: "IPv4", + input: IPv4(0), + expected: 4, + }, + { + name: "IPv6", + input: IPv6(0, 0), + expected: 16, + }, + } + + for _, test := range tests { + assert.Equal(t, test.expected, test.input.SizeBytes(), test.name) + } +} diff --git a/net/prefix_test.go b/net/prefix_test.go index ddd07a6db499cc597d7cc58a9136af9ca21325e2..247c6da0e5e7d1abf4dc2f46402f08f5743b4c3b 100644 --- a/net/prefix_test.go +++ b/net/prefix_test.go @@ -300,13 +300,11 @@ func TestGetSupernet(t *testing.T) { func TestContains(t *testing.T) { tests := []struct { - name string a Prefix b Prefix expected bool }{ { - name: "Test 1", a: Prefix{ addr: IPv4(0), pfxlen: 0, @@ -318,7 +316,6 @@ func TestContains(t *testing.T) { expected: true, }, { - name: "Test 2", a: Prefix{ addr: IPv4(100), pfxlen: 24, @@ -330,7 +327,6 @@ func TestContains(t *testing.T) { expected: false, }, { - name: "Test 3", a: Prefix{ addr: IPv4(167772160), pfxlen: 8, @@ -342,7 +338,6 @@ func TestContains(t *testing.T) { expected: true, }, { - name: "Test 4", a: Prefix{ addr: IPv4(167772160), pfxlen: 8, @@ -354,7 +349,6 @@ func TestContains(t *testing.T) { expected: true, }, { - name: "Test 5", a: Prefix{ addr: IPv4(167772160), pfxlen: 8, @@ -366,7 +360,6 @@ func TestContains(t *testing.T) { expected: false, }, { - name: "Test 6", a: Prefix{ addr: IPv4(167772160), pfxlen: 8, @@ -378,7 +371,6 @@ func TestContains(t *testing.T) { expected: false, }, { - name: "Test 7", a: Prefix{ addr: IPv4FromOctets(169, 0, 0, 0), pfxlen: 25, @@ -390,7 +382,6 @@ func TestContains(t *testing.T) { expected: false, }, { - name: "IPv6: 2001:678:1e0:100::/56 is subnet of 2001:678:1e0::/48", a: Prefix{ addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0), pfxlen: 48, @@ -402,7 +393,6 @@ func TestContains(t *testing.T) { }, }, { - name: "IPv6: 2001:678:1e0:100::/56 is subnet of 2001:678:1e0::/48", a: Prefix{ addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0x200, 0, 0, 0, 0), pfxlen: 56, @@ -413,11 +403,22 @@ func TestContains(t *testing.T) { }, expected: false, }, + { + a: Prefix{ + addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0x200, 0, 0, 0, 0), + pfxlen: 65, + }, + b: Prefix{ + addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0x100, 0, 0, 0, 0), + pfxlen: 64, + }, + expected: false, + }, } for _, test := range tests { res := test.a.Contains(test.b) - assert.Equal(t, res, test.expected, "Unexpected result %v for test %s: %s contains %s", res, test.name, test.a, test.b) + assert.Equal(t, res, test.expected, "Subnet %s contains %s", test.a, test.b) } } diff --git a/route/bgp_path.go b/route/bgp_path.go index 31516124563d6ca9641de982044537b2d2aee4f2..195a1da0a766775a0502c136d7911aea6cc16bf8 100644 --- a/route/bgp_path.go +++ b/route/bgp_path.go @@ -236,6 +236,8 @@ func (b *BGPPath) better(c *BGPPath) bool { // Print all known information about a route in logfile friendly format func (b *BGPPath) String() string { + buf := &strings.Builder{} + origin := "" switch b.Origin { case 0: @@ -251,30 +253,32 @@ func (b *BGPPath) String() string { bgpType = "external" } - ret := fmt.Sprintf("Local Pref: %d, ", b.LocalPref) - ret += fmt.Sprintf("Origin: %s, ", origin) - ret += fmt.Sprintf("AS Path: %v, ", b.ASPath) - ret += fmt.Sprintf("BGP type: %s, ", bgpType) - ret += fmt.Sprintf("NEXT HOP: %s, ", b.NextHop) - ret += fmt.Sprintf("MED: %d, ", b.MED) - ret += fmt.Sprintf("Path ID: %d, ", b.PathIdentifier) - ret += fmt.Sprintf("Source: %s, ", b.Source) - ret += fmt.Sprintf("Communities: %v, ", b.Communities) - ret += fmt.Sprintf("LargeCommunities: %v, ", b.LargeCommunities) + fmt.Fprintf(buf, "Local Pref: %d, ", b.LocalPref) + fmt.Fprintf(buf, "Origin: %s, ", origin) + fmt.Fprintf(buf, "AS Path: %v, ", b.ASPath) + fmt.Fprintf(buf, "BGP type: %s, ", bgpType) + fmt.Fprintf(buf, "NEXT HOP: %s, ", b.NextHop) + fmt.Fprintf(buf, "MED: %d, ", b.MED) + fmt.Fprintf(buf, "Path ID: %d, ", b.PathIdentifier) + fmt.Fprintf(buf, "Source: %s, ", b.Source) + fmt.Fprintf(buf, "Communities: %v, ", b.Communities) + fmt.Fprintf(buf, "LargeCommunities: %v", b.LargeCommunities) if b.OriginatorID != 0 { oid := convert.Uint32Byte(b.OriginatorID) - ret += fmt.Sprintf("OriginatorID: %d.%d.%d.%d, ", oid[0], oid[1], oid[2], oid[3]) + fmt.Fprintf(buf, ", OriginatorID: %d.%d.%d.%d", oid[0], oid[1], oid[2], oid[3]) } if b.ClusterList != nil { - ret += fmt.Sprintf("ClusterList %s", b.ClusterListString()) + fmt.Fprintf(buf, ", ClusterList %s", b.ClusterListString()) } - return ret + return buf.String() } // Print all known information about a route in human readable form func (b *BGPPath) Print() string { + buf := &strings.Builder{} + origin := "" switch b.Origin { case 0: @@ -290,26 +294,26 @@ func (b *BGPPath) Print() string { bgpType = "external" } - ret := fmt.Sprintf("\t\tLocal Pref: %d\n", b.LocalPref) - ret += fmt.Sprintf("\t\tOrigin: %s\n", origin) - ret += fmt.Sprintf("\t\tAS Path: %v\n", b.ASPath) - ret += fmt.Sprintf("\t\tBGP type: %s\n", bgpType) - ret += fmt.Sprintf("\t\tNEXT HOP: %s\n", b.NextHop) - ret += fmt.Sprintf("\t\tMED: %d\n", b.MED) - ret += fmt.Sprintf("\t\tPath ID: %d\n", b.PathIdentifier) - ret += fmt.Sprintf("\t\tSource: %s\n", b.Source) - ret += fmt.Sprintf("\t\tCommunities: %v\n", b.Communities) - ret += fmt.Sprintf("\t\tLargeCommunities: %v\n", b.LargeCommunities) + fmt.Fprintf(buf, "\t\tLocal Pref: %d\n", b.LocalPref) + fmt.Fprintf(buf, "\t\tOrigin: %s\n", origin) + fmt.Fprintf(buf, "\t\tAS Path: %v\n", b.ASPath) + fmt.Fprintf(buf, "\t\tBGP type: %s\n", bgpType) + fmt.Fprintf(buf, "\t\tNEXT HOP: %s\n", b.NextHop) + fmt.Fprintf(buf, "\t\tMED: %d\n", b.MED) + fmt.Fprintf(buf, "\t\tPath ID: %d\n", b.PathIdentifier) + fmt.Fprintf(buf, "\t\tSource: %s\n", b.Source) + fmt.Fprintf(buf, "\t\tCommunities: %v\n", b.Communities) + fmt.Fprintf(buf, "\t\tLargeCommunities: %v\n", b.LargeCommunities) if b.OriginatorID != 0 { oid := convert.Uint32Byte(b.OriginatorID) - ret += fmt.Sprintf("\t\tOriginatorID: %d.%d.%d.%d\n", oid[0], oid[1], oid[2], oid[3]) + fmt.Fprintf(buf, "\t\tOriginatorID: %d.%d.%d.%d\n", oid[0], oid[1], oid[2], oid[3]) } if b.ClusterList != nil { - ret += fmt.Sprintf("\t\tClusterList %s\n", b.ClusterListString()) + fmt.Fprintf(buf, "\t\tClusterList %s\n", b.ClusterListString()) } - return ret + return buf.String() } // Prepend the given BGPPath with the given ASN given times @@ -400,31 +404,44 @@ func (b *BGPPath) ComputeHash() string { // CommunitiesString returns the formated communities func (b *BGPPath) CommunitiesString() string { - str := "" - for _, com := range b.Communities { - str += types.CommunityStringForUint32(com) + " " + str := &strings.Builder{} + + for i, com := range b.Communities { + if i > 0 { + str.WriteByte(' ') + } + str.WriteString(types.CommunityStringForUint32(com)) } - return strings.TrimRight(str, " ") + return str.String() } // ClusterListString returns the formated ClusterList func (b *BGPPath) ClusterListString() string { - str := "" - for _, cid := range b.ClusterList { + str := &strings.Builder{} + + for i, cid := range b.ClusterList { + if i > 0 { + str.WriteByte(' ') + } octes := convert.Uint32Byte(cid) - str += fmt.Sprintf("%d.%d.%d.%d ", octes[0], octes[1], octes[2], octes[3]) + + fmt.Fprintf(str, "%d.%d.%d.%d", octes[0], octes[1], octes[2], octes[3]) } - return strings.TrimRight(str, " ") + return str.String() } // LargeCommunitiesString returns the formated communities func (b *BGPPath) LargeCommunitiesString() string { - str := "" - for _, com := range b.LargeCommunities { - str += com.String() + " " + str := &strings.Builder{} + + for i, com := range b.LargeCommunities { + if i > 0 { + str.WriteByte(' ') + } + str.WriteString(com.String()) } - return strings.TrimRight(str, " ") + return str.String() } diff --git a/route/bgp_path_test.go b/route/bgp_path_test.go index abbd8fb8ff71c29ca1cd18aa3d3a00f1ba7c0c60..dff71dac720eb980952f6444db0be20df6324da2 100644 --- a/route/bgp_path_test.go +++ b/route/bgp_path_test.go @@ -311,9 +311,40 @@ func TestLength(t *testing.T) { for _, test := range tests { calcLen := test.path.Length() + assert.Equal(t, test.expected, calcLen, test.name) + } +} +func TestBGPPathString(t *testing.T) { + tests := []struct { + input BGPPath + expectedPrint string + expectedString string + }{ + { + input: BGPPath{ + EBGP: true, + OriginatorID: 23, + ClusterList: []uint32{10, 20}, + }, + expectedString: "Local Pref: 0, Origin: Incomplete, AS Path: , BGP type: external, NEXT HOP: 0:0:0:0:0:0:0:0, MED: 0, Path ID: 0, Source: 0:0:0:0:0:0:0:0, Communities: [], LargeCommunities: [], OriginatorID: 0.0.0.23, ClusterList 0.0.0.10 0.0.0.20", + expectedPrint: ` Local Pref: 0 + Origin: Incomplete + AS Path: + BGP type: external + NEXT HOP: 0:0:0:0:0:0:0:0 + MED: 0 + Path ID: 0 + Source: 0:0:0:0:0:0:0:0 + Communities: [] + LargeCommunities: [] + OriginatorID: 0.0.0.23 + ClusterList 0.0.0.10 0.0.0.20 +`, + }, + } - if calcLen != test.expected { - t.Errorf("Unexpected result for test %q: Expected: %d Got: %d", test.name, test.expected, calcLen) - } + for _, test := range tests { + assert.Equal(t, test.expectedString, test.input.String()) + assert.Equal(t, test.expectedPrint, test.input.Print()) } }