diff --git a/pkg/api/networkservice/connection_helpers.go b/pkg/api/networkservice/connection_helpers.go index 7a85cba..98ee2b7 100644 --- a/pkg/api/networkservice/connection_helpers.go +++ b/pkg/api/networkservice/connection_helpers.go @@ -2,6 +2,8 @@ // // Copyright (c) 2021 Doc.ai and/or its affiliates. // +// Copyright (c) 2023 Cisco and/or its affiliates. +// // SPDX-License-Identifier: Apache-2.0 // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -124,7 +126,7 @@ func (x *Connection) IsComplete() error { return nil } -// MatchesMonitorScopeSelector - Returns true of the connection matches the selector +// MatchesMonitorScopeSelector - Returns true if the connection matches the selector func (x *Connection) MatchesMonitorScopeSelector(selector *MonitorScopeSelector) bool { if x == nil { return false @@ -133,24 +135,33 @@ func (x *Connection) MatchesMonitorScopeSelector(selector *MonitorScopeSelector) if len(selector.GetPathSegments()) == 0 { return true } - // Iterate through the Connection.NetworkServiceManagers array looking for a subarray that matches - // the selector.NetworkServiceManagers array, treating "" in the selector.NetworkServiceManagers array + // Iterate through the Connection.PathSegments array looking for a subarray that matches + // the selector.PathSegments array, treating "" in the selector.PathSegments array // as a wildcard for i := range x.GetPath().GetPathSegments() { - // If there aren't enough elements left in the Connection.NetworkServiceManagers array to match - // all of the elements in the select.NetworkServiceManager array...clearly we can't match + // If there aren't enough elements left in the Connection.PathSegments array to match + // all of the elements in the select.PathSegments array...clearly we can't match if i+len(selector.GetPathSegments()) > len(x.GetPath().GetPathSegments()) { return false } - // Iterate through the selector.NetworkServiceManagers array to see is the subarray starting at - // Connection.NetworkServiceManagers[i] matches selector.NetworkServiceManagers + // Iterate through the selector.PathSegments array to see is the subarray starting at + // Connection.PathSegments[i] matches selector.PathSegments for j := range selector.GetPathSegments() { // "" matches as a wildcard... failure to match either as wildcard or exact match means the subarray - // starting at Connection.NetworkServiceManagers[i] doesn't match selectors.NetworkServiceManagers + // starting at Connection.PathSegments[i] doesn't match selectors.PathSegments if selector.GetPathSegments()[j].GetName() != "" && x.GetPath().GetPathSegments()[i+j].GetName() != selector.GetPathSegments()[j].GetName() { break } - // If this is the last element in the selector.NetworkServiceManagers array and we still are matching... + + if selector.GetPathSegments()[j].GetId() != "" && x.GetPath().GetPathSegments()[i+j].GetId() != selector.GetPathSegments()[j].GetId() { + break + } + + if selector.GetPathSegments()[j].GetToken() != "" && x.GetPath().GetPathSegments()[i+j].GetToken() != selector.GetPathSegments()[j].GetToken() { + break + } + + // If this is the last element in the selector.PathSegments array and we still are matching... // return true if j == len(selector.GetPathSegments())-1 { return true diff --git a/pkg/api/networkservice/connection_helpers_test.go b/pkg/api/networkservice/connection_helpers_test.go new file mode 100644 index 0000000..2ab3fc1 --- /dev/null +++ b/pkg/api/networkservice/connection_helpers_test.go @@ -0,0 +1,101 @@ +// Copyright (c) 2023 Cisco and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// 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 networkservice_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/networkservicemesh/api/pkg/api/networkservice" +) + +// nolint: funlen +func TestMonitorScopeSelector(t *testing.T) { + cases := []struct { + testname string + connSegments []*networkservice.PathSegment + selectorSegments []*networkservice.PathSegment + matches bool + }{ + { + testname: "IdenticalPaths", + connSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1", Token: "t1"}, {Name: "s2", Id: "id2", Token: "t2"}}, + selectorSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1", Token: "t1"}, {Name: "s2", Id: "id2", Token: "t2"}}, + matches: true, + }, + { + testname: "DifferentNames", + connSegments: []*networkservice.PathSegment{{Name: "s15", Id: "id1", Token: "t1"}, {Name: "s2", Id: "id2", Token: "t2"}}, + selectorSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1", Token: "t1"}, {Name: "s2", Id: "id2", Token: "t2"}}, + matches: false, + }, + { + testname: "DifferentIds", + connSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id15", Token: "t1"}, {Name: "s2", Id: "id2", Token: "t2"}}, + selectorSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1", Token: "t1"}, {Name: "s2", Id: "id2", Token: "t2"}}, + matches: false, + }, + { + testname: "DifferentTokens", + connSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1", Token: "t1"}, {Name: "s2", Id: "id2", Token: "t2"}}, + selectorSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1", Token: "t15"}, {Name: "s2", Id: "id2", Token: "t2"}}, + matches: false, + }, + { + testname: "SelectorPathIsLonger", + connSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1"}, {Name: "s2", Id: "id2"}}, + selectorSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1"}, {Name: "s2", Id: "id2"}, {Name: "s3", Id: "id3"}}, + matches: false, + }, + { + testname: "ConnPathContainsSelectorPath", + connSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1"}, {Name: "s2", Id: "id2"}, {Name: "s3", Id: "id3"}}, + selectorSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1"}, {Name: "s2", Id: "id2"}}, + matches: true, + }, + { + testname: "EmptyID", + connSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1"}, {Name: "s2", Id: "id2"}}, + selectorSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1"}, {Name: "s2", Id: ""}}, + matches: true, + }, + { + testname: "EmptyName", + connSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1"}, {Name: "s2", Id: "id2"}}, + selectorSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1"}, {Name: "", Id: "id2"}}, + matches: true, + }, + { + testname: "EmptyToken", + connSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1", Token: "t1"}, {Name: "s2", Id: "id2", Token: "t2"}}, + selectorSegments: []*networkservice.PathSegment{{Name: "s1", Id: "id1", Token: "t1"}, {Name: "", Id: "id2", Token: ""}}, + matches: true, + }, + } + + for _, testCase := range cases { + c := testCase + t.Run(c.testname, func(t *testing.T) { + path := &networkservice.Path{PathSegments: c.connSegments} + conn := networkservice.Connection{Path: path} + selector := &networkservice.MonitorScopeSelector{PathSegments: c.selectorSegments} + + require.Equal(t, conn.MatchesMonitorScopeSelector(selector), c.matches) + }) + } +}