VOL-3121 - Separated out logical ports from logical agent.
Similar to flows/groups/meters.
Also modified device_route tests to generate unique port IDs (`.OfpPort.PortNo`s) across all UNI ports withing each test, i.e. within an OLT.
Also replaced logicalPortsNo map & associated NNI vs UNI logic with root device checks.
Change-Id: Ib0cecbf7d4f8d509ce7c989b9ccf697c8b0d17d6
diff --git a/rw_core/core/device/flow/loader_test.go b/rw_core/core/device/flow/loader_test.go
index b739272..8973f12 100644
--- a/rw_core/core/device/flow/loader_test.go
+++ b/rw_core/core/device/flow/loader_test.go
@@ -22,34 +22,43 @@
"os"
"regexp"
"strconv"
- "strings"
"testing"
)
// TestLoadersIdentical ensures that the group, flow, and meter loaders always have an identical implementation.
func TestLoadersIdentical(t *testing.T) {
+ types := []string{"flow", "group", "meter", "logical_port"}
+
identical := [][]string{
- {"ofp\\.OfpFlowStats", "ofp\\.OfpGroupEntry", "ofp\\.OfpMeterEntry"},
- {"\\.Id", "\\.Desc\\.GroupId", "\\.Config.MeterId"},
- {"uint64", "uint32", "uint32"},
- {"Flow", "Group", "Meter"},
- {"flow", "group", "meter"},
+ {`ofp\.OfpFlowStats`, `ofp\.OfpGroupEntry`, `ofp\.OfpMeterEntry`, `voltha\.LogicalPort`},
+ {`\.Id`, `\.Desc\.GroupId`, `\.Config\.MeterId`, `\.OfpPort\.PortNo`},
+ {`uint64`, `uint32`, `uint32`, `uint32`},
+ {`Flow`, `Group`, `Meter`, `Port`},
+ {`flow`, `group`, `meter`, `port|logical_port`},
}
- regexes := make([]*regexp.Regexp, len(identical))
+ regexes := make([][]*regexp.Regexp, len(identical[0]))
+ for i := range regexes {
+ regexes[i] = make([]*regexp.Regexp, len(identical))
+ }
for i, group := range identical {
- regexes[i] = regexp.MustCompile(strings.Join(group, "|"))
+ for j, regexStr := range group {
+ // convert from column-wise to row-wise for convenience
+ regexes[j][i] = regexp.MustCompile(regexStr)
+ }
}
- for i := 1; i < len(identical[0]); i++ {
- if err := compare(regexes, "../"+identical[4][0]+"/loader.go", "../"+identical[4][i]+"/loader.go"); err != nil {
+ for i := 1; i < len(types); i++ {
+ if err := compare(regexes[0], regexes[i],
+ "../"+types[0]+"/loader.go",
+ "../"+types[i]+"/loader.go"); err != nil {
t.Error(err)
return
}
}
}
-func compare(regexes []*regexp.Regexp, fileNameA, fileNameB string) error {
+func compare(regexesA, regexesB []*regexp.Regexp, fileNameA, fileNameB string) error {
fileA, err := os.Open(fileNameA)
if err != nil {
return err
@@ -64,43 +73,63 @@
scannerA, scannerB := bufio.NewScanner(fileA), bufio.NewScanner(fileB)
- spaceRegex := regexp.MustCompile(" +")
+ // treat any number of spaces as a single space
+ spaceRegex := regexp.MustCompile(` +`)
+ // extra lines are permitted before a "blank" line, or before a lock/unlock
+ spacerRegex := regexp.MustCompile(`^(?:[^a-z]*|.*Lock\(\)|.*Unlock\(\))$`)
+ // ignore import type differences
+ libGoImportRegex := regexp.MustCompile(`^.*github\.com/opencord/voltha-protos/.*$`)
- line := 1
+ lineA, lineB := 1, 1
+linesLoop:
for {
- if continueA, continueB := scannerA.Scan(), scannerB.Scan(); continueA != continueB {
- if !continueA && continueB {
- if err := scannerA.Err(); err != nil {
- return err
+ if continueA, continueB := scannerA.Scan(), scannerB.Scan(); !continueA || !continueB {
+ // EOF
+ break linesLoop
+ }
+ textA, textB := scannerA.Text(), scannerB.Text()
+
+ // allow any number of "extra" lines just before a spacer line
+ for {
+ isSpacerA, isSpacerB := spacerRegex.MatchString(textA), spacerRegex.MatchString(textB)
+ if isSpacerA && !isSpacerB {
+ if !scannerB.Scan() {
+ // EOF
+ break linesLoop
}
- }
- if continueA && !continueB {
- if err := scannerB.Err(); err != nil {
- return err
+ lineB++
+ textB = scannerB.Text()
+ continue
+ } else if isSpacerB && !isSpacerA {
+ if !scannerA.Scan() {
+ // EOF
+ break linesLoop
}
+ lineA++
+ textA = scannerA.Text()
+ continue
}
- return fmt.Errorf("line %d: files are not the same length", line)
- } else if !continueA {
- // EOF from both files
break
}
- textA, textB := scannerA.Text(), scannerB.Text()
-
replacedA, replacedB := textA, textB
- for i, regex := range regexes {
+ for i := range regexesA {
replacement := "{{type" + strconv.Itoa(i) + "}}"
- replacedA, replacedB = regex.ReplaceAllString(replacedA, replacement), regex.ReplaceAllString(replacedB, replacement)
+ replacedA, replacedB = regexesA[i].ReplaceAllString(replacedA, replacement), regexesB[i].ReplaceAllString(replacedB, replacement)
}
// replace multiple spaces with single space
replacedA, replacedB = spaceRegex.ReplaceAllString(replacedA, " "), spaceRegex.ReplaceAllString(replacedB, " ")
- if replacedA != replacedB {
- return fmt.Errorf("line %d: files %s and %s do not match: \n\t%s\n\t%s\n\n\t%s\n\t%s", line, fileNameA, fileNameB, textA, textB, replacedA, replacedB)
+ // ignore voltha-protos import of ofp vs voltha
+ replacedA, replacedB = libGoImportRegex.ReplaceAllString(replacedA, "{{lib-go-import}}"), libGoImportRegex.ReplaceAllString(replacedB, "{{lib-go-import}}")
+
+ if replacedA != replacedB && textA != textB {
+ return fmt.Errorf("files which must be identical do not match: \n %s:%d\n %s\n %s:%d\n %s\n\n\t%s\n\t%s", fileNameA, lineA, textA, fileNameB, lineB, textB, replacedA, replacedB)
}
- line++
+ lineA++
+ lineB++
}
if err := scannerA.Err(); err != nil {