blob: 84b00e83c2cdf19e490bdc2aea876256dcc4764c [file] [log] [blame]
/*
* Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors
* 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.
*/
/*
This file contains unit test cases for functions in the file resourcemanager.go.
This file also implements the Client interface to mock the kv-client, fields struct to mock OpenOltResourceMgr
and few utility functions.
*/
//Package adaptercore provides the utility for olt devices, flows and statistics
package resourcemanager
import (
"context"
"encoding/json"
"errors"
"fmt"
"reflect"
"strconv"
"strings"
"testing"
"time"
"github.com/opencord/voltha-lib-go/v7/pkg/techprofile"
"github.com/opencord/voltha-openolt-adapter/pkg/mocks"
"github.com/opencord/voltha-lib-go/v7/pkg/db"
"github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
fu "github.com/opencord/voltha-lib-go/v7/pkg/flows"
"github.com/opencord/voltha-lib-go/v7/pkg/log"
ponrmgr "github.com/opencord/voltha-lib-go/v7/pkg/ponresourcemanager"
ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
"github.com/opencord/voltha-protos/v5/go/openolt"
)
func init() {
_, _ = log.SetDefaultLogger(log.JSON, log.DebugLevel, nil)
}
const (
// MeterConfig meter to extract meter
MeterConfig = "meter_id"
// TpIDSuffixPath to extract Techprofile
// TpIDSuffixPath = "tp_id"
// FlowIDInfo to extract flows
FlowIDInfo = "flow_id_info"
// FlowIds to extract flows
FlowIDs = "flow_ids"
// GemportIDs to gemport_ids
GemportIDs = "gemport_ids"
// AllocIDs to extract alloc_ids
AllocIDs = "alloc_ids"
// GemportIDPool to extract gemport
GemportIDPool = "gemport_id_pool"
// AllocIDPool to extract allocid
AllocIDPool = "alloc_id_pool"
// FlowIDpool to extract Flow ids
FlowIDpool = "flow_id_pool"
)
// fields mocks OpenOltResourceMgr struct.
type fields struct {
DeviceID string
Address string
Args string
KVStore *db.Backend
DeviceType string
DevInfo *openolt.DeviceInfo
PonRsrMgr *ponrmgr.PONResourceManager
NumOfPonPorts uint32
TechProfileRef techprofile.TechProfileIf
}
// MockKVClient mocks the AdapterProxy interface.
type MockResKVClient struct {
}
// getResMgr mocks OpenOltResourceMgr struct.
func getResMgr() *fields {
var resMgr fields
resMgr.KVStore = &db.Backend{
Client: &MockResKVClient{},
}
resMgr.PonRsrMgr = &ponrmgr.PONResourceManager{}
ranges := make(map[string]interface{})
sharedIdxByType := make(map[string]string)
sharedIdxByType["ALLOC_ID"] = "ALLOC_ID"
sharedIdxByType["ONU_ID"] = "ONU_ID"
sharedIdxByType["GEMPORT_ID"] = "GEMPORT_ID"
sharedIdxByType["FLOW_ID"] = "FLOW_ID"
ranges["ONU_ID"] = uint32(0)
ranges["GEMPORT_ID"] = uint32(0)
ranges["ALLOC_ID"] = uint32(0)
ranges["FLOW_ID"] = uint32(0)
ranges["onu_id_shared"] = uint32(0)
ranges["alloc_id_shared"] = uint32(0)
ranges["gemport_id_shared"] = uint32(0)
ranges["flow_id_shared"] = uint32(0)
resMgr.NumOfPonPorts = 16
resMgr.DevInfo = &openolt.DeviceInfo{PonPorts: 16}
resMgr.PonRsrMgr.DeviceID = "onu-1"
resMgr.PonRsrMgr.IntfIDs = []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
resMgr.PonRsrMgr.KVStore = &db.Backend{
Client: &MockResKVClient{},
}
resMgr.PonRsrMgr.Technology = "XGS-PON"
resMgr.PonRsrMgr.PonResourceRanges = ranges
resMgr.PonRsrMgr.SharedIdxByType = sharedIdxByType
resMgr.TechProfileRef = mocks.MockTechProfile{}
/*
tpMgr, err := tp.NewTechProfile(ctx, resMgr.PonRsrMgr, "etcd", "127.0.0.1", "/")
if err != nil {
logger.Fatal(ctx, err.Error())
}
*/
return &resMgr
}
// List function implemented for KVClient.
func (kvclient *MockResKVClient) List(ctx context.Context, key string) (map[string]*kvstore.KVPair, error) {
return nil, errors.New("key didn't find")
}
// Get mock function implementation for KVClient
func (kvclient *MockResKVClient) Get(ctx context.Context, key string) (*kvstore.KVPair, error) {
logger.Debugw(ctx, "Warning Warning Warning: Get of MockKVClient called", log.Fields{"key": key})
if key != "" {
if strings.Contains(key, MeterConfig) {
var bands []*ofp.OfpMeterBandHeader
bands = append(bands, &ofp.OfpMeterBandHeader{Type: ofp.OfpMeterBandType_OFPMBT_DSCP_REMARK,
Rate: 1024, Data: &ofp.OfpMeterBandHeader_DscpRemark{DscpRemark: &ofp.OfpMeterBandDscpRemark{PrecLevel: 2}}})
bands = append(bands, &ofp.OfpMeterBandHeader{Type: ofp.OfpMeterBandType_OFPMBT_DSCP_REMARK,
Rate: 1024, Data: &ofp.OfpMeterBandHeader_DscpRemark{DscpRemark: &ofp.OfpMeterBandDscpRemark{PrecLevel: 3}}})
sep := strings.Split(key, "/")[1]
val, _ := strconv.ParseInt(strings.Split(sep, ",")[1], 10, 32)
if uint32(val) > 1 {
meterConfig := &ofp.OfpMeterConfig{MeterId: uint32(val), Bands: bands}
str, _ := json.Marshal(meterConfig)
return kvstore.NewKVPair(key, str, "mock", 3000, 1), nil
}
return nil, errors.New("invalid meter")
}
if strings.Contains(key, FlowIDpool) || strings.Contains(key, GemportIDPool) || strings.Contains(key, AllocIDPool) {
logger.Debug(ctx, "Error Error Error Key:", FlowIDpool, GemportIDPool, AllocIDPool)
data := make(map[string]interface{})
data["pool"] = "1024"
data["start_idx"] = 1
data["end_idx"] = 1024
str, _ := json.Marshal(data)
return kvstore.NewKVPair(key, str, "mock", 3000, 1), nil
}
if strings.Contains(key, FlowIDInfo) || strings.Contains(key, FlowIDs) {
logger.Debug(ctx, "Error Error Error Key:", FlowIDs, FlowIDInfo)
str, _ := json.Marshal([]uint32{1, 2})
return kvstore.NewKVPair(key, str, "mock", 3000, 1), nil
}
if strings.Contains(key, AllocIDs) || strings.Contains(key, GemportIDs) {
logger.Debug(ctx, "Error Error Error Key:", AllocIDs, GemportIDs)
str, _ := json.Marshal(1)
return kvstore.NewKVPair(key, str, "mock", 3000, 1), nil
}
if strings.Contains(key, McastQueuesForIntf) {
logger.Debug(ctx, "Error Error Error Key:", McastQueuesForIntf)
mcastQueues := make(map[uint32][]uint32)
mcastQueues[10] = []uint32{4000, 0}
str, _ := json.Marshal(mcastQueues)
return kvstore.NewKVPair(key, str, "mock", 3000, 1), nil
}
if strings.Contains(key, "flow_groups") && !strings.Contains(key, "1000") {
groupInfo := GroupInfo{GroupID: 2, OutPorts: []uint32{2}}
str, _ := json.Marshal(groupInfo)
return kvstore.NewKVPair(key, str, "mock", 3000, 1), nil
}
maps := make(map[string]*kvstore.KVPair)
maps[key] = &kvstore.KVPair{Key: key}
return maps[key], nil
}
return nil, errors.New("key didn't find")
}
// Put mock function implementation for KVClient
func (kvclient *MockResKVClient) Put(ctx context.Context, key string, value interface{}) error {
if key != "" {
return nil
}
return errors.New("key didn't find")
}
// Delete mock function implementation for KVClient
func (kvclient *MockResKVClient) Delete(ctx context.Context, key string) error {
return nil
}
// DeleteWithPrefix mock function implementation for KVClient
func (kvclient *MockResKVClient) DeleteWithPrefix(ctx context.Context, prefix string) error {
return nil
}
// Reserve mock function implementation for KVClient
func (kvclient *MockResKVClient) Reserve(ctx context.Context, key string, value interface{}, ttl time.Duration) (interface{}, error) {
return nil, errors.New("key didn't find")
}
// ReleaseReservation mock function implementation for KVClient
func (kvclient *MockResKVClient) ReleaseReservation(ctx context.Context, key string) error {
return nil
}
// ReleaseAllReservations mock function implementation for KVClient
func (kvclient *MockResKVClient) ReleaseAllReservations(ctx context.Context) error {
return nil
}
// RenewReservation mock function implementation for KVClient
func (kvclient *MockResKVClient) RenewReservation(ctx context.Context, key string) error {
return nil
}
// Watch mock function implementation for KVClient
func (kvclient *MockResKVClient) Watch(ctx context.Context, key string, withPrefix bool) chan *kvstore.Event {
return nil
}
// AcquireLock mock function implementation for KVClient
func (kvclient *MockResKVClient) AcquireLock(ctx context.Context, lockName string, timeout time.Duration) error {
return nil
}
// ReleaseLock mock function implementation for KVClient
func (kvclient *MockResKVClient) ReleaseLock(lockName string) error {
return nil
}
// IsConnectionUp mock function implementation for KVClient
func (kvclient *MockResKVClient) IsConnectionUp(ctx context.Context) bool { // timeout in second
return true
}
// CloseWatch mock function implementation for KVClient
func (kvclient *MockResKVClient) CloseWatch(ctx context.Context, key string, ch chan *kvstore.Event) {
}
// Close mock function implementation for KVClient
func (kvclient *MockResKVClient) Close(ctx context.Context) {
}
// testResMgrObject maps fields type to OpenOltResourceMgr type.
func testResMgrObject(testResMgr *fields) *OpenOltResourceMgr {
var rsrMgr = OpenOltResourceMgr{
DeviceID: testResMgr.DeviceID,
Args: testResMgr.Args,
KVStore: testResMgr.KVStore,
DeviceType: testResMgr.DeviceType,
Address: testResMgr.Address,
DevInfo: testResMgr.DevInfo,
PonRsrMgr: testResMgr.PonRsrMgr,
TechprofileRef: testResMgr.TechProfileRef,
}
rsrMgr.InitLocalCache()
return &rsrMgr
}
func TestNewResourceMgr(t *testing.T) {
type args struct {
deviceID string
intfID uint32
KVStoreAddress string
kvStoreType string
deviceType string
devInfo *openolt.DeviceInfo
kvStorePrefix string
}
/* As of not the current NewResourceMgr test is not doing anything as there was no resourceranges passed.
passing the resource ranges would mean passing a mock and changes in all around including device handler and other places.
For now , removed the older version of proto which used ONUIDSTart and ONUIDENd which is not valid.
This test needs to be updated once the kv store mock is fixed all around. Use the below resource ranges in the Ranges of deviceinfo once the kv store is fixed.
intfids := []uint32{0, 1, 2, 3, 4, 5}
devOnuRsrcPools := &openolt.DeviceInfo_DeviceResourceRanges_Pool{Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID, Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF, Start: 1, End: 60}
devGemRsrcPools := &openolt.DeviceInfo_DeviceResourceRanges_Pool{Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID, Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF, Start: 1, End: 10000}
devAllocRsrcPools := &openolt.DeviceInfo_DeviceResourceRanges_Pool{Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID, Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF, Start: 1, End: 256}
devFlowRsrcPools := &openolt.DeviceInfo_DeviceResourceRanges_Pool{Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID, Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_SAME_TECH, Start: 1, End: 20000}
pool := []*openolt.DeviceInfo_DeviceResourceRanges_Pool{devOnuRsrcPools, devGemRsrcPools, devAllocRsrcPools, devFlowRsrcPools}
devRsrc := &openolt.DeviceInfo_DeviceResourceRanges{IntfIds: intfids, Technology: "GPON", Pools: pool}
devRsrcPool := []*openolt.DeviceInfo_DeviceResourceRanges{devRsrc}
*/
tests := []struct {
name string
args args
want *OpenOltResourceMgr
}{
{"NewResourceMgr-2", args{"olt1", 0, "1:2", "etcd",
"olt", &openolt.DeviceInfo{}, "service/voltha"}, &OpenOltResourceMgr{}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if got := NewResourceMgr(ctx, tt.args.intfID, tt.args.deviceID, tt.args.KVStoreAddress, tt.args.kvStoreType, tt.args.deviceType, tt.args.devInfo, tt.args.kvStorePrefix); reflect.TypeOf(got) != reflect.TypeOf(tt.want) {
t.Errorf("NewResourceMgr() = %v, want %v", got, tt.want)
}
})
}
}
func TestOpenOltResourceMgr_Delete(t *testing.T) {
type args struct {
intfID uint32
}
tests := []struct {
name string
fields *fields
wantErr error
args args
}{
{"Delete-1", getResMgr(), errors.New("failed to clear device resource pool"), args{intfID: 0}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := RsrcMgr.Delete(ctx, tt.args.intfID); (err != nil) && reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) {
t.Errorf("Delete() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestOpenOltResourceMgr_FreePONResourcesForONU(t *testing.T) {
type args struct {
intfID uint32
onuID uint32
uniID uint32
}
tests := []struct {
name string
fields *fields
args args
}{
{"FreePONResourcesForONU-1", getResMgr(), args{1, 0, 2}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
RsrcMgr.FreePONResourcesForONU(ctx, tt.args.onuID, tt.args.uniID)
})
}
}
func TestOpenOltResourceMgr_FreeonuID(t *testing.T) {
type args struct {
intfID uint32
onuID []uint32
}
tests := []struct {
name string
fields *fields
args args
}{
{"FreeOnuID-1", getResMgr(), args{1, []uint32{1, 2}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
RsrcMgr.FreeonuID(ctx, tt.args.onuID)
})
}
}
func TestOpenOltResourceMgr_GetCurrentAllocIDForOnu(t *testing.T) {
type args struct {
intfID uint32
onuID uint32
uniID uint32
}
tests := []struct {
name string
fields *fields
args args
want []uint32
}{
{"GetCurrentAllocIDForOnu-1", getResMgr(), args{1, 2, 2}, []uint32{}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
got := RsrcMgr.GetCurrentAllocIDsForOnu(ctx, tt.args.onuID, tt.args.uniID)
if len(got) != len(tt.want) {
t.Errorf("GetCurrentAllocIDsForOnu() = %v, want %v", got, tt.want)
} else {
for i := range tt.want {
if got[i] != tt.want[i] {
t.Errorf("GetCurrentAllocIDsForOnu() = %v, want %v", got, tt.want)
break
}
}
}
})
}
}
func TestOpenOltResourceMgr_DeleteAllFlowIDsForGemForIntf(t *testing.T) {
type args struct {
PONIntfID uint32
}
tests := []struct {
name string
fields *fields
args args
want error
}{
{"DeleteAllFlowIDsForGemForIntf-1", getResMgr(), args{0}, nil},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := RsrcMgr.DeleteAllFlowIDsForGemForIntf(ctx)
if err != nil {
t.Errorf("DeleteAllFlowIDsForGemForIntf() returned error")
}
})
}
}
func TestOpenOltResourceMgr_DeleteAllOnuGemInfoForIntf(t *testing.T) {
type args struct {
PONIntfID uint32
}
tests := []struct {
name string
fields *fields
args args
want error
}{
{"DeleteAllOnuGemInfoForIntf-1", getResMgr(), args{0}, nil},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := RsrcMgr.DeleteAllOnuGemInfoForIntf(ctx)
if err != nil {
t.Errorf("DeleteAllOnuGemInfoForIntf() returned error")
}
})
}
}
func TestOpenOltResourceMgr_deleteGemPort(t *testing.T) {
type args struct {
intfID uint32
onuID uint32
gemPortIDs []uint32
gemPortIDsToBeDeleted []uint32
gemPortIDsRemaining []uint32
serialNum string
finalLength int
}
tests := []struct {
name string
fields *fields
args args
}{
// Add/Delete single gem port
{"DeleteGemPortFromLocalCache1", getResMgr(), args{0, 1, []uint32{1}, []uint32{1}, []uint32{}, "onu1", 0}},
// Delete all gemports
{"DeleteGemPortFromLocalCache2", getResMgr(), args{0, 1, []uint32{1, 2, 3, 4}, []uint32{1, 2, 3, 4}, []uint32{}, "onu1", 0}},
// Try to delete when there is no gem port
{"DeleteGemPortFromLocalCache3", getResMgr(), args{0, 1, []uint32{}, []uint32{1, 2}, nil, "onu1", 0}},
// Try to delete non-existent gem port
{"DeleteGemPortFromLocalCache4", getResMgr(), args{0, 1, []uint32{1}, []uint32{2}, []uint32{1}, "onu1", 1}},
// Try to delete two of the gem ports
{"DeleteGemPortFromLocalCache5", getResMgr(), args{0, 1, []uint32{1, 2, 3, 4}, []uint32{2, 4}, []uint32{1, 3}, "onu1", 2}},
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
if err := RsrcMgr.DelOnuGemInfo(ctx, tt.args.onuID); err != nil {
t.Errorf("failed to remove onu")
}
if err := RsrcMgr.AddNewOnuGemInfoToCacheAndKvStore(ctx, tt.args.onuID, tt.args.serialNum); err != nil {
t.Errorf("failed to add onu")
}
for _, gemPort := range tt.args.gemPortIDs {
if err := RsrcMgr.AddGemToOnuGemInfo(ctx, tt.args.onuID, gemPort); err != nil {
t.Errorf("failed to add gem to onu")
}
}
for _, gemPortDeleted := range tt.args.gemPortIDsToBeDeleted {
if err := RsrcMgr.RemoveGemFromOnuGemInfo(ctx, tt.args.onuID, gemPortDeleted); err != nil {
t.Errorf("failed to remove gem from onu")
}
}
lenofGemPorts := 0
gP, err := RsrcMgr.GetOnuGemInfo(ctx, tt.args.onuID)
if err != nil || gP == nil {
t.Errorf("failed to get onuGemInfo")
}
var gemPorts []uint32
lenofGemPorts = len(gP.GemPorts)
gemPorts = gP.GemPorts
if lenofGemPorts != tt.args.finalLength {
t.Errorf("GemPorts length is not as expected len = %d, want %d", lenofGemPorts, tt.args.finalLength)
}
if !reflect.DeepEqual(tt.args.gemPortIDsRemaining, gemPorts) {
t.Errorf("GemPorts are not as expected = %v, want %v", gemPorts, tt.args.gemPortIDsRemaining)
}
})
}
}
func TestOpenOltResourceMgr_AddNewOnuGemInfo(t *testing.T) {
type args struct {
PONIntfID uint32
OnuCount uint32
}
tests := []struct {
name string
fields *fields
args args
want error
}{
{"AddNewOnuGemInfoForIntf-0", getResMgr(), args{0, 32}, nil},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
for j := 1; j <= int(tt.args.OnuCount); j++ {
go func(i uint32, j uint32) {
// TODO: actually verify success
_ = RsrcMgr.AddNewOnuGemInfoToCacheAndKvStore(ctx, i, fmt.Sprintf("onu-%d", i))
}(tt.args.PONIntfID, uint32(j))
}
})
}
}
func TestOpenOltFlowMgr_addGemPortToOnuInfoMap(t *testing.T) {
type args struct {
intfID uint32
onuID uint32
gemPortIDs []uint32
gemPortIDsRemaining []uint32
serialNum string
finalLength int
}
tests := []struct {
name string
fields *fields
args args
}{
// Add single gem port
{"addGemPortToOnuInfoMap1", getResMgr(), args{0, 1, []uint32{1}, []uint32{1}, "onu1", 1}},
// Delete all gemports
{"addGemPortToOnuInfoMap2", getResMgr(), args{0, 1, []uint32{1, 2, 3, 4}, []uint32{1, 2, 3, 4}, "onu1", 4}},
// Do not add any gemport
{"addGemPortToOnuInfoMap3", getResMgr(), args{0, 1, []uint32{}, nil, "onu1", 0}},
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
if err := RsrcMgr.DelOnuGemInfo(ctx, tt.args.onuID); err != nil {
t.Errorf("failed to remove onu")
}
if err := RsrcMgr.AddNewOnuGemInfoToCacheAndKvStore(ctx, tt.args.onuID, tt.args.serialNum); err != nil {
t.Errorf("failed to add onu")
}
for _, gemPort := range tt.args.gemPortIDs {
if err := RsrcMgr.AddGemToOnuGemInfo(ctx, tt.args.onuID, gemPort); err != nil {
t.Errorf("failed to add gem to onu")
}
}
lenofGemPorts := 0
gP, err := RsrcMgr.GetOnuGemInfo(ctx, tt.args.onuID)
var gemPorts []uint32
if err == nil && gP != nil {
lenofGemPorts = len(gP.GemPorts)
gemPorts = gP.GemPorts
}
if lenofGemPorts != tt.args.finalLength {
t.Errorf("GemPorts length is not as expected len = %d, want %d", lenofGemPorts, tt.args.finalLength)
}
if !reflect.DeepEqual(tt.args.gemPortIDsRemaining, gemPorts) {
t.Errorf("GemPorts are not as expected = %v, want %v", gemPorts, tt.args.gemPortIDsRemaining)
}
})
}
}
func TestOpenOltResourceMgr_GetCurrentGEMPortIDsForOnu(t *testing.T) {
type args struct {
intfID uint32
onuID uint32
uniID uint32
}
tests := []struct {
name string
fields *fields
args args
want []uint32
}{
{"GetCurrentGEMPortIDsForOnu-1", getResMgr(), args{1, 2, 2}, []uint32{}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if got := RsrcMgr.GetCurrentGEMPortIDsForOnu(ctx, tt.args.onuID, tt.args.uniID); reflect.TypeOf(got) != reflect.TypeOf(tt.want) {
t.Errorf("GetCurrentGEMPortIDsForOnu() = %v, want %v", got, tt.want)
}
})
}
}
func TestOpenOltResourceMgr_GetMeterInfoForOnu(t *testing.T) {
type args struct {
Direction string
IntfID uint32
OnuID uint32
UniID uint32
tpID uint32
}
tests := []struct {
name string
fields *fields
args args
want *MeterInfo
wantErr error
}{
{"GetMeterInfoForOnu", getResMgr(), args{"DOWNSTREAM", 0, 1, 1, 64},
&MeterInfo{}, errors.New("failed to get Meter config from kvstore for path")},
{"GetMeterInfoForOnu", getResMgr(), args{"DOWNSTREAM", 1, 2, 2, 65},
&MeterInfo{}, errors.New("failed to get Meter config from kvstore for path")},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
got, err := RsrcMgr.GetMeterInfoForOnu(ctx, tt.args.Direction, tt.args.OnuID, tt.args.UniID, tt.args.tpID)
if reflect.TypeOf(got) != reflect.TypeOf(tt.want) && err != nil {
t.Errorf("GetMeterInfoForOnu() got = %v, want %v", got, tt.want)
}
})
}
}
func TestOpenOltResourceMgr_GetONUID(t *testing.T) {
type args struct {
ponIntfID uint32
}
tests := []struct {
name string
fields *fields
args args
want uint32
wantErr error
}{
{"GetONUID-1", getResMgr(), args{1}, uint32(0), errors.New("json errors")},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
got, err := RsrcMgr.GetONUID(ctx)
if got != tt.want && err != nil {
t.Errorf("GetONUID() got = %v, want %v", got, tt.want)
}
})
}
}
func TestOpenOltResourceMgr_GetTechProfileIDForOnu(t *testing.T) {
type args struct {
IntfID uint32
OnuID uint32
UniID uint32
}
tests := []struct {
name string
fields *fields
args args
want []uint32
}{
{"GetTechProfileIDForOnu-1", getResMgr(), args{1, 2, 2},
[]uint32{1}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if got := RsrcMgr.GetTechProfileIDForOnu(ctx, tt.args.OnuID, tt.args.UniID); reflect.TypeOf(got) != reflect.TypeOf(tt.want) {
t.Errorf("GetTechProfileIDForOnu() = %v, want %v", got, tt.want)
}
})
}
}
func TestOpenOltResourceMgr_RemoveMeterIDForOnu(t *testing.T) {
type args struct {
Direction string
IntfID uint32
OnuID uint32
UniID uint32
tpID uint32
}
tests := []struct {
name string
fields *fields
args args
wantErr error
}{
{"RemoveMeterIdForOnu-1", getResMgr(), args{"DOWNSTREAM", 1, 1, 1, 64},
errors.New("failed to delete meter id %s from kvstore")},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := RsrcMgr.RemoveMeterInfoForOnu(ctx, tt.args.Direction, tt.args.OnuID, tt.args.UniID,
tt.args.tpID); reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) && err != nil {
t.Errorf("RemoveMeterIDForOnu() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestOpenOltResourceMgr_RemoveTechProfileIDForOnu(t *testing.T) {
type args struct {
IntfID uint32
OnuID uint32
UniID uint32
tpID uint32
}
tests := []struct {
name string
fields *fields
args args
wantErr error
}{
{"RemoveTechProfileIDForOnu-1", getResMgr(), args{1, 2, 2, 64},
errors.New("failed to delete techprofile id resource %s in KV store")},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := RsrcMgr.RemoveTechProfileIDForOnu(ctx, tt.args.OnuID, tt.args.UniID,
tt.args.tpID); reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) && err != nil {
t.Errorf("RemoveTechProfileIDForOnu() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestOpenOltResourceMgr_UpdateAllocIdsForOnu(t *testing.T) {
type args struct {
ponPort uint32
onuID uint32
uniID uint32
allocID []uint32
}
tests := []struct {
name string
fields *fields
args args
wantErr error
}{
{"UpdateAllocIdsForOnu-1", getResMgr(), args{1, 2, 2, []uint32{1, 2}},
errors.New("")},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := RsrcMgr.UpdateAllocIdsForOnu(ctx, tt.args.onuID, tt.args.uniID, tt.args.allocID); err != nil && reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) {
t.Errorf("UpdateAllocIdsForOnu() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestOpenOltResourceMgr_UpdateGEMPortIDsForOnu(t *testing.T) {
type args struct {
ponPort uint32
onuID uint32
uniID uint32
GEMPortList []uint32
}
tests := []struct {
name string
fields *fields
args args
wantErr error
}{
{"UpdateGEMPortIDsForOnu-1", getResMgr(), args{1, 2, 2,
[]uint32{1, 2}}, errors.New("failed to update resource")},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := RsrcMgr.UpdateGEMPortIDsForOnu(ctx, tt.args.onuID, tt.args.uniID, tt.args.GEMPortList); err != nil && reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) {
t.Errorf("UpdateGEMPortIDsForOnu() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestOpenOltResourceMgr_UpdateMeterIDForOnu(t *testing.T) {
type args struct {
Direction string
IntfID uint32
OnuID uint32
UniID uint32
tpID uint32
MeterInfo *MeterInfo
}
tests := []struct {
name string
fields *fields
args args
wantErr error
}{
{"UpdateMeterIDForOnu-1", getResMgr(), args{"DOWNSTREAM", 1, 2,
2, 64, &MeterInfo{}}, errors.New("failed to get Meter config from kvstore for path")},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := RsrcMgr.StoreMeterInfoForOnu(ctx, tt.args.Direction, tt.args.OnuID, tt.args.UniID,
tt.args.tpID, tt.args.MeterInfo); reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) && err != nil {
t.Errorf("UpdateMeterIDForOnu() got = %v, want %v", err, tt.wantErr)
}
})
}
}
func TestOpenOltResourceMgr_UpdateTechProfileIDForOnu(t *testing.T) {
type args struct {
IntfID uint32
OnuID uint32
UniID uint32
TpID uint32
}
tests := []struct {
name string
fields *fields
args args
wantErr error
}{
{"UpdateTechProfileIDForOnu-1", getResMgr(), args{1, 2, 2,
2}, errors.New("failed to update resource")},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := RsrcMgr.UpdateTechProfileIDForOnu(ctx, tt.args.OnuID, tt.args.UniID, tt.args.TpID); reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) && err != nil {
t.Errorf("UpdateTechProfileIDForOnu() got = %v, want %v", err, tt.wantErr)
}
})
}
}
func TestSetKVClient(t *testing.T) {
type args struct {
backend string
address string
DeviceID string
kvStorePrefix string
}
tests := []struct {
name string
args args
want *db.Backend
}{
{"setKVClient-1", args{"etcd", "1.1.1.1:1", "olt1", "service/voltha"}, &db.Backend{}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := SetKVClient(context.Background(), tt.args.backend, tt.args.address, tt.args.DeviceID, tt.args.kvStorePrefix); reflect.TypeOf(got) != reflect.TypeOf(tt.want) {
t.Errorf("SetKVClient() = %v, want %v", got, tt.want)
}
})
}
}
func Test_newKVClient(t *testing.T) {
type args struct {
storeType string
address string
timeout time.Duration
}
var kvClient kvstore.Client
tests := []struct {
name string
args args
want kvstore.Client
wantErr error
}{
{"newKVClient-1", args{"", "3.3.3.3", 1}, kvClient, errors.New("unsupported-kv-store")},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := newKVClient(context.Background(), tt.args.storeType, tt.args.address, tt.args.timeout)
if got != nil && reflect.TypeOf(got) != reflect.TypeOf(tt.want) {
t.Errorf("newKVClient() got = %v, want %v", got, tt.want)
}
if (err != nil) && reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) {
t.Errorf("newKVClient() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}
func TestOpenOltResourceMgr_AddMcastQueueForIntf(t *testing.T) {
type args struct {
intf uint32
gem uint32
servicePriority uint32
}
tests := []struct {
name string
args args
fields *fields
}{
{"AddMcastQueueForIntf-1", args{0, 4000, 0}, getResMgr()},
{"AddMcastQueueForIntf-2", args{1, 4000, 1}, getResMgr()},
{"AddMcastQueueForIntf-3", args{2, 4000, 2}, getResMgr()},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := RsrcMgr.AddMcastQueueForIntf(ctx, tt.args.gem, tt.args.servicePriority)
if err != nil {
t.Errorf("%s got err= %s wants nil", tt.name, err)
return
}
})
}
}
func TestOpenOltResourceMgr_DeleteMcastQueueForIntf(t *testing.T) {
tests := []struct {
name string
fields *fields
}{
{"DeleteMcastQueueForIntf-1", getResMgr()},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
RsrcMgr.DeleteMcastQueueForIntf(ctx)
})
}
}
func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
groupDesc := ofp.OfpGroupDesc{
Type: ofp.OfpGroupType_OFPGT_ALL,
GroupId: groupID,
}
groupEntry := ofp.OfpGroupEntry{
Desc: &groupDesc,
}
for i := 0; i < len(outPorts); i++ {
var acts []*ofp.OfpAction
acts = append(acts, fu.Output(outPorts[i]))
bucket := ofp.OfpBucket{
Actions: acts,
}
groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
}
return &groupEntry
}
func TestOpenOltResourceMgr_AddFlowGroupToKVStore(t *testing.T) {
type args struct {
group *ofp.OfpGroupEntry
cached bool
}
//create group 1
group1 := newGroup(1, []uint32{1})
//create group 2
group2 := newGroup(2, []uint32{2})
//define test set
tests := []struct {
name string
args args
fields *fields
}{
{"AddFlowGroupToKVStore-1", args{group1, true}, getResMgr()},
{"AddFlowGroupToKVStore-2", args{group2, false}, getResMgr()},
}
//execute tests
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := RsrcMgr.AddFlowGroupToKVStore(ctx, tt.args.group, tt.args.cached)
if err != nil {
t.Errorf("%s got err= %s wants nil", tt.name, err)
return
}
})
}
}
func TestOpenOltResourceMgr_RemoveFlowGroupFromKVStore(t *testing.T) {
type args struct {
groupID uint32
cached bool
}
//define test set
tests := []struct {
name string
args args
fields *fields
}{
{"RemoveFlowGroupFromKVStore-1", args{1, true}, getResMgr()},
{"RemoveFlowGroupFromKVStore-2", args{2, false}, getResMgr()},
}
//execute tests
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := RsrcMgr.RemoveFlowGroupFromKVStore(ctx, tt.args.groupID, tt.args.cached)
if err != nil {
t.Errorf("%s got false but wants true", tt.name)
return
}
})
}
}
func TestOpenOltResourceMgr_GetFlowGroupFromKVStore(t *testing.T) {
type args struct {
groupID uint32
cached bool
}
//define test set
tests := []struct {
name string
args args
fields *fields
}{
{"GetFlowGroupFromKVStore-1", args{1, true}, getResMgr()},
{"GetFlowGroupFromKVStore-2", args{2, false}, getResMgr()},
{"GetFlowGroupFromKVStore-3", args{1000, false}, getResMgr()},
}
//execute tests
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RsrcMgr := testResMgrObject(tt.fields)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
exists, groupInfo, err := RsrcMgr.GetFlowGroupFromKVStore(ctx, tt.args.groupID, tt.args.cached)
if err != nil {
t.Errorf("%s got error but wants nil error", tt.name)
return
} else if exists && (groupInfo.GroupID == 0) {
t.Errorf("%s got true and nil group info but expected not nil group info", tt.name)
return
} else if tt.args.groupID == 3 && exists {
t.Errorf("%s got true but wants false", tt.name)
return
}
})
}
}