From 1b6d5072e52bebd5f3a3b171e566e576c7c4b273 Mon Sep 17 00:00:00 2001
From: Christoph Petrausch <christoph.petrausch@inovex.de>
Date: Sun, 10 Jun 2018 15:44:33 +0200
Subject: [PATCH] Added tests for large community string parsing

---
 protocols/bgp/packet/large_community.go      | 10 ++-
 protocols/bgp/packet/large_community_test.go | 86 ++++++++++++++++++++
 2 files changed, 92 insertions(+), 4 deletions(-)
 create mode 100644 protocols/bgp/packet/large_community_test.go

diff --git a/protocols/bgp/packet/large_community.go b/protocols/bgp/packet/large_community.go
index 5b3f7788..7547fd60 100644
--- a/protocols/bgp/packet/large_community.go
+++ b/protocols/bgp/packet/large_community.go
@@ -2,10 +2,13 @@ package packet
 
 import (
 	"fmt"
+	"regexp"
 	"strconv"
 	"strings"
 )
 
+var largeCommunityRegEx = regexp.MustCompile("^\\(?\\d+,\\d+,\\d+\\)?$")
+
 type LargeCommunity struct {
 	GlobalAdministrator uint32
 	DataPart1           uint32
@@ -17,13 +20,12 @@ func (c LargeCommunity) String() string {
 }
 
 func ParseLargeCommunityString(s string) (com LargeCommunity, err error) {
+	if !largeCommunityRegEx.Match([]byte(s)) {
+		return com, fmt.Errorf("malformed large community string %s", s)
+	}
 	s = strings.Trim(s, "()")
 	t := strings.Split(s, ",")
 
-	if len(t) != 3 {
-		return com, fmt.Errorf("can not parse large community %s", s)
-	}
-
 	v, err := strconv.ParseUint(t[0], 10, 32)
 	if err != nil {
 		return com, err
diff --git a/protocols/bgp/packet/large_community_test.go b/protocols/bgp/packet/large_community_test.go
new file mode 100644
index 00000000..867fe27e
--- /dev/null
+++ b/protocols/bgp/packet/large_community_test.go
@@ -0,0 +1,86 @@
+package packet
+
+import (
+	"errors"
+	"testing"
+
+	"fmt"
+	"math"
+
+	"strconv"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestParseLargeCommunityString(t *testing.T) {
+	tests := []struct {
+		name     string
+		in       string
+		expected LargeCommunity
+		err      error
+	}{
+		{
+			name: "normal large community",
+			in:   "(1,2,3)",
+			expected: LargeCommunity{
+				GlobalAdministrator: 1,
+				DataPart1:           2,
+				DataPart2:           3,
+			},
+			err: nil,
+		},
+		{
+			name:     "too short community",
+			in:       "(1,2)",
+			expected: LargeCommunity{},
+			err:      errors.New("malformed large community string (1,2)"),
+		},
+		{
+			name: "missing parentheses large community",
+			in:   "1,2,3",
+			expected: LargeCommunity{
+				GlobalAdministrator: 1,
+				DataPart1:           2,
+				DataPart2:           3,
+			},
+			err: nil,
+		},
+		{
+			name:     "malformed large community",
+			in:       "[1,2,3]",
+			expected: LargeCommunity{},
+			err:      errors.New("malformed large community string [1,2,3]"),
+		},
+		{
+			name:     "missing digit",
+			in:       "(,2,3)",
+			expected: LargeCommunity{},
+			err:      errors.New("malformed large community string (,2,3)"),
+		},
+		{
+			name:     "to big global administrator",
+			in:       fmt.Sprintf("(%d,1,2)", math.MaxInt64),
+			expected: LargeCommunity{},
+			err:      &strconv.NumError{Func: "ParseUint", Num: fmt.Sprintf("%d", math.MaxInt64), Err: strconv.ErrRange},
+		},
+		{
+			name:     "to big data part 1",
+			in:       fmt.Sprintf("(1,%d,2)", math.MaxInt64),
+			expected: LargeCommunity{1, 0, 0},
+			err:      &strconv.NumError{Func: "ParseUint", Num: fmt.Sprintf("%d", math.MaxInt64), Err: strconv.ErrRange},
+		},
+		{
+			name:     "to big data part 2",
+			in:       fmt.Sprintf("(1,2,%d)", math.MaxInt64),
+			expected: LargeCommunity{1, 2, 0},
+			err:      &strconv.NumError{Func: "ParseUint", Num: fmt.Sprintf("%d", math.MaxInt64), Err: strconv.ErrRange},
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			com, err := ParseLargeCommunityString(test.in)
+			assert.Equal(t, test.err, err)
+			assert.Equal(t, test.expected, com)
+		})
+	}
+}
-- 
GitLab