Adding UTs part-1
Change-Id: I7fdb7751f536d1a616cf2a81b7ef16747d71f692
diff --git a/go.mod b/go.mod
index f2704f9..6440ed7 100755
--- a/go.mod
+++ b/go.mod
@@ -11,6 +11,7 @@
require (
github.com/go-redis/redis/v8 v8.11.5
+ github.com/golang/mock v1.4.4
github.com/golang/protobuf v1.5.2
github.com/google/gopacket v0.0.0-00010101000000-000000000000
github.com/gorilla/mux v1.8.0
@@ -19,7 +20,7 @@
github.com/opencord/voltha-lib-go/v7 v7.2.1
github.com/opencord/voltha-protos/v5 v5.2.4
github.com/sirupsen/logrus v1.8.1 // indirect
- github.com/stretchr/testify v1.7.1 // indirect
+ github.com/stretchr/testify v1.8.2
go.uber.org/atomic v1.9.0
google.golang.org/grpc v1.44.0
)
diff --git a/go.sum b/go.sum
index e1d6bf7..ae62787 100644
--- a/go.sum
+++ b/go.sum
@@ -82,6 +82,8 @@
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
+github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -158,9 +160,11 @@
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
@@ -242,16 +246,20 @@
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tinojj/gopacket v1.1.20-0.20220525133109-3e65a52a1a61 h1:31bWrwIx9gNzEX8gaeFzJx5Vy0cj35OfBXvr0hZL8Jc=
github.com/tinojj/gopacket v1.1.20-0.20220525133109-3e65a52a1a61/go.mod h1:riddUzxTSBpJXk3qBHtYr4qOhFhT6k/1c0E3qkQjQpA=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA=
@@ -397,6 +405,7 @@
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -446,6 +455,7 @@
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
@@ -461,8 +471,9 @@
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
diff --git a/internal/pkg/application/application_test.go b/internal/pkg/application/application_test.go
new file mode 100644
index 0000000..ca2e2b9
--- /dev/null
+++ b/internal/pkg/application/application_test.go
@@ -0,0 +1,2377 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* 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 application
+
+import (
+ "context"
+ "encoding/json"
+ "net"
+ "reflect"
+ "sync"
+ "testing"
+ "voltha-go-controller/internal/pkg/controller"
+ "voltha-go-controller/internal/pkg/intf"
+ "voltha-go-controller/internal/pkg/of"
+ "voltha-go-controller/internal/pkg/util"
+ "voltha-go-controller/internal/test/mocks"
+
+ "github.com/golang/mock/gomock"
+ "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
+ "github.com/stretchr/testify/assert"
+ "go.uber.org/atomic"
+)
+
+func TestVoltApplication_RestoreNbDeviceFromDb(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ deviceID string
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "VoltApplication_RestoreNbDeviceFromDb",
+ args: args{
+ cntx: context.Background(),
+ deviceID: "test_device_id",
+ },
+ },
+ {
+ name: "VoltApplication_RestoreNbDeviceFromDb_invalid_Value_type",
+ args: args{
+ cntx: context.Background(),
+ deviceID: "test_device_id1",
+ },
+ },
+ {
+ name: "VoltApplication_RestoreNbDeviceFromDb_unmarshal_error",
+ args: args{
+ cntx: context.Background(),
+ deviceID: "test_device_id1",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ NbDevice: sync.Map{},
+ }
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ switch tt.name {
+ case "VoltApplication_RestoreNbDeviceFromDb":
+ var port PonPortCfg
+ port = PonPortCfg{
+ PortAlarmProfileID: "test",
+ PortID: 256,
+ MaxActiveChannels: 256,
+ ActiveIGMPChannels: 7679,
+ EnableMulticastKPI: false,
+ }
+ b, err := json.Marshal(port)
+ if err != nil {
+ panic(err)
+ }
+ test := map[string]*kvstore.KVPair{}
+ test["test_device_id"] = &kvstore.KVPair{
+ Key: "test_device_id",
+ Value: b,
+ }
+ dbintf.EXPECT().GetAllNbPorts(gomock.Any(), gomock.Any()).Return(test, nil).Times(1)
+ got := va.RestoreNbDeviceFromDb(tt.args.cntx, tt.args.deviceID)
+ assert.NotNil(t, got)
+ case "VoltApplication_RestoreNbDeviceFromDb_invalid_Value_type":
+ test := map[string]*kvstore.KVPair{}
+ test["test_device_id"] = &kvstore.KVPair{
+ Key: "test_device_id",
+ Value: "invalid_value",
+ }
+ dbintf.EXPECT().GetAllNbPorts(gomock.Any(), gomock.Any()).Return(test, nil).Times(1)
+ got := va.RestoreNbDeviceFromDb(tt.args.cntx, tt.args.deviceID)
+ assert.NotNil(t, got)
+ case "VoltApplication_RestoreNbDeviceFromDb_unmarshal_error":
+ b, err := json.Marshal("error")
+ if err != nil {
+ panic(err)
+ }
+ test := map[string]*kvstore.KVPair{}
+ test["test_device_id"] = &kvstore.KVPair{
+ Key: "test_device_id",
+ Value: b,
+ }
+ dbintf.EXPECT().GetAllNbPorts(gomock.Any(), gomock.Any()).Return(test, nil).Times(1)
+ got := va.RestoreNbDeviceFromDb(tt.args.cntx, tt.args.deviceID)
+ assert.NotNil(t, got)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_UpdateDeviceConfig(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ deviceConfig *DeviceConfig
+ }
+
+ dvcConfg := &DeviceConfig{
+ SerialNumber: "SDX6320031",
+ HardwareIdentifier: "0.0.0.0",
+ IPAddress: "127.26.1.74",
+ UplinkPort: "43322",
+ NasID: "12345",
+ NniDhcpTrapVid: 123,
+ }
+
+ voltDev := &VoltDevice{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "SDX6320031",
+ args: args{
+ cntx: context.Background(),
+ deviceConfig: dvcConfg,
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ DevicesConfig: sync.Map{},
+ }
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutDeviceConfig(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
+
+ va.UpdateDeviceConfig(tt.args.cntx, tt.args.deviceConfig)
+ })
+ }
+}
+
+func TestVoltApplication_RestoreOltFlowService(t *testing.T) {
+ type fields struct {
+ OltFlowServiceConfig OltFlowService
+ }
+ type args struct {
+ cntx context.Context
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ }{
+ {
+ name: "OltFlowService",
+ args: args{
+ cntx: context.Background(),
+ },
+ fields: fields{
+ OltFlowServiceConfig: OltFlowService{
+ DefaultTechProfileID: 1233,
+ EnableDhcpOnNni: true,
+ EnableIgmpOnNni: false,
+ RemoveFlowsOnDisable: false,
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ OltFlowServiceConfig: tt.fields.OltFlowServiceConfig,
+ }
+
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().GetOltFlowService(gomock.Any()).AnyTimes()
+
+ va.RestoreOltFlowService(tt.args.cntx)
+ })
+ }
+}
+
+func TestVoltApplication_UpdateOltFlowService(t *testing.T) {
+ type fields struct {
+ OltFlowServiceConfig OltFlowService
+ }
+ type args struct {
+ cntx context.Context
+ oltFlowService OltFlowService
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ }{
+ {
+ name: "OltFlowService",
+ args: args{
+ cntx: context.Background(),
+ oltFlowService: OltFlowService{
+ DefaultTechProfileID: 1233,
+ EnableDhcpOnNni: true,
+ EnableIgmpOnNni: false,
+ RemoveFlowsOnDisable: false,
+ },
+ },
+ fields: fields{
+ OltFlowServiceConfig: OltFlowService{
+ DefaultTechProfileID: 1233,
+ EnableDhcpOnNni: true,
+ EnableIgmpOnNni: false,
+ RemoveFlowsOnDisable: false,
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ OltFlowServiceConfig: tt.fields.OltFlowServiceConfig,
+ }
+
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutOltFlowService(gomock.Any(), gomock.Any()).AnyTimes()
+ va.UpdateOltFlowService(tt.args.cntx, tt.args.oltFlowService)
+ })
+ }
+}
+
+func TestVoltApplication_TriggerPendingVpvDeleteReq(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ device string
+ }
+ macAdd, _ := net.ParseMAC("ff:ff:ff:ff:ff:ff")
+ test := map[*VoltPortVnet]bool{}
+ test[&VoltPortVnet{Device: "SDX6320031", Port: "16777472", MacAddr: macAdd}] = true
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "SDX6320031",
+ args: args{
+ cntx: context.Background(),
+ device: "SDX6320031",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ VoltPortVnetsToDelete: test,
+ }
+ va.TriggerPendingVpvDeleteReq(tt.args.cntx, tt.args.device)
+ })
+ }
+}
+
+func TestVoltApplication_TriggerPendingProfileDeleteReq(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ device string
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "SDX6320031",
+ args: args{
+ cntx: context.Background(),
+ device: "SDX6320031",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ }
+ va.TriggerPendingProfileDeleteReq(tt.args.cntx, tt.args.device)
+ })
+ }
+}
+
+func TestVoltApplication_TriggerPendingServiceDeleteReq(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ device string
+ }
+ voltServ := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ Device: "SDX6320031",
+ ForceDelete: true,
+ },
+ }
+
+ servicesToDel := map[string]bool{}
+ servicesToDel["SCOM00001c75-1_SCOM00001c75-1-4096-2310-4096-65"] = true
+
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_TriggerPendingServiceDeleteReq",
+ args: args{
+ cntx: context.Background(),
+ device: "SDX6320031",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ ServicesToDelete: servicesToDel,
+ ServiceByName: sync.Map{},
+ DevicesDisc: sync.Map{},
+ }
+
+ va.ServiceByName.Store("SCOM00001c75-1_SCOM00001c75-1-4096-2310-4096-65", voltServ)
+
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
+ dbintf.EXPECT().DelService(gomock.Any(), gomock.Any()).AnyTimes()
+ va.TriggerPendingServiceDeleteReq(tt.args.cntx, tt.args.device)
+ })
+ }
+}
+
+func TestVoltApplication_TriggerPendingVnetDeleteReq(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ device string
+ }
+
+ vnetToDel := map[string]bool{}
+ vnetToDel["2310-4096-4096"] = true
+
+ voltVnet := &VoltVnet{
+ Version: "v3",
+ VnetConfig: VnetConfig{
+ Name: "2310-4096-4096",
+ VnetType: "Encapsulation",
+ SVlan: 2310,
+ CVlan: 4096,
+ UniVlan: 4096,
+ SVlanTpid: 33024,
+ },
+ VnetOper: VnetOper{
+ PendingDeviceToDelete: "SDX63200313",
+ },
+ }
+ voltDev := &VoltDevice{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ }
+
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Negative_Case_TriggerPendingVnetDeleteReq",
+ args: args{
+ cntx: context.Background(),
+ device: "SDX6320031",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ VnetsToDelete: vnetToDel,
+ DevicesDisc: sync.Map{},
+ }
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ va.VnetsByName.Store("2310-4096-4096", voltVnet)
+ va.TriggerPendingVnetDeleteReq(tt.args.cntx, tt.args.device)
+ })
+ }
+}
+
+func TestVoltApplication_UpdateMacInPortMap(t *testing.T) {
+ type args struct {
+ macAddr net.HardwareAddr
+ port string
+ }
+ macAdd, _ := net.ParseMAC("ff:ff:ff:ff:ff:ff")
+ macPort := map[string]string{}
+ macPort[macAdd.String()] = "1234"
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_UpdateMacInPortMap",
+ args: args{
+ macAddr: macAdd,
+ port: "1234",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ macPortMap: macPort,
+ }
+ va.UpdateMacInPortMap(tt.args.macAddr, tt.args.port)
+ })
+ }
+}
+
+func TestVoltApplication_GetMacInPortMap(t *testing.T) {
+ type args struct {
+ macAddr net.HardwareAddr
+ }
+ macAdd, _ := net.ParseMAC("ff:ff:ff:ff:ff:ff")
+ macPort := map[string]string{}
+ macPort[macAdd.String()] = "1234"
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {
+ name: "Positive_Case_GetMacInPortMap",
+ args: args{
+ macAddr: macAdd,
+ },
+ want: "1234",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ macPortMap: macPort,
+ }
+ if got := va.GetMacInPortMap(tt.args.macAddr); got != tt.want {
+ t.Errorf("VoltApplication.GetMacInPortMap() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_pushFlowFailureNotif(t *testing.T) {
+ type args struct {
+ flowStatus intf.FlowStatus
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_pushFlowFailureNotif",
+ args: args{
+ flowStatus: intf.FlowStatus{
+ Device: "SDX6320031",
+ Cookie: "68786618880",
+ Status: 0,
+ Flow: &of.VoltSubFlow{
+ Cookie: 68786618880,
+ TableID: 0,
+ Priority: 100,
+ ErrorReason: "",
+ OldCookie: 0,
+ },
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ pushFlowFailureNotif(tt.args.flowStatus)
+ })
+ }
+}
+
+func TestGetPonPortIDFromUNIPort(t *testing.T) {
+ type args struct {
+ uniPortID uint32
+ }
+ tests := []struct {
+ name string
+ args args
+ want uint32
+ }{
+ {
+ name: "Positive_Case_pushFlowFailureNotif",
+ args: args{
+ uniPortID: 1049600,
+ },
+ want: 1,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := GetPonPortIDFromUNIPort(tt.args.uniPortID); got != tt.want {
+ t.Errorf("GetPonPortIDFromUNIPort() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_ProcessFlowModResultIndication(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ flowStatus intf.FlowStatus
+ }
+ voltDev := &VoltDevice{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ FlowAddEventMap: util.NewConcurrentMap(),
+ }
+ flowState := intf.FlowStatus{
+ Device: "SDX6320031",
+ Cookie: "68786618880",
+ Status: 1005,
+ FlowModType: 0,
+ Flow: &of.VoltSubFlow{
+ Cookie: 68786618880,
+ OldCookie: 0,
+ TableID: 0,
+ State: 0,
+ Priority: 100,
+ },
+ }
+ flowAddEvent := map[string]*FlowEvent{}
+ flowEvent := &FlowEvent{
+ device: "SDX6320031",
+ cookie: "68786618880",
+ eType: EventTypeControlFlowAdded,
+ }
+ flowAddEvent["68786618880"] = flowEvent
+ voltDev.FlowAddEventMap.Set("6878661888", flowEvent)
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_ProcessFlowModResultIndication",
+ args: args{
+ cntx: context.Background(),
+ flowStatus: flowState,
+ },
+ },
+ {
+ name: "Negetive_Case_ProcessFlowModResultIndication",
+ args: args{
+ cntx: context.Background(),
+ flowStatus: flowState,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_ProcessFlowModResultIndication":
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ va.ProcessFlowModResultIndication(tt.args.cntx, tt.args.flowStatus)
+ case "Negetive_Case_ProcessFlowModResultIndication":
+ va.ProcessFlowModResultIndication(tt.args.cntx, tt.args.flowStatus)
+ }
+ })
+ }
+}
+func Test_getPendingPoolKey(t *testing.T) {
+ type args struct {
+ mvlan of.VlanType
+ device string
+ }
+
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {
+ name: "Positive_Case_getPendingPoolKey",
+ args: args{
+ mvlan: of.VlanAny,
+ device: "SDX6320031",
+ },
+ want: "4096_SDX6320031",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := getPendingPoolKey(tt.args.mvlan, tt.args.device); got != tt.want {
+ t.Errorf("getPendingPoolKey() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestNewVoltPort(t *testing.T) {
+ type args struct {
+ device string
+ name string
+ id uint32
+ }
+
+ voltPort := &VoltPort{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ Device: "SDX6320031",
+ ID: 16777472,
+ State: PortStateDown,
+ ChannelPerSubAlarmRaised: false,
+ Type: VoltPortTypeNni,
+ }
+
+ voltPort1 := &VoltPort{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ Device: "SDX6320031",
+ ID: 1049600,
+ State: PortStateDown,
+ ChannelPerSubAlarmRaised: false,
+ PonPort: GetPonPortIDFromUNIPort(1049600),
+ }
+ tests := []struct {
+ name string
+ args args
+ want *VoltPort
+ }{
+ {
+ name: "Positive_Case_TestNewVoltPort",
+ args: args{
+ id: 16777472,
+ device: "SDX6320031",
+ name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ },
+ want: voltPort,
+ },
+ {
+ name: "Positive_Case2_TestNewVoltPort",
+ args: args{
+ id: 1049600,
+ device: "SDX6320031",
+ name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ },
+ want: voltPort1,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ switch tt.name {
+ case "Positive_Case_TestNewVoltPort":
+ if got := NewVoltPort(tt.args.device, tt.args.name, tt.args.id); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("NewVoltPort() = %v, want %v", got, tt.want)
+ }
+ case "Positive_Case2_TestNewVoltPort":
+ if got := NewVoltPort(tt.args.device, tt.args.name, tt.args.id); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("NewVoltPort() = %v, want %v", got, tt.want)
+ }
+ }
+ })
+ }
+}
+
+func TestVoltPort_SetPortID(t *testing.T) {
+ type args struct {
+ id uint32
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_TestNewVoltPort",
+ args: args{
+ id: 16777472,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ vp := &VoltPort{
+ ID: 16777472,
+ Type: VoltPortTypeNni,
+ }
+ vp.SetPortID(tt.args.id)
+ })
+ }
+}
+
+func TestNewVoltDevice(t *testing.T) {
+ type args struct {
+ name string
+ slno string
+ southBoundID string
+ }
+
+ devConfig := &DeviceConfig{
+ SerialNumber: "SDX6320033",
+ NniDhcpTrapVid: 4,
+ }
+ voltDevice := &VoltDevice{
+ Name: "11c3175b-50f3-4220-9555-93df733ded1d",
+ SerialNum: "SDX6320033",
+ SouthBoundID: "68580342-6b3e-57cb-9ea4-06125594e330",
+ State: controller.DeviceStateDOWN,
+ NniPort: "",
+ icmpv6GroupAdded: false,
+ IgmpDsFlowAppliedForMvlan: make(map[uint16]bool),
+ ConfiguredVlanForDeviceFlows: util.NewConcurrentMap(),
+ MigratingServices: util.NewConcurrentMap(),
+ VpvsBySvlan: util.NewConcurrentMap(),
+ FlowAddEventMap: util.NewConcurrentMap(),
+ FlowDelEventMap: util.NewConcurrentMap(),
+ GlobalDhcpFlowAdded: false,
+ NniDhcpTrapVid: 4,
+ }
+
+ GetApplication().DevicesConfig.Store("SDX6320033", devConfig)
+ tests := []struct {
+ name string
+ args args
+ want *VoltDevice
+ }{
+ {
+ name: "Positive_Case_TestNewVoltDevice",
+ args: args{
+ name: "11c3175b-50f3-4220-9555-93df733ded1d",
+ slno: "SDX6320033",
+ southBoundID: "68580342-6b3e-57cb-9ea4-06125594e330",
+ },
+ want: voltDevice,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := NewVoltDevice(tt.args.name, tt.args.slno, tt.args.southBoundID); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("NewVoltDevice() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_GetAssociatedVpvsForDevice(t *testing.T) {
+ type args struct {
+ device string
+ svlan of.VlanType
+ }
+
+ voltDev := &VoltDevice{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ SerialNum: "SDX6320033",
+ NniDhcpTrapVid: 123,
+ VpvsBySvlan: util.NewConcurrentMap(),
+ }
+
+ cuncurrentMap := &util.ConcurrentMap{
+ Count: atomic.NewUint64(0),
+ }
+
+ voltDev1 := &VoltDevice{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ SerialNum: "SDX6320033",
+ NniDhcpTrapVid: 123,
+ VpvsBySvlan: cuncurrentMap,
+ }
+ tests := []struct {
+ name string
+ args args
+ want *util.ConcurrentMap
+ }{
+ {
+ name: "Positive_Case_GetAssociatedVpvsForDevice",
+ args: args{
+ device: "SDX6320033",
+ svlan: of.VlanAny,
+ },
+ want: util.NewConcurrentMap(),
+ },
+ {
+ name: "Positive_Case2_GetAssociatedVpvsForDevice",
+ args: args{
+ device: "SDX6320033",
+ svlan: of.VlanAny,
+ },
+ want: cuncurrentMap,
+ },
+ {
+ name: "Negetive_Case2_GetAssociatedVpvsForDevice",
+ args: args{
+ device: "SDX6320031",
+ svlan: of.VlanAny,
+ },
+ want: nil,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ switch tt.name {
+ case "Positive_Case_GetAssociatedVpvsForDevice":
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ VnetsBySvlan: util.NewConcurrentMap(),
+ }
+ va.DevicesDisc.Store("SDX6320033", voltDev)
+ if got := va.GetAssociatedVpvsForDevice(tt.args.device, tt.args.svlan); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("VoltApplication.GetAssociatedVpvsForDevice() = %v, want %v", got, tt.want)
+ }
+ case "Positive_Case2_GetAssociatedVpvsForDevice":
+ va1 := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ VnetsBySvlan: cuncurrentMap,
+ }
+ va1.DevicesDisc.Store("SDX6320033", voltDev1)
+ va1.VnetsBySvlan.Set(of.VlanAny, cuncurrentMap)
+ if got := va1.GetAssociatedVpvsForDevice(tt.args.device, tt.args.svlan); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("VoltApplication.GetAssociatedVpvsForDevice() = %v, want %v", got, tt.want)
+ }
+ case "Negetive_Case2_GetAssociatedVpvsForDevice":
+ va1 := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ }
+ if got := va1.GetAssociatedVpvsForDevice(tt.args.device, tt.args.svlan); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("VoltApplication.GetAssociatedVpvsForDevice() = %v, want %v", got, tt.want)
+ }
+ }
+ })
+ }
+}
+
+func TestVoltApplication_AssociateVpvsToDevice(t *testing.T) {
+ type args struct {
+ device string
+ vpv *VoltPortVnet
+ }
+
+ vpv := &VoltPortVnet{
+ Device: "SDX6320033",
+ SVlan: of.VlanAny,
+ }
+ voltDev := &VoltDevice{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ SerialNum: "SDX6320033",
+ NniDhcpTrapVid: 123,
+ VpvsBySvlan: util.NewConcurrentMap(),
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_AssociateVpvsToDevice",
+ args: args{
+ device: "SDX6320033",
+ vpv: vpv,
+ },
+ },
+ {
+ name: "Negetive_Case_AssociateVpvsToDevice",
+ args: args{
+ device: "SDX6320033",
+ vpv: vpv,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ switch tt.name {
+ case "Positive_Case_AssociateVpvsToDevice":
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ VnetsBySvlan: util.NewConcurrentMap(),
+ }
+ va.DevicesDisc.Store("SDX6320033", voltDev)
+ va.AssociateVpvsToDevice(tt.args.device, tt.args.vpv)
+ case "Negetive_Case_AssociateVpvsToDevice":
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ VnetsBySvlan: util.NewConcurrentMap(),
+ }
+ va.AssociateVpvsToDevice(tt.args.device, tt.args.vpv)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_DisassociateVpvsFromDevice(t *testing.T) {
+ type args struct {
+ device string
+ vpv *VoltPortVnet
+ }
+ vpv := &VoltPortVnet{
+ Device: "SDX6320033",
+ SVlan: of.VlanAny,
+ }
+
+ voltDev := &VoltDevice{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ SerialNum: "SDX6320033",
+ NniDhcpTrapVid: 123,
+ VpvsBySvlan: util.NewConcurrentMap(),
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_DisassociateVpvsFromDevice",
+ args: args{
+ device: "SDX6320033",
+ vpv: vpv,
+ },
+ },
+ {
+ name: "Negetive_Case_DisassociateVpvsFromDevice",
+ args: args{
+ device: "SDX6320033",
+ vpv: vpv,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ switch tt.name {
+ case "Positive_Case_DisassociateVpvsFromDevice":
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ VnetsBySvlan: util.NewConcurrentMap(),
+ }
+ va.DevicesDisc.Store("SDX6320033", voltDev)
+ va.DisassociateVpvsFromDevice(tt.args.device, tt.args.vpv)
+ case "Negetive_Case_DisassociateVpvsFromDevice":
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ VnetsBySvlan: util.NewConcurrentMap(),
+ }
+ va.DisassociateVpvsFromDevice(tt.args.device, tt.args.vpv)
+ }
+ })
+ }
+}
+
+func TestVoltDevice_GetPort(t *testing.T) {
+ type args struct {
+ port string
+ }
+ voltPort := &VoltPort{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ Device: "SDX6320031",
+ ID: 16777472,
+ State: PortStateDown,
+ ChannelPerSubAlarmRaised: false,
+ Type: VoltPortTypeNni,
+ }
+ tests := []struct {
+ name string
+ args args
+ want *VoltPort
+ }{
+ {
+ name: "Positive_Case_GetPort",
+ args: args{
+ port: "16777472",
+ },
+ want: voltPort,
+ },
+ {
+ name: "Negetive_Case_GetPort",
+ args: args{
+ port: "16777472",
+ },
+ want: nil,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ d := &VoltDevice{
+ Ports: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_GetPort":
+ d.Ports.Store("16777472", voltPort)
+ if got := d.GetPort(tt.args.port); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("VoltDevice.GetPort() = %v, want %v", got, tt.want)
+ }
+ case "Negetive_Case_GetPort":
+ if got := d.GetPort(tt.args.port); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("VoltDevice.GetPort() = %v, want %v", got, tt.want)
+ }
+ }
+ })
+ }
+}
+
+func TestVoltDevice_GetPortNameFromPortID(t *testing.T) {
+ type args struct {
+ portID uint32
+ }
+ voltPort := &VoltPort{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ Device: "SDX6320031",
+ ID: 16777472,
+ State: PortStateDown,
+ ChannelPerSubAlarmRaised: false,
+ Type: VoltPortTypeNni,
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {
+ name: "Positive_Case_GetPort",
+ args: args{
+ portID: 16777472,
+ },
+ want: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ d := &VoltDevice{
+ Ports: sync.Map{},
+ }
+ d.Ports.Store(16777472, voltPort)
+ if got := d.GetPortNameFromPortID(tt.args.portID); got != tt.want {
+ t.Errorf("VoltDevice.GetPortNameFromPortID() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestVoltDevice_DelPort(t *testing.T) {
+ type args struct {
+ port string
+ }
+ voltPort := &VoltPort{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ Device: "SDX6320031",
+ ID: 16777472,
+ State: PortStateDown,
+ ChannelPerSubAlarmRaised: false,
+ Type: VoltPortTypeNni,
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_DelPort",
+ args: args{
+ port: "16777472",
+ },
+ },
+ {
+ name: "Negetive_Case_DelPort",
+ args: args{
+ port: "16777472",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ d := &VoltDevice{
+ Ports: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_DelPort":
+ d.Ports.Store("16777472", voltPort)
+ d.DelPort(tt.args.port)
+ case "Negetive_Case_DelPort":
+ d.DelPort(tt.args.port)
+ }
+ })
+ }
+}
+
+func TestVoltDevice_pushFlowsForUnis(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_pushFlowsForUnis",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ {
+ name: "Negetive_Case_pushFlowsForUnis",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ {
+ name: "Negetive_Case1_pushFlowsForUnis",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ d := &VoltDevice{
+ Name: "SDX6320031",
+ SerialNum: "SDX6320031",
+ Ports: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_pushFlowsForUnis":
+ voltPort := &VoltPort{
+ Name: "16777472",
+ Device: "SDX6320031",
+ ID: 16777472,
+ State: PortStateUp,
+ ChannelPerSubAlarmRaised: false,
+ Type: VoltPortTypeNni,
+ }
+ d.Ports.Store("16777472", voltPort)
+ ga := GetApplication()
+ voltPortVnets := make([]*VoltPortVnet, 0)
+ voltPortVnet := &VoltPortVnet{
+ Device: "SDX6320031",
+ Port: "16777472",
+ DeleteInProgress: true,
+ }
+ voltPortVnets = append(voltPortVnets, voltPortVnet)
+ ga.VnetsByPort.Store("16777472", voltPortVnets)
+
+ d.pushFlowsForUnis(tt.args.cntx)
+ case "Negetive_Case_pushFlowsForUnis":
+ voltPort1 := &VoltPort{
+ Name: "16777472",
+ Device: "SDX6320031",
+ ID: 16777472,
+ State: PortStateDown,
+ ChannelPerSubAlarmRaised: false,
+ Type: VoltPortTypeNni,
+ }
+ d.Ports.Store("16777472", voltPort1)
+ d.pushFlowsForUnis(tt.args.cntx)
+ case "Negetive_Case1_pushFlowsForUnis":
+ voltPort2 := &VoltPort{
+ Name: "16777472",
+ Device: "SDX6320031",
+ ID: 16777472,
+ State: PortStateUp,
+ ChannelPerSubAlarmRaised: false,
+ Type: VoltPortTypeNni,
+ }
+ d.Ports.Store("1677747", voltPort2)
+ d.pushFlowsForUnis(tt.args.cntx)
+ }
+ })
+ }
+}
+
+func TestNewNbDevice(t *testing.T) {
+ tests := []struct {
+ name string
+ want *NbDevice
+ }{
+ {
+ name: "Positive_Case_pushFlowsForUnis",
+ want: &NbDevice{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := NewNbDevice(); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("NewNbDevice() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestNbDevice_WriteToDb(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ portID uint32
+ ponPort *PonPortCfg
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_pushFlowsForUnis",
+ args: args{
+ cntx: context.Background(),
+ portID: controller.NNIPortID,
+ ponPort: &PonPortCfg{
+ PortID: controller.NNIPortID,
+ EnableMulticastKPI: false,
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ nbd := &NbDevice{
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ }
+ switch tt.name {
+ case "Positive_Case_pushFlowsForUnis":
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutNbDevicePort(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+ nbd.WriteToDb(tt.args.cntx, tt.args.portID, tt.args.ponPort)
+ }
+ })
+ }
+}
+
+func TestNbDevice_AddPortToNbDevice(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ portID uint32
+ allowedChannels uint32
+ enableMulticastKPI bool
+ portAlarmProfileID string
+ }
+ ponPort := &PonPortCfg{
+ PortID: controller.NNIPortID,
+ MaxActiveChannels: 123,
+ EnableMulticastKPI: false,
+ PortAlarmProfileID: "16777",
+ }
+ tests := []struct {
+ name string
+ args args
+ want *PonPortCfg
+ }{
+ {
+ name: "Positive_Case_AddPortToNbDevice",
+ args: args{
+ cntx: context.Background(),
+ portID: controller.NNIPortID,
+ allowedChannels: 123,
+ enableMulticastKPI: false,
+ portAlarmProfileID: "16777",
+ },
+ want: ponPort,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ nbd := &NbDevice{
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ PonPorts: sync.Map{},
+ }
+ nbd.PonPorts.Store(controller.NNIPortID, ponPort)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutNbDevicePort(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+ if got := nbd.AddPortToNbDevice(tt.args.cntx, tt.args.portID, tt.args.allowedChannels, tt.args.enableMulticastKPI, tt.args.portAlarmProfileID); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("NbDevice.AddPortToNbDevice() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_AddDeviceConfig(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ serialNum string
+ hardwareIdentifier string
+ nasID string
+ ipAddress string
+ uplinkPort string
+ nniDhcpTrapID int
+ }
+ dvcConfg := &DeviceConfig{
+ SerialNumber: "SDX6320031",
+ HardwareIdentifier: "0.0.0.0",
+ IPAddress: "127.26.1.74",
+ UplinkPort: "16777216",
+ NasID: "12345",
+ NniDhcpTrapVid: 123,
+ }
+ voltDev := &VoltDevice{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {
+ name: "Positive_Case_AddDeviceConfig",
+ args: args{
+ cntx: context.Background(),
+ serialNum: "SDX6320031",
+ hardwareIdentifier: "0.0.0.0.",
+ nasID: "12345",
+ ipAddress: "127.26.1.74",
+ uplinkPort: "16777216",
+ nniDhcpTrapID: 123,
+ },
+ wantErr: false,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesConfig: sync.Map{},
+ }
+ va.DevicesConfig.Store("SDX6320031", dvcConfg)
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutDeviceConfig(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
+ if err := va.AddDeviceConfig(tt.args.cntx, tt.args.serialNum, tt.args.hardwareIdentifier, tt.args.nasID, tt.args.ipAddress, tt.args.uplinkPort, tt.args.nniDhcpTrapID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.AddDeviceConfig() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_GetDeviceConfig(t *testing.T) {
+ type args struct {
+ serNum string
+ }
+ dvcConfg := &DeviceConfig{
+ SerialNumber: "SDX6320031",
+ HardwareIdentifier: "0.0.0.0",
+ IPAddress: "127.26.1.74",
+ UplinkPort: "16777216",
+ NasID: "12345",
+ NniDhcpTrapVid: 123,
+ }
+ tests := []struct {
+ name string
+ args args
+ want *DeviceConfig
+ }{
+ {
+ name: "Positive_Case_GetDeviceConfig",
+ args: args{
+ serNum: "SDX6320031",
+ },
+ want: dvcConfg,
+ },
+ {
+ name: "Negetive_Case_GetDeviceConfig",
+ args: args{
+ serNum: "SDX6320031",
+ },
+ want: nil,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesConfig: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_GetDeviceConfig":
+ va.DevicesConfig.Store("SDX6320031", dvcConfg)
+ if got := va.GetDeviceConfig(tt.args.serNum); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("VoltApplication.GetDeviceConfig() = %v, want %v", got, tt.want)
+ }
+ case "Negetive_Case_GetDeviceConfig":
+ if got := va.GetDeviceConfig(tt.args.serNum); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("VoltApplication.GetDeviceConfig() = %v, want %v", got, tt.want)
+ }
+ }
+ })
+ }
+}
+
+func TestNbDevice_UpdatePortToNbDevice(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ portID uint32
+ allowedChannels uint32
+ enableMulticastKPI bool
+ portAlarmProfileID string
+ }
+ ponPort := &PonPortCfg{
+ PortID: controller.NNIPortID,
+ MaxActiveChannels: 123,
+ EnableMulticastKPI: false,
+ PortAlarmProfileID: "16777",
+ }
+ tests := []struct {
+ name string
+ args args
+ want *PonPortCfg
+ }{
+ {
+ name: "Positive_Case_UpdatePortToNbDevice",
+ args: args{
+ cntx: context.Background(),
+ portID: controller.NNIPortID,
+ allowedChannels: 123,
+ enableMulticastKPI: false,
+ portAlarmProfileID: "16777",
+ },
+ want: ponPort,
+ },
+ {
+ name: "Negetive_Case_UpdatePortToNbDevice",
+ args: args{
+ cntx: context.Background(),
+ portID: 0,
+ allowedChannels: 123,
+ enableMulticastKPI: false,
+ portAlarmProfileID: "16777",
+ },
+ want: nil,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ nbd := &NbDevice{
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ PonPorts: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_UpdatePortToNbDevice":
+ nbd.PonPorts.Store(controller.NNIPortID, ponPort)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutNbDevicePort(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+ if got := nbd.UpdatePortToNbDevice(tt.args.cntx, tt.args.portID, tt.args.allowedChannels, tt.args.enableMulticastKPI, tt.args.portAlarmProfileID); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("NbDevice.UpdatePortToNbDevice() = %v, want %v", got, tt.want)
+ }
+ case "Negetive_Case_UpdatePortToNbDevice":
+ if got := nbd.UpdatePortToNbDevice(tt.args.cntx, tt.args.portID, tt.args.allowedChannels, tt.args.enableMulticastKPI, tt.args.portAlarmProfileID); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("NbDevice.UpdatePortToNbDevice() = %v, want %v", got, tt.want)
+ }
+ }
+ })
+ }
+}
+
+func TestNbDevice_DeletePortFromNbDevice(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ portID uint32
+ }
+ ponPort := &PonPortCfg{
+ PortID: controller.NNIPortID,
+ MaxActiveChannels: 123,
+ EnableMulticastKPI: false,
+ PortAlarmProfileID: "16777",
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_DeletePortFromNbDevice",
+ args: args{
+ portID: controller.NNIPortID,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ nbd := &NbDevice{
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ PonPorts: sync.Map{},
+ }
+ nbd.PonPorts.Store(controller.NNIPortID, ponPort)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().DelNbDevicePort(nil, "49686e2d-618f-4e8e-bca0-442ab850a63a", controller.NNIPortID).AnyTimes()
+ nbd.DeletePortFromNbDevice(tt.args.cntx, tt.args.portID)
+ })
+ }
+}
+
+func TestVoltDevice_RegisterFlowAddEvent(t *testing.T) {
+ type args struct {
+ cookie string
+ event *FlowEvent
+ }
+ flowEvent := &FlowEvent{
+ device: "SDX6320031",
+ cookie: "68786618880",
+ eType: EventTypeControlFlowAdded,
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_RegisterFlowAddEvent",
+ args: args{
+ cookie: "68786618880",
+ event: flowEvent,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ d := &VoltDevice{
+ FlowAddEventMap: util.NewConcurrentMap(),
+ }
+ d.RegisterFlowAddEvent(tt.args.cookie, tt.args.event)
+ })
+ }
+}
+
+func TestVoltDevice_RegisterFlowDelEvent(t *testing.T) {
+ type args struct {
+ cookie string
+ event *FlowEvent
+ }
+ flowEvent := &FlowEvent{
+ device: "SDX6320031",
+ cookie: "68786618880",
+ eType: EventTypeControlFlowRemoved,
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_RegisterFlowDelEvent",
+ args: args{
+ cookie: "68786618880",
+ event: flowEvent,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ d := &VoltDevice{
+ FlowDelEventMap: util.NewConcurrentMap(),
+ }
+ d.RegisterFlowDelEvent(tt.args.cookie, tt.args.event)
+ })
+ }
+}
+
+func TestVoltDevice_UnRegisterFlowEvent(t *testing.T) {
+ type args struct {
+ cookie string
+ flowModType of.Command
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_RegisterFlowDelEvent",
+ args: args{
+ cookie: "68786618880",
+ flowModType: of.CommandDel,
+ },
+ },
+ {
+ name: "Negetive_Case_RegisterFlowDelEvent",
+ args: args{
+ cookie: "68786618880",
+ flowModType: opt82,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ switch tt.name {
+ case "Positive_Case_RegisterFlowDelEvent":
+ d := &VoltDevice{
+ FlowDelEventMap: util.NewConcurrentMap(),
+ }
+ d.UnRegisterFlowEvent(tt.args.cookie, tt.args.flowModType)
+ case "Negetive_Case_RegisterFlowDelEvent":
+ d := &VoltDevice{
+ FlowDelEventMap: util.NewConcurrentMap(),
+ }
+ d.UnRegisterFlowEvent(tt.args.cookie, tt.args.flowModType)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_InitStaticConfig(t *testing.T) {
+ tests := []struct {
+ name string
+ }{
+ {
+ name: "Positive_Case_InitStaticConfig",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{}
+ va.InitStaticConfig()
+ })
+ }
+}
+
+func TestVoltApplication_SetVendorID(t *testing.T) {
+ type args struct {
+ vendorID string
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_SetVendorID",
+ args: args{
+ vendorID: "DT",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{}
+ va.SetVendorID(tt.args.vendorID)
+ })
+ }
+}
+
+func TestVoltApplication_GetVendorID(t *testing.T) {
+ tests := []struct {
+ name string
+ want string
+ }{
+ {
+ name: "Positive_Case_GetVendorID",
+ want: "DT",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ vendorID: "DT",
+ }
+ if got := va.GetVendorID(); got != tt.want {
+ t.Errorf("VoltApplication.GetVendorID() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_SetRebootFlag(t *testing.T) {
+ type args struct {
+ flag bool
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_SetRebootFlag",
+ args: args{
+ flag: true,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{}
+ va.SetRebootFlag(tt.args.flag)
+ })
+ }
+}
+
+func TestVoltApplication_GetUpgradeFlag(t *testing.T) {
+ tests := []struct {
+ name string
+ want bool
+ }{
+ {
+ name: "Positive_Case_GetUpgradeFlag",
+ want: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{}
+ isUpgradeComplete = true
+ if got := va.GetUpgradeFlag(); got != tt.want {
+ t.Errorf("VoltApplication.GetUpgradeFlag() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_SetUpgradeFlag(t *testing.T) {
+ type args struct {
+ flag bool
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_GetUpgradeFlag",
+ args: args{
+ flag: true,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{}
+ va.SetUpgradeFlag(tt.args.flag)
+ })
+ }
+}
+
+func TestVoltApplication_AddDevice(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ device string
+ slno string
+ southBoundID string
+ }
+ voltDev := &VoltDevice{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ NniPort: "16777216",
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a123",
+ }
+ nbd := &NbDevice{
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a123",
+ PonPorts: sync.Map{},
+ }
+ ponPortCnf := &PonPortCfg{
+ PortID: controller.NNIPortID,
+ MaxActiveChannels: 123,
+ EnableMulticastKPI: false,
+ PortAlarmProfileID: "16777",
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_AddDevice",
+ args: args{
+ cntx: context.Background(),
+ device: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ slno: "SDX6320031",
+ southBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a123",
+ },
+ },
+ {
+ name: "Negetive_Case_AddDevice",
+ args: args{
+ cntx: context.Background(),
+ device: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ slno: "SDX6320031",
+ southBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a123",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ NbDevice: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_AddDevice":
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ va.NbDevice.Store("49686e2d-618f-4e8e-bca0-442ab850a63a123", nbd)
+ nbd.PonPorts.Store(controller.NNIPortID, ponPortCnf)
+ va.AddDevice(tt.args.cntx, tt.args.device, tt.args.slno, tt.args.southBoundID)
+ case "Negetive_Case_AddDevice":
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ nbd.PonPorts.Store(controller.NNIPortID, ponPortCnf)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().GetAllNbPorts(context.Background(), "49686e2d-618f-4e8e-bca0-442ab850a63a123").AnyTimes()
+ va.AddDevice(tt.args.cntx, tt.args.device, tt.args.slno, tt.args.southBoundID)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_DelDevice(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ device string
+ }
+ voltDev := &VoltDevice{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ NniPort: "16777216",
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a123",
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_AddDevice",
+ args: args{
+ cntx: context.Background(),
+ device: "SDX6320031",
+ },
+ },
+ {
+ name: "Delete_Case_AddDevice",
+ args: args{
+ cntx: context.Background(),
+ device: "SDX6320031",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_AddDevice":
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().DelAllRoutesForDevice(context.Background(), "SDX6320031").AnyTimes()
+ dbintf.EXPECT().GetAllMigrateServicesReq(context.Background(), "SDX6320031").AnyTimes()
+ dbintf.EXPECT().DelAllGroup(context.Background(), "SDX6320031").AnyTimes()
+ dbintf.EXPECT().DelAllMeter(context.Background(), "SDX6320031").AnyTimes()
+ dbintf.EXPECT().DelAllPorts(context.Background(), "SDX6320031").AnyTimes()
+ va.DelDevice(tt.args.cntx, tt.args.device)
+ case "Delete_Case_AddDevice":
+ va.DelDevice(tt.args.cntx, tt.args.device)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_PortAddInd(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ device string
+ id uint32
+ portName string
+ }
+ voltDev := &VoltDevice{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ NniPort: "16777216",
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a123",
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_PortAddInd",
+ args: args{
+ cntx: context.Background(),
+ device: "SDX6320031",
+ id: controller.NNIPortID,
+ portName: "16777216",
+ },
+ },
+ {
+ name: "Negetive_Case_PortAddInd",
+ args: args{
+ cntx: context.Background(),
+ device: "SDX6320031",
+ id: controller.NNIPortID,
+ portName: "16777216",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_PortAddInd":
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ va.PortAddInd(tt.args.cntx, tt.args.device, tt.args.id, tt.args.portName)
+ case "Negetive_Case_PortAddInd":
+ va.PortAddInd(tt.args.cntx, tt.args.device, tt.args.id, tt.args.portName)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_PortUpdateInd(t *testing.T) {
+ type args struct {
+ device string
+ portName string
+ id uint32
+ }
+ voltDev := &VoltDevice{
+ Name: "SDX6320031",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ NniPort: "16777216",
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a123",
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_PortUpdateInd",
+ args: args{
+ device: "SDX6320031",
+ id: controller.NNIPortID,
+ portName: "16777216",
+ },
+ },
+ {
+ name: "Negetive_Case_PortUpdateInd",
+ args: args{
+ device: "SDX6320031",
+ id: controller.NNIPortID,
+ portName: "16777216",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_PortAddInd":
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ d := &VoltDevice{
+ Ports: sync.Map{},
+ }
+ voltPort := &VoltPort{
+ Name: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ Device: "SDX6320031",
+ ID: 16777472,
+ State: PortStateDown,
+ ChannelPerSubAlarmRaised: false,
+ Type: VoltPortTypeNni,
+ }
+ d.Ports.Store(16777472, voltPort)
+ va.PortUpdateInd(tt.args.device, tt.args.portName, tt.args.id)
+ case "Negetive_Case_PortUpdateInd":
+ va.PortUpdateInd(tt.args.device, tt.args.portName, tt.args.id)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_AddNbPonPort(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ oltSbID string
+ portID uint32
+ maxAllowedChannels uint32
+ enableMulticastKPI bool
+ portAlarmProfileID string
+ }
+ voltDev := &VoltDevice{
+ Name: "SDX6320031",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ NniPort: "16777216",
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ }
+ nbd := &NbDevice{
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {
+ name: "Positive_Case_AddNbPonPort",
+ args: args{
+ cntx: context.Background(),
+ oltSbID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ portID: 16777472,
+ maxAllowedChannels: 0,
+ enableMulticastKPI: false,
+ portAlarmProfileID: "16777",
+ },
+ },
+ {
+ name: "Negetive_Case_AddNbPonPort",
+ args: args{
+ cntx: context.Background(),
+ oltSbID: "0",
+ portID: 16777472,
+ maxAllowedChannels: 0,
+ enableMulticastKPI: false,
+ portAlarmProfileID: "16777",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ NbDevice: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_AddNbPonPort":
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ va.NbDevice.Store("49686e2d-618f-4e8e-bca0-442ab850a63a", nbd)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutNbDevicePort(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+ if err := va.AddNbPonPort(tt.args.cntx, tt.args.oltSbID, tt.args.portID, tt.args.maxAllowedChannels, tt.args.enableMulticastKPI, tt.args.portAlarmProfileID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.AddNbPonPort() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ case "Negetive_Case_AddNbPonPort":
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutNbDevicePort(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+ if err := va.AddNbPonPort(tt.args.cntx, tt.args.oltSbID, tt.args.portID, tt.args.maxAllowedChannels, tt.args.enableMulticastKPI, tt.args.portAlarmProfileID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.AddNbPonPort() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ }
+ })
+ }
+}
+
+func TestVoltApplication_UpdateNbPonPort(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ oltSbID string
+ portID uint32
+ maxAllowedChannels uint32
+ enableMulticastKPI bool
+ portAlarmProfileID string
+ }
+ voltDev := &VoltDevice{
+ Name: "SDX6320031",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ NniPort: "16777216",
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ ActiveChannelsPerPon: sync.Map{},
+ }
+ nbd := &NbDevice{
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ PonPorts: sync.Map{},
+ }
+ ponPortCnf := &PonPortCfg{
+ PortID: controller.NNIPortID,
+ MaxActiveChannels: 123,
+ EnableMulticastKPI: false,
+ PortAlarmProfileID: "16777",
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {
+ name: "Positive_Case_UpdateNbPonPort",
+ args: args{
+ cntx: context.Background(),
+ oltSbID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ portID: controller.NNIPortID,
+ maxAllowedChannels: 0,
+ enableMulticastKPI: false,
+ portAlarmProfileID: "16777",
+ },
+ wantErr: false,
+ },
+ {
+ name: "Negetive_Case_Port_doesn't_exists",
+ args: args{
+ cntx: context.Background(),
+ oltSbID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ portID: 16777472,
+ maxAllowedChannels: 0,
+ enableMulticastKPI: false,
+ portAlarmProfileID: "16777",
+ },
+ wantErr: true,
+ },
+ {
+ name: "Negetive_Case_Device-doesn't-exists",
+ args: args{
+ cntx: context.Background(),
+ oltSbID: "0",
+ portID: 16777472,
+ maxAllowedChannels: 0,
+ enableMulticastKPI: false,
+ portAlarmProfileID: "16777",
+ },
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ NbDevice: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_UpdateNbPonPort":
+ va.NbDevice.Store("49686e2d-618f-4e8e-bca0-442ab850a63a", nbd)
+ nbd.PonPorts.Store(controller.NNIPortID, ponPortCnf)
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ voltDev.ActiveChannelsPerPon.Store(controller.NNIPortID, ponPortCnf)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutNbDevicePort(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+ if err := va.UpdateNbPonPort(tt.args.cntx, tt.args.oltSbID, tt.args.portID, tt.args.maxAllowedChannels, tt.args.enableMulticastKPI, tt.args.portAlarmProfileID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.UpdateNbPonPort() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ case "Negetive_Case_Port_doesn't_exists":
+ va.NbDevice.Store("49686e2d-618f-4e8e-bca0-442ab850a63a", nbd)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutNbDevicePort(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+ if err := va.UpdateNbPonPort(tt.args.cntx, tt.args.oltSbID, tt.args.portID, tt.args.maxAllowedChannels, tt.args.enableMulticastKPI, tt.args.portAlarmProfileID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.UpdateNbPonPort() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ case "Negetive_Case_Device-doesn't-exists":
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutNbDevicePort(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+ if err := va.UpdateNbPonPort(tt.args.cntx, tt.args.oltSbID, tt.args.portID, tt.args.maxAllowedChannels, tt.args.enableMulticastKPI, tt.args.portAlarmProfileID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.UpdateNbPonPort() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ }
+ })
+ }
+}
+
+func TestVoltApplication_DeleteNbPonPort(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ oltSbID string
+ portID uint32
+ }
+ voltDev := &VoltDevice{
+ Name: "SDX6320031",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ NniPort: "16777216",
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ ActiveChannelsPerPon: sync.Map{},
+ }
+ nbd := &NbDevice{
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ }
+ ponPortCnf := &PonPortCfg{
+ PortID: controller.NNIPortID,
+ MaxActiveChannels: 123,
+ EnableMulticastKPI: false,
+ PortAlarmProfileID: "16777",
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {
+ name: "Positive_Case_DeleteNbPonPort",
+ args: args{
+ cntx: context.Background(),
+ oltSbID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ portID: controller.NNIPortID,
+ },
+ wantErr: false,
+ },
+ {
+ name: "Negetive_Case_DeleteNbPonPort",
+ args: args{
+ cntx: context.Background(),
+ oltSbID: "0",
+ portID: controller.NNIPortID,
+ },
+ wantErr: false,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ NbDevice: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_DeleteNbPonPort":
+ va.NbDevice.Store("49686e2d-618f-4e8e-bca0-442ab850a63a", nbd)
+ nbd.PonPorts.Store(controller.NNIPortID, ponPortCnf)
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ voltDev.ActiveChannelsPerPon.Store(controller.NNIPortID, ponPortCnf)
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().DelNbDevicePort(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+ if err := va.DeleteNbPonPort(tt.args.cntx, tt.args.oltSbID, tt.args.portID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.DeleteNbPonPort() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ case "Negetive_Case_DeleteNbPonPort":
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().DelNbDevicePort(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+ if err := va.DeleteNbPonPort(tt.args.cntx, tt.args.oltSbID, tt.args.portID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.DeleteNbPonPort() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ }
+ })
+ }
+}
+
+func TestVoltApplication_DeviceUpInd(t *testing.T) {
+ type args struct {
+ device string
+ }
+ voltDev := &VoltDevice{
+ Name: "SDX6320031",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ NniPort: "16777216",
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_DeviceUpInd",
+ args: args{
+ device: "SDX6320031",
+ },
+ },
+ {
+ name: "Negetive_Case_DeviceUpInd",
+ args: args{
+ device: "o",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_DeviceUpInd":
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ va.DeviceUpInd(tt.args.device)
+ case "Negetive_Case_DeviceUpInd":
+ va.DeviceUpInd(tt.args.device)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_DeviceDownInd(t *testing.T) {
+ type args struct {
+ device string
+ }
+ voltDev := &VoltDevice{
+ Name: "SDX6320031",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ NniPort: "16777216",
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_DeviceDownInd",
+ args: args{
+ device: "SDX6320031",
+ },
+ },
+ {
+ name: "Negetive_Case_DeviceDownInd",
+ args: args{
+ device: "o",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ }
+ switch tt.name {
+ case "Positive_Case_DeviceDownInd":
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ va.DeviceDownInd(tt.args.device)
+ case "Negetive_Case_DeviceDownInd":
+ va.DeviceDownInd(tt.args.device)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_DeviceRebootInd(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ device string
+ serialNum string
+ southBoundID string
+ }
+ voltDev := &VoltDevice{
+ Name: "SDX6320031",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ NniPort: "16777216",
+ SouthBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ State: controller.DeviceStateREBOOTED,
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Positive_Case_DeviceRebootInd",
+ args: args{
+ device: "SDX6320031",
+ serialNum: "SDX6320031",
+ southBoundID: "49686e2d-618f-4e8e-bca0-442ab850a63a",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ }
+ va.DevicesDisc.Store("SDX6320031", voltDev)
+ va.DeviceRebootInd(tt.args.cntx, tt.args.device, tt.args.serialNum, tt.args.southBoundID)
+ })
+ }
+}
diff --git a/internal/pkg/application/flowevent_test.go b/internal/pkg/application/flowevent_test.go
new file mode 100644
index 0000000..400176a
--- /dev/null
+++ b/internal/pkg/application/flowevent_test.go
@@ -0,0 +1,290 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* 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 application
+
+import (
+ "context"
+ "testing"
+ "voltha-go-controller/internal/pkg/intf"
+ "voltha-go-controller/internal/pkg/of"
+ "voltha-go-controller/internal/pkg/util"
+ "voltha-go-controller/internal/test/mocks"
+
+ "github.com/golang/mock/gomock"
+)
+
+var voltPortVnet = &VoltPortVnet{
+ Device: "test_device",
+}
+var voltService = &VoltService{
+ Version: "test_version",
+}
+
+func TestExecuteFlowEvent(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ vd *VoltDevice
+ cookie string
+ flowStatus intf.FlowStatus
+ }
+ tests := []struct {
+ name string
+ args args
+ want bool
+ }{
+ {
+ name: "ExecuteFlowEvent_add",
+ args: args{
+ cntx: context.Background(),
+ vd: &VoltDevice{
+ SouthBoundID: "test_device_id",
+ FlowAddEventMap: util.NewConcurrentMap(),
+ },
+ cookie: "test_cookie",
+ flowStatus: intf.FlowStatus{
+ Device: "test_device",
+ FlowModType: of.CommandAdd,
+ },
+ },
+ },
+ {
+ name: "ExecuteFlowEvent_del",
+ args: args{
+ cntx: context.Background(),
+ vd: &VoltDevice{
+ SouthBoundID: "test_device_id",
+ FlowDelEventMap: util.NewConcurrentMap(),
+ },
+ cookie: "test_cookie",
+ flowStatus: intf.FlowStatus{
+ Device: "test_device",
+ FlowModType: of.CommandDel,
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ switch tt.name {
+ case "ExecuteFlowEvent_add":
+ if got := ExecuteFlowEvent(tt.args.cntx, tt.args.vd, tt.args.cookie, tt.args.flowStatus); got != tt.want {
+ t.Errorf("ExecuteFlowEvent() = %v, want %v", got, tt.want)
+ }
+ case "ExecuteFlowEvent_del":
+ if got := ExecuteFlowEvent(tt.args.cntx, tt.args.vd, tt.args.cookie, tt.args.flowStatus); got != tt.want {
+ t.Errorf("ExecuteFlowEvent() = %v, want %v", got, tt.want)
+ }
+ }
+ })
+ }
+}
+
+func TestInitEventFuncMapper(t *testing.T) {
+ tests := []struct {
+ name string
+ }{
+ {
+ name: "InitEventFuncMapper",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ InitEventFuncMapper()
+ })
+ }
+}
+
+func TestProcessUsIgmpFlowAddEvent(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ event *FlowEvent
+ flowStatus intf.FlowStatus
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "ProcessUsIgmpFlowAddEvent",
+ args: args{
+ cntx: context.Background(),
+ event: &FlowEvent{
+ device: "test_device",
+ eType: EventTypeControlFlowAdded,
+ eventData: voltPortVnet,
+ },
+ flowStatus: intf.FlowStatus{
+ Device: "test_device",
+ Status: uint32(0),
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ ProcessUsIgmpFlowAddEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
+ })
+ }
+}
+
+func TestProcessServiceFlowAddEvent(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ event *FlowEvent
+ flowStatus intf.FlowStatus
+ }
+
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "ProcessServiceFlowAddEvent",
+ args: args{
+ cntx: context.Background(),
+ event: &FlowEvent{
+ device: "test_device",
+ eventData: voltService,
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ ProcessServiceFlowAddEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
+ })
+ }
+}
+
+func TestProcessControlFlowAddEvent(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ event *FlowEvent
+ flowStatus intf.FlowStatus
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "ProcessControlFlowAddEvent",
+ args: args{
+ cntx: context.Background(),
+ event: &FlowEvent{
+ eventData: voltPortVnet,
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ ProcessControlFlowAddEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
+ })
+ }
+}
+
+func TestProcessServiceFlowDelEvent(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ event *FlowEvent
+ flowStatus intf.FlowStatus
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "ProcessServiceFlowDelEvent",
+ args: args{
+ cntx: context.Background(),
+ event: &FlowEvent{
+ eventData: voltService,
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
+ ProcessServiceFlowDelEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
+ })
+ }
+}
+
+func TestProcessControlFlowDelEvent(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ event *FlowEvent
+ flowStatus intf.FlowStatus
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "ProcessControlFlowDelEvent",
+ args: args{
+ cntx: context.Background(),
+ event: &FlowEvent{
+ eventData: voltPortVnet,
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutVpv(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
+ ProcessControlFlowDelEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
+ })
+ }
+}
+
+func TestProcessMcastFlowDelEvent(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ event *FlowEvent
+ flowStatus intf.FlowStatus
+ }
+ mvlanProfile := &MvlanProfile{
+ Version: "test_version",
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "ProcessMcastFlowDelEvent",
+ args: args{
+ cntx: context.Background(),
+ event: &FlowEvent{
+ eventData: mvlanProfile,
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutMvlan(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
+ ProcessMcastFlowDelEvent(tt.args.cntx, tt.args.event, tt.args.flowStatus)
+ })
+ }
+}
diff --git a/internal/pkg/application/igmp_test.go b/internal/pkg/application/igmp_test.go
new file mode 100644
index 0000000..9e1e940
--- /dev/null
+++ b/internal/pkg/application/igmp_test.go
@@ -0,0 +1,36 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* 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 application
+
+import (
+ "testing"
+)
+
+func TestVoltApplication_InitIgmpSrcMac(t *testing.T) {
+ tests := []struct {
+ name string
+ }{
+ {
+ name: "test",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{}
+ va.InitIgmpSrcMac()
+ })
+ }
+}
diff --git a/internal/pkg/application/service_test.go b/internal/pkg/application/service_test.go
new file mode 100644
index 0000000..b9c458b
--- /dev/null
+++ b/internal/pkg/application/service_test.go
@@ -0,0 +1,1552 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* 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 application
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "sync"
+ "testing"
+ "voltha-go-controller/internal/pkg/controller"
+ cntlr "voltha-go-controller/internal/pkg/controller"
+ "voltha-go-controller/internal/pkg/of"
+ "voltha-go-controller/internal/pkg/util"
+ "voltha-go-controller/internal/test/mocks"
+
+ "github.com/golang/mock/gomock"
+ "github.com/google/gopacket/layers"
+ "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
+ "github.com/stretchr/testify/assert"
+ "go.uber.org/atomic"
+)
+
+var test_device = "test_device"
+var voltPort = &VoltPort{
+ Name: "test_name",
+ Device: test_device,
+}
+var voltDevice = &VoltDevice{
+ Name: "test_name",
+ State: controller.DeviceStateUP,
+ FlowAddEventMap: util.NewConcurrentMap(),
+ FlowDelEventMap: util.NewConcurrentMap(),
+ SerialNum: "test_serial_number",
+}
+
+var voltMeter = &VoltMeter{
+ Name: "test_volt_meter",
+ Version: "test_version",
+}
+
+var voltVnet = &VoltVnet{
+ Version: "test_version",
+ VnetConfig: VnetConfig{
+ Name: "test_name",
+ },
+}
+
+var voltPortVnet1 = []*VoltPortVnet{
+ {
+ Device: "4096-4096-4096",
+ SVlan: of.VlanAny,
+ CVlan: of.VlanAny,
+ UniVlan: of.VlanAny,
+ IgmpEnabled: true,
+ servicesCount: &atomic.Uint64{},
+ },
+}
+
+var voltDevice1 = &VoltDevice{
+ State: cntlr.DeviceStateDOWN,
+}
+
+var GetDeviceFromPort_error = "GetDeviceFromPort_error"
+
+func TestVoltApplication_RestoreSvcsFromDb(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "VoltApplication_RestoreSvcsFromDb",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ {
+ name: "invalid_value_type",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ {
+ name: "unmarshal_error",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ voltService := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ Device: "SDX6320031",
+ ForceDelete: true,
+ DeleteInProgress: true,
+ },
+ VoltServiceCfg: VoltServiceCfg{
+ Name: "test_service_name",
+ },
+ }
+ serviceToDelete := map[string]bool{}
+ serviceToDelete[voltService.VoltServiceCfg.Name] = true
+ va := &VoltApplication{
+ ServicesToDelete: serviceToDelete,
+ }
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ switch tt.name {
+ case "VoltApplication_RestoreSvcsFromDb":
+
+ b, err := json.Marshal(voltService)
+ if err != nil {
+ panic(err)
+ }
+ kvPair := map[string]*kvstore.KVPair{}
+ kvPair["key"] = &kvstore.KVPair{
+ Key: "test_key",
+ Value: b,
+ Version: 1,
+ }
+ dbintf.EXPECT().GetServices(tt.args.cntx).Return(kvPair, nil).Times(1)
+ va.RestoreSvcsFromDb(tt.args.cntx)
+ case "invalid_value_type":
+ kvPair := map[string]*kvstore.KVPair{}
+ kvPair["key"] = &kvstore.KVPair{
+ Key: "test_key",
+ Value: "invalid_value",
+ Version: 1,
+ }
+ dbintf.EXPECT().GetServices(tt.args.cntx).Return(kvPair, nil).Times(1)
+ va.RestoreSvcsFromDb(tt.args.cntx)
+ case "unmarshal_error":
+ b, err := json.Marshal("test")
+ if err != nil {
+ panic(err)
+ }
+ kvPair := map[string]*kvstore.KVPair{}
+ kvPair["key"] = &kvstore.KVPair{
+ Key: "test_key",
+ Value: b,
+ Version: 1,
+ }
+ dbintf.EXPECT().GetServices(tt.args.cntx).Return(kvPair, nil).Times(1)
+ va.RestoreSvcsFromDb(tt.args.cntx)
+ }
+ })
+ }
+}
+
+func TestVoltService_FlowRemoveFailure(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ cookie string
+ errorCode uint32
+ errReason string
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "VoltService_FlowRemoveFailure",
+ args: args{
+ cntx: context.Background(),
+ cookie: "test_cookie",
+ errorCode: 200,
+ errReason: "test_reason",
+ },
+ },
+ {
+ name: "cookie_not_found",
+ args: args{
+ cntx: context.Background(),
+ cookie: "test_cookie",
+ errorCode: 200,
+ errReason: "test_reason",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ switch tt.name {
+ case "VoltService_FlowRemoveFailure":
+ associatedFlows := map[string]bool{}
+ associatedFlows["test_cookie"] = true
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ AssociatedFlows: associatedFlows,
+ },
+ }
+ vs.FlowRemoveFailure(tt.args.cntx, tt.args.cookie, tt.args.errorCode, tt.args.errReason)
+ case "cookie_not_found":
+ associatedFlows := map[string]bool{}
+ associatedFlows["cookie"] = true
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ AssociatedFlows: associatedFlows,
+ },
+ }
+ vs.FlowRemoveFailure(tt.args.cntx, tt.args.cookie, tt.args.errorCode, tt.args.errReason)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_GetServiceNameFromCookie(t *testing.T) {
+ type args struct {
+ cookie uint64
+ portName string
+ pbit uint8
+ device string
+ tableMetadata uint64
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "VoltApplication_GetServiceNameFromCookie",
+ args: args{
+ cookie: uint64(1),
+ portName: "test_port_name",
+ device: "SDX6320031",
+ pbit: 2,
+ tableMetadata: uint64(2),
+ },
+ },
+ }
+ voltDev := &VoltDevice{
+ Name: "SDX6320031",
+ SerialNum: "SDX6320031",
+ NniDhcpTrapVid: 123,
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ ga := GetApplication()
+ ga.DevicesDisc.Store("SDX6320031", voltDev)
+ voltPortVnets := make([]*VoltPortVnet, 0)
+ voltPortVnet := &VoltPortVnet{
+ Device: test_device,
+ VlanControl: ONUCVlanOLTSVlan,
+ }
+ voltPortVnets = append(voltPortVnets, voltPortVnet)
+ ga.VnetsByPort.Store("test_port_name", voltPortVnets)
+ got := ga.GetServiceNameFromCookie(tt.args.cookie, tt.args.portName, tt.args.pbit, tt.args.device, tt.args.tableMetadata)
+ assert.Nil(t, got)
+ })
+ }
+}
+
+func TestVoltService_SvcUpInd(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "VoltService_SvcUpInd",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ PendingFlows: make(map[string]bool),
+ },
+ VoltServiceCfg: VoltServiceCfg{
+ SVlanTpid: layers.EthernetTypeDot1Q,
+ MacAddr: layers.EthernetBroadcast,
+ },
+ }
+ vs.Port = test_device
+ vs.Device = "device"
+ ga := GetApplication()
+ _ = cntlr.NewController(context.Background(), mocks.NewMockApp(gomock.NewController(t)))
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
+ ga.PortsDisc.Store(test_device, voltPort)
+ ga.DevicesDisc.Store(test_device, voltDevice)
+ vs.SvcUpInd(tt.args.cntx)
+ })
+ }
+}
+
+func TestVoltService_SvcDownInd(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "VoltService_SvcDownInd",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ UsHSIAFlowsApplied: true,
+ DsHSIAFlowsApplied: true,
+ },
+ VoltServiceCfg: VoltServiceCfg{
+ SVlanTpid: layers.EthernetTypeQinQ,
+ MacAddr: layers.EthernetBroadcast,
+ },
+ }
+ vs.Port = test_device
+ vs.Device = "device"
+ ga := GetApplication()
+ _ = cntlr.NewController(context.Background(), mocks.NewMockApp(gomock.NewController(t)))
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
+ ga.PortsDisc.Store(test_device, voltPort)
+ ga.DevicesDisc.Store(test_device, voltDevice)
+ vs.SvcDownInd(tt.args.cntx)
+ })
+ }
+}
+
+func TestVoltApplication_AddService(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ cfg VoltServiceCfg
+ oper *VoltServiceOper
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "VoltApplication_AddService",
+ args: args{
+ cntx: context.Background(),
+ cfg: VoltServiceCfg{
+ Name: "test_name",
+ Port: "test_port",
+ DsMeterProfile: "4096-4096-4096",
+ UsMeterProfile: "4096-4096-4096",
+ SVlan: of.VlanAny,
+ CVlan: of.VlanAny,
+ UniVlan: of.VlanAny,
+ MacLearning: Learn,
+ IsActivated: true,
+ },
+ oper: &VoltServiceOper{
+ Device: "4096-4096-4096",
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ MeterMgr: MeterMgr{
+ Meters: sync.Map{},
+ },
+ VnetsByPort: sync.Map{},
+ VnetsByTag: sync.Map{},
+ }
+ va.MeterMgr.Meters.Store("4096-4096-4096", voltMeter)
+ va.VnetsByTag.Store("4096-4096-4096", voltVnet)
+ voltPortVnet1[0].SVlan = of.VlanAny
+ voltPortVnet1[0].CVlan = of.VlanAny
+ voltPortVnet1[0].UniVlan = of.VlanAny
+ voltPortVnet1[0].servicesCount = atomic.NewUint64(uint64(56))
+ voltPortVnet1[0].MacAddr = layers.EthernetBroadcast
+ voltPortVnet1[0].Port = "test_port"
+ va.VnetsByPort.Store("test_port", voltPortVnet1)
+ ga := GetApplication()
+ voltPort1 := &VoltPort{
+ Name: "test_name",
+ Device: test_device,
+ }
+ deviceConfig := &DeviceConfig{
+ SerialNumber: "test_serial_number",
+ }
+ ga.PortsDisc.Store("test_port", voltPort1)
+ ga.DevicesDisc.Store(test_device, voltDevice)
+ ga.DevicesConfig.Store("test_serial_number", deviceConfig)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
+ dbintf.EXPECT().PutVpv(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
+ err := va.AddService(tt.args.cntx, tt.args.cfg, tt.args.oper)
+ assert.Nil(t, err)
+ })
+ }
+}
+
+func TestVoltApplication_DelService(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ name string
+ forceDelete bool
+ newSvc *VoltServiceCfg
+ serviceMigration bool
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "VoltApplication_DelService",
+ args: args{
+ cntx: context.Background(),
+ name: "test_name",
+ forceDelete: true,
+ newSvc: &VoltServiceCfg{
+ Name: "vs_cfg_name",
+ Port: "test_port",
+ },
+ serviceMigration: true,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ ServiceByName: sync.Map{},
+ VnetsByPort: sync.Map{},
+ }
+ voltService := &VoltService{
+ Version: "test_version",
+ VoltServiceCfg: VoltServiceCfg{
+ Port: "4096-4096-4096",
+ SVlan: of.VlanAny,
+ CVlan: of.VlanAny,
+ UniVlan: of.VlanAny,
+ },
+ }
+ va.ServiceByName.Store(tt.args.name, voltService)
+ va.VnetsByPort.Store("4096-4096-4096", voltPortVnet1)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().DelService(gomock.Any(), gomock.Any()).AnyTimes()
+ dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
+ va.DelService(tt.args.cntx, tt.args.name, tt.args.forceDelete, tt.args.newSvc, tt.args.serviceMigration)
+ })
+ }
+}
+
+func TestVoltService_FlowInstallSuccess(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ cookie string
+ bwAvailInfo of.BwAvailDetails
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "VoltService_FlowInstallSuccess",
+ args: args{
+ cntx: context.Background(),
+ cookie: "test_cookie",
+ bwAvailInfo: of.BwAvailDetails{
+ PrevBw: "test_prev_BW",
+ PresentBw: "test_present_BW",
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ pendingFlows := map[string]bool{}
+ pendingFlows["test_cookie"] = true
+ associatedFlows := map[string]bool{}
+ associatedFlows["test_cookie"] = true
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ PendingFlows: pendingFlows,
+ AssociatedFlows: associatedFlows,
+ DsHSIAFlowsApplied: true,
+ },
+ VoltServiceCfg: VoltServiceCfg{
+ Port: "test_port",
+ },
+ }
+ ga := GetApplication()
+ ga.PortsDisc.Store("test_port", voltPort)
+ ga.DevicesDisc.Store(test_device, voltDevice)
+ vs.FlowInstallSuccess(tt.args.cntx, tt.args.cookie, tt.args.bwAvailInfo)
+ })
+ }
+}
+
+func TestVoltService_AddMeterToDevice(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {
+ name: "VoltService_AddMeterToDevice",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ {
+ name: GetDeviceFromPort_error,
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ {
+ name: "DeviceState_down",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ switch tt.name {
+ case "VoltService_AddMeterToDevice":
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ DeleteInProgress: true,
+ },
+ VoltServiceCfg: VoltServiceCfg{
+ Port: "test_port",
+ },
+ }
+ ga := GetApplication()
+ ga.PortsDisc.Store("test_port", voltPort)
+ ga.DevicesDisc.Store(test_device, voltDevice)
+ err := vs.AddMeterToDevice(tt.args.cntx)
+ assert.Nil(t, err)
+ case GetDeviceFromPort_error:
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ DeleteInProgress: true,
+ },
+ VoltServiceCfg: VoltServiceCfg{
+ Port: "",
+ },
+ }
+ err := vs.AddMeterToDevice(tt.args.cntx)
+ assert.NotNil(t, err)
+ case "DeviceState_down":
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ DeleteInProgress: true,
+ },
+ VoltServiceCfg: VoltServiceCfg{
+ Port: "test_port",
+ },
+ }
+ ga := GetApplication()
+ ga.PortsDisc.Store("test_port", voltPort)
+ ga.DevicesDisc.Store(test_device, voltDevice1)
+ err := vs.AddMeterToDevice(tt.args.cntx)
+ assert.Nil(t, err)
+ }
+ })
+ }
+}
+
+func TestVoltService_AddUsHsiaFlows(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {
+ name: "DeleteInProgress_true",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ {
+ name: "GetDeviceFromPort_error",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ {
+ name: "DeviceState_down",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ switch tt.name {
+ case "DeleteInProgress_true":
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ DeleteInProgress: true,
+ },
+ }
+ err := vs.AddUsHsiaFlows(tt.args.cntx)
+ assert.Nil(t, err)
+ case "GetDeviceFromPort_error":
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ DeleteInProgress: false,
+ },
+ }
+ err := vs.AddUsHsiaFlows(tt.args.cntx)
+ assert.NotNil(t, err)
+ case "DeviceState_down":
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ DeleteInProgress: false,
+ },
+ VoltServiceCfg: VoltServiceCfg{
+ Port: "test_port",
+ },
+ }
+ ga := GetApplication()
+ ga.PortsDisc.Store("test_port", voltPort)
+ ga.DevicesDisc.Store(test_device, voltDevice1)
+ err := vs.AddUsHsiaFlows(tt.args.cntx)
+ assert.Nil(t, err)
+ }
+ })
+ }
+}
+
+func TestVoltService_AddHsiaFlows(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "AddUsHsiaFlows_error",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ vs := &VoltService{
+ VoltServiceCfg: VoltServiceCfg{
+ Port: "test_port",
+ VlanControl: 5,
+ },
+ }
+ ga := GetApplication()
+ ga.PortsDisc.Store("test_port", voltPort)
+ ga.DevicesDisc.Store(test_device, voltDevice)
+ vs.AddHsiaFlows(tt.args.cntx)
+ })
+ }
+}
+
+func TestVoltService_ForceWriteToDb(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "PutService_error",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ switch tt.name {
+ case "PutService_error":
+ vs := &VoltService{}
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("error")).AnyTimes()
+ vs.ForceWriteToDb(tt.args.cntx)
+ }
+ })
+ }
+}
+
+func TestVoltService_isDataRateAttrPresent(t *testing.T) {
+ tests := []struct {
+ name string
+ want bool
+ }{
+ {
+ name: "VoltService_isDataRateAttrPresent",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ vs := &VoltService{}
+ if got := vs.isDataRateAttrPresent(); got != tt.want {
+ t.Errorf("VoltService.isDataRateAttrPresent() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestVoltService_GetServicePbit(t *testing.T) {
+ tests := []struct {
+ name string
+ want int
+ }{
+ {
+ name: "VoltService_GetServicePbit",
+ want: -1,
+ },
+ {
+ name: "!IsPbitExist",
+ want: 8,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ switch tt.name {
+ case "VoltService_GetServicePbit":
+ vs := &VoltService{
+ VoltServiceCfg: VoltServiceCfg{
+ Pbits: []of.PbitType{of.PbitMatchAll},
+ },
+ }
+ if got := vs.GetServicePbit(); got != tt.want {
+ t.Errorf("VoltService.GetServicePbit() = %v, want %v", got, tt.want)
+ }
+ case "!IsPbitExist":
+ vs := &VoltService{}
+ if got := vs.GetServicePbit(); got != tt.want {
+ t.Errorf("VoltService.GetServicePbit() = %v, want %v", got, tt.want)
+ }
+ }
+ })
+ }
+}
+
+func TestVoltApplication_DeactivateService(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ deviceID string
+ portNo string
+ sVlan of.VlanType
+ cVlan of.VlanType
+ tpID uint16
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {
+ name: "VoltApplication_DeactivateService",
+ args: args{
+ cntx: context.Background(),
+ deviceID: "test_device_id",
+ portNo: "test_port",
+ sVlan: of.VlanNone,
+ cVlan: of.VlanAny,
+ tpID: AnyVlan,
+ },
+ },
+ {
+ name: "VoltPortVnet_nil",
+ args: args{
+ cntx: context.Background(),
+ deviceID: "test_device_id",
+ portNo: "test_port",
+ sVlan: of.VlanNone,
+ cVlan: of.VlanAny,
+ tpID: AnyVlan,
+ },
+ },
+ {
+ name: "sVlan != of.VlanNone",
+ args: args{
+ cntx: context.Background(),
+ deviceID: "test_device_id",
+ portNo: "test_port",
+ sVlan: of.VlanAny,
+ cVlan: of.VlanAny,
+ tpID: AnyVlan,
+ },
+ },
+ {
+ name: GetDeviceFromPort_error,
+ args: args{
+ cntx: context.Background(),
+ deviceID: "test_device_id",
+ portNo: "test_port",
+ sVlan: of.VlanNone,
+ cVlan: of.VlanAny,
+ tpID: AnyVlan,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ ServiceByName: sync.Map{},
+ VnetsByPort: sync.Map{},
+ DevicesDisc: sync.Map{},
+ PortsDisc: sync.Map{},
+ }
+ voltServiceTest := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ Device: test_device,
+ },
+ Version: "test_version",
+ VoltServiceCfg: VoltServiceCfg{
+ Port: "test_port",
+ Name: "test_name",
+ IsActivated: true,
+ CVlan: of.VlanAny,
+ SVlan: of.VlanAny,
+ UniVlan: of.VlanAny,
+ },
+ }
+ switch tt.name {
+ case "VoltApplication_DeactivateService":
+ va.ServiceByName.Store("test_name", voltServiceTest)
+ va.PortsDisc.Store("test_port", voltPort)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
+ va.DevicesDisc.Store(test_device, voltDevice)
+ voltDevice.Ports.Store("test_port", voltPort)
+ va.VnetsByPort.Store("test_port", voltPortVnet1)
+ voltPortVnet1[0].servicesCount.Store(uint64(1))
+ dbintf.EXPECT().PutVpv(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
+ if err := va.DeactivateService(tt.args.cntx, tt.args.deviceID, tt.args.portNo, tt.args.sVlan, tt.args.cVlan, tt.args.tpID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.DeactivateService() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ case "VoltPortVnet_nil":
+ va.ServiceByName.Store("test_name", voltServiceTest)
+ va.PortsDisc.Store("test_port", voltPort)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
+ va.DevicesDisc.Store(test_device, voltDevice)
+ voltDevice.Ports.Store("test_port", voltPort)
+ if err := va.DeactivateService(tt.args.cntx, tt.args.deviceID, tt.args.portNo, tt.args.sVlan, tt.args.cVlan, tt.args.tpID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.DeactivateService() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ case "sVlan != of.VlanNone":
+ va.ServiceByName.Store("test_name", voltServiceTest)
+ if err := va.DeactivateService(tt.args.cntx, tt.args.deviceID, tt.args.portNo, tt.args.sVlan, tt.args.cVlan, tt.args.tpID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.DeactivateService() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ case GetDeviceFromPort_error:
+ va.ServiceByName.Store("test_name", voltServiceTest)
+ if err := va.DeactivateService(tt.args.cntx, tt.args.deviceID, tt.args.portNo, tt.args.sVlan, tt.args.cVlan, tt.args.tpID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.DeactivateService() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ }
+ })
+ }
+}
+
+func TestVoltApplication_ActivateService(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ deviceID string
+ portNo string
+ sVlan of.VlanType
+ cVlan of.VlanType
+ tpID uint16
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {
+ name: "VoltApplication_ActivateService",
+ args: args{
+ cntx: context.Background(),
+ deviceID: "test_name",
+ portNo: "test_port",
+ sVlan: of.VlanNone,
+ cVlan: of.VlanAny,
+ tpID: AnyVlan,
+ },
+ },
+ {
+ name: "VoltPortVnet_nil",
+ args: args{
+ cntx: context.Background(),
+ deviceID: "test_name",
+ portNo: "test_port",
+ sVlan: of.VlanNone,
+ cVlan: of.VlanAny,
+ tpID: AnyVlan,
+ },
+ },
+ {
+ name: GetDeviceFromPort_error,
+ args: args{
+ cntx: context.Background(),
+ deviceID: "test_name",
+ portNo: "test_port",
+ sVlan: of.VlanNone,
+ cVlan: of.VlanAny,
+ tpID: AnyVlan,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ DevicesDisc: sync.Map{},
+ }
+ var voltPortTest = &VoltPort{
+ Name: "test_name",
+ State: PortStateUp,
+ }
+ voltServiceTest := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ Device: test_device,
+ },
+ Version: "test_version",
+ VoltServiceCfg: VoltServiceCfg{
+ Port: "test_port",
+ Name: "test_name",
+ IsActivated: false,
+ CVlan: of.VlanAny,
+ SVlan: of.VlanAny,
+ UniVlan: of.VlanAny,
+ },
+ }
+ switch tt.name {
+ case "VoltApplication_ActivateService":
+ voltPortTest.Device = test_device
+ va.PortsDisc.Store("test_port", voltPortTest)
+ va.DevicesDisc.Store(test_device, voltDevice)
+ va.ServiceByName.Store("test_name", voltServiceTest)
+ va.VnetsByPort.Store("test_port", voltPortVnet1)
+ voltDevice.Ports.Store("test_port", voltPortTest)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
+ if err := va.ActivateService(tt.args.cntx, tt.args.deviceID, tt.args.portNo, tt.args.sVlan, tt.args.cVlan, tt.args.tpID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.ActivateService() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ case "VoltPortVnet_nil":
+ voltPortTest.Device = test_device
+ va.ServiceByName.Store("test_name", voltServiceTest)
+ va.PortsDisc.Store("test_port", voltPortTest)
+ dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+ db = dbintf
+ dbintf.EXPECT().PutService(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
+ va.DevicesDisc.Store(test_device, voltDevice)
+ voltDevice.Ports.Store("test_port", voltPortTest)
+ if err := va.ActivateService(tt.args.cntx, tt.args.deviceID, tt.args.portNo, tt.args.sVlan, tt.args.cVlan, tt.args.tpID); (err != nil) != tt.wantErr {
+ t.Errorf("VoltApplication.ActivateService() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ case GetDeviceFromPort_error:
+ err := va.ActivateService(tt.args.cntx, tt.args.deviceID, tt.args.portNo, tt.args.sVlan, tt.args.cVlan, tt.args.tpID)
+ assert.NotNil(t, err)
+ }
+ })
+ }
+}
+
+func TestVoltApplication_GetProgrammedSubscribers(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ deviceID string
+ portNo string
+ }
+ tests := []struct {
+ name string
+ args args
+ want []*VoltService
+ wantErr bool
+ }{
+ {
+ name: "VoltApplication_GetProgrammedSubscribers",
+ args: args{
+ cntx: context.Background(),
+ deviceID: test_device,
+ portNo: "test_port",
+ },
+ },
+ {
+ name: "portNo_nil",
+ args: args{
+ cntx: context.Background(),
+ deviceID: test_device,
+ },
+ },
+ {
+ name: "deviceID_nil",
+ args: args{
+ cntx: context.Background(),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ vendorID: "test_vendor",
+ }
+ voltServiceTest := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ Device: test_device,
+ },
+ Version: "test_version",
+ VoltServiceCfg: VoltServiceCfg{
+ Port: "test_port",
+ Name: "test_name",
+ IsActivated: false,
+ CVlan: of.VlanAny,
+ SVlan: of.VlanAny,
+ UniVlan: of.VlanAny,
+ },
+ }
+ switch tt.name {
+ case "VoltApplication_GetProgrammedSubscribers":
+ va.ServiceByName.Store("test_name", voltServiceTest)
+ got, err := va.GetProgrammedSubscribers(tt.args.cntx, tt.args.deviceID, tt.args.portNo)
+ assert.NotNil(t, got)
+ assert.Nil(t, err)
+ case "portNo_nil":
+ va.ServiceByName.Store("test_name", voltServiceTest)
+ got, err := va.GetProgrammedSubscribers(tt.args.cntx, tt.args.deviceID, tt.args.portNo)
+ assert.NotNil(t, got)
+ assert.Nil(t, err)
+ case "deviceID_nil":
+ va.ServiceByName.Store("test_name", voltServiceTest)
+ got, err := va.GetProgrammedSubscribers(tt.args.cntx, tt.args.deviceID, tt.args.portNo)
+ assert.NotNil(t, got)
+ assert.Nil(t, err)
+ }
+ })
+ }
+}
+
+func TestVoltService_JSONMarshal(t *testing.T) {
+ tests := []struct {
+ name string
+ }{
+ {
+ name: "VoltService_JSONMarshal",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ Device: test_device,
+ },
+ Version: "test_version",
+ VoltServiceCfg: VoltServiceCfg{
+ Name: "test_name",
+ },
+ }
+ got, err := vs.JSONMarshal()
+ assert.NotNil(t, got)
+ assert.Nil(t, err)
+ })
+ }
+}
+
+func TestVoltService_triggerServiceInProgressInd(t *testing.T) {
+ tests := []struct {
+ name string
+ }{
+ {
+ name: "VoltService_triggerServiceInProgressInd",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ vs := &VoltService{
+ Version: "test_version",
+ }
+ vs.triggerServiceInProgressInd()
+ })
+ }
+}
+
+func TestVoltService_TriggerAssociatedFlowDelete(t *testing.T) {
+ type args struct {
+ cntx context.Context
+ }
+ tests := []struct {
+ name string
+ args args
+ want bool
+ }{
+ {
+ name: "VoltService_TriggerAssociatedFlowDelete",
+ args: args{
+ cntx: context.Background(),
+ },
+ want: true,
+ },
+ {
+ name: "cookieList_nil",
+ args: args{
+ cntx: context.Background(),
+ },
+ want: false,
+ },
+ }
+ associatedFlows := map[string]bool{}
+ associatedFlows["5765317"] = true
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ switch tt.name {
+ case "VoltService_TriggerAssociatedFlowDelete":
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ UsHSIAFlowsApplied: true,
+ DsHSIAFlowsApplied: true,
+ AssociatedFlows: associatedFlows,
+ Device: test_device,
+ },
+ }
+ ga := GetApplication()
+ ga.DevicesDisc.Store(test_device, voltDevice)
+ if got := vs.TriggerAssociatedFlowDelete(tt.args.cntx); got != tt.want {
+ t.Errorf("VoltService.TriggerAssociatedFlowDelete() = %v, want %v", got, tt.want)
+ }
+ case "cookieList_nil":
+ vs := &VoltService{
+ VoltServiceOper: VoltServiceOper{
+ UsHSIAFlowsApplied: true,
+ DsHSIAFlowsApplied: true,
+ Device: test_device,
+ },
+ }
+ ga := GetApplication()
+ ga.DevicesDisc.Store(test_device, voltDevice)
+ if got := vs.TriggerAssociatedFlowDelete(tt.args.cntx); got != tt.want {
+ t.Errorf("VoltService.TriggerAssociatedFlowDelete() = %v, want %v", got, tt.want)
+ }
+ }
+ })
+ }
+}
+
+func TestVoltApplication_DeepEqualServicecfg(t *testing.T) {
+ type args struct {
+ evs *VoltServiceCfg
+ nvs *VoltServiceCfg
+ }
+ a := map[int]int{}
+ a[0] = 0
+ tests := []struct {
+ name string
+ args args
+ want bool
+ }{
+ {
+ name: "VoltApplication_DeepEqualServicecfg",
+ args: args{
+ evs: &VoltServiceCfg{
+ Port: "test_port",
+ },
+ nvs: &VoltServiceCfg{
+ Port: "test_port",
+ },
+ },
+ want: true,
+ },
+ {
+ name: "nvs.Name != evs.Name",
+ args: args{
+ evs: &VoltServiceCfg{
+ Name: "test_name",
+ },
+ nvs: &VoltServiceCfg{
+ Port: "test_port",
+ },
+ },
+ want: false,
+ },
+ {
+ name: "nvs.UniVlan != evs.UniVlan",
+ args: args{
+ evs: &VoltServiceCfg{
+ UniVlan: of.VlanAny,
+ },
+ nvs: &VoltServiceCfg{
+ Port: "test_port",
+ },
+ },
+ want: false,
+ },
+ {
+ name: "nvs.CVlan != evs.CVlan",
+ args: args{
+ evs: &VoltServiceCfg{
+ CVlan: of.VlanAny,
+ },
+ nvs: &VoltServiceCfg{
+ Port: "test_port",
+ },
+ },
+ want: false,
+ },
+ {
+ name: "nvs.SVlan != evs.SVlan",
+ args: args{
+ evs: &VoltServiceCfg{
+ SVlan: of.VlanAny,
+ },
+ nvs: &VoltServiceCfg{
+ Port: "test_port",
+ },
+ },
+ want: false,
+ },
+ {
+ name: "nvs.SVlanTpid != 0",
+ args: args{
+ evs: &VoltServiceCfg{
+ SVlanTpid: layers.EthernetTypeARP,
+ },
+ nvs: &VoltServiceCfg{
+ SVlanTpid: layers.EthernetTypeCiscoDiscovery,
+ },
+ },
+ want: false,
+ },
+ {
+ name: "nvs.Pbits != evs.Pbits",
+ args: args{
+ evs: &VoltServiceCfg{
+ Pbits: []of.PbitType{
+ PbitMatchAll,
+ },
+ },
+ nvs: &VoltServiceCfg{
+ Port: "test_port",
+ },
+ },
+ want: false,
+ },
+ {
+ name: "nvs.DsRemarkPbitsMap != evs.DsRemarkPbitsMap",
+ args: args{
+ evs: &VoltServiceCfg{
+ DsRemarkPbitsMap: a,
+ },
+ nvs: &VoltServiceCfg{
+ Port: "test_port",
+ },
+ },
+ want: false,
+ },
+ {
+ name: "nvs.TechProfileID != evs.TechProfileID",
+ args: args{
+ evs: &VoltServiceCfg{
+ TechProfileID: uint16(1),
+ },
+ nvs: &VoltServiceCfg{
+ Port: "test_port",
+ },
+ },
+ want: false,
+ },
+ {
+ name: "nvs.CircuitID != evs.CircuitID",
+ args: args{
+ evs: &VoltServiceCfg{
+ CircuitID: "test_circuit_id",
+ },
+ nvs: &VoltServiceCfg{
+ Port: "test_port",
+ },
+ },
+ want: false,
+ },
+ {
+ name: "nvs.RemoteID != evs.RemoteID",
+ args: args{
+ evs: &VoltServiceCfg{
+ RemoteID: []byte{1},
+ },
+ nvs: &VoltServiceCfg{
+ Port: "test_port",
+ },
+ },
+ want: false,
+ },
+ {
+ name: "nvs.Port != evs.Port",
+ args: args{
+ evs: &VoltServiceCfg{},
+ nvs: &VoltServiceCfg{
+ Port: "test_port",
+ },
+ },
+ want: false,
+ },
+ {
+ name: "nvs.PonPort != evs.PonPort",
+ args: args{
+ evs: &VoltServiceCfg{},
+ nvs: &VoltServiceCfg{
+ PonPort: uint32(1),
+ },
+ },
+ want: false,
+ },
+ {
+ name: "evs.MacLearning == MacLearningNone",
+ args: args{
+ evs: &VoltServiceCfg{
+ MacAddr: layers.EthernetBroadcast,
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.IgmpEnabled != evs.IgmpEnabled",
+ args: args{
+ evs: &VoltServiceCfg{
+ IgmpEnabled: true,
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.McastService != evs.McastService",
+ args: args{
+ evs: &VoltServiceCfg{
+ McastService: true,
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.ONTEtherTypeClassification != evs.ONTEtherTypeClassification",
+ args: args{
+ evs: &VoltServiceCfg{
+ ONTEtherTypeClassification: 1,
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.UsMeterProfile != evs.UsMeterProfile",
+ args: args{
+ evs: &VoltServiceCfg{
+ UsMeterProfile: "UsMeterProfile",
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.DsMeterProfile != evs.DsMeterProfile",
+ args: args{
+ evs: &VoltServiceCfg{
+ DsMeterProfile: "DsMeterProfile",
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.AggDsMeterProfile != evs.AggDsMeterProfile",
+ args: args{
+ evs: &VoltServiceCfg{
+ AggDsMeterProfile: "AggDsMeterProfile",
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.VnetID != evs.VnetID",
+ args: args{
+ evs: &VoltServiceCfg{
+ VnetID: "VnetID",
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.MvlanProfileName != evs.MvlanProfileName",
+ args: args{
+ evs: &VoltServiceCfg{
+ MvlanProfileName: "MvlanProfileName",
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.RemoteIDType != evs.RemoteIDType",
+ args: args{
+ evs: &VoltServiceCfg{
+ RemoteIDType: "RemoteIDType",
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.SchedID != evs.SchedID",
+ args: args{
+ evs: &VoltServiceCfg{
+ SchedID: 1,
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.AllowTransparent != evs.AllowTransparent",
+ args: args{
+ evs: &VoltServiceCfg{
+ AllowTransparent: true,
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.EnableMulticastKPI != evs.EnableMulticastKPI",
+ args: args{
+ evs: &VoltServiceCfg{
+ EnableMulticastKPI: true,
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.DataRateAttr != evs.DataRateAttr",
+ args: args{
+ evs: &VoltServiceCfg{
+ DataRateAttr: "DataRateAttr",
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.MinDataRateUs != evs.MinDataRateUs",
+ args: args{
+ evs: &VoltServiceCfg{
+ MinDataRateUs: uint32(1),
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.MinDataRateDs != evs.MinDataRateDs",
+ args: args{
+ evs: &VoltServiceCfg{
+ MinDataRateDs: uint32(1),
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.MaxDataRateUs != evs.MaxDataRateUs",
+ args: args{
+ evs: &VoltServiceCfg{
+ MaxDataRateUs: uint32(1),
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ {
+ name: "nvs.MaxDataRateDs != evs.MaxDataRateDs",
+ args: args{
+ evs: &VoltServiceCfg{
+ MaxDataRateDs: uint32(1),
+ },
+ nvs: &VoltServiceCfg{},
+ },
+ want: false,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ va := &VoltApplication{
+ vendorID: "test_vendor_id",
+ }
+ switch tt.name {
+ case "VoltApplication_DeepEqualServicecfg", "nvs.Name != evs.Name", "nvs.UniVlan != evs.UniVlan",
+ "nvs.CVlan != evs.CVlan", "nvs.SVlan != evs.SVlan", "nvs.SVlanTpid != 0", "nvs.Pbits != evs.Pbits",
+ "nvs.DsRemarkPbitsMap != evs.DsRemarkPbitsMap", "nvs.TechProfileID != evs.TechProfileID",
+ "nvs.CircuitID != evs.CircuitID", "nvs.RemoteID != evs.RemoteID", "nvs.Port != evs.Port",
+ "evs.MacLearning == MacLearningNone", "nvs.PonPort != evs.PonPort", "nvs.IgmpEnabled != evs.IgmpEnabled",
+ "nvs.McastService != evs.McastService", "nvs.ONTEtherTypeClassification != evs.ONTEtherTypeClassification",
+ "nvs.UsMeterProfile != evs.UsMeterProfile",
+ "nvs.DsMeterProfile != evs.DsMeterProfile", "nvs.AggDsMeterProfile != evs.AggDsMeterProfile",
+ "nvs.VnetID != evs.VnetID", "nvs.MvlanProfileName != evs.MvlanProfileName",
+ "nvs.RemoteIDType != evs.RemoteIDType", "nvs.SchedID != evs.SchedID",
+ "nvs.AllowTransparent != evs.AllowTransparent",
+ "nvs.EnableMulticastKPI != evs.EnableMulticastKPI", "nvs.DataRateAttr != evs.DataRateAttr",
+ "nvs.MinDataRateUs != evs.MinDataRateUs", "nvs.MinDataRateDs != evs.MinDataRateDs",
+ "nvs.MaxDataRateUs != evs.MaxDataRateUs", "nvs.MaxDataRateDs != evs.MaxDataRateDs":
+ if got := va.DeepEqualServicecfg(tt.args.evs, tt.args.nvs); got != tt.want {
+ t.Errorf("VoltApplication.DeepEqualServicecfg() = %v, want %v", got, tt.want)
+ }
+ }
+ })
+ }
+}
diff --git a/internal/pkg/controller/addflows_test.go b/internal/pkg/controller/addflows_test.go
new file mode 100644
index 0000000..d1e86ec
--- /dev/null
+++ b/internal/pkg/controller/addflows_test.go
@@ -0,0 +1,49 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* 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 controller
+
+import (
+ "testing"
+ "voltha-go-controller/internal/pkg/of"
+)
+
+func Test_isFlowOperSuccess(t *testing.T) {
+ type args struct {
+ statusCode uint32
+ oper of.Command
+ }
+ tests := []struct {
+ name string
+ args args
+ want bool
+ }{
+ {
+ name: "test",
+ args: args{
+ statusCode: uint32(1004),
+ oper: of.CommandAdd,
+ },
+ want: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := isFlowOperSuccess(tt.args.statusCode, tt.args.oper); got != tt.want {
+ t.Errorf("isFlowOperSuccess() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/internal/pkg/of/flows_test.go b/internal/pkg/of/flows_test.go
new file mode 100644
index 0000000..28a6d46
--- /dev/null
+++ b/internal/pkg/of/flows_test.go
@@ -0,0 +1,86 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* 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 of
+
+import (
+ "net"
+ "testing"
+)
+
+func TestMatch_SetTableMetadata(t *testing.T) {
+ type fields struct {
+ SrcMacAddr net.HardwareAddr
+ SrcMacMask net.HardwareAddr
+ DstMacAddr net.HardwareAddr
+ DstMacMask net.HardwareAddr
+ SrcIpv4Addr net.IP
+ DstIpv4Addr net.IP
+ TableMetadata uint64
+ InPort uint32
+ MatchVlan VlanType
+ Pbits PbitType
+ L3Protocol EtherType
+ SrcPort uint16
+ DstPort uint16
+ L4Protocol IPProtocol
+ DstIpv4Match bool
+ SrcIpv4Match bool
+ SrcMacMatch bool
+ DstMacMatch bool
+ MatchPbits bool
+ }
+ type args struct {
+ metadata uint64
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ }{
+ {
+ name: "test",
+ args: args{
+ metadata: uint64(537416),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ m := &Match{
+ SrcMacAddr: tt.fields.SrcMacAddr,
+ SrcMacMask: tt.fields.SrcMacMask,
+ DstMacAddr: tt.fields.DstMacAddr,
+ DstMacMask: tt.fields.DstMacMask,
+ SrcIpv4Addr: tt.fields.SrcIpv4Addr,
+ DstIpv4Addr: tt.fields.DstIpv4Addr,
+ TableMetadata: tt.fields.TableMetadata,
+ InPort: tt.fields.InPort,
+ MatchVlan: tt.fields.MatchVlan,
+ Pbits: tt.fields.Pbits,
+ L3Protocol: tt.fields.L3Protocol,
+ SrcPort: tt.fields.SrcPort,
+ DstPort: tt.fields.DstPort,
+ L4Protocol: tt.fields.L4Protocol,
+ DstIpv4Match: tt.fields.DstIpv4Match,
+ SrcIpv4Match: tt.fields.SrcIpv4Match,
+ SrcMacMatch: tt.fields.SrcMacMatch,
+ DstMacMatch: tt.fields.DstMacMatch,
+ MatchPbits: tt.fields.MatchPbits,
+ }
+ m.SetTableMetadata(tt.args.metadata)
+ })
+ }
+}
diff --git a/internal/pkg/tasks/tasks_test.go b/internal/pkg/tasks/tasks_test.go
new file mode 100644
index 0000000..f451c71
--- /dev/null
+++ b/internal/pkg/tasks/tasks_test.go
@@ -0,0 +1,16 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* 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 tasks
diff --git a/internal/pkg/util/concurrentmap.go b/internal/pkg/util/concurrentmap.go
index 380e3aa..fce8f49 100644
--- a/internal/pkg/util/concurrentmap.go
+++ b/internal/pkg/util/concurrentmap.go
@@ -23,7 +23,7 @@
// ConcurrentMap implements a wrapper on top of SyncMap so that the count is also maintained
type ConcurrentMap struct {
- count *atomic.Uint64
+ Count *atomic.Uint64
syncMap sync.Map
MapLock sync.RWMutex
}
@@ -31,7 +31,7 @@
// NewConcurrentMap - Initializes new ConcurentMap Object
func NewConcurrentMap() *ConcurrentMap {
var cm ConcurrentMap
- cm.count = atomic.NewUint64(0)
+ cm.Count = atomic.NewUint64(0)
return &cm
}
@@ -43,13 +43,13 @@
// Set - Store the value in sync map against the key provided
func (cm *ConcurrentMap) Set(key, value interface{}) {
- if cm.count == nil {
- cm.count = atomic.NewUint64(0)
+ if cm.Count == nil {
+ cm.Count = atomic.NewUint64(0)
}
_, exists := cm.syncMap.Load(key)
cm.syncMap.Store(key, value)
if !exists {
- cm.count.Inc()
+ cm.Count.Inc()
}
}
@@ -57,7 +57,7 @@
func (cm *ConcurrentMap) Remove(key interface{}) bool {
if _, ok := cm.syncMap.Load(key); ok {
cm.syncMap.Delete(key)
- cm.count.Dec()
+ cm.Count.Dec()
return true
}
return false
@@ -79,8 +79,8 @@
// Length - return the no of entries present in the map
func (cm *ConcurrentMap) Length() uint64 {
- if cm.count == nil {
+ if cm.Count == nil {
return 0
}
- return cm.count.Load()
+ return cm.Count.Load()
}
diff --git a/internal/pkg/vpagent/changeEvent_test.go b/internal/pkg/vpagent/changeEvent_test.go
new file mode 100644
index 0000000..35b195e
--- /dev/null
+++ b/internal/pkg/vpagent/changeEvent_test.go
@@ -0,0 +1,16 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* 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 vpagent
diff --git a/internal/test/mocks/mock_appif.go b/internal/test/mocks/mock_appif.go
new file mode 100644
index 0000000..42bd490
--- /dev/null
+++ b/internal/test/mocks/mock_appif.go
@@ -0,0 +1,255 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* 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.
+ */
+
+// Code generated by MockGen. DO NOT EDIT.
+// Source: /home/vinod/go/src/gerrit.opencord.org/voltha-go-controller/internal/pkg/intf/appif.go
+
+// Package mock_intf is a generated GoMock package.
+package mocks
+
+import (
+ context "context"
+ reflect "reflect"
+ intf "voltha-go-controller/internal/pkg/intf"
+
+ gomock "github.com/golang/mock/gomock"
+)
+
+// MockApp is a mock of App interface.
+type MockApp struct {
+ ctrl *gomock.Controller
+ recorder *MockAppMockRecorder
+}
+
+// MockAppMockRecorder is the mock recorder for MockApp.
+type MockAppMockRecorder struct {
+ mock *MockApp
+}
+
+// NewMockApp creates a new mock instance.
+func NewMockApp(ctrl *gomock.Controller) *MockApp {
+ mock := &MockApp{ctrl: ctrl}
+ mock.recorder = &MockAppMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockApp) EXPECT() *MockAppMockRecorder {
+ return m.recorder
+}
+
+// AddDevice mocks base method.
+func (m *MockApp) AddDevice(arg0 context.Context, arg1, arg2, arg3 string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "AddDevice", arg0, arg1, arg2, arg3)
+}
+
+// AddDevice indicates an expected call of AddDevice.
+func (mr *MockAppMockRecorder) AddDevice(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDevice", reflect.TypeOf((*MockApp)(nil).AddDevice), arg0, arg1, arg2, arg3)
+}
+
+// DelDevice mocks base method.
+func (m *MockApp) DelDevice(arg0 context.Context, arg1 string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "DelDevice", arg0, arg1)
+}
+
+// DelDevice indicates an expected call of DelDevice.
+func (mr *MockAppMockRecorder) DelDevice(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelDevice", reflect.TypeOf((*MockApp)(nil).DelDevice), arg0, arg1)
+}
+
+// DeviceDisableInd mocks base method.
+func (m *MockApp) DeviceDisableInd(arg0 context.Context, arg1 string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "DeviceDisableInd", arg0, arg1)
+}
+
+// DeviceDisableInd indicates an expected call of DeviceDisableInd.
+func (mr *MockAppMockRecorder) DeviceDisableInd(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeviceDisableInd", reflect.TypeOf((*MockApp)(nil).DeviceDisableInd), arg0, arg1)
+}
+
+// DeviceDownInd mocks base method.
+func (m *MockApp) DeviceDownInd(arg0 string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "DeviceDownInd", arg0)
+}
+
+// DeviceDownInd indicates an expected call of DeviceDownInd.
+func (mr *MockAppMockRecorder) DeviceDownInd(arg0 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeviceDownInd", reflect.TypeOf((*MockApp)(nil).DeviceDownInd), arg0)
+}
+
+// DeviceRebootInd mocks base method.
+func (m *MockApp) DeviceRebootInd(arg0 context.Context, arg1, arg2, arg3 string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "DeviceRebootInd", arg0, arg1, arg2, arg3)
+}
+
+// DeviceRebootInd indicates an expected call of DeviceRebootInd.
+func (mr *MockAppMockRecorder) DeviceRebootInd(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeviceRebootInd", reflect.TypeOf((*MockApp)(nil).DeviceRebootInd), arg0, arg1, arg2, arg3)
+}
+
+// DeviceUpInd mocks base method.
+func (m *MockApp) DeviceUpInd(arg0 string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "DeviceUpInd", arg0)
+}
+
+// DeviceUpInd indicates an expected call of DeviceUpInd.
+func (mr *MockAppMockRecorder) DeviceUpInd(arg0 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeviceUpInd", reflect.TypeOf((*MockApp)(nil).DeviceUpInd), arg0)
+}
+
+// PacketInInd mocks base method.
+func (m *MockApp) PacketInInd(arg0 context.Context, arg1, arg2 string, arg3 []byte) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "PacketInInd", arg0, arg1, arg2, arg3)
+}
+
+// PacketInInd indicates an expected call of PacketInInd.
+func (mr *MockAppMockRecorder) PacketInInd(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PacketInInd", reflect.TypeOf((*MockApp)(nil).PacketInInd), arg0, arg1, arg2, arg3)
+}
+
+// PortAddInd mocks base method.
+func (m *MockApp) PortAddInd(arg0 context.Context, arg1 string, arg2 uint32, arg3 string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "PortAddInd", arg0, arg1, arg2, arg3)
+}
+
+// PortAddInd indicates an expected call of PortAddInd.
+func (mr *MockAppMockRecorder) PortAddInd(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PortAddInd", reflect.TypeOf((*MockApp)(nil).PortAddInd), arg0, arg1, arg2, arg3)
+}
+
+// PortDelInd mocks base method.
+func (m *MockApp) PortDelInd(arg0 context.Context, arg1, arg2 string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "PortDelInd", arg0, arg1, arg2)
+}
+
+// PortDelInd indicates an expected call of PortDelInd.
+func (mr *MockAppMockRecorder) PortDelInd(arg0, arg1, arg2 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PortDelInd", reflect.TypeOf((*MockApp)(nil).PortDelInd), arg0, arg1, arg2)
+}
+
+// PortDownInd mocks base method.
+func (m *MockApp) PortDownInd(arg0 context.Context, arg1, arg2 string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "PortDownInd", arg0, arg1, arg2)
+}
+
+// PortDownInd indicates an expected call of PortDownInd.
+func (mr *MockAppMockRecorder) PortDownInd(arg0, arg1, arg2 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PortDownInd", reflect.TypeOf((*MockApp)(nil).PortDownInd), arg0, arg1, arg2)
+}
+
+// PortUpInd mocks base method.
+func (m *MockApp) PortUpInd(arg0 context.Context, arg1, arg2 string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "PortUpInd", arg0, arg1, arg2)
+}
+
+// PortUpInd indicates an expected call of PortUpInd.
+func (mr *MockAppMockRecorder) PortUpInd(arg0, arg1, arg2 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PortUpInd", reflect.TypeOf((*MockApp)(nil).PortUpInd), arg0, arg1, arg2)
+}
+
+// PortUpdateInd mocks base method.
+func (m *MockApp) PortUpdateInd(arg0, arg1 string, arg2 uint32) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "PortUpdateInd", arg0, arg1, arg2)
+}
+
+// PortUpdateInd indicates an expected call of PortUpdateInd.
+func (mr *MockAppMockRecorder) PortUpdateInd(arg0, arg1, arg2 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PortUpdateInd", reflect.TypeOf((*MockApp)(nil).PortUpdateInd), arg0, arg1, arg2)
+}
+
+// ProcessFlowModResultIndication mocks base method.
+func (m *MockApp) ProcessFlowModResultIndication(arg0 context.Context, arg1 intf.FlowStatus) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "ProcessFlowModResultIndication", arg0, arg1)
+}
+
+// ProcessFlowModResultIndication indicates an expected call of ProcessFlowModResultIndication.
+func (mr *MockAppMockRecorder) ProcessFlowModResultIndication(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessFlowModResultIndication", reflect.TypeOf((*MockApp)(nil).ProcessFlowModResultIndication), arg0, arg1)
+}
+
+// SetRebootFlag mocks base method.
+func (m *MockApp) SetRebootFlag(arg0 bool) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "SetRebootFlag", arg0)
+}
+
+// SetRebootFlag indicates an expected call of SetRebootFlag.
+func (mr *MockAppMockRecorder) SetRebootFlag(arg0 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetRebootFlag", reflect.TypeOf((*MockApp)(nil).SetRebootFlag), arg0)
+}
+
+// TriggerPendingMigrateServicesReq mocks base method.
+func (m *MockApp) TriggerPendingMigrateServicesReq(arg0 context.Context, arg1 string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "TriggerPendingMigrateServicesReq", arg0, arg1)
+}
+
+// TriggerPendingMigrateServicesReq indicates an expected call of TriggerPendingMigrateServicesReq.
+func (mr *MockAppMockRecorder) TriggerPendingMigrateServicesReq(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TriggerPendingMigrateServicesReq", reflect.TypeOf((*MockApp)(nil).TriggerPendingMigrateServicesReq), arg0, arg1)
+}
+
+// TriggerPendingProfileDeleteReq mocks base method.
+func (m *MockApp) TriggerPendingProfileDeleteReq(arg0 context.Context, arg1 string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "TriggerPendingProfileDeleteReq", arg0, arg1)
+}
+
+// TriggerPendingProfileDeleteReq indicates an expected call of TriggerPendingProfileDeleteReq.
+func (mr *MockAppMockRecorder) TriggerPendingProfileDeleteReq(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TriggerPendingProfileDeleteReq", reflect.TypeOf((*MockApp)(nil).TriggerPendingProfileDeleteReq), arg0, arg1)
+}
+
+// UpdateMvlanProfilesForDevice mocks base method.
+func (m *MockApp) UpdateMvlanProfilesForDevice(arg0 context.Context, arg1 string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "UpdateMvlanProfilesForDevice", arg0, arg1)
+}
+
+// UpdateMvlanProfilesForDevice indicates an expected call of UpdateMvlanProfilesForDevice.
+func (mr *MockAppMockRecorder) UpdateMvlanProfilesForDevice(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateMvlanProfilesForDevice", reflect.TypeOf((*MockApp)(nil).UpdateMvlanProfilesForDevice), arg0, arg1)
+}
diff --git a/internal/test/mocks/mock_dbintf.go b/internal/test/mocks/mock_dbintf.go
new file mode 100644
index 0000000..75a22ff
--- /dev/null
+++ b/internal/test/mocks/mock_dbintf.go
@@ -0,0 +1,1914 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* 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.
+ */
+
+// Code generated by MockGen. DO NOT EDIT.
+// Source: /home/vinod/go/src/gerrit.opencord.org/voltha-go-controller/database/dbintf.go
+
+// Package mock_database is a generated GoMock package.
+package mocks
+
+import (
+ context "context"
+ net "net"
+ reflect "reflect"
+ of "voltha-go-controller/internal/pkg/of"
+
+ gomock "github.com/golang/mock/gomock"
+ kvstore "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
+)
+
+// MockDBIntf is a mock of DBIntf interface.
+type MockDBIntf struct {
+ ctrl *gomock.Controller
+ recorder *MockDBIntfMockRecorder
+}
+
+// MockDBIntfMockRecorder is the mock recorder for MockDBIntf.
+type MockDBIntfMockRecorder struct {
+ mock *MockDBIntf
+}
+
+// NewMockDBIntf creates a new mock instance.
+func NewMockDBIntf(ctrl *gomock.Controller) *MockDBIntf {
+ mock := &MockDBIntf{ctrl: ctrl}
+ mock.recorder = &MockDBIntfMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockDBIntf) EXPECT() *MockDBIntfMockRecorder {
+ return m.recorder
+}
+
+// Del mocks base method.
+func (m *MockDBIntf) Del(ctx context.Context, path string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Del", ctx, path)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// Del indicates an expected call of Del.
+func (mr *MockDBIntfMockRecorder) Del(ctx, path interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Del", reflect.TypeOf((*MockDBIntf)(nil).Del), ctx, path)
+}
+
+// DelAllGroup mocks base method.
+func (m *MockDBIntf) DelAllGroup(ctx context.Context, deviceID string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelAllGroup", ctx, deviceID)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelAllGroup indicates an expected call of DelAllGroup.
+func (mr *MockDBIntfMockRecorder) DelAllGroup(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelAllGroup", reflect.TypeOf((*MockDBIntf)(nil).DelAllGroup), ctx, deviceID)
+}
+
+// DelAllIgmpRcvr mocks base method.
+func (m *MockDBIntf) DelAllIgmpRcvr(ctx context.Context, mvlan of.VlanType, gip net.IP, device string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelAllIgmpRcvr", ctx, mvlan, gip, device)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelAllIgmpRcvr indicates an expected call of DelAllIgmpRcvr.
+func (mr *MockDBIntfMockRecorder) DelAllIgmpRcvr(ctx, mvlan, gip, device interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelAllIgmpRcvr", reflect.TypeOf((*MockDBIntf)(nil).DelAllIgmpRcvr), ctx, mvlan, gip, device)
+}
+
+// DelAllMeter mocks base method.
+func (m *MockDBIntf) DelAllMeter(ctx context.Context, device string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelAllMeter", ctx, device)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelAllMeter indicates an expected call of DelAllMeter.
+func (mr *MockDBIntfMockRecorder) DelAllMeter(ctx, device interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelAllMeter", reflect.TypeOf((*MockDBIntf)(nil).DelAllMeter), ctx, device)
+}
+
+// DelAllMigrateServicesReq mocks base method.
+func (m *MockDBIntf) DelAllMigrateServicesReq(ctx context.Context, deviceID string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelAllMigrateServicesReq", ctx, deviceID)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelAllMigrateServicesReq indicates an expected call of DelAllMigrateServicesReq.
+func (mr *MockDBIntfMockRecorder) DelAllMigrateServicesReq(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelAllMigrateServicesReq", reflect.TypeOf((*MockDBIntf)(nil).DelAllMigrateServicesReq), ctx, deviceID)
+}
+
+// DelAllPONCounters mocks base method.
+func (m *MockDBIntf) DelAllPONCounters(ctx context.Context, device string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelAllPONCounters", ctx, device)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelAllPONCounters indicates an expected call of DelAllPONCounters.
+func (mr *MockDBIntfMockRecorder) DelAllPONCounters(ctx, device interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelAllPONCounters", reflect.TypeOf((*MockDBIntf)(nil).DelAllPONCounters), ctx, device)
+}
+
+// DelAllPorts mocks base method.
+func (m *MockDBIntf) DelAllPorts(ctx context.Context, deviceID string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelAllPorts", ctx, deviceID)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelAllPorts indicates an expected call of DelAllPorts.
+func (mr *MockDBIntfMockRecorder) DelAllPorts(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelAllPorts", reflect.TypeOf((*MockDBIntf)(nil).DelAllPorts), ctx, deviceID)
+}
+
+// DelAllRoutesForDevice mocks base method.
+func (m *MockDBIntf) DelAllRoutesForDevice(ctx context.Context, device string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelAllRoutesForDevice", ctx, device)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelAllRoutesForDevice indicates an expected call of DelAllRoutesForDevice.
+func (mr *MockDBIntfMockRecorder) DelAllRoutesForDevice(ctx, device interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelAllRoutesForDevice", reflect.TypeOf((*MockDBIntf)(nil).DelAllRoutesForDevice), ctx, device)
+}
+
+// DelAllServiceChannelCounter mocks base method.
+func (m *MockDBIntf) DelAllServiceChannelCounter(ctx context.Context, serviceName string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelAllServiceChannelCounter", ctx, serviceName)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelAllServiceChannelCounter indicates an expected call of DelAllServiceChannelCounter.
+func (mr *MockDBIntfMockRecorder) DelAllServiceChannelCounter(ctx, serviceName interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelAllServiceChannelCounter", reflect.TypeOf((*MockDBIntf)(nil).DelAllServiceChannelCounter), ctx, serviceName)
+}
+
+// DelDeviceMeter mocks base method.
+func (m *MockDBIntf) DelDeviceMeter(ctx context.Context, deviceID string, meterID uint32) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelDeviceMeter", ctx, deviceID, meterID)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelDeviceMeter indicates an expected call of DelDeviceMeter.
+func (mr *MockDBIntfMockRecorder) DelDeviceMeter(ctx, deviceID, meterID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelDeviceMeter", reflect.TypeOf((*MockDBIntf)(nil).DelDeviceMeter), ctx, deviceID, meterID)
+}
+
+// DelFlow mocks base method.
+func (m *MockDBIntf) DelFlow(ctx context.Context, deviceID string, flowID uint64) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelFlow", ctx, deviceID, flowID)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelFlow indicates an expected call of DelFlow.
+func (mr *MockDBIntfMockRecorder) DelFlow(ctx, deviceID, flowID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelFlow", reflect.TypeOf((*MockDBIntf)(nil).DelFlow), ctx, deviceID, flowID)
+}
+
+// DelGroup mocks base method.
+func (m *MockDBIntf) DelGroup(ctx context.Context, deviceID string, groupID uint32) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelGroup", ctx, deviceID, groupID)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelGroup indicates an expected call of DelGroup.
+func (mr *MockDBIntfMockRecorder) DelGroup(ctx, deviceID, groupID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelGroup", reflect.TypeOf((*MockDBIntf)(nil).DelGroup), ctx, deviceID, groupID)
+}
+
+// DelHealth mocks base method.
+func (m *MockDBIntf) DelHealth(ctx context.Context) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelHealth", ctx)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelHealth indicates an expected call of DelHealth.
+func (mr *MockDBIntfMockRecorder) DelHealth(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelHealth", reflect.TypeOf((*MockDBIntf)(nil).DelHealth), ctx)
+}
+
+// DelIGMPCfg mocks base method.
+func (m *MockDBIntf) DelIGMPCfg(ctx context.Context) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelIGMPCfg", ctx)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelIGMPCfg indicates an expected call of DelIGMPCfg.
+func (mr *MockDBIntfMockRecorder) DelIGMPCfg(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelIGMPCfg", reflect.TypeOf((*MockDBIntf)(nil).DelIGMPCfg), ctx)
+}
+
+// DelIgmpChannel mocks base method.
+func (m *MockDBIntf) DelIgmpChannel(ctx context.Context, mvlan of.VlanType, gName, device string, gip net.IP) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelIgmpChannel", ctx, mvlan, gName, device, gip)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelIgmpChannel indicates an expected call of DelIgmpChannel.
+func (mr *MockDBIntfMockRecorder) DelIgmpChannel(ctx, mvlan, gName, device, gip interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelIgmpChannel", reflect.TypeOf((*MockDBIntf)(nil).DelIgmpChannel), ctx, mvlan, gName, device, gip)
+}
+
+// DelIgmpDevice mocks base method.
+func (m *MockDBIntf) DelIgmpDevice(ctx context.Context, mvlan of.VlanType, gid string, gip net.IP, device string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelIgmpDevice", ctx, mvlan, gid, gip, device)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelIgmpDevice indicates an expected call of DelIgmpDevice.
+func (mr *MockDBIntfMockRecorder) DelIgmpDevice(ctx, mvlan, gid, gip, device interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelIgmpDevice", reflect.TypeOf((*MockDBIntf)(nil).DelIgmpDevice), ctx, mvlan, gid, gip, device)
+}
+
+// DelIgmpGroup mocks base method.
+func (m *MockDBIntf) DelIgmpGroup(ctx context.Context, id string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelIgmpGroup", ctx, id)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelIgmpGroup indicates an expected call of DelIgmpGroup.
+func (mr *MockDBIntfMockRecorder) DelIgmpGroup(ctx, id interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelIgmpGroup", reflect.TypeOf((*MockDBIntf)(nil).DelIgmpGroup), ctx, id)
+}
+
+// DelIgmpProfile mocks base method.
+func (m *MockDBIntf) DelIgmpProfile(ctx context.Context, name string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelIgmpProfile", ctx, name)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelIgmpProfile indicates an expected call of DelIgmpProfile.
+func (mr *MockDBIntfMockRecorder) DelIgmpProfile(ctx, name interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelIgmpProfile", reflect.TypeOf((*MockDBIntf)(nil).DelIgmpProfile), ctx, name)
+}
+
+// DelIgmpRcvr mocks base method.
+func (m *MockDBIntf) DelIgmpRcvr(ctx context.Context, mvlan of.VlanType, gip net.IP, device, rcvr string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelIgmpRcvr", ctx, mvlan, gip, device, rcvr)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelIgmpRcvr indicates an expected call of DelIgmpRcvr.
+func (mr *MockDBIntfMockRecorder) DelIgmpRcvr(ctx, mvlan, gip, device, rcvr interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelIgmpRcvr", reflect.TypeOf((*MockDBIntf)(nil).DelIgmpRcvr), ctx, mvlan, gip, device, rcvr)
+}
+
+// DelMcastConfig mocks base method.
+func (m *MockDBIntf) DelMcastConfig(ctx context.Context, name string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelMcastConfig", ctx, name)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelMcastConfig indicates an expected call of DelMcastConfig.
+func (mr *MockDBIntfMockRecorder) DelMcastConfig(ctx, name interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelMcastConfig", reflect.TypeOf((*MockDBIntf)(nil).DelMcastConfig), ctx, name)
+}
+
+// DelMeter mocks base method.
+func (m *MockDBIntf) DelMeter(ctx context.Context, name string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelMeter", ctx, name)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelMeter indicates an expected call of DelMeter.
+func (mr *MockDBIntfMockRecorder) DelMeter(ctx, name interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelMeter", reflect.TypeOf((*MockDBIntf)(nil).DelMeter), ctx, name)
+}
+
+// DelMigrateServicesReq mocks base method.
+func (m *MockDBIntf) DelMigrateServicesReq(ctx context.Context, deviceID, vlan string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelMigrateServicesReq", ctx, deviceID, vlan)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelMigrateServicesReq indicates an expected call of DelMigrateServicesReq.
+func (mr *MockDBIntfMockRecorder) DelMigrateServicesReq(ctx, deviceID, vlan interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelMigrateServicesReq", reflect.TypeOf((*MockDBIntf)(nil).DelMigrateServicesReq), ctx, deviceID, vlan)
+}
+
+// DelMigrationInfo mocks base method.
+func (m *MockDBIntf) DelMigrationInfo(ctx context.Context) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelMigrationInfo", ctx)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelMigrationInfo indicates an expected call of DelMigrationInfo.
+func (mr *MockDBIntfMockRecorder) DelMigrationInfo(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelMigrationInfo", reflect.TypeOf((*MockDBIntf)(nil).DelMigrationInfo), ctx)
+}
+
+// DelMvlan mocks base method.
+func (m *MockDBIntf) DelMvlan(ctx context.Context, mvlan uint16) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelMvlan", ctx, mvlan)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelMvlan indicates an expected call of DelMvlan.
+func (mr *MockDBIntfMockRecorder) DelMvlan(ctx, mvlan interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelMvlan", reflect.TypeOf((*MockDBIntf)(nil).DelMvlan), ctx, mvlan)
+}
+
+// DelNbDevicePort mocks base method.
+func (m *MockDBIntf) DelNbDevicePort(ctx context.Context, device string, ponPortID uint32) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "DelNbDevicePort", ctx, device, ponPortID)
+}
+
+// DelNbDevicePort indicates an expected call of DelNbDevicePort.
+func (mr *MockDBIntfMockRecorder) DelNbDevicePort(ctx, device, ponPortID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelNbDevicePort", reflect.TypeOf((*MockDBIntf)(nil).DelNbDevicePort), ctx, device, ponPortID)
+}
+
+// DelOlt mocks base method.
+func (m *MockDBIntf) DelOlt(ctx context.Context, deviceID string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelOlt", ctx, deviceID)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelOlt indicates an expected call of DelOlt.
+func (mr *MockDBIntfMockRecorder) DelOlt(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelOlt", reflect.TypeOf((*MockDBIntf)(nil).DelOlt), ctx, deviceID)
+}
+
+// DelPONCounters mocks base method.
+func (m *MockDBIntf) DelPONCounters(ctx context.Context, device, ponID string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "DelPONCounters", ctx, device, ponID)
+}
+
+// DelPONCounters indicates an expected call of DelPONCounters.
+func (mr *MockDBIntfMockRecorder) DelPONCounters(ctx, device, ponID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelPONCounters", reflect.TypeOf((*MockDBIntf)(nil).DelPONCounters), ctx, device, ponID)
+}
+
+// DelPonChannelCounter mocks base method.
+func (m *MockDBIntf) DelPonChannelCounter(ctx context.Context, device, ponID, channel string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelPonChannelCounter", ctx, device, ponID, channel)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelPonChannelCounter indicates an expected call of DelPonChannelCounter.
+func (mr *MockDBIntfMockRecorder) DelPonChannelCounter(ctx, device, ponID, channel interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelPonChannelCounter", reflect.TypeOf((*MockDBIntf)(nil).DelPonChannelCounter), ctx, device, ponID, channel)
+}
+
+// DelPonCounter mocks base method.
+func (m *MockDBIntf) DelPonCounter(ctx context.Context, device, ponID string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelPonCounter", ctx, device, ponID)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelPonCounter indicates an expected call of DelPonCounter.
+func (mr *MockDBIntfMockRecorder) DelPonCounter(ctx, device, ponID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelPonCounter", reflect.TypeOf((*MockDBIntf)(nil).DelPonCounter), ctx, device, ponID)
+}
+
+// DelPort mocks base method.
+func (m *MockDBIntf) DelPort(ctx context.Context, deviceID string, portID uint32) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelPort", ctx, deviceID, portID)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelPort indicates an expected call of DelPort.
+func (mr *MockDBIntfMockRecorder) DelPort(ctx, deviceID, portID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelPort", reflect.TypeOf((*MockDBIntf)(nil).DelPort), ctx, deviceID, portID)
+}
+
+// DelPortAlarmData mocks base method.
+func (m *MockDBIntf) DelPortAlarmData(ctx context.Context, deviceID string, portID uint32) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "DelPortAlarmData", ctx, deviceID, portID)
+}
+
+// DelPortAlarmData indicates an expected call of DelPortAlarmData.
+func (mr *MockDBIntfMockRecorder) DelPortAlarmData(ctx, deviceID, portID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelPortAlarmData", reflect.TypeOf((*MockDBIntf)(nil).DelPortAlarmData), ctx, deviceID, portID)
+}
+
+// DelPortAlarmProfile mocks base method.
+func (m *MockDBIntf) DelPortAlarmProfile(ctx context.Context, portAlarmProfileID string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "DelPortAlarmProfile", ctx, portAlarmProfileID)
+}
+
+// DelPortAlarmProfile indicates an expected call of DelPortAlarmProfile.
+func (mr *MockDBIntfMockRecorder) DelPortAlarmProfile(ctx, portAlarmProfileID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelPortAlarmProfile", reflect.TypeOf((*MockDBIntf)(nil).DelPortAlarmProfile), ctx, portAlarmProfileID)
+}
+
+// DelService mocks base method.
+func (m *MockDBIntf) DelService(ctx context.Context, name string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelService", ctx, name)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelService indicates an expected call of DelService.
+func (mr *MockDBIntfMockRecorder) DelService(ctx, name interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelService", reflect.TypeOf((*MockDBIntf)(nil).DelService), ctx, name)
+}
+
+// DelServiceChannelCounter mocks base method.
+func (m *MockDBIntf) DelServiceChannelCounter(ctx context.Context, serviceName, channel string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelServiceChannelCounter", ctx, serviceName, channel)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelServiceChannelCounter indicates an expected call of DelServiceChannelCounter.
+func (mr *MockDBIntfMockRecorder) DelServiceChannelCounter(ctx, serviceName, channel interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelServiceChannelCounter", reflect.TypeOf((*MockDBIntf)(nil).DelServiceChannelCounter), ctx, serviceName, channel)
+}
+
+// DelSubAlarmData mocks base method.
+func (m *MockDBIntf) DelSubAlarmData(ctx context.Context, deviceID, portName string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "DelSubAlarmData", ctx, deviceID, portName)
+}
+
+// DelSubAlarmData indicates an expected call of DelSubAlarmData.
+func (mr *MockDBIntfMockRecorder) DelSubAlarmData(ctx, deviceID, portName interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelSubAlarmData", reflect.TypeOf((*MockDBIntf)(nil).DelSubAlarmData), ctx, deviceID, portName)
+}
+
+// DelVnet mocks base method.
+func (m *MockDBIntf) DelVnet(ctx context.Context, name string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelVnet", ctx, name)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelVnet indicates an expected call of DelVnet.
+func (mr *MockDBIntfMockRecorder) DelVnet(ctx, name interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelVnet", reflect.TypeOf((*MockDBIntf)(nil).DelVnet), ctx, name)
+}
+
+// DelVpv mocks base method.
+func (m *MockDBIntf) DelVpv(ctx context.Context, port string, SVlan, CVlan, UniVlan uint16) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DelVpv", ctx, port, SVlan, CVlan, UniVlan)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DelVpv indicates an expected call of DelVpv.
+func (mr *MockDBIntfMockRecorder) DelVpv(ctx, port, SVlan, CVlan, UniVlan interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelVpv", reflect.TypeOf((*MockDBIntf)(nil).DelVpv), ctx, port, SVlan, CVlan, UniVlan)
+}
+
+// DeleteAll mocks base method.
+func (m *MockDBIntf) DeleteAll(ctx context.Context, path string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DeleteAll", ctx, path)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DeleteAll indicates an expected call of DeleteAll.
+func (mr *MockDBIntfMockRecorder) DeleteAll(ctx, path interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAll", reflect.TypeOf((*MockDBIntf)(nil).DeleteAll), ctx, path)
+}
+
+// DeleteAllUnderHashKey mocks base method.
+func (m *MockDBIntf) DeleteAllUnderHashKey(ctx context.Context, hashKeyPrefix string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "DeleteAllUnderHashKey", ctx, hashKeyPrefix)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DeleteAllUnderHashKey indicates an expected call of DeleteAllUnderHashKey.
+func (mr *MockDBIntfMockRecorder) DeleteAllUnderHashKey(ctx, hashKeyPrefix interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAllUnderHashKey", reflect.TypeOf((*MockDBIntf)(nil).DeleteAllUnderHashKey), ctx, hashKeyPrefix)
+}
+
+// Get mocks base method.
+func (m *MockDBIntf) Get(ctx context.Context, key string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Get", ctx, key)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// Get indicates an expected call of Get.
+func (mr *MockDBIntfMockRecorder) Get(ctx, key interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockDBIntf)(nil).Get), ctx, key)
+}
+
+// GetAllIgmpChannels mocks base method.
+func (m *MockDBIntf) GetAllIgmpChannels(ctx context.Context) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetAllIgmpChannels", ctx)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetAllIgmpChannels indicates an expected call of GetAllIgmpChannels.
+func (mr *MockDBIntfMockRecorder) GetAllIgmpChannels(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllIgmpChannels", reflect.TypeOf((*MockDBIntf)(nil).GetAllIgmpChannels), ctx)
+}
+
+// GetAllIgmpDevices mocks base method.
+func (m *MockDBIntf) GetAllIgmpDevices(ctx context.Context) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetAllIgmpDevices", ctx)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetAllIgmpDevices indicates an expected call of GetAllIgmpDevices.
+func (mr *MockDBIntfMockRecorder) GetAllIgmpDevices(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllIgmpDevices", reflect.TypeOf((*MockDBIntf)(nil).GetAllIgmpDevices), ctx)
+}
+
+// GetAllIgmpRcvrs mocks base method.
+func (m *MockDBIntf) GetAllIgmpRcvrs(ctx context.Context) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetAllIgmpRcvrs", ctx)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetAllIgmpRcvrs indicates an expected call of GetAllIgmpRcvrs.
+func (mr *MockDBIntfMockRecorder) GetAllIgmpRcvrs(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllIgmpRcvrs", reflect.TypeOf((*MockDBIntf)(nil).GetAllIgmpRcvrs), ctx)
+}
+
+// GetAllMigrateServicesReq mocks base method.
+func (m *MockDBIntf) GetAllMigrateServicesReq(ctx context.Context, deviceID string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetAllMigrateServicesReq", ctx, deviceID)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetAllMigrateServicesReq indicates an expected call of GetAllMigrateServicesReq.
+func (mr *MockDBIntfMockRecorder) GetAllMigrateServicesReq(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllMigrateServicesReq", reflect.TypeOf((*MockDBIntf)(nil).GetAllMigrateServicesReq), ctx, deviceID)
+}
+
+// GetAllNbPorts mocks base method.
+func (m *MockDBIntf) GetAllNbPorts(ctx context.Context, deviceID string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetAllNbPorts", ctx, deviceID)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetAllNbPorts indicates an expected call of GetAllNbPorts.
+func (mr *MockDBIntfMockRecorder) GetAllNbPorts(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllNbPorts", reflect.TypeOf((*MockDBIntf)(nil).GetAllNbPorts), ctx, deviceID)
+}
+
+// GetAllPonChannelCounters mocks base method.
+func (m *MockDBIntf) GetAllPonChannelCounters(ctx context.Context, device, ponID string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetAllPonChannelCounters", ctx, device, ponID)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetAllPonChannelCounters indicates an expected call of GetAllPonChannelCounters.
+func (mr *MockDBIntfMockRecorder) GetAllPonChannelCounters(ctx, device, ponID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllPonChannelCounters", reflect.TypeOf((*MockDBIntf)(nil).GetAllPonChannelCounters), ctx, device, ponID)
+}
+
+// GetAllPonCounters mocks base method.
+func (m *MockDBIntf) GetAllPonCounters(ctx context.Context, device string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetAllPonCounters", ctx, device)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetAllPonCounters indicates an expected call of GetAllPonCounters.
+func (mr *MockDBIntfMockRecorder) GetAllPonCounters(ctx, device interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllPonCounters", reflect.TypeOf((*MockDBIntf)(nil).GetAllPonCounters), ctx, device)
+}
+
+// GetAllPortAlarmData mocks base method.
+func (m *MockDBIntf) GetAllPortAlarmData(ctx context.Context, deviceID string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetAllPortAlarmData", ctx, deviceID)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetAllPortAlarmData indicates an expected call of GetAllPortAlarmData.
+func (mr *MockDBIntfMockRecorder) GetAllPortAlarmData(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllPortAlarmData", reflect.TypeOf((*MockDBIntf)(nil).GetAllPortAlarmData), ctx, deviceID)
+}
+
+// GetAllServiceChannelCounters mocks base method.
+func (m *MockDBIntf) GetAllServiceChannelCounters(ctx context.Context, serviceName string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetAllServiceChannelCounters", ctx, serviceName)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetAllServiceChannelCounters indicates an expected call of GetAllServiceChannelCounters.
+func (mr *MockDBIntfMockRecorder) GetAllServiceChannelCounters(ctx, serviceName interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllServiceChannelCounters", reflect.TypeOf((*MockDBIntf)(nil).GetAllServiceChannelCounters), ctx, serviceName)
+}
+
+// GetAllSubAlarmData mocks base method.
+func (m *MockDBIntf) GetAllSubAlarmData(ctx context.Context, deviceID string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetAllSubAlarmData", ctx, deviceID)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetAllSubAlarmData indicates an expected call of GetAllSubAlarmData.
+func (mr *MockDBIntfMockRecorder) GetAllSubAlarmData(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllSubAlarmData", reflect.TypeOf((*MockDBIntf)(nil).GetAllSubAlarmData), ctx, deviceID)
+}
+
+// GetDeviceConfig mocks base method.
+func (m *MockDBIntf) GetDeviceConfig(ctx context.Context) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetDeviceConfig", ctx)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetDeviceConfig indicates an expected call of GetDeviceConfig.
+func (mr *MockDBIntfMockRecorder) GetDeviceConfig(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeviceConfig", reflect.TypeOf((*MockDBIntf)(nil).GetDeviceConfig), ctx)
+}
+
+// GetDeviceMeter mocks base method.
+func (m *MockDBIntf) GetDeviceMeter(ctx context.Context, deviceID string, meterID uint32) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetDeviceMeter", ctx, deviceID, meterID)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetDeviceMeter indicates an expected call of GetDeviceMeter.
+func (mr *MockDBIntfMockRecorder) GetDeviceMeter(ctx, deviceID, meterID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeviceMeter", reflect.TypeOf((*MockDBIntf)(nil).GetDeviceMeter), ctx, deviceID, meterID)
+}
+
+// GetDeviceMeters mocks base method.
+func (m *MockDBIntf) GetDeviceMeters(ctx context.Context, deviceID string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetDeviceMeters", ctx, deviceID)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetDeviceMeters indicates an expected call of GetDeviceMeters.
+func (mr *MockDBIntfMockRecorder) GetDeviceMeters(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeviceMeters", reflect.TypeOf((*MockDBIntf)(nil).GetDeviceMeters), ctx, deviceID)
+}
+
+// GetFlow mocks base method.
+func (m *MockDBIntf) GetFlow(ctx context.Context, deviceID string, flowID uint64) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetFlow", ctx, deviceID, flowID)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetFlow indicates an expected call of GetFlow.
+func (mr *MockDBIntfMockRecorder) GetFlow(ctx, deviceID, flowID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFlow", reflect.TypeOf((*MockDBIntf)(nil).GetFlow), ctx, deviceID, flowID)
+}
+
+// GetFlowHash mocks base method.
+func (m *MockDBIntf) GetFlowHash(ctx context.Context, deviceID string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetFlowHash", ctx, deviceID)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetFlowHash indicates an expected call of GetFlowHash.
+func (mr *MockDBIntfMockRecorder) GetFlowHash(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFlowHash", reflect.TypeOf((*MockDBIntf)(nil).GetFlowHash), ctx, deviceID)
+}
+
+// GetFlows mocks base method.
+func (m *MockDBIntf) GetFlows(ctx context.Context, deviceID string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetFlows", ctx, deviceID)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetFlows indicates an expected call of GetFlows.
+func (mr *MockDBIntfMockRecorder) GetFlows(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFlows", reflect.TypeOf((*MockDBIntf)(nil).GetFlows), ctx, deviceID)
+}
+
+// GetGroup mocks base method.
+func (m *MockDBIntf) GetGroup(ctx context.Context, deviceID string, groupID uint32) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetGroup", ctx, deviceID, groupID)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetGroup indicates an expected call of GetGroup.
+func (mr *MockDBIntfMockRecorder) GetGroup(ctx, deviceID, groupID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetGroup", reflect.TypeOf((*MockDBIntf)(nil).GetGroup), ctx, deviceID, groupID)
+}
+
+// GetGroups mocks base method.
+func (m *MockDBIntf) GetGroups(ctx context.Context, deviceID string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetGroups", ctx, deviceID)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetGroups indicates an expected call of GetGroups.
+func (mr *MockDBIntfMockRecorder) GetGroups(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetGroups", reflect.TypeOf((*MockDBIntf)(nil).GetGroups), ctx, deviceID)
+}
+
+// GetHealth mocks base method.
+func (m *MockDBIntf) GetHealth(ctx context.Context) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetHealth", ctx)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetHealth indicates an expected call of GetHealth.
+func (mr *MockDBIntfMockRecorder) GetHealth(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHealth", reflect.TypeOf((*MockDBIntf)(nil).GetHealth), ctx)
+}
+
+// GetIgmpChannel mocks base method.
+func (m *MockDBIntf) GetIgmpChannel(ctx context.Context, mvlan of.VlanType, gName, device string, gip net.IP) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetIgmpChannel", ctx, mvlan, gName, device, gip)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetIgmpChannel indicates an expected call of GetIgmpChannel.
+func (mr *MockDBIntfMockRecorder) GetIgmpChannel(ctx, mvlan, gName, device, gip interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIgmpChannel", reflect.TypeOf((*MockDBIntf)(nil).GetIgmpChannel), ctx, mvlan, gName, device, gip)
+}
+
+// GetIgmpChannels mocks base method.
+func (m *MockDBIntf) GetIgmpChannels(ctx context.Context, mvlan of.VlanType, gname, device string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetIgmpChannels", ctx, mvlan, gname, device)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetIgmpChannels indicates an expected call of GetIgmpChannels.
+func (mr *MockDBIntfMockRecorder) GetIgmpChannels(ctx, mvlan, gname, device interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIgmpChannels", reflect.TypeOf((*MockDBIntf)(nil).GetIgmpChannels), ctx, mvlan, gname, device)
+}
+
+// GetIgmpDevice mocks base method.
+func (m *MockDBIntf) GetIgmpDevice(ctx context.Context, mvlan of.VlanType, gid string, gip net.IP, device string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetIgmpDevice", ctx, mvlan, gid, gip, device)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetIgmpDevice indicates an expected call of GetIgmpDevice.
+func (mr *MockDBIntfMockRecorder) GetIgmpDevice(ctx, mvlan, gid, gip, device interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIgmpDevice", reflect.TypeOf((*MockDBIntf)(nil).GetIgmpDevice), ctx, mvlan, gid, gip, device)
+}
+
+// GetIgmpDevices mocks base method.
+func (m *MockDBIntf) GetIgmpDevices(ctx context.Context, mvlan of.VlanType, gid string, gip net.IP) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetIgmpDevices", ctx, mvlan, gid, gip)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetIgmpDevices indicates an expected call of GetIgmpDevices.
+func (mr *MockDBIntfMockRecorder) GetIgmpDevices(ctx, mvlan, gid, gip interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIgmpDevices", reflect.TypeOf((*MockDBIntf)(nil).GetIgmpDevices), ctx, mvlan, gid, gip)
+}
+
+// GetIgmpGroup mocks base method.
+func (m *MockDBIntf) GetIgmpGroup(ctx context.Context, id string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetIgmpGroup", ctx, id)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetIgmpGroup indicates an expected call of GetIgmpGroup.
+func (mr *MockDBIntfMockRecorder) GetIgmpGroup(ctx, id interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIgmpGroup", reflect.TypeOf((*MockDBIntf)(nil).GetIgmpGroup), ctx, id)
+}
+
+// GetIgmpGroups mocks base method.
+func (m *MockDBIntf) GetIgmpGroups(ctx context.Context) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetIgmpGroups", ctx)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetIgmpGroups indicates an expected call of GetIgmpGroups.
+func (mr *MockDBIntfMockRecorder) GetIgmpGroups(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIgmpGroups", reflect.TypeOf((*MockDBIntf)(nil).GetIgmpGroups), ctx)
+}
+
+// GetIgmpProfile mocks base method.
+func (m *MockDBIntf) GetIgmpProfile(ctx context.Context, name string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetIgmpProfile", ctx, name)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetIgmpProfile indicates an expected call of GetIgmpProfile.
+func (mr *MockDBIntfMockRecorder) GetIgmpProfile(ctx, name interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIgmpProfile", reflect.TypeOf((*MockDBIntf)(nil).GetIgmpProfile), ctx, name)
+}
+
+// GetIgmpProfiles mocks base method.
+func (m *MockDBIntf) GetIgmpProfiles(ctx context.Context) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetIgmpProfiles", ctx)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetIgmpProfiles indicates an expected call of GetIgmpProfiles.
+func (mr *MockDBIntfMockRecorder) GetIgmpProfiles(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIgmpProfiles", reflect.TypeOf((*MockDBIntf)(nil).GetIgmpProfiles), ctx)
+}
+
+// GetIgmpRcvr mocks base method.
+func (m *MockDBIntf) GetIgmpRcvr(ctx context.Context, mvlan of.VlanType, gip net.IP, device, rcvr string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetIgmpRcvr", ctx, mvlan, gip, device, rcvr)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetIgmpRcvr indicates an expected call of GetIgmpRcvr.
+func (mr *MockDBIntfMockRecorder) GetIgmpRcvr(ctx, mvlan, gip, device, rcvr interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIgmpRcvr", reflect.TypeOf((*MockDBIntf)(nil).GetIgmpRcvr), ctx, mvlan, gip, device, rcvr)
+}
+
+// GetIgmpRcvrs mocks base method.
+func (m *MockDBIntf) GetIgmpRcvrs(ctx context.Context, mvlan of.VlanType, gip net.IP, device string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetIgmpRcvrs", ctx, mvlan, gip, device)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetIgmpRcvrs indicates an expected call of GetIgmpRcvrs.
+func (mr *MockDBIntfMockRecorder) GetIgmpRcvrs(ctx, mvlan, gip, device interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIgmpRcvrs", reflect.TypeOf((*MockDBIntf)(nil).GetIgmpRcvrs), ctx, mvlan, gip, device)
+}
+
+// GetMcastConfig mocks base method.
+func (m *MockDBIntf) GetMcastConfig(ctx context.Context, name string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetMcastConfig", ctx, name)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetMcastConfig indicates an expected call of GetMcastConfig.
+func (mr *MockDBIntfMockRecorder) GetMcastConfig(ctx, name interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMcastConfig", reflect.TypeOf((*MockDBIntf)(nil).GetMcastConfig), ctx, name)
+}
+
+// GetMcastConfigs mocks base method.
+func (m *MockDBIntf) GetMcastConfigs(ctx context.Context) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetMcastConfigs", ctx)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetMcastConfigs indicates an expected call of GetMcastConfigs.
+func (mr *MockDBIntfMockRecorder) GetMcastConfigs(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMcastConfigs", reflect.TypeOf((*MockDBIntf)(nil).GetMcastConfigs), ctx)
+}
+
+// GetMeter mocks base method.
+func (m *MockDBIntf) GetMeter(ctx context.Context, name string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetMeter", ctx, name)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetMeter indicates an expected call of GetMeter.
+func (mr *MockDBIntfMockRecorder) GetMeter(ctx, name interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMeter", reflect.TypeOf((*MockDBIntf)(nil).GetMeter), ctx, name)
+}
+
+// GetMeters mocks base method.
+func (m *MockDBIntf) GetMeters(ctx context.Context) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetMeters", ctx)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetMeters indicates an expected call of GetMeters.
+func (mr *MockDBIntfMockRecorder) GetMeters(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMeters", reflect.TypeOf((*MockDBIntf)(nil).GetMeters), ctx)
+}
+
+// GetMigrateServicesReq mocks base method.
+func (m *MockDBIntf) GetMigrateServicesReq(ctx context.Context, deviceID, vlan string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetMigrateServicesReq", ctx, deviceID, vlan)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetMigrateServicesReq indicates an expected call of GetMigrateServicesReq.
+func (mr *MockDBIntfMockRecorder) GetMigrateServicesReq(ctx, deviceID, vlan interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMigrateServicesReq", reflect.TypeOf((*MockDBIntf)(nil).GetMigrateServicesReq), ctx, deviceID, vlan)
+}
+
+// GetMigrationInfo mocks base method.
+func (m *MockDBIntf) GetMigrationInfo(ctx context.Context) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetMigrationInfo", ctx)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetMigrationInfo indicates an expected call of GetMigrationInfo.
+func (mr *MockDBIntfMockRecorder) GetMigrationInfo(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMigrationInfo", reflect.TypeOf((*MockDBIntf)(nil).GetMigrationInfo), ctx)
+}
+
+// GetMvlan mocks base method.
+func (m *MockDBIntf) GetMvlan(ctx context.Context, mvlan uint16) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetMvlan", ctx, mvlan)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetMvlan indicates an expected call of GetMvlan.
+func (mr *MockDBIntfMockRecorder) GetMvlan(ctx, mvlan interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMvlan", reflect.TypeOf((*MockDBIntf)(nil).GetMvlan), ctx, mvlan)
+}
+
+// GetMvlans mocks base method.
+func (m *MockDBIntf) GetMvlans(ctx context.Context) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetMvlans", ctx)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetMvlans indicates an expected call of GetMvlans.
+func (mr *MockDBIntfMockRecorder) GetMvlans(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMvlans", reflect.TypeOf((*MockDBIntf)(nil).GetMvlans), ctx)
+}
+
+// GetOlt mocks base method.
+func (m *MockDBIntf) GetOlt(ctx context.Context, deviceID string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetOlt", ctx, deviceID)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetOlt indicates an expected call of GetOlt.
+func (mr *MockDBIntfMockRecorder) GetOlt(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOlt", reflect.TypeOf((*MockDBIntf)(nil).GetOlt), ctx, deviceID)
+}
+
+// GetOltFlowService mocks base method.
+func (m *MockDBIntf) GetOltFlowService(ctx context.Context) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetOltFlowService", ctx)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetOltFlowService indicates an expected call of GetOltFlowService.
+func (mr *MockDBIntfMockRecorder) GetOltFlowService(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOltFlowService", reflect.TypeOf((*MockDBIntf)(nil).GetOltFlowService), ctx)
+}
+
+// GetOltIgmpCounter mocks base method.
+func (m *MockDBIntf) GetOltIgmpCounter(ctx context.Context, device string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetOltIgmpCounter", ctx, device)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetOltIgmpCounter indicates an expected call of GetOltIgmpCounter.
+func (mr *MockDBIntfMockRecorder) GetOltIgmpCounter(ctx, device interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOltIgmpCounter", reflect.TypeOf((*MockDBIntf)(nil).GetOltIgmpCounter), ctx, device)
+}
+
+// GetPonChannelCounter mocks base method.
+func (m *MockDBIntf) GetPonChannelCounter(ctx context.Context, device, ponID, channel string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetPonChannelCounter", ctx, device, ponID, channel)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetPonChannelCounter indicates an expected call of GetPonChannelCounter.
+func (mr *MockDBIntfMockRecorder) GetPonChannelCounter(ctx, device, ponID, channel interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPonChannelCounter", reflect.TypeOf((*MockDBIntf)(nil).GetPonChannelCounter), ctx, device, ponID, channel)
+}
+
+// GetPonCounter mocks base method.
+func (m *MockDBIntf) GetPonCounter(ctx context.Context, device, ponID string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetPonCounter", ctx, device, ponID)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetPonCounter indicates an expected call of GetPonCounter.
+func (mr *MockDBIntfMockRecorder) GetPonCounter(ctx, device, ponID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPonCounter", reflect.TypeOf((*MockDBIntf)(nil).GetPonCounter), ctx, device, ponID)
+}
+
+// GetPort mocks base method.
+func (m *MockDBIntf) GetPort(ctx context.Context, deviceID string, portID uint32) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetPort", ctx, deviceID, portID)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetPort indicates an expected call of GetPort.
+func (mr *MockDBIntfMockRecorder) GetPort(ctx, deviceID, portID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPort", reflect.TypeOf((*MockDBIntf)(nil).GetPort), ctx, deviceID, portID)
+}
+
+// GetPortAlarmData mocks base method.
+func (m *MockDBIntf) GetPortAlarmData(ctx context.Context, deviceID string, portID uint32) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetPortAlarmData", ctx, deviceID, portID)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetPortAlarmData indicates an expected call of GetPortAlarmData.
+func (mr *MockDBIntfMockRecorder) GetPortAlarmData(ctx, deviceID, portID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPortAlarmData", reflect.TypeOf((*MockDBIntf)(nil).GetPortAlarmData), ctx, deviceID, portID)
+}
+
+// GetPortAlarmProfile mocks base method.
+func (m *MockDBIntf) GetPortAlarmProfile(ctx context.Context, portAlarmProfileID string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetPortAlarmProfile", ctx, portAlarmProfileID)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetPortAlarmProfile indicates an expected call of GetPortAlarmProfile.
+func (mr *MockDBIntfMockRecorder) GetPortAlarmProfile(ctx, portAlarmProfileID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPortAlarmProfile", reflect.TypeOf((*MockDBIntf)(nil).GetPortAlarmProfile), ctx, portAlarmProfileID)
+}
+
+// GetPorts mocks base method.
+func (m *MockDBIntf) GetPorts(ctx context.Context, deviceID string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetPorts", ctx, deviceID)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetPorts indicates an expected call of GetPorts.
+func (mr *MockDBIntfMockRecorder) GetPorts(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPorts", reflect.TypeOf((*MockDBIntf)(nil).GetPorts), ctx, deviceID)
+}
+
+// GetPrevIgmpChannels mocks base method.
+func (m *MockDBIntf) GetPrevIgmpChannels(ctx context.Context, gname, device string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetPrevIgmpChannels", ctx, gname, device)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetPrevIgmpChannels indicates an expected call of GetPrevIgmpChannels.
+func (mr *MockDBIntfMockRecorder) GetPrevIgmpChannels(ctx, gname, device interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPrevIgmpChannels", reflect.TypeOf((*MockDBIntf)(nil).GetPrevIgmpChannels), ctx, gname, device)
+}
+
+// GetPrevIgmpDevices mocks base method.
+func (m *MockDBIntf) GetPrevIgmpDevices(ctx context.Context, mvlan of.VlanType, gid string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetPrevIgmpDevices", ctx, mvlan, gid)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetPrevIgmpDevices indicates an expected call of GetPrevIgmpDevices.
+func (mr *MockDBIntfMockRecorder) GetPrevIgmpDevices(ctx, mvlan, gid interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPrevIgmpDevices", reflect.TypeOf((*MockDBIntf)(nil).GetPrevIgmpDevices), ctx, mvlan, gid)
+}
+
+// GetPrevIgmpRcvrs mocks base method.
+func (m *MockDBIntf) GetPrevIgmpRcvrs(ctx context.Context, gip net.IP, device string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetPrevIgmpRcvrs", ctx, gip, device)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetPrevIgmpRcvrs indicates an expected call of GetPrevIgmpRcvrs.
+func (mr *MockDBIntfMockRecorder) GetPrevIgmpRcvrs(ctx, gip, device interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPrevIgmpRcvrs", reflect.TypeOf((*MockDBIntf)(nil).GetPrevIgmpRcvrs), ctx, gip, device)
+}
+
+// GetService mocks base method.
+func (m *MockDBIntf) GetService(ctx context.Context, name string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetService", ctx, name)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetService indicates an expected call of GetService.
+func (mr *MockDBIntfMockRecorder) GetService(ctx, name interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetService", reflect.TypeOf((*MockDBIntf)(nil).GetService), ctx, name)
+}
+
+// GetServiceChannelCounter mocks base method.
+func (m *MockDBIntf) GetServiceChannelCounter(ctx context.Context, serviceName, channel string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetServiceChannelCounter", ctx, serviceName, channel)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetServiceChannelCounter indicates an expected call of GetServiceChannelCounter.
+func (mr *MockDBIntfMockRecorder) GetServiceChannelCounter(ctx, serviceName, channel interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceChannelCounter", reflect.TypeOf((*MockDBIntf)(nil).GetServiceChannelCounter), ctx, serviceName, channel)
+}
+
+// GetServices mocks base method.
+func (m *MockDBIntf) GetServices(ctx context.Context) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetServices", ctx)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetServices indicates an expected call of GetServices.
+func (mr *MockDBIntfMockRecorder) GetServices(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServices", reflect.TypeOf((*MockDBIntf)(nil).GetServices), ctx)
+}
+
+// GetSubAlarmData mocks base method.
+func (m *MockDBIntf) GetSubAlarmData(ctx context.Context, deviceID, portName string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetSubAlarmData", ctx, deviceID, portName)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetSubAlarmData indicates an expected call of GetSubAlarmData.
+func (mr *MockDBIntfMockRecorder) GetSubAlarmData(ctx, deviceID, portName interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubAlarmData", reflect.TypeOf((*MockDBIntf)(nil).GetSubAlarmData), ctx, deviceID, portName)
+}
+
+// GetVnet mocks base method.
+func (m *MockDBIntf) GetVnet(ctx context.Context, name string) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetVnet", ctx, name)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetVnet indicates an expected call of GetVnet.
+func (mr *MockDBIntfMockRecorder) GetVnet(ctx, name interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVnet", reflect.TypeOf((*MockDBIntf)(nil).GetVnet), ctx, name)
+}
+
+// GetVnets mocks base method.
+func (m *MockDBIntf) GetVnets(ctx context.Context) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetVnets", ctx)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetVnets indicates an expected call of GetVnets.
+func (mr *MockDBIntfMockRecorder) GetVnets(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVnets", reflect.TypeOf((*MockDBIntf)(nil).GetVnets), ctx)
+}
+
+// GetVpv mocks base method.
+func (m *MockDBIntf) GetVpv(ctx context.Context, port string, SVlan, CVlan, UniVlan uint16) (string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetVpv", ctx, port, SVlan, CVlan, UniVlan)
+ ret0, _ := ret[0].(string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetVpv indicates an expected call of GetVpv.
+func (mr *MockDBIntfMockRecorder) GetVpv(ctx, port, SVlan, CVlan, UniVlan interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVpv", reflect.TypeOf((*MockDBIntf)(nil).GetVpv), ctx, port, SVlan, CVlan, UniVlan)
+}
+
+// GetVpvs mocks base method.
+func (m *MockDBIntf) GetVpvs(ctx context.Context) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetVpvs", ctx)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetVpvs indicates an expected call of GetVpvs.
+func (mr *MockDBIntfMockRecorder) GetVpvs(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVpvs", reflect.TypeOf((*MockDBIntf)(nil).GetVpvs), ctx)
+}
+
+// List mocks base method.
+func (m *MockDBIntf) List(ctx context.Context, key string) (map[string]*kvstore.KVPair, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "List", ctx, key)
+ ret0, _ := ret[0].(map[string]*kvstore.KVPair)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// List indicates an expected call of List.
+func (mr *MockDBIntfMockRecorder) List(ctx, key interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockDBIntf)(nil).List), ctx, key)
+}
+
+// OltExists mocks base method.
+func (m *MockDBIntf) OltExists(ctx context.Context, deviceID string) bool {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "OltExists", ctx, deviceID)
+ ret0, _ := ret[0].(bool)
+ return ret0
+}
+
+// OltExists indicates an expected call of OltExists.
+func (mr *MockDBIntfMockRecorder) OltExists(ctx, deviceID interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OltExists", reflect.TypeOf((*MockDBIntf)(nil).OltExists), ctx, deviceID)
+}
+
+// Put mocks base method.
+func (m *MockDBIntf) Put(ctx context.Context, fullKeyPath, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Put", ctx, fullKeyPath, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// Put indicates an expected call of Put.
+func (mr *MockDBIntfMockRecorder) Put(ctx, fullKeyPath, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockDBIntf)(nil).Put), ctx, fullKeyPath, value)
+}
+
+// PutDeviceConfig mocks base method.
+func (m *MockDBIntf) PutDeviceConfig(ctx context.Context, serialNum, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutDeviceConfig", ctx, serialNum, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutDeviceConfig indicates an expected call of PutDeviceConfig.
+func (mr *MockDBIntfMockRecorder) PutDeviceConfig(ctx, serialNum, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutDeviceConfig", reflect.TypeOf((*MockDBIntf)(nil).PutDeviceConfig), ctx, serialNum, value)
+}
+
+// PutDeviceMeter mocks base method.
+func (m *MockDBIntf) PutDeviceMeter(ctx context.Context, deviceID string, meterID uint32, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutDeviceMeter", ctx, deviceID, meterID, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutDeviceMeter indicates an expected call of PutDeviceMeter.
+func (mr *MockDBIntfMockRecorder) PutDeviceMeter(ctx, deviceID, meterID, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutDeviceMeter", reflect.TypeOf((*MockDBIntf)(nil).PutDeviceMeter), ctx, deviceID, meterID, value)
+}
+
+// PutFlow mocks base method.
+func (m *MockDBIntf) PutFlow(ctx context.Context, deviceID string, flowID uint64, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutFlow", ctx, deviceID, flowID, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutFlow indicates an expected call of PutFlow.
+func (mr *MockDBIntfMockRecorder) PutFlow(ctx, deviceID, flowID, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutFlow", reflect.TypeOf((*MockDBIntf)(nil).PutFlow), ctx, deviceID, flowID, value)
+}
+
+// PutFlowHash mocks base method.
+func (m *MockDBIntf) PutFlowHash(ctx context.Context, deviceID, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutFlowHash", ctx, deviceID, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutFlowHash indicates an expected call of PutFlowHash.
+func (mr *MockDBIntfMockRecorder) PutFlowHash(ctx, deviceID, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutFlowHash", reflect.TypeOf((*MockDBIntf)(nil).PutFlowHash), ctx, deviceID, value)
+}
+
+// PutGroup mocks base method.
+func (m *MockDBIntf) PutGroup(ctx context.Context, deviceID string, groupID uint32, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutGroup", ctx, deviceID, groupID, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutGroup indicates an expected call of PutGroup.
+func (mr *MockDBIntfMockRecorder) PutGroup(ctx, deviceID, groupID, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutGroup", reflect.TypeOf((*MockDBIntf)(nil).PutGroup), ctx, deviceID, groupID, value)
+}
+
+// PutHealth mocks base method.
+func (m *MockDBIntf) PutHealth(ctx context.Context, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutHealth", ctx, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutHealth indicates an expected call of PutHealth.
+func (mr *MockDBIntfMockRecorder) PutHealth(ctx, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutHealth", reflect.TypeOf((*MockDBIntf)(nil).PutHealth), ctx, value)
+}
+
+// PutIgmpChannel mocks base method.
+func (m *MockDBIntf) PutIgmpChannel(ctx context.Context, mvlan of.VlanType, gName, device string, gip net.IP, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutIgmpChannel", ctx, mvlan, gName, device, gip, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutIgmpChannel indicates an expected call of PutIgmpChannel.
+func (mr *MockDBIntfMockRecorder) PutIgmpChannel(ctx, mvlan, gName, device, gip, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutIgmpChannel", reflect.TypeOf((*MockDBIntf)(nil).PutIgmpChannel), ctx, mvlan, gName, device, gip, value)
+}
+
+// PutIgmpDevice mocks base method.
+func (m *MockDBIntf) PutIgmpDevice(ctx context.Context, mvlan of.VlanType, gid string, gip net.IP, device, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutIgmpDevice", ctx, mvlan, gid, gip, device, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutIgmpDevice indicates an expected call of PutIgmpDevice.
+func (mr *MockDBIntfMockRecorder) PutIgmpDevice(ctx, mvlan, gid, gip, device, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutIgmpDevice", reflect.TypeOf((*MockDBIntf)(nil).PutIgmpDevice), ctx, mvlan, gid, gip, device, value)
+}
+
+// PutIgmpGroup mocks base method.
+func (m *MockDBIntf) PutIgmpGroup(ctx context.Context, id, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutIgmpGroup", ctx, id, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutIgmpGroup indicates an expected call of PutIgmpGroup.
+func (mr *MockDBIntfMockRecorder) PutIgmpGroup(ctx, id, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutIgmpGroup", reflect.TypeOf((*MockDBIntf)(nil).PutIgmpGroup), ctx, id, value)
+}
+
+// PutIgmpProfile mocks base method.
+func (m *MockDBIntf) PutIgmpProfile(ctx context.Context, name, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutIgmpProfile", ctx, name, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutIgmpProfile indicates an expected call of PutIgmpProfile.
+func (mr *MockDBIntfMockRecorder) PutIgmpProfile(ctx, name, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutIgmpProfile", reflect.TypeOf((*MockDBIntf)(nil).PutIgmpProfile), ctx, name, value)
+}
+
+// PutIgmpRcvr mocks base method.
+func (m *MockDBIntf) PutIgmpRcvr(ctx context.Context, mvlan of.VlanType, gip net.IP, device, rcvr, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutIgmpRcvr", ctx, mvlan, gip, device, rcvr, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutIgmpRcvr indicates an expected call of PutIgmpRcvr.
+func (mr *MockDBIntfMockRecorder) PutIgmpRcvr(ctx, mvlan, gip, device, rcvr, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutIgmpRcvr", reflect.TypeOf((*MockDBIntf)(nil).PutIgmpRcvr), ctx, mvlan, gip, device, rcvr, value)
+}
+
+// PutMcastConfig mocks base method.
+func (m *MockDBIntf) PutMcastConfig(ctx context.Context, name, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutMcastConfig", ctx, name, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutMcastConfig indicates an expected call of PutMcastConfig.
+func (mr *MockDBIntfMockRecorder) PutMcastConfig(ctx, name, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutMcastConfig", reflect.TypeOf((*MockDBIntf)(nil).PutMcastConfig), ctx, name, value)
+}
+
+// PutMeter mocks base method.
+func (m *MockDBIntf) PutMeter(ctx context.Context, name, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutMeter", ctx, name, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutMeter indicates an expected call of PutMeter.
+func (mr *MockDBIntfMockRecorder) PutMeter(ctx, name, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutMeter", reflect.TypeOf((*MockDBIntf)(nil).PutMeter), ctx, name, value)
+}
+
+// PutMigrateServicesReq mocks base method.
+func (m *MockDBIntf) PutMigrateServicesReq(ctx context.Context, deviceID, vlan, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutMigrateServicesReq", ctx, deviceID, vlan, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutMigrateServicesReq indicates an expected call of PutMigrateServicesReq.
+func (mr *MockDBIntfMockRecorder) PutMigrateServicesReq(ctx, deviceID, vlan, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutMigrateServicesReq", reflect.TypeOf((*MockDBIntf)(nil).PutMigrateServicesReq), ctx, deviceID, vlan, value)
+}
+
+// PutMigrationInfo mocks base method.
+func (m *MockDBIntf) PutMigrationInfo(ctx context.Context, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutMigrationInfo", ctx, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutMigrationInfo indicates an expected call of PutMigrationInfo.
+func (mr *MockDBIntfMockRecorder) PutMigrationInfo(ctx, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutMigrationInfo", reflect.TypeOf((*MockDBIntf)(nil).PutMigrationInfo), ctx, value)
+}
+
+// PutMvlan mocks base method.
+func (m *MockDBIntf) PutMvlan(ctx context.Context, mvlan uint16, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutMvlan", ctx, mvlan, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutMvlan indicates an expected call of PutMvlan.
+func (mr *MockDBIntfMockRecorder) PutMvlan(ctx, mvlan, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutMvlan", reflect.TypeOf((*MockDBIntf)(nil).PutMvlan), ctx, mvlan, value)
+}
+
+// PutNbDevicePort mocks base method.
+func (m *MockDBIntf) PutNbDevicePort(ctx context.Context, device string, ponPortID uint32, value string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "PutNbDevicePort", ctx, device, ponPortID, value)
+}
+
+// PutNbDevicePort indicates an expected call of PutNbDevicePort.
+func (mr *MockDBIntfMockRecorder) PutNbDevicePort(ctx, device, ponPortID, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutNbDevicePort", reflect.TypeOf((*MockDBIntf)(nil).PutNbDevicePort), ctx, device, ponPortID, value)
+}
+
+// PutOlt mocks base method.
+func (m *MockDBIntf) PutOlt(ctx context.Context, deviceID, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutOlt", ctx, deviceID, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutOlt indicates an expected call of PutOlt.
+func (mr *MockDBIntfMockRecorder) PutOlt(ctx, deviceID, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutOlt", reflect.TypeOf((*MockDBIntf)(nil).PutOlt), ctx, deviceID, value)
+}
+
+// PutOltFlowService mocks base method.
+func (m *MockDBIntf) PutOltFlowService(ctx context.Context, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutOltFlowService", ctx, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutOltFlowService indicates an expected call of PutOltFlowService.
+func (mr *MockDBIntfMockRecorder) PutOltFlowService(ctx, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutOltFlowService", reflect.TypeOf((*MockDBIntf)(nil).PutOltFlowService), ctx, value)
+}
+
+// PutOltIgmpCounters mocks base method.
+func (m *MockDBIntf) PutOltIgmpCounters(ctx context.Context, device, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutOltIgmpCounters", ctx, device, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutOltIgmpCounters indicates an expected call of PutOltIgmpCounters.
+func (mr *MockDBIntfMockRecorder) PutOltIgmpCounters(ctx, device, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutOltIgmpCounters", reflect.TypeOf((*MockDBIntf)(nil).PutOltIgmpCounters), ctx, device, value)
+}
+
+// PutPonChannelCounter mocks base method.
+func (m *MockDBIntf) PutPonChannelCounter(ctx context.Context, device, ponID, channel, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutPonChannelCounter", ctx, device, ponID, channel, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutPonChannelCounter indicates an expected call of PutPonChannelCounter.
+func (mr *MockDBIntfMockRecorder) PutPonChannelCounter(ctx, device, ponID, channel, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutPonChannelCounter", reflect.TypeOf((*MockDBIntf)(nil).PutPonChannelCounter), ctx, device, ponID, channel, value)
+}
+
+// PutPonCounter mocks base method.
+func (m *MockDBIntf) PutPonCounter(ctx context.Context, device, ponID, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutPonCounter", ctx, device, ponID, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutPonCounter indicates an expected call of PutPonCounter.
+func (mr *MockDBIntfMockRecorder) PutPonCounter(ctx, device, ponID, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutPonCounter", reflect.TypeOf((*MockDBIntf)(nil).PutPonCounter), ctx, device, ponID, value)
+}
+
+// PutPort mocks base method.
+func (m *MockDBIntf) PutPort(ctx context.Context, deviceID string, portID uint32, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutPort", ctx, deviceID, portID, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutPort indicates an expected call of PutPort.
+func (mr *MockDBIntfMockRecorder) PutPort(ctx, deviceID, portID, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutPort", reflect.TypeOf((*MockDBIntf)(nil).PutPort), ctx, deviceID, portID, value)
+}
+
+// PutPortAlarmData mocks base method.
+func (m *MockDBIntf) PutPortAlarmData(ctx context.Context, deviceID string, portID uint32, value string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "PutPortAlarmData", ctx, deviceID, portID, value)
+}
+
+// PutPortAlarmData indicates an expected call of PutPortAlarmData.
+func (mr *MockDBIntfMockRecorder) PutPortAlarmData(ctx, deviceID, portID, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutPortAlarmData", reflect.TypeOf((*MockDBIntf)(nil).PutPortAlarmData), ctx, deviceID, portID, value)
+}
+
+// PutPortAlarmProfile mocks base method.
+func (m *MockDBIntf) PutPortAlarmProfile(ctx context.Context, portAlarmProfileID, value string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "PutPortAlarmProfile", ctx, portAlarmProfileID, value)
+}
+
+// PutPortAlarmProfile indicates an expected call of PutPortAlarmProfile.
+func (mr *MockDBIntfMockRecorder) PutPortAlarmProfile(ctx, portAlarmProfileID, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutPortAlarmProfile", reflect.TypeOf((*MockDBIntf)(nil).PutPortAlarmProfile), ctx, portAlarmProfileID, value)
+}
+
+// PutService mocks base method.
+func (m *MockDBIntf) PutService(ctx context.Context, name, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutService", ctx, name, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutService indicates an expected call of PutService.
+func (mr *MockDBIntfMockRecorder) PutService(ctx, name, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutService", reflect.TypeOf((*MockDBIntf)(nil).PutService), ctx, name, value)
+}
+
+// PutServiceChannelCounter mocks base method.
+func (m *MockDBIntf) PutServiceChannelCounter(ctx context.Context, serviceName, channel, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutServiceChannelCounter", ctx, serviceName, channel, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutServiceChannelCounter indicates an expected call of PutServiceChannelCounter.
+func (mr *MockDBIntfMockRecorder) PutServiceChannelCounter(ctx, serviceName, channel, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutServiceChannelCounter", reflect.TypeOf((*MockDBIntf)(nil).PutServiceChannelCounter), ctx, serviceName, channel, value)
+}
+
+// PutSubAlarmData mocks base method.
+func (m *MockDBIntf) PutSubAlarmData(ctx context.Context, deviceID, portName, value string) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "PutSubAlarmData", ctx, deviceID, portName, value)
+}
+
+// PutSubAlarmData indicates an expected call of PutSubAlarmData.
+func (mr *MockDBIntfMockRecorder) PutSubAlarmData(ctx, deviceID, portName, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutSubAlarmData", reflect.TypeOf((*MockDBIntf)(nil).PutSubAlarmData), ctx, deviceID, portName, value)
+}
+
+// PutVnet mocks base method.
+func (m *MockDBIntf) PutVnet(ctx context.Context, name, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutVnet", ctx, name, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutVnet indicates an expected call of PutVnet.
+func (mr *MockDBIntfMockRecorder) PutVnet(ctx, name, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutVnet", reflect.TypeOf((*MockDBIntf)(nil).PutVnet), ctx, name, value)
+}
+
+// PutVpv mocks base method.
+func (m *MockDBIntf) PutVpv(ctx context.Context, port string, SVlan, CVlan, UniVlan uint16, value string) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "PutVpv", ctx, port, SVlan, CVlan, UniVlan, value)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PutVpv indicates an expected call of PutVpv.
+func (mr *MockDBIntfMockRecorder) PutVpv(ctx, port, SVlan, CVlan, UniVlan, value interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutVpv", reflect.TypeOf((*MockDBIntf)(nil).PutVpv), ctx, port, SVlan, CVlan, UniVlan, value)
+}
diff --git a/tests/results/go-test-coverage.out b/tests/results/go-test-coverage.out
new file mode 100644
index 0000000..eb766b9
--- /dev/null
+++ b/tests/results/go-test-coverage.out
@@ -0,0 +1,5597 @@
+#
+# Copyright 2022-present Open Networking Foundation
+# 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.
+#
+
+mode: count
+voltha-go-controller/internal/pkg/application/igmp.go:105.13,107.2 1 1
+voltha-go-controller/internal/pkg/application/igmp.go:110.95,112.2 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:114.35,117.17 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:121.2,125.15 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:117.17,120.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:128.38,130.16 2 2
+voltha-go-controller/internal/pkg/application/igmp.go:133.2,134.27 2 2
+voltha-go-controller/internal/pkg/application/igmp.go:148.2,148.64 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:130.16,132.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:134.27,136.17 2 4
+voltha-go-controller/internal/pkg/application/igmp.go:139.3,139.30 1 4
+voltha-go-controller/internal/pkg/application/igmp.go:136.17,138.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:139.30,140.62 1 4
+voltha-go-controller/internal/pkg/application/igmp.go:140.62,141.35 1 4
+voltha-go-controller/internal/pkg/application/igmp.go:141.35,144.6 2 2
+voltha-go-controller/internal/pkg/application/igmp.go:153.51,163.2 8 0
+voltha-go-controller/internal/pkg/application/igmp.go:166.71,173.2 6 0
+voltha-go-controller/internal/pkg/application/igmp.go:180.62,188.2 7 0
+voltha-go-controller/internal/pkg/application/igmp.go:195.49,203.2 7 0
+voltha-go-controller/internal/pkg/application/igmp.go:207.51,217.2 8 0
+voltha-go-controller/internal/pkg/application/igmp.go:220.71,227.2 6 0
+voltha-go-controller/internal/pkg/application/igmp.go:230.60,236.40 6 0
+voltha-go-controller/internal/pkg/application/igmp.go:239.2,240.11 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:236.40,238.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:244.78,250.2 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:253.73,259.2 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:262.55,267.2 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:270.54,275.2 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:278.79,286.10 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:291.2,296.13 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:286.10,288.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:288.8,290.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:300.114,313.83 7 0
+voltha-go-controller/internal/pkg/application/igmp.go:317.2,317.26 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:313.83,316.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:321.114,334.83 7 0
+voltha-go-controller/internal/pkg/application/igmp.go:338.2,338.26 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:334.83,337.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:342.103,355.83 7 0
+voltha-go-controller/internal/pkg/application/igmp.go:359.2,359.26 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:355.83,358.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:363.132,376.83 7 0
+voltha-go-controller/internal/pkg/application/igmp.go:380.2,380.26 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:376.83,379.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:384.100,397.83 7 0
+voltha-go-controller/internal/pkg/application/igmp.go:401.2,401.26 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:397.83,400.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:405.35,406.31 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:409.2,409.21 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:406.31,408.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:413.47,414.25 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:419.2,419.14 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:414.25,415.18 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:415.18,417.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:423.82,425.63 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:436.2,436.14 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:425.63,431.44 6 0
+voltha-go-controller/internal/pkg/application/igmp.go:434.3,434.14 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:431.44,433.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:450.102,455.61 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:463.2,464.17 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:469.2,469.45 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:455.61,456.91 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:459.3,459.15 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:456.91,458.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:464.17,467.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:469.45,471.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:475.78,481.59 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:489.2,490.17 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:495.2,495.45 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:499.2,499.20 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:481.59,482.91 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:485.3,485.14 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:482.91,484.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:490.17,493.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:495.45,497.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:503.74,505.31 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:505.31,507.10 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:511.3,513.17 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:517.3,520.41 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:523.3,527.58 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:530.3,532.33 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:535.3,535.126 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:507.10,509.12 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:513.17,515.12 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:520.41,522.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:527.58,529.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:532.33,534.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:542.117,544.73 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:566.2,567.12 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:544.73,545.68 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:561.3,561.44 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:564.3,564.12 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:545.68,551.4 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:551.9,553.48 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:557.4,559.35 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:553.48,556.5 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:561.44,563.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:575.83,577.20 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:581.2,586.8 6 0
+voltha-go-controller/internal/pkg/application/igmp.go:597.2,597.12 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:577.20,580.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:586.8,596.3 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:602.78,604.11 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:604.11,609.51 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:609.51,612.31 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:624.4,624.29 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:612.31,617.5 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:617.10,620.46 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:620.46,622.6 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:630.74,632.38 2 3
+voltha-go-controller/internal/pkg/application/igmp.go:636.2,637.9 2 2
+voltha-go-controller/internal/pkg/application/igmp.go:640.2,643.20 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:646.2,646.44 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:632.38,635.3 2 1
+voltha-go-controller/internal/pkg/application/igmp.go:637.9,639.3 1 2
+voltha-go-controller/internal/pkg/application/igmp.go:643.20,645.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:651.97,654.77 2 1
+voltha-go-controller/internal/pkg/application/igmp.go:666.2,671.42 3 1
+voltha-go-controller/internal/pkg/application/igmp.go:654.77,657.17 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:660.3,660.63 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:664.3,664.14 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:657.17,659.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:660.63,663.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:676.112,679.77 2 1
+voltha-go-controller/internal/pkg/application/igmp.go:690.2,695.46 3 1
+voltha-go-controller/internal/pkg/application/igmp.go:679.77,682.17 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:685.3,685.70 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:688.3,688.14 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:682.17,684.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:685.70,687.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:700.152,701.40 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:707.2,707.54 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:701.40,702.12 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:705.3,705.19 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:702.12,704.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:707.54,710.16 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:721.3,721.56 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:710.16,713.72 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:719.4,719.46 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:713.72,718.5 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:721.56,726.4 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:734.77,737.81 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:743.2,743.57 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:793.2,794.13 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:737.81,741.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:743.57,747.68 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:761.3,761.71 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:747.68,748.67 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:748.67,751.56 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:756.5,756.16 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:751.56,755.6 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:758.9,760.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:761.71,768.62 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:785.4,786.126 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:768.62,772.5 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:772.10,772.83 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:772.83,777.18 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:777.18,778.104 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:778.104,779.112 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:779.112,781.8 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:787.9,791.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:798.116,810.98 7 0
+voltha-go-controller/internal/pkg/application/igmp.go:810.98,818.17 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:826.3,827.17 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:832.3,839.103 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:844.3,844.16 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:818.17,821.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:821.9,821.30 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:821.30,824.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:827.17,831.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:839.103,843.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:844.16,852.44 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:858.4,859.29 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:852.44,857.5 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:860.9,862.97 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:862.97,869.45 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:875.5,876.30 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:869.45,874.6 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:877.10,880.5 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:882.8,882.49 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:882.49,887.17 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:895.3,900.67 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:887.17,890.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:890.9,890.30 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:890.30,893.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:900.67,905.34 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:905.34,907.5 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:909.8,916.21 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:920.3,924.56 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:916.21,919.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:924.56,926.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:926.9,927.70 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:927.70,930.11 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:935.5,935.30 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:930.11,932.6 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:932.11,934.6 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:942.116,946.23 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:950.2,959.50 7 0
+voltha-go-controller/internal/pkg/application/igmp.go:946.23,949.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:959.50,964.17 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:971.3,972.17 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:977.3,981.45 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:964.17,967.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:967.9,967.30 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:967.30,970.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:972.17,976.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:981.45,985.14 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:985.14,986.108 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:992.5,992.18 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:986.108,991.6 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:992.18,1000.46 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:1006.6,1008.31 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1000.46,1005.7 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1009.11,1012.101 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1012.101,1018.47 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:1024.7,1026.32 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1018.47,1023.8 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1027.12,1029.7 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1031.10,1031.24 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1031.24,1036.35 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:1036.35,1038.6 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1039.10,1041.5 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1043.8,1050.21 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1054.3,1058.56 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:1050.21,1053.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1058.56,1060.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1060.9,1061.70 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1061.70,1064.11 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1069.5,1069.30 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1064.11,1066.6 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1066.11,1068.6 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1076.120,1078.64 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1100.2,1100.35 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1078.64,1081.26 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1085.3,1086.10 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1091.3,1091.79 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1096.3,1098.14 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1081.26,1084.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1086.10,1090.4 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1091.79,1095.4 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1104.84,1107.72 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1118.2,1118.13 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1107.72,1109.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1109.8,1109.43 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1109.43,1110.27 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1110.27,1112.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1113.8,1113.115 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1113.115,1114.27 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1114.27,1116.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1121.59,1122.108 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1125.2,1125.14 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1122.108,1124.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1130.114,1132.18 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1136.2,1136.47 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1142.2,1142.44 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1132.18,1135.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1136.47,1141.3 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1142.44,1145.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1149.91,1152.2 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1155.94,1158.2 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1161.76,1164.2 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1167.70,1169.31 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1169.31,1171.10 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1175.3,1177.17 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1181.3,1183.37 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1189.3,1189.79 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1171.10,1173.12 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1177.17,1179.12 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1183.37,1184.40 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1184.40,1187.5 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1194.81,1195.53 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1198.2,1198.12 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1195.53,1197.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1202.77,1203.54 1 1
+voltha-go-controller/internal/pkg/application/igmp.go:1206.2,1206.12 1 1
+voltha-go-controller/internal/pkg/application/igmp.go:1203.54,1205.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1210.203,1212.9 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1216.2,1226.41 7 0
+voltha-go-controller/internal/pkg/application/igmp.go:1229.2,1229.40 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1232.2,1232.49 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1237.2,1238.97 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1252.2,1261.44 7 0
+voltha-go-controller/internal/pkg/application/igmp.go:1264.2,1264.52 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1270.2,1272.12 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1212.9,1215.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1226.41,1228.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1229.40,1231.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1232.49,1233.52 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1233.52,1235.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1238.97,1240.58 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1249.3,1250.13 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1240.58,1242.46 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1245.4,1245.54 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1242.46,1244.5 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1245.54,1247.5 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1261.44,1263.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1264.52,1266.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1276.68,1277.45 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1282.2,1282.14 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1277.45,1278.32 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1278.32,1280.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1286.69,1288.2 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1291.97,1292.85 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1295.2,1295.12 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1292.85,1294.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1298.112,1300.2 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1302.87,1304.2 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1307.157,1311.21 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1319.2,1320.9 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1323.2,1332.66 7 0
+voltha-go-controller/internal/pkg/application/igmp.go:1354.2,1357.49 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1360.2,1362.12 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1311.21,1313.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1313.8,1316.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1320.9,1322.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1332.66,1334.24 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1338.3,1338.34 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1352.3,1352.14 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1334.24,1336.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1338.34,1339.36 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1342.4,1343.27 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1348.4,1350.70 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1339.36,1340.13 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1343.27,1345.5 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1345.10,1347.5 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1357.49,1359.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1365.108,1367.68 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1367.68,1372.45 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:1375.3,1375.45 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1372.45,1374.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1379.110,1381.68 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1381.68,1386.45 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:1386.45,1388.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1393.151,1397.60 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:1397.60,1398.66 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1398.66,1400.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1405.95,1406.79 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1413.2,1414.12 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1406.79,1408.44 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1411.3,1411.14 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1408.44,1410.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1418.160,1420.21 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1425.2,1432.41 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:1446.2,1446.49 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1450.2,1450.12 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1420.21,1423.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1432.41,1433.70 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1443.3,1443.53 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1433.70,1436.27 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1441.4,1441.15 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1436.27,1438.5 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1438.10,1440.5 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1446.49,1448.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1454.62,1457.16 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1460.2,1460.113 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1463.2,1463.12 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1457.16,1459.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1460.113,1462.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1467.76,1469.46 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1469.46,1471.10 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1475.3,1477.17 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1481.3,1482.141 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1471.10,1473.12 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1477.17,1479.12 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1488.156,1491.54 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1495.2,1495.58 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1506.2,1506.16 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1510.2,1514.39 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1517.2,1517.40 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1520.2,1520.49 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1526.2,1529.44 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1533.2,1533.12 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1491.54,1494.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1495.58,1497.42 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1497.42,1498.41 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1498.41,1502.5 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1506.16,1508.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1514.39,1516.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1517.40,1519.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1520.49,1521.52 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1521.52,1523.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1529.44,1531.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1540.106,1541.65 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1549.2,1549.16 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1541.65,1543.54 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1543.54,1545.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1546.8,1548.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1553.59,1555.29 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1558.2,1558.60 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1572.2,1572.31 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1555.29,1557.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1558.60,1560.33 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1570.3,1570.14 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1560.33,1561.36 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1561.36,1565.35 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:1565.35,1567.6 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1576.35,1580.2 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1583.109,1586.54 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1591.2,1592.24 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1599.2,1601.52 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1605.2,1605.12 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1586.54,1589.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1592.24,1594.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1594.8,1597.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1601.52,1603.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1609.74,1610.65 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1613.2,1613.12 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1610.65,1612.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1616.76,1634.49 16 0
+voltha-go-controller/internal/pkg/application/igmp.go:1634.49,1636.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1640.72,1641.65 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1646.2,1647.46 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1641.65,1643.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1651.87,1653.2 1 1
+voltha-go-controller/internal/pkg/application/igmp.go:1656.62,1658.2 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1682.89,1684.36 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1689.2,1690.24 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1695.2,1698.16 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1703.2,1703.12 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1684.36,1688.3 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1690.24,1693.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1698.16,1701.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1707.112,1709.24 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1714.2,1721.46 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:1725.2,1736.91 10 0
+voltha-go-controller/internal/pkg/application/igmp.go:1742.2,1742.42 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1746.2,1746.52 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1750.2,1750.12 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1709.24,1712.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1721.46,1724.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1736.91,1738.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1738.8,1740.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1742.42,1744.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1746.52,1748.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1754.76,1757.43 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1757.43,1759.10 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1763.3,1765.17 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1769.3,1770.75 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1759.10,1761.12 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1765.17,1767.12 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1775.45,1777.16 2 2
+voltha-go-controller/internal/pkg/application/igmp.go:1781.2,1781.21 1 2
+voltha-go-controller/internal/pkg/application/igmp.go:1777.16,1780.3 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1785.85,1786.58 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1802.2,1803.12 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1786.58,1789.32 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1800.3,1800.13 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1789.32,1794.4 4 0
+voltha-go-controller/internal/pkg/application/igmp.go:1794.9,1798.4 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1807.125,1809.61 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1809.61,1811.53 2 0
+voltha-go-controller/internal/pkg/application/igmp.go:1811.53,1814.31 3 0
+voltha-go-controller/internal/pkg/application/igmp.go:1814.31,1816.5 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1817.9,1819.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1820.8,1822.3 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1826.122,1827.121 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1834.2,1834.58 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1827.121,1828.97 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1828.97,1830.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1830.9,1832.4 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1834.58,1835.122 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1835.122,1836.98 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1836.98,1838.5 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1838.10,1840.5 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1846.94,1851.55 3 3
+voltha-go-controller/internal/pkg/application/igmp.go:1861.2,1861.26 1 3
+voltha-go-controller/internal/pkg/application/igmp.go:1851.55,1856.33 5 0
+voltha-go-controller/internal/pkg/application/igmp.go:1859.3,1859.14 1 0
+voltha-go-controller/internal/pkg/application/igmp.go:1856.33,1858.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:53.99,67.2 13 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:70.72,72.48 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:75.2,77.18 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:72.48,74.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:81.65,84.29 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:97.2,97.44 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:84.29,86.10 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:90.3,90.59 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:86.10,88.12 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:90.59,93.4 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:93.9,95.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:97.44,99.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:103.68,105.16 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:108.2,108.114 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:111.2,112.12 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:105.16,107.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:108.114,110.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:116.62,118.2 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:121.62,123.2 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:126.56,129.2 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:132.56,135.2 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:138.70,140.37 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:144.2,144.29 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:150.2,151.13 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:140.37,142.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:144.29,146.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:146.8,148.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:155.73,157.30 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:164.2,164.23 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:157.30,158.40 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:158.40,159.23 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:159.23,161.5 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:168.71,170.42 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:174.2,174.30 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:186.2,186.14 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:170.42,172.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:174.30,175.40 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:182.3,182.18 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:175.40,177.23 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:177.23,179.10 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:182.18,184.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:190.56,193.44 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:210.2,210.39 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:193.44,195.40 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:201.3,201.40 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:195.40,196.31 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:196.31,199.5 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:201.40,202.31 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:202.31,205.5 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:207.8,209.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:210.39,211.22 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:211.22,214.4 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:219.56,222.39 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:228.2,228.39 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:234.2,234.39 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:222.39,223.30 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:223.30,226.4 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:228.39,229.30 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:229.30,232.4 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:234.39,235.22 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:235.22,238.4 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:245.117,250.69 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:254.2,255.16 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:259.2,260.10 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:338.2,338.82 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:341.2,341.65 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:250.69,252.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:255.16,258.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:260.10,261.26 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:282.3,282.44 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:261.26,262.31 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:273.4,273.32 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:262.31,264.32 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:264.32,267.6 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:273.32,275.33 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:275.33,278.6 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:282.44,285.55 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:285.55,286.52 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:286.52,288.31 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:288.31,292.7 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:296.8,297.26 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:324.3,324.44 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:336.3,336.46 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:297.26,298.31 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:312.4,312.32 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:298.31,300.32 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:304.5,304.34 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:300.32,303.6 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:304.34,306.6 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:312.32,315.46 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:315.46,316.34 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:316.34,319.7 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:324.44,325.39 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:325.39,326.52 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:326.52,328.31 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:328.31,332.7 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:338.82,340.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:345.70,347.16 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:350.2,350.12 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:347.16,349.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:356.141,364.43 7 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:373.2,387.19 9 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:415.2,415.67 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:418.2,422.19 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:429.2,431.44 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:434.2,434.82 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:437.2,437.22 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:364.43,365.54 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:368.3,368.43 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:365.54,367.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:369.8,369.25 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:369.25,372.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:387.19,391.63 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:391.63,396.4 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:396.9,403.64 5 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:408.4,408.13 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:403.64,407.5 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:408.13,410.5 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:415.67,417.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:422.19,425.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:425.8,425.25 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:425.25,427.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:431.44,433.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:434.82,436.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:442.111,453.76 6 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:477.2,477.29 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:488.2,488.19 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:492.2,492.44 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:495.2,497.25 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:453.76,454.44 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:474.3,474.71 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:454.44,458.19 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:458.19,460.5 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:461.9,462.47 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:462.47,466.20 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:466.20,468.6 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:469.10,472.5 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:477.29,481.44 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:484.3,486.14 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:481.44,483.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:488.19,491.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:492.44,494.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:501.68,508.2 6 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:511.67,514.2 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:517.67,519.21 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:522.2,522.120 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:519.21,521.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:526.55,553.112 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:559.2,559.101 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:564.2,564.16 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:568.2,569.16 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:553.112,557.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:559.101,561.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:561.8,563.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:564.16,567.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:569.16,571.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:571.8,573.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:577.62,579.16 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:583.2,584.66 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:579.16,582.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:588.62,590.16 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:594.2,597.87 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:590.16,593.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:597.87,600.17 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:600.17,602.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:607.66,637.2 18 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:640.50,641.117 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:641.117,643.18 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:643.18,645.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:650.50,669.101 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:669.101,671.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:671.8,673.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:677.52,679.2 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:682.42,685.46 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:689.2,692.48 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:685.46,687.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:692.48,693.25 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:696.3,696.111 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:693.25,694.12 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:696.111,699.4 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:699.9,701.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:706.106,707.33 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:710.2,710.98 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:707.33,709.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:714.66,717.25 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:717.25,719.22 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:719.22,721.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:722.8,722.34 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupchannel.go:722.34,725.3 2 0
+voltha-go-controller/internal/pkg/application/igmpponportchannel.go:30.37,35.2 3 0
+voltha-go-controller/internal/pkg/application/igmpponportchannel.go:39.59,41.2 1 0
+voltha-go-controller/internal/pkg/application/igmpponportchannel.go:50.44,55.2 3 0
+voltha-go-controller/internal/pkg/application/igmpponportchannel.go:59.72,61.2 1 0
+voltha-go-controller/internal/pkg/application/igmpponportchannel.go:64.87,67.9 3 0
+voltha-go-controller/internal/pkg/application/igmpponportchannel.go:72.2,74.21 3 0
+voltha-go-controller/internal/pkg/application/igmpponportchannel.go:67.9,71.3 2 0
+voltha-go-controller/internal/pkg/application/igmpponportchannel.go:78.92,81.8 3 0
+voltha-go-controller/internal/pkg/application/igmpponportchannel.go:95.2,95.18 1 0
+voltha-go-controller/internal/pkg/application/igmpponportchannel.go:81.8,83.51 2 0
+voltha-go-controller/internal/pkg/application/igmpponportchannel.go:83.51,88.4 2 0
+voltha-go-controller/internal/pkg/application/igmpponportchannel.go:88.9,90.4 1 0
+voltha-go-controller/internal/pkg/application/igmpponportchannel.go:91.8,94.3 2 0
+voltha-go-controller/internal/pkg/application/util.go:37.77,38.19 1 4
+voltha-go-controller/internal/pkg/application/util.go:39.32,40.28 1 1
+voltha-go-controller/internal/pkg/application/util.go:41.31,42.28 1 1
+voltha-go-controller/internal/pkg/application/util.go:43.41,44.28 1 0
+voltha-go-controller/internal/pkg/application/util.go:45.40,46.28 1 0
+voltha-go-controller/internal/pkg/application/util.go:47.10,48.50 1 2
+voltha-go-controller/internal/pkg/application/util.go:52.42,54.16 2 1
+voltha-go-controller/internal/pkg/application/util.go:57.2,57.14 1 1
+voltha-go-controller/internal/pkg/application/util.go:54.16,56.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:67.49,68.25 1 9
+voltha-go-controller/internal/pkg/application/vnets.go:73.2,73.14 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:68.25,69.16 1 9
+voltha-go-controller/internal/pkg/application/vnets.go:69.16,71.4 1 9
+voltha-go-controller/internal/pkg/application/vnets.go:157.44,160.33 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:163.2,164.47 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:167.2,168.12 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:160.33,162.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:164.47,166.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:172.54,174.31 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:177.2,178.26 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:174.31,176.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:182.96,188.25 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:188.25,189.37 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:189.37,190.46 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:190.46,194.5 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:194.10,196.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:197.9,201.4 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:205.53,209.2 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:212.53,213.25 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:217.2,217.25 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:213.25,216.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:221.58,226.44 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:226.44,227.62 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:227.62,229.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:235.75,237.2 1 2
+voltha-go-controller/internal/pkg/application/vnets.go:240.100,244.74 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:247.2,247.67 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:250.2,250.12 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:244.74,246.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:247.67,249.3 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:257.65,258.47 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:261.2,261.12 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:258.47,260.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:265.74,271.59 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:276.2,277.40 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:271.59,273.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:273.8,275.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:281.61,285.60 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:285.60,289.3 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:293.96,298.15 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:315.2,315.15 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:328.2,335.12 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:298.15,300.45 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:308.3,308.32 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:300.45,301.49 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:306.4,306.56 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:301.49,304.13 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:308.32,312.4 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:315.15,317.18 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:323.3,323.64 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:317.18,322.4 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:324.8,326.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:339.94,342.51 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:367.2,368.12 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:342.51,348.33 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:348.33,353.76 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:360.4,360.31 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:353.76,357.5 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:357.10,359.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:361.9,364.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:372.81,377.2 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:490.52,521.2 28 0
+voltha-go-controller/internal/pkg/application/vnets.go:523.51,524.46 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:530.2,535.31 4 1
+voltha-go-controller/internal/pkg/application/vnets.go:524.46,528.3 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:539.56,541.93 2 2
+voltha-go-controller/internal/pkg/application/vnets.go:548.2,548.103 1 2
+voltha-go-controller/internal/pkg/application/vnets.go:541.93,542.48 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:542.48,546.4 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:554.48,556.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:559.47,561.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:564.56,566.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:569.61,571.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:574.57,576.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:579.62,581.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:584.60,586.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:589.65,591.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:594.82,596.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:599.99,601.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:604.57,605.25 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:615.2,615.49 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:607.20,608.46 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:610.8,611.48 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:612.16,613.48 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:619.71,621.8 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:624.2,624.16 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:621.8,623.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:628.81,632.2 3 1
+voltha-go-controller/internal/pkg/application/vnets.go:635.81,640.25 3 1
+voltha-go-controller/internal/pkg/application/vnets.go:648.2,648.201 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:640.25,641.48 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:646.3,646.26 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:641.48,644.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:652.86,654.38 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:659.2,659.21 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:654.38,656.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:656.8,656.45 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:656.45,658.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:663.130,664.55 1 3
+voltha-go-controller/internal/pkg/application/vnets.go:664.55,666.3 1 3
+voltha-go-controller/internal/pkg/application/vnets.go:672.87,680.2 6 0
+voltha-go-controller/internal/pkg/application/vnets.go:684.67,685.32 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:685.32,686.17 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:687.32,690.81 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:699.103,706.2 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:709.79,712.78 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:716.2,717.14 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:712.78,715.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:721.84,725.42 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:734.2,736.22 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:725.42,728.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:744.91,745.26 1 2
+voltha-go-controller/internal/pkg/application/vnets.go:749.2,753.15 4 1
+voltha-go-controller/internal/pkg/application/vnets.go:758.2,758.52 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:769.2,769.17 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:774.2,774.50 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:816.2,816.21 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:829.2,829.21 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:745.26,748.3 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:753.15,756.3 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:758.52,761.23 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:761.23,762.61 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:762.61,765.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:769.17,772.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:774.50,779.58 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:782.3,782.37 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:785.3,786.75 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:779.58,781.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:782.37,784.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:786.75,789.38 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:795.4,795.25 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:789.38,791.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:795.25,797.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:799.8,806.24 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:809.3,810.24 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:806.24,808.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:810.24,812.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:816.21,819.48 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:824.3,824.23 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:819.48,822.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:824.23,826.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:835.104,836.79 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:840.2,847.32 5 1
+voltha-go-controller/internal/pkg/application/vnets.go:836.79,839.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:853.82,857.64 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:865.2,865.44 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:896.2,897.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:904.2,904.22 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:914.2,914.21 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:857.64,859.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:865.44,867.53 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:872.3,872.37 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:891.3,891.61 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:867.53,871.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:872.37,886.4 7 0
+voltha-go-controller/internal/pkg/application/vnets.go:886.9,890.4 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:892.8,894.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:897.16,902.3 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:904.22,906.37 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:910.3,910.24 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:906.37,908.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:910.24,912.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:918.103,919.72 1 4
+voltha-go-controller/internal/pkg/application/vnets.go:922.2,922.13 1 4
+voltha-go-controller/internal/pkg/application/vnets.go:919.72,921.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:926.65,927.46 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:930.2,930.27 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:933.2,933.13 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:927.46,929.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:930.27,932.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:937.71,940.54 3 1
+voltha-go-controller/internal/pkg/application/vnets.go:953.2,955.16 3 1
+voltha-go-controller/internal/pkg/application/vnets.go:940.54,942.34 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:951.3,951.14 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:942.34,943.72 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:943.72,949.5 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:959.68,961.54 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:977.2,979.15 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:961.54,963.64 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:971.3,972.23 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:975.3,975.14 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:963.64,968.4 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:972.23,974.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:984.73,992.21 3 1
+voltha-go-controller/internal/pkg/application/vnets.go:997.2,997.40 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1008.2,1008.96 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1014.2,1019.22 5 1
+voltha-go-controller/internal/pkg/application/vnets.go:1027.2,1033.32 4 1
+voltha-go-controller/internal/pkg/application/vnets.go:1041.2,1042.16 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:1048.2,1048.22 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1054.2,1056.48 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:1063.2,1063.22 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1076.2,1076.41 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1088.2,1088.21 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:992.21,994.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:997.40,998.38 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:998.38,1000.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1000.9,1000.38 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1000.38,1002.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1002.9,1002.40 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1002.40,1004.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1008.96,1010.3 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1010.8,1010.42 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1010.42,1012.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1019.22,1026.3 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:1033.32,1034.33 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1034.33,1036.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1036.9,1038.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1042.16,1047.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1048.22,1051.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1056.48,1059.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1063.22,1064.75 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1064.75,1066.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1066.9,1067.51 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1067.51,1069.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1076.41,1078.48 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1083.3,1083.23 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1078.48,1081.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1083.23,1086.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1092.90,1097.2 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:1100.84,1102.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1105.105,1112.2 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:1115.105,1121.2 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:1124.72,1126.49 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1129.2,1129.13 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1126.49,1128.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1133.72,1135.49 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1138.2,1138.13 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1135.49,1137.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1142.77,1157.2 14 0
+voltha-go-controller/internal/pkg/application/vnets.go:1160.72,1162.49 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:1165.2,1165.13 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1162.49,1164.3 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1169.72,1171.49 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:1174.2,1174.13 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1171.49,1173.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1178.78,1182.47 3 1
+voltha-go-controller/internal/pkg/application/vnets.go:1185.2,1185.13 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1182.47,1184.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1189.74,1191.51 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1194.2,1194.13 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1191.51,1193.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1198.61,1199.38 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1199.38,1200.20 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1228.3,1229.22 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1200.20,1201.51 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1205.4,1205.51 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1209.4,1210.34 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1201.51,1204.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1205.51,1208.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1212.9,1212.26 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1212.26,1213.50 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1217.4,1217.72 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1213.50,1216.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1218.9,1218.25 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1218.25,1219.52 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1223.4,1223.52 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1219.52,1222.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1223.52,1226.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1234.61,1236.37 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1267.2,1267.47 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1236.37,1237.20 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1264.3,1265.22 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:1237.20,1238.51 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1242.4,1244.51 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1238.51,1241.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1244.51,1247.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1249.9,1249.26 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1249.26,1250.50 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1250.50,1253.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1254.9,1254.25 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1254.25,1255.52 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1259.4,1259.52 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1255.52,1258.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1259.52,1262.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1267.47,1270.3 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1274.61,1276.23 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1276.23,1279.3 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:1283.69,1286.2 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1289.69,1293.56 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1303.2,1304.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1317.2,1317.12 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1293.56,1294.43 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1294.43,1297.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1298.8,1301.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1304.16,1306.58 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1306.58,1310.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1311.8,1316.3 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1321.69,1325.56 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1334.2,1334.28 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1339.2,1340.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1352.2,1352.47 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1355.2,1355.12 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1325.56,1326.43 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1326.43,1329.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1330.8,1333.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1334.28,1337.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1340.16,1341.58 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1341.58,1345.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1346.8,1351.3 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1352.47,1354.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1359.61,1360.49 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1365.2,1365.49 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1360.49,1363.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1365.49,1368.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1374.69,1376.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1380.2,1381.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1386.2,1386.12 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1376.16,1378.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1381.16,1384.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1389.88,1391.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1394.2,1395.12 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1391.16,1393.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1401.69,1403.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1406.2,1407.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1417.2,1417.12 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1403.16,1405.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1407.16,1410.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1420.90,1422.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1425.2,1426.12 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1422.16,1424.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1440.68,1443.56 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1453.2,1454.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1463.2,1463.12 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1443.56,1444.43 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1444.43,1447.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1448.8,1451.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1454.16,1456.58 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1456.58,1458.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1459.8,1462.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1469.68,1471.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1474.2,1475.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1478.2,1479.12 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1471.16,1473.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1475.16,1477.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1483.70,1489.56 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:1499.2,1499.55 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1509.2,1509.12 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1489.56,1490.43 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1490.43,1493.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1494.8,1497.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1499.55,1502.58 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1502.58,1504.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1505.8,1508.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1513.70,1518.56 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:1528.2,1529.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1537.2,1537.12 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1518.56,1519.43 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1519.43,1522.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1523.8,1526.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1529.16,1530.58 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1530.58,1532.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1533.8,1536.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1543.70,1546.16 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1549.2,1550.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1553.2,1554.12 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1546.16,1548.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1550.16,1552.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1560.70,1563.16 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1566.2,1567.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1570.2,1571.12 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1563.16,1565.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1567.16,1569.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1575.67,1576.42 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1612.2,1612.12 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1576.42,1577.33 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1581.3,1582.17 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1589.3,1590.17 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1609.3,1610.22 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1577.33,1580.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1582.17,1585.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1585.9,1585.54 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1585.54,1588.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1590.17,1591.39 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1602.4,1602.95 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1591.39,1592.65 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1592.65,1600.6 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1602.95,1604.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1605.9,1608.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1618.67,1619.41 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:1637.2,1637.12 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1619.41,1621.17 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:1625.3,1626.17 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:1634.3,1635.22 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1621.17,1624.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1626.17,1627.65 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1627.65,1629.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1630.9,1633.4 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:1644.67,1652.36 6 0
+voltha-go-controller/internal/pkg/application/vnets.go:1662.2,1666.16 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:1670.2,1677.55 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:1692.2,1693.26 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1696.2,1696.36 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1701.2,1706.18 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:1652.36,1657.3 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:1657.8,1661.3 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1666.16,1669.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1677.55,1680.37 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1685.3,1687.15 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1680.37,1682.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1682.9,1684.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1693.26,1695.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1696.36,1699.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1710.67,1717.36 6 0
+voltha-go-controller/internal/pkg/application/vnets.go:1720.2,1725.16 6 0
+voltha-go-controller/internal/pkg/application/vnets.go:1728.2,1729.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1732.2,1739.26 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:1742.2,1742.36 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1747.2,1754.18 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:1717.36,1719.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1725.16,1727.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1729.16,1731.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1739.26,1741.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1742.36,1746.3 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1759.68,1773.16 12 0
+voltha-go-controller/internal/pkg/application/vnets.go:1777.2,1777.55 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1784.2,1792.26 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:1795.2,1804.18 8 0
+voltha-go-controller/internal/pkg/application/vnets.go:1773.16,1775.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1777.55,1783.3 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:1792.26,1794.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1809.68,1823.16 12 0
+voltha-go-controller/internal/pkg/application/vnets.go:1826.2,1827.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1830.2,1837.26 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:1840.2,1849.18 8 0
+voltha-go-controller/internal/pkg/application/vnets.go:1823.16,1825.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1827.16,1829.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1837.26,1839.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1856.66,1864.74 6 0
+voltha-go-controller/internal/pkg/application/vnets.go:1868.2,1869.52 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1872.2,1874.16 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1877.2,1883.26 6 0
+voltha-go-controller/internal/pkg/application/vnets.go:1886.2,1895.18 9 0
+voltha-go-controller/internal/pkg/application/vnets.go:1864.74,1866.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1869.52,1871.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1874.16,1876.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1883.26,1885.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1899.69,1900.25 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1917.2,1917.12 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1901.12,1902.31 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1903.24,1904.31 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1905.24,1906.33 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1908.16,1909.31 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1910.16,1911.33 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1913.10,1915.45 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1921.68,1928.74 6 0
+voltha-go-controller/internal/pkg/application/vnets.go:1932.2,1932.52 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1935.2,1937.16 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1940.2,1947.26 6 0
+voltha-go-controller/internal/pkg/application/vnets.go:1950.2,1962.18 9 0
+voltha-go-controller/internal/pkg/application/vnets.go:1928.74,1930.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1932.52,1934.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1937.16,1939.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1947.26,1949.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1966.68,1976.36 8 0
+voltha-go-controller/internal/pkg/application/vnets.go:1980.2,1982.16 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:1985.2,1986.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:1989.2,1996.26 7 0
+voltha-go-controller/internal/pkg/application/vnets.go:1999.2,2008.18 8 0
+voltha-go-controller/internal/pkg/application/vnets.go:1976.36,1978.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1982.16,1984.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1986.16,1988.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:1996.26,1998.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2012.63,2013.25 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2014.12,2015.31 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2019.12,2020.31 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2021.10,2022.90 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2028.65,2031.16 3 1
+voltha-go-controller/internal/pkg/application/vnets.go:2034.2,2044.16 9 0
+voltha-go-controller/internal/pkg/application/vnets.go:2047.2,2052.74 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2055.2,2058.22 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2075.2,2076.26 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2079.2,2089.18 9 0
+voltha-go-controller/internal/pkg/application/vnets.go:2031.16,2033.3 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:2044.16,2046.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2052.74,2054.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2058.22,2064.3 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:2064.8,2066.56 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2066.56,2072.4 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:2076.26,2078.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2093.58,2094.26 1 4
+voltha-go-controller/internal/pkg/application/vnets.go:2098.2,2098.26 1 4
+voltha-go-controller/internal/pkg/application/vnets.go:2094.26,2097.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2102.63,2106.45 4 4
+voltha-go-controller/internal/pkg/application/vnets.go:2106.45,2107.121 1 4
+voltha-go-controller/internal/pkg/application/vnets.go:2107.121,2110.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2115.58,2118.2 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2121.69,2123.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2126.65,2136.2 7 0
+voltha-go-controller/internal/pkg/application/vnets.go:2139.71,2141.48 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2141.48,2143.10 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2147.3,2152.58 6 0
+voltha-go-controller/internal/pkg/application/vnets.go:2156.3,2156.27 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2160.3,2160.140 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2143.10,2146.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2152.58,2154.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2156.27,2159.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2165.68,2168.30 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2168.30,2170.10 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2174.3,2174.34 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2170.10,2172.12 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2182.128,2183.45 1 6
+voltha-go-controller/internal/pkg/application/vnets.go:2186.2,2187.45 2 4
+voltha-go-controller/internal/pkg/application/vnets.go:2192.2,2192.12 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2183.45,2185.3 1 2
+voltha-go-controller/internal/pkg/application/vnets.go:2187.45,2188.46 1 4
+voltha-go-controller/internal/pkg/application/vnets.go:2188.46,2190.4 1 4
+voltha-go-controller/internal/pkg/application/vnets.go:2196.125,2203.45 6 0
+voltha-go-controller/internal/pkg/application/vnets.go:2206.2,2218.21 9 0
+voltha-go-controller/internal/pkg/application/vnets.go:2230.2,2231.16 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2241.2,2242.12 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2203.45,2205.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2218.21,2222.17 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2225.3,2226.13 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2222.17,2224.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2231.16,2234.15 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2234.15,2236.69 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2236.69,2238.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2246.98,2258.9 5 1
+voltha-go-controller/internal/pkg/application/vnets.go:2261.2,2262.28 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2258.9,2260.3 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:2262.28,2263.18 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2263.18,2277.39 10 0
+voltha-go-controller/internal/pkg/application/vnets.go:2280.4,2280.59 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2283.4,2284.10 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2277.39,2279.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2280.59,2282.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2290.69,2293.28 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2293.28,2295.10 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2299.3,2301.17 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2305.3,2306.75 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2310.3,2310.28 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2295.10,2297.12 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2301.17,2303.12 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2306.75,2308.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2310.28,2313.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2321.119,2324.9 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:2327.2,2331.23 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:2336.2,2342.9 3 1
+voltha-go-controller/internal/pkg/application/vnets.go:2346.2,2347.47 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:2373.2,2373.12 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:2324.9,2326.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2331.23,2333.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2342.9,2345.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2347.47,2349.27 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:2350.25,2352.50 2 1
+voltha-go-controller/internal/pkg/application/vnets.go:2356.9,2360.96 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2364.13,2366.69 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2369.11,2370.92 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2352.50,2354.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2360.96,2362.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2366.69,2368.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2380.141,2383.9 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2386.2,2390.23 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2395.2,2399.48 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2426.2,2426.17 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2383.9,2385.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2390.23,2392.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2399.48,2401.48 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2401.48,2403.28 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2404.26,2406.51 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2410.10,2412.95 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2416.14,2418.97 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2421.12,2422.93 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2406.51,2408.6 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2412.95,2414.6 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2418.97,2420.6 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2433.122,2437.2 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2440.85,2442.60 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2500.2,2500.32 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2442.60,2444.58 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2448.3,2448.47 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2452.3,2452.92 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2457.3,2457.106 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2464.3,2466.17 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2470.3,2470.62 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2498.3,2498.14 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2444.58,2447.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2448.47,2451.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2452.92,2455.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2457.106,2463.4 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:2466.17,2469.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2470.62,2471.111 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2477.4,2479.18 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2483.4,2488.18 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2492.4,2496.89 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2471.111,2474.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2479.18,2482.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2488.18,2491.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2504.91,2509.16 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2513.2,2513.50 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2551.2,2551.34 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2509.16,2512.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2513.50,2515.106 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2522.3,2523.17 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2526.3,2526.92 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2530.3,2532.17 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2536.3,2540.17 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2544.3,2549.14 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:2515.106,2521.4 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:2523.17,2525.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2526.92,2529.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2532.17,2535.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2540.17,2543.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2555.87,2557.60 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2598.2,2598.32 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2557.60,2560.106 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2569.3,2569.62 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2596.3,2596.14 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2560.106,2564.30 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2564.30,2567.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2569.62,2570.111 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2575.4,2578.18 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2582.4,2588.18 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:2592.4,2594.82 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2570.111,2573.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2578.18,2581.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2588.18,2591.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2602.93,2604.49 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2642.2,2645.16 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2604.49,2606.106 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2618.3,2619.17 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2622.3,2625.17 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2630.3,2633.17 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2638.3,2640.14 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2606.106,2610.30 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2610.30,2613.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2614.9,2617.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2619.17,2621.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2625.17,2628.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2633.17,2636.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2645.16,2648.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2652.121,2654.60 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2702.2,2702.32 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2654.60,2656.42 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2659.3,2659.106 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2680.3,2680.62 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2700.3,2700.15 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2656.42,2658.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2659.106,2663.30 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2663.30,2666.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2667.9,2667.56 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2667.56,2679.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2680.62,2681.111 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2685.4,2687.63 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2690.4,2694.63 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2697.4,2698.82 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2681.111,2684.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2687.63,2689.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2694.63,2696.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2706.66,2720.30 13 0
+voltha-go-controller/internal/pkg/application/vnets.go:2725.2,2731.13 6 0
+voltha-go-controller/internal/pkg/application/vnets.go:2720.30,2722.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2722.8,2724.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2735.65,2754.30 15 0
+voltha-go-controller/internal/pkg/application/vnets.go:2759.2,2765.13 6 0
+voltha-go-controller/internal/pkg/application/vnets.go:2754.30,2756.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2756.8,2758.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2769.47,2782.56 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2786.2,2786.41 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2782.56,2785.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2790.61,2797.12 7 0
+voltha-go-controller/internal/pkg/application/vnets.go:2815.2,2818.12 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2797.12,2798.27 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2802.3,2804.27 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2798.27,2801.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2805.8,2806.26 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2810.3,2813.54 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2806.26,2809.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2822.84,2823.25 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2838.2,2838.14 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2825.20,2826.47 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2831.8,2832.25 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2835.10,2836.90 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2826.47,2828.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2832.25,2834.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2842.103,2843.36 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2852.2,2852.74 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2843.36,2851.3 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2856.96,2857.58 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2862.2,2863.40 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2857.58,2861.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2867.105,2871.36 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2882.2,2882.74 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2871.36,2881.3 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2886.66,2889.27 3 1
+voltha-go-controller/internal/pkg/application/vnets.go:2892.2,2892.58 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2889.27,2891.3 1 1
+voltha-go-controller/internal/pkg/application/vnets.go:2892.58,2896.3 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2900.96,2908.2 6 1
+voltha-go-controller/internal/pkg/application/vnets.go:2911.132,2916.58 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2921.2,2924.26 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2916.58,2920.3 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2924.26,2928.3 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:2928.8,2931.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2935.100,2942.36 5 0
+voltha-go-controller/internal/pkg/application/vnets.go:2957.2,2958.80 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2942.36,2951.59 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2954.3,2955.46 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2951.59,2953.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2962.77,2963.26 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2966.2,2967.78 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2975.2,2975.27 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2963.26,2965.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2967.78,2972.3 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2972.8,2974.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2979.91,2985.47 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:2990.2,2990.55 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2996.2,2996.20 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2985.47,2987.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:2990.55,2992.57 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:2992.57,2994.4 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3000.127,3004.53 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:3015.2,3015.179 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3004.53,3005.35 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3005.35,3008.27 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3012.4,3012.10 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3008.27,3011.5 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3019.100,3023.58 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3031.2,3032.40 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3023.58,3025.22 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3029.3,3029.14 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3025.22,3028.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3036.112,3039.9 3 0
+voltha-go-controller/internal/pkg/application/vnets.go:3042.2,3046.23 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3052.2,3054.9 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3058.2,3059.55 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3071.2,3071.46 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3079.2,3079.16 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3039.9,3041.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3046.23,3048.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3054.9,3057.3 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3059.55,3061.22 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3068.3,3068.14 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3061.22,3067.4 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3071.46,3072.25 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3072.25,3074.22 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3074.22,3075.10 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3083.91,3088.30 4 0
+voltha-go-controller/internal/pkg/application/vnets.go:3091.2,3093.26 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3097.2,3097.36 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3110.2,3110.13 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3088.30,3090.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3093.26,3095.3 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3097.36,3098.58 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3098.58,3105.57 7 0
+voltha-go-controller/internal/pkg/application/vnets.go:3105.57,3107.5 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3114.51,3124.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3127.56,3173.2 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3175.72,3177.55 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3186.2,3186.20 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3177.55,3179.22 2 0
+voltha-go-controller/internal/pkg/application/vnets.go:3184.3,3184.14 1 0
+voltha-go-controller/internal/pkg/application/vnets.go:3179.22,3183.4 3 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:42.31,48.12 3 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:48.12,49.7 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:49.7,50.11 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:51.16,53.11 2 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:54.20,57.17 3 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:64.25,66.44 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:66.44,68.29 2 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:90.3,90.33 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:68.29,70.78 2 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:79.4,82.44 2 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:70.78,73.5 2 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:82.44,86.13 3 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:95.58,102.61 6 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:110.2,110.25 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:114.2,115.14 2 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:102.61,105.3 2 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:110.25,112.3 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:119.46,126.61 6 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:133.2,133.33 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:139.2,142.42 3 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:147.2,147.14 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:126.61,130.3 3 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:133.33,136.3 2 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:142.42,144.3 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:144.8,146.3 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:151.30,153.2 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:161.56,166.2 4 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:177.75,182.2 4 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:184.49,186.2 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:188.55,191.2 2 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:193.64,195.2 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:197.63,199.2 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:201.66,203.2 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:205.51,208.2 2 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:210.71,211.55 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:214.2,216.18 3 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:211.55,213.3 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:225.51,227.2 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:230.60,231.37 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:236.2,236.14 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:231.37,232.20 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:232.20,234.4 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:240.54,241.31 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:241.31,242.30 1 0
+voltha-go-controller/internal/pkg/application/dhcpserverhandler.go:242.30,244.9 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:53.61,60.2 6 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:63.80,72.28 9 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:72.28,74.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:74.8,76.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:80.85,84.28 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:90.2,90.33 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:84.28,86.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:86.8,88.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:90.33,92.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:96.81,97.29 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:101.2,103.33 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:106.2,106.43 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:109.2,109.29 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:97.29,100.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:103.33,105.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:106.43,108.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:109.29,111.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:115.100,118.20 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:118.20,120.34 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:120.34,122.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:123.8,127.33 4 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:130.3,130.66 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:137.3,141.36 5 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:165.3,165.31 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:127.33,129.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:130.66,132.114 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:132.114,135.5 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:141.36,142.44 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:145.4,148.35 4 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:161.4,163.104 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:142.44,143.13 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:148.35,149.20 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:156.5,159.6 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:149.20,152.6 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:152.11,155.6 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:171.121,175.44 4 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:178.2,178.12 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:175.44,177.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:183.85,187.29 4 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:190.2,193.61 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:209.2,211.107 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:215.2,215.25 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:187.29,189.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:193.61,196.26 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:206.3,207.14 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:196.26,201.40 4 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:201.40,203.5 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:211.107,214.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:215.25,218.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:224.88,226.57 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:226.57,229.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:229.8,232.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:235.103,239.51 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:246.2,247.16 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:239.51,242.44 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:242.44,244.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:252.111,259.9 6 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:263.2,265.8 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:268.2,271.36 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:276.2,276.29 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:259.9,262.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:265.8,267.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:271.36,274.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:276.29,278.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:283.153,285.39 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:285.39,288.30 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:288.30,290.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:295.84,296.20 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:300.2,302.66 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:307.2,309.20 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:296.20,298.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:302.66,306.3 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:313.60,315.33 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:323.2,323.20 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:315.33,316.67 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:321.3,321.42 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:316.67,320.4 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:327.120,329.20 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:335.2,337.29 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:340.2,340.18 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:329.20,330.34 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:333.3,333.13 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:330.34,332.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:337.29,339.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:345.85,346.15 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:350.2,352.36 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:358.2,358.63 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:367.2,367.13 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:346.15,349.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:352.36,357.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:358.63,362.35 4 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:362.35,365.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:371.49,373.33 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:373.33,376.66 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:380.3,380.35 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:396.3,396.37 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:409.3,411.23 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:376.66,378.12 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:380.35,388.77 6 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:394.4,394.52 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:388.77,393.5 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:396.37,403.31 5 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:403.31,405.13 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:411.23,412.46 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:412.46,415.5 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:424.56,425.33 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:425.33,426.65 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:426.65,428.31 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:428.31,430.5 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:431.9,433.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:441.36,444.16 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:448.2,453.43 4 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:456.2,457.51 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:444.16,446.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:453.43,455.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:464.42,466.2 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:472.45,474.33 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:480.2,480.14 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:474.33,475.52 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:478.3,478.10 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:475.52,476.12 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:484.52,486.38 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:489.2,489.21 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:486.38,488.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:493.59,496.33 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:496.33,498.10 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:502.3,502.61 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:498.10,500.12 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:502.61,507.23 4 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:512.4,518.38 4 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:528.4,529.30 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:535.4,536.70 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:507.23,510.5 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:518.38,522.47 4 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:522.47,525.6 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:529.30,532.5 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:532.10,534.5 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:537.9,539.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:544.38,546.8 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:550.2,550.11 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:546.8,549.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:554.60,557.16 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:560.2,560.72 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:563.2,563.12 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:557.16,559.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:560.72,562.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:567.83,570.22 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:573.2,579.43 5 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:570.22,572.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:579.43,581.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:584.73,588.54 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:588.54,593.31 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:600.3,600.33 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:606.3,606.31 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:593.31,594.12 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:600.33,602.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:606.31,608.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:613.81,623.29 7 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:628.2,628.43 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:623.29,627.3 3 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:628.43,630.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:634.57,636.33 2 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:639.2,639.41 1 0
+voltha-go-controller/internal/pkg/application/igmpgroup.go:636.33,638.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:99.164,114.48 14 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:117.2,117.13 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:114.48,116.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:121.91,126.35 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:131.2,131.46 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:134.2,134.25 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:126.35,128.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:128.8,130.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:131.46,133.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:138.67,144.36 6 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:149.2,149.24 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:144.36,146.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:146.8,148.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:153.55,154.26 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:157.2,157.18 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:154.26,156.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:161.64,162.26 1 1
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:167.2,169.16 3 1
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:172.2,172.74 1 1
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:175.2,175.12 1 1
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:162.26,165.3 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:169.16,171.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:172.74,174.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:179.63,180.33 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:187.2,187.14 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:180.33,181.19 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:181.19,182.75 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:182.75,184.5 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:191.56,192.33 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:197.2,197.14 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:192.33,193.42 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:193.42,195.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:201.66,204.33 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:210.2,210.26 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:213.2,213.36 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:204.33,205.19 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:205.19,208.4 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:210.26,212.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:217.74,220.36 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:226.2,226.26 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:229.2,229.36 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:220.36,221.19 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:221.19,224.4 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:226.26,228.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:233.58,236.39 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:240.2,241.51 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:254.2,254.26 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:236.39,238.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:241.51,242.44 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:242.44,247.38 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:247.38,249.5 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:250.9,252.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:258.83,259.21 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:264.2,264.36 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:259.21,262.3 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:264.36,266.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:270.52,271.36 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:276.2,276.14 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:271.36,272.48 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:272.48,274.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:280.74,281.57 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:286.2,286.14 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:281.57,282.56 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:282.56,284.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:290.58,292.2 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:295.102,302.36 5 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:318.2,318.44 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:321.2,321.80 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:302.36,312.60 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:315.3,316.47 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:312.60,314.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:318.44,320.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:325.96,331.48 4 1
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:335.2,335.44 1 1
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:331.48,333.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:335.44,337.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:341.110,345.54 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:351.2,351.184 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:345.54,346.35 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:346.35,349.4 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:355.63,357.2 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:360.78,361.29 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:364.2,364.40 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:361.29,363.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:368.64,369.33 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:376.2,376.11 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:369.33,370.19 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:370.19,371.35 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:371.35,373.5 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:380.68,385.8 5 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:389.2,389.12 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:385.8,388.3 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:393.88,397.42 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:402.2,403.14 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:408.2,410.40 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:397.42,400.3 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:403.14,406.3 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:410.40,415.17 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:421.3,421.80 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:415.17,418.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:421.80,423.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:423.9,425.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:430.90,434.74 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:434.74,436.15 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:436.15,443.81 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:450.4,450.72 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:463.4,464.18 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:443.81,445.5 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:445.10,447.5 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:450.72,452.30 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:459.5,459.16 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:452.30,455.36 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:455.36,457.7 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:464.18,466.5 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:472.91,475.9 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:478.2,482.32 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:498.2,498.12 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:475.9,477.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:482.32,484.17 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:484.17,486.18 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:490.4,492.55 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:486.18,489.5 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:493.9,495.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:502.92,507.9 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:510.2,516.16 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:531.2,531.12 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:507.9,509.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:516.16,520.17 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:524.3,526.54 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:520.17,523.4 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:527.8,529.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:535.80,537.9 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:540.2,550.16 9 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:553.2,554.17 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:557.2,565.18 8 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:537.9,539.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:550.16,552.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:554.17,556.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:569.118,571.64 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:585.2,585.20 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:571.64,574.42 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:579.3,582.14 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:574.42,577.4 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:585.20,588.3 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:588.8,590.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:594.119,598.64 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:651.2,651.20 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:598.64,601.42 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:605.3,605.35 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:648.3,648.14 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:601.42,604.4 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:605.35,609.52 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:609.52,611.59 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:611.59,612.71 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:612.71,617.48 5 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:623.7,623.47 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:636.7,636.24 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:640.7,640.49 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:617.48,618.59 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:621.8,621.48 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:618.59,620.9 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:623.47,625.73 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:628.8,630.88 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:625.73,627.9 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:630.88,632.9 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:636.24,639.8 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:640.49,642.8 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:651.20,654.3 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:654.8,656.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:661.79,662.74 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:724.2,724.59 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:662.74,665.28 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:668.3,671.69 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:719.3,722.14 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:665.28,667.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:671.69,672.31 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:672.31,674.60 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:674.60,676.6 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:677.10,679.46 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:712.5,713.46 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:716.5,716.16 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:679.46,682.24 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:682.24,694.118 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:694.118,696.8 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:696.13,697.65 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:702.8,702.16 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:697.65,698.62 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:698.62,700.10 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:704.12,707.37 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:707.37,709.8 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:713.46,715.6 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:728.113,731.80 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:737.2,737.14 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:731.80,733.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:733.8,733.26 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:733.26,735.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:741.58,743.34 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:750.2,750.33 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:758.2,758.11 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:743.34,745.20 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:745.20,747.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:750.33,751.19 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:754.3,754.33 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:751.19,753.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:754.33,756.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:762.120,769.43 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:769.43,771.13 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:771.13,776.17 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:776.17,779.89 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:779.89,784.6 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:784.11,786.6 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:787.10,789.41 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:793.5,797.30 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:789.41,791.6 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:799.9,799.23 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:799.23,802.30 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:817.4,817.34 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:802.30,804.22 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:804.22,809.6 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:809.11,811.6 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:812.10,816.5 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:817.34,819.5 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:820.9,822.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:827.106,831.35 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:834.2,834.67 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:849.2,849.60 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:831.35,833.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:834.67,835.75 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:835.75,840.38 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:840.38,845.10 5 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:853.147,857.35 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:860.2,860.67 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:875.2,875.60 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:857.35,859.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:860.67,861.75 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:861.75,866.38 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:866.38,871.10 5 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:879.79,888.20 7 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:902.2,902.34 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:910.2,911.34 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:916.2,916.30 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:929.2,931.49 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:934.2,934.44 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:937.2,937.117 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:888.20,889.60 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:889.60,891.53 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:891.53,894.5 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:895.9,898.4 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:902.34,906.69 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:906.69,908.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:911.34,913.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:916.30,918.72 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:918.72,919.32 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:919.32,922.5 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:922.10,925.5 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:931.49,933.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:934.44,936.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:941.106,942.40 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:945.2,946.40 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:950.2,950.36 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:954.2,958.18 5 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:962.2,965.28 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:983.2,985.28 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1002.2,1002.14 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:942.40,944.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:946.40,948.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:950.36,952.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:958.18,960.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:965.28,968.29 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:978.3,978.13 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:968.29,969.18 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:972.4,972.35 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:969.18,970.13 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:972.35,975.10 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:978.13,980.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:985.28,988.29 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:998.3,998.13 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:988.29,989.18 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:992.4,992.35 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:989.18,990.13 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:992.35,995.10 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:998.13,1000.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1006.63,1009.36 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1009.36,1011.15 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1015.3,1015.51 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1011.15,1014.4 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1015.51,1018.37 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1021.4,1021.80 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1032.4,1032.15 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1018.37,1020.5 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1021.80,1025.5 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1025.10,1025.88 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1025.88,1031.5 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1038.96,1044.30 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1047.2,1049.26 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1053.2,1053.36 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1067.2,1067.13 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1044.30,1046.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1049.26,1051.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1053.36,1054.58 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1054.58,1062.18 8 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1062.18,1064.5 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1071.56,1087.2 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1090.58,1092.29 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1097.2,1097.17 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1101.2,1101.10 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1092.29,1093.24 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1093.24,1094.9 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1097.17,1100.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1105.55,1106.39 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1122.2,1122.14 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1106.39,1107.39 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1107.39,1111.23 4 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1114.4,1115.42 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1111.23,1113.5 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1115.42,1117.5 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1118.9,1118.46 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1118.46,1120.4 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1144.72,1153.46 6 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1157.2,1168.91 10 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1173.2,1175.21 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1153.46,1156.3 2 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1168.91,1170.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1170.8,1172.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1179.43,1196.2 1 1
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1199.71,1202.16 3 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1205.2,1205.84 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1208.2,1208.12 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1202.16,1204.3 1 0
+voltha-go-controller/internal/pkg/application/igmpprofiles.go:1205.84,1207.3 1 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:48.30,50.2 1 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:53.35,55.2 1 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:58.36,60.2 1 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:63.40,65.2 1 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:68.29,69.2 0 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:72.68,77.2 4 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:95.89,102.2 6 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:105.41,107.2 1 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:110.42,112.2 1 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:115.46,117.2 1 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:120.35,121.2 0 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:124.74,129.2 4 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:141.78,147.2 5 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:150.42,152.2 1 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:155.43,157.2 1 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:160.47,162.2 1 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:165.36,166.2 0 0
+voltha-go-controller/internal/pkg/application/igmptasks.go:169.75,175.2 5 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:82.64,84.16 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:87.2,87.63 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:90.2,90.12 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:84.16,86.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:87.63,89.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:94.58,95.50 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:95.50,97.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:101.74,104.15 3 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:107.2,107.64 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:110.2,111.16 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:115.2,115.12 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:104.15,106.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:107.64,109.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:111.16,114.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:122.57,128.16 5 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:133.2,133.16 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:176.2,178.14 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:128.16,131.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:133.16,138.48 5 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:142.3,144.15 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:138.48,140.4 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:146.8,146.37 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:146.37,150.56 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:150.56,151.50 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:151.50,154.5 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:156.8,160.56 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:168.3,170.23 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:160.56,161.52 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:161.52,162.24 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:162.24,165.6 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:170.23,172.4 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:183.49,192.12 5 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:214.2,214.15 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:226.2,229.47 3 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:232.2,232.93 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:192.12,195.17 3 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:202.3,208.47 6 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:195.17,198.48 3 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:198.48,200.5 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:208.47,211.4 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:214.15,215.35 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:215.35,218.49 3 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:222.4,222.10 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:218.49,220.5 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:229.47,231.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:236.48,238.65 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:264.2,264.12 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:238.65,239.54 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:244.3,244.40 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:259.3,259.17 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:239.54,241.12 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:244.40,245.18 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:250.33,251.46 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:252.12,253.46 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:255.9,257.4 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:259.17,262.4 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:268.55,271.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:274.71,277.16 3 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:282.2,282.34 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:288.2,288.46 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:312.2,312.12 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:277.16,281.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:282.34,285.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:288.46,292.10 3 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:297.3,299.26 3 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:305.3,307.66 3 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:292.10,295.4 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:299.26,302.4 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:302.9,302.48 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:302.48,304.4 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:307.66,310.4 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:316.64,323.16 6 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:328.2,328.60 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:333.2,333.59 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:338.2,338.34 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:343.2,347.53 5 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:351.2,352.28 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:323.16,326.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:328.60,331.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:333.59,336.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:338.34,340.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:347.53,350.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:356.63,359.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:362.67,365.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:368.67,371.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:374.68,377.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:380.68,383.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:386.70,389.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:392.61,397.16 4 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:402.2,402.25 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:406.2,406.40 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:411.2,413.55 3 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:417.2,418.28 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:397.16,400.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:402.25,404.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:406.40,408.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:408.8,408.49 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:408.49,410.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:413.55,416.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:422.60,430.16 7 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:435.2,435.61 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:440.2,440.60 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:444.2,444.35 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:447.2,447.38 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:451.2,451.38 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:455.2,455.38 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:459.2,459.24 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:462.2,466.54 4 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:470.2,472.28 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:430.16,433.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:435.61,438.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:440.60,442.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:444.35,446.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:447.38,449.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:451.38,453.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:455.38,457.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:459.24,461.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:466.54,469.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:476.62,481.16 4 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:486.2,487.36 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:492.2,492.54 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:496.2,497.28 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:481.16,484.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:487.36,490.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:492.54,495.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:501.62,504.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:507.65,511.16 3 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:515.2,515.52 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:519.2,520.26 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:511.16,514.3 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:515.52,517.3 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:524.66,527.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:530.67,533.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:536.68,539.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:542.65,545.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:548.65,551.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:554.66,557.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:560.65,563.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:566.62,569.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:572.67,575.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:578.71,581.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:584.71,587.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:590.65,593.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:596.42,599.2 2 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:602.67,607.66 3 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:611.2,611.12 1 0
+voltha-go-controller/internal/pkg/application/major_upgrade.go:607.66,610.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:169.55,183.2 12 2
+voltha-go-controller/internal/pkg/application/service.go:186.56,190.25 3 16
+voltha-go-controller/internal/pkg/application/service.go:194.2,194.25 1 16
+voltha-go-controller/internal/pkg/application/service.go:190.25,193.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:198.61,201.16 2 18
+voltha-go-controller/internal/pkg/application/service.go:205.2,205.66 1 18
+voltha-go-controller/internal/pkg/application/service.go:201.16,204.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:205.66,207.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:211.53,213.2 1 1
+voltha-go-controller/internal/pkg/application/service.go:216.56,222.2 3 3
+voltha-go-controller/internal/pkg/application/service.go:227.63,228.21 1 0
+voltha-go-controller/internal/pkg/application/service.go:232.2,232.26 1 0
+voltha-go-controller/internal/pkg/application/service.go:235.2,235.14 1 0
+voltha-go-controller/internal/pkg/application/service.go:228.21,230.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:232.26,234.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:241.63,242.29 1 0
+voltha-go-controller/internal/pkg/application/service.go:249.2,249.14 1 0
+voltha-go-controller/internal/pkg/application/service.go:242.29,243.31 1 0
+voltha-go-controller/internal/pkg/application/service.go:243.31,244.18 1 0
+voltha-go-controller/internal/pkg/application/service.go:244.18,246.5 1 0
+voltha-go-controller/internal/pkg/application/service.go:254.59,255.30 1 10
+voltha-go-controller/internal/pkg/application/service.go:260.2,260.14 1 9
+voltha-go-controller/internal/pkg/application/service.go:255.30,256.17 1 1
+voltha-go-controller/internal/pkg/application/service.go:256.17,258.4 1 1
+voltha-go-controller/internal/pkg/application/service.go:264.59,265.48 1 2
+voltha-go-controller/internal/pkg/application/service.go:269.2,269.48 1 2
+voltha-go-controller/internal/pkg/application/service.go:265.48,268.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:269.48,272.3 2 1
+voltha-go-controller/internal/pkg/application/service.go:276.59,277.48 1 3
+voltha-go-controller/internal/pkg/application/service.go:282.2,282.48 1 3
+voltha-go-controller/internal/pkg/application/service.go:277.48,280.3 2 1
+voltha-go-controller/internal/pkg/application/service.go:282.48,285.3 2 1
+voltha-go-controller/internal/pkg/application/service.go:288.69,289.48 1 3
+voltha-go-controller/internal/pkg/application/service.go:292.2,295.16 4 3
+voltha-go-controller/internal/pkg/application/service.go:302.2,304.12 3 1
+voltha-go-controller/internal/pkg/application/service.go:289.48,291.3 1 3
+voltha-go-controller/internal/pkg/application/service.go:295.16,298.3 2 1
+voltha-go-controller/internal/pkg/application/service.go:298.8,298.53 1 2
+voltha-go-controller/internal/pkg/application/service.go:298.53,301.3 2 1
+voltha-go-controller/internal/pkg/application/service.go:308.67,309.48 1 5
+voltha-go-controller/internal/pkg/application/service.go:314.2,316.43 3 4
+voltha-go-controller/internal/pkg/application/service.go:357.2,358.12 2 2
+voltha-go-controller/internal/pkg/application/service.go:309.48,312.3 2 1
+voltha-go-controller/internal/pkg/application/service.go:316.43,318.17 2 4
+voltha-go-controller/internal/pkg/application/service.go:326.3,328.39 2 2
+voltha-go-controller/internal/pkg/application/service.go:332.3,336.25 3 2
+voltha-go-controller/internal/pkg/application/service.go:339.3,339.31 1 2
+voltha-go-controller/internal/pkg/application/service.go:354.3,355.88 2 2
+voltha-go-controller/internal/pkg/application/service.go:318.17,321.4 2 1
+voltha-go-controller/internal/pkg/application/service.go:321.9,321.54 1 3
+voltha-go-controller/internal/pkg/application/service.go:321.54,324.4 2 1
+voltha-go-controller/internal/pkg/application/service.go:328.39,331.4 2 2
+voltha-go-controller/internal/pkg/application/service.go:336.25,338.4 1 2
+voltha-go-controller/internal/pkg/application/service.go:339.31,341.18 2 2
+voltha-go-controller/internal/pkg/application/service.go:347.4,348.61 2 1
+voltha-go-controller/internal/pkg/application/service.go:341.18,345.13 4 1
+voltha-go-controller/internal/pkg/application/service.go:348.61,352.5 3 1
+voltha-go-controller/internal/pkg/application/service.go:362.67,363.25 1 2
+voltha-go-controller/internal/pkg/application/service.go:368.2,370.43 3 2
+voltha-go-controller/internal/pkg/application/service.go:432.2,433.12 2 1
+voltha-go-controller/internal/pkg/application/service.go:363.25,366.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:370.43,372.17 2 2
+voltha-go-controller/internal/pkg/application/service.go:380.3,384.36 3 2
+voltha-go-controller/internal/pkg/application/service.go:429.3,430.88 2 1
+voltha-go-controller/internal/pkg/application/service.go:372.17,375.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:375.9,375.54 1 2
+voltha-go-controller/internal/pkg/application/service.go:375.54,378.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:384.36,386.18 2 2
+voltha-go-controller/internal/pkg/application/service.go:390.4,391.60 2 1
+voltha-go-controller/internal/pkg/application/service.go:386.18,389.5 2 1
+voltha-go-controller/internal/pkg/application/service.go:391.60,395.5 3 1
+voltha-go-controller/internal/pkg/application/service.go:396.9,398.62 1 0
+voltha-go-controller/internal/pkg/application/service.go:398.62,400.19 2 0
+voltha-go-controller/internal/pkg/application/service.go:404.5,406.62 3 0
+voltha-go-controller/internal/pkg/application/service.go:400.19,403.6 2 0
+voltha-go-controller/internal/pkg/application/service.go:406.62,410.6 3 0
+voltha-go-controller/internal/pkg/application/service.go:411.10,412.48 1 0
+voltha-go-controller/internal/pkg/application/service.go:412.48,414.20 2 0
+voltha-go-controller/internal/pkg/application/service.go:420.6,421.63 2 0
+voltha-go-controller/internal/pkg/application/service.go:414.20,418.15 4 0
+voltha-go-controller/internal/pkg/application/service.go:421.63,425.7 3 0
+voltha-go-controller/internal/pkg/application/service.go:437.67,439.42 2 6
+voltha-go-controller/internal/pkg/application/service.go:469.2,470.12 2 3
+voltha-go-controller/internal/pkg/application/service.go:439.42,441.17 2 5
+voltha-go-controller/internal/pkg/application/service.go:446.3,450.25 3 2
+voltha-go-controller/internal/pkg/application/service.go:453.3,453.31 1 2
+voltha-go-controller/internal/pkg/application/service.go:467.3,467.32 1 2
+voltha-go-controller/internal/pkg/application/service.go:441.17,444.4 2 3
+voltha-go-controller/internal/pkg/application/service.go:450.25,452.4 1 2
+voltha-go-controller/internal/pkg/application/service.go:453.31,455.18 2 2
+voltha-go-controller/internal/pkg/application/service.go:461.4,462.60 2 2
+voltha-go-controller/internal/pkg/application/service.go:455.18,459.13 4 0
+voltha-go-controller/internal/pkg/application/service.go:462.60,465.5 2 2
+voltha-go-controller/internal/pkg/application/service.go:474.67,476.42 2 6
+voltha-go-controller/internal/pkg/application/service.go:526.2,529.12 3 2
+voltha-go-controller/internal/pkg/application/service.go:476.42,478.17 2 5
+voltha-go-controller/internal/pkg/application/service.go:483.3,486.36 3 2
+voltha-go-controller/internal/pkg/application/service.go:524.3,524.32 1 1
+voltha-go-controller/internal/pkg/application/service.go:478.17,481.4 2 3
+voltha-go-controller/internal/pkg/application/service.go:486.36,488.18 2 2
+voltha-go-controller/internal/pkg/application/service.go:492.4,493.60 2 1
+voltha-go-controller/internal/pkg/application/service.go:488.18,491.5 2 1
+voltha-go-controller/internal/pkg/application/service.go:493.60,496.5 2 1
+voltha-go-controller/internal/pkg/application/service.go:497.9,497.65 1 0
+voltha-go-controller/internal/pkg/application/service.go:497.65,499.18 2 0
+voltha-go-controller/internal/pkg/application/service.go:503.4,504.60 2 0
+voltha-go-controller/internal/pkg/application/service.go:499.18,502.5 2 0
+voltha-go-controller/internal/pkg/application/service.go:504.60,507.5 2 0
+voltha-go-controller/internal/pkg/application/service.go:508.9,509.46 1 0
+voltha-go-controller/internal/pkg/application/service.go:509.46,511.19 2 0
+voltha-go-controller/internal/pkg/application/service.go:517.5,518.61 2 0
+voltha-go-controller/internal/pkg/application/service.go:511.19,515.14 4 0
+voltha-go-controller/internal/pkg/application/service.go:518.61,521.6 2 0
+voltha-go-controller/internal/pkg/application/service.go:534.82,540.16 4 4
+voltha-go-controller/internal/pkg/application/service.go:543.2,549.25 6 4
+voltha-go-controller/internal/pkg/application/service.go:554.2,557.71 3 4
+voltha-go-controller/internal/pkg/application/service.go:565.2,566.16 2 4
+voltha-go-controller/internal/pkg/application/service.go:712.2,712.18 1 2
+voltha-go-controller/internal/pkg/application/service.go:540.16,542.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:549.25,551.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:557.71,563.3 4 4
+voltha-go-controller/internal/pkg/application/service.go:566.16,569.3 2 2
+voltha-go-controller/internal/pkg/application/service.go:572.2,578.29 5 2
+voltha-go-controller/internal/pkg/application/service.go:581.3,581.57 1 2
+voltha-go-controller/internal/pkg/application/service.go:589.3,589.61 1 2
+voltha-go-controller/internal/pkg/application/service.go:592.3,593.36 2 2
+voltha-go-controller/internal/pkg/application/service.go:596.3,603.46 4 2
+voltha-go-controller/internal/pkg/application/service.go:606.3,619.46 2 2
+voltha-go-controller/internal/pkg/application/service.go:632.3,632.41 1 2
+voltha-go-controller/internal/pkg/application/service.go:647.3,649.25 2 2
+voltha-go-controller/internal/pkg/application/service.go:578.29,580.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:581.57,587.4 3 0
+voltha-go-controller/internal/pkg/application/service.go:589.61,591.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:593.36,595.4 1 2
+voltha-go-controller/internal/pkg/application/service.go:603.46,605.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:619.46,622.4 2 2
+voltha-go-controller/internal/pkg/application/service.go:632.41,639.19 2 0
+voltha-go-controller/internal/pkg/application/service.go:639.19,641.5 1 0
+voltha-go-controller/internal/pkg/application/service.go:642.9,645.4 1 2
+voltha-go-controller/internal/pkg/application/service.go:653.2,657.36 4 2
+voltha-go-controller/internal/pkg/application/service.go:661.3,661.61 1 2
+voltha-go-controller/internal/pkg/application/service.go:664.3,664.29 1 2
+voltha-go-controller/internal/pkg/application/service.go:668.3,668.57 1 2
+voltha-go-controller/internal/pkg/application/service.go:672.3,677.46 4 2
+voltha-go-controller/internal/pkg/application/service.go:680.3,683.29 2 2
+voltha-go-controller/internal/pkg/application/service.go:689.3,691.41 2 2
+voltha-go-controller/internal/pkg/application/service.go:706.3,709.25 3 2
+voltha-go-controller/internal/pkg/application/service.go:657.36,659.4 1 2
+voltha-go-controller/internal/pkg/application/service.go:661.61,663.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:664.29,666.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:668.57,670.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:677.46,679.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:683.29,685.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:685.9,688.4 1 2
+voltha-go-controller/internal/pkg/application/service.go:691.41,698.19 2 0
+voltha-go-controller/internal/pkg/application/service.go:698.19,700.5 1 0
+voltha-go-controller/internal/pkg/application/service.go:701.9,704.4 1 2
+voltha-go-controller/internal/pkg/application/service.go:717.82,723.16 4 4
+voltha-go-controller/internal/pkg/application/service.go:726.2,733.2 5 4
+voltha-go-controller/internal/pkg/application/service.go:822.2,822.18 1 3
+voltha-go-controller/internal/pkg/application/service.go:723.16,725.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:733.2,739.39 5 4
+voltha-go-controller/internal/pkg/application/service.go:745.3,745.61 1 4
+voltha-go-controller/internal/pkg/application/service.go:748.3,755.46 3 3
+voltha-go-controller/internal/pkg/application/service.go:758.3,760.41 2 3
+voltha-go-controller/internal/pkg/application/service.go:774.3,776.118 3 3
+voltha-go-controller/internal/pkg/application/service.go:739.39,742.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:742.9,742.46 1 4
+voltha-go-controller/internal/pkg/application/service.go:742.46,744.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:745.61,747.4 1 1
+voltha-go-controller/internal/pkg/application/service.go:755.46,757.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:760.41,767.19 2 0
+voltha-go-controller/internal/pkg/application/service.go:767.19,769.5 1 0
+voltha-go-controller/internal/pkg/application/service.go:770.9,773.4 1 3
+voltha-go-controller/internal/pkg/application/service.go:780.2,785.61 4 3
+voltha-go-controller/internal/pkg/application/service.go:788.3,788.39 1 3
+voltha-go-controller/internal/pkg/application/service.go:791.3,797.46 5 3
+voltha-go-controller/internal/pkg/application/service.go:800.3,802.41 2 3
+voltha-go-controller/internal/pkg/application/service.go:816.3,819.118 3 3
+voltha-go-controller/internal/pkg/application/service.go:785.61,787.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:788.39,790.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:797.46,799.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:802.41,809.19 2 0
+voltha-go-controller/internal/pkg/application/service.go:809.19,811.5 1 0
+voltha-go-controller/internal/pkg/application/service.go:812.9,815.4 1 3
+voltha-go-controller/internal/pkg/application/service.go:825.119,831.2 4 6
+voltha-go-controller/internal/pkg/application/service.go:835.75,836.24 1 3
+voltha-go-controller/internal/pkg/application/service.go:862.2,862.12 1 3
+voltha-go-controller/internal/pkg/application/service.go:837.12,838.30 1 3
+voltha-go-controller/internal/pkg/application/service.go:839.24,841.43 2 0
+voltha-go-controller/internal/pkg/application/service.go:842.24,845.43 3 0
+voltha-go-controller/internal/pkg/application/service.go:846.16,847.30 1 0
+voltha-go-controller/internal/pkg/application/service.go:848.16,849.60 1 0
+voltha-go-controller/internal/pkg/application/service.go:858.10,860.45 2 0
+voltha-go-controller/internal/pkg/application/service.go:849.60,852.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:852.9,852.39 1 0
+voltha-go-controller/internal/pkg/application/service.go:852.39,855.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:855.9,857.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:867.75,868.24 1 2
+voltha-go-controller/internal/pkg/application/service.go:891.2,891.12 1 2
+voltha-go-controller/internal/pkg/application/service.go:869.12,870.30 1 2
+voltha-go-controller/internal/pkg/application/service.go:871.24,873.20 2 0
+voltha-go-controller/internal/pkg/application/service.go:874.24,877.30 3 0
+voltha-go-controller/internal/pkg/application/service.go:878.16,879.30 1 0
+voltha-go-controller/internal/pkg/application/service.go:880.16,882.60 2 0
+voltha-go-controller/internal/pkg/application/service.go:887.10,889.45 2 0
+voltha-go-controller/internal/pkg/application/service.go:882.60,884.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:884.9,886.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:896.75,897.24 1 4
+voltha-go-controller/internal/pkg/application/service.go:922.2,922.12 1 3
+voltha-go-controller/internal/pkg/application/service.go:898.12,899.30 1 3
+voltha-go-controller/internal/pkg/application/service.go:900.24,901.32 1 0
+voltha-go-controller/internal/pkg/application/service.go:907.24,908.32 1 0
+voltha-go-controller/internal/pkg/application/service.go:909.16,910.32 1 0
+voltha-go-controller/internal/pkg/application/service.go:916.16,917.32 1 0
+voltha-go-controller/internal/pkg/application/service.go:918.10,920.45 2 1
+voltha-go-controller/internal/pkg/application/service.go:901.32,904.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:904.9,906.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:910.32,913.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:913.9,915.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:927.75,928.24 1 2
+voltha-go-controller/internal/pkg/application/service.go:953.2,953.12 1 2
+voltha-go-controller/internal/pkg/application/service.go:929.12,930.30 1 2
+voltha-go-controller/internal/pkg/application/service.go:931.24,933.32 2 0
+voltha-go-controller/internal/pkg/application/service.go:938.24,939.32 1 0
+voltha-go-controller/internal/pkg/application/service.go:940.16,942.32 2 0
+voltha-go-controller/internal/pkg/application/service.go:947.16,948.32 1 0
+voltha-go-controller/internal/pkg/application/service.go:949.10,951.45 2 0
+voltha-go-controller/internal/pkg/application/service.go:933.32,935.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:935.9,937.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:942.32,944.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:944.9,946.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:957.55,959.2 1 1
+voltha-go-controller/internal/pkg/application/service.go:962.57,964.2 1 1
+voltha-go-controller/internal/pkg/application/service.go:967.49,969.2 1 0
+voltha-go-controller/internal/pkg/application/service.go:972.49,974.2 1 0
+voltha-go-controller/internal/pkg/application/service.go:977.58,979.2 1 0
+voltha-go-controller/internal/pkg/application/service.go:995.110,1003.17 3 2
+voltha-go-controller/internal/pkg/application/service.go:1010.2,1013.17 3 2
+voltha-go-controller/internal/pkg/application/service.go:1031.2,1034.61 2 2
+voltha-go-controller/internal/pkg/application/service.go:1051.2,1051.61 1 1
+voltha-go-controller/internal/pkg/application/service.go:1058.2,1063.17 4 1
+voltha-go-controller/internal/pkg/application/service.go:1077.2,1078.16 2 1
+voltha-go-controller/internal/pkg/application/service.go:1082.2,1087.17 4 1
+voltha-go-controller/internal/pkg/application/service.go:1104.2,1105.12 2 1
+voltha-go-controller/internal/pkg/application/service.go:1003.17,1004.49 1 0
+voltha-go-controller/internal/pkg/application/service.go:1004.49,1007.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:1013.17,1024.3 10 2
+voltha-go-controller/internal/pkg/application/service.go:1024.8,1026.44 1 0
+voltha-go-controller/internal/pkg/application/service.go:1029.3,1029.67 1 0
+voltha-go-controller/internal/pkg/application/service.go:1026.44,1028.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:1034.61,1036.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1036.8,1038.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1051.61,1053.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1053.8,1055.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1063.17,1064.86 1 1
+voltha-go-controller/internal/pkg/application/service.go:1064.86,1068.4 3 1
+voltha-go-controller/internal/pkg/application/service.go:1068.9,1070.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:1071.8,1074.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:1078.16,1080.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1087.17,1088.29 1 0
+voltha-go-controller/internal/pkg/application/service.go:1093.3,1095.18 3 0
+voltha-go-controller/internal/pkg/application/service.go:1101.3,1101.94 1 0
+voltha-go-controller/internal/pkg/application/service.go:1088.29,1090.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:1095.18,1098.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:1110.86,1111.59 1 0
+voltha-go-controller/internal/pkg/application/service.go:1111.59,1114.40 3 0
+voltha-go-controller/internal/pkg/application/service.go:1125.3,1125.14 1 0
+voltha-go-controller/internal/pkg/application/service.go:1114.40,1121.57 5 0
+voltha-go-controller/internal/pkg/application/service.go:1121.57,1123.5 1 0
+voltha-go-controller/internal/pkg/application/service.go:1130.139,1138.9 6 1
+voltha-go-controller/internal/pkg/application/service.go:1142.2,1144.16 3 1
+voltha-go-controller/internal/pkg/application/service.go:1150.2,1154.34 4 1
+voltha-go-controller/internal/pkg/application/service.go:1157.2,1162.21 4 1
+voltha-go-controller/internal/pkg/application/service.go:1165.2,1167.35 3 1
+voltha-go-controller/internal/pkg/application/service.go:1174.2,1174.20 1 1
+voltha-go-controller/internal/pkg/application/service.go:1180.2,1180.19 1 1
+voltha-go-controller/internal/pkg/application/service.go:1185.2,1187.67 2 1
+voltha-go-controller/internal/pkg/application/service.go:1196.2,1196.63 1 1
+voltha-go-controller/internal/pkg/application/service.go:1205.2,1205.37 1 1
+voltha-go-controller/internal/pkg/application/service.go:1217.2,1217.38 1 1
+voltha-go-controller/internal/pkg/application/service.go:1222.2,1223.45 2 1
+voltha-go-controller/internal/pkg/application/service.go:1138.9,1141.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:1144.16,1147.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:1154.34,1156.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1162.21,1164.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1167.35,1169.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1174.20,1178.3 3 1
+voltha-go-controller/internal/pkg/application/service.go:1180.19,1183.3 2 1
+voltha-go-controller/internal/pkg/application/service.go:1187.67,1188.84 1 0
+voltha-go-controller/internal/pkg/application/service.go:1188.84,1189.39 1 0
+voltha-go-controller/internal/pkg/application/service.go:1189.39,1193.5 3 0
+voltha-go-controller/internal/pkg/application/service.go:1196.63,1197.80 1 0
+voltha-go-controller/internal/pkg/application/service.go:1197.80,1198.38 1 0
+voltha-go-controller/internal/pkg/application/service.go:1198.38,1202.5 3 0
+voltha-go-controller/internal/pkg/application/service.go:1205.37,1206.64 1 0
+voltha-go-controller/internal/pkg/application/service.go:1206.64,1207.81 1 0
+voltha-go-controller/internal/pkg/application/service.go:1207.81,1208.39 1 0
+voltha-go-controller/internal/pkg/application/service.go:1208.39,1212.6 3 0
+voltha-go-controller/internal/pkg/application/service.go:1217.38,1219.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1223.45,1225.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1230.100,1236.36 3 2
+voltha-go-controller/internal/pkg/application/service.go:1247.2,1247.73 1 2
+voltha-go-controller/internal/pkg/application/service.go:1236.36,1246.3 4 4
+voltha-go-controller/internal/pkg/application/service.go:1252.111,1253.25 1 2
+voltha-go-controller/internal/pkg/application/service.go:1257.2,1259.43 2 2
+voltha-go-controller/internal/pkg/application/service.go:1265.2,1269.61 5 1
+voltha-go-controller/internal/pkg/application/service.go:1275.2,1277.56 2 1
+voltha-go-controller/internal/pkg/application/service.go:1294.2,1294.159 1 0
+voltha-go-controller/internal/pkg/application/service.go:1253.25,1256.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:1259.43,1263.3 3 1
+voltha-go-controller/internal/pkg/application/service.go:1269.61,1274.3 4 1
+voltha-go-controller/internal/pkg/application/service.go:1277.56,1279.17 2 1
+voltha-go-controller/internal/pkg/application/service.go:1287.3,1287.38 1 1
+voltha-go-controller/internal/pkg/application/service.go:1291.3,1292.9 2 1
+voltha-go-controller/internal/pkg/application/service.go:1279.17,1282.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:1282.9,1282.54 1 1
+voltha-go-controller/internal/pkg/application/service.go:1282.54,1285.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:1287.38,1290.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:1299.94,1302.43 2 0
+voltha-go-controller/internal/pkg/application/service.go:1307.2,1309.51 3 0
+voltha-go-controller/internal/pkg/application/service.go:1302.43,1306.3 3 0
+voltha-go-controller/internal/pkg/application/service.go:1314.100,1315.21 1 4
+voltha-go-controller/internal/pkg/application/service.go:1331.2,1331.73 1 4
+voltha-go-controller/internal/pkg/application/service.go:1315.21,1321.37 3 4
+voltha-go-controller/internal/pkg/application/service.go:1321.37,1329.4 3 7
+voltha-go-controller/internal/pkg/application/service.go:1335.68,1336.83 1 2
+voltha-go-controller/internal/pkg/application/service.go:1336.83,1340.3 3 1
+voltha-go-controller/internal/pkg/application/service.go:1345.79,1353.45 3 1
+voltha-go-controller/internal/pkg/application/service.go:1361.2,1365.60 3 1
+voltha-go-controller/internal/pkg/application/service.go:1385.2,1385.202 1 0
+voltha-go-controller/internal/pkg/application/service.go:1353.45,1355.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1355.8,1355.49 1 1
+voltha-go-controller/internal/pkg/application/service.go:1355.49,1357.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1357.8,1359.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1365.60,1367.20 2 1
+voltha-go-controller/internal/pkg/application/service.go:1375.3,1375.26 1 0
+voltha-go-controller/internal/pkg/application/service.go:1380.3,1383.9 3 0
+voltha-go-controller/internal/pkg/application/service.go:1367.20,1370.4 2 1
+voltha-go-controller/internal/pkg/application/service.go:1370.9,1370.54 1 0
+voltha-go-controller/internal/pkg/application/service.go:1370.54,1373.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:1375.26,1379.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:1390.115,1393.46 2 2
+voltha-go-controller/internal/pkg/application/service.go:1398.2,1398.25 1 1
+voltha-go-controller/internal/pkg/application/service.go:1401.2,1405.32 4 1
+voltha-go-controller/internal/pkg/application/service.go:1393.46,1397.3 3 1
+voltha-go-controller/internal/pkg/application/service.go:1398.25,1400.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1408.85,1410.16 2 10
+voltha-go-controller/internal/pkg/application/service.go:1410.16,1413.3 2 3
+voltha-go-controller/internal/pkg/application/service.go:1413.8,1413.53 1 7
+voltha-go-controller/internal/pkg/application/service.go:1413.53,1416.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:1420.68,1423.25 2 3
+voltha-go-controller/internal/pkg/application/service.go:1423.25,1425.10 2 3
+voltha-go-controller/internal/pkg/application/service.go:1429.3,1431.17 3 2
+voltha-go-controller/internal/pkg/application/service.go:1435.3,1436.87 2 1
+voltha-go-controller/internal/pkg/application/service.go:1440.3,1440.43 1 1
+voltha-go-controller/internal/pkg/application/service.go:1425.10,1427.12 2 1
+voltha-go-controller/internal/pkg/application/service.go:1431.17,1433.12 2 1
+voltha-go-controller/internal/pkg/application/service.go:1436.87,1438.4 1 1
+voltha-go-controller/internal/pkg/application/service.go:1440.43,1443.4 2 1
+voltha-go-controller/internal/pkg/application/service.go:1448.65,1449.47 1 1
+voltha-go-controller/internal/pkg/application/service.go:1452.2,1452.12 1 0
+voltha-go-controller/internal/pkg/application/service.go:1449.47,1451.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1456.46,1458.2 1 0
+voltha-go-controller/internal/pkg/application/service.go:1461.45,1463.2 1 0
+voltha-go-controller/internal/pkg/application/service.go:1466.42,1467.70 1 0
+voltha-go-controller/internal/pkg/application/service.go:1472.2,1472.14 1 0
+voltha-go-controller/internal/pkg/application/service.go:1467.70,1469.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1469.8,1469.85 1 0
+voltha-go-controller/internal/pkg/application/service.go:1469.85,1471.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1476.147,1480.45 3 1
+voltha-go-controller/internal/pkg/application/service.go:1487.2,1491.20 5 1
+voltha-go-controller/internal/pkg/application/service.go:1496.2,1496.16 1 1
+voltha-go-controller/internal/pkg/application/service.go:1480.45,1483.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1483.8,1486.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1491.20,1493.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1493.8,1495.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1522.148,1531.2 8 0
+voltha-go-controller/internal/pkg/application/service.go:1534.55,1536.2 1 0
+voltha-go-controller/internal/pkg/application/service.go:1547.68,1549.45 2 0
+voltha-go-controller/internal/pkg/application/service.go:1549.45,1550.97 1 0
+voltha-go-controller/internal/pkg/application/service.go:1550.97,1553.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:1558.155,1560.50 2 0
+voltha-go-controller/internal/pkg/application/service.go:1563.2,1563.50 1 0
+voltha-go-controller/internal/pkg/application/service.go:1567.2,1568.14 2 0
+voltha-go-controller/internal/pkg/application/service.go:1573.2,1575.38 2 0
+voltha-go-controller/internal/pkg/application/service.go:1578.2,1583.12 5 0
+voltha-go-controller/internal/pkg/application/service.go:1560.50,1562.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1563.50,1565.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1568.14,1571.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:1575.38,1577.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1587.92,1589.47 2 0
+voltha-go-controller/internal/pkg/application/service.go:1589.47,1591.16 1 0
+voltha-go-controller/internal/pkg/application/service.go:1597.3,1598.51 2 0
+voltha-go-controller/internal/pkg/application/service.go:1591.16,1594.12 3 0
+voltha-go-controller/internal/pkg/application/service.go:1598.51,1601.18 3 0
+voltha-go-controller/internal/pkg/application/service.go:1605.4,1621.29 8 0
+voltha-go-controller/internal/pkg/application/service.go:1601.18,1603.13 2 0
+voltha-go-controller/internal/pkg/application/service.go:1621.29,1625.5 3 0
+voltha-go-controller/internal/pkg/application/service.go:1625.10,1627.5 1 0
+voltha-go-controller/internal/pkg/application/service.go:1628.9,1630.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:1635.72,1637.67 2 0
+voltha-go-controller/internal/pkg/application/service.go:1643.2,1647.125 4 0
+voltha-go-controller/internal/pkg/application/service.go:1637.67,1639.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1639.8,1641.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1651.131,1652.45 1 0
+voltha-go-controller/internal/pkg/application/service.go:1662.2,1663.12 2 0
+voltha-go-controller/internal/pkg/application/service.go:1652.45,1654.65 2 0
+voltha-go-controller/internal/pkg/application/service.go:1654.65,1657.48 3 0
+voltha-go-controller/internal/pkg/application/service.go:1657.48,1659.5 1 0
+voltha-go-controller/internal/pkg/application/service.go:1667.139,1668.45 1 0
+voltha-go-controller/internal/pkg/application/service.go:1668.45,1669.61 1 0
+voltha-go-controller/internal/pkg/application/service.go:1669.61,1670.65 1 0
+voltha-go-controller/internal/pkg/application/service.go:1670.65,1672.5 1 0
+voltha-go-controller/internal/pkg/application/service.go:1679.81,1703.26 22 0
+voltha-go-controller/internal/pkg/application/service.go:1708.2,1712.49 4 0
+voltha-go-controller/internal/pkg/application/service.go:1717.2,1737.86 15 0
+voltha-go-controller/internal/pkg/application/service.go:1740.2,1749.39 8 0
+voltha-go-controller/internal/pkg/application/service.go:1703.26,1706.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:1712.49,1715.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:1737.86,1739.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1754.94,1760.32 4 0
+voltha-go-controller/internal/pkg/application/service.go:1764.2,1764.21 1 0
+voltha-go-controller/internal/pkg/application/service.go:1760.32,1763.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:1769.98,1771.2 1 0
+voltha-go-controller/internal/pkg/application/service.go:1774.160,1776.30 2 1
+voltha-go-controller/internal/pkg/application/service.go:1776.30,1778.10 2 0
+voltha-go-controller/internal/pkg/application/service.go:1782.3,1784.187 3 0
+voltha-go-controller/internal/pkg/application/service.go:1778.10,1780.12 2 0
+voltha-go-controller/internal/pkg/application/service.go:1789.94,1791.48 2 0
+voltha-go-controller/internal/pkg/application/service.go:1796.2,1796.13 1 0
+voltha-go-controller/internal/pkg/application/service.go:1791.48,1793.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1793.8,1795.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1800.90,1804.2 3 0
+voltha-go-controller/internal/pkg/application/service.go:1807.80,1808.36 1 0
+voltha-go-controller/internal/pkg/application/service.go:1813.2,1813.67 1 0
+voltha-go-controller/internal/pkg/application/service.go:1808.36,1809.65 1 0
+voltha-go-controller/internal/pkg/application/service.go:1809.65,1811.4 1 0
+voltha-go-controller/internal/pkg/application/service.go:1818.95,1819.26 1 31
+voltha-go-controller/internal/pkg/application/service.go:1822.2,1822.32 1 30
+voltha-go-controller/internal/pkg/application/service.go:1825.2,1825.28 1 29
+voltha-go-controller/internal/pkg/application/service.go:1828.2,1828.28 1 28
+voltha-go-controller/internal/pkg/application/service.go:1831.2,1831.58 1 27
+voltha-go-controller/internal/pkg/application/service.go:1834.2,1834.49 1 26
+voltha-go-controller/internal/pkg/application/service.go:1837.2,1837.68 1 25
+voltha-go-controller/internal/pkg/application/service.go:1840.2,1840.44 1 24
+voltha-go-controller/internal/pkg/application/service.go:1843.2,1843.36 1 23
+voltha-go-controller/internal/pkg/application/service.go:1846.2,1846.46 1 22
+voltha-go-controller/internal/pkg/application/service.go:1849.2,1849.26 1 21
+voltha-go-controller/internal/pkg/application/service.go:1852.2,1852.32 1 20
+voltha-go-controller/internal/pkg/application/service.go:1855.2,1855.89 1 19
+voltha-go-controller/internal/pkg/application/service.go:1858.2,1858.52 1 18
+voltha-go-controller/internal/pkg/application/service.go:1861.2,1861.40 1 18
+voltha-go-controller/internal/pkg/application/service.go:1864.2,1864.42 1 17
+voltha-go-controller/internal/pkg/application/service.go:1867.2,1867.70 1 16
+voltha-go-controller/internal/pkg/application/service.go:1870.2,1870.46 1 15
+voltha-go-controller/internal/pkg/application/service.go:1873.2,1873.46 1 14
+voltha-go-controller/internal/pkg/application/service.go:1876.2,1876.52 1 13
+voltha-go-controller/internal/pkg/application/service.go:1879.2,1879.30 1 12
+voltha-go-controller/internal/pkg/application/service.go:1882.2,1882.50 1 11
+voltha-go-controller/internal/pkg/application/service.go:1885.2,1885.42 1 10
+voltha-go-controller/internal/pkg/application/service.go:1888.2,1888.32 1 9
+voltha-go-controller/internal/pkg/application/service.go:1891.2,1891.50 1 8
+voltha-go-controller/internal/pkg/application/service.go:1894.2,1894.54 1 7
+voltha-go-controller/internal/pkg/application/service.go:1897.2,1897.42 1 6
+voltha-go-controller/internal/pkg/application/service.go:1900.2,1900.44 1 5
+voltha-go-controller/internal/pkg/application/service.go:1903.2,1903.44 1 4
+voltha-go-controller/internal/pkg/application/service.go:1906.2,1906.44 1 3
+voltha-go-controller/internal/pkg/application/service.go:1909.2,1909.44 1 2
+voltha-go-controller/internal/pkg/application/service.go:1913.2,1913.13 1 1
+voltha-go-controller/internal/pkg/application/service.go:1819.26,1821.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1822.32,1824.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1825.28,1827.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1828.28,1830.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1831.58,1833.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1834.49,1836.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1837.68,1839.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1840.44,1842.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1843.36,1845.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1846.46,1848.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1849.26,1851.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1852.32,1854.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1855.89,1857.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1858.52,1860.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:1861.40,1863.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1864.42,1866.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1867.70,1869.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1870.46,1872.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1873.46,1875.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1876.52,1878.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1879.30,1881.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1882.50,1884.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1885.42,1887.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1888.32,1890.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1891.50,1893.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1894.54,1896.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1897.42,1899.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1900.44,1902.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1903.44,1905.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1906.44,1908.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1909.44,1911.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1917.79,1920.27 1 2
+voltha-go-controller/internal/pkg/application/service.go:1926.2,1926.27 1 2
+voltha-go-controller/internal/pkg/application/service.go:1932.2,1934.41 3 2
+voltha-go-controller/internal/pkg/application/service.go:1937.2,1939.26 2 2
+voltha-go-controller/internal/pkg/application/service.go:1944.2,1944.36 1 1
+voltha-go-controller/internal/pkg/application/service.go:1957.2,1957.13 1 1
+voltha-go-controller/internal/pkg/application/service.go:1920.27,1921.49 1 2
+voltha-go-controller/internal/pkg/application/service.go:1921.49,1923.4 1 2
+voltha-go-controller/internal/pkg/application/service.go:1926.27,1927.49 1 2
+voltha-go-controller/internal/pkg/application/service.go:1927.49,1929.4 1 2
+voltha-go-controller/internal/pkg/application/service.go:1934.41,1936.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1939.26,1941.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:1944.36,1945.61 1 1
+voltha-go-controller/internal/pkg/application/service.go:1945.61,1952.54 7 1
+voltha-go-controller/internal/pkg/application/service.go:1952.54,1954.5 1 1
+voltha-go-controller/internal/pkg/application/service.go:1961.55,1962.2 0 1
+voltha-go-controller/internal/pkg/application/service.go:1965.54,1990.2 1 1
+voltha-go-controller/internal/pkg/application/service.go:1993.124,1996.59 3 3
+voltha-go-controller/internal/pkg/application/service.go:2013.2,2013.21 1 3
+voltha-go-controller/internal/pkg/application/service.go:1996.59,1998.24 2 3
+voltha-go-controller/internal/pkg/application/service.go:2011.3,2011.14 1 3
+voltha-go-controller/internal/pkg/application/service.go:1998.24,1999.23 1 2
+voltha-go-controller/internal/pkg/application/service.go:1999.23,2000.51 1 1
+voltha-go-controller/internal/pkg/application/service.go:2000.51,2002.6 1 1
+voltha-go-controller/internal/pkg/application/service.go:2003.10,2004.30 1 1
+voltha-go-controller/internal/pkg/application/service.go:2004.30,2006.6 1 1
+voltha-go-controller/internal/pkg/application/service.go:2008.9,2010.4 1 1
+voltha-go-controller/internal/pkg/application/service.go:2017.136,2020.16 3 3
+voltha-go-controller/internal/pkg/application/service.go:2025.2,2025.27 1 2
+voltha-go-controller/internal/pkg/application/service.go:2031.2,2031.59 1 2
+voltha-go-controller/internal/pkg/application/service.go:2060.2,2060.12 1 2
+voltha-go-controller/internal/pkg/application/service.go:2020.16,2023.3 2 1
+voltha-go-controller/internal/pkg/application/service.go:2025.27,2027.3 1 0
+voltha-go-controller/internal/pkg/application/service.go:2027.8,2027.36 1 2
+voltha-go-controller/internal/pkg/application/service.go:2027.36,2030.3 2 0
+voltha-go-controller/internal/pkg/application/service.go:2031.59,2034.99 2 2
+voltha-go-controller/internal/pkg/application/service.go:2038.3,2038.43 1 2
+voltha-go-controller/internal/pkg/application/service.go:2058.3,2058.14 1 2
+voltha-go-controller/internal/pkg/application/service.go:2034.99,2037.4 2 0
+voltha-go-controller/internal/pkg/application/service.go:2038.43,2040.16 2 2
+voltha-go-controller/internal/pkg/application/service.go:2044.4,2049.30 5 2
+voltha-go-controller/internal/pkg/application/service.go:2040.16,2043.5 2 0
+voltha-go-controller/internal/pkg/application/service.go:2049.30,2050.85 1 2
+voltha-go-controller/internal/pkg/application/service.go:2050.85,2053.6 1 1
+voltha-go-controller/internal/pkg/application/service.go:2053.11,2055.6 1 1
+voltha-go-controller/internal/pkg/application/service.go:2064.138,2066.59 2 4
+voltha-go-controller/internal/pkg/application/service.go:2100.2,2100.12 1 4
+voltha-go-controller/internal/pkg/application/service.go:2066.59,2070.99 3 4
+voltha-go-controller/internal/pkg/application/service.go:2074.3,2074.42 1 3
+voltha-go-controller/internal/pkg/application/service.go:2098.3,2098.14 1 2
+voltha-go-controller/internal/pkg/application/service.go:2070.99,2073.4 2 1
+voltha-go-controller/internal/pkg/application/service.go:2074.42,2079.18 5 3
+voltha-go-controller/internal/pkg/application/service.go:2085.4,2086.93 2 2
+voltha-go-controller/internal/pkg/application/service.go:2079.18,2084.5 2 1
+voltha-go-controller/internal/pkg/application/service.go:2086.93,2087.85 1 2
+voltha-go-controller/internal/pkg/application/service.go:2087.85,2090.25 2 1
+voltha-go-controller/internal/pkg/application/service.go:2090.25,2092.7 1 1
+voltha-go-controller/internal/pkg/application/service.go:2093.11,2095.6 1 1
+voltha-go-controller/internal/pkg/application/service.go:2107.45,2108.37 1 2
+voltha-go-controller/internal/pkg/application/service.go:2111.2,2111.54 1 1
+voltha-go-controller/internal/pkg/application/service.go:2116.2,2116.30 1 1
+voltha-go-controller/internal/pkg/application/service.go:2108.37,2110.3 1 1
+voltha-go-controller/internal/pkg/application/service.go:2111.54,2112.40 1 8
+voltha-go-controller/internal/pkg/application/service.go:2112.40,2114.4 1 0
+voltha-go-controller/internal/pkg/application/flowevent.go:66.28,76.2 1 2
+voltha-go-controller/internal/pkg/application/flowevent.go:79.109,83.16 3 3
+voltha-go-controller/internal/pkg/application/flowevent.go:87.2,89.55 2 3
+voltha-go-controller/internal/pkg/application/flowevent.go:94.2,98.13 5 0
+voltha-go-controller/internal/pkg/application/flowevent.go:83.16,86.3 2 0
+voltha-go-controller/internal/pkg/application/flowevent.go:89.55,93.3 3 3
+voltha-go-controller/internal/pkg/application/flowevent.go:102.100,105.50 3 1
+voltha-go-controller/internal/pkg/application/flowevent.go:105.50,107.3 1 1
+voltha-go-controller/internal/pkg/application/flowevent.go:107.8,109.3 1 0
+voltha-go-controller/internal/pkg/application/flowevent.go:113.101,116.50 3 1
+voltha-go-controller/internal/pkg/application/flowevent.go:116.50,118.3 1 1
+voltha-go-controller/internal/pkg/application/flowevent.go:118.8,120.3 1 0
+voltha-go-controller/internal/pkg/application/flowevent.go:124.101,127.51 3 1
+voltha-go-controller/internal/pkg/application/flowevent.go:127.51,129.3 1 0
+voltha-go-controller/internal/pkg/application/flowevent.go:133.101,136.51 3 1
+voltha-go-controller/internal/pkg/application/flowevent.go:136.51,138.3 1 1
+voltha-go-controller/internal/pkg/application/flowevent.go:138.8,140.3 1 0
+voltha-go-controller/internal/pkg/application/flowevent.go:144.101,147.51 3 1
+voltha-go-controller/internal/pkg/application/flowevent.go:147.51,149.3 1 1
+voltha-go-controller/internal/pkg/application/flowevent.go:149.8,151.3 1 0
+voltha-go-controller/internal/pkg/application/flowevent.go:155.99,158.51 3 1
+voltha-go-controller/internal/pkg/application/flowevent.go:158.51,160.3 1 1
+voltha-go-controller/internal/pkg/application/flowevent.go:160.8,162.3 1 0
+voltha-go-controller/internal/pkg/application/flowevent.go:166.100,169.51 3 0
+voltha-go-controller/internal/pkg/application/flowevent.go:169.51,171.3 1 0
+voltha-go-controller/internal/pkg/application/flowevent.go:171.8,173.3 1 0
+voltha-go-controller/internal/pkg/application/flowevent.go:177.60,181.39 3 7
+voltha-go-controller/internal/pkg/application/flowevent.go:186.2,186.15 1 7
+voltha-go-controller/internal/pkg/application/flowevent.go:181.39,183.3 1 6
+voltha-go-controller/internal/pkg/application/flowevent.go:183.8,183.65 1 1
+voltha-go-controller/internal/pkg/application/flowevent.go:183.65,185.3 1 0
+voltha-go-controller/internal/pkg/application/igmpport.go:47.121,57.2 9 0
+voltha-go-controller/internal/pkg/application/igmpport.go:60.59,62.2 1 0
+voltha-go-controller/internal/pkg/application/igmpport.go:65.59,67.2 1 0
+voltha-go-controller/internal/pkg/application/igmpport.go:70.53,73.2 2 0
+voltha-go-controller/internal/pkg/application/igmpport.go:76.53,79.2 2 0
+voltha-go-controller/internal/pkg/application/igmpport.go:82.53,84.39 2 0
+voltha-go-controller/internal/pkg/application/igmpport.go:84.39,85.22 1 0
+voltha-go-controller/internal/pkg/application/igmpport.go:85.22,88.4 2 0
+voltha-go-controller/internal/pkg/application/igmpport.go:93.53,95.39 2 0
+voltha-go-controller/internal/pkg/application/igmpport.go:95.39,96.22 1 0
+voltha-go-controller/internal/pkg/application/igmpport.go:96.22,99.4 2 0
+voltha-go-controller/internal/pkg/application/igmpport.go:104.111,106.16 2 0
+voltha-go-controller/internal/pkg/application/igmpport.go:109.2,109.88 1 0
+voltha-go-controller/internal/pkg/application/igmpport.go:112.2,112.12 1 0
+voltha-go-controller/internal/pkg/application/igmpport.go:106.16,108.3 1 0
+voltha-go-controller/internal/pkg/application/igmpport.go:109.88,111.3 1 0
+voltha-go-controller/internal/pkg/application/igmpport.go:116.66,118.48 2 0
+voltha-go-controller/internal/pkg/application/igmpport.go:122.2,122.18 1 0
+voltha-go-controller/internal/pkg/application/igmpport.go:118.48,121.3 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:46.87,47.50 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:54.2,54.12 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:47.50,49.17 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:49.17,52.4 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:59.81,63.2 3 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:67.78,70.20 3 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:79.2,80.61 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:83.2,83.12 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:70.20,73.3 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:73.8,75.27 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:75.27,77.4 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:80.61,82.3 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:88.77,93.26 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:97.2,97.34 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:103.2,106.47 3 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:109.2,109.12 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:93.26,95.3 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:97.34,100.3 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:106.47,108.3 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:112.79,114.61 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:120.2,120.51 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:123.2,123.12 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:114.61,116.47 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:116.47,118.4 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:120.51,122.3 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:128.83,131.25 3 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:134.2,134.43 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:138.2,138.12 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:131.25,133.3 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:134.43,136.3 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:143.84,146.26 3 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:149.2,149.44 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:154.2,154.12 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:146.26,148.3 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:149.44,152.3 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:159.85,163.2 3 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:165.63,168.33 3 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:168.33,170.10 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:174.3,174.61 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:170.10,172.12 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:174.61,177.44 3 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:180.4,180.80 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:177.44,179.5 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:180.80,182.5 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:182.10,184.5 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:185.9,187.4 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:191.71,194.35 3 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:194.35,196.10 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:200.3,200.62 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:196.10,198.12 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:200.62,203.44 3 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:206.4,206.46 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:210.4,210.71 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:203.44,205.5 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:206.46,208.5 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:211.9,213.4 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:217.69,220.29 3 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:220.29,222.10 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:226.3,226.59 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:222.10,224.12 2 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:226.59,229.44 3 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:232.4,232.84 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:236.4,236.68 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:229.44,231.5 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:232.84,234.5 1 0
+voltha-go-controller/internal/pkg/application/minor_upgrade.go:237.9,239.4 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:102.80,109.2 5 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:112.102,114.47 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:117.2,119.12 3 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:114.47,116.3 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:123.44,127.2 3 1
+voltha-go-controller/internal/pkg/application/pppoeia.go:130.92,138.2 7 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:141.92,146.20 5 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:150.2,152.26 3 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:146.20,149.3 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:156.94,158.45 2 1
+voltha-go-controller/internal/pkg/application/pppoeia.go:162.2,165.72 4 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:158.45,161.3 2 1
+voltha-go-controller/internal/pkg/application/pppoeia.go:169.130,171.20 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:175.2,178.46 4 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:181.2,181.34 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:171.20,174.3 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:178.46,180.3 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:185.116,189.97 4 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:202.2,202.20 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:210.2,211.63 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:189.97,191.34 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:199.3,199.18 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:191.34,194.22 3 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:197.4,197.20 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:194.22,196.5 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:202.20,205.9 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:205.9,208.4 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:217.57,223.67 4 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:227.2,229.19 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:234.2,234.19 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:240.2,240.33 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:261.2,262.47 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:223.67,225.3 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:229.19,233.3 3 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:234.19,238.3 3 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:240.33,260.3 16 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:266.39,267.43 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:267.43,268.51 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:268.51,271.4 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:280.122,294.19 7 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:300.2,302.16 3 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:308.2,308.17 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:321.2,337.26 10 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:360.2,360.25 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:377.2,381.77 4 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:386.2,386.104 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:294.19,298.3 3 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:302.16,305.3 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:308.17,311.41 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:318.3,318.22 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:311.41,313.4 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:313.9,313.48 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:313.48,315.4 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:315.9,315.48 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:315.48,317.4 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:337.26,342.92 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:345.3,346.57 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:350.3,350.32 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:342.92,344.4 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:346.57,349.4 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:350.32,352.30 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:355.4,356.45 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:352.30,354.5 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:361.24,363.40 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:365.8,367.40 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:369.12,371.40 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:372.10,374.9 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:381.77,384.3 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:386.104,388.3 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:393.122,397.16 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:402.2,403.37 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:409.2,425.19 10 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:431.2,431.17 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:453.2,470.26 11 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:487.2,487.25 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:504.2,507.77 4 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:513.2,513.103 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:397.16,400.3 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:403.37,406.3 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:425.19,429.3 3 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:431.17,433.73 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:445.3,445.41 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:450.3,450.22 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:433.73,434.52 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:442.4,442.36 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:434.52,436.55 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:436.55,440.6 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:445.41,447.4 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:447.9,447.48 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:447.48,449.4 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:470.26,472.45 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:477.3,477.32 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:472.45,476.4 3 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:477.32,479.30 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:482.4,483.45 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:479.30,481.5 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:489.20,493.40 4 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:496.8,498.40 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:499.10,501.9 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:507.77,509.3 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:513.103,515.3 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:519.120,522.19 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:525.2,526.9 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:532.2,533.64 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:538.2,538.10 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:522.19,524.3 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:526.9,528.3 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:533.64,535.3 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:538.10,543.3 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:543.8,546.3 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:550.96,553.2 2 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:558.13,561.2 2 1
+voltha-go-controller/internal/pkg/application/pppoeia.go:564.96,566.2 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:579.92,586.2 6 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:589.45,591.2 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:594.46,596.2 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:599.50,601.2 1 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:604.39,605.2 0 0
+voltha-go-controller/internal/pkg/application/pppoeia.go:608.78,613.2 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:65.96,81.47 15 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:87.2,98.21 7 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:102.2,102.13 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:81.47,83.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:83.8,86.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:98.21,101.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:107.88,110.75 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:115.2,125.21 8 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:129.2,129.44 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:110.75,114.3 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:125.21,128.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:129.44,131.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:134.101,138.130 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:143.2,143.86 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:138.130,142.3 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:147.88,150.55 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:159.2,160.44 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:163.2,163.75 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:150.55,153.45 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:156.3,157.14 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:153.45,155.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:160.44,162.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:167.70,169.48 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:172.2,172.18 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:169.48,171.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:176.45,177.50 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:180.2,180.22 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:177.50,179.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:184.91,185.76 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:207.2,209.39 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:185.76,192.43 6 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:192.43,195.22 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:199.4,202.70 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:195.22,197.5 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:204.8,206.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:213.67,216.35 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:216.35,218.10 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:222.3,222.30 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:218.10,220.12 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:227.67,229.16 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:232.2,232.113 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:235.2,236.12 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:229.16,231.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:232.113,234.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:240.42,248.2 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:252.111,253.65 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:262.2,262.10 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:253.65,256.86 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:256.86,258.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:259.8,261.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:266.113,271.59 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:286.2,287.22 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:271.59,277.3 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:277.8,285.3 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:291.118,296.58 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:307.2,307.19 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:296.58,299.58 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:303.3,303.107 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:299.58,302.4 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:304.8,306.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:311.60,314.2 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:317.64,320.2 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:326.94,331.9 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:338.2,338.25 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:343.2,344.19 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:360.2,360.44 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:331.9,334.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:334.8,336.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:338.25,341.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:344.19,347.21 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:350.3,356.23 5 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:347.21,349.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:356.23,358.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:360.44,362.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:366.174,369.20 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:374.2,377.20 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:380.2,387.44 7 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:369.20,372.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:377.20,379.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:387.44,389.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:393.48,395.55 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:399.2,400.21 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:395.55,398.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:405.145,414.42 8 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:421.2,421.67 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:425.2,426.59 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:430.2,430.29 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:433.2,437.21 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:440.2,440.44 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:414.42,416.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:416.8,416.25 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:416.25,419.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:421.67,424.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:426.59,428.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:430.29,432.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:437.21,439.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:440.44,442.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:447.114,453.20 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:456.2,458.42 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:466.2,466.42 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:475.2,480.19 5 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:483.2,483.44 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:486.2,487.21 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:453.20,455.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:458.42,465.3 6 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:466.42,473.3 6 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:480.19,482.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:483.44,485.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:491.94,492.29 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:495.2,499.64 5 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:503.2,504.15 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:492.29,494.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:499.64,502.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:504.15,507.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:517.84,520.24 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:523.2,523.31 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:537.2,537.14 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:520.24,522.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:523.31,524.28 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:524.28,527.25 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:533.4,534.15 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:527.25,529.5 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:529.10,532.5 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:541.66,543.68 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:548.2,548.43 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:543.68,547.3 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:552.93,554.29 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:562.2,562.63 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:566.2,566.133 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:554.29,558.45 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:558.45,560.4 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:562.63,565.3 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:570.42,571.25 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:571.25,579.63 7 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:594.3,598.28 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:579.63,582.63 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:589.4,589.22 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:592.4,592.15 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:582.63,587.5 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:589.22,591.5 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:604.42,605.24 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:605.24,613.63 7 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:628.3,631.65 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:613.63,616.63 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:623.4,623.22 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:626.4,626.15 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:616.63,621.5 4 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:623.22,625.5 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:632.8,634.3 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:638.58,646.24 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:646.24,657.3 9 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:662.63,666.66 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:695.2,695.41 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:666.66,668.47 2 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:693.3,693.14 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:668.47,669.29 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:673.4,678.50 5 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:682.4,684.64 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:669.29,670.13 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:678.50,680.5 1 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:684.64,689.5 3 0
+voltha-go-controller/internal/pkg/application/igmpgroupdevice.go:689.10,691.5 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:123.13,126.2 2 1
+voltha-go-controller/internal/pkg/application/dhcprelay.go:129.74,137.2 6 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:140.88,143.8 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:146.2,146.12 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:143.8,145.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:150.88,152.43 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:155.2,157.12 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:152.43,154.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:161.38,165.2 3 1
+voltha-go-controller/internal/pkg/application/dhcprelay.go:168.94,173.20 5 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:177.2,184.12 6 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:173.20,176.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:188.88,193.20 5 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:197.2,201.26 5 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:193.20,196.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:205.126,207.45 2 1
+voltha-go-controller/internal/pkg/application/dhcprelay.go:211.2,217.69 7 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:207.45,210.3 2 1
+voltha-go-controller/internal/pkg/application/dhcprelay.go:221.102,229.2 7 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:232.96,239.2 6 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:242.126,244.20 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:248.2,252.42 5 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:255.2,255.34 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:244.20,247.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:252.42,254.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:259.132,265.44 5 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:268.2,268.34 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:265.44,267.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:272.93,274.21 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:284.2,284.8 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:274.21,277.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:277.8,277.28 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:277.28,280.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:280.8,283.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:288.118,295.20 6 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:304.2,304.33 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:309.2,309.63 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:295.20,298.9 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:298.9,301.4 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:304.33,308.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:314.85,322.45 6 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:330.2,331.20 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:340.2,340.33 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:346.2,346.74 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:322.45,324.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:324.8,326.98 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:326.98,328.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:331.20,334.9 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:334.9,337.4 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:340.33,345.3 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:376.78,377.40 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:394.2,395.17 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:377.40,379.46 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:379.46,382.18 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:390.4,391.9 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:382.18,385.22 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:388.5,388.40 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:385.22,387.6 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:402.77,406.19 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:411.2,411.19 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:417.2,417.33 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:439.2,440.49 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:406.19,410.3 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:411.19,415.3 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:417.33,437.3 16 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:446.41,447.44 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:447.44,448.27 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:448.27,451.4 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:456.58,457.38 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:462.2,462.38 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:457.38,458.47 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:458.47,460.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:466.55,468.35 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:473.2,473.44 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:468.35,469.42 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:469.42,471.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:477.53,479.2 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:482.57,487.48 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:493.2,493.28 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:487.48,489.22 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:489.22,491.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:497.60,500.48 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:516.2,516.15 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:500.48,501.35 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:501.35,502.38 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:502.38,505.19 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:511.5,512.10 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:505.19,510.6 4 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:520.60,523.48 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:539.2,539.28 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:523.48,524.35 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:524.35,525.38 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:525.38,527.56 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:527.56,531.11 4 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:532.11,534.11 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:548.121,569.19 11 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:575.2,577.23 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:583.2,586.30 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:569.19,573.3 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:577.23,580.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:586.30,589.20 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:608.3,609.60 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:613.3,627.27 8 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:649.3,649.26 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:665.3,670.78 6 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:675.3,675.105 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:589.20,593.76 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:604.4,604.94 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:593.76,595.41 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:602.5,602.35 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:595.41,601.6 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:609.60,612.4 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:627.27,632.93 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:635.4,636.58 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:640.4,640.33 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:632.93,634.5 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:636.58,639.5 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:640.33,642.31 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:645.5,646.46 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:642.31,644.6 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:650.25,652.41 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:654.9,656.41 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:658.13,660.41 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:661.11,662.91 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:670.78,673.4 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:675.105,677.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:683.60,688.63 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:699.2,699.17 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:688.63,692.44 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:696.3,696.14 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:692.44,695.4 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:700.61,701.44 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:707.33,710.42 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:712.52,714.39 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:719.31,720.40 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:701.44,703.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:703.9,703.50 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:703.50,705.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:714.39,716.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:716.9,716.46 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:716.46,718.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:726.84,732.63 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:741.2,741.17 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:732.63,734.44 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:738.3,738.14 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:734.44,737.4 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:742.35,743.46 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:745.35,748.46 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:750.33,752.44 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:758.121,762.16 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:767.2,768.37 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:776.2,787.19 10 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:795.2,795.83 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:805.2,805.19 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:846.2,847.59 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:851.2,867.26 10 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:883.2,883.25 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:899.2,904.77 6 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:910.2,910.103 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:913.2,913.19 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:762.16,765.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:768.37,771.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:787.19,791.3 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:795.83,796.58 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:796.58,798.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:805.19,810.84 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:828.3,835.28 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:810.84,811.60 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:811.60,813.67 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:821.5,822.55 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:813.67,820.6 4 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:822.55,825.6 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:835.28,837.46 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:842.4,842.43 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:837.46,839.5 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:839.10,839.34 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:839.34,841.5 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:847.59,850.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:867.26,869.45 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:874.3,874.32 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:869.45,873.4 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:874.32,876.30 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:879.4,880.45 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:876.30,878.5 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:885.20,889.40 4 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:892.8,894.40 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:895.10,896.90 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:904.77,906.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:910.103,912.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:913.19,916.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:920.95,922.2 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:926.117,931.18 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:935.2,936.45 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:931.18,933.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:936.45,941.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:941.8,944.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:948.95,950.2 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:958.124,960.18 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:963.2,965.24 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:978.2,978.12 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:960.18,962.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:968.31,969.52 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:970.99,971.116 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:972.40,973.80 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:974.38,976.52 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:982.54,983.34 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:989.2,989.12 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:983.34,985.45 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:985.45,987.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:993.137,997.15 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1009.2,1009.14 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:997.15,998.24 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:998.24,1000.26 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1003.4,1003.24 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1000.26,1002.5 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1003.24,1006.5 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1014.121,1020.16 4 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1025.2,1026.37 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1034.2,1044.44 6 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1049.2,1055.45 5 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1064.2,1067.19 4 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1072.2,1072.51 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1082.2,1082.19 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1105.2,1106.59 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1110.2,1125.26 9 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1140.2,1140.25 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1156.2,1161.77 6 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1166.2,1166.103 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1169.2,1169.19 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1020.16,1023.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1026.37,1029.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1044.44,1046.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1046.8,1046.32 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1046.32,1048.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1055.45,1057.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1057.8,1059.98 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1059.98,1061.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1067.19,1071.3 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1072.51,1073.66 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1076.3,1076.30 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1073.66,1075.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1082.19,1083.52 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1101.3,1101.91 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1083.52,1084.51 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1084.51,1086.67 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1094.5,1095.55 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1086.67,1093.6 4 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1095.55,1098.6 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1106.59,1109.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1125.26,1127.45 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1131.3,1131.32 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1127.45,1130.4 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1131.32,1133.30 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1136.4,1137.45 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1133.30,1135.5 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1142.20,1146.40 4 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1149.8,1151.40 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1152.10,1153.90 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1161.77,1163.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1166.103,1168.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1169.19,1172.3 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1176.56,1178.56 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1183.2,1183.51 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1178.56,1179.43 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1179.43,1181.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1187.121,1202.58 8 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1207.2,1208.16 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1214.2,1218.19 5 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1224.2,1226.23 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1231.2,1233.30 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1202.58,1205.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1208.16,1211.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1218.19,1222.3 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1226.23,1229.3 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1233.30,1236.20 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1252.3,1257.60 4 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1261.3,1275.27 8 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1297.3,1297.26 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1313.3,1318.78 6 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1323.3,1323.105 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1236.20,1240.69 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1248.4,1248.93 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1240.69,1243.26 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1246.5,1246.51 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1243.26,1245.6 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1257.60,1260.4 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1275.27,1280.93 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1283.4,1284.58 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1288.4,1288.33 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1280.93,1282.5 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1284.58,1287.5 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1288.33,1290.31 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1293.5,1294.46 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1290.31,1292.6 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1298.25,1300.41 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1302.9,1304.41 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1306.13,1308.41 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1309.11,1310.91 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1318.78,1321.4 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1323.105,1325.4 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1332.13,1334.2 1 1
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1348.108,1351.39 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1383.2,1383.25 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1351.39,1353.40 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1381.3,1381.28 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1353.40,1355.10 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1355.10,1358.58 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1365.5,1365.53 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1358.58,1362.6 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1365.53,1378.6 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1393.77,1396.39 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1414.2,1414.24 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1396.39,1399.40 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1412.3,1412.28 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1399.40,1401.10 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1401.10,1410.5 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1417.129,1420.39 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1447.2,1447.22 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1420.39,1423.40 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1445.3,1445.28 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1423.40,1425.10 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1425.10,1426.89 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1426.89,1434.6 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1434.11,1434.80 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1434.80,1442.6 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1450.75,1453.51 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1474.2,1476.26 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1453.51,1456.60 3 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1472.3,1472.14 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1456.60,1461.11 4 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1464.4,1464.48 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1469.4,1470.15 2 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1461.11,1463.5 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1464.48,1465.43 1 0
+voltha-go-controller/internal/pkg/application/dhcprelay.go:1465.43,1467.6 1 0
+voltha-go-controller/internal/pkg/application/meters.go:67.27,69.2 1 1
+voltha-go-controller/internal/pkg/application/meters.go:91.60,94.16 3 0
+voltha-go-controller/internal/pkg/application/meters.go:97.2,97.64 1 0
+voltha-go-controller/internal/pkg/application/meters.go:100.2,100.12 1 0
+voltha-go-controller/internal/pkg/application/meters.go:94.16,96.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:97.64,99.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:104.54,106.2 1 0
+voltha-go-controller/internal/pkg/application/meters.go:109.67,112.8 3 3
+voltha-go-controller/internal/pkg/application/meters.go:115.2,115.16 1 1
+voltha-go-controller/internal/pkg/application/meters.go:112.8,114.3 1 2
+voltha-go-controller/internal/pkg/application/meters.go:119.63,122.8 3 10
+voltha-go-controller/internal/pkg/application/meters.go:125.2,125.16 1 10
+voltha-go-controller/internal/pkg/application/meters.go:122.8,124.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:129.47,133.2 3 0
+voltha-go-controller/internal/pkg/application/meters.go:136.47,140.2 3 0
+voltha-go-controller/internal/pkg/application/meters.go:143.80,156.17 3 0
+voltha-go-controller/internal/pkg/application/meters.go:161.2,161.32 1 0
+voltha-go-controller/internal/pkg/application/meters.go:166.2,168.17 3 0
+voltha-go-controller/internal/pkg/application/meters.go:174.2,174.17 1 0
+voltha-go-controller/internal/pkg/application/meters.go:179.2,182.17 2 0
+voltha-go-controller/internal/pkg/application/meters.go:186.2,192.17 4 0
+voltha-go-controller/internal/pkg/application/meters.go:196.2,197.96 2 0
+voltha-go-controller/internal/pkg/application/meters.go:156.17,158.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:161.32,163.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:168.17,170.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:170.8,172.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:174.17,176.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:176.8,178.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:182.17,184.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:192.17,194.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:197.96,199.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:203.100,206.16 3 8
+voltha-go-controller/internal/pkg/application/meters.go:206.16,207.22 1 0
+voltha-go-controller/internal/pkg/application/meters.go:212.3,212.38 1 0
+voltha-go-controller/internal/pkg/application/meters.go:207.22,208.63 1 0
+voltha-go-controller/internal/pkg/application/meters.go:208.63,210.5 1 0
+voltha-go-controller/internal/pkg/application/meters.go:213.8,215.3 1 8
+voltha-go-controller/internal/pkg/application/meters.go:219.62,223.24 3 0
+voltha-go-controller/internal/pkg/application/meters.go:241.2,241.90 1 0
+voltha-go-controller/internal/pkg/application/meters.go:223.24,225.10 2 0
+voltha-go-controller/internal/pkg/application/meters.go:229.3,231.17 3 0
+voltha-go-controller/internal/pkg/application/meters.go:235.3,237.31 3 0
+voltha-go-controller/internal/pkg/application/meters.go:225.10,227.12 2 0
+voltha-go-controller/internal/pkg/application/meters.go:231.17,233.12 2 0
+voltha-go-controller/internal/pkg/application/meters.go:237.31,239.4 1 0
+voltha-go-controller/internal/pkg/application/meters.go:245.78,247.46 2 0
+voltha-go-controller/internal/pkg/application/meters.go:252.2,259.44 5 0
+voltha-go-controller/internal/pkg/application/meters.go:247.46,250.3 2 0
+voltha-go-controller/internal/pkg/application/meters.go:259.44,261.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:265.81,267.47 2 0
+voltha-go-controller/internal/pkg/application/meters.go:271.2,272.44 2 0
+voltha-go-controller/internal/pkg/application/meters.go:267.47,270.3 2 0
+voltha-go-controller/internal/pkg/application/meters.go:272.44,274.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:279.68,280.39 1 8
+voltha-go-controller/internal/pkg/application/meters.go:283.2,283.41 1 8
+voltha-go-controller/internal/pkg/application/meters.go:280.39,282.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:288.65,289.45 1 3
+voltha-go-controller/internal/pkg/application/meters.go:292.2,292.41 1 1
+voltha-go-controller/internal/pkg/application/meters.go:289.45,291.3 1 2
+voltha-go-controller/internal/pkg/application/meters.go:296.67,300.96 3 0
+voltha-go-controller/internal/pkg/application/meters.go:300.96,302.3 1 0
+voltha-go-controller/internal/pkg/application/meters.go:306.82,308.43 2 0
+voltha-go-controller/internal/pkg/application/meters.go:312.2,313.33 2 0
+voltha-go-controller/internal/pkg/application/meters.go:319.2,319.70 1 0
+voltha-go-controller/internal/pkg/application/meters.go:325.2,329.12 4 0
+voltha-go-controller/internal/pkg/application/meters.go:308.43,311.3 2 0
+voltha-go-controller/internal/pkg/application/meters.go:313.33,317.3 2 0
+voltha-go-controller/internal/pkg/application/meters.go:319.70,324.3 4 0
+voltha-go-controller/internal/pkg/application/timer.go:44.91,45.25 1 2
+voltha-go-controller/internal/pkg/application/timer.go:49.2,51.6 3 2
+voltha-go-controller/internal/pkg/application/timer.go:45.25,48.3 2 0
+voltha-go-controller/internal/pkg/application/timer.go:51.6,52.10 1 2
+voltha-go-controller/internal/pkg/application/timer.go:53.31,54.21 1 0
+voltha-go-controller/internal/pkg/application/timer.go:60.35,61.10 1 0
+voltha-go-controller/internal/pkg/application/timer.go:55.19,56.14 1 0
+voltha-go-controller/internal/pkg/application/timer.go:57.26,58.33 1 0
+voltha-go-controller/internal/pkg/application/timer.go:67.18,68.35 1 0
+voltha-go-controller/internal/pkg/application/timer.go:68.35,70.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:47.13,51.16 3 1
+voltha-go-controller/internal/pkg/application/application.go:51.16,52.13 1 0
+voltha-go-controller/internal/pkg/application/application.go:109.64,110.27 1 4
+voltha-go-controller/internal/pkg/application/application.go:113.2,113.37 1 4
+voltha-go-controller/internal/pkg/application/application.go:110.27,112.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:160.67,165.24 5 3
+voltha-go-controller/internal/pkg/application/application.go:170.2,172.12 3 3
+voltha-go-controller/internal/pkg/application/application.go:165.24,167.3 1 2
+voltha-go-controller/internal/pkg/application/application.go:167.8,169.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:176.42,178.24 2 1
+voltha-go-controller/internal/pkg/application/application.go:178.24,180.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:222.72,238.65 16 3
+voltha-go-controller/internal/pkg/application/application.go:243.2,243.11 1 3
+voltha-go-controller/internal/pkg/application/application.go:238.65,242.3 2 1
+voltha-go-controller/internal/pkg/application/application.go:247.109,248.41 1 5
+voltha-go-controller/internal/pkg/application/application.go:251.2,251.12 1 3
+voltha-go-controller/internal/pkg/application/application.go:248.41,250.3 1 2
+voltha-go-controller/internal/pkg/application/application.go:255.84,256.41 1 3
+voltha-go-controller/internal/pkg/application/application.go:263.2,263.109 1 2
+voltha-go-controller/internal/pkg/application/application.go:256.41,262.3 5 1
+voltha-go-controller/internal/pkg/application/application.go:267.89,268.41 1 3
+voltha-go-controller/internal/pkg/application/application.go:275.2,275.112 1 2
+voltha-go-controller/internal/pkg/application/application.go:268.41,274.3 5 1
+voltha-go-controller/internal/pkg/application/application.go:279.79,284.48 4 4
+voltha-go-controller/internal/pkg/application/application.go:289.2,290.15 2 4
+voltha-go-controller/internal/pkg/application/application.go:284.48,286.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:286.8,288.3 1 3
+voltha-go-controller/internal/pkg/application/application.go:294.64,295.49 1 1
+voltha-go-controller/internal/pkg/application/application.go:309.2,310.41 2 1
+voltha-go-controller/internal/pkg/application/application.go:317.2,320.24 4 1
+voltha-go-controller/internal/pkg/application/application.go:323.2,324.10 2 1
+voltha-go-controller/internal/pkg/application/application.go:295.49,296.39 1 1
+voltha-go-controller/internal/pkg/application/application.go:296.39,299.64 2 0
+voltha-go-controller/internal/pkg/application/application.go:299.64,303.5 3 0
+voltha-go-controller/internal/pkg/application/application.go:303.10,306.5 2 0
+voltha-go-controller/internal/pkg/application/application.go:310.41,316.3 5 0
+voltha-go-controller/internal/pkg/application/application.go:320.24,322.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:328.53,329.41 1 6
+voltha-go-controller/internal/pkg/application/application.go:332.2,332.12 1 1
+voltha-go-controller/internal/pkg/application/application.go:329.41,331.3 1 5
+voltha-go-controller/internal/pkg/application/application.go:336.66,338.50 2 1
+voltha-go-controller/internal/pkg/application/application.go:345.2,345.17 1 1
+voltha-go-controller/internal/pkg/application/application.go:338.50,340.22 2 1
+voltha-go-controller/internal/pkg/application/application.go:343.3,343.14 1 1
+voltha-go-controller/internal/pkg/application/application.go:340.22,342.4 1 1
+voltha-go-controller/internal/pkg/application/application.go:349.43,350.37 1 2
+voltha-go-controller/internal/pkg/application/application.go:350.37,352.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:352.8,354.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:358.61,360.50 2 4
+voltha-go-controller/internal/pkg/application/application.go:360.50,366.30 4 4
+voltha-go-controller/internal/pkg/application/application.go:371.3,372.10 2 2
+voltha-go-controller/internal/pkg/application/application.go:376.3,376.47 1 1
+voltha-go-controller/internal/pkg/application/application.go:381.3,381.14 1 1
+voltha-go-controller/internal/pkg/application/application.go:366.30,368.4 1 2
+voltha-go-controller/internal/pkg/application/application.go:372.10,374.4 1 1
+voltha-go-controller/internal/pkg/application/application.go:376.47,380.4 3 1
+voltha-go-controller/internal/pkg/application/application.go:474.99,480.30 4 4
+voltha-go-controller/internal/pkg/application/application.go:496.2,497.17 2 4
+voltha-go-controller/internal/pkg/application/application.go:480.30,482.10 2 3
+voltha-go-controller/internal/pkg/application/application.go:486.3,488.17 3 2
+voltha-go-controller/internal/pkg/application/application.go:492.3,494.52 3 1
+voltha-go-controller/internal/pkg/application/application.go:482.10,484.12 2 1
+voltha-go-controller/internal/pkg/application/application.go:488.17,490.12 2 1
+voltha-go-controller/internal/pkg/application/application.go:501.30,504.2 2 6
+voltha-go-controller/internal/pkg/application/application.go:507.90,509.16 2 6
+voltha-go-controller/internal/pkg/application/application.go:513.2,513.63 1 6
+voltha-go-controller/internal/pkg/application/application.go:509.16,512.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:518.66,528.2 4 3
+voltha-go-controller/internal/pkg/application/application.go:531.76,534.33 2 0
+voltha-go-controller/internal/pkg/application/application.go:534.33,536.10 2 0
+voltha-go-controller/internal/pkg/application/application.go:540.3,542.17 3 0
+voltha-go-controller/internal/pkg/application/application.go:546.3,547.190 2 0
+voltha-go-controller/internal/pkg/application/application.go:536.10,538.12 2 0
+voltha-go-controller/internal/pkg/application/application.go:542.17,544.12 2 0
+voltha-go-controller/internal/pkg/application/application.go:547.190,549.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:554.121,556.16 2 2
+voltha-go-controller/internal/pkg/application/application.go:560.2,561.18 2 2
+voltha-go-controller/internal/pkg/application/application.go:565.2,565.12 1 2
+voltha-go-controller/internal/pkg/application/application.go:556.16,559.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:561.18,564.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:568.159,581.16 5 1
+voltha-go-controller/internal/pkg/application/application.go:587.2,588.19 2 1
+voltha-go-controller/internal/pkg/application/application.go:593.2,593.12 1 1
+voltha-go-controller/internal/pkg/application/application.go:581.16,584.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:588.19,591.3 2 1
+voltha-go-controller/internal/pkg/application/application.go:597.73,598.48 1 3
+voltha-go-controller/internal/pkg/application/application.go:601.2,601.12 1 1
+voltha-go-controller/internal/pkg/application/application.go:598.48,600.3 1 2
+voltha-go-controller/internal/pkg/application/application.go:605.161,607.13 2 4
+voltha-go-controller/internal/pkg/application/application.go:611.2,612.26 2 2
+voltha-go-controller/internal/pkg/application/application.go:618.2,620.13 3 2
+voltha-go-controller/internal/pkg/application/application.go:607.13,610.3 2 2
+voltha-go-controller/internal/pkg/application/application.go:612.26,616.3 3 1
+voltha-go-controller/internal/pkg/application/application.go:624.82,625.44 1 2
+voltha-go-controller/internal/pkg/application/application.go:628.2,628.52 1 2
+voltha-go-controller/internal/pkg/application/application.go:625.44,627.3 1 2
+voltha-go-controller/internal/pkg/application/application.go:632.40,633.25 1 88
+voltha-go-controller/internal/pkg/application/application.go:636.2,636.21 1 88
+voltha-go-controller/internal/pkg/application/application.go:633.25,635.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:641.44,661.2 19 1
+voltha-go-controller/internal/pkg/application/application.go:664.96,665.21 1 5
+voltha-go-controller/internal/pkg/application/application.go:673.2,673.64 1 1
+voltha-go-controller/internal/pkg/application/application.go:666.21,667.32 1 2
+voltha-go-controller/internal/pkg/application/application.go:668.21,669.32 1 2
+voltha-go-controller/internal/pkg/application/application.go:670.10,671.49 1 1
+voltha-go-controller/internal/pkg/application/application.go:677.76,682.2 4 5
+voltha-go-controller/internal/pkg/application/application.go:685.76,690.2 4 8
+voltha-go-controller/internal/pkg/application/application.go:693.81,696.16 3 2
+voltha-go-controller/internal/pkg/application/application.go:700.2,702.29 3 1
+voltha-go-controller/internal/pkg/application/application.go:696.16,699.3 2 1
+voltha-go-controller/internal/pkg/application/application.go:706.62,709.50 1 1
+voltha-go-controller/internal/pkg/application/application.go:709.50,713.3 3 5000
+voltha-go-controller/internal/pkg/application/application.go:717.61,719.30 2 0
+voltha-go-controller/internal/pkg/application/application.go:723.2,723.12 1 0
+voltha-go-controller/internal/pkg/application/application.go:719.30,722.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:727.75,728.38 1 0
+voltha-go-controller/internal/pkg/application/application.go:734.2,734.44 1 0
+voltha-go-controller/internal/pkg/application/application.go:728.38,729.24 1 0
+voltha-go-controller/internal/pkg/application/application.go:729.24,732.4 2 0
+voltha-go-controller/internal/pkg/application/application.go:738.58,740.2 1 0
+voltha-go-controller/internal/pkg/application/application.go:743.71,745.56 2 0
+voltha-go-controller/internal/pkg/application/application.go:751.2,753.98 2 0
+voltha-go-controller/internal/pkg/application/application.go:745.56,746.44 1 0
+voltha-go-controller/internal/pkg/application/application.go:746.44,749.4 2 0
+voltha-go-controller/internal/pkg/application/application.go:758.64,782.2 23 0
+voltha-go-controller/internal/pkg/application/application.go:785.47,787.2 1 1
+voltha-go-controller/internal/pkg/application/application.go:790.57,792.2 1 1
+voltha-go-controller/internal/pkg/application/application.go:795.49,797.2 1 1
+voltha-go-controller/internal/pkg/application/application.go:800.53,802.2 1 1
+voltha-go-controller/internal/pkg/application/application.go:805.50,807.2 1 1
+voltha-go-controller/internal/pkg/application/application.go:810.54,812.2 1 1
+voltha-go-controller/internal/pkg/application/application.go:823.102,825.46 2 2
+voltha-go-controller/internal/pkg/application/application.go:828.2,830.47 2 2
+voltha-go-controller/internal/pkg/application/application.go:837.2,837.64 1 2
+voltha-go-controller/internal/pkg/application/application.go:845.2,845.33 1 2
+voltha-go-controller/internal/pkg/application/application.go:825.46,827.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:830.47,836.3 5 1
+voltha-go-controller/internal/pkg/application/application.go:837.64,840.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:840.8,844.3 2 1
+voltha-go-controller/internal/pkg/application/application.go:849.65,850.46 1 56
+voltha-go-controller/internal/pkg/application/application.go:853.2,853.12 1 13
+voltha-go-controller/internal/pkg/application/application.go:850.46,852.3 1 43
+voltha-go-controller/internal/pkg/application/application.go:857.75,859.51 2 2
+voltha-go-controller/internal/pkg/application/application.go:859.51,868.3 8 1
+voltha-go-controller/internal/pkg/application/application.go:868.8,870.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:875.83,878.61 3 3
+voltha-go-controller/internal/pkg/application/application.go:883.2,884.25 2 3
+voltha-go-controller/internal/pkg/application/application.go:878.61,882.3 3 3
+voltha-go-controller/internal/pkg/application/application.go:890.104,893.41 3 2
+voltha-go-controller/internal/pkg/application/application.go:893.41,898.22 5 1
+voltha-go-controller/internal/pkg/application/application.go:898.22,900.4 1 1
+voltha-go-controller/internal/pkg/application/application.go:901.8,904.3 2 1
+voltha-go-controller/internal/pkg/application/application.go:909.89,911.41 2 0
+voltha-go-controller/internal/pkg/application/application.go:911.41,913.41 2 0
+voltha-go-controller/internal/pkg/application/application.go:918.3,918.52 1 0
+voltha-go-controller/internal/pkg/application/application.go:930.3,933.43 4 0
+voltha-go-controller/internal/pkg/application/application.go:913.41,916.4 2 0
+voltha-go-controller/internal/pkg/application/application.go:918.52,920.62 2 0
+voltha-go-controller/internal/pkg/application/application.go:920.62,922.5 1 0
+voltha-go-controller/internal/pkg/application/application.go:922.10,923.48 1 0
+voltha-go-controller/internal/pkg/application/application.go:923.48,927.6 3 0
+voltha-go-controller/internal/pkg/application/application.go:933.43,935.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:936.8,938.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:942.85,946.41 4 1
+voltha-go-controller/internal/pkg/application/application.go:946.41,949.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:949.8,951.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:956.60,960.9 3 2
+voltha-go-controller/internal/pkg/application/application.go:966.2,969.47 2 2
+voltha-go-controller/internal/pkg/application/application.go:979.2,982.12 3 2
+voltha-go-controller/internal/pkg/application/application.go:960.9,963.3 2 1
+voltha-go-controller/internal/pkg/application/application.go:963.8,965.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:969.47,971.41 2 2
+voltha-go-controller/internal/pkg/application/application.go:977.3,977.14 1 1
+voltha-go-controller/internal/pkg/application/application.go:971.41,972.74 1 1
+voltha-go-controller/internal/pkg/application/application.go:975.4,975.16 1 1
+voltha-go-controller/internal/pkg/application/application.go:972.74,974.5 1 1
+voltha-go-controller/internal/pkg/application/application.go:986.175,990.9 3 3
+voltha-go-controller/internal/pkg/application/application.go:994.2,997.17 3 2
+voltha-go-controller/internal/pkg/application/application.go:1000.2,1003.47 2 1
+voltha-go-controller/internal/pkg/application/application.go:1020.2,1022.12 2 1
+voltha-go-controller/internal/pkg/application/application.go:990.9,993.3 2 1
+voltha-go-controller/internal/pkg/application/application.go:997.17,999.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:1003.47,1005.41 2 1
+voltha-go-controller/internal/pkg/application/application.go:1018.3,1018.14 1 0
+voltha-go-controller/internal/pkg/application/application.go:1005.41,1007.73 2 1
+voltha-go-controller/internal/pkg/application/application.go:1015.4,1016.16 2 1
+voltha-go-controller/internal/pkg/application/application.go:1007.73,1009.36 2 1
+voltha-go-controller/internal/pkg/application/application.go:1009.36,1013.6 3 1
+voltha-go-controller/internal/pkg/application/application.go:1026.103,1028.8 2 2
+voltha-go-controller/internal/pkg/application/application.go:1036.2,1036.47 1 1
+voltha-go-controller/internal/pkg/application/application.go:1046.2,1047.12 2 1
+voltha-go-controller/internal/pkg/application/application.go:1028.8,1031.3 2 1
+voltha-go-controller/internal/pkg/application/application.go:1031.8,1034.3 2 1
+voltha-go-controller/internal/pkg/application/application.go:1036.47,1038.41 2 1
+voltha-go-controller/internal/pkg/application/application.go:1044.3,1044.14 1 0
+voltha-go-controller/internal/pkg/application/application.go:1038.41,1039.73 1 1
+voltha-go-controller/internal/pkg/application/application.go:1042.4,1042.16 1 1
+voltha-go-controller/internal/pkg/application/application.go:1039.73,1041.5 1 1
+voltha-go-controller/internal/pkg/application/application.go:1056.70,1060.9 4 2
+voltha-go-controller/internal/pkg/application/application.go:1063.2,1063.37 1 1
+voltha-go-controller/internal/pkg/application/application.go:1060.9,1062.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:1067.94,1070.69 2 0
+voltha-go-controller/internal/pkg/application/application.go:1075.2,1078.48 2 0
+voltha-go-controller/internal/pkg/application/application.go:1070.69,1074.3 3 0
+voltha-go-controller/internal/pkg/application/application.go:1082.55,1084.41 2 2
+voltha-go-controller/internal/pkg/application/application.go:1084.41,1086.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:1086.8,1088.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:1092.57,1094.41 2 2
+voltha-go-controller/internal/pkg/application/application.go:1094.41,1096.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:1096.8,1098.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:1102.120,1105.41 2 1
+voltha-go-controller/internal/pkg/application/application.go:1112.2,1112.63 1 0
+voltha-go-controller/internal/pkg/application/application.go:1105.41,1106.48 1 1
+voltha-go-controller/internal/pkg/application/application.go:1110.3,1110.43 1 0
+voltha-go-controller/internal/pkg/application/application.go:1106.48,1109.4 2 1
+voltha-go-controller/internal/pkg/application/application.go:1116.82,1120.14 3 0
+voltha-go-controller/internal/pkg/application/application.go:1125.2,1126.67 2 0
+voltha-go-controller/internal/pkg/application/application.go:1120.14,1123.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:1130.124,1134.40 4 0
+voltha-go-controller/internal/pkg/application/application.go:1138.2,1138.13 1 0
+voltha-go-controller/internal/pkg/application/application.go:1134.40,1136.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1138.13,1139.16 1 0
+voltha-go-controller/internal/pkg/application/application.go:1139.16,1141.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1142.8,1144.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1148.106,1151.69 2 0
+voltha-go-controller/internal/pkg/application/application.go:1156.2,1156.49 1 0
+voltha-go-controller/internal/pkg/application/application.go:1151.69,1155.3 3 0
+voltha-go-controller/internal/pkg/application/application.go:1164.80,1170.9 6 47
+voltha-go-controller/internal/pkg/application/application.go:1173.2,1174.14 2 33
+voltha-go-controller/internal/pkg/application/application.go:1177.2,1177.15 1 33
+voltha-go-controller/internal/pkg/application/application.go:1170.9,1172.3 1 14
+voltha-go-controller/internal/pkg/application/application.go:1174.14,1176.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1182.67,1186.9 4 16
+voltha-go-controller/internal/pkg/application/application.go:1189.2,1189.30 1 8
+voltha-go-controller/internal/pkg/application/application.go:1186.9,1188.3 1 8
+voltha-go-controller/internal/pkg/application/application.go:1194.69,1198.67 4 0
+voltha-go-controller/internal/pkg/application/application.go:1206.2,1206.22 1 0
+voltha-go-controller/internal/pkg/application/application.go:1198.67,1200.26 2 0
+voltha-go-controller/internal/pkg/application/application.go:1204.3,1204.14 1 0
+voltha-go-controller/internal/pkg/application/application.go:1200.26,1203.4 2 0
+voltha-go-controller/internal/pkg/application/application.go:1210.75,1212.16 2 0
+voltha-go-controller/internal/pkg/application/application.go:1216.2,1216.16 1 0
+voltha-go-controller/internal/pkg/application/application.go:1212.16,1215.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:1221.73,1225.9 4 0
+voltha-go-controller/internal/pkg/application/application.go:1228.2,1228.33 1 0
+voltha-go-controller/internal/pkg/application/application.go:1225.9,1227.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1232.71,1235.22 3 0
+voltha-go-controller/internal/pkg/application/application.go:1238.2,1238.21 1 0
+voltha-go-controller/internal/pkg/application/application.go:1235.22,1237.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1242.86,1245.22 3 0
+voltha-go-controller/internal/pkg/application/application.go:1248.2,1251.21 4 0
+voltha-go-controller/internal/pkg/application/application.go:1245.22,1247.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1255.86,1258.22 3 0
+voltha-go-controller/internal/pkg/application/application.go:1261.2,1261.36 1 0
+voltha-go-controller/internal/pkg/application/application.go:1268.2,1269.21 2 0
+voltha-go-controller/internal/pkg/application/application.go:1258.22,1260.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1261.36,1262.21 1 0
+voltha-go-controller/internal/pkg/application/application.go:1262.21,1265.9 3 0
+voltha-go-controller/internal/pkg/application/application.go:1276.124,1278.13 2 0
+voltha-go-controller/internal/pkg/application/application.go:1278.13,1280.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1280.8,1280.32 1 0
+voltha-go-controller/internal/pkg/application/application.go:1280.32,1283.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1288.84,1292.57 2 0
+voltha-go-controller/internal/pkg/application/application.go:1295.2,1295.55 1 0
+voltha-go-controller/internal/pkg/application/application.go:1292.57,1294.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1295.55,1298.62 2 0
+voltha-go-controller/internal/pkg/application/application.go:1310.3,1310.14 1 0
+voltha-go-controller/internal/pkg/application/application.go:1298.62,1300.19 2 0
+voltha-go-controller/internal/pkg/application/application.go:1303.4,1303.47 1 0
+voltha-go-controller/internal/pkg/application/application.go:1300.19,1302.5 1 0
+voltha-go-controller/internal/pkg/application/application.go:1303.47,1305.60 1 0
+voltha-go-controller/internal/pkg/application/application.go:1305.60,1307.6 1 0
+voltha-go-controller/internal/pkg/application/application.go:1321.88,1324.14 2 0
+voltha-go-controller/internal/pkg/application/application.go:1330.2,1336.14 3 0
+voltha-go-controller/internal/pkg/application/application.go:1341.2,1345.31 4 0
+voltha-go-controller/internal/pkg/application/application.go:1351.2,1352.60 2 0
+voltha-go-controller/internal/pkg/application/application.go:1359.2,1359.21 1 0
+voltha-go-controller/internal/pkg/application/application.go:1364.2,1364.45 1 0
+voltha-go-controller/internal/pkg/application/application.go:1324.14,1327.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:1336.14,1340.3 3 0
+voltha-go-controller/internal/pkg/application/application.go:1345.31,1350.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1352.60,1356.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:1359.21,1362.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:1364.45,1367.35 2 0
+voltha-go-controller/internal/pkg/application/application.go:1378.3,1378.23 1 0
+voltha-go-controller/internal/pkg/application/application.go:1367.35,1371.37 1 0
+voltha-go-controller/internal/pkg/application/application.go:1371.37,1373.5 1 0
+voltha-go-controller/internal/pkg/application/application.go:1374.9,1377.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1404.49,1408.23 3 0
+voltha-go-controller/internal/pkg/application/application.go:1414.2,1414.21 1 0
+voltha-go-controller/internal/pkg/application/application.go:1425.2,1425.13 1 0
+voltha-go-controller/internal/pkg/application/application.go:1408.23,1411.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:1414.21,1415.73 1 0
+voltha-go-controller/internal/pkg/application/application.go:1420.3,1420.79 1 0
+voltha-go-controller/internal/pkg/application/application.go:1423.3,1423.15 1 0
+voltha-go-controller/internal/pkg/application/application.go:1415.73,1417.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1417.9,1419.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1420.79,1422.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1430.90,1434.14 3 0
+voltha-go-controller/internal/pkg/application/application.go:1439.2,1444.14 3 0
+voltha-go-controller/internal/pkg/application/application.go:1449.2,1452.47 3 0
+voltha-go-controller/internal/pkg/application/application.go:1457.2,1457.31 1 0
+voltha-go-controller/internal/pkg/application/application.go:1463.2,1464.60 2 0
+voltha-go-controller/internal/pkg/application/application.go:1470.2,1470.45 1 0
+voltha-go-controller/internal/pkg/application/application.go:1434.14,1437.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:1444.14,1448.3 3 0
+voltha-go-controller/internal/pkg/application/application.go:1452.47,1455.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:1457.31,1462.3 4 0
+voltha-go-controller/internal/pkg/application/application.go:1464.60,1468.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:1470.45,1473.22 3 0
+voltha-go-controller/internal/pkg/application/application.go:1476.3,1476.23 1 0
+voltha-go-controller/internal/pkg/application/application.go:1473.22,1475.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1488.102,1491.33 2 0
+voltha-go-controller/internal/pkg/application/application.go:1495.2,1500.35 4 0
+voltha-go-controller/internal/pkg/application/application.go:1507.2,1507.17 1 0
+voltha-go-controller/internal/pkg/application/application.go:1513.2,1520.17 3 0
+voltha-go-controller/internal/pkg/application/application.go:1528.2,1529.18 2 0
+voltha-go-controller/internal/pkg/application/application.go:1552.2,1553.18 2 0
+voltha-go-controller/internal/pkg/application/application.go:1569.2,1570.19 2 0
+voltha-go-controller/internal/pkg/application/application.go:1491.33,1493.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1500.35,1501.45 1 0
+voltha-go-controller/internal/pkg/application/application.go:1501.45,1503.9 2 0
+voltha-go-controller/internal/pkg/application/application.go:1507.17,1511.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:1520.17,1521.46 1 0
+voltha-go-controller/internal/pkg/application/application.go:1526.3,1526.9 1 0
+voltha-go-controller/internal/pkg/application/application.go:1521.46,1523.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1523.9,1525.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1529.18,1532.42 2 0
+voltha-go-controller/internal/pkg/application/application.go:1550.3,1550.9 1 0
+voltha-go-controller/internal/pkg/application/application.go:1532.42,1535.20 3 0
+voltha-go-controller/internal/pkg/application/application.go:1535.20,1536.51 1 0
+voltha-go-controller/internal/pkg/application/application.go:1536.51,1538.6 1 0
+voltha-go-controller/internal/pkg/application/application.go:1538.11,1540.6 1 0
+voltha-go-controller/internal/pkg/application/application.go:1542.9,1542.50 1 0
+voltha-go-controller/internal/pkg/application/application.go:1542.50,1544.48 2 0
+voltha-go-controller/internal/pkg/application/application.go:1544.48,1546.5 1 0
+voltha-go-controller/internal/pkg/application/application.go:1546.10,1548.5 1 0
+voltha-go-controller/internal/pkg/application/application.go:1553.18,1555.44 2 0
+voltha-go-controller/internal/pkg/application/application.go:1566.3,1566.9 1 0
+voltha-go-controller/internal/pkg/application/application.go:1555.44,1558.20 3 0
+voltha-go-controller/internal/pkg/application/application.go:1558.20,1559.51 1 0
+voltha-go-controller/internal/pkg/application/application.go:1559.51,1561.6 1 0
+voltha-go-controller/internal/pkg/application/application.go:1561.11,1563.6 1 0
+voltha-go-controller/internal/pkg/application/application.go:1570.19,1572.48 2 0
+voltha-go-controller/internal/pkg/application/application.go:1572.48,1574.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1574.9,1576.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1583.50,1585.33 2 0
+voltha-go-controller/internal/pkg/application/application.go:1593.2,1593.14 1 0
+voltha-go-controller/internal/pkg/application/application.go:1585.33,1586.45 1 0
+voltha-go-controller/internal/pkg/application/application.go:1586.45,1588.10 2 0
+voltha-go-controller/internal/pkg/application/application.go:1588.10,1590.5 1 0
+voltha-go-controller/internal/pkg/application/application.go:1597.45,1598.33 1 0
+voltha-go-controller/internal/pkg/application/application.go:1606.2,1606.21 1 0
+voltha-go-controller/internal/pkg/application/application.go:1598.33,1599.45 1 0
+voltha-go-controller/internal/pkg/application/application.go:1599.45,1601.10 2 0
+voltha-go-controller/internal/pkg/application/application.go:1601.10,1603.5 1 0
+voltha-go-controller/internal/pkg/application/application.go:1610.119,1613.22 3 1
+voltha-go-controller/internal/pkg/application/application.go:1632.2,1632.59 1 1
+voltha-go-controller/internal/pkg/application/application.go:1651.2,1662.16 5 1
+voltha-go-controller/internal/pkg/application/application.go:1613.22,1621.62 6 0
+voltha-go-controller/internal/pkg/application/application.go:1625.3,1625.62 1 0
+voltha-go-controller/internal/pkg/application/application.go:1621.62,1623.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1625.62,1627.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1628.8,1630.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:1632.59,1634.28 2 0
+voltha-go-controller/internal/pkg/application/application.go:1649.3,1649.14 1 0
+voltha-go-controller/internal/pkg/application/application.go:1634.28,1635.30 1 0
+voltha-go-controller/internal/pkg/application/application.go:1635.30,1642.24 4 0
+voltha-go-controller/internal/pkg/application/application.go:1642.24,1646.6 2 0
+voltha-go-controller/internal/pkg/application/application.go:1662.16,1663.59 1 0
+voltha-go-controller/internal/pkg/application/application.go:1673.3,1673.64 1 0
+voltha-go-controller/internal/pkg/application/application.go:1663.59,1665.61 2 0
+voltha-go-controller/internal/pkg/application/application.go:1670.4,1671.15 2 0
+voltha-go-controller/internal/pkg/application/application.go:1665.61,1669.5 3 0
+voltha-go-controller/internal/pkg/application/application.go:1674.8,1676.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:1680.55,1683.2 2 3
+voltha-go-controller/internal/pkg/application/application.go:1686.109,1688.14 2 2
+voltha-go-controller/internal/pkg/application/application.go:1693.2,1695.28 2 1
+voltha-go-controller/internal/pkg/application/application.go:1688.14,1691.3 2 1
+voltha-go-controller/internal/pkg/application/application.go:1695.28,1697.72 2 1
+voltha-go-controller/internal/pkg/application/application.go:1697.72,1699.4 1 1
+voltha-go-controller/internal/pkg/application/application.go:1703.55,1708.2 4 2
+voltha-go-controller/internal/pkg/application/application.go:1711.94,1712.66 1 0
+voltha-go-controller/internal/pkg/application/application.go:1719.2,1719.58 1 0
+voltha-go-controller/internal/pkg/application/application.go:1712.66,1714.46 2 0
+voltha-go-controller/internal/pkg/application/application.go:1717.3,1717.14 1 0
+voltha-go-controller/internal/pkg/application/application.go:1714.46,1716.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1730.73,1733.32 3 0
+voltha-go-controller/internal/pkg/application/application.go:1740.2,1740.16 1 0
+voltha-go-controller/internal/pkg/application/application.go:1733.32,1739.3 5 0
+voltha-go-controller/internal/pkg/application/application.go:1744.95,1747.23 2 0
+voltha-go-controller/internal/pkg/application/application.go:1747.23,1750.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1750.8,1756.58 4 0
+voltha-go-controller/internal/pkg/application/application.go:1768.3,1768.71 1 0
+voltha-go-controller/internal/pkg/application/application.go:1781.3,1786.54 4 0
+voltha-go-controller/internal/pkg/application/application.go:1756.58,1758.59 2 0
+voltha-go-controller/internal/pkg/application/application.go:1765.4,1765.15 1 0
+voltha-go-controller/internal/pkg/application/application.go:1758.59,1759.33 1 0
+voltha-go-controller/internal/pkg/application/application.go:1759.33,1762.11 3 0
+voltha-go-controller/internal/pkg/application/application.go:1768.71,1770.50 2 0
+voltha-go-controller/internal/pkg/application/application.go:1778.4,1778.15 1 0
+voltha-go-controller/internal/pkg/application/application.go:1770.50,1771.33 1 0
+voltha-go-controller/internal/pkg/application/application.go:1771.33,1775.11 4 0
+voltha-go-controller/internal/pkg/application/application.go:1792.39,1794.47 2 0
+voltha-go-controller/internal/pkg/application/application.go:1816.2,1818.25 2 0
+voltha-go-controller/internal/pkg/application/application.go:1822.2,1822.23 1 0
+voltha-go-controller/internal/pkg/application/application.go:1794.47,1796.28 2 0
+voltha-go-controller/internal/pkg/application/application.go:1814.3,1814.14 1 0
+voltha-go-controller/internal/pkg/application/application.go:1796.28,1797.76 1 0
+voltha-go-controller/internal/pkg/application/application.go:1797.76,1799.39 2 0
+voltha-go-controller/internal/pkg/application/application.go:1807.5,1807.46 1 0
+voltha-go-controller/internal/pkg/application/application.go:1799.39,1801.6 1 0
+voltha-go-controller/internal/pkg/application/application.go:1801.11,1801.80 1 0
+voltha-go-controller/internal/pkg/application/application.go:1801.80,1803.6 1 0
+voltha-go-controller/internal/pkg/application/application.go:1803.11,1805.14 2 0
+voltha-go-controller/internal/pkg/application/application.go:1807.46,1811.6 3 0
+voltha-go-controller/internal/pkg/application/application.go:1818.25,1821.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:1826.77,1827.32 1 2
+voltha-go-controller/internal/pkg/application/application.go:1835.2,1836.11 2 1
+voltha-go-controller/internal/pkg/application/application.go:1827.32,1830.54 3 2
+voltha-go-controller/internal/pkg/application/application.go:1830.54,1833.4 2 1
+voltha-go-controller/internal/pkg/application/application.go:1840.86,1841.32 1 1
+voltha-go-controller/internal/pkg/application/application.go:1841.32,1846.3 4 1
+voltha-go-controller/internal/pkg/application/application.go:1850.73,1851.32 1 1
+voltha-go-controller/internal/pkg/application/application.go:1851.32,1857.3 5 1
+voltha-go-controller/internal/pkg/application/application.go:1861.65,1873.33 6 0
+voltha-go-controller/internal/pkg/application/application.go:1873.33,1876.48 2 0
+voltha-go-controller/internal/pkg/application/application.go:1879.3,1882.35 2 0
+voltha-go-controller/internal/pkg/application/application.go:1876.48,1878.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1887.90,1894.42 5 0
+voltha-go-controller/internal/pkg/application/application.go:1898.2,1898.14 1 0
+voltha-go-controller/internal/pkg/application/application.go:1894.42,1897.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:1902.112,1910.2 5 0
+voltha-go-controller/internal/pkg/application/application.go:1916.93,1917.47 1 0
+voltha-go-controller/internal/pkg/application/application.go:1917.47,1919.26 2 0
+voltha-go-controller/internal/pkg/application/application.go:1919.26,1920.35 1 0
+voltha-go-controller/internal/pkg/application/application.go:1920.35,1922.5 1 0
+voltha-go-controller/internal/pkg/application/application.go:1928.77,1930.47 2 0
+voltha-go-controller/internal/pkg/application/application.go:1930.47,1932.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:1936.97,1947.29 7 0
+voltha-go-controller/internal/pkg/application/application.go:1953.2,1953.24 1 0
+voltha-go-controller/internal/pkg/application/application.go:1967.2,1967.12 1 0
+voltha-go-controller/internal/pkg/application/application.go:1947.29,1950.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:1953.24,1955.31 1 0
+voltha-go-controller/internal/pkg/application/application.go:1961.3,1961.33 1 0
+voltha-go-controller/internal/pkg/application/application.go:1955.31,1958.4 2 0
+voltha-go-controller/internal/pkg/application/application.go:1961.33,1963.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1974.106,1982.17 5 1
+voltha-go-controller/internal/pkg/application/application.go:1989.2,1989.38 1 1
+voltha-go-controller/internal/pkg/application/application.go:1982.17,1984.3 1 1
+voltha-go-controller/internal/pkg/application/application.go:1989.38,1991.44 2 0
+voltha-go-controller/internal/pkg/application/application.go:1991.44,1993.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:1997.65,1999.2 1 1
+voltha-go-controller/internal/pkg/application/application.go:2001.70,2003.71 2 0
+voltha-go-controller/internal/pkg/application/application.go:2008.2,2008.42 1 0
+voltha-go-controller/internal/pkg/application/application.go:2003.71,2007.3 3 0
+voltha-go-controller/internal/pkg/application/application.go:2012.96,2017.2 4 1
+voltha-go-controller/internal/pkg/application/application.go:2020.96,2022.47 2 2
+voltha-go-controller/internal/pkg/application/application.go:2022.47,2024.50 2 1
+voltha-go-controller/internal/pkg/application/application.go:2024.50,2025.27 1 1
+voltha-go-controller/internal/pkg/application/application.go:2025.27,2028.23 3 1
+voltha-go-controller/internal/pkg/application/application.go:2028.23,2030.6 1 1
+voltha-go-controller/internal/pkg/application/application.go:2032.9,2034.4 1 0
+voltha-go-controller/internal/pkg/application/application.go:2039.92,2041.44 2 2
+voltha-go-controller/internal/pkg/application/application.go:2041.44,2042.27 1 1
+voltha-go-controller/internal/pkg/application/application.go:2042.27,2045.4 2 1
+voltha-go-controller/internal/pkg/application/application.go:2050.93,2052.41 2 2
+voltha-go-controller/internal/pkg/application/application.go:2052.41,2053.68 1 1
+voltha-go-controller/internal/pkg/application/application.go:2053.68,2056.121 3 1
+voltha-go-controller/internal/pkg/application/application.go:2056.121,2059.5 2 0
+voltha-go-controller/internal/pkg/application/application.go:2059.10,2061.5 1 1
+voltha-go-controller/internal/pkg/application/application.go:2076.102,2080.16 4 1
+voltha-go-controller/internal/pkg/application/application.go:2084.2,2084.43 1 1
+voltha-go-controller/internal/pkg/application/application.go:2080.16,2083.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:2088.72,2090.16 2 1
+voltha-go-controller/internal/pkg/application/application.go:2094.2,2095.16 2 1
+voltha-go-controller/internal/pkg/application/application.go:2099.2,2099.120 1 0
+voltha-go-controller/internal/pkg/application/application.go:2090.16,2093.3 2 0
+voltha-go-controller/internal/pkg/application/application.go:2095.16,2098.3 2 1
+voltha-go-controller/internal/pkg/application/application.go:2102.97,2106.16 4 1
+voltha-go-controller/internal/pkg/application/application.go:2109.2,2112.19 3 1
+voltha-go-controller/internal/pkg/application/application.go:2106.16,2108.3 1 0
+voltha-go-controller/internal/pkg/application/application.go:2112.19,2115.3 2 1
+voltha-go-controller/internal/pkg/controller/controller.go:40.13,44.16 3 1
+voltha-go-controller/internal/pkg/controller/controller.go:44.16,45.13 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:69.75,82.2 11 0
+voltha-go-controller/internal/pkg/controller/controller.go:86.67,88.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:91.69,93.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:96.99,111.2 11 0
+voltha-go-controller/internal/pkg/controller/controller.go:114.69,116.8 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:120.2,122.64 3 0
+voltha-go-controller/internal/pkg/controller/controller.go:116.8,119.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:126.76,130.66 4 0
+voltha-go-controller/internal/pkg/controller/controller.go:136.2,137.138 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:130.66,133.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:133.8,135.3 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:142.65,145.2 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:148.64,150.8 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:153.2,153.42 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:150.8,152.3 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:157.74,162.2 4 0
+voltha-go-controller/internal/pkg/controller/controller.go:165.75,169.8 4 0
+voltha-go-controller/internal/pkg/controller/controller.go:172.2,176.16 4 0
+voltha-go-controller/internal/pkg/controller/controller.go:182.2,182.13 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:169.8,171.3 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:176.16,178.3 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:178.8,180.3 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:186.77,190.9 4 0
+voltha-go-controller/internal/pkg/controller/controller.go:193.2,195.13 3 0
+voltha-go-controller/internal/pkg/controller/controller.go:190.9,192.3 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:199.102,205.2 5 0
+voltha-go-controller/internal/pkg/controller/controller.go:208.77,210.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:213.94,215.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:218.96,220.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:223.56,226.2 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:229.58,232.2 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:235.107,237.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:240.71,242.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:245.72,247.8 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:250.2,250.46 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:247.8,249.3 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:254.121,257.16 3 0
+voltha-go-controller/internal/pkg/controller/controller.go:260.2,261.58 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:257.16,259.3 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:265.110,267.16 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:271.2,272.20 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:276.2,276.18 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:282.2,283.24 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:293.2,293.25 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:312.2,312.12 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:267.16,270.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:272.20,275.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:276.18,280.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:283.24,286.41 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:286.41,287.88 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:287.88,288.10 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:293.25,296.41 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:296.41,298.64 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:301.4,301.51 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:298.64,300.5 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:301.51,303.5 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:305.8,308.37 3 0
+voltha-go-controller/internal/pkg/controller/controller.go:308.37,310.4 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:316.110,318.16 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:322.2,323.20 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:327.2,327.18 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:333.2,334.24 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:344.2,344.25 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:360.2,360.12 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:318.16,321.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:323.20,326.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:327.18,331.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:334.24,337.41 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:337.41,338.88 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:338.88,339.10 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:344.25,347.41 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:347.41,349.64 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:349.64,351.5 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:353.8,356.37 3 0
+voltha-go-controller/internal/pkg/controller/controller.go:356.37,358.4 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:364.89,366.16 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:371.2,372.20 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:377.2,377.18 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:383.2,384.12 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:366.16,369.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:372.20,375.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:377.18,381.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:388.111,390.16 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:395.2,396.20 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:401.2,402.12 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:390.16,393.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:396.20,399.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:406.98,408.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:411.87,413.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:416.79,418.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:421.86,423.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:426.88,428.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:431.53,433.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:436.55,438.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:441.101,443.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:446.86,448.16 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:452.2,452.29 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:448.16,451.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:456.83,458.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:461.38,463.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:502.66,504.32 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:508.2,508.24 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:504.32,507.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:512.71,514.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:517.71,519.2 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:522.74,525.2 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:528.91,530.16 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:534.2,534.39 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:537.2,537.17 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:530.16,533.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:534.39,536.3 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:541.79,543.16 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:547.2,547.29 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:543.16,546.3 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:551.67,553.30 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:556.2,556.19 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:553.30,555.3 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:560.74,562.30 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:565.2,565.19 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:562.30,564.3 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:567.76,570.35 3 0
+voltha-go-controller/internal/pkg/controller/controller.go:577.2,577.20 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:570.35,572.39 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:575.3,575.84 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:572.39,574.4 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:580.102,583.35 3 0
+voltha-go-controller/internal/pkg/controller/controller.go:593.2,593.20 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:583.35,586.17 3 0
+voltha-go-controller/internal/pkg/controller/controller.go:590.3,591.60 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:586.17,589.4 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:596.62,599.35 3 0
+voltha-go-controller/internal/pkg/controller/controller.go:613.2,614.20 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:599.35,600.57 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:600.57,605.11 4 0
+voltha-go-controller/internal/pkg/controller/controller.go:608.4,610.15 3 0
+voltha-go-controller/internal/pkg/controller/controller.go:605.11,607.5 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:617.88,620.35 3 0
+voltha-go-controller/internal/pkg/controller/controller.go:629.2,629.20 1 0
+voltha-go-controller/internal/pkg/controller/controller.go:620.35,623.10 3 0
+voltha-go-controller/internal/pkg/controller/controller.go:626.3,627.61 2 0
+voltha-go-controller/internal/pkg/controller/controller.go:623.10,625.4 1 0
+voltha-go-controller/internal/pkg/controller/device.go:70.49,82.2 8 0
+voltha-go-controller/internal/pkg/controller/device.go:91.51,95.2 3 0
+voltha-go-controller/internal/pkg/controller/device.go:149.159,167.16 17 0
+voltha-go-controller/internal/pkg/controller/device.go:178.2,179.16 2 0
+voltha-go-controller/internal/pkg/controller/device.go:167.16,169.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:169.8,172.17 3 0
+voltha-go-controller/internal/pkg/controller/device.go:172.17,174.4 1 0
+voltha-go-controller/internal/pkg/controller/device.go:174.9,176.4 1 0
+voltha-go-controller/internal/pkg/controller/device.go:183.31,188.2 4 0
+voltha-go-controller/internal/pkg/controller/device.go:191.65,197.2 5 0
+voltha-go-controller/internal/pkg/controller/device.go:200.50,205.28 5 0
+voltha-go-controller/internal/pkg/controller/device.go:208.2,208.14 1 0
+voltha-go-controller/internal/pkg/controller/device.go:205.28,207.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:212.57,217.28 5 0
+voltha-go-controller/internal/pkg/controller/device.go:222.2,222.14 1 0
+voltha-go-controller/internal/pkg/controller/device.go:217.28,218.35 1 0
+voltha-go-controller/internal/pkg/controller/device.go:218.35,220.4 1 0
+voltha-go-controller/internal/pkg/controller/device.go:226.76,230.39 4 0
+voltha-go-controller/internal/pkg/controller/device.go:233.2,235.12 3 0
+voltha-go-controller/internal/pkg/controller/device.go:230.39,232.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:239.74,240.46 1 0
+voltha-go-controller/internal/pkg/controller/device.go:240.46,241.71 1 0
+voltha-go-controller/internal/pkg/controller/device.go:241.71,243.4 1 0
+voltha-go-controller/internal/pkg/controller/device.go:248.76,251.39 3 0
+voltha-go-controller/internal/pkg/controller/device.go:256.2,256.42 1 0
+voltha-go-controller/internal/pkg/controller/device.go:251.39,255.3 3 0
+voltha-go-controller/internal/pkg/controller/device.go:260.69,262.2 1 0
+voltha-go-controller/internal/pkg/controller/device.go:265.72,268.39 3 0
+voltha-go-controller/internal/pkg/controller/device.go:276.2,276.14 1 0
+voltha-go-controller/internal/pkg/controller/device.go:268.39,270.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:270.8,270.65 1 0
+voltha-go-controller/internal/pkg/controller/device.go:270.65,271.43 1 0
+voltha-go-controller/internal/pkg/controller/device.go:271.43,274.4 2 0
+voltha-go-controller/internal/pkg/controller/device.go:280.89,283.42 3 0
+voltha-go-controller/internal/pkg/controller/device.go:290.2,290.42 1 0
+voltha-go-controller/internal/pkg/controller/device.go:283.42,289.3 4 0
+voltha-go-controller/internal/pkg/controller/device.go:294.59,296.29 2 0
+voltha-go-controller/internal/pkg/controller/device.go:296.29,298.10 2 0
+voltha-go-controller/internal/pkg/controller/device.go:302.3,302.28 1 0
+voltha-go-controller/internal/pkg/controller/device.go:298.10,300.12 2 0
+voltha-go-controller/internal/pkg/controller/device.go:307.49,309.49 2 0
+voltha-go-controller/internal/pkg/controller/device.go:309.49,310.41 1 0
+voltha-go-controller/internal/pkg/controller/device.go:310.41,313.4 2 0
+voltha-go-controller/internal/pkg/controller/device.go:313.9,315.4 1 0
+voltha-go-controller/internal/pkg/controller/device.go:316.8,318.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:326.74,330.2 3 0
+voltha-go-controller/internal/pkg/controller/device.go:333.70,334.47 1 0
+voltha-go-controller/internal/pkg/controller/device.go:334.47,336.74 2 0
+voltha-go-controller/internal/pkg/controller/device.go:336.74,338.4 1 0
+voltha-go-controller/internal/pkg/controller/device.go:343.71,344.47 1 0
+voltha-go-controller/internal/pkg/controller/device.go:344.47,347.3 2 0
+voltha-go-controller/internal/pkg/controller/device.go:351.71,353.2 1 0
+voltha-go-controller/internal/pkg/controller/device.go:356.60,359.31 3 0
+voltha-go-controller/internal/pkg/controller/device.go:359.31,361.10 2 0
+voltha-go-controller/internal/pkg/controller/device.go:365.3,365.29 1 0
+voltha-go-controller/internal/pkg/controller/device.go:361.10,363.12 2 0
+voltha-go-controller/internal/pkg/controller/device.go:370.50,372.50 2 0
+voltha-go-controller/internal/pkg/controller/device.go:372.50,373.49 1 0
+voltha-go-controller/internal/pkg/controller/device.go:373.49,376.4 2 0
+voltha-go-controller/internal/pkg/controller/device.go:376.9,378.4 1 0
+voltha-go-controller/internal/pkg/controller/device.go:379.8,381.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:385.72,388.37 3 0
+voltha-go-controller/internal/pkg/controller/device.go:391.2,393.12 3 0
+voltha-go-controller/internal/pkg/controller/device.go:388.37,390.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:397.75,400.37 3 0
+voltha-go-controller/internal/pkg/controller/device.go:406.2,406.12 1 0
+voltha-go-controller/internal/pkg/controller/device.go:400.37,403.3 2 0
+voltha-go-controller/internal/pkg/controller/device.go:403.8,405.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:410.57,413.31 3 0
+voltha-go-controller/internal/pkg/controller/device.go:416.2,416.43 1 0
+voltha-go-controller/internal/pkg/controller/device.go:413.31,415.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:420.71,423.37 3 0
+voltha-go-controller/internal/pkg/controller/device.go:428.2,428.14 1 0
+voltha-go-controller/internal/pkg/controller/device.go:423.37,427.3 3 0
+voltha-go-controller/internal/pkg/controller/device.go:432.70,433.47 1 0
+voltha-go-controller/internal/pkg/controller/device.go:433.47,434.75 1 0
+voltha-go-controller/internal/pkg/controller/device.go:434.75,436.4 1 0
+voltha-go-controller/internal/pkg/controller/device.go:441.66,443.2 1 0
+voltha-go-controller/internal/pkg/controller/device.go:446.60,448.31 2 0
+voltha-go-controller/internal/pkg/controller/device.go:448.31,450.10 2 0
+voltha-go-controller/internal/pkg/controller/device.go:454.3,454.29 1 0
+voltha-go-controller/internal/pkg/controller/device.go:450.10,452.12 2 0
+voltha-go-controller/internal/pkg/controller/device.go:459.50,461.50 2 0
+voltha-go-controller/internal/pkg/controller/device.go:461.50,462.39 1 0
+voltha-go-controller/internal/pkg/controller/device.go:462.39,465.4 2 0
+voltha-go-controller/internal/pkg/controller/device.go:465.9,467.4 1 0
+voltha-go-controller/internal/pkg/controller/device.go:468.8,470.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:474.60,476.2 1 0
+voltha-go-controller/internal/pkg/controller/device.go:480.71,485.34 5 0
+voltha-go-controller/internal/pkg/controller/device.go:488.2,488.38 1 0
+voltha-go-controller/internal/pkg/controller/device.go:492.2,498.12 7 0
+voltha-go-controller/internal/pkg/controller/device.go:485.34,487.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:488.38,490.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:503.65,505.14 2 0
+voltha-go-controller/internal/pkg/controller/device.go:508.2,508.28 1 0
+voltha-go-controller/internal/pkg/controller/device.go:511.2,520.12 8 0
+voltha-go-controller/internal/pkg/controller/device.go:505.14,507.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:508.28,510.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:524.83,529.9 4 0
+voltha-go-controller/internal/pkg/controller/device.go:532.2,537.95 6 0
+voltha-go-controller/internal/pkg/controller/device.go:529.9,531.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:541.57,545.34 3 0
+voltha-go-controller/internal/pkg/controller/device.go:548.2,549.42 2 0
+voltha-go-controller/internal/pkg/controller/device.go:545.34,547.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:553.53,558.8 4 0
+voltha-go-controller/internal/pkg/controller/device.go:561.2,561.12 1 0
+voltha-go-controller/internal/pkg/controller/device.go:558.8,560.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:565.57,570.8 4 0
+voltha-go-controller/internal/pkg/controller/device.go:573.2,573.12 1 0
+voltha-go-controller/internal/pkg/controller/device.go:570.8,572.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:577.63,581.38 3 0
+voltha-go-controller/internal/pkg/controller/device.go:584.2,584.53 1 0
+voltha-go-controller/internal/pkg/controller/device.go:581.38,583.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:588.57,592.38 3 0
+voltha-go-controller/internal/pkg/controller/device.go:595.2,595.41 1 0
+voltha-go-controller/internal/pkg/controller/device.go:592.38,594.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:599.71,601.46 2 0
+voltha-go-controller/internal/pkg/controller/device.go:601.46,602.66 1 0
+voltha-go-controller/internal/pkg/controller/device.go:602.66,604.4 1 0
+voltha-go-controller/internal/pkg/controller/device.go:609.65,611.2 1 0
+voltha-go-controller/internal/pkg/controller/device.go:614.59,616.29 2 0
+voltha-go-controller/internal/pkg/controller/device.go:616.29,618.10 2 0
+voltha-go-controller/internal/pkg/controller/device.go:622.3,622.34 1 0
+voltha-go-controller/internal/pkg/controller/device.go:618.10,620.12 2 0
+voltha-go-controller/internal/pkg/controller/device.go:627.71,629.49 2 0
+voltha-go-controller/internal/pkg/controller/device.go:629.49,630.41 1 0
+voltha-go-controller/internal/pkg/controller/device.go:630.41,635.4 4 0
+voltha-go-controller/internal/pkg/controller/device.go:635.9,637.4 1 0
+voltha-go-controller/internal/pkg/controller/device.go:638.8,640.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:646.27,648.2 1 0
+voltha-go-controller/internal/pkg/controller/device.go:651.26,652.2 0 0
+voltha-go-controller/internal/pkg/controller/device.go:656.79,679.2 17 0
+voltha-go-controller/internal/pkg/controller/device.go:681.44,684.6 2 0
+voltha-go-controller/internal/pkg/controller/device.go:694.2,694.13 1 0
+voltha-go-controller/internal/pkg/controller/device.go:684.6,685.10 1 0
+voltha-go-controller/internal/pkg/controller/device.go:686.23,688.14 2 0
+voltha-go-controller/internal/pkg/controller/device.go:689.17,691.23 2 0
+voltha-go-controller/internal/pkg/controller/device.go:698.32,713.2 11 0
+voltha-go-controller/internal/pkg/controller/device.go:716.34,721.2 4 0
+voltha-go-controller/internal/pkg/controller/device.go:724.56,727.36 2 0
+voltha-go-controller/internal/pkg/controller/device.go:733.2,737.28 5 0
+voltha-go-controller/internal/pkg/controller/device.go:727.36,731.3 3 0
+voltha-go-controller/internal/pkg/controller/device.go:741.58,746.2 4 0
+voltha-go-controller/internal/pkg/controller/device.go:749.59,755.35 4 0
+voltha-go-controller/internal/pkg/controller/device.go:755.35,756.34 1 0
+voltha-go-controller/internal/pkg/controller/device.go:756.34,761.4 4 0
+voltha-go-controller/internal/pkg/controller/device.go:766.63,772.35 4 0
+voltha-go-controller/internal/pkg/controller/device.go:772.35,773.34 1 0
+voltha-go-controller/internal/pkg/controller/device.go:773.34,777.4 3 0
+voltha-go-controller/internal/pkg/controller/device.go:783.102,784.46 1 0
+voltha-go-controller/internal/pkg/controller/device.go:784.46,785.19 1 0
+voltha-go-controller/internal/pkg/controller/device.go:794.3,794.40 1 0
+voltha-go-controller/internal/pkg/controller/device.go:785.19,787.32 2 0
+voltha-go-controller/internal/pkg/controller/device.go:791.4,792.64 2 0
+voltha-go-controller/internal/pkg/controller/device.go:787.32,790.5 2 0
+voltha-go-controller/internal/pkg/controller/device.go:814.84,815.55 1 0
+voltha-go-controller/internal/pkg/controller/device.go:819.2,819.40 1 0
+voltha-go-controller/internal/pkg/controller/device.go:815.55,818.3 2 0
+voltha-go-controller/internal/pkg/controller/device.go:819.40,826.79 3 0
+voltha-go-controller/internal/pkg/controller/device.go:826.79,832.4 4 0
+voltha-go-controller/internal/pkg/controller/device.go:832.9,832.90 1 0
+voltha-go-controller/internal/pkg/controller/device.go:832.90,838.4 4 0
+voltha-go-controller/internal/pkg/controller/device.go:838.9,840.4 1 0
+voltha-go-controller/internal/pkg/controller/device.go:845.95,846.55 1 0
+voltha-go-controller/internal/pkg/controller/device.go:850.2,850.40 1 0
+voltha-go-controller/internal/pkg/controller/device.go:846.55,849.3 2 0
+voltha-go-controller/internal/pkg/controller/device.go:850.40,853.29 3 0
+voltha-go-controller/internal/pkg/controller/device.go:853.29,856.4 2 0
+voltha-go-controller/internal/pkg/controller/device.go:856.9,856.38 1 0
+voltha-go-controller/internal/pkg/controller/device.go:856.38,859.4 2 0
+voltha-go-controller/internal/pkg/controller/device.go:866.60,870.2 3 0
+voltha-go-controller/internal/pkg/controller/device.go:874.68,876.62 2 0
+voltha-go-controller/internal/pkg/controller/device.go:880.2,882.51 3 0
+voltha-go-controller/internal/pkg/controller/device.go:876.62,879.3 2 0
+voltha-go-controller/internal/pkg/controller/device.go:882.51,884.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:884.8,886.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:890.51,891.44 1 0
+voltha-go-controller/internal/pkg/controller/device.go:902.2,902.10 1 0
+voltha-go-controller/internal/pkg/controller/device.go:891.44,892.62 1 0
+voltha-go-controller/internal/pkg/controller/device.go:892.62,893.67 1 0
+voltha-go-controller/internal/pkg/controller/device.go:893.67,894.74 1 0
+voltha-go-controller/internal/pkg/controller/device.go:894.74,895.76 1 0
+voltha-go-controller/internal/pkg/controller/device.go:895.76,897.7 1 0
+voltha-go-controller/internal/pkg/controller/device.go:907.99,909.16 2 0
+voltha-go-controller/internal/pkg/controller/device.go:912.2,913.17 2 0
+voltha-go-controller/internal/pkg/controller/device.go:916.2,917.54 2 0
+voltha-go-controller/internal/pkg/controller/device.go:909.16,911.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:913.17,915.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:922.100,942.2 9 0
+voltha-go-controller/internal/pkg/controller/device.go:947.70,951.32 3 0
+voltha-go-controller/internal/pkg/controller/device.go:957.2,958.22 2 0
+voltha-go-controller/internal/pkg/controller/device.go:951.32,955.3 2 0
+voltha-go-controller/internal/pkg/controller/device.go:958.22,962.3 3 0
+voltha-go-controller/internal/pkg/controller/device.go:962.8,966.3 2 0
+voltha-go-controller/internal/pkg/controller/device.go:970.68,974.2 3 0
+voltha-go-controller/internal/pkg/controller/device.go:977.90,978.35 1 0
+voltha-go-controller/internal/pkg/controller/device.go:984.2,985.20 2 0
+voltha-go-controller/internal/pkg/controller/device.go:978.35,979.49 1 0
+voltha-go-controller/internal/pkg/controller/device.go:979.49,982.4 2 0
+voltha-go-controller/internal/pkg/controller/device.go:988.72,991.21 2 0
+voltha-go-controller/internal/pkg/controller/device.go:995.2,996.60 2 0
+voltha-go-controller/internal/pkg/controller/device.go:1000.2,1003.35 3 0
+voltha-go-controller/internal/pkg/controller/device.go:991.21,994.3 2 0
+voltha-go-controller/internal/pkg/controller/device.go:996.60,999.3 2 0
+voltha-go-controller/internal/pkg/controller/device.go:1006.66,1014.2 7 0
+voltha-go-controller/internal/pkg/controller/device.go:1017.65,1023.2 4 0
+voltha-go-controller/internal/pkg/controller/device.go:1025.58,1027.16 2 0
+voltha-go-controller/internal/pkg/controller/device.go:1031.2,1031.65 1 0
+voltha-go-controller/internal/pkg/controller/device.go:1027.16,1030.3 2 0
+voltha-go-controller/internal/pkg/controller/device.go:1031.65,1033.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:1037.57,1038.30 1 0
+voltha-go-controller/internal/pkg/controller/device.go:1042.2,1042.51 1 0
+voltha-go-controller/internal/pkg/controller/device.go:1046.2,1046.14 1 0
+voltha-go-controller/internal/pkg/controller/device.go:1038.30,1040.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:1042.51,1044.3 1 0
+voltha-go-controller/internal/pkg/controller/device.go:1049.136,1052.2 2 0
+voltha-go-controller/internal/pkg/controller/device.go:1054.164,1058.62 3 0
+voltha-go-controller/internal/pkg/controller/device.go:1069.2,1069.27 1 0
+voltha-go-controller/internal/pkg/controller/device.go:1088.2,1099.66 3 0
+voltha-go-controller/internal/pkg/controller/device.go:1058.62,1059.42 1 0
+voltha-go-controller/internal/pkg/controller/device.go:1059.42,1063.4 3 0
+voltha-go-controller/internal/pkg/controller/device.go:1069.27,1072.15 3 0
+voltha-go-controller/internal/pkg/controller/device.go:1076.3,1077.89 2 0
+voltha-go-controller/internal/pkg/controller/device.go:1072.15,1075.4 2 0
+voltha-go-controller/internal/pkg/controller/device.go:1078.8,1079.29 1 0
+voltha-go-controller/internal/pkg/controller/device.go:1079.29,1080.48 1 0
+voltha-go-controller/internal/pkg/controller/device.go:1080.48,1082.5 1 0
+voltha-go-controller/internal/pkg/controller/device.go:1083.9,1083.22 1 0
+voltha-go-controller/internal/pkg/controller/device.go:1083.22,1085.4 1 0
+voltha-go-controller/internal/pkg/controller/pendingprofiles.go:34.66,39.2 4 0
+voltha-go-controller/internal/pkg/controller/pendingprofiles.go:42.47,44.2 1 0
+voltha-go-controller/internal/pkg/controller/pendingprofiles.go:47.48,49.2 1 0
+voltha-go-controller/internal/pkg/controller/pendingprofiles.go:52.52,54.2 1 0
+voltha-go-controller/internal/pkg/controller/pendingprofiles.go:57.41,58.2 0 0
+voltha-go-controller/internal/pkg/controller/pendingprofiles.go:62.80,84.53 14 0
+voltha-go-controller/internal/pkg/controller/pendingprofiles.go:88.2,91.16 3 0
+voltha-go-controller/internal/pkg/controller/pendingprofiles.go:84.53,87.3 2 0
+voltha-go-controller/internal/pkg/controller/pendingprofiles.go:95.81,98.2 2 0
+voltha-go-controller/internal/pkg/controller/utils.go:28.22,33.2 4 0
+voltha-go-controller/internal/pkg/controller/utils.go:36.50,42.2 5 0
+voltha-go-controller/internal/pkg/controller/addflows.go:43.92,51.2 7 0
+voltha-go-controller/internal/pkg/controller/addflows.go:54.40,55.41 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:58.2,58.25 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:55.41,57.3 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:62.41,64.2 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:67.45,69.2 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:72.34,73.2 0 0
+voltha-go-controller/internal/pkg/controller/addflows.go:76.73,83.41 6 0
+voltha-go-controller/internal/pkg/controller/addflows.go:115.2,115.44 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:121.2,121.53 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:134.2,134.55 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:141.2,142.29 2 0
+voltha-go-controller/internal/pkg/controller/addflows.go:168.2,168.12 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:83.41,85.40 2 0
+voltha-go-controller/internal/pkg/controller/addflows.go:85.40,87.55 2 0
+voltha-go-controller/internal/pkg/controller/addflows.go:101.4,101.38 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:87.55,93.40 2 0
+voltha-go-controller/internal/pkg/controller/addflows.go:93.40,95.43 2 0
+voltha-go-controller/internal/pkg/controller/addflows.go:95.43,98.7 2 0
+voltha-go-controller/internal/pkg/controller/addflows.go:102.9,104.11 2 0
+voltha-go-controller/internal/pkg/controller/addflows.go:111.4,111.100 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:104.11,106.5 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:106.10,110.5 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:115.44,117.3 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:121.53,123.54 2 0
+voltha-go-controller/internal/pkg/controller/addflows.go:123.54,124.43 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:130.4,130.14 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:124.43,126.42 2 0
+voltha-go-controller/internal/pkg/controller/addflows.go:126.42,128.6 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:134.55,135.42 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:138.3,138.13 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:135.42,137.4 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:142.29,144.49 2 0
+voltha-go-controller/internal/pkg/controller/addflows.go:144.49,145.8 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:163.4,163.108 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:145.8,146.76 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:161.5,161.10 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:146.76,152.96 3 0
+voltha-go-controller/internal/pkg/controller/addflows.go:152.96,153.35 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:158.7,158.114 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:153.35,156.16 3 0
+voltha-go-controller/internal/pkg/controller/addflows.go:164.9,166.4 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:171.65,174.45 2 1
+voltha-go-controller/internal/pkg/controller/addflows.go:178.2,178.81 1 1
+voltha-go-controller/internal/pkg/controller/addflows.go:183.2,183.14 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:174.45,176.3 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:178.81,180.3 1 1
+voltha-go-controller/internal/pkg/controller/addflows.go:180.8,180.84 1 0
+voltha-go-controller/internal/pkg/controller/addflows.go:180.84,182.3 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:55.72,63.2 7 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:66.38,68.2 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:71.39,73.2 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:76.43,78.2 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:81.31,83.2 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:86.71,91.13 4 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:96.2,97.16 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:107.2,108.35 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:113.2,116.59 3 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:141.2,141.55 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:146.2,146.47 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:156.2,158.13 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:162.2,166.12 5 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:91.13,94.3 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:97.16,99.3 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:108.35,111.3 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:116.59,119.42 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:137.3,137.111 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:119.42,120.194 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:131.4,131.28 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:120.194,125.5 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:125.10,130.5 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:132.9,136.4 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:141.55,144.3 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:146.47,147.22 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:151.3,151.14 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:154.3,154.32 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:147.22,149.12 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:151.14,152.9 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:158.13,161.3 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:170.91,173.42 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:188.2,188.34 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:193.2,193.30 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:173.42,178.53 3 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:181.3,181.54 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:184.3,184.103 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:178.53,180.4 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:181.54,183.4 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:188.34,191.3 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:193.30,194.26 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:194.26,196.4 1 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:201.75,203.25 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:203.25,206.53 2 0
+voltha-go-controller/internal/pkg/controller/auditdevice.go:206.53,208.4 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:50.58,57.2 6 0
+voltha-go-controller/internal/pkg/controller/audittables.go:60.43,62.2 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:65.44,67.2 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:70.48,72.2 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:75.36,77.2 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:81.76,89.40 6 0
+voltha-go-controller/internal/pkg/controller/audittables.go:95.2,95.41 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:101.2,101.53 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:107.2,107.43 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:114.2,117.16 4 0
+voltha-go-controller/internal/pkg/controller/audittables.go:89.40,92.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:95.41,98.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:101.53,104.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:107.43,110.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:124.49,125.14 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:128.2,129.47 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:137.2,138.16 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:144.2,145.29 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:150.2,151.42 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:168.2,168.15 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:174.2,174.12 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:125.14,127.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:129.47,132.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:138.16,141.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:145.29,147.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:151.42,152.15 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:155.3,157.40 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:152.15,153.9 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:157.40,161.4 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:161.9,166.4 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:168.15,171.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:171.8,173.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:178.66,180.31 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:180.31,182.17 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:186.3,186.49 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:182.17,184.12 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:186.49,187.80 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:187.80,189.5 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:190.9,192.4 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:197.83,199.31 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:199.31,204.49 5 0
+voltha-go-controller/internal/pkg/controller/audittables.go:204.49,205.81 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:205.81,207.5 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:208.9,210.4 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:218.68,219.14 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:223.2,224.47 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:232.2,233.16 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:238.2,249.31 5 0
+voltha-go-controller/internal/pkg/controller/audittables.go:253.2,255.40 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:279.2,281.15 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:290.2,290.12 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:219.14,221.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:224.47,227.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:233.16,236.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:249.31,251.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:255.40,256.15 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:260.3,261.42 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:256.15,257.9 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:261.42,266.74 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:269.4,271.82 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:266.74,268.5 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:272.9,277.4 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:281.15,287.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:287.8,289.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:295.87,301.47 6 0
+voltha-go-controller/internal/pkg/controller/audittables.go:305.2,305.31 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:301.47,304.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:305.31,308.26 3 0
+voltha-go-controller/internal/pkg/controller/audittables.go:314.3,315.74 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:318.3,318.114 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:308.26,309.75 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:309.75,311.13 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:315.74,317.4 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:323.102,327.47 3 0
+voltha-go-controller/internal/pkg/controller/audittables.go:333.2,333.29 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:327.47,330.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:333.29,334.61 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:339.3,362.80 17 0
+voltha-go-controller/internal/pkg/controller/audittables.go:365.3,365.108 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:334.61,336.12 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:362.80,364.4 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:373.81,377.14 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:381.2,382.47 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:390.2,391.16 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:396.2,398.32 3 0
+voltha-go-controller/internal/pkg/controller/audittables.go:401.2,406.15 3 0
+voltha-go-controller/internal/pkg/controller/audittables.go:422.2,422.24 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:377.14,379.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:382.47,385.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:391.16,394.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:398.32,400.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:406.15,417.3 4 0
+voltha-go-controller/internal/pkg/controller/audittables.go:417.8,419.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:426.78,427.14 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:431.2,434.44 4 0
+voltha-go-controller/internal/pkg/controller/audittables.go:445.2,445.13 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:427.14,429.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:434.44,439.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:439.8,444.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:448.75,454.43 3 0
+voltha-go-controller/internal/pkg/controller/audittables.go:463.2,466.46 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:454.43,455.47 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:455.47,456.59 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:456.59,459.5 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:466.46,468.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:472.69,474.2 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:477.73,479.2 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:482.91,486.47 3 0
+voltha-go-controller/internal/pkg/controller/audittables.go:490.2,490.34 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:486.47,489.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:490.34,493.87 3 0
+voltha-go-controller/internal/pkg/controller/audittables.go:493.87,495.4 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:500.82,504.47 3 0
+voltha-go-controller/internal/pkg/controller/audittables.go:510.2,510.35 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:504.47,507.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:510.35,519.87 7 0
+voltha-go-controller/internal/pkg/controller/audittables.go:523.3,525.87 3 0
+voltha-go-controller/internal/pkg/controller/audittables.go:519.87,521.4 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:525.87,527.4 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:531.48,532.14 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:536.2,537.47 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:541.2,542.16 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:552.2,553.35 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:557.2,558.59 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:577.2,577.56 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:582.2,582.48 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:593.2,593.14 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:597.2,599.12 3 0
+voltha-go-controller/internal/pkg/controller/audittables.go:532.14,534.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:537.47,540.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:542.16,544.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:553.35,555.3 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:558.59,561.42 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:574.3,574.111 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:561.42,562.194 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:568.4,568.28 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:562.194,567.5 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:569.9,573.4 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:577.56,580.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:582.48,583.22 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:587.3,587.15 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:590.3,590.32 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:583.22,585.12 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:587.15,588.9 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:593.14,596.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:603.96,606.42 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:621.2,621.34 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:626.2,626.30 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:606.42,611.54 3 0
+voltha-go-controller/internal/pkg/controller/audittables.go:614.3,614.54 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:617.3,617.103 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:611.54,613.4 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:614.54,616.4 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:621.34,624.3 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:626.30,627.26 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:627.26,629.4 1 0
+voltha-go-controller/internal/pkg/controller/audittables.go:634.80,636.25 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:636.25,639.54 2 0
+voltha-go-controller/internal/pkg/controller/audittables.go:639.54,641.4 1 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:38.103,46.2 7 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:49.43,51.2 1 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:54.44,56.2 1 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:59.48,61.2 1 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:64.37,65.2 0 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:68.76,72.69 3 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:92.2,92.47 1 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:72.69,77.62 5 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:89.3,90.13 2 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:77.62,79.52 2 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:79.52,81.5 1 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:82.9,82.72 1 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:82.72,83.58 1 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:83.58,85.5 1 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:86.9,86.72 1 0
+voltha-go-controller/internal/pkg/controller/changeevent.go:86.72,88.4 1 0
+voltha-go-controller/internal/pkg/controller/controllertasks.go:37.64,43.2 5 0
+voltha-go-controller/internal/pkg/controller/controllertasks.go:46.41,48.2 1 0
+voltha-go-controller/internal/pkg/controller/controllertasks.go:51.42,53.2 1 0
+voltha-go-controller/internal/pkg/controller/controllertasks.go:56.46,58.2 1 0
+voltha-go-controller/internal/pkg/controller/controllertasks.go:61.35,62.2 0 0
+voltha-go-controller/internal/pkg/controller/controllertasks.go:65.74,76.2 7 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:41.90,49.2 7 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:52.40,54.2 1 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:57.41,59.2 1 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:62.45,64.2 1 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:67.34,68.2 0 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:71.73,77.48 5 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:94.2,94.45 1 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:101.2,101.56 1 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:106.2,107.48 2 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:127.2,128.12 2 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:77.48,80.67 2 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:90.3,91.14 2 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:80.67,81.98 1 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:86.4,88.16 2 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:81.98,85.5 2 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:94.45,97.3 2 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:97.8,99.3 1 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:101.56,104.3 2 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:107.48,111.7 1 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:125.3,125.13 1 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:111.7,114.58 3 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:117.4,118.13 2 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:122.4,123.9 2 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:114.58,115.10 1 0
+voltha-go-controller/internal/pkg/controller/modgroup.go:118.13,120.13 2 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:37.115,46.2 8 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:49.40,51.2 1 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:54.41,56.2 1 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:59.45,61.2 1 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:64.34,65.2 0 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:68.73,90.39 3 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:104.2,104.39 1 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:108.2,109.16 2 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:114.2,114.48 1 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:129.2,130.12 2 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:90.39,92.61 2 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:96.3,96.89 1 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:92.61,95.4 1 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:97.8,98.43 1 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:98.43,101.4 1 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:104.39,107.3 2 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:109.16,112.3 2 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:114.48,115.79 1 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:126.3,126.13 1 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:115.79,117.4 1 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:117.9,119.64 2 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:123.4,123.90 1 0
+voltha-go-controller/internal/pkg/controller/modmeter.go:119.64,122.5 1 0
+voltha-go-controller/internal/pkg/of/flows.go:101.55,103.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:106.42,108.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:149.39,151.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:204.25,214.2 9 0
+voltha-go-controller/internal/pkg/of/flows.go:217.40,219.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:222.45,224.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:227.42,229.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:232.51,234.2 1 1
+voltha-go-controller/internal/pkg/of/flows.go:237.54,240.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:243.54,246.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:249.45,252.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:255.44,258.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:261.44,264.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:267.31,269.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:272.34,275.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:278.33,281.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:284.32,287.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:290.33,293.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:296.32,298.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:349.26,357.2 7 0
+voltha-go-controller/internal/pkg/of/flows.go:360.42,363.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:366.76,369.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:372.44,374.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:377.31,379.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:382.45,384.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:387.52,389.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:392.39,394.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:397.44,399.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:402.42,405.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:408.44,411.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:414.45,417.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:434.36,439.2 4 0
+voltha-go-controller/internal/pkg/of/flows.go:442.51,444.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:500.51,509.2 8 0
+voltha-go-controller/internal/pkg/of/flows.go:512.62,521.2 8 0
+voltha-go-controller/internal/pkg/of/flows.go:524.55,533.2 8 0
+voltha-go-controller/internal/pkg/of/flows.go:536.55,545.2 8 0
+voltha-go-controller/internal/pkg/of/flows.go:548.49,558.2 9 0
+voltha-go-controller/internal/pkg/of/flows.go:561.51,570.2 8 0
+voltha-go-controller/internal/pkg/of/flows.go:573.55,582.2 8 0
+voltha-go-controller/internal/pkg/of/flows.go:585.35,588.17 3 0
+voltha-go-controller/internal/pkg/of/flows.go:592.2,596.15 5 0
+voltha-go-controller/internal/pkg/of/flows.go:588.17,591.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:600.50,609.2 8 0
+voltha-go-controller/internal/pkg/of/flows.go:612.50,621.2 8 0
+voltha-go-controller/internal/pkg/of/flows.go:624.55,633.2 8 0
+voltha-go-controller/internal/pkg/of/flows.go:636.51,645.2 8 0
+voltha-go-controller/internal/pkg/of/flows.go:648.51,657.2 8 0
+voltha-go-controller/internal/pkg/of/flows.go:660.64,669.2 4 0
+voltha-go-controller/internal/pkg/of/flows.go:672.64,681.2 4 0
+voltha-go-controller/internal/pkg/of/flows.go:684.50,694.2 7 0
+voltha-go-controller/internal/pkg/of/flows.go:697.71,702.2 4 0
+voltha-go-controller/internal/pkg/of/flows.go:705.40,707.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:710.80,728.2 13 0
+voltha-go-controller/internal/pkg/of/flows.go:731.57,734.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:737.51,750.2 10 0
+voltha-go-controller/internal/pkg/of/flows.go:753.53,760.2 6 0
+voltha-go-controller/internal/pkg/of/flows.go:763.60,773.2 7 0
+voltha-go-controller/internal/pkg/of/flows.go:776.50,778.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:781.66,791.2 7 0
+voltha-go-controller/internal/pkg/of/flows.go:794.50,796.2 1 0
+voltha-go-controller/internal/pkg/of/flows.go:799.88,808.25 4 0
+voltha-go-controller/internal/pkg/of/flows.go:814.2,814.32 1 0
+voltha-go-controller/internal/pkg/of/flows.go:820.2,820.19 1 0
+voltha-go-controller/internal/pkg/of/flows.go:826.2,826.19 1 0
+voltha-go-controller/internal/pkg/of/flows.go:832.2,832.29 1 0
+voltha-go-controller/internal/pkg/of/flows.go:837.2,837.18 1 0
+voltha-go-controller/internal/pkg/of/flows.go:843.2,843.34 1 0
+voltha-go-controller/internal/pkg/of/flows.go:849.2,849.20 1 0
+voltha-go-controller/internal/pkg/of/flows.go:855.2,855.20 1 0
+voltha-go-controller/internal/pkg/of/flows.go:861.2,861.38 1 0
+voltha-go-controller/internal/pkg/of/flows.go:867.2,867.20 1 0
+voltha-go-controller/internal/pkg/of/flows.go:873.2,873.20 1 0
+voltha-go-controller/internal/pkg/of/flows.go:880.2,880.37 1 0
+voltha-go-controller/internal/pkg/of/flows.go:886.2,886.20 1 0
+voltha-go-controller/internal/pkg/of/flows.go:892.2,892.21 1 0
+voltha-go-controller/internal/pkg/of/flows.go:948.2,948.32 1 0
+voltha-go-controller/internal/pkg/of/flows.go:808.25,811.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:814.32,817.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:820.19,823.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:826.19,829.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:832.29,835.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:837.18,840.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:843.34,846.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:849.20,852.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:855.20,858.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:861.38,864.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:867.20,870.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:873.20,876.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:880.37,883.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:886.20,889.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:892.21,895.3 2 0
+voltha-go-controller/internal/pkg/of/flows.go:899.2,908.24 5 0
+voltha-go-controller/internal/pkg/of/flows.go:915.3,915.28 1 0
+voltha-go-controller/internal/pkg/of/flows.go:920.3,920.24 1 0
+voltha-go-controller/internal/pkg/of/flows.go:926.3,926.27 1 0
+voltha-go-controller/internal/pkg/of/flows.go:935.3,935.48 1 0
+voltha-go-controller/internal/pkg/of/flows.go:945.3,945.52 1 0
+voltha-go-controller/internal/pkg/of/flows.go:908.24,909.38 1 0
+voltha-go-controller/internal/pkg/of/flows.go:909.38,912.5 2 0
+voltha-go-controller/internal/pkg/of/flows.go:915.28,918.4 2 0
+voltha-go-controller/internal/pkg/of/flows.go:920.24,923.4 2 0
+voltha-go-controller/internal/pkg/of/flows.go:926.27,929.36 3 0
+voltha-go-controller/internal/pkg/of/flows.go:929.36,932.5 2 0
+voltha-go-controller/internal/pkg/of/flows.go:935.48,938.4 2 0
+voltha-go-controller/internal/pkg/of/flows.go:938.9,938.52 1 0
+voltha-go-controller/internal/pkg/of/flows.go:938.52,941.4 2 0
+voltha-go-controller/internal/pkg/of/flows.go:941.9,941.50 1 0
+voltha-go-controller/internal/pkg/of/flows.go:941.50,944.4 2 0
+voltha-go-controller/internal/pkg/of/flows.go:953.76,977.2 2 0
+voltha-go-controller/internal/pkg/of/flows.go:991.112,994.29 3 0
+voltha-go-controller/internal/pkg/of/flows.go:999.2,999.29 1 0
+voltha-go-controller/internal/pkg/of/flows.go:1006.2,1006.14 1 0
+voltha-go-controller/internal/pkg/of/flows.go:994.29,996.3 1 0
+voltha-go-controller/internal/pkg/of/flows.go:996.8,998.3 1 0
+voltha-go-controller/internal/pkg/of/flows.go:999.29,1005.3 5 0
+voltha-go-controller/internal/pkg/of/flows.go:1009.13,1013.16 3 1
+voltha-go-controller/internal/pkg/of/flows.go:1013.16,1014.13 1 0
+voltha-go-controller/internal/pkg/of/group.go:70.65,84.47 4 0
+voltha-go-controller/internal/pkg/of/group.go:109.2,109.32 1 0
+voltha-go-controller/internal/pkg/of/group.go:147.2,148.20 2 0
+voltha-go-controller/internal/pkg/of/group.go:84.47,107.3 4 0
+voltha-go-controller/internal/pkg/of/group.go:109.32,123.25 4 0
+voltha-go-controller/internal/pkg/of/group.go:144.3,144.78 1 0
+voltha-go-controller/internal/pkg/of/group.go:123.25,143.4 2 0
+voltha-go-controller/internal/pkg/of/meter.go:59.33,63.2 3 0
+voltha-go-controller/internal/pkg/of/meter.go:66.50,69.2 2 0
+voltha-go-controller/internal/pkg/of/meter.go:72.90,77.26 3 0
+voltha-go-controller/internal/pkg/of/meter.go:86.2,86.17 1 0
+voltha-go-controller/internal/pkg/of/meter.go:77.26,80.29 3 0
+voltha-go-controller/internal/pkg/of/meter.go:80.29,82.4 1 0
+voltha-go-controller/internal/pkg/of/meter.go:83.8,85.3 1 0
+voltha-go-controller/internal/pkg/of/meter.go:90.47,99.2 5 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:51.39,57.2 5 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:60.34,62.2 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:65.35,67.2 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:70.39,72.2 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:75.39,78.2 2 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:81.67,84.26 3 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:94.2,95.12 2 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:84.26,88.17 4 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:91.3,92.88 2 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:88.17,90.4 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:100.35,104.2 3 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:108.27,111.62 2 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:111.62,115.3 2 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:143.43,152.2 8 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:156.50,161.2 3 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:165.58,168.25 3 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:173.2,174.18 2 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:168.25,172.3 3 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:179.39,182.2 2 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:185.47,187.2 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:193.37,199.26 4 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:199.26,201.3 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:206.38,208.2 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:212.28,219.24 5 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:223.2,223.17 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:219.24,222.3 2 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:228.40,234.18 5 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:241.2,241.29 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:234.18,237.3 2 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:237.8,239.3 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:247.43,249.2 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:254.39,257.2 2 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:262.37,264.2 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:269.33,271.42 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:271.42,278.32 5 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:282.3,284.17 2 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:287.3,287.31 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:293.3,293.19 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:278.32,281.4 2 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:284.17,286.4 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:287.31,291.4 2 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:293.19,294.9 1 0
+voltha-go-controller/internal/pkg/tasks/tasks.go:300.13,304.16 3 1
+voltha-go-controller/internal/pkg/tasks/tasks.go:304.16,305.13 1 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:28.59,31.15 2 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:35.2,35.29 1 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:39.2,43.16 5 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:49.1,51.6 1 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:31.15,34.3 2 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:35.29,38.3 2 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:43.16,47.3 2 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:51.6,52.10 1 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:53.21,55.13 2 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:56.11,58.21 2 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:68.4,68.27 1 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:76.4,76.30 1 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:58.21,60.19 2 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:65.5,65.13 1 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:60.19,64.6 2 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:68.27,71.14 2 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:72.10,72.25 1 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:72.25,74.13 2 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:81.58,84.6 2 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:95.2,95.49 1 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:84.6,85.10 1 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:86.21,88.13 2 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:89.40,90.53 1 0
+voltha-go-controller/internal/pkg/vpagent/packetIn.go:90.53,92.5 1 0
+voltha-go-controller/internal/pkg/vpagent/packetOut.go:26.58,29.15 2 0
+voltha-go-controller/internal/pkg/vpagent/packetOut.go:33.2,33.29 1 0
+voltha-go-controller/internal/pkg/vpagent/packetOut.go:37.2,41.16 5 0
+voltha-go-controller/internal/pkg/vpagent/packetOut.go:45.1,46.6 1 0
+voltha-go-controller/internal/pkg/vpagent/packetOut.go:29.15,32.3 2 0
+voltha-go-controller/internal/pkg/vpagent/packetOut.go:33.29,36.3 2 0
+voltha-go-controller/internal/pkg/vpagent/packetOut.go:41.16,44.3 2 0
+voltha-go-controller/internal/pkg/vpagent/packetOut.go:46.6,47.10 1 0
+voltha-go-controller/internal/pkg/vpagent/packetOut.go:48.21,49.13 1 0
+voltha-go-controller/internal/pkg/vpagent/packetOut.go:50.46,52.54 2 0
+voltha-go-controller/internal/pkg/vpagent/packetOut.go:57.4,57.40 1 0
+voltha-go-controller/internal/pkg/vpagent/packetOut.go:52.54,55.14 2 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:30.64,32.36 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:37.2,41.6 3 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:50.2,50.13 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:32.36,34.3 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:41.6,42.10 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:43.21,45.14 2 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:46.17,47.30 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:53.61,55.29 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:60.2,61.16 2 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:68.2,71.41 4 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:78.2,78.33 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:84.2,85.34 2 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:96.2,96.34 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:55.29,59.3 3 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:61.16,66.3 3 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:71.41,74.37 3 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:74.37,76.4 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:78.33,80.36 2 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:80.36,82.4 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:85.34,89.51 3 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:89.51,91.4 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:91.9,93.4 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:96.34,101.3 4 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:104.78,112.24 8 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:118.2,119.16 2 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:132.2,133.12 2 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:112.24,117.3 4 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:119.16,131.3 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:137.79,141.16 3 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:141.16,143.3 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:146.65,147.44 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:150.2,150.12 1 0
+voltha-go-controller/internal/pkg/vpagent/refresh.go:147.44,149.3 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:38.13,42.16 3 1
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:42.16,43.13 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:83.52,101.40 2 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:109.2,109.35 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:117.2,117.15 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:120.2,121.18 2 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:101.40,107.3 2 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:109.35,115.3 2 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:117.15,119.3 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:125.28,127.2 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:130.66,132.2 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:135.46,142.14 3 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:146.2,163.6 5 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:142.14,144.3 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:163.6,164.10 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:165.21,167.25 2 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:170.4,170.22 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:173.4,173.10 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:174.30,175.17 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:167.25,169.5 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:170.22,172.5 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:176.23,187.15 6 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:193.33,197.35 2 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:206.36,207.17 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:210.5,211.35 2 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:217.5,217.36 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:227.23,228.45 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:229.12,231.33 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:187.15,188.71 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:188.71,190.7 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:197.35,204.6 6 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:207.17,209.6 1 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:211.35,216.6 4 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:217.36,219.16 2 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:219.16,221.72 2 0
+voltha-go-controller/internal/pkg/vpagent/volthaprotoagent.go:221.72,223.8 1 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:28.62,31.15 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:35.2,35.29 1 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:39.2,43.27 5 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:48.2,49.16 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:55.1,56.6 1 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:31.15,34.3 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:35.29,38.3 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:43.27,46.3 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:49.16,53.3 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:56.6,57.10 1 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:58.21,60.13 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:61.11,63.21 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:72.4,72.27 1 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:80.4,81.52 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:63.21,65.19 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:70.5,70.13 1 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:65.19,69.6 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:72.27,75.14 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:76.10,76.25 1 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:76.25,78.13 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:86.61,90.6 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:105.2,105.51 1 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:90.6,91.10 1 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:92.21,94.13 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:95.48,97.58 2 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:97.58,98.56 1 0
+voltha-go-controller/internal/pkg/vpagent/changeEvent.go:98.56,100.6 1 0
+voltha-go-controller/internal/pkg/vpagent/common.go:29.37,30.16 1 0
+voltha-go-controller/internal/pkg/vpagent/common.go:34.2,35.8 2 0
+voltha-go-controller/internal/pkg/vpagent/common.go:40.2,41.8 2 0
+voltha-go-controller/internal/pkg/vpagent/common.go:47.2,47.29 1 0
+voltha-go-controller/internal/pkg/vpagent/common.go:52.2,52.80 1 0
+voltha-go-controller/internal/pkg/vpagent/common.go:30.16,32.3 1 0
+voltha-go-controller/internal/pkg/vpagent/common.go:35.8,38.3 1 0
+voltha-go-controller/internal/pkg/vpagent/common.go:41.8,44.3 1 0
+voltha-go-controller/internal/pkg/vpagent/common.go:47.29,49.3 1 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:34.92,35.14 1 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:39.2,39.33 1 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:43.2,46.70 4 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:78.2,78.14 1 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:81.2,81.50 1 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:35.14,37.3 1 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:39.33,41.3 1 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:46.70,48.17 2 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:66.3,71.70 2 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:48.17,50.18 2 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:50.18,51.81 1 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:51.81,58.18 4 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:61.6,62.16 2 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:58.18,60.7 1 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:71.70,72.37 1 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:75.4,75.40 1 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:72.37,74.5 1 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:78.14,80.3 1 0
+voltha-go-controller/internal/pkg/vpagent/connection.go:85.47,89.2 2 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:72.13,76.16 3 1
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:76.16,77.13 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:86.79,88.18 2 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:89.13,90.51 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:91.15,92.51 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:93.10,94.74 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:99.109,102.46 2 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:108.2,109.55 2 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:114.2,118.26 2 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:102.46,105.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:109.55,113.3 3 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:121.73,124.34 2 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:132.2,132.48 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:124.34,127.17 3 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:130.3,130.9 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:127.17,129.4 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:132.48,158.56 21 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:176.3,176.21 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:185.3,186.25 2 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:190.3,209.35 5 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:212.3,212.39 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:215.3,215.55 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:228.3,228.74 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:231.3,231.72 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:158.56,161.4 2 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:161.9,162.42 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:162.42,165.5 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:165.10,166.41 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:170.5,170.105 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:166.41,168.6 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:170.105,172.6 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:176.21,178.4 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:186.25,188.4 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:209.35,211.4 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:212.39,214.4 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:215.55,217.50 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:217.50,219.5 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:219.10,219.66 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:219.66,221.5 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:221.10,223.5 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:224.9,224.64 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:224.64,226.4 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:228.74,230.4 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:231.72,233.4 1 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:238.109,248.46 6 1
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:254.2,255.55 2 1
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:261.2,261.44 1 1
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:274.2,275.53 2 1
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:248.46,251.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:255.55,259.3 3 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:261.44,269.58 7 0
+voltha-go-controller/voltha-go-controller/nbi/subscriber.go:269.58,271.4 1 0
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:59.76,61.18 2 1
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:62.12,63.44 1 0
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:64.13,65.44 1 1
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:66.15,67.44 1 0
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:68.10,69.74 1 0
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:74.99,79.46 4 1
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:85.2,86.55 2 1
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:91.2,104.79 4 0
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:79.46,82.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:86.55,90.3 3 1
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:108.99,113.9 4 1
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:118.2,130.16 3 0
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:136.2,138.16 3 0
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:113.9,117.3 3 1
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:130.16,134.3 3 0
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:138.16,141.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:145.99,150.46 4 1
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:155.2,156.55 2 1
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:161.2,164.75 3 1
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:169.2,169.79 1 0
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:150.46,153.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:156.55,160.3 3 0
+voltha-go-controller/voltha-go-controller/nbi/bwprofile.go:164.75,168.3 3 1
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:38.48,41.2 2 0
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:44.79,46.18 2 3
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:47.12,48.25 1 2
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:49.10,50.74 1 1
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:55.83,64.17 7 2
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:89.2,90.16 2 1
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:96.2,98.16 3 1
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:64.17,68.24 3 1
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:68.24,72.4 3 0
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:72.9,75.4 2 1
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:76.8,78.54 1 1
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:86.3,86.38 1 1
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:78.54,85.4 6 0
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:90.16,94.3 3 0
+voltha-go-controller/voltha-go-controller/nbi/device_info.go:98.16,101.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/flow_hash.go:35.77,37.18 2 0
+voltha-go-controller/voltha-go-controller/nbi/flow_hash.go:38.13,39.23 1 0
+voltha-go-controller/voltha-go-controller/nbi/flow_hash.go:40.10,41.74 1 0
+voltha-go-controller/voltha-go-controller/nbi/flow_hash.go:46.79,52.17 5 0
+voltha-go-controller/voltha-go-controller/nbi/flow_hash.go:61.2,61.93 1 0
+voltha-go-controller/voltha-go-controller/nbi/flow_hash.go:52.17,54.17 2 0
+voltha-go-controller/voltha-go-controller/nbi/flow_hash.go:58.3,58.44 1 0
+voltha-go-controller/voltha-go-controller/nbi/flow_hash.go:54.17,57.4 2 0
+voltha-go-controller/voltha-go-controller/nbi/get_device_id_list.go:31.81,33.18 2 2
+voltha-go-controller/voltha-go-controller/nbi/get_device_id_list.go:34.12,35.27 1 1
+voltha-go-controller/voltha-go-controller/nbi/get_device_id_list.go:36.10,37.74 1 1
+voltha-go-controller/voltha-go-controller/nbi/get_device_id_list.go:42.87,47.55 4 1
+voltha-go-controller/voltha-go-controller/nbi/get_device_id_list.go:53.2,56.16 3 1
+voltha-go-controller/voltha-go-controller/nbi/get_device_id_list.go:62.2,64.16 3 1
+voltha-go-controller/voltha-go-controller/nbi/get_device_id_list.go:47.55,52.3 4 0
+voltha-go-controller/voltha-go-controller/nbi/get_device_id_list.go:56.16,60.3 3 0
+voltha-go-controller/voltha-go-controller/nbi/get_device_id_list.go:64.16,67.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:56.79,58.18 2 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:59.13,60.51 1 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:61.15,62.51 1 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:63.10,64.74 1 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:69.108,72.46 2 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:78.2,79.55 2 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:84.2,86.35 2 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:72.46,75.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:79.55,83.3 3 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:90.109,91.2 0 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:93.103,96.103 2 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:101.2,109.56 6 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:96.103,100.3 3 0
+voltha-go-controller/voltha-go-controller/nbi/igmpproxy.go:109.56,113.3 3 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:55.13,59.16 3 1
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:59.16,60.13 1 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:65.88,67.18 2 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:68.13,69.34 1 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:70.10,71.74 1 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:76.108,79.46 2 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:85.2,86.55 2 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:91.2,95.73 2 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:110.2,110.64 1 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:114.2,114.30 1 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:119.2,119.30 1 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:79.46,82.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:86.55,90.3 3 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:95.73,108.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:110.64,112.3 1 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:114.30,117.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/netConfig.go:119.30,122.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/rest.go:67.18,103.2 34 0
+voltha-go-controller/voltha-go-controller/nbi/rest.go:105.13,109.16 3 1
+voltha-go-controller/voltha-go-controller/nbi/rest.go:109.16,110.13 1 0
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:33.77,35.18 2 1
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:36.12,37.23 1 1
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:38.10,39.74 1 0
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:44.79,52.17 6 1
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:75.2,76.16 2 0
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:82.2,84.16 3 0
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:52.17,56.24 3 1
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:56.24,59.4 2 0
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:59.9,62.4 2 1
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:63.8,65.58 1 0
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:72.3,72.42 1 0
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:65.58,71.4 5 0
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:76.16,80.3 3 0
+voltha-go-controller/voltha-go-controller/nbi/task_list.go:84.16,87.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:52.253,61.2 8 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:64.102,68.82 3 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:72.2,72.37 1 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:76.2,76.25 1 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:79.2,79.14 1 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:68.82,70.3 1 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:72.37,74.3 1 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:76.25,78.3 1 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:83.84,85.18 2 1
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:86.12,87.30 1 1
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:88.10,89.74 1 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:94.93,106.48 9 1
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:138.2,138.18 1 1
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:142.2,143.23 2 1
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:147.2,148.16 2 1
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:154.2,156.16 3 1
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:106.48,111.34 3 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:116.3,117.10 2 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:121.3,121.51 1 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:135.3,135.14 1 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:111.34,113.4 1 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:117.10,119.4 1 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:121.51,130.17 6 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:130.17,133.5 2 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:138.18,141.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:143.23,145.3 1 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:148.16,152.3 3 0
+voltha-go-controller/voltha-go-controller/nbi/dhcp_session.go:156.16,159.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:79.79,81.18 2 1
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:82.13,83.47 1 0
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:84.15,85.47 1 1
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:86.10,87.74 1 0
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:92.104,95.46 2 1
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:101.2,102.55 2 1
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:107.2,109.31 2 0
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:95.46,98.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:102.55,106.3 3 1
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:113.104,127.16 9 1
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:127.16,130.3 2 0
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:133.95,146.34 9 0
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:151.2,151.89 1 0
+voltha-go-controller/voltha-go-controller/nbi/mvlan.go:146.34,150.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:269.40,271.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:278.43,280.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:287.44,289.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:296.43,298.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:305.40,307.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:314.42,316.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:323.42,325.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:332.44,334.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:352.54,354.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:362.58,364.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:372.54,374.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:381.57,383.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:390.55,392.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:499.64,505.2 5 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:507.68,510.35 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:514.2,514.18 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:510.35,513.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:517.43,519.32 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:528.2,528.18 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:519.32,521.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:521.8,521.39 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:521.39,523.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:523.8,523.39 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:523.39,525.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:525.8,525.39 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:525.39,527.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:531.65,539.25 7 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:546.2,546.38 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:553.2,553.25 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:560.2,560.25 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:567.2,567.43 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:574.2,574.47 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:581.2,581.26 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:588.2,588.26 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:595.2,595.32 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:604.2,604.25 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:618.2,618.32 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:637.2,637.36 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:645.2,645.29 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:652.2,652.26 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:659.2,659.13 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:539.25,545.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:546.38,552.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:553.25,559.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:560.25,566.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:567.43,573.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:574.47,580.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:581.26,587.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:588.26,594.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:595.32,601.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:604.25,608.25 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:616.3,616.98 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:609.34,610.39 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:611.31,612.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:613.31,614.78 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:618.32,619.41 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:619.41,620.27 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:623.4,634.99 4 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:620.27,621.13 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:637.36,644.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:645.29,651.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:652.26,658.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:662.79,664.26 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:691.2,691.13 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:664.26,690.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:719.67,723.16 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:727.2,728.41 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:733.2,739.15 7 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:723.16,726.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:728.41,730.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:730.8,732.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:765.57,769.39 4 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:774.2,774.42 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:779.2,783.16 4 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:787.2,788.23 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:792.2,792.13 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:769.39,771.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:771.8,773.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:774.42,776.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:776.8,778.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:783.16,785.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:788.23,791.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:794.84,799.23 5 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:830.2,830.15 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:799.23,800.46 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:815.3,815.46 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:822.3,828.4 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:800.46,814.4 5 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:815.46,817.4 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:817.9,817.53 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:817.53,819.4 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:819.9,819.53 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:819.53,821.4 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:833.89,836.39 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:844.2,844.44 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:851.2,857.14 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:836.39,843.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:844.44,846.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:846.8,846.51 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:846.51,848.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:848.8,848.51 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/models.go:848.51,850.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:32.13,36.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:36.16,37.13 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:42.80,47.18 4 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:48.12,49.20 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:55.10,56.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:49.20,51.4 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:51.9,53.4 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:60.116,64.16 4 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:67.2,72.16 4 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:78.2,82.16 4 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:88.2,90.16 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:64.16,66.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:72.16,76.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:82.16,86.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:90.16,93.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:96.100,102.16 5 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:108.2,108.36 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:113.2,114.16 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:120.2,122.16 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:102.16,106.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:108.36,111.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:114.16,118.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/groups.go:122.16,125.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:31.13,35.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:35.16,36.13 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:41.80,47.18 6 2
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:48.12,49.54 1 2
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:54.10,55.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:49.54,51.4 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:51.9,53.4 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:59.113,62.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:68.2,69.16 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:75.2,77.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:62.16,66.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:69.16,73.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:77.16,80.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:83.144,86.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:92.2,93.16 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:99.2,101.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:86.16,90.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:93.16,97.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/maclearning_info.go:101.16,104.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/dhcprelayadapter.go:34.13,38.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/dhcprelayadapter.go:38.16,39.13 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/dhcprelayadapter.go:47.78,49.18 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/dhcprelayadapter.go:50.12,51.48 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/dhcprelayadapter.go:52.10,53.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/dhcprelayadapter.go:57.105,61.16 4 1
+voltha-go-controller/voltha-go-controller/onos_nbi/dhcprelayadapter.go:67.2,68.16 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/dhcprelayadapter.go:74.2,76.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/dhcprelayadapter.go:61.16,65.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/dhcprelayadapter.go:68.16,72.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/dhcprelayadapter.go:76.16,79.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:58.73,60.18 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:61.12,62.42 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:63.10,64.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:68.81,70.18 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:71.12,72.50 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:73.10,74.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:78.109,80.16 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:84.2,86.16 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:92.2,94.16 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:80.16,83.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:86.16,90.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:94.16,97.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:100.94,106.45 6 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:123.2,124.16 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:130.2,132.16 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:106.45,108.17 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:112.3,112.42 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:108.17,111.4 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:114.8,116.17 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:120.3,120.44 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:116.17,119.4 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:124.16,128.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:132.16,135.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:138.79,139.24 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:142.2,142.49 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:139.24,141.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/flowadapter.go:145.88,147.2 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:32.13,36.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:36.16,37.13 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:42.80,47.18 4 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:48.12,49.20 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:56.10,57.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:49.20,52.4 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:52.9,54.4 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:61.112,66.16 5 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:69.2,72.16 4 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:77.2,77.41 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:81.2,82.16 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:87.2,89.16 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:66.16,68.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:72.16,75.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:77.41,80.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:82.16,86.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:89.16,92.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:95.100,100.16 5 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:104.2,104.42 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:110.2,111.16 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:116.2,118.16 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:100.16,103.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:104.42,105.32 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:105.32,108.4 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:111.16,115.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/meters.go:118.16,121.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:71.77,73.18 2 2
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:74.13,75.49 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:76.15,77.51 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:78.12,79.58 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:80.10,81.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:85.89,87.18 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:88.13,89.61 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:90.15,91.63 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:92.10,93.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:97.105,104.46 5 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:110.2,110.42 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:104.46,108.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:110.42,113.17 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:118.3,119.20 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:124.3,125.25 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:130.3,130.99 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:113.17,117.4 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:119.20,123.4 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:125.25,129.4 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:130.99,133.4 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:137.107,144.46 5 1
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:150.2,150.42 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:144.46,148.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:150.42,153.17 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:158.3,159.20 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:164.3,165.25 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:170.3,170.101 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:153.17,157.4 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:159.20,163.4 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:165.25,169.4 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:170.101,173.4 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:177.117,187.19 9 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:196.2,196.19 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:205.2,205.19 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:215.2,215.21 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:187.19,189.17 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:194.3,194.26 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:189.17,193.4 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:196.19,198.17 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:203.3,203.26 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:198.17,202.4 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:205.19,207.17 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:212.3,212.27 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:207.17,211.4 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:215.21,216.118 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:216.118,219.4 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:223.119,233.19 9 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:242.2,242.19 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:251.2,251.19 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:261.2,261.21 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:233.19,235.17 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:240.3,240.26 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:235.17,239.4 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:242.19,244.17 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:249.3,249.26 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:244.17,248.4 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:251.19,253.17 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:258.3,258.27 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:253.17,257.4 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:261.21,262.120 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:262.120,265.4 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:269.114,276.16 7 1
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:279.2,282.16 4 1
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:288.2,290.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:276.16,278.3 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:282.16,286.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltapprestadapter.go:290.16,293.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltflowservice.go:33.83,35.18 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/oltflowservice.go:36.13,37.57 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltflowservice.go:38.12,39.53 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/oltflowservice.go:40.10,41.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltflowservice.go:45.119,48.46 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltflowservice.go:54.2,55.55 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltflowservice.go:60.2,60.55 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltflowservice.go:48.46,51.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltflowservice.go:55.55,59.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltflowservice.go:63.115,70.16 6 1
+voltha-go-controller/voltha-go-controller/onos_nbi/oltflowservice.go:75.2,77.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/oltflowservice.go:70.16,74.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/oltflowservice.go:77.16,80.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/portIgnored.go:29.13,33.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/portIgnored.go:33.16,34.13 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/portIgnored.go:38.93,40.18 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/portIgnored.go:41.12,43.54 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/portIgnored.go:45.10,46.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/portIgnored.go:50.113,52.16 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/portIgnored.go:58.2,59.16 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/portIgnored.go:65.2,67.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/portIgnored.go:52.16,56.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/portIgnored.go:59.16,63.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/portIgnored.go:67.16,70.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceconfig.go:41.81,43.18 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceconfig.go:44.13,45.49 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceconfig.go:46.12,47.51 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceconfig.go:48.10,49.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceconfig.go:53.109,57.46 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceconfig.go:62.2,63.55 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceconfig.go:68.2,68.52 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceconfig.go:57.46,60.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceconfig.go:63.55,67.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceconfig.go:71.111,79.16 8 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceconfig.go:85.2,87.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceconfig.go:79.16,83.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceconfig.go:87.16,90.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:37.75,39.18 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:40.12,41.25 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:42.10,43.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:48.79,53.53 4 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:59.2,62.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:68.2,70.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:53.53,58.3 4 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:62.16,66.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:70.16,73.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:77.79,79.18 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:80.12,81.23 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:82.10,83.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:88.91,90.18 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:91.12,92.32 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:93.10,94.74 1 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:99.90,107.51 6 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:113.2,113.23 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:122.2,123.16 2 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:129.2,131.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:107.51,112.3 4 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:113.23,116.24 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:116.24,120.4 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:123.16,127.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:131.16,134.3 2 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:138.81,143.51 4 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:150.2,150.53 1 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:155.2,158.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:164.2,166.16 3 1
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:143.51,148.3 4 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:150.53,154.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:158.16,162.3 3 0
+voltha-go-controller/voltha-go-controller/onos_nbi/deviceportadapter.go:166.16,169.3 2 0
diff --git a/tests/results/go-test-coverage.xml b/tests/results/go-test-coverage.xml
new file mode 100644
index 0000000..7da8f4c
--- /dev/null
+++ b/tests/results/go-test-coverage.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright 2022-present Open Networking Foundation
+ 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.
+ -->
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE coverage SYSTEM "http://cobertura.sourceforge.net/xml/coverage-04.dtd">
+<coverage line-rate="NaN" branch-rate="0" version="" timestamp="1686978186261" lines-covered="0" lines-valid="0" branches-covered="0" branches-valid="0" complexity="0">
+ <sources>
+ <source>/usr/local/go/src</source>
+ <source>/app/src</source>
+ </sources>
+ <packages></packages>
+</coverage>
diff --git a/tests/results/go-test-results.xml b/tests/results/go-test-results.xml
new file mode 100644
index 0000000..23fdefb
--- /dev/null
+++ b/tests/results/go-test-results.xml
@@ -0,0 +1,328 @@
+<!--
+ Copyright 2022-present Open Networking Foundation
+ 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.
+ -->
+
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuites>
+ <testsuite tests="232" failures="0" time="0.094" name="voltha-go-controller/internal/pkg/application">
+ <properties>
+ <property name="go.version" value="go1.16.3"></property>
+ <property name="coverage.statements.pct" value="17.3"></property>
+ </properties>
+ <testcase classname="application" name="TestVoltApplication_RestoreNbDeviceFromDb" time="0.010"></testcase>
+ <testcase classname="application" name="TestVoltApplication_RestoreNbDeviceFromDb/VoltApplication_RestoreNbDeviceFromDb" time="0.010"></testcase>
+ <testcase classname="application" name="TestVoltApplication_RestoreNbDeviceFromDb/VoltApplication_RestoreNbDeviceFromDb_invalid_Value_type" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_RestoreNbDeviceFromDb/VoltApplication_RestoreNbDeviceFromDb_unmarshal_error" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_UpdateDeviceConfig" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_UpdateDeviceConfig/SDX6320031" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_RestoreOltFlowService" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_RestoreOltFlowService/OltFlowService" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_UpdateOltFlowService" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_UpdateOltFlowService/OltFlowService" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_TriggerPendingVpvDeleteReq" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_TriggerPendingVpvDeleteReq/SDX6320031" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_TriggerPendingProfileDeleteReq" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_TriggerPendingProfileDeleteReq/SDX6320031" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_TriggerPendingServiceDeleteReq" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_TriggerPendingServiceDeleteReq/Positive_Case_TriggerPendingServiceDeleteReq" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_TriggerPendingVnetDeleteReq" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_TriggerPendingVnetDeleteReq/Negative_Case_TriggerPendingVnetDeleteReq" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_UpdateMacInPortMap" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_UpdateMacInPortMap/Positive_Case_UpdateMacInPortMap" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetMacInPortMap" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetMacInPortMap/Positive_Case_GetMacInPortMap" time="0.000"></testcase>
+ <testcase classname="application" name="Test_pushFlowFailureNotif" time="0.000"></testcase>
+ <testcase classname="application" name="Test_pushFlowFailureNotif/Positive_Case_pushFlowFailureNotif" time="0.000"></testcase>
+ <testcase classname="application" name="TestGetPonPortIDFromUNIPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestGetPonPortIDFromUNIPort/Positive_Case_pushFlowFailureNotif" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_ProcessFlowModResultIndication" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_ProcessFlowModResultIndication/Positive_Case_ProcessFlowModResultIndication" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_ProcessFlowModResultIndication/Negetive_Case_ProcessFlowModResultIndication" time="0.000"></testcase>
+ <testcase classname="application" name="Test_getPendingPoolKey" time="0.000"></testcase>
+ <testcase classname="application" name="Test_getPendingPoolKey/Positive_Case_getPendingPoolKey" time="0.000"></testcase>
+ <testcase classname="application" name="TestNewVoltPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestNewVoltPort/Positive_Case_TestNewVoltPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestNewVoltPort/Positive_Case2_TestNewVoltPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltPort_SetPortID" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltPort_SetPortID/Positive_Case_TestNewVoltPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestNewVoltDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestNewVoltDevice/Positive_Case_TestNewVoltDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetAssociatedVpvsForDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetAssociatedVpvsForDevice/Positive_Case_GetAssociatedVpvsForDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetAssociatedVpvsForDevice/Positive_Case2_GetAssociatedVpvsForDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetAssociatedVpvsForDevice/Negetive_Case2_GetAssociatedVpvsForDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_AssociateVpvsToDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_AssociateVpvsToDevice/Positive_Case_AssociateVpvsToDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_AssociateVpvsToDevice/Negetive_Case_AssociateVpvsToDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DisassociateVpvsFromDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DisassociateVpvsFromDevice/Positive_Case_DisassociateVpvsFromDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DisassociateVpvsFromDevice/Negetive_Case_DisassociateVpvsFromDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_GetPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_GetPort/Positive_Case_GetPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_GetPort/Negetive_Case_GetPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_GetPortNameFromPortID" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_GetPortNameFromPortID/Positive_Case_GetPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_DelPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_DelPort/Positive_Case_DelPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_DelPort/Negetive_Case_DelPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_pushFlowsForUnis" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_pushFlowsForUnis/Positive_Case_pushFlowsForUnis" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_pushFlowsForUnis/Negetive_Case_pushFlowsForUnis" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_pushFlowsForUnis/Negetive_Case1_pushFlowsForUnis" time="0.000"></testcase>
+ <testcase classname="application" name="TestNewNbDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestNewNbDevice/Positive_Case_pushFlowsForUnis" time="0.000"></testcase>
+ <testcase classname="application" name="TestNbDevice_WriteToDb" time="0.000"></testcase>
+ <testcase classname="application" name="TestNbDevice_WriteToDb/Positive_Case_pushFlowsForUnis" time="0.000"></testcase>
+ <testcase classname="application" name="TestNbDevice_AddPortToNbDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestNbDevice_AddPortToNbDevice/Positive_Case_AddPortToNbDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_AddDeviceConfig" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_AddDeviceConfig/Positive_Case_AddDeviceConfig" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetDeviceConfig" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetDeviceConfig/Positive_Case_GetDeviceConfig" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetDeviceConfig/Negetive_Case_GetDeviceConfig" time="0.000"></testcase>
+ <testcase classname="application" name="TestNbDevice_UpdatePortToNbDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestNbDevice_UpdatePortToNbDevice/Positive_Case_UpdatePortToNbDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestNbDevice_UpdatePortToNbDevice/Negetive_Case_UpdatePortToNbDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestNbDevice_DeletePortFromNbDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestNbDevice_DeletePortFromNbDevice/Positive_Case_DeletePortFromNbDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_RegisterFlowAddEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_RegisterFlowAddEvent/Positive_Case_RegisterFlowAddEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_RegisterFlowDelEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_RegisterFlowDelEvent/Positive_Case_RegisterFlowDelEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_UnRegisterFlowEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_UnRegisterFlowEvent/Positive_Case_RegisterFlowDelEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltDevice_UnRegisterFlowEvent/Negetive_Case_RegisterFlowDelEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_InitStaticConfig" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_InitStaticConfig/Positive_Case_InitStaticConfig" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_SetVendorID" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_SetVendorID/Positive_Case_SetVendorID" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetVendorID" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetVendorID/Positive_Case_GetVendorID" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_SetRebootFlag" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_SetRebootFlag/Positive_Case_SetRebootFlag" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetUpgradeFlag" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetUpgradeFlag/Positive_Case_GetUpgradeFlag" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_SetUpgradeFlag" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_SetUpgradeFlag/Positive_Case_GetUpgradeFlag" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_AddDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_AddDevice/Positive_Case_AddDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_AddDevice/Negetive_Case_AddDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DelDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DelDevice/Positive_Case_AddDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DelDevice/Delete_Case_AddDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_PortAddInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_PortAddInd/Positive_Case_PortAddInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_PortAddInd/Negetive_Case_PortAddInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_PortUpdateInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_PortUpdateInd/Positive_Case_PortUpdateInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_PortUpdateInd/Negetive_Case_PortUpdateInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_AddNbPonPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_AddNbPonPort/Positive_Case_AddNbPonPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_AddNbPonPort/Negetive_Case_AddNbPonPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_UpdateNbPonPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_UpdateNbPonPort/Positive_Case_UpdateNbPonPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_UpdateNbPonPort/Negetive_Case_Port_doesn't_exists" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_UpdateNbPonPort/Negetive_Case_Device-doesn't-exists" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeleteNbPonPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeleteNbPonPort/Positive_Case_DeleteNbPonPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeleteNbPonPort/Negetive_Case_DeleteNbPonPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeviceUpInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeviceUpInd/Positive_Case_DeviceUpInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeviceUpInd/Negetive_Case_DeviceUpInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeviceDownInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeviceDownInd/Positive_Case_DeviceDownInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeviceDownInd/Negetive_Case_DeviceDownInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeviceRebootInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeviceRebootInd/Positive_Case_DeviceRebootInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestExecuteFlowEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestExecuteFlowEvent/ExecuteFlowEvent_add" time="0.000"></testcase>
+ <testcase classname="application" name="TestExecuteFlowEvent/ExecuteFlowEvent_del" time="0.000"></testcase>
+ <testcase classname="application" name="TestInitEventFuncMapper" time="0.000"></testcase>
+ <testcase classname="application" name="TestInitEventFuncMapper/InitEventFuncMapper" time="0.000"></testcase>
+ <testcase classname="application" name="TestProcessUsIgmpFlowAddEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestProcessUsIgmpFlowAddEvent/ProcessUsIgmpFlowAddEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestProcessServiceFlowAddEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestProcessServiceFlowAddEvent/ProcessServiceFlowAddEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestProcessControlFlowAddEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestProcessControlFlowAddEvent/ProcessControlFlowAddEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestProcessServiceFlowDelEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestProcessServiceFlowDelEvent/ProcessServiceFlowDelEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestProcessControlFlowDelEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestProcessControlFlowDelEvent/ProcessControlFlowDelEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestProcessMcastFlowDelEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestProcessMcastFlowDelEvent/ProcessMcastFlowDelEvent" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_InitIgmpSrcMac" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_InitIgmpSrcMac/test" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_RestoreSvcsFromDb" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_RestoreSvcsFromDb/VoltApplication_RestoreSvcsFromDb" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_RestoreSvcsFromDb/invalid_value_type" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_RestoreSvcsFromDb/unmarshal_error" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_FlowRemoveFailure" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_FlowRemoveFailure/VoltService_FlowRemoveFailure" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_FlowRemoveFailure/cookie_not_found" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetServiceNameFromCookie" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetServiceNameFromCookie/VoltApplication_GetServiceNameFromCookie" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_SvcUpInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_SvcUpInd/VoltService_SvcUpInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_SvcDownInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_SvcDownInd/VoltService_SvcDownInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_AddService" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_AddService/VoltApplication_AddService" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DelService" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DelService/VoltApplication_DelService" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_FlowInstallSuccess" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_FlowInstallSuccess/VoltService_FlowInstallSuccess" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_AddMeterToDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_AddMeterToDevice/VoltService_AddMeterToDevice" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_AddMeterToDevice/GetDeviceFromPort_error" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_AddMeterToDevice/DeviceState_down" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_AddUsHsiaFlows" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_AddUsHsiaFlows/DeleteInProgress_true" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_AddUsHsiaFlows/GetDeviceFromPort_error" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_AddUsHsiaFlows/DeviceState_down" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_AddHsiaFlows" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_AddHsiaFlows/AddUsHsiaFlows_error" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_ForceWriteToDb" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_ForceWriteToDb/PutService_error" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_isDataRateAttrPresent" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_isDataRateAttrPresent/VoltService_isDataRateAttrPresent" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_GetServicePbit" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_GetServicePbit/VoltService_GetServicePbit" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_GetServicePbit/!IsPbitExist" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeactivateService" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeactivateService/VoltApplication_DeactivateService" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeactivateService/VoltPortVnet_nil" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeactivateService/sVlan_!=_of.VlanNone" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeactivateService/GetDeviceFromPort_error" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_ActivateService" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_ActivateService/VoltApplication_ActivateService" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_ActivateService/VoltPortVnet_nil" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_ActivateService/GetDeviceFromPort_error" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetProgrammedSubscribers" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetProgrammedSubscribers/VoltApplication_GetProgrammedSubscribers" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetProgrammedSubscribers/portNo_nil" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_GetProgrammedSubscribers/deviceID_nil" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_JSONMarshal" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_JSONMarshal/VoltService_JSONMarshal" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_triggerServiceInProgressInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_triggerServiceInProgressInd/VoltService_triggerServiceInProgressInd" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_TriggerAssociatedFlowDelete" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_TriggerAssociatedFlowDelete/VoltService_TriggerAssociatedFlowDelete" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltService_TriggerAssociatedFlowDelete/cookieList_nil" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/VoltApplication_DeepEqualServicecfg" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.Name_!=_evs.Name" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.UniVlan_!=_evs.UniVlan" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.CVlan_!=_evs.CVlan" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.SVlan_!=_evs.SVlan" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.SVlanTpid_!=_0" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.Pbits_!=_evs.Pbits" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.DsRemarkPbitsMap_!=_evs.DsRemarkPbitsMap" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.TechProfileID_!=_evs.TechProfileID" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.CircuitID_!=_evs.CircuitID" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.RemoteID_!=_evs.RemoteID" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.Port_!=_evs.Port" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.PonPort_!=_evs.PonPort" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/evs.MacLearning_==_MacLearningNone" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.IgmpEnabled_!=_evs.IgmpEnabled" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.McastService_!=_evs.McastService" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.ONTEtherTypeClassification_!=_evs.ONTEtherTypeClassification" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.UsMeterProfile_!=_evs.UsMeterProfile" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.DsMeterProfile_!=_evs.DsMeterProfile" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.AggDsMeterProfile_!=_evs.AggDsMeterProfile" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.VnetID_!=_evs.VnetID" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.MvlanProfileName_!=_evs.MvlanProfileName" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.RemoteIDType_!=_evs.RemoteIDType" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.SchedID_!=_evs.SchedID" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.AllowTransparent_!=_evs.AllowTransparent" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.EnableMulticastKPI_!=_evs.EnableMulticastKPI" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.DataRateAttr_!=_evs.DataRateAttr" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.MinDataRateUs_!=_evs.MinDataRateUs" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.MinDataRateDs_!=_evs.MinDataRateDs" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.MaxDataRateUs_!=_evs.MaxDataRateUs" time="0.000"></testcase>
+ <testcase classname="application" name="TestVoltApplication_DeepEqualServicecfg/nvs.MaxDataRateDs_!=_evs.MaxDataRateDs" time="0.000"></testcase>
+ </testsuite>
+ <testsuite tests="2" failures="0" time="0.065" name="voltha-go-controller/internal/pkg/controller">
+ <properties>
+ <property name="go.version" value="go1.16.3"></property>
+ <property name="coverage.statements.pct" value="0.5"></property>
+ </properties>
+ <testcase classname="controller" name="Test_isFlowOperSuccess" time="0.000"></testcase>
+ <testcase classname="controller" name="Test_isFlowOperSuccess/test" time="0.000"></testcase>
+ </testsuite>
+ <testsuite tests="2" failures="0" time="0.025" name="voltha-go-controller/internal/pkg/of">
+ <properties>
+ <property name="go.version" value="go1.16.3"></property>
+ <property name="coverage.statements.pct" value="1.1"></property>
+ </properties>
+ <testcase classname="of" name="TestMatch_SetTableMetadata" time="0.000"></testcase>
+ <testcase classname="of" name="TestMatch_SetTableMetadata/test" time="0.000"></testcase>
+ </testsuite>
+ <testsuite tests="22" failures="0" time="0.025" name="voltha-go-controller/voltha-go-controller/nbi">
+ <properties>
+ <property name="go.version" value="go1.16.3"></property>
+ <property name="coverage.statements.pct" value="29.7"></property>
+ </properties>
+ <testcase classname="nbi" name="TestProfileHandle_GetProfile" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestProfileHandle_GetProfile/GetProfile" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestProfileHandle_DelProfile" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestProfileHandle_DelProfile/DelProfile" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestProfileHandle_AddProfile" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestDeviceInfoHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestDeviceInfoHandle_ServeHTTP/DeviceInfoHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestGetDeviceInfoPositive" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestGetDeviceInfoUnsupportedReq" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestDHCPSessionInfoHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestDHCPSessionInfoHandle_ServeHTTP/DHCPSessionInfoHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestDeviceIDListHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestDeviceIDListHandle_ServeHTTP/DeviceIDListHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestDeviceIDListUnsupportedReq" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestMulticastHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestMulticastHandle_ServeHTTP/MulticastHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestMulticastHandle_AddMvlanInfo" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestMulticastHandle_AddMvlanInfo/AddMvlanInfo_unmarshal_error" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestSubscriberHandle_DelSubscriberInfo" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestSubscriberHandle_DelSubscriberInfo/SubscriberHandle_DelSubscriberInfo" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestTaskListHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="nbi" name="TestTaskListHandle_ServeHTTP/GetTaskList_invalid_input" time="0.000"></testcase>
+ </testsuite>
+ <testsuite tests="22" failures="0" time="0.022" name="voltha-go-controller/voltha-go-controller/onos_nbi">
+ <properties>
+ <property name="go.version" value="go1.16.3"></property>
+ <property name="coverage.statements.pct" value="22.7"></property>
+ </properties>
+ <testcase classname="onos_nbi" name="TestDeviceConfigHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestDeviceConfigHandle_ServeHTTP/DeviceConfigHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestDeviceHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestDeviceHandle_ServeHTTP/DeviceHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestDevicePortHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestDevicePortHandle_ServeHTTP/DevicePortHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestDevicePortHandle_ServeHTTPWithDeviceID" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestDevicePortHandle_ServeHTTPWithDeviceID/DevicePortHandle_ServeHTTPWithDeviceID" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestDhcpRelayHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestDhcpRelayHandle_ServeHTTP/DhcpRelayHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestMacLearnerHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestMacLearnerHandle_ServeHTTP/MacLearnerHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestMacLearnerHandle_GetAllMacLearnerInfo_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestMacLearnerHandle_GetAllMacLearnerInfo_ServeHTTP/MacLearnerHandle_GetAllMacLearnerInfo_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestServiceAdapter_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestServiceAdapter_ServeHTTP/ServiceAdapter_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestServiceAdapter_DeactivateService_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestServiceAdapter_DeactivateService_ServeHTTP/Invalid_port_number" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestOltFlowServiceHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestOltFlowServiceHandle_ServeHTTP/OltFlowServiceHandle_ServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestPortIgnoredHandle_PortsIgnoredServeHTTP" time="0.000"></testcase>
+ <testcase classname="onos_nbi" name="TestPortIgnoredHandle_PortsIgnoredServeHTTP/PortIgnoredHandle_PortsIgnoredServeHTTP" time="0.000"></testcase>
+ </testsuite>
+</testsuites>
diff --git a/vendor/github.com/davecgh/go-spew/LICENSE b/vendor/github.com/davecgh/go-spew/LICENSE
new file mode 100644
index 0000000..bc52e96
--- /dev/null
+++ b/vendor/github.com/davecgh/go-spew/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/davecgh/go-spew/spew/bypass.go
new file mode 100644
index 0000000..7929947
--- /dev/null
+++ b/vendor/github.com/davecgh/go-spew/spew/bypass.go
@@ -0,0 +1,145 @@
+// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// NOTE: Due to the following build constraints, this file will only be compiled
+// when the code is not running on Google App Engine, compiled by GopherJS, and
+// "-tags safe" is not added to the go build command line. The "disableunsafe"
+// tag is deprecated and thus should not be used.
+// Go versions prior to 1.4 are disabled because they use a different layout
+// for interfaces which make the implementation of unsafeReflectValue more complex.
+// +build !js,!appengine,!safe,!disableunsafe,go1.4
+
+package spew
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+const (
+ // UnsafeDisabled is a build-time constant which specifies whether or
+ // not access to the unsafe package is available.
+ UnsafeDisabled = false
+
+ // ptrSize is the size of a pointer on the current arch.
+ ptrSize = unsafe.Sizeof((*byte)(nil))
+)
+
+type flag uintptr
+
+var (
+ // flagRO indicates whether the value field of a reflect.Value
+ // is read-only.
+ flagRO flag
+
+ // flagAddr indicates whether the address of the reflect.Value's
+ // value may be taken.
+ flagAddr flag
+)
+
+// flagKindMask holds the bits that make up the kind
+// part of the flags field. In all the supported versions,
+// it is in the lower 5 bits.
+const flagKindMask = flag(0x1f)
+
+// Different versions of Go have used different
+// bit layouts for the flags type. This table
+// records the known combinations.
+var okFlags = []struct {
+ ro, addr flag
+}{{
+ // From Go 1.4 to 1.5
+ ro: 1 << 5,
+ addr: 1 << 7,
+}, {
+ // Up to Go tip.
+ ro: 1<<5 | 1<<6,
+ addr: 1 << 8,
+}}
+
+var flagValOffset = func() uintptr {
+ field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
+ if !ok {
+ panic("reflect.Value has no flag field")
+ }
+ return field.Offset
+}()
+
+// flagField returns a pointer to the flag field of a reflect.Value.
+func flagField(v *reflect.Value) *flag {
+ return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset))
+}
+
+// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
+// the typical safety restrictions preventing access to unaddressable and
+// unexported data. It works by digging the raw pointer to the underlying
+// value out of the protected value and generating a new unprotected (unsafe)
+// reflect.Value to it.
+//
+// This allows us to check for implementations of the Stringer and error
+// interfaces to be used for pretty printing ordinarily unaddressable and
+// inaccessible values such as unexported struct fields.
+func unsafeReflectValue(v reflect.Value) reflect.Value {
+ if !v.IsValid() || (v.CanInterface() && v.CanAddr()) {
+ return v
+ }
+ flagFieldPtr := flagField(&v)
+ *flagFieldPtr &^= flagRO
+ *flagFieldPtr |= flagAddr
+ return v
+}
+
+// Sanity checks against future reflect package changes
+// to the type or semantics of the Value.flag field.
+func init() {
+ field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
+ if !ok {
+ panic("reflect.Value has no flag field")
+ }
+ if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() {
+ panic("reflect.Value flag field has changed kind")
+ }
+ type t0 int
+ var t struct {
+ A t0
+ // t0 will have flagEmbedRO set.
+ t0
+ // a will have flagStickyRO set
+ a t0
+ }
+ vA := reflect.ValueOf(t).FieldByName("A")
+ va := reflect.ValueOf(t).FieldByName("a")
+ vt0 := reflect.ValueOf(t).FieldByName("t0")
+
+ // Infer flagRO from the difference between the flags
+ // for the (otherwise identical) fields in t.
+ flagPublic := *flagField(&vA)
+ flagWithRO := *flagField(&va) | *flagField(&vt0)
+ flagRO = flagPublic ^ flagWithRO
+
+ // Infer flagAddr from the difference between a value
+ // taken from a pointer and not.
+ vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A")
+ flagNoPtr := *flagField(&vA)
+ flagPtr := *flagField(&vPtrA)
+ flagAddr = flagNoPtr ^ flagPtr
+
+ // Check that the inferred flags tally with one of the known versions.
+ for _, f := range okFlags {
+ if flagRO == f.ro && flagAddr == f.addr {
+ return
+ }
+ }
+ panic("reflect.Value read-only flag has changed semantics")
+}
diff --git a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
new file mode 100644
index 0000000..205c28d
--- /dev/null
+++ b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
@@ -0,0 +1,38 @@
+// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// NOTE: Due to the following build constraints, this file will only be compiled
+// when the code is running on Google App Engine, compiled by GopherJS, or
+// "-tags safe" is added to the go build command line. The "disableunsafe"
+// tag is deprecated and thus should not be used.
+// +build js appengine safe disableunsafe !go1.4
+
+package spew
+
+import "reflect"
+
+const (
+ // UnsafeDisabled is a build-time constant which specifies whether or
+ // not access to the unsafe package is available.
+ UnsafeDisabled = true
+)
+
+// unsafeReflectValue typically converts the passed reflect.Value into a one
+// that bypasses the typical safety restrictions preventing access to
+// unaddressable and unexported data. However, doing this relies on access to
+// the unsafe package. This is a stub version which simply returns the passed
+// reflect.Value when the unsafe package is not available.
+func unsafeReflectValue(v reflect.Value) reflect.Value {
+ return v
+}
diff --git a/vendor/github.com/davecgh/go-spew/spew/common.go b/vendor/github.com/davecgh/go-spew/spew/common.go
new file mode 100644
index 0000000..1be8ce9
--- /dev/null
+++ b/vendor/github.com/davecgh/go-spew/spew/common.go
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "reflect"
+ "sort"
+ "strconv"
+)
+
+// Some constants in the form of bytes to avoid string overhead. This mirrors
+// the technique used in the fmt package.
+var (
+ panicBytes = []byte("(PANIC=")
+ plusBytes = []byte("+")
+ iBytes = []byte("i")
+ trueBytes = []byte("true")
+ falseBytes = []byte("false")
+ interfaceBytes = []byte("(interface {})")
+ commaNewlineBytes = []byte(",\n")
+ newlineBytes = []byte("\n")
+ openBraceBytes = []byte("{")
+ openBraceNewlineBytes = []byte("{\n")
+ closeBraceBytes = []byte("}")
+ asteriskBytes = []byte("*")
+ colonBytes = []byte(":")
+ colonSpaceBytes = []byte(": ")
+ openParenBytes = []byte("(")
+ closeParenBytes = []byte(")")
+ spaceBytes = []byte(" ")
+ pointerChainBytes = []byte("->")
+ nilAngleBytes = []byte("<nil>")
+ maxNewlineBytes = []byte("<max depth reached>\n")
+ maxShortBytes = []byte("<max>")
+ circularBytes = []byte("<already shown>")
+ circularShortBytes = []byte("<shown>")
+ invalidAngleBytes = []byte("<invalid>")
+ openBracketBytes = []byte("[")
+ closeBracketBytes = []byte("]")
+ percentBytes = []byte("%")
+ precisionBytes = []byte(".")
+ openAngleBytes = []byte("<")
+ closeAngleBytes = []byte(">")
+ openMapBytes = []byte("map[")
+ closeMapBytes = []byte("]")
+ lenEqualsBytes = []byte("len=")
+ capEqualsBytes = []byte("cap=")
+)
+
+// hexDigits is used to map a decimal value to a hex digit.
+var hexDigits = "0123456789abcdef"
+
+// catchPanic handles any panics that might occur during the handleMethods
+// calls.
+func catchPanic(w io.Writer, v reflect.Value) {
+ if err := recover(); err != nil {
+ w.Write(panicBytes)
+ fmt.Fprintf(w, "%v", err)
+ w.Write(closeParenBytes)
+ }
+}
+
+// handleMethods attempts to call the Error and String methods on the underlying
+// type the passed reflect.Value represents and outputes the result to Writer w.
+//
+// It handles panics in any called methods by catching and displaying the error
+// as the formatted value.
+func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
+ // We need an interface to check if the type implements the error or
+ // Stringer interface. However, the reflect package won't give us an
+ // interface on certain things like unexported struct fields in order
+ // to enforce visibility rules. We use unsafe, when it's available,
+ // to bypass these restrictions since this package does not mutate the
+ // values.
+ if !v.CanInterface() {
+ if UnsafeDisabled {
+ return false
+ }
+
+ v = unsafeReflectValue(v)
+ }
+
+ // Choose whether or not to do error and Stringer interface lookups against
+ // the base type or a pointer to the base type depending on settings.
+ // Technically calling one of these methods with a pointer receiver can
+ // mutate the value, however, types which choose to satisify an error or
+ // Stringer interface with a pointer receiver should not be mutating their
+ // state inside these interface methods.
+ if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
+ v = unsafeReflectValue(v)
+ }
+ if v.CanAddr() {
+ v = v.Addr()
+ }
+
+ // Is it an error or Stringer?
+ switch iface := v.Interface().(type) {
+ case error:
+ defer catchPanic(w, v)
+ if cs.ContinueOnMethod {
+ w.Write(openParenBytes)
+ w.Write([]byte(iface.Error()))
+ w.Write(closeParenBytes)
+ w.Write(spaceBytes)
+ return false
+ }
+
+ w.Write([]byte(iface.Error()))
+ return true
+
+ case fmt.Stringer:
+ defer catchPanic(w, v)
+ if cs.ContinueOnMethod {
+ w.Write(openParenBytes)
+ w.Write([]byte(iface.String()))
+ w.Write(closeParenBytes)
+ w.Write(spaceBytes)
+ return false
+ }
+ w.Write([]byte(iface.String()))
+ return true
+ }
+ return false
+}
+
+// printBool outputs a boolean value as true or false to Writer w.
+func printBool(w io.Writer, val bool) {
+ if val {
+ w.Write(trueBytes)
+ } else {
+ w.Write(falseBytes)
+ }
+}
+
+// printInt outputs a signed integer value to Writer w.
+func printInt(w io.Writer, val int64, base int) {
+ w.Write([]byte(strconv.FormatInt(val, base)))
+}
+
+// printUint outputs an unsigned integer value to Writer w.
+func printUint(w io.Writer, val uint64, base int) {
+ w.Write([]byte(strconv.FormatUint(val, base)))
+}
+
+// printFloat outputs a floating point value using the specified precision,
+// which is expected to be 32 or 64bit, to Writer w.
+func printFloat(w io.Writer, val float64, precision int) {
+ w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
+}
+
+// printComplex outputs a complex value using the specified float precision
+// for the real and imaginary parts to Writer w.
+func printComplex(w io.Writer, c complex128, floatPrecision int) {
+ r := real(c)
+ w.Write(openParenBytes)
+ w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
+ i := imag(c)
+ if i >= 0 {
+ w.Write(plusBytes)
+ }
+ w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
+ w.Write(iBytes)
+ w.Write(closeParenBytes)
+}
+
+// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
+// prefix to Writer w.
+func printHexPtr(w io.Writer, p uintptr) {
+ // Null pointer.
+ num := uint64(p)
+ if num == 0 {
+ w.Write(nilAngleBytes)
+ return
+ }
+
+ // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
+ buf := make([]byte, 18)
+
+ // It's simpler to construct the hex string right to left.
+ base := uint64(16)
+ i := len(buf) - 1
+ for num >= base {
+ buf[i] = hexDigits[num%base]
+ num /= base
+ i--
+ }
+ buf[i] = hexDigits[num]
+
+ // Add '0x' prefix.
+ i--
+ buf[i] = 'x'
+ i--
+ buf[i] = '0'
+
+ // Strip unused leading bytes.
+ buf = buf[i:]
+ w.Write(buf)
+}
+
+// valuesSorter implements sort.Interface to allow a slice of reflect.Value
+// elements to be sorted.
+type valuesSorter struct {
+ values []reflect.Value
+ strings []string // either nil or same len and values
+ cs *ConfigState
+}
+
+// newValuesSorter initializes a valuesSorter instance, which holds a set of
+// surrogate keys on which the data should be sorted. It uses flags in
+// ConfigState to decide if and how to populate those surrogate keys.
+func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
+ vs := &valuesSorter{values: values, cs: cs}
+ if canSortSimply(vs.values[0].Kind()) {
+ return vs
+ }
+ if !cs.DisableMethods {
+ vs.strings = make([]string, len(values))
+ for i := range vs.values {
+ b := bytes.Buffer{}
+ if !handleMethods(cs, &b, vs.values[i]) {
+ vs.strings = nil
+ break
+ }
+ vs.strings[i] = b.String()
+ }
+ }
+ if vs.strings == nil && cs.SpewKeys {
+ vs.strings = make([]string, len(values))
+ for i := range vs.values {
+ vs.strings[i] = Sprintf("%#v", vs.values[i].Interface())
+ }
+ }
+ return vs
+}
+
+// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
+// directly, or whether it should be considered for sorting by surrogate keys
+// (if the ConfigState allows it).
+func canSortSimply(kind reflect.Kind) bool {
+ // This switch parallels valueSortLess, except for the default case.
+ switch kind {
+ case reflect.Bool:
+ return true
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+ return true
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+ return true
+ case reflect.Float32, reflect.Float64:
+ return true
+ case reflect.String:
+ return true
+ case reflect.Uintptr:
+ return true
+ case reflect.Array:
+ return true
+ }
+ return false
+}
+
+// Len returns the number of values in the slice. It is part of the
+// sort.Interface implementation.
+func (s *valuesSorter) Len() int {
+ return len(s.values)
+}
+
+// Swap swaps the values at the passed indices. It is part of the
+// sort.Interface implementation.
+func (s *valuesSorter) Swap(i, j int) {
+ s.values[i], s.values[j] = s.values[j], s.values[i]
+ if s.strings != nil {
+ s.strings[i], s.strings[j] = s.strings[j], s.strings[i]
+ }
+}
+
+// valueSortLess returns whether the first value should sort before the second
+// value. It is used by valueSorter.Less as part of the sort.Interface
+// implementation.
+func valueSortLess(a, b reflect.Value) bool {
+ switch a.Kind() {
+ case reflect.Bool:
+ return !a.Bool() && b.Bool()
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+ return a.Int() < b.Int()
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+ return a.Uint() < b.Uint()
+ case reflect.Float32, reflect.Float64:
+ return a.Float() < b.Float()
+ case reflect.String:
+ return a.String() < b.String()
+ case reflect.Uintptr:
+ return a.Uint() < b.Uint()
+ case reflect.Array:
+ // Compare the contents of both arrays.
+ l := a.Len()
+ for i := 0; i < l; i++ {
+ av := a.Index(i)
+ bv := b.Index(i)
+ if av.Interface() == bv.Interface() {
+ continue
+ }
+ return valueSortLess(av, bv)
+ }
+ }
+ return a.String() < b.String()
+}
+
+// Less returns whether the value at index i should sort before the
+// value at index j. It is part of the sort.Interface implementation.
+func (s *valuesSorter) Less(i, j int) bool {
+ if s.strings == nil {
+ return valueSortLess(s.values[i], s.values[j])
+ }
+ return s.strings[i] < s.strings[j]
+}
+
+// sortValues is a sort function that handles both native types and any type that
+// can be converted to error or Stringer. Other inputs are sorted according to
+// their Value.String() value to ensure display stability.
+func sortValues(values []reflect.Value, cs *ConfigState) {
+ if len(values) == 0 {
+ return
+ }
+ sort.Sort(newValuesSorter(values, cs))
+}
diff --git a/vendor/github.com/davecgh/go-spew/spew/config.go b/vendor/github.com/davecgh/go-spew/spew/config.go
new file mode 100644
index 0000000..2e3d22f
--- /dev/null
+++ b/vendor/github.com/davecgh/go-spew/spew/config.go
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+)
+
+// ConfigState houses the configuration options used by spew to format and
+// display values. There is a global instance, Config, that is used to control
+// all top-level Formatter and Dump functionality. Each ConfigState instance
+// provides methods equivalent to the top-level functions.
+//
+// The zero value for ConfigState provides no indentation. You would typically
+// want to set it to a space or a tab.
+//
+// Alternatively, you can use NewDefaultConfig to get a ConfigState instance
+// with default settings. See the documentation of NewDefaultConfig for default
+// values.
+type ConfigState struct {
+ // Indent specifies the string to use for each indentation level. The
+ // global config instance that all top-level functions use set this to a
+ // single space by default. If you would like more indentation, you might
+ // set this to a tab with "\t" or perhaps two spaces with " ".
+ Indent string
+
+ // MaxDepth controls the maximum number of levels to descend into nested
+ // data structures. The default, 0, means there is no limit.
+ //
+ // NOTE: Circular data structures are properly detected, so it is not
+ // necessary to set this value unless you specifically want to limit deeply
+ // nested data structures.
+ MaxDepth int
+
+ // DisableMethods specifies whether or not error and Stringer interfaces are
+ // invoked for types that implement them.
+ DisableMethods bool
+
+ // DisablePointerMethods specifies whether or not to check for and invoke
+ // error and Stringer interfaces on types which only accept a pointer
+ // receiver when the current type is not a pointer.
+ //
+ // NOTE: This might be an unsafe action since calling one of these methods
+ // with a pointer receiver could technically mutate the value, however,
+ // in practice, types which choose to satisify an error or Stringer
+ // interface with a pointer receiver should not be mutating their state
+ // inside these interface methods. As a result, this option relies on
+ // access to the unsafe package, so it will not have any effect when
+ // running in environments without access to the unsafe package such as
+ // Google App Engine or with the "safe" build tag specified.
+ DisablePointerMethods bool
+
+ // DisablePointerAddresses specifies whether to disable the printing of
+ // pointer addresses. This is useful when diffing data structures in tests.
+ DisablePointerAddresses bool
+
+ // DisableCapacities specifies whether to disable the printing of capacities
+ // for arrays, slices, maps and channels. This is useful when diffing
+ // data structures in tests.
+ DisableCapacities bool
+
+ // ContinueOnMethod specifies whether or not recursion should continue once
+ // a custom error or Stringer interface is invoked. The default, false,
+ // means it will print the results of invoking the custom error or Stringer
+ // interface and return immediately instead of continuing to recurse into
+ // the internals of the data type.
+ //
+ // NOTE: This flag does not have any effect if method invocation is disabled
+ // via the DisableMethods or DisablePointerMethods options.
+ ContinueOnMethod bool
+
+ // SortKeys specifies map keys should be sorted before being printed. Use
+ // this to have a more deterministic, diffable output. Note that only
+ // native types (bool, int, uint, floats, uintptr and string) and types
+ // that support the error or Stringer interfaces (if methods are
+ // enabled) are supported, with other types sorted according to the
+ // reflect.Value.String() output which guarantees display stability.
+ SortKeys bool
+
+ // SpewKeys specifies that, as a last resort attempt, map keys should
+ // be spewed to strings and sorted by those strings. This is only
+ // considered if SortKeys is true.
+ SpewKeys bool
+}
+
+// Config is the active configuration of the top-level functions.
+// The configuration can be changed by modifying the contents of spew.Config.
+var Config = ConfigState{Indent: " "}
+
+// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the formatted string as a value that satisfies error. See NewFormatter
+// for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) {
+ return fmt.Errorf(format, c.convertArgs(a)...)
+}
+
+// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
+ return fmt.Fprint(w, c.convertArgs(a)...)
+}
+
+// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
+ return fmt.Fprintf(w, format, c.convertArgs(a)...)
+}
+
+// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
+// passed with a Formatter interface returned by c.NewFormatter. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
+ return fmt.Fprintln(w, c.convertArgs(a)...)
+}
+
+// Print is a wrapper for fmt.Print that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Print(c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Print(a ...interface{}) (n int, err error) {
+ return fmt.Print(c.convertArgs(a)...)
+}
+
+// Printf is a wrapper for fmt.Printf that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) {
+ return fmt.Printf(format, c.convertArgs(a)...)
+}
+
+// Println is a wrapper for fmt.Println that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Println(c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Println(a ...interface{}) (n int, err error) {
+ return fmt.Println(c.convertArgs(a)...)
+}
+
+// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the resulting string. See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Sprint(a ...interface{}) string {
+ return fmt.Sprint(c.convertArgs(a)...)
+}
+
+// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the resulting string. See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Sprintf(format string, a ...interface{}) string {
+ return fmt.Sprintf(format, c.convertArgs(a)...)
+}
+
+// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
+// were passed with a Formatter interface returned by c.NewFormatter. It
+// returns the resulting string. See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Sprintln(a ...interface{}) string {
+ return fmt.Sprintln(c.convertArgs(a)...)
+}
+
+/*
+NewFormatter returns a custom formatter that satisfies the fmt.Formatter
+interface. As a result, it integrates cleanly with standard fmt package
+printing functions. The formatter is useful for inline printing of smaller data
+types similar to the standard %v format specifier.
+
+The custom formatter only responds to the %v (most compact), %+v (adds pointer
+addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb
+combinations. Any other verbs such as %x and %q will be sent to the the
+standard fmt package for formatting. In addition, the custom formatter ignores
+the width and precision arguments (however they will still work on the format
+specifiers not handled by the custom formatter).
+
+Typically this function shouldn't be called directly. It is much easier to make
+use of the custom formatter by calling one of the convenience functions such as
+c.Printf, c.Println, or c.Printf.
+*/
+func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter {
+ return newFormatter(c, v)
+}
+
+// Fdump formats and displays the passed arguments to io.Writer w. It formats
+// exactly the same as Dump.
+func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) {
+ fdump(c, w, a...)
+}
+
+/*
+Dump displays the passed parameters to standard out with newlines, customizable
+indentation, and additional debug information such as complete types and all
+pointer addresses used to indirect to the final value. It provides the
+following features over the built-in printing facilities provided by the fmt
+package:
+
+ * Pointers are dereferenced and followed
+ * Circular data structures are detected and handled properly
+ * Custom Stringer/error interfaces are optionally invoked, including
+ on unexported types
+ * Custom types which only implement the Stringer/error interfaces via
+ a pointer receiver are optionally invoked when passing non-pointer
+ variables
+ * Byte arrays and slices are dumped like the hexdump -C command which
+ includes offsets, byte values in hex, and ASCII output
+
+The configuration options are controlled by modifying the public members
+of c. See ConfigState for options documentation.
+
+See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
+get the formatted result as a string.
+*/
+func (c *ConfigState) Dump(a ...interface{}) {
+ fdump(c, os.Stdout, a...)
+}
+
+// Sdump returns a string with the passed arguments formatted exactly the same
+// as Dump.
+func (c *ConfigState) Sdump(a ...interface{}) string {
+ var buf bytes.Buffer
+ fdump(c, &buf, a...)
+ return buf.String()
+}
+
+// convertArgs accepts a slice of arguments and returns a slice of the same
+// length with each argument converted to a spew Formatter interface using
+// the ConfigState associated with s.
+func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) {
+ formatters = make([]interface{}, len(args))
+ for index, arg := range args {
+ formatters[index] = newFormatter(c, arg)
+ }
+ return formatters
+}
+
+// NewDefaultConfig returns a ConfigState with the following default settings.
+//
+// Indent: " "
+// MaxDepth: 0
+// DisableMethods: false
+// DisablePointerMethods: false
+// ContinueOnMethod: false
+// SortKeys: false
+func NewDefaultConfig() *ConfigState {
+ return &ConfigState{Indent: " "}
+}
diff --git a/vendor/github.com/davecgh/go-spew/spew/doc.go b/vendor/github.com/davecgh/go-spew/spew/doc.go
new file mode 100644
index 0000000..aacaac6
--- /dev/null
+++ b/vendor/github.com/davecgh/go-spew/spew/doc.go
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+Package spew implements a deep pretty printer for Go data structures to aid in
+debugging.
+
+A quick overview of the additional features spew provides over the built-in
+printing facilities for Go data types are as follows:
+
+ * Pointers are dereferenced and followed
+ * Circular data structures are detected and handled properly
+ * Custom Stringer/error interfaces are optionally invoked, including
+ on unexported types
+ * Custom types which only implement the Stringer/error interfaces via
+ a pointer receiver are optionally invoked when passing non-pointer
+ variables
+ * Byte arrays and slices are dumped like the hexdump -C command which
+ includes offsets, byte values in hex, and ASCII output (only when using
+ Dump style)
+
+There are two different approaches spew allows for dumping Go data structures:
+
+ * Dump style which prints with newlines, customizable indentation,
+ and additional debug information such as types and all pointer addresses
+ used to indirect to the final value
+ * A custom Formatter interface that integrates cleanly with the standard fmt
+ package and replaces %v, %+v, %#v, and %#+v to provide inline printing
+ similar to the default %v while providing the additional functionality
+ outlined above and passing unsupported format verbs such as %x and %q
+ along to fmt
+
+Quick Start
+
+This section demonstrates how to quickly get started with spew. See the
+sections below for further details on formatting and configuration options.
+
+To dump a variable with full newlines, indentation, type, and pointer
+information use Dump, Fdump, or Sdump:
+ spew.Dump(myVar1, myVar2, ...)
+ spew.Fdump(someWriter, myVar1, myVar2, ...)
+ str := spew.Sdump(myVar1, myVar2, ...)
+
+Alternatively, if you would prefer to use format strings with a compacted inline
+printing style, use the convenience wrappers Printf, Fprintf, etc with
+%v (most compact), %+v (adds pointer addresses), %#v (adds types), or
+%#+v (adds types and pointer addresses):
+ spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+ spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+ spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+ spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+
+Configuration Options
+
+Configuration of spew is handled by fields in the ConfigState type. For
+convenience, all of the top-level functions use a global state available
+via the spew.Config global.
+
+It is also possible to create a ConfigState instance that provides methods
+equivalent to the top-level functions. This allows concurrent configuration
+options. See the ConfigState documentation for more details.
+
+The following configuration options are available:
+ * Indent
+ String to use for each indentation level for Dump functions.
+ It is a single space by default. A popular alternative is "\t".
+
+ * MaxDepth
+ Maximum number of levels to descend into nested data structures.
+ There is no limit by default.
+
+ * DisableMethods
+ Disables invocation of error and Stringer interface methods.
+ Method invocation is enabled by default.
+
+ * DisablePointerMethods
+ Disables invocation of error and Stringer interface methods on types
+ which only accept pointer receivers from non-pointer variables.
+ Pointer method invocation is enabled by default.
+
+ * DisablePointerAddresses
+ DisablePointerAddresses specifies whether to disable the printing of
+ pointer addresses. This is useful when diffing data structures in tests.
+
+ * DisableCapacities
+ DisableCapacities specifies whether to disable the printing of
+ capacities for arrays, slices, maps and channels. This is useful when
+ diffing data structures in tests.
+
+ * ContinueOnMethod
+ Enables recursion into types after invoking error and Stringer interface
+ methods. Recursion after method invocation is disabled by default.
+
+ * SortKeys
+ Specifies map keys should be sorted before being printed. Use
+ this to have a more deterministic, diffable output. Note that
+ only native types (bool, int, uint, floats, uintptr and string)
+ and types which implement error or Stringer interfaces are
+ supported with other types sorted according to the
+ reflect.Value.String() output which guarantees display
+ stability. Natural map order is used by default.
+
+ * SpewKeys
+ Specifies that, as a last resort attempt, map keys should be
+ spewed to strings and sorted by those strings. This is only
+ considered if SortKeys is true.
+
+Dump Usage
+
+Simply call spew.Dump with a list of variables you want to dump:
+
+ spew.Dump(myVar1, myVar2, ...)
+
+You may also call spew.Fdump if you would prefer to output to an arbitrary
+io.Writer. For example, to dump to standard error:
+
+ spew.Fdump(os.Stderr, myVar1, myVar2, ...)
+
+A third option is to call spew.Sdump to get the formatted output as a string:
+
+ str := spew.Sdump(myVar1, myVar2, ...)
+
+Sample Dump Output
+
+See the Dump example for details on the setup of the types and variables being
+shown here.
+
+ (main.Foo) {
+ unexportedField: (*main.Bar)(0xf84002e210)({
+ flag: (main.Flag) flagTwo,
+ data: (uintptr) <nil>
+ }),
+ ExportedField: (map[interface {}]interface {}) (len=1) {
+ (string) (len=3) "one": (bool) true
+ }
+ }
+
+Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C
+command as shown.
+ ([]uint8) (len=32 cap=32) {
+ 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
+ 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
+ 00000020 31 32 |12|
+ }
+
+Custom Formatter
+
+Spew provides a custom formatter that implements the fmt.Formatter interface
+so that it integrates cleanly with standard fmt package printing functions. The
+formatter is useful for inline printing of smaller data types similar to the
+standard %v format specifier.
+
+The custom formatter only responds to the %v (most compact), %+v (adds pointer
+addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
+combinations. Any other verbs such as %x and %q will be sent to the the
+standard fmt package for formatting. In addition, the custom formatter ignores
+the width and precision arguments (however they will still work on the format
+specifiers not handled by the custom formatter).
+
+Custom Formatter Usage
+
+The simplest way to make use of the spew custom formatter is to call one of the
+convenience functions such as spew.Printf, spew.Println, or spew.Printf. The
+functions have syntax you are most likely already familiar with:
+
+ spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+ spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+ spew.Println(myVar, myVar2)
+ spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+ spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+
+See the Index for the full list convenience functions.
+
+Sample Formatter Output
+
+Double pointer to a uint8:
+ %v: <**>5
+ %+v: <**>(0xf8400420d0->0xf8400420c8)5
+ %#v: (**uint8)5
+ %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
+
+Pointer to circular struct with a uint8 field and a pointer to itself:
+ %v: <*>{1 <*><shown>}
+ %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
+ %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
+ %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}
+
+See the Printf example for details on the setup of variables being shown
+here.
+
+Errors
+
+Since it is possible for custom Stringer/error interfaces to panic, spew
+detects them and handles them internally by printing the panic information
+inline with the output. Since spew is intended to provide deep pretty printing
+capabilities on structures, it intentionally does not return any errors.
+*/
+package spew
diff --git a/vendor/github.com/davecgh/go-spew/spew/dump.go b/vendor/github.com/davecgh/go-spew/spew/dump.go
new file mode 100644
index 0000000..f78d89f
--- /dev/null
+++ b/vendor/github.com/davecgh/go-spew/spew/dump.go
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+ "bytes"
+ "encoding/hex"
+ "fmt"
+ "io"
+ "os"
+ "reflect"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var (
+ // uint8Type is a reflect.Type representing a uint8. It is used to
+ // convert cgo types to uint8 slices for hexdumping.
+ uint8Type = reflect.TypeOf(uint8(0))
+
+ // cCharRE is a regular expression that matches a cgo char.
+ // It is used to detect character arrays to hexdump them.
+ cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`)
+
+ // cUnsignedCharRE is a regular expression that matches a cgo unsigned
+ // char. It is used to detect unsigned character arrays to hexdump
+ // them.
+ cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`)
+
+ // cUint8tCharRE is a regular expression that matches a cgo uint8_t.
+ // It is used to detect uint8_t arrays to hexdump them.
+ cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`)
+)
+
+// dumpState contains information about the state of a dump operation.
+type dumpState struct {
+ w io.Writer
+ depth int
+ pointers map[uintptr]int
+ ignoreNextType bool
+ ignoreNextIndent bool
+ cs *ConfigState
+}
+
+// indent performs indentation according to the depth level and cs.Indent
+// option.
+func (d *dumpState) indent() {
+ if d.ignoreNextIndent {
+ d.ignoreNextIndent = false
+ return
+ }
+ d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth))
+}
+
+// unpackValue returns values inside of non-nil interfaces when possible.
+// This is useful for data types like structs, arrays, slices, and maps which
+// can contain varying types packed inside an interface.
+func (d *dumpState) unpackValue(v reflect.Value) reflect.Value {
+ if v.Kind() == reflect.Interface && !v.IsNil() {
+ v = v.Elem()
+ }
+ return v
+}
+
+// dumpPtr handles formatting of pointers by indirecting them as necessary.
+func (d *dumpState) dumpPtr(v reflect.Value) {
+ // Remove pointers at or below the current depth from map used to detect
+ // circular refs.
+ for k, depth := range d.pointers {
+ if depth >= d.depth {
+ delete(d.pointers, k)
+ }
+ }
+
+ // Keep list of all dereferenced pointers to show later.
+ pointerChain := make([]uintptr, 0)
+
+ // Figure out how many levels of indirection there are by dereferencing
+ // pointers and unpacking interfaces down the chain while detecting circular
+ // references.
+ nilFound := false
+ cycleFound := false
+ indirects := 0
+ ve := v
+ for ve.Kind() == reflect.Ptr {
+ if ve.IsNil() {
+ nilFound = true
+ break
+ }
+ indirects++
+ addr := ve.Pointer()
+ pointerChain = append(pointerChain, addr)
+ if pd, ok := d.pointers[addr]; ok && pd < d.depth {
+ cycleFound = true
+ indirects--
+ break
+ }
+ d.pointers[addr] = d.depth
+
+ ve = ve.Elem()
+ if ve.Kind() == reflect.Interface {
+ if ve.IsNil() {
+ nilFound = true
+ break
+ }
+ ve = ve.Elem()
+ }
+ }
+
+ // Display type information.
+ d.w.Write(openParenBytes)
+ d.w.Write(bytes.Repeat(asteriskBytes, indirects))
+ d.w.Write([]byte(ve.Type().String()))
+ d.w.Write(closeParenBytes)
+
+ // Display pointer information.
+ if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 {
+ d.w.Write(openParenBytes)
+ for i, addr := range pointerChain {
+ if i > 0 {
+ d.w.Write(pointerChainBytes)
+ }
+ printHexPtr(d.w, addr)
+ }
+ d.w.Write(closeParenBytes)
+ }
+
+ // Display dereferenced value.
+ d.w.Write(openParenBytes)
+ switch {
+ case nilFound:
+ d.w.Write(nilAngleBytes)
+
+ case cycleFound:
+ d.w.Write(circularBytes)
+
+ default:
+ d.ignoreNextType = true
+ d.dump(ve)
+ }
+ d.w.Write(closeParenBytes)
+}
+
+// dumpSlice handles formatting of arrays and slices. Byte (uint8 under
+// reflection) arrays and slices are dumped in hexdump -C fashion.
+func (d *dumpState) dumpSlice(v reflect.Value) {
+ // Determine whether this type should be hex dumped or not. Also,
+ // for types which should be hexdumped, try to use the underlying data
+ // first, then fall back to trying to convert them to a uint8 slice.
+ var buf []uint8
+ doConvert := false
+ doHexDump := false
+ numEntries := v.Len()
+ if numEntries > 0 {
+ vt := v.Index(0).Type()
+ vts := vt.String()
+ switch {
+ // C types that need to be converted.
+ case cCharRE.MatchString(vts):
+ fallthrough
+ case cUnsignedCharRE.MatchString(vts):
+ fallthrough
+ case cUint8tCharRE.MatchString(vts):
+ doConvert = true
+
+ // Try to use existing uint8 slices and fall back to converting
+ // and copying if that fails.
+ case vt.Kind() == reflect.Uint8:
+ // We need an addressable interface to convert the type
+ // to a byte slice. However, the reflect package won't
+ // give us an interface on certain things like
+ // unexported struct fields in order to enforce
+ // visibility rules. We use unsafe, when available, to
+ // bypass these restrictions since this package does not
+ // mutate the values.
+ vs := v
+ if !vs.CanInterface() || !vs.CanAddr() {
+ vs = unsafeReflectValue(vs)
+ }
+ if !UnsafeDisabled {
+ vs = vs.Slice(0, numEntries)
+
+ // Use the existing uint8 slice if it can be
+ // type asserted.
+ iface := vs.Interface()
+ if slice, ok := iface.([]uint8); ok {
+ buf = slice
+ doHexDump = true
+ break
+ }
+ }
+
+ // The underlying data needs to be converted if it can't
+ // be type asserted to a uint8 slice.
+ doConvert = true
+ }
+
+ // Copy and convert the underlying type if needed.
+ if doConvert && vt.ConvertibleTo(uint8Type) {
+ // Convert and copy each element into a uint8 byte
+ // slice.
+ buf = make([]uint8, numEntries)
+ for i := 0; i < numEntries; i++ {
+ vv := v.Index(i)
+ buf[i] = uint8(vv.Convert(uint8Type).Uint())
+ }
+ doHexDump = true
+ }
+ }
+
+ // Hexdump the entire slice as needed.
+ if doHexDump {
+ indent := strings.Repeat(d.cs.Indent, d.depth)
+ str := indent + hex.Dump(buf)
+ str = strings.Replace(str, "\n", "\n"+indent, -1)
+ str = strings.TrimRight(str, d.cs.Indent)
+ d.w.Write([]byte(str))
+ return
+ }
+
+ // Recursively call dump for each item.
+ for i := 0; i < numEntries; i++ {
+ d.dump(d.unpackValue(v.Index(i)))
+ if i < (numEntries - 1) {
+ d.w.Write(commaNewlineBytes)
+ } else {
+ d.w.Write(newlineBytes)
+ }
+ }
+}
+
+// dump is the main workhorse for dumping a value. It uses the passed reflect
+// value to figure out what kind of object we are dealing with and formats it
+// appropriately. It is a recursive function, however circular data structures
+// are detected and handled properly.
+func (d *dumpState) dump(v reflect.Value) {
+ // Handle invalid reflect values immediately.
+ kind := v.Kind()
+ if kind == reflect.Invalid {
+ d.w.Write(invalidAngleBytes)
+ return
+ }
+
+ // Handle pointers specially.
+ if kind == reflect.Ptr {
+ d.indent()
+ d.dumpPtr(v)
+ return
+ }
+
+ // Print type information unless already handled elsewhere.
+ if !d.ignoreNextType {
+ d.indent()
+ d.w.Write(openParenBytes)
+ d.w.Write([]byte(v.Type().String()))
+ d.w.Write(closeParenBytes)
+ d.w.Write(spaceBytes)
+ }
+ d.ignoreNextType = false
+
+ // Display length and capacity if the built-in len and cap functions
+ // work with the value's kind and the len/cap itself is non-zero.
+ valueLen, valueCap := 0, 0
+ switch v.Kind() {
+ case reflect.Array, reflect.Slice, reflect.Chan:
+ valueLen, valueCap = v.Len(), v.Cap()
+ case reflect.Map, reflect.String:
+ valueLen = v.Len()
+ }
+ if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 {
+ d.w.Write(openParenBytes)
+ if valueLen != 0 {
+ d.w.Write(lenEqualsBytes)
+ printInt(d.w, int64(valueLen), 10)
+ }
+ if !d.cs.DisableCapacities && valueCap != 0 {
+ if valueLen != 0 {
+ d.w.Write(spaceBytes)
+ }
+ d.w.Write(capEqualsBytes)
+ printInt(d.w, int64(valueCap), 10)
+ }
+ d.w.Write(closeParenBytes)
+ d.w.Write(spaceBytes)
+ }
+
+ // Call Stringer/error interfaces if they exist and the handle methods flag
+ // is enabled
+ if !d.cs.DisableMethods {
+ if (kind != reflect.Invalid) && (kind != reflect.Interface) {
+ if handled := handleMethods(d.cs, d.w, v); handled {
+ return
+ }
+ }
+ }
+
+ switch kind {
+ case reflect.Invalid:
+ // Do nothing. We should never get here since invalid has already
+ // been handled above.
+
+ case reflect.Bool:
+ printBool(d.w, v.Bool())
+
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+ printInt(d.w, v.Int(), 10)
+
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+ printUint(d.w, v.Uint(), 10)
+
+ case reflect.Float32:
+ printFloat(d.w, v.Float(), 32)
+
+ case reflect.Float64:
+ printFloat(d.w, v.Float(), 64)
+
+ case reflect.Complex64:
+ printComplex(d.w, v.Complex(), 32)
+
+ case reflect.Complex128:
+ printComplex(d.w, v.Complex(), 64)
+
+ case reflect.Slice:
+ if v.IsNil() {
+ d.w.Write(nilAngleBytes)
+ break
+ }
+ fallthrough
+
+ case reflect.Array:
+ d.w.Write(openBraceNewlineBytes)
+ d.depth++
+ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
+ d.indent()
+ d.w.Write(maxNewlineBytes)
+ } else {
+ d.dumpSlice(v)
+ }
+ d.depth--
+ d.indent()
+ d.w.Write(closeBraceBytes)
+
+ case reflect.String:
+ d.w.Write([]byte(strconv.Quote(v.String())))
+
+ case reflect.Interface:
+ // The only time we should get here is for nil interfaces due to
+ // unpackValue calls.
+ if v.IsNil() {
+ d.w.Write(nilAngleBytes)
+ }
+
+ case reflect.Ptr:
+ // Do nothing. We should never get here since pointers have already
+ // been handled above.
+
+ case reflect.Map:
+ // nil maps should be indicated as different than empty maps
+ if v.IsNil() {
+ d.w.Write(nilAngleBytes)
+ break
+ }
+
+ d.w.Write(openBraceNewlineBytes)
+ d.depth++
+ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
+ d.indent()
+ d.w.Write(maxNewlineBytes)
+ } else {
+ numEntries := v.Len()
+ keys := v.MapKeys()
+ if d.cs.SortKeys {
+ sortValues(keys, d.cs)
+ }
+ for i, key := range keys {
+ d.dump(d.unpackValue(key))
+ d.w.Write(colonSpaceBytes)
+ d.ignoreNextIndent = true
+ d.dump(d.unpackValue(v.MapIndex(key)))
+ if i < (numEntries - 1) {
+ d.w.Write(commaNewlineBytes)
+ } else {
+ d.w.Write(newlineBytes)
+ }
+ }
+ }
+ d.depth--
+ d.indent()
+ d.w.Write(closeBraceBytes)
+
+ case reflect.Struct:
+ d.w.Write(openBraceNewlineBytes)
+ d.depth++
+ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
+ d.indent()
+ d.w.Write(maxNewlineBytes)
+ } else {
+ vt := v.Type()
+ numFields := v.NumField()
+ for i := 0; i < numFields; i++ {
+ d.indent()
+ vtf := vt.Field(i)
+ d.w.Write([]byte(vtf.Name))
+ d.w.Write(colonSpaceBytes)
+ d.ignoreNextIndent = true
+ d.dump(d.unpackValue(v.Field(i)))
+ if i < (numFields - 1) {
+ d.w.Write(commaNewlineBytes)
+ } else {
+ d.w.Write(newlineBytes)
+ }
+ }
+ }
+ d.depth--
+ d.indent()
+ d.w.Write(closeBraceBytes)
+
+ case reflect.Uintptr:
+ printHexPtr(d.w, uintptr(v.Uint()))
+
+ case reflect.UnsafePointer, reflect.Chan, reflect.Func:
+ printHexPtr(d.w, v.Pointer())
+
+ // There were not any other types at the time this code was written, but
+ // fall back to letting the default fmt package handle it in case any new
+ // types are added.
+ default:
+ if v.CanInterface() {
+ fmt.Fprintf(d.w, "%v", v.Interface())
+ } else {
+ fmt.Fprintf(d.w, "%v", v.String())
+ }
+ }
+}
+
+// fdump is a helper function to consolidate the logic from the various public
+// methods which take varying writers and config states.
+func fdump(cs *ConfigState, w io.Writer, a ...interface{}) {
+ for _, arg := range a {
+ if arg == nil {
+ w.Write(interfaceBytes)
+ w.Write(spaceBytes)
+ w.Write(nilAngleBytes)
+ w.Write(newlineBytes)
+ continue
+ }
+
+ d := dumpState{w: w, cs: cs}
+ d.pointers = make(map[uintptr]int)
+ d.dump(reflect.ValueOf(arg))
+ d.w.Write(newlineBytes)
+ }
+}
+
+// Fdump formats and displays the passed arguments to io.Writer w. It formats
+// exactly the same as Dump.
+func Fdump(w io.Writer, a ...interface{}) {
+ fdump(&Config, w, a...)
+}
+
+// Sdump returns a string with the passed arguments formatted exactly the same
+// as Dump.
+func Sdump(a ...interface{}) string {
+ var buf bytes.Buffer
+ fdump(&Config, &buf, a...)
+ return buf.String()
+}
+
+/*
+Dump displays the passed parameters to standard out with newlines, customizable
+indentation, and additional debug information such as complete types and all
+pointer addresses used to indirect to the final value. It provides the
+following features over the built-in printing facilities provided by the fmt
+package:
+
+ * Pointers are dereferenced and followed
+ * Circular data structures are detected and handled properly
+ * Custom Stringer/error interfaces are optionally invoked, including
+ on unexported types
+ * Custom types which only implement the Stringer/error interfaces via
+ a pointer receiver are optionally invoked when passing non-pointer
+ variables
+ * Byte arrays and slices are dumped like the hexdump -C command which
+ includes offsets, byte values in hex, and ASCII output
+
+The configuration options are controlled by an exported package global,
+spew.Config. See ConfigState for options documentation.
+
+See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
+get the formatted result as a string.
+*/
+func Dump(a ...interface{}) {
+ fdump(&Config, os.Stdout, a...)
+}
diff --git a/vendor/github.com/davecgh/go-spew/spew/format.go b/vendor/github.com/davecgh/go-spew/spew/format.go
new file mode 100644
index 0000000..b04edb7
--- /dev/null
+++ b/vendor/github.com/davecgh/go-spew/spew/format.go
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+// supportedFlags is a list of all the character flags supported by fmt package.
+const supportedFlags = "0-+# "
+
+// formatState implements the fmt.Formatter interface and contains information
+// about the state of a formatting operation. The NewFormatter function can
+// be used to get a new Formatter which can be used directly as arguments
+// in standard fmt package printing calls.
+type formatState struct {
+ value interface{}
+ fs fmt.State
+ depth int
+ pointers map[uintptr]int
+ ignoreNextType bool
+ cs *ConfigState
+}
+
+// buildDefaultFormat recreates the original format string without precision
+// and width information to pass in to fmt.Sprintf in the case of an
+// unrecognized type. Unless new types are added to the language, this
+// function won't ever be called.
+func (f *formatState) buildDefaultFormat() (format string) {
+ buf := bytes.NewBuffer(percentBytes)
+
+ for _, flag := range supportedFlags {
+ if f.fs.Flag(int(flag)) {
+ buf.WriteRune(flag)
+ }
+ }
+
+ buf.WriteRune('v')
+
+ format = buf.String()
+ return format
+}
+
+// constructOrigFormat recreates the original format string including precision
+// and width information to pass along to the standard fmt package. This allows
+// automatic deferral of all format strings this package doesn't support.
+func (f *formatState) constructOrigFormat(verb rune) (format string) {
+ buf := bytes.NewBuffer(percentBytes)
+
+ for _, flag := range supportedFlags {
+ if f.fs.Flag(int(flag)) {
+ buf.WriteRune(flag)
+ }
+ }
+
+ if width, ok := f.fs.Width(); ok {
+ buf.WriteString(strconv.Itoa(width))
+ }
+
+ if precision, ok := f.fs.Precision(); ok {
+ buf.Write(precisionBytes)
+ buf.WriteString(strconv.Itoa(precision))
+ }
+
+ buf.WriteRune(verb)
+
+ format = buf.String()
+ return format
+}
+
+// unpackValue returns values inside of non-nil interfaces when possible and
+// ensures that types for values which have been unpacked from an interface
+// are displayed when the show types flag is also set.
+// This is useful for data types like structs, arrays, slices, and maps which
+// can contain varying types packed inside an interface.
+func (f *formatState) unpackValue(v reflect.Value) reflect.Value {
+ if v.Kind() == reflect.Interface {
+ f.ignoreNextType = false
+ if !v.IsNil() {
+ v = v.Elem()
+ }
+ }
+ return v
+}
+
+// formatPtr handles formatting of pointers by indirecting them as necessary.
+func (f *formatState) formatPtr(v reflect.Value) {
+ // Display nil if top level pointer is nil.
+ showTypes := f.fs.Flag('#')
+ if v.IsNil() && (!showTypes || f.ignoreNextType) {
+ f.fs.Write(nilAngleBytes)
+ return
+ }
+
+ // Remove pointers at or below the current depth from map used to detect
+ // circular refs.
+ for k, depth := range f.pointers {
+ if depth >= f.depth {
+ delete(f.pointers, k)
+ }
+ }
+
+ // Keep list of all dereferenced pointers to possibly show later.
+ pointerChain := make([]uintptr, 0)
+
+ // Figure out how many levels of indirection there are by derferencing
+ // pointers and unpacking interfaces down the chain while detecting circular
+ // references.
+ nilFound := false
+ cycleFound := false
+ indirects := 0
+ ve := v
+ for ve.Kind() == reflect.Ptr {
+ if ve.IsNil() {
+ nilFound = true
+ break
+ }
+ indirects++
+ addr := ve.Pointer()
+ pointerChain = append(pointerChain, addr)
+ if pd, ok := f.pointers[addr]; ok && pd < f.depth {
+ cycleFound = true
+ indirects--
+ break
+ }
+ f.pointers[addr] = f.depth
+
+ ve = ve.Elem()
+ if ve.Kind() == reflect.Interface {
+ if ve.IsNil() {
+ nilFound = true
+ break
+ }
+ ve = ve.Elem()
+ }
+ }
+
+ // Display type or indirection level depending on flags.
+ if showTypes && !f.ignoreNextType {
+ f.fs.Write(openParenBytes)
+ f.fs.Write(bytes.Repeat(asteriskBytes, indirects))
+ f.fs.Write([]byte(ve.Type().String()))
+ f.fs.Write(closeParenBytes)
+ } else {
+ if nilFound || cycleFound {
+ indirects += strings.Count(ve.Type().String(), "*")
+ }
+ f.fs.Write(openAngleBytes)
+ f.fs.Write([]byte(strings.Repeat("*", indirects)))
+ f.fs.Write(closeAngleBytes)
+ }
+
+ // Display pointer information depending on flags.
+ if f.fs.Flag('+') && (len(pointerChain) > 0) {
+ f.fs.Write(openParenBytes)
+ for i, addr := range pointerChain {
+ if i > 0 {
+ f.fs.Write(pointerChainBytes)
+ }
+ printHexPtr(f.fs, addr)
+ }
+ f.fs.Write(closeParenBytes)
+ }
+
+ // Display dereferenced value.
+ switch {
+ case nilFound:
+ f.fs.Write(nilAngleBytes)
+
+ case cycleFound:
+ f.fs.Write(circularShortBytes)
+
+ default:
+ f.ignoreNextType = true
+ f.format(ve)
+ }
+}
+
+// format is the main workhorse for providing the Formatter interface. It
+// uses the passed reflect value to figure out what kind of object we are
+// dealing with and formats it appropriately. It is a recursive function,
+// however circular data structures are detected and handled properly.
+func (f *formatState) format(v reflect.Value) {
+ // Handle invalid reflect values immediately.
+ kind := v.Kind()
+ if kind == reflect.Invalid {
+ f.fs.Write(invalidAngleBytes)
+ return
+ }
+
+ // Handle pointers specially.
+ if kind == reflect.Ptr {
+ f.formatPtr(v)
+ return
+ }
+
+ // Print type information unless already handled elsewhere.
+ if !f.ignoreNextType && f.fs.Flag('#') {
+ f.fs.Write(openParenBytes)
+ f.fs.Write([]byte(v.Type().String()))
+ f.fs.Write(closeParenBytes)
+ }
+ f.ignoreNextType = false
+
+ // Call Stringer/error interfaces if they exist and the handle methods
+ // flag is enabled.
+ if !f.cs.DisableMethods {
+ if (kind != reflect.Invalid) && (kind != reflect.Interface) {
+ if handled := handleMethods(f.cs, f.fs, v); handled {
+ return
+ }
+ }
+ }
+
+ switch kind {
+ case reflect.Invalid:
+ // Do nothing. We should never get here since invalid has already
+ // been handled above.
+
+ case reflect.Bool:
+ printBool(f.fs, v.Bool())
+
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+ printInt(f.fs, v.Int(), 10)
+
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+ printUint(f.fs, v.Uint(), 10)
+
+ case reflect.Float32:
+ printFloat(f.fs, v.Float(), 32)
+
+ case reflect.Float64:
+ printFloat(f.fs, v.Float(), 64)
+
+ case reflect.Complex64:
+ printComplex(f.fs, v.Complex(), 32)
+
+ case reflect.Complex128:
+ printComplex(f.fs, v.Complex(), 64)
+
+ case reflect.Slice:
+ if v.IsNil() {
+ f.fs.Write(nilAngleBytes)
+ break
+ }
+ fallthrough
+
+ case reflect.Array:
+ f.fs.Write(openBracketBytes)
+ f.depth++
+ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
+ f.fs.Write(maxShortBytes)
+ } else {
+ numEntries := v.Len()
+ for i := 0; i < numEntries; i++ {
+ if i > 0 {
+ f.fs.Write(spaceBytes)
+ }
+ f.ignoreNextType = true
+ f.format(f.unpackValue(v.Index(i)))
+ }
+ }
+ f.depth--
+ f.fs.Write(closeBracketBytes)
+
+ case reflect.String:
+ f.fs.Write([]byte(v.String()))
+
+ case reflect.Interface:
+ // The only time we should get here is for nil interfaces due to
+ // unpackValue calls.
+ if v.IsNil() {
+ f.fs.Write(nilAngleBytes)
+ }
+
+ case reflect.Ptr:
+ // Do nothing. We should never get here since pointers have already
+ // been handled above.
+
+ case reflect.Map:
+ // nil maps should be indicated as different than empty maps
+ if v.IsNil() {
+ f.fs.Write(nilAngleBytes)
+ break
+ }
+
+ f.fs.Write(openMapBytes)
+ f.depth++
+ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
+ f.fs.Write(maxShortBytes)
+ } else {
+ keys := v.MapKeys()
+ if f.cs.SortKeys {
+ sortValues(keys, f.cs)
+ }
+ for i, key := range keys {
+ if i > 0 {
+ f.fs.Write(spaceBytes)
+ }
+ f.ignoreNextType = true
+ f.format(f.unpackValue(key))
+ f.fs.Write(colonBytes)
+ f.ignoreNextType = true
+ f.format(f.unpackValue(v.MapIndex(key)))
+ }
+ }
+ f.depth--
+ f.fs.Write(closeMapBytes)
+
+ case reflect.Struct:
+ numFields := v.NumField()
+ f.fs.Write(openBraceBytes)
+ f.depth++
+ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
+ f.fs.Write(maxShortBytes)
+ } else {
+ vt := v.Type()
+ for i := 0; i < numFields; i++ {
+ if i > 0 {
+ f.fs.Write(spaceBytes)
+ }
+ vtf := vt.Field(i)
+ if f.fs.Flag('+') || f.fs.Flag('#') {
+ f.fs.Write([]byte(vtf.Name))
+ f.fs.Write(colonBytes)
+ }
+ f.format(f.unpackValue(v.Field(i)))
+ }
+ }
+ f.depth--
+ f.fs.Write(closeBraceBytes)
+
+ case reflect.Uintptr:
+ printHexPtr(f.fs, uintptr(v.Uint()))
+
+ case reflect.UnsafePointer, reflect.Chan, reflect.Func:
+ printHexPtr(f.fs, v.Pointer())
+
+ // There were not any other types at the time this code was written, but
+ // fall back to letting the default fmt package handle it if any get added.
+ default:
+ format := f.buildDefaultFormat()
+ if v.CanInterface() {
+ fmt.Fprintf(f.fs, format, v.Interface())
+ } else {
+ fmt.Fprintf(f.fs, format, v.String())
+ }
+ }
+}
+
+// Format satisfies the fmt.Formatter interface. See NewFormatter for usage
+// details.
+func (f *formatState) Format(fs fmt.State, verb rune) {
+ f.fs = fs
+
+ // Use standard formatting for verbs that are not v.
+ if verb != 'v' {
+ format := f.constructOrigFormat(verb)
+ fmt.Fprintf(fs, format, f.value)
+ return
+ }
+
+ if f.value == nil {
+ if fs.Flag('#') {
+ fs.Write(interfaceBytes)
+ }
+ fs.Write(nilAngleBytes)
+ return
+ }
+
+ f.format(reflect.ValueOf(f.value))
+}
+
+// newFormatter is a helper function to consolidate the logic from the various
+// public methods which take varying config states.
+func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter {
+ fs := &formatState{value: v, cs: cs}
+ fs.pointers = make(map[uintptr]int)
+ return fs
+}
+
+/*
+NewFormatter returns a custom formatter that satisfies the fmt.Formatter
+interface. As a result, it integrates cleanly with standard fmt package
+printing functions. The formatter is useful for inline printing of smaller data
+types similar to the standard %v format specifier.
+
+The custom formatter only responds to the %v (most compact), %+v (adds pointer
+addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
+combinations. Any other verbs such as %x and %q will be sent to the the
+standard fmt package for formatting. In addition, the custom formatter ignores
+the width and precision arguments (however they will still work on the format
+specifiers not handled by the custom formatter).
+
+Typically this function shouldn't be called directly. It is much easier to make
+use of the custom formatter by calling one of the convenience functions such as
+Printf, Println, or Fprintf.
+*/
+func NewFormatter(v interface{}) fmt.Formatter {
+ return newFormatter(&Config, v)
+}
diff --git a/vendor/github.com/davecgh/go-spew/spew/spew.go b/vendor/github.com/davecgh/go-spew/spew/spew.go
new file mode 100644
index 0000000..32c0e33
--- /dev/null
+++ b/vendor/github.com/davecgh/go-spew/spew/spew.go
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+ "fmt"
+ "io"
+)
+
+// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the formatted string as a value that satisfies error. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b))
+func Errorf(format string, a ...interface{}) (err error) {
+ return fmt.Errorf(format, convertArgs(a)...)
+}
+
+// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b))
+func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
+ return fmt.Fprint(w, convertArgs(a)...)
+}
+
+// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b))
+func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
+ return fmt.Fprintf(w, format, convertArgs(a)...)
+}
+
+// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
+// passed with a default Formatter interface returned by NewFormatter. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b))
+func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
+ return fmt.Fprintln(w, convertArgs(a)...)
+}
+
+// Print is a wrapper for fmt.Print that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b))
+func Print(a ...interface{}) (n int, err error) {
+ return fmt.Print(convertArgs(a)...)
+}
+
+// Printf is a wrapper for fmt.Printf that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b))
+func Printf(format string, a ...interface{}) (n int, err error) {
+ return fmt.Printf(format, convertArgs(a)...)
+}
+
+// Println is a wrapper for fmt.Println that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b))
+func Println(a ...interface{}) (n int, err error) {
+ return fmt.Println(convertArgs(a)...)
+}
+
+// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the resulting string. See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b))
+func Sprint(a ...interface{}) string {
+ return fmt.Sprint(convertArgs(a)...)
+}
+
+// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the resulting string. See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b))
+func Sprintf(format string, a ...interface{}) string {
+ return fmt.Sprintf(format, convertArgs(a)...)
+}
+
+// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
+// were passed with a default Formatter interface returned by NewFormatter. It
+// returns the resulting string. See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b))
+func Sprintln(a ...interface{}) string {
+ return fmt.Sprintln(convertArgs(a)...)
+}
+
+// convertArgs accepts a slice of arguments and returns a slice of the same
+// length with each argument converted to a default spew Formatter interface.
+func convertArgs(args []interface{}) (formatters []interface{}) {
+ formatters = make([]interface{}, len(args))
+ for index, arg := range args {
+ formatters[index] = NewFormatter(arg)
+ }
+ return formatters
+}
diff --git a/vendor/github.com/golang/mock/AUTHORS b/vendor/github.com/golang/mock/AUTHORS
new file mode 100644
index 0000000..660b8cc
--- /dev/null
+++ b/vendor/github.com/golang/mock/AUTHORS
@@ -0,0 +1,12 @@
+# This is the official list of GoMock authors for copyright purposes.
+# This file is distinct from the CONTRIBUTORS files.
+# See the latter for an explanation.
+
+# Names should be added to this file as
+# Name or Organization <email address>
+# The email address is not required for organizations.
+
+# Please keep the list sorted.
+
+Alex Reece <awreece@gmail.com>
+Google Inc.
diff --git a/vendor/github.com/golang/mock/CONTRIBUTORS b/vendor/github.com/golang/mock/CONTRIBUTORS
new file mode 100644
index 0000000..def849c
--- /dev/null
+++ b/vendor/github.com/golang/mock/CONTRIBUTORS
@@ -0,0 +1,37 @@
+# This is the official list of people who can contribute (and typically
+# have contributed) code to the gomock repository.
+# The AUTHORS file lists the copyright holders; this file
+# lists people. For example, Google employees are listed here
+# but not in AUTHORS, because Google holds the copyright.
+#
+# The submission process automatically checks to make sure
+# that people submitting code are listed in this file (by email address).
+#
+# Names should be added to this file only after verifying that
+# the individual or the individual's organization has agreed to
+# the appropriate Contributor License Agreement, found here:
+#
+# http://code.google.com/legal/individual-cla-v1.0.html
+# http://code.google.com/legal/corporate-cla-v1.0.html
+#
+# The agreement for individuals can be filled out on the web.
+#
+# When adding J Random Contributor's name to this file,
+# either J's name or J's organization's name should be
+# added to the AUTHORS file, depending on whether the
+# individual or corporate CLA was used.
+
+# Names should be added to this file like so:
+# Name <email address>
+#
+# An entry with two email addresses specifies that the
+# first address should be used in the submit logs and
+# that the second address should be recognized as the
+# same person when interacting with Rietveld.
+
+# Please keep the list sorted.
+
+Aaron Jacobs <jacobsa@google.com> <aaronjjacobs@gmail.com>
+Alex Reece <awreece@gmail.com>
+David Symonds <dsymonds@golang.org>
+Ryan Barrett <ryanb@google.com>
diff --git a/vendor/github.com/golang/mock/LICENSE b/vendor/github.com/golang/mock/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/vendor/github.com/golang/mock/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/vendor/github.com/golang/mock/gomock/call.go b/vendor/github.com/golang/mock/gomock/call.go
new file mode 100644
index 0000000..7345f65
--- /dev/null
+++ b/vendor/github.com/golang/mock/gomock/call.go
@@ -0,0 +1,427 @@
+// Copyright 2010 Google Inc.
+//
+// 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 gomock
+
+import (
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+// Call represents an expected call to a mock.
+type Call struct {
+ t TestHelper // for triggering test failures on invalid call setup
+
+ receiver interface{} // the receiver of the method call
+ method string // the name of the method
+ methodType reflect.Type // the type of the method
+ args []Matcher // the args
+ origin string // file and line number of call setup
+
+ preReqs []*Call // prerequisite calls
+
+ // Expectations
+ minCalls, maxCalls int
+
+ numCalls int // actual number made
+
+ // actions are called when this Call is called. Each action gets the args and
+ // can set the return values by returning a non-nil slice. Actions run in the
+ // order they are created.
+ actions []func([]interface{}) []interface{}
+}
+
+// newCall creates a *Call. It requires the method type in order to support
+// unexported methods.
+func newCall(t TestHelper, receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call {
+ t.Helper()
+
+ // TODO: check arity, types.
+ margs := make([]Matcher, len(args))
+ for i, arg := range args {
+ if m, ok := arg.(Matcher); ok {
+ margs[i] = m
+ } else if arg == nil {
+ // Handle nil specially so that passing a nil interface value
+ // will match the typed nils of concrete args.
+ margs[i] = Nil()
+ } else {
+ margs[i] = Eq(arg)
+ }
+ }
+
+ origin := callerInfo(3)
+ actions := []func([]interface{}) []interface{}{func([]interface{}) []interface{} {
+ // Synthesize the zero value for each of the return args' types.
+ rets := make([]interface{}, methodType.NumOut())
+ for i := 0; i < methodType.NumOut(); i++ {
+ rets[i] = reflect.Zero(methodType.Out(i)).Interface()
+ }
+ return rets
+ }}
+ return &Call{t: t, receiver: receiver, method: method, methodType: methodType,
+ args: margs, origin: origin, minCalls: 1, maxCalls: 1, actions: actions}
+}
+
+// AnyTimes allows the expectation to be called 0 or more times
+func (c *Call) AnyTimes() *Call {
+ c.minCalls, c.maxCalls = 0, 1e8 // close enough to infinity
+ return c
+}
+
+// MinTimes requires the call to occur at least n times. If AnyTimes or MaxTimes have not been called or if MaxTimes
+// was previously called with 1, MinTimes also sets the maximum number of calls to infinity.
+func (c *Call) MinTimes(n int) *Call {
+ c.minCalls = n
+ if c.maxCalls == 1 {
+ c.maxCalls = 1e8
+ }
+ return c
+}
+
+// MaxTimes limits the number of calls to n times. If AnyTimes or MinTimes have not been called or if MinTimes was
+// previously called with 1, MaxTimes also sets the minimum number of calls to 0.
+func (c *Call) MaxTimes(n int) *Call {
+ c.maxCalls = n
+ if c.minCalls == 1 {
+ c.minCalls = 0
+ }
+ return c
+}
+
+// DoAndReturn declares the action to run when the call is matched.
+// The return values from this function are returned by the mocked function.
+// It takes an interface{} argument to support n-arity functions.
+func (c *Call) DoAndReturn(f interface{}) *Call {
+ // TODO: Check arity and types here, rather than dying badly elsewhere.
+ v := reflect.ValueOf(f)
+
+ c.addAction(func(args []interface{}) []interface{} {
+ vargs := make([]reflect.Value, len(args))
+ ft := v.Type()
+ for i := 0; i < len(args); i++ {
+ if args[i] != nil {
+ vargs[i] = reflect.ValueOf(args[i])
+ } else {
+ // Use the zero value for the arg.
+ vargs[i] = reflect.Zero(ft.In(i))
+ }
+ }
+ vrets := v.Call(vargs)
+ rets := make([]interface{}, len(vrets))
+ for i, ret := range vrets {
+ rets[i] = ret.Interface()
+ }
+ return rets
+ })
+ return c
+}
+
+// Do declares the action to run when the call is matched. The function's
+// return values are ignored to retain backward compatibility. To use the
+// return values call DoAndReturn.
+// It takes an interface{} argument to support n-arity functions.
+func (c *Call) Do(f interface{}) *Call {
+ // TODO: Check arity and types here, rather than dying badly elsewhere.
+ v := reflect.ValueOf(f)
+
+ c.addAction(func(args []interface{}) []interface{} {
+ vargs := make([]reflect.Value, len(args))
+ ft := v.Type()
+ for i := 0; i < len(args); i++ {
+ if args[i] != nil {
+ vargs[i] = reflect.ValueOf(args[i])
+ } else {
+ // Use the zero value for the arg.
+ vargs[i] = reflect.Zero(ft.In(i))
+ }
+ }
+ v.Call(vargs)
+ return nil
+ })
+ return c
+}
+
+// Return declares the values to be returned by the mocked function call.
+func (c *Call) Return(rets ...interface{}) *Call {
+ c.t.Helper()
+
+ mt := c.methodType
+ if len(rets) != mt.NumOut() {
+ c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d [%s]",
+ c.receiver, c.method, len(rets), mt.NumOut(), c.origin)
+ }
+ for i, ret := range rets {
+ if got, want := reflect.TypeOf(ret), mt.Out(i); got == want {
+ // Identical types; nothing to do.
+ } else if got == nil {
+ // Nil needs special handling.
+ switch want.Kind() {
+ case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+ // ok
+ default:
+ c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable [%s]",
+ i, c.receiver, c.method, want, c.origin)
+ }
+ } else if got.AssignableTo(want) {
+ // Assignable type relation. Make the assignment now so that the generated code
+ // can return the values with a type assertion.
+ v := reflect.New(want).Elem()
+ v.Set(reflect.ValueOf(ret))
+ rets[i] = v.Interface()
+ } else {
+ c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v [%s]",
+ i, c.receiver, c.method, got, want, c.origin)
+ }
+ }
+
+ c.addAction(func([]interface{}) []interface{} {
+ return rets
+ })
+
+ return c
+}
+
+// Times declares the exact number of times a function call is expected to be executed.
+func (c *Call) Times(n int) *Call {
+ c.minCalls, c.maxCalls = n, n
+ return c
+}
+
+// SetArg declares an action that will set the nth argument's value,
+// indirected through a pointer. Or, in the case of a slice, SetArg
+// will copy value's elements into the nth argument.
+func (c *Call) SetArg(n int, value interface{}) *Call {
+ c.t.Helper()
+
+ mt := c.methodType
+ // TODO: This will break on variadic methods.
+ // We will need to check those at invocation time.
+ if n < 0 || n >= mt.NumIn() {
+ c.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]",
+ n, mt.NumIn(), c.origin)
+ }
+ // Permit setting argument through an interface.
+ // In the interface case, we don't (nay, can't) check the type here.
+ at := mt.In(n)
+ switch at.Kind() {
+ case reflect.Ptr:
+ dt := at.Elem()
+ if vt := reflect.TypeOf(value); !vt.AssignableTo(dt) {
+ c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v [%s]",
+ n, vt, dt, c.origin)
+ }
+ case reflect.Interface:
+ // nothing to do
+ case reflect.Slice:
+ // nothing to do
+ default:
+ c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice type %v [%s]",
+ n, at, c.origin)
+ }
+
+ c.addAction(func(args []interface{}) []interface{} {
+ v := reflect.ValueOf(value)
+ switch reflect.TypeOf(args[n]).Kind() {
+ case reflect.Slice:
+ setSlice(args[n], v)
+ default:
+ reflect.ValueOf(args[n]).Elem().Set(v)
+ }
+ return nil
+ })
+ return c
+}
+
+// isPreReq returns true if other is a direct or indirect prerequisite to c.
+func (c *Call) isPreReq(other *Call) bool {
+ for _, preReq := range c.preReqs {
+ if other == preReq || preReq.isPreReq(other) {
+ return true
+ }
+ }
+ return false
+}
+
+// After declares that the call may only match after preReq has been exhausted.
+func (c *Call) After(preReq *Call) *Call {
+ c.t.Helper()
+
+ if c == preReq {
+ c.t.Fatalf("A call isn't allowed to be its own prerequisite")
+ }
+ if preReq.isPreReq(c) {
+ c.t.Fatalf("Loop in call order: %v is a prerequisite to %v (possibly indirectly).", c, preReq)
+ }
+
+ c.preReqs = append(c.preReqs, preReq)
+ return c
+}
+
+// Returns true if the minimum number of calls have been made.
+func (c *Call) satisfied() bool {
+ return c.numCalls >= c.minCalls
+}
+
+// Returns true if the maximum number of calls have been made.
+func (c *Call) exhausted() bool {
+ return c.numCalls >= c.maxCalls
+}
+
+func (c *Call) String() string {
+ args := make([]string, len(c.args))
+ for i, arg := range c.args {
+ args[i] = arg.String()
+ }
+ arguments := strings.Join(args, ", ")
+ return fmt.Sprintf("%T.%v(%s) %s", c.receiver, c.method, arguments, c.origin)
+}
+
+// Tests if the given call matches the expected call.
+// If yes, returns nil. If no, returns error with message explaining why it does not match.
+func (c *Call) matches(args []interface{}) error {
+ if !c.methodType.IsVariadic() {
+ if len(args) != len(c.args) {
+ return fmt.Errorf("expected call at %s has the wrong number of arguments. Got: %d, want: %d",
+ c.origin, len(args), len(c.args))
+ }
+
+ for i, m := range c.args {
+ if !m.Matches(args[i]) {
+ got := fmt.Sprintf("%v", args[i])
+ if gs, ok := m.(GotFormatter); ok {
+ got = gs.Got(args[i])
+ }
+
+ return fmt.Errorf(
+ "expected call at %s doesn't match the argument at index %d.\nGot: %v\nWant: %v",
+ c.origin, i, got, m,
+ )
+ }
+ }
+ } else {
+ if len(c.args) < c.methodType.NumIn()-1 {
+ return fmt.Errorf("expected call at %s has the wrong number of matchers. Got: %d, want: %d",
+ c.origin, len(c.args), c.methodType.NumIn()-1)
+ }
+ if len(c.args) != c.methodType.NumIn() && len(args) != len(c.args) {
+ return fmt.Errorf("expected call at %s has the wrong number of arguments. Got: %d, want: %d",
+ c.origin, len(args), len(c.args))
+ }
+ if len(args) < len(c.args)-1 {
+ return fmt.Errorf("expected call at %s has the wrong number of arguments. Got: %d, want: greater than or equal to %d",
+ c.origin, len(args), len(c.args)-1)
+ }
+
+ for i, m := range c.args {
+ if i < c.methodType.NumIn()-1 {
+ // Non-variadic args
+ if !m.Matches(args[i]) {
+ return fmt.Errorf("expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
+ c.origin, strconv.Itoa(i), args[i], m)
+ }
+ continue
+ }
+ // The last arg has a possibility of a variadic argument, so let it branch
+
+ // sample: Foo(a int, b int, c ...int)
+ if i < len(c.args) && i < len(args) {
+ if m.Matches(args[i]) {
+ // Got Foo(a, b, c) want Foo(matcherA, matcherB, gomock.Any())
+ // Got Foo(a, b, c) want Foo(matcherA, matcherB, someSliceMatcher)
+ // Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC)
+ // Got Foo(a, b) want Foo(matcherA, matcherB)
+ // Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD)
+ continue
+ }
+ }
+
+ // The number of actual args don't match the number of matchers,
+ // or the last matcher is a slice and the last arg is not.
+ // If this function still matches it is because the last matcher
+ // matches all the remaining arguments or the lack of any.
+ // Convert the remaining arguments, if any, into a slice of the
+ // expected type.
+ vargsType := c.methodType.In(c.methodType.NumIn() - 1)
+ vargs := reflect.MakeSlice(vargsType, 0, len(args)-i)
+ for _, arg := range args[i:] {
+ vargs = reflect.Append(vargs, reflect.ValueOf(arg))
+ }
+ if m.Matches(vargs.Interface()) {
+ // Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, gomock.Any())
+ // Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, someSliceMatcher)
+ // Got Foo(a, b) want Foo(matcherA, matcherB, gomock.Any())
+ // Got Foo(a, b) want Foo(matcherA, matcherB, someEmptySliceMatcher)
+ break
+ }
+ // Wrong number of matchers or not match. Fail.
+ // Got Foo(a, b) want Foo(matcherA, matcherB, matcherC, matcherD)
+ // Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC, matcherD)
+ // Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD, matcherE)
+ // Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, matcherC, matcherD)
+ // Got Foo(a, b, c) want Foo(matcherA, matcherB)
+ return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
+ c.origin, strconv.Itoa(i), args[i:], c.args[i])
+
+ }
+ }
+
+ // Check that all prerequisite calls have been satisfied.
+ for _, preReqCall := range c.preReqs {
+ if !preReqCall.satisfied() {
+ return fmt.Errorf("Expected call at %s doesn't have a prerequisite call satisfied:\n%v\nshould be called before:\n%v",
+ c.origin, preReqCall, c)
+ }
+ }
+
+ // Check that the call is not exhausted.
+ if c.exhausted() {
+ return fmt.Errorf("expected call at %s has already been called the max number of times", c.origin)
+ }
+
+ return nil
+}
+
+// dropPrereqs tells the expected Call to not re-check prerequisite calls any
+// longer, and to return its current set.
+func (c *Call) dropPrereqs() (preReqs []*Call) {
+ preReqs = c.preReqs
+ c.preReqs = nil
+ return
+}
+
+func (c *Call) call() []func([]interface{}) []interface{} {
+ c.numCalls++
+ return c.actions
+}
+
+// InOrder declares that the given calls should occur in order.
+func InOrder(calls ...*Call) {
+ for i := 1; i < len(calls); i++ {
+ calls[i].After(calls[i-1])
+ }
+}
+
+func setSlice(arg interface{}, v reflect.Value) {
+ va := reflect.ValueOf(arg)
+ for i := 0; i < v.Len(); i++ {
+ va.Index(i).Set(v.Index(i))
+ }
+}
+
+func (c *Call) addAction(action func([]interface{}) []interface{}) {
+ c.actions = append(c.actions, action)
+}
diff --git a/vendor/github.com/golang/mock/gomock/callset.go b/vendor/github.com/golang/mock/gomock/callset.go
new file mode 100644
index 0000000..b046b52
--- /dev/null
+++ b/vendor/github.com/golang/mock/gomock/callset.go
@@ -0,0 +1,108 @@
+// Copyright 2011 Google Inc.
+//
+// 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 gomock
+
+import (
+ "bytes"
+ "fmt"
+)
+
+// callSet represents a set of expected calls, indexed by receiver and method
+// name.
+type callSet struct {
+ // Calls that are still expected.
+ expected map[callSetKey][]*Call
+ // Calls that have been exhausted.
+ exhausted map[callSetKey][]*Call
+}
+
+// callSetKey is the key in the maps in callSet
+type callSetKey struct {
+ receiver interface{}
+ fname string
+}
+
+func newCallSet() *callSet {
+ return &callSet{make(map[callSetKey][]*Call), make(map[callSetKey][]*Call)}
+}
+
+// Add adds a new expected call.
+func (cs callSet) Add(call *Call) {
+ key := callSetKey{call.receiver, call.method}
+ m := cs.expected
+ if call.exhausted() {
+ m = cs.exhausted
+ }
+ m[key] = append(m[key], call)
+}
+
+// Remove removes an expected call.
+func (cs callSet) Remove(call *Call) {
+ key := callSetKey{call.receiver, call.method}
+ calls := cs.expected[key]
+ for i, c := range calls {
+ if c == call {
+ // maintain order for remaining calls
+ cs.expected[key] = append(calls[:i], calls[i+1:]...)
+ cs.exhausted[key] = append(cs.exhausted[key], call)
+ break
+ }
+ }
+}
+
+// FindMatch searches for a matching call. Returns error with explanation message if no call matched.
+func (cs callSet) FindMatch(receiver interface{}, method string, args []interface{}) (*Call, error) {
+ key := callSetKey{receiver, method}
+
+ // Search through the expected calls.
+ expected := cs.expected[key]
+ var callsErrors bytes.Buffer
+ for _, call := range expected {
+ err := call.matches(args)
+ if err != nil {
+ _, _ = fmt.Fprintf(&callsErrors, "\n%v", err)
+ } else {
+ return call, nil
+ }
+ }
+
+ // If we haven't found a match then search through the exhausted calls so we
+ // get useful error messages.
+ exhausted := cs.exhausted[key]
+ for _, call := range exhausted {
+ if err := call.matches(args); err != nil {
+ _, _ = fmt.Fprintf(&callsErrors, "\n%v", err)
+ }
+ }
+
+ if len(expected)+len(exhausted) == 0 {
+ _, _ = fmt.Fprintf(&callsErrors, "there are no expected calls of the method %q for that receiver", method)
+ }
+
+ return nil, fmt.Errorf(callsErrors.String())
+}
+
+// Failures returns the calls that are not satisfied.
+func (cs callSet) Failures() []*Call {
+ failures := make([]*Call, 0, len(cs.expected))
+ for _, calls := range cs.expected {
+ for _, call := range calls {
+ if !call.satisfied() {
+ failures = append(failures, call)
+ }
+ }
+ }
+ return failures
+}
diff --git a/vendor/github.com/golang/mock/gomock/controller.go b/vendor/github.com/golang/mock/gomock/controller.go
new file mode 100644
index 0000000..d7c3c65
--- /dev/null
+++ b/vendor/github.com/golang/mock/gomock/controller.go
@@ -0,0 +1,264 @@
+// Copyright 2010 Google Inc.
+//
+// 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 gomock is a mock framework for Go.
+//
+// Standard usage:
+// (1) Define an interface that you wish to mock.
+// type MyInterface interface {
+// SomeMethod(x int64, y string)
+// }
+// (2) Use mockgen to generate a mock from the interface.
+// (3) Use the mock in a test:
+// func TestMyThing(t *testing.T) {
+// mockCtrl := gomock.NewController(t)
+// defer mockCtrl.Finish()
+//
+// mockObj := something.NewMockMyInterface(mockCtrl)
+// mockObj.EXPECT().SomeMethod(4, "blah")
+// // pass mockObj to a real object and play with it.
+// }
+//
+// By default, expected calls are not enforced to run in any particular order.
+// Call order dependency can be enforced by use of InOrder and/or Call.After.
+// Call.After can create more varied call order dependencies, but InOrder is
+// often more convenient.
+//
+// The following examples create equivalent call order dependencies.
+//
+// Example of using Call.After to chain expected call order:
+//
+// firstCall := mockObj.EXPECT().SomeMethod(1, "first")
+// secondCall := mockObj.EXPECT().SomeMethod(2, "second").After(firstCall)
+// mockObj.EXPECT().SomeMethod(3, "third").After(secondCall)
+//
+// Example of using InOrder to declare expected call order:
+//
+// gomock.InOrder(
+// mockObj.EXPECT().SomeMethod(1, "first"),
+// mockObj.EXPECT().SomeMethod(2, "second"),
+// mockObj.EXPECT().SomeMethod(3, "third"),
+// )
+//
+// TODO:
+// - Handle different argument/return types (e.g. ..., chan, map, interface).
+package gomock
+
+import (
+ "context"
+ "fmt"
+ "reflect"
+ "runtime"
+ "sync"
+)
+
+// A TestReporter is something that can be used to report test failures. It
+// is satisfied by the standard library's *testing.T.
+type TestReporter interface {
+ Errorf(format string, args ...interface{})
+ Fatalf(format string, args ...interface{})
+}
+
+// TestHelper is a TestReporter that has the Helper method. It is satisfied
+// by the standard library's *testing.T.
+type TestHelper interface {
+ TestReporter
+ Helper()
+}
+
+// A Controller represents the top-level control of a mock ecosystem. It
+// defines the scope and lifetime of mock objects, as well as their
+// expectations. It is safe to call Controller's methods from multiple
+// goroutines. Each test should create a new Controller and invoke Finish via
+// defer.
+//
+// func TestFoo(t *testing.T) {
+// ctrl := gomock.NewController(t)
+// defer ctrl.Finish()
+// // ..
+// }
+//
+// func TestBar(t *testing.T) {
+// t.Run("Sub-Test-1", st) {
+// ctrl := gomock.NewController(st)
+// defer ctrl.Finish()
+// // ..
+// })
+// t.Run("Sub-Test-2", st) {
+// ctrl := gomock.NewController(st)
+// defer ctrl.Finish()
+// // ..
+// })
+// })
+type Controller struct {
+ // T should only be called within a generated mock. It is not intended to
+ // be used in user code and may be changed in future versions. T is the
+ // TestReporter passed in when creating the Controller via NewController.
+ // If the TestReporter does not implement a TestHelper it will be wrapped
+ // with a nopTestHelper.
+ T TestHelper
+ mu sync.Mutex
+ expectedCalls *callSet
+ finished bool
+}
+
+// NewController returns a new Controller. It is the preferred way to create a
+// Controller.
+func NewController(t TestReporter) *Controller {
+ h, ok := t.(TestHelper)
+ if !ok {
+ h = nopTestHelper{t}
+ }
+
+ return &Controller{
+ T: h,
+ expectedCalls: newCallSet(),
+ }
+}
+
+type cancelReporter struct {
+ TestHelper
+ cancel func()
+}
+
+func (r *cancelReporter) Errorf(format string, args ...interface{}) {
+ r.TestHelper.Errorf(format, args...)
+}
+func (r *cancelReporter) Fatalf(format string, args ...interface{}) {
+ defer r.cancel()
+ r.TestHelper.Fatalf(format, args...)
+}
+
+// WithContext returns a new Controller and a Context, which is cancelled on any
+// fatal failure.
+func WithContext(ctx context.Context, t TestReporter) (*Controller, context.Context) {
+ h, ok := t.(TestHelper)
+ if !ok {
+ h = nopTestHelper{t}
+ }
+
+ ctx, cancel := context.WithCancel(ctx)
+ return NewController(&cancelReporter{h, cancel}), ctx
+}
+
+type nopTestHelper struct {
+ TestReporter
+}
+
+func (h nopTestHelper) Helper() {}
+
+// RecordCall is called by a mock. It should not be called by user code.
+func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ...interface{}) *Call {
+ ctrl.T.Helper()
+
+ recv := reflect.ValueOf(receiver)
+ for i := 0; i < recv.Type().NumMethod(); i++ {
+ if recv.Type().Method(i).Name == method {
+ return ctrl.RecordCallWithMethodType(receiver, method, recv.Method(i).Type(), args...)
+ }
+ }
+ ctrl.T.Fatalf("gomock: failed finding method %s on %T", method, receiver)
+ panic("unreachable")
+}
+
+// RecordCallWithMethodType is called by a mock. It should not be called by user code.
+func (ctrl *Controller) RecordCallWithMethodType(receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call {
+ ctrl.T.Helper()
+
+ call := newCall(ctrl.T, receiver, method, methodType, args...)
+
+ ctrl.mu.Lock()
+ defer ctrl.mu.Unlock()
+ ctrl.expectedCalls.Add(call)
+
+ return call
+}
+
+// Call is called by a mock. It should not be called by user code.
+func (ctrl *Controller) Call(receiver interface{}, method string, args ...interface{}) []interface{} {
+ ctrl.T.Helper()
+
+ // Nest this code so we can use defer to make sure the lock is released.
+ actions := func() []func([]interface{}) []interface{} {
+ ctrl.T.Helper()
+ ctrl.mu.Lock()
+ defer ctrl.mu.Unlock()
+
+ expected, err := ctrl.expectedCalls.FindMatch(receiver, method, args)
+ if err != nil {
+ origin := callerInfo(2)
+ ctrl.T.Fatalf("Unexpected call to %T.%v(%v) at %s because: %s", receiver, method, args, origin, err)
+ }
+
+ // Two things happen here:
+ // * the matching call no longer needs to check prerequite calls,
+ // * and the prerequite calls are no longer expected, so remove them.
+ preReqCalls := expected.dropPrereqs()
+ for _, preReqCall := range preReqCalls {
+ ctrl.expectedCalls.Remove(preReqCall)
+ }
+
+ actions := expected.call()
+ if expected.exhausted() {
+ ctrl.expectedCalls.Remove(expected)
+ }
+ return actions
+ }()
+
+ var rets []interface{}
+ for _, action := range actions {
+ if r := action(args); r != nil {
+ rets = r
+ }
+ }
+
+ return rets
+}
+
+// Finish checks to see if all the methods that were expected to be called
+// were called. It should be invoked for each Controller. It is not idempotent
+// and therefore can only be invoked once.
+func (ctrl *Controller) Finish() {
+ ctrl.T.Helper()
+
+ ctrl.mu.Lock()
+ defer ctrl.mu.Unlock()
+
+ if ctrl.finished {
+ ctrl.T.Fatalf("Controller.Finish was called more than once. It has to be called exactly once.")
+ }
+ ctrl.finished = true
+
+ // If we're currently panicking, probably because this is a deferred call,
+ // pass through the panic.
+ if err := recover(); err != nil {
+ panic(err)
+ }
+
+ // Check that all remaining expected calls are satisfied.
+ failures := ctrl.expectedCalls.Failures()
+ for _, call := range failures {
+ ctrl.T.Errorf("missing call(s) to %v", call)
+ }
+ if len(failures) != 0 {
+ ctrl.T.Fatalf("aborting test due to missing call(s)")
+ }
+}
+
+func callerInfo(skip int) string {
+ if _, file, line, ok := runtime.Caller(skip + 1); ok {
+ return fmt.Sprintf("%s:%d", file, line)
+ }
+ return "unknown file"
+}
diff --git a/vendor/github.com/golang/mock/gomock/matchers.go b/vendor/github.com/golang/mock/gomock/matchers.go
new file mode 100644
index 0000000..7bfc07b
--- /dev/null
+++ b/vendor/github.com/golang/mock/gomock/matchers.go
@@ -0,0 +1,255 @@
+// Copyright 2010 Google Inc.
+//
+// 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 gomock
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+)
+
+// A Matcher is a representation of a class of values.
+// It is used to represent the valid or expected arguments to a mocked method.
+type Matcher interface {
+ // Matches returns whether x is a match.
+ Matches(x interface{}) bool
+
+ // String describes what the matcher matches.
+ String() string
+}
+
+// WantFormatter modifies the given Matcher's String() method to the given
+// Stringer. This allows for control on how the "Want" is formatted when
+// printing .
+func WantFormatter(s fmt.Stringer, m Matcher) Matcher {
+ type matcher interface {
+ Matches(x interface{}) bool
+ }
+
+ return struct {
+ matcher
+ fmt.Stringer
+ }{
+ matcher: m,
+ Stringer: s,
+ }
+}
+
+// StringerFunc type is an adapter to allow the use of ordinary functions as
+// a Stringer. If f is a function with the appropriate signature,
+// StringerFunc(f) is a Stringer that calls f.
+type StringerFunc func() string
+
+// String implements fmt.Stringer.
+func (f StringerFunc) String() string {
+ return f()
+}
+
+// GotFormatter is used to better print failure messages. If a matcher
+// implements GotFormatter, it will use the result from Got when printing
+// the failure message.
+type GotFormatter interface {
+ // Got is invoked with the received value. The result is used when
+ // printing the failure message.
+ Got(got interface{}) string
+}
+
+// GotFormatterFunc type is an adapter to allow the use of ordinary
+// functions as a GotFormatter. If f is a function with the appropriate
+// signature, GotFormatterFunc(f) is a GotFormatter that calls f.
+type GotFormatterFunc func(got interface{}) string
+
+// Got implements GotFormatter.
+func (f GotFormatterFunc) Got(got interface{}) string {
+ return f(got)
+}
+
+// GotFormatterAdapter attaches a GotFormatter to a Matcher.
+func GotFormatterAdapter(s GotFormatter, m Matcher) Matcher {
+ return struct {
+ GotFormatter
+ Matcher
+ }{
+ GotFormatter: s,
+ Matcher: m,
+ }
+}
+
+type anyMatcher struct{}
+
+func (anyMatcher) Matches(interface{}) bool {
+ return true
+}
+
+func (anyMatcher) String() string {
+ return "is anything"
+}
+
+type eqMatcher struct {
+ x interface{}
+}
+
+func (e eqMatcher) Matches(x interface{}) bool {
+ return reflect.DeepEqual(e.x, x)
+}
+
+func (e eqMatcher) String() string {
+ return fmt.Sprintf("is equal to %v", e.x)
+}
+
+type nilMatcher struct{}
+
+func (nilMatcher) Matches(x interface{}) bool {
+ if x == nil {
+ return true
+ }
+
+ v := reflect.ValueOf(x)
+ switch v.Kind() {
+ case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map,
+ reflect.Ptr, reflect.Slice:
+ return v.IsNil()
+ }
+
+ return false
+}
+
+func (nilMatcher) String() string {
+ return "is nil"
+}
+
+type notMatcher struct {
+ m Matcher
+}
+
+func (n notMatcher) Matches(x interface{}) bool {
+ return !n.m.Matches(x)
+}
+
+func (n notMatcher) String() string {
+ // TODO: Improve this if we add a NotString method to the Matcher interface.
+ return "not(" + n.m.String() + ")"
+}
+
+type assignableToTypeOfMatcher struct {
+ targetType reflect.Type
+}
+
+func (m assignableToTypeOfMatcher) Matches(x interface{}) bool {
+ return reflect.TypeOf(x).AssignableTo(m.targetType)
+}
+
+func (m assignableToTypeOfMatcher) String() string {
+ return "is assignable to " + m.targetType.Name()
+}
+
+type allMatcher struct {
+ matchers []Matcher
+}
+
+func (am allMatcher) Matches(x interface{}) bool {
+ for _, m := range am.matchers {
+ if !m.Matches(x) {
+ return false
+ }
+ }
+ return true
+}
+
+func (am allMatcher) String() string {
+ ss := make([]string, 0, len(am.matchers))
+ for _, matcher := range am.matchers {
+ ss = append(ss, matcher.String())
+ }
+ return strings.Join(ss, "; ")
+}
+
+type lenMatcher struct {
+ i int
+}
+
+func (m lenMatcher) Matches(x interface{}) bool {
+ v := reflect.ValueOf(x)
+ switch v.Kind() {
+ case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
+ return v.Len() == m.i
+ default:
+ return false
+ }
+}
+
+func (m lenMatcher) String() string {
+ return fmt.Sprintf("has length %d", m.i)
+}
+
+// Constructors
+
+// All returns a composite Matcher that returns true if and only all of the
+// matchers return true.
+func All(ms ...Matcher) Matcher { return allMatcher{ms} }
+
+// Any returns a matcher that always matches.
+func Any() Matcher { return anyMatcher{} }
+
+// Eq returns a matcher that matches on equality.
+//
+// Example usage:
+// Eq(5).Matches(5) // returns true
+// Eq(5).Matches(4) // returns false
+func Eq(x interface{}) Matcher { return eqMatcher{x} }
+
+// Len returns a matcher that matches on length. This matcher returns false if
+// is compared to a type that is not an array, chan, map, slice, or string.
+func Len(i int) Matcher {
+ return lenMatcher{i}
+}
+
+// Nil returns a matcher that matches if the received value is nil.
+//
+// Example usage:
+// var x *bytes.Buffer
+// Nil().Matches(x) // returns true
+// x = &bytes.Buffer{}
+// Nil().Matches(x) // returns false
+func Nil() Matcher { return nilMatcher{} }
+
+// Not reverses the results of its given child matcher.
+//
+// Example usage:
+// Not(Eq(5)).Matches(4) // returns true
+// Not(Eq(5)).Matches(5) // returns false
+func Not(x interface{}) Matcher {
+ if m, ok := x.(Matcher); ok {
+ return notMatcher{m}
+ }
+ return notMatcher{Eq(x)}
+}
+
+// AssignableToTypeOf is a Matcher that matches if the parameter to the mock
+// function is assignable to the type of the parameter to this function.
+//
+// Example usage:
+// var s fmt.Stringer = &bytes.Buffer{}
+// AssignableToTypeOf(s).Matches(time.Second) // returns true
+// AssignableToTypeOf(s).Matches(99) // returns false
+//
+// var ctx = reflect.TypeOf((*context.Context)).Elem()
+// AssignableToTypeOf(ctx).Matches(context.Background()) // returns true
+func AssignableToTypeOf(x interface{}) Matcher {
+ if xt, ok := x.(reflect.Type); ok {
+ return assignableToTypeOfMatcher{xt}
+ }
+ return assignableToTypeOfMatcher{reflect.TypeOf(x)}
+}
diff --git a/vendor/github.com/pmezard/go-difflib/LICENSE b/vendor/github.com/pmezard/go-difflib/LICENSE
new file mode 100644
index 0000000..c67dad6
--- /dev/null
+++ b/vendor/github.com/pmezard/go-difflib/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2013, Patrick Mezard
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+ The names of its contributors may not be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go
new file mode 100644
index 0000000..003e99f
--- /dev/null
+++ b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go
@@ -0,0 +1,772 @@
+// Package difflib is a partial port of Python difflib module.
+//
+// It provides tools to compare sequences of strings and generate textual diffs.
+//
+// The following class and functions have been ported:
+//
+// - SequenceMatcher
+//
+// - unified_diff
+//
+// - context_diff
+//
+// Getting unified diffs was the main goal of the port. Keep in mind this code
+// is mostly suitable to output text differences in a human friendly way, there
+// are no guarantees generated diffs are consumable by patch(1).
+package difflib
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "strings"
+)
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
+
+func max(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
+
+func calculateRatio(matches, length int) float64 {
+ if length > 0 {
+ return 2.0 * float64(matches) / float64(length)
+ }
+ return 1.0
+}
+
+type Match struct {
+ A int
+ B int
+ Size int
+}
+
+type OpCode struct {
+ Tag byte
+ I1 int
+ I2 int
+ J1 int
+ J2 int
+}
+
+// SequenceMatcher compares sequence of strings. The basic
+// algorithm predates, and is a little fancier than, an algorithm
+// published in the late 1980's by Ratcliff and Obershelp under the
+// hyperbolic name "gestalt pattern matching". The basic idea is to find
+// the longest contiguous matching subsequence that contains no "junk"
+// elements (R-O doesn't address junk). The same idea is then applied
+// recursively to the pieces of the sequences to the left and to the right
+// of the matching subsequence. This does not yield minimal edit
+// sequences, but does tend to yield matches that "look right" to people.
+//
+// SequenceMatcher tries to compute a "human-friendly diff" between two
+// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the
+// longest *contiguous* & junk-free matching subsequence. That's what
+// catches peoples' eyes. The Windows(tm) windiff has another interesting
+// notion, pairing up elements that appear uniquely in each sequence.
+// That, and the method here, appear to yield more intuitive difference
+// reports than does diff. This method appears to be the least vulnerable
+// to synching up on blocks of "junk lines", though (like blank lines in
+// ordinary text files, or maybe "<P>" lines in HTML files). That may be
+// because this is the only method of the 3 that has a *concept* of
+// "junk" <wink>.
+//
+// Timing: Basic R-O is cubic time worst case and quadratic time expected
+// case. SequenceMatcher is quadratic time for the worst case and has
+// expected-case behavior dependent in a complicated way on how many
+// elements the sequences have in common; best case time is linear.
+type SequenceMatcher struct {
+ a []string
+ b []string
+ b2j map[string][]int
+ IsJunk func(string) bool
+ autoJunk bool
+ bJunk map[string]struct{}
+ matchingBlocks []Match
+ fullBCount map[string]int
+ bPopular map[string]struct{}
+ opCodes []OpCode
+}
+
+func NewMatcher(a, b []string) *SequenceMatcher {
+ m := SequenceMatcher{autoJunk: true}
+ m.SetSeqs(a, b)
+ return &m
+}
+
+func NewMatcherWithJunk(a, b []string, autoJunk bool,
+ isJunk func(string) bool) *SequenceMatcher {
+
+ m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk}
+ m.SetSeqs(a, b)
+ return &m
+}
+
+// Set two sequences to be compared.
+func (m *SequenceMatcher) SetSeqs(a, b []string) {
+ m.SetSeq1(a)
+ m.SetSeq2(b)
+}
+
+// Set the first sequence to be compared. The second sequence to be compared is
+// not changed.
+//
+// SequenceMatcher computes and caches detailed information about the second
+// sequence, so if you want to compare one sequence S against many sequences,
+// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other
+// sequences.
+//
+// See also SetSeqs() and SetSeq2().
+func (m *SequenceMatcher) SetSeq1(a []string) {
+ if &a == &m.a {
+ return
+ }
+ m.a = a
+ m.matchingBlocks = nil
+ m.opCodes = nil
+}
+
+// Set the second sequence to be compared. The first sequence to be compared is
+// not changed.
+func (m *SequenceMatcher) SetSeq2(b []string) {
+ if &b == &m.b {
+ return
+ }
+ m.b = b
+ m.matchingBlocks = nil
+ m.opCodes = nil
+ m.fullBCount = nil
+ m.chainB()
+}
+
+func (m *SequenceMatcher) chainB() {
+ // Populate line -> index mapping
+ b2j := map[string][]int{}
+ for i, s := range m.b {
+ indices := b2j[s]
+ indices = append(indices, i)
+ b2j[s] = indices
+ }
+
+ // Purge junk elements
+ m.bJunk = map[string]struct{}{}
+ if m.IsJunk != nil {
+ junk := m.bJunk
+ for s, _ := range b2j {
+ if m.IsJunk(s) {
+ junk[s] = struct{}{}
+ }
+ }
+ for s, _ := range junk {
+ delete(b2j, s)
+ }
+ }
+
+ // Purge remaining popular elements
+ popular := map[string]struct{}{}
+ n := len(m.b)
+ if m.autoJunk && n >= 200 {
+ ntest := n/100 + 1
+ for s, indices := range b2j {
+ if len(indices) > ntest {
+ popular[s] = struct{}{}
+ }
+ }
+ for s, _ := range popular {
+ delete(b2j, s)
+ }
+ }
+ m.bPopular = popular
+ m.b2j = b2j
+}
+
+func (m *SequenceMatcher) isBJunk(s string) bool {
+ _, ok := m.bJunk[s]
+ return ok
+}
+
+// Find longest matching block in a[alo:ahi] and b[blo:bhi].
+//
+// If IsJunk is not defined:
+//
+// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where
+// alo <= i <= i+k <= ahi
+// blo <= j <= j+k <= bhi
+// and for all (i',j',k') meeting those conditions,
+// k >= k'
+// i <= i'
+// and if i == i', j <= j'
+//
+// In other words, of all maximal matching blocks, return one that
+// starts earliest in a, and of all those maximal matching blocks that
+// start earliest in a, return the one that starts earliest in b.
+//
+// If IsJunk is defined, first the longest matching block is
+// determined as above, but with the additional restriction that no
+// junk element appears in the block. Then that block is extended as
+// far as possible by matching (only) junk elements on both sides. So
+// the resulting block never matches on junk except as identical junk
+// happens to be adjacent to an "interesting" match.
+//
+// If no blocks match, return (alo, blo, 0).
+func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match {
+ // CAUTION: stripping common prefix or suffix would be incorrect.
+ // E.g.,
+ // ab
+ // acab
+ // Longest matching block is "ab", but if common prefix is
+ // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so
+ // strip, so ends up claiming that ab is changed to acab by
+ // inserting "ca" in the middle. That's minimal but unintuitive:
+ // "it's obvious" that someone inserted "ac" at the front.
+ // Windiff ends up at the same place as diff, but by pairing up
+ // the unique 'b's and then matching the first two 'a's.
+ besti, bestj, bestsize := alo, blo, 0
+
+ // find longest junk-free match
+ // during an iteration of the loop, j2len[j] = length of longest
+ // junk-free match ending with a[i-1] and b[j]
+ j2len := map[int]int{}
+ for i := alo; i != ahi; i++ {
+ // look at all instances of a[i] in b; note that because
+ // b2j has no junk keys, the loop is skipped if a[i] is junk
+ newj2len := map[int]int{}
+ for _, j := range m.b2j[m.a[i]] {
+ // a[i] matches b[j]
+ if j < blo {
+ continue
+ }
+ if j >= bhi {
+ break
+ }
+ k := j2len[j-1] + 1
+ newj2len[j] = k
+ if k > bestsize {
+ besti, bestj, bestsize = i-k+1, j-k+1, k
+ }
+ }
+ j2len = newj2len
+ }
+
+ // Extend the best by non-junk elements on each end. In particular,
+ // "popular" non-junk elements aren't in b2j, which greatly speeds
+ // the inner loop above, but also means "the best" match so far
+ // doesn't contain any junk *or* popular non-junk elements.
+ for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) &&
+ m.a[besti-1] == m.b[bestj-1] {
+ besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
+ }
+ for besti+bestsize < ahi && bestj+bestsize < bhi &&
+ !m.isBJunk(m.b[bestj+bestsize]) &&
+ m.a[besti+bestsize] == m.b[bestj+bestsize] {
+ bestsize += 1
+ }
+
+ // Now that we have a wholly interesting match (albeit possibly
+ // empty!), we may as well suck up the matching junk on each
+ // side of it too. Can't think of a good reason not to, and it
+ // saves post-processing the (possibly considerable) expense of
+ // figuring out what to do with it. In the case of an empty
+ // interesting match, this is clearly the right thing to do,
+ // because no other kind of match is possible in the regions.
+ for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) &&
+ m.a[besti-1] == m.b[bestj-1] {
+ besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
+ }
+ for besti+bestsize < ahi && bestj+bestsize < bhi &&
+ m.isBJunk(m.b[bestj+bestsize]) &&
+ m.a[besti+bestsize] == m.b[bestj+bestsize] {
+ bestsize += 1
+ }
+
+ return Match{A: besti, B: bestj, Size: bestsize}
+}
+
+// Return list of triples describing matching subsequences.
+//
+// Each triple is of the form (i, j, n), and means that
+// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in
+// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are
+// adjacent triples in the list, and the second is not the last triple in the
+// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe
+// adjacent equal blocks.
+//
+// The last triple is a dummy, (len(a), len(b), 0), and is the only
+// triple with n==0.
+func (m *SequenceMatcher) GetMatchingBlocks() []Match {
+ if m.matchingBlocks != nil {
+ return m.matchingBlocks
+ }
+
+ var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match
+ matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match {
+ match := m.findLongestMatch(alo, ahi, blo, bhi)
+ i, j, k := match.A, match.B, match.Size
+ if match.Size > 0 {
+ if alo < i && blo < j {
+ matched = matchBlocks(alo, i, blo, j, matched)
+ }
+ matched = append(matched, match)
+ if i+k < ahi && j+k < bhi {
+ matched = matchBlocks(i+k, ahi, j+k, bhi, matched)
+ }
+ }
+ return matched
+ }
+ matched := matchBlocks(0, len(m.a), 0, len(m.b), nil)
+
+ // It's possible that we have adjacent equal blocks in the
+ // matching_blocks list now.
+ nonAdjacent := []Match{}
+ i1, j1, k1 := 0, 0, 0
+ for _, b := range matched {
+ // Is this block adjacent to i1, j1, k1?
+ i2, j2, k2 := b.A, b.B, b.Size
+ if i1+k1 == i2 && j1+k1 == j2 {
+ // Yes, so collapse them -- this just increases the length of
+ // the first block by the length of the second, and the first
+ // block so lengthened remains the block to compare against.
+ k1 += k2
+ } else {
+ // Not adjacent. Remember the first block (k1==0 means it's
+ // the dummy we started with), and make the second block the
+ // new block to compare against.
+ if k1 > 0 {
+ nonAdjacent = append(nonAdjacent, Match{i1, j1, k1})
+ }
+ i1, j1, k1 = i2, j2, k2
+ }
+ }
+ if k1 > 0 {
+ nonAdjacent = append(nonAdjacent, Match{i1, j1, k1})
+ }
+
+ nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0})
+ m.matchingBlocks = nonAdjacent
+ return m.matchingBlocks
+}
+
+// Return list of 5-tuples describing how to turn a into b.
+//
+// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple
+// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the
+// tuple preceding it, and likewise for j1 == the previous j2.
+//
+// The tags are characters, with these meanings:
+//
+// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2]
+//
+// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case.
+//
+// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case.
+//
+// 'e' (equal): a[i1:i2] == b[j1:j2]
+func (m *SequenceMatcher) GetOpCodes() []OpCode {
+ if m.opCodes != nil {
+ return m.opCodes
+ }
+ i, j := 0, 0
+ matching := m.GetMatchingBlocks()
+ opCodes := make([]OpCode, 0, len(matching))
+ for _, m := range matching {
+ // invariant: we've pumped out correct diffs to change
+ // a[:i] into b[:j], and the next matching block is
+ // a[ai:ai+size] == b[bj:bj+size]. So we need to pump
+ // out a diff to change a[i:ai] into b[j:bj], pump out
+ // the matching block, and move (i,j) beyond the match
+ ai, bj, size := m.A, m.B, m.Size
+ tag := byte(0)
+ if i < ai && j < bj {
+ tag = 'r'
+ } else if i < ai {
+ tag = 'd'
+ } else if j < bj {
+ tag = 'i'
+ }
+ if tag > 0 {
+ opCodes = append(opCodes, OpCode{tag, i, ai, j, bj})
+ }
+ i, j = ai+size, bj+size
+ // the list of matching blocks is terminated by a
+ // sentinel with size 0
+ if size > 0 {
+ opCodes = append(opCodes, OpCode{'e', ai, i, bj, j})
+ }
+ }
+ m.opCodes = opCodes
+ return m.opCodes
+}
+
+// Isolate change clusters by eliminating ranges with no changes.
+//
+// Return a generator of groups with up to n lines of context.
+// Each group is in the same format as returned by GetOpCodes().
+func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
+ if n < 0 {
+ n = 3
+ }
+ codes := m.GetOpCodes()
+ if len(codes) == 0 {
+ codes = []OpCode{OpCode{'e', 0, 1, 0, 1}}
+ }
+ // Fixup leading and trailing groups if they show no changes.
+ if codes[0].Tag == 'e' {
+ c := codes[0]
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2}
+ }
+ if codes[len(codes)-1].Tag == 'e' {
+ c := codes[len(codes)-1]
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)}
+ }
+ nn := n + n
+ groups := [][]OpCode{}
+ group := []OpCode{}
+ for _, c := range codes {
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ // End the current group and start a new one whenever
+ // there is a large range with no changes.
+ if c.Tag == 'e' && i2-i1 > nn {
+ group = append(group, OpCode{c.Tag, i1, min(i2, i1+n),
+ j1, min(j2, j1+n)})
+ groups = append(groups, group)
+ group = []OpCode{}
+ i1, j1 = max(i1, i2-n), max(j1, j2-n)
+ }
+ group = append(group, OpCode{c.Tag, i1, i2, j1, j2})
+ }
+ if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') {
+ groups = append(groups, group)
+ }
+ return groups
+}
+
+// Return a measure of the sequences' similarity (float in [0,1]).
+//
+// Where T is the total number of elements in both sequences, and
+// M is the number of matches, this is 2.0*M / T.
+// Note that this is 1 if the sequences are identical, and 0 if
+// they have nothing in common.
+//
+// .Ratio() is expensive to compute if you haven't already computed
+// .GetMatchingBlocks() or .GetOpCodes(), in which case you may
+// want to try .QuickRatio() or .RealQuickRation() first to get an
+// upper bound.
+func (m *SequenceMatcher) Ratio() float64 {
+ matches := 0
+ for _, m := range m.GetMatchingBlocks() {
+ matches += m.Size
+ }
+ return calculateRatio(matches, len(m.a)+len(m.b))
+}
+
+// Return an upper bound on ratio() relatively quickly.
+//
+// This isn't defined beyond that it is an upper bound on .Ratio(), and
+// is faster to compute.
+func (m *SequenceMatcher) QuickRatio() float64 {
+ // viewing a and b as multisets, set matches to the cardinality
+ // of their intersection; this counts the number of matches
+ // without regard to order, so is clearly an upper bound
+ if m.fullBCount == nil {
+ m.fullBCount = map[string]int{}
+ for _, s := range m.b {
+ m.fullBCount[s] = m.fullBCount[s] + 1
+ }
+ }
+
+ // avail[x] is the number of times x appears in 'b' less the
+ // number of times we've seen it in 'a' so far ... kinda
+ avail := map[string]int{}
+ matches := 0
+ for _, s := range m.a {
+ n, ok := avail[s]
+ if !ok {
+ n = m.fullBCount[s]
+ }
+ avail[s] = n - 1
+ if n > 0 {
+ matches += 1
+ }
+ }
+ return calculateRatio(matches, len(m.a)+len(m.b))
+}
+
+// Return an upper bound on ratio() very quickly.
+//
+// This isn't defined beyond that it is an upper bound on .Ratio(), and
+// is faster to compute than either .Ratio() or .QuickRatio().
+func (m *SequenceMatcher) RealQuickRatio() float64 {
+ la, lb := len(m.a), len(m.b)
+ return calculateRatio(min(la, lb), la+lb)
+}
+
+// Convert range to the "ed" format
+func formatRangeUnified(start, stop int) string {
+ // Per the diff spec at http://www.unix.org/single_unix_specification/
+ beginning := start + 1 // lines start numbering with one
+ length := stop - start
+ if length == 1 {
+ return fmt.Sprintf("%d", beginning)
+ }
+ if length == 0 {
+ beginning -= 1 // empty ranges begin at line just before the range
+ }
+ return fmt.Sprintf("%d,%d", beginning, length)
+}
+
+// Unified diff parameters
+type UnifiedDiff struct {
+ A []string // First sequence lines
+ FromFile string // First file name
+ FromDate string // First file time
+ B []string // Second sequence lines
+ ToFile string // Second file name
+ ToDate string // Second file time
+ Eol string // Headers end of line, defaults to LF
+ Context int // Number of context lines
+}
+
+// Compare two sequences of lines; generate the delta as a unified diff.
+//
+// Unified diffs are a compact way of showing line changes and a few
+// lines of context. The number of context lines is set by 'n' which
+// defaults to three.
+//
+// By default, the diff control lines (those with ---, +++, or @@) are
+// created with a trailing newline. This is helpful so that inputs
+// created from file.readlines() result in diffs that are suitable for
+// file.writelines() since both the inputs and outputs have trailing
+// newlines.
+//
+// For inputs that do not have trailing newlines, set the lineterm
+// argument to "" so that the output will be uniformly newline free.
+//
+// The unidiff format normally has a header for filenames and modification
+// times. Any or all of these may be specified using strings for
+// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
+// The modification times are normally expressed in the ISO 8601 format.
+func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error {
+ buf := bufio.NewWriter(writer)
+ defer buf.Flush()
+ wf := func(format string, args ...interface{}) error {
+ _, err := buf.WriteString(fmt.Sprintf(format, args...))
+ return err
+ }
+ ws := func(s string) error {
+ _, err := buf.WriteString(s)
+ return err
+ }
+
+ if len(diff.Eol) == 0 {
+ diff.Eol = "\n"
+ }
+
+ started := false
+ m := NewMatcher(diff.A, diff.B)
+ for _, g := range m.GetGroupedOpCodes(diff.Context) {
+ if !started {
+ started = true
+ fromDate := ""
+ if len(diff.FromDate) > 0 {
+ fromDate = "\t" + diff.FromDate
+ }
+ toDate := ""
+ if len(diff.ToDate) > 0 {
+ toDate = "\t" + diff.ToDate
+ }
+ if diff.FromFile != "" || diff.ToFile != "" {
+ err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol)
+ if err != nil {
+ return err
+ }
+ err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ first, last := g[0], g[len(g)-1]
+ range1 := formatRangeUnified(first.I1, last.I2)
+ range2 := formatRangeUnified(first.J1, last.J2)
+ if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil {
+ return err
+ }
+ for _, c := range g {
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ if c.Tag == 'e' {
+ for _, line := range diff.A[i1:i2] {
+ if err := ws(" " + line); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ if c.Tag == 'r' || c.Tag == 'd' {
+ for _, line := range diff.A[i1:i2] {
+ if err := ws("-" + line); err != nil {
+ return err
+ }
+ }
+ }
+ if c.Tag == 'r' || c.Tag == 'i' {
+ for _, line := range diff.B[j1:j2] {
+ if err := ws("+" + line); err != nil {
+ return err
+ }
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// Like WriteUnifiedDiff but returns the diff a string.
+func GetUnifiedDiffString(diff UnifiedDiff) (string, error) {
+ w := &bytes.Buffer{}
+ err := WriteUnifiedDiff(w, diff)
+ return string(w.Bytes()), err
+}
+
+// Convert range to the "ed" format.
+func formatRangeContext(start, stop int) string {
+ // Per the diff spec at http://www.unix.org/single_unix_specification/
+ beginning := start + 1 // lines start numbering with one
+ length := stop - start
+ if length == 0 {
+ beginning -= 1 // empty ranges begin at line just before the range
+ }
+ if length <= 1 {
+ return fmt.Sprintf("%d", beginning)
+ }
+ return fmt.Sprintf("%d,%d", beginning, beginning+length-1)
+}
+
+type ContextDiff UnifiedDiff
+
+// Compare two sequences of lines; generate the delta as a context diff.
+//
+// Context diffs are a compact way of showing line changes and a few
+// lines of context. The number of context lines is set by diff.Context
+// which defaults to three.
+//
+// By default, the diff control lines (those with *** or ---) are
+// created with a trailing newline.
+//
+// For inputs that do not have trailing newlines, set the diff.Eol
+// argument to "" so that the output will be uniformly newline free.
+//
+// The context diff format normally has a header for filenames and
+// modification times. Any or all of these may be specified using
+// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate.
+// The modification times are normally expressed in the ISO 8601 format.
+// If not specified, the strings default to blanks.
+func WriteContextDiff(writer io.Writer, diff ContextDiff) error {
+ buf := bufio.NewWriter(writer)
+ defer buf.Flush()
+ var diffErr error
+ wf := func(format string, args ...interface{}) {
+ _, err := buf.WriteString(fmt.Sprintf(format, args...))
+ if diffErr == nil && err != nil {
+ diffErr = err
+ }
+ }
+ ws := func(s string) {
+ _, err := buf.WriteString(s)
+ if diffErr == nil && err != nil {
+ diffErr = err
+ }
+ }
+
+ if len(diff.Eol) == 0 {
+ diff.Eol = "\n"
+ }
+
+ prefix := map[byte]string{
+ 'i': "+ ",
+ 'd': "- ",
+ 'r': "! ",
+ 'e': " ",
+ }
+
+ started := false
+ m := NewMatcher(diff.A, diff.B)
+ for _, g := range m.GetGroupedOpCodes(diff.Context) {
+ if !started {
+ started = true
+ fromDate := ""
+ if len(diff.FromDate) > 0 {
+ fromDate = "\t" + diff.FromDate
+ }
+ toDate := ""
+ if len(diff.ToDate) > 0 {
+ toDate = "\t" + diff.ToDate
+ }
+ if diff.FromFile != "" || diff.ToFile != "" {
+ wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol)
+ wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol)
+ }
+ }
+
+ first, last := g[0], g[len(g)-1]
+ ws("***************" + diff.Eol)
+
+ range1 := formatRangeContext(first.I1, last.I2)
+ wf("*** %s ****%s", range1, diff.Eol)
+ for _, c := range g {
+ if c.Tag == 'r' || c.Tag == 'd' {
+ for _, cc := range g {
+ if cc.Tag == 'i' {
+ continue
+ }
+ for _, line := range diff.A[cc.I1:cc.I2] {
+ ws(prefix[cc.Tag] + line)
+ }
+ }
+ break
+ }
+ }
+
+ range2 := formatRangeContext(first.J1, last.J2)
+ wf("--- %s ----%s", range2, diff.Eol)
+ for _, c := range g {
+ if c.Tag == 'r' || c.Tag == 'i' {
+ for _, cc := range g {
+ if cc.Tag == 'd' {
+ continue
+ }
+ for _, line := range diff.B[cc.J1:cc.J2] {
+ ws(prefix[cc.Tag] + line)
+ }
+ }
+ break
+ }
+ }
+ }
+ return diffErr
+}
+
+// Like WriteContextDiff but returns the diff a string.
+func GetContextDiffString(diff ContextDiff) (string, error) {
+ w := &bytes.Buffer{}
+ err := WriteContextDiff(w, diff)
+ return string(w.Bytes()), err
+}
+
+// Split a string on "\n" while preserving them. The output can be used
+// as input for UnifiedDiff and ContextDiff structures.
+func SplitLines(s string) []string {
+ lines := strings.SplitAfter(s, "\n")
+ lines[len(lines)-1] += "\n"
+ return lines
+}
diff --git a/vendor/github.com/stretchr/testify/LICENSE b/vendor/github.com/stretchr/testify/LICENSE
new file mode 100644
index 0000000..4b0421c
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go
new file mode 100644
index 0000000..95d8e59
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go
@@ -0,0 +1,458 @@
+package assert
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "time"
+)
+
+type CompareType int
+
+const (
+ compareLess CompareType = iota - 1
+ compareEqual
+ compareGreater
+)
+
+var (
+ intType = reflect.TypeOf(int(1))
+ int8Type = reflect.TypeOf(int8(1))
+ int16Type = reflect.TypeOf(int16(1))
+ int32Type = reflect.TypeOf(int32(1))
+ int64Type = reflect.TypeOf(int64(1))
+
+ uintType = reflect.TypeOf(uint(1))
+ uint8Type = reflect.TypeOf(uint8(1))
+ uint16Type = reflect.TypeOf(uint16(1))
+ uint32Type = reflect.TypeOf(uint32(1))
+ uint64Type = reflect.TypeOf(uint64(1))
+
+ float32Type = reflect.TypeOf(float32(1))
+ float64Type = reflect.TypeOf(float64(1))
+
+ stringType = reflect.TypeOf("")
+
+ timeType = reflect.TypeOf(time.Time{})
+ bytesType = reflect.TypeOf([]byte{})
+)
+
+func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
+ obj1Value := reflect.ValueOf(obj1)
+ obj2Value := reflect.ValueOf(obj2)
+
+ // throughout this switch we try and avoid calling .Convert() if possible,
+ // as this has a pretty big performance impact
+ switch kind {
+ case reflect.Int:
+ {
+ intobj1, ok := obj1.(int)
+ if !ok {
+ intobj1 = obj1Value.Convert(intType).Interface().(int)
+ }
+ intobj2, ok := obj2.(int)
+ if !ok {
+ intobj2 = obj2Value.Convert(intType).Interface().(int)
+ }
+ if intobj1 > intobj2 {
+ return compareGreater, true
+ }
+ if intobj1 == intobj2 {
+ return compareEqual, true
+ }
+ if intobj1 < intobj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Int8:
+ {
+ int8obj1, ok := obj1.(int8)
+ if !ok {
+ int8obj1 = obj1Value.Convert(int8Type).Interface().(int8)
+ }
+ int8obj2, ok := obj2.(int8)
+ if !ok {
+ int8obj2 = obj2Value.Convert(int8Type).Interface().(int8)
+ }
+ if int8obj1 > int8obj2 {
+ return compareGreater, true
+ }
+ if int8obj1 == int8obj2 {
+ return compareEqual, true
+ }
+ if int8obj1 < int8obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Int16:
+ {
+ int16obj1, ok := obj1.(int16)
+ if !ok {
+ int16obj1 = obj1Value.Convert(int16Type).Interface().(int16)
+ }
+ int16obj2, ok := obj2.(int16)
+ if !ok {
+ int16obj2 = obj2Value.Convert(int16Type).Interface().(int16)
+ }
+ if int16obj1 > int16obj2 {
+ return compareGreater, true
+ }
+ if int16obj1 == int16obj2 {
+ return compareEqual, true
+ }
+ if int16obj1 < int16obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Int32:
+ {
+ int32obj1, ok := obj1.(int32)
+ if !ok {
+ int32obj1 = obj1Value.Convert(int32Type).Interface().(int32)
+ }
+ int32obj2, ok := obj2.(int32)
+ if !ok {
+ int32obj2 = obj2Value.Convert(int32Type).Interface().(int32)
+ }
+ if int32obj1 > int32obj2 {
+ return compareGreater, true
+ }
+ if int32obj1 == int32obj2 {
+ return compareEqual, true
+ }
+ if int32obj1 < int32obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Int64:
+ {
+ int64obj1, ok := obj1.(int64)
+ if !ok {
+ int64obj1 = obj1Value.Convert(int64Type).Interface().(int64)
+ }
+ int64obj2, ok := obj2.(int64)
+ if !ok {
+ int64obj2 = obj2Value.Convert(int64Type).Interface().(int64)
+ }
+ if int64obj1 > int64obj2 {
+ return compareGreater, true
+ }
+ if int64obj1 == int64obj2 {
+ return compareEqual, true
+ }
+ if int64obj1 < int64obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Uint:
+ {
+ uintobj1, ok := obj1.(uint)
+ if !ok {
+ uintobj1 = obj1Value.Convert(uintType).Interface().(uint)
+ }
+ uintobj2, ok := obj2.(uint)
+ if !ok {
+ uintobj2 = obj2Value.Convert(uintType).Interface().(uint)
+ }
+ if uintobj1 > uintobj2 {
+ return compareGreater, true
+ }
+ if uintobj1 == uintobj2 {
+ return compareEqual, true
+ }
+ if uintobj1 < uintobj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Uint8:
+ {
+ uint8obj1, ok := obj1.(uint8)
+ if !ok {
+ uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8)
+ }
+ uint8obj2, ok := obj2.(uint8)
+ if !ok {
+ uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8)
+ }
+ if uint8obj1 > uint8obj2 {
+ return compareGreater, true
+ }
+ if uint8obj1 == uint8obj2 {
+ return compareEqual, true
+ }
+ if uint8obj1 < uint8obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Uint16:
+ {
+ uint16obj1, ok := obj1.(uint16)
+ if !ok {
+ uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16)
+ }
+ uint16obj2, ok := obj2.(uint16)
+ if !ok {
+ uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16)
+ }
+ if uint16obj1 > uint16obj2 {
+ return compareGreater, true
+ }
+ if uint16obj1 == uint16obj2 {
+ return compareEqual, true
+ }
+ if uint16obj1 < uint16obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Uint32:
+ {
+ uint32obj1, ok := obj1.(uint32)
+ if !ok {
+ uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32)
+ }
+ uint32obj2, ok := obj2.(uint32)
+ if !ok {
+ uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32)
+ }
+ if uint32obj1 > uint32obj2 {
+ return compareGreater, true
+ }
+ if uint32obj1 == uint32obj2 {
+ return compareEqual, true
+ }
+ if uint32obj1 < uint32obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Uint64:
+ {
+ uint64obj1, ok := obj1.(uint64)
+ if !ok {
+ uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64)
+ }
+ uint64obj2, ok := obj2.(uint64)
+ if !ok {
+ uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64)
+ }
+ if uint64obj1 > uint64obj2 {
+ return compareGreater, true
+ }
+ if uint64obj1 == uint64obj2 {
+ return compareEqual, true
+ }
+ if uint64obj1 < uint64obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Float32:
+ {
+ float32obj1, ok := obj1.(float32)
+ if !ok {
+ float32obj1 = obj1Value.Convert(float32Type).Interface().(float32)
+ }
+ float32obj2, ok := obj2.(float32)
+ if !ok {
+ float32obj2 = obj2Value.Convert(float32Type).Interface().(float32)
+ }
+ if float32obj1 > float32obj2 {
+ return compareGreater, true
+ }
+ if float32obj1 == float32obj2 {
+ return compareEqual, true
+ }
+ if float32obj1 < float32obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Float64:
+ {
+ float64obj1, ok := obj1.(float64)
+ if !ok {
+ float64obj1 = obj1Value.Convert(float64Type).Interface().(float64)
+ }
+ float64obj2, ok := obj2.(float64)
+ if !ok {
+ float64obj2 = obj2Value.Convert(float64Type).Interface().(float64)
+ }
+ if float64obj1 > float64obj2 {
+ return compareGreater, true
+ }
+ if float64obj1 == float64obj2 {
+ return compareEqual, true
+ }
+ if float64obj1 < float64obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.String:
+ {
+ stringobj1, ok := obj1.(string)
+ if !ok {
+ stringobj1 = obj1Value.Convert(stringType).Interface().(string)
+ }
+ stringobj2, ok := obj2.(string)
+ if !ok {
+ stringobj2 = obj2Value.Convert(stringType).Interface().(string)
+ }
+ if stringobj1 > stringobj2 {
+ return compareGreater, true
+ }
+ if stringobj1 == stringobj2 {
+ return compareEqual, true
+ }
+ if stringobj1 < stringobj2 {
+ return compareLess, true
+ }
+ }
+ // Check for known struct types we can check for compare results.
+ case reflect.Struct:
+ {
+ // All structs enter here. We're not interested in most types.
+ if !canConvert(obj1Value, timeType) {
+ break
+ }
+
+ // time.Time can compared!
+ timeObj1, ok := obj1.(time.Time)
+ if !ok {
+ timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time)
+ }
+
+ timeObj2, ok := obj2.(time.Time)
+ if !ok {
+ timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time)
+ }
+
+ return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64)
+ }
+ case reflect.Slice:
+ {
+ // We only care about the []byte type.
+ if !canConvert(obj1Value, bytesType) {
+ break
+ }
+
+ // []byte can be compared!
+ bytesObj1, ok := obj1.([]byte)
+ if !ok {
+ bytesObj1 = obj1Value.Convert(bytesType).Interface().([]byte)
+
+ }
+ bytesObj2, ok := obj2.([]byte)
+ if !ok {
+ bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte)
+ }
+
+ return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true
+ }
+ }
+
+ return compareEqual, false
+}
+
+// Greater asserts that the first element is greater than the second
+//
+// assert.Greater(t, 2, 1)
+// assert.Greater(t, float64(2), float64(1))
+// assert.Greater(t, "b", "a")
+func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
+}
+
+// GreaterOrEqual asserts that the first element is greater than or equal to the second
+//
+// assert.GreaterOrEqual(t, 2, 1)
+// assert.GreaterOrEqual(t, 2, 2)
+// assert.GreaterOrEqual(t, "b", "a")
+// assert.GreaterOrEqual(t, "b", "b")
+func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
+}
+
+// Less asserts that the first element is less than the second
+//
+// assert.Less(t, 1, 2)
+// assert.Less(t, float64(1), float64(2))
+// assert.Less(t, "a", "b")
+func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
+}
+
+// LessOrEqual asserts that the first element is less than or equal to the second
+//
+// assert.LessOrEqual(t, 1, 2)
+// assert.LessOrEqual(t, 2, 2)
+// assert.LessOrEqual(t, "a", "b")
+// assert.LessOrEqual(t, "b", "b")
+func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
+}
+
+// Positive asserts that the specified element is positive
+//
+// assert.Positive(t, 1)
+// assert.Positive(t, 1.23)
+func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ zero := reflect.Zero(reflect.TypeOf(e))
+ return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs...)
+}
+
+// Negative asserts that the specified element is negative
+//
+// assert.Negative(t, -1)
+// assert.Negative(t, -1.23)
+func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ zero := reflect.Zero(reflect.TypeOf(e))
+ return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs...)
+}
+
+func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ e1Kind := reflect.ValueOf(e1).Kind()
+ e2Kind := reflect.ValueOf(e2).Kind()
+ if e1Kind != e2Kind {
+ return Fail(t, "Elements should be the same type", msgAndArgs...)
+ }
+
+ compareResult, isComparable := compare(e1, e2, e1Kind)
+ if !isComparable {
+ return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
+ }
+
+ if !containsValue(allowedComparesResults, compareResult) {
+ return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...)
+ }
+
+ return true
+}
+
+func containsValue(values []CompareType, value CompareType) bool {
+ for _, v := range values {
+ if v == value {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go
new file mode 100644
index 0000000..da86790
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go
@@ -0,0 +1,16 @@
+//go:build go1.17
+// +build go1.17
+
+// TODO: once support for Go 1.16 is dropped, this file can be
+// merged/removed with assertion_compare_go1.17_test.go and
+// assertion_compare_legacy.go
+
+package assert
+
+import "reflect"
+
+// Wrapper around reflect.Value.CanConvert, for compatibility
+// reasons.
+func canConvert(value reflect.Value, to reflect.Type) bool {
+ return value.CanConvert(to)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go
new file mode 100644
index 0000000..1701af2
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go
@@ -0,0 +1,16 @@
+//go:build !go1.17
+// +build !go1.17
+
+// TODO: once support for Go 1.16 is dropped, this file can be
+// merged/removed with assertion_compare_go1.17_test.go and
+// assertion_compare_can_convert.go
+
+package assert
+
+import "reflect"
+
+// Older versions of Go does not have the reflect.Value.CanConvert
+// method.
+func canConvert(value reflect.Value, to reflect.Type) bool {
+ return false
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go
new file mode 100644
index 0000000..7880b8f
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go
@@ -0,0 +1,763 @@
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+ */
+
+package assert
+
+import (
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+// Conditionf uses a Comparison to assert a complex condition.
+func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Condition(t, comp, append([]interface{}{msg}, args...)...)
+}
+
+// Containsf asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted")
+// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
+// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
+func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Contains(t, s, contains, append([]interface{}{msg}, args...)...)
+}
+
+// DirExistsf checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
+func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return DirExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
+// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
+func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...)
+}
+
+// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// assert.Emptyf(t, obj, "error message %s", "formatted")
+func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Empty(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// Equalf asserts that two objects are equal.
+//
+// assert.Equalf(t, 123, 123, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Equal(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
+func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
+}
+
+// EqualValuesf asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
+func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Errorf asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Errorf(t, err, "error message %s", "formatted") {
+// assert.Equal(t, expectedErrorf, err)
+// }
+func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Error(t, err, append([]interface{}{msg}, args...)...)
+}
+
+// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...)
+}
+
+// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
+// and that the error contains the specified substring.
+//
+// actualObj, err := SomeFunction()
+// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted")
+func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorContains(t, theError, contains, append([]interface{}{msg}, args...)...)
+}
+
+// ErrorIsf asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
+}
+
+// Eventuallyf asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick.
+//
+// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
+}
+
+// Exactlyf asserts that two objects are equal in value and type.
+//
+// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted")
+func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Failf reports a failure through
+func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, failureMessage, append([]interface{}{msg}, args...)...)
+}
+
+// FailNowf fails test
+func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...)
+}
+
+// Falsef asserts that the specified value is false.
+//
+// assert.Falsef(t, myBool, "error message %s", "formatted")
+func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return False(t, value, append([]interface{}{msg}, args...)...)
+}
+
+// FileExistsf checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
+func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return FileExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
+// Greaterf asserts that the first element is greater than the second
+//
+// assert.Greaterf(t, 2, 1, "error message %s", "formatted")
+// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted")
+// assert.Greaterf(t, "b", "a", "error message %s", "formatted")
+func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Greater(t, e1, e2, append([]interface{}{msg}, args...)...)
+}
+
+// GreaterOrEqualf asserts that the first element is greater than or equal to the second
+//
+// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted")
+// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted")
+// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted")
+// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted")
+func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return GreaterOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPBodyContainsf asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPBodyNotContainsf asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPErrorf asserts that a specified handler returns an error status code.
+//
+// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPRedirectf asserts that a specified handler returns a redirect status code.
+//
+// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPStatusCodef asserts that a specified handler returns a specified status code.
+//
+// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPStatusCode(t, handler, method, url, values, statuscode, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPSuccessf asserts that a specified handler returns a success status code.
+//
+// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
+}
+
+// Implementsf asserts that an object is implemented by the specified interface.
+//
+// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
+func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaf asserts that the two numerals are within delta of each other.
+//
+// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
+func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaSlicef is the same as InDelta, except it compares two slices.
+func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InEpsilonf asserts that expected and actual have a relative error less than epsilon
+func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
+}
+
+// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
+func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
+}
+
+// IsDecreasingf asserts that the collection is decreasing
+//
+// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted")
+// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted")
+// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
+func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsDecreasing(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// IsIncreasingf asserts that the collection is increasing
+//
+// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted")
+// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted")
+// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
+func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsIncreasing(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// IsNonDecreasingf asserts that the collection is not decreasing
+//
+// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted")
+// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted")
+// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
+func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsNonDecreasing(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// IsNonIncreasingf asserts that the collection is not increasing
+//
+// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted")
+// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted")
+// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
+func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsNonIncreasing(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// IsTypef asserts that the specified objects are of the same type.
+func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...)
+}
+
+// JSONEqf asserts that two JSON strings are equivalent.
+//
+// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
+func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Lenf asserts that the specified object has specific length.
+// Lenf also fails if the object has a type that len() not accept.
+//
+// assert.Lenf(t, mySlice, 3, "error message %s", "formatted")
+func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Len(t, object, length, append([]interface{}{msg}, args...)...)
+}
+
+// Lessf asserts that the first element is less than the second
+//
+// assert.Lessf(t, 1, 2, "error message %s", "formatted")
+// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted")
+// assert.Lessf(t, "a", "b", "error message %s", "formatted")
+func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Less(t, e1, e2, append([]interface{}{msg}, args...)...)
+}
+
+// LessOrEqualf asserts that the first element is less than or equal to the second
+//
+// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted")
+// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted")
+// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted")
+// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted")
+func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...)
+}
+
+// Negativef asserts that the specified element is negative
+//
+// assert.Negativef(t, -1, "error message %s", "formatted")
+// assert.Negativef(t, -1.23, "error message %s", "formatted")
+func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Negative(t, e, append([]interface{}{msg}, args...)...)
+}
+
+// Neverf asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Never(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
+}
+
+// Nilf asserts that the specified object is nil.
+//
+// assert.Nilf(t, err, "error message %s", "formatted")
+func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Nil(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NoDirExistsf checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoDirExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
+// NoErrorf asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoErrorf(t, err, "error message %s", "formatted") {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoError(t, err, append([]interface{}{msg}, args...)...)
+}
+
+// NoFileExistsf checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoFileExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
+// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted")
+// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
+// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
+func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
+}
+
+// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if assert.NotEmptyf(t, obj, "error message %s", "formatted") {
+// assert.Equal(t, "two", obj[1])
+// }
+func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEmpty(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NotEqualf asserts that the specified values are NOT equal.
+//
+// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// NotEqualValuesf asserts that two objects are not equal even when converted to the same type
+//
+// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted")
+func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
+}
+
+// NotNilf asserts that the specified object is not nil.
+//
+// assert.NotNilf(t, err, "error message %s", "formatted")
+func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotNil(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
+func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotPanics(t, f, append([]interface{}{msg}, args...)...)
+}
+
+// NotRegexpf asserts that a specified regexp does not match a string.
+//
+// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
+// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
+func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...)
+}
+
+// NotSamef asserts that two pointers do not reference the same object.
+//
+// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// NotSubsetf asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
+func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...)
+}
+
+// NotZerof asserts that i is not the zero value for its type.
+func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotZero(t, i, append([]interface{}{msg}, args...)...)
+}
+
+// Panicsf asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
+func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Panics(t, f, append([]interface{}{msg}, args...)...)
+}
+
+// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithError(t, errString, f, append([]interface{}{msg}, args...)...)
+}
+
+// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...)
+}
+
+// Positivef asserts that the specified element is positive
+//
+// assert.Positivef(t, 1, "error message %s", "formatted")
+// assert.Positivef(t, 1.23, "error message %s", "formatted")
+func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Positive(t, e, append([]interface{}{msg}, args...)...)
+}
+
+// Regexpf asserts that a specified regexp matches a string.
+//
+// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
+// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
+func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Regexp(t, rx, str, append([]interface{}{msg}, args...)...)
+}
+
+// Samef asserts that two pointers reference the same object.
+//
+// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Same(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Subsetf asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
+func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Subset(t, list, subset, append([]interface{}{msg}, args...)...)
+}
+
+// Truef asserts that the specified value is true.
+//
+// assert.Truef(t, myBool, "error message %s", "formatted")
+func Truef(t TestingT, value bool, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return True(t, value, append([]interface{}{msg}, args...)...)
+}
+
+// WithinDurationf asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
+func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// WithinRangef asserts that a time is within a time range (inclusive).
+//
+// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
+func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinRange(t, actual, start, end, append([]interface{}{msg}, args...)...)
+}
+
+// YAMLEqf asserts that two YAML strings are equivalent.
+func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return YAMLEq(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Zerof asserts that i is the zero value for its type.
+func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Zero(t, i, append([]interface{}{msg}, args...)...)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
new file mode 100644
index 0000000..d2bb0b8
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
@@ -0,0 +1,5 @@
+{{.CommentFormat}}
+func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool {
+ if h, ok := t.(tHelper); ok { h.Helper() }
+ return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}})
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
new file mode 100644
index 0000000..339515b
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
@@ -0,0 +1,1514 @@
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+ */
+
+package assert
+
+import (
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+// Condition uses a Comparison to assert a complex condition.
+func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Condition(a.t, comp, msgAndArgs...)
+}
+
+// Conditionf uses a Comparison to assert a complex condition.
+func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Conditionf(a.t, comp, msg, args...)
+}
+
+// Contains asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// a.Contains("Hello World", "World")
+// a.Contains(["Hello", "World"], "World")
+// a.Contains({"Hello": "World"}, "Hello")
+func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Contains(a.t, s, contains, msgAndArgs...)
+}
+
+// Containsf asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// a.Containsf("Hello World", "World", "error message %s", "formatted")
+// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted")
+// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted")
+func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Containsf(a.t, s, contains, msg, args...)
+}
+
+// DirExists checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
+func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return DirExists(a.t, path, msgAndArgs...)
+}
+
+// DirExistsf checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
+func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return DirExistsf(a.t, path, msg, args...)
+}
+
+// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])
+func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ElementsMatch(a.t, listA, listB, msgAndArgs...)
+}
+
+// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
+func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ElementsMatchf(a.t, listA, listB, msg, args...)
+}
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// a.Empty(obj)
+func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Empty(a.t, object, msgAndArgs...)
+}
+
+// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// a.Emptyf(obj, "error message %s", "formatted")
+func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Emptyf(a.t, object, msg, args...)
+}
+
+// Equal asserts that two objects are equal.
+//
+// a.Equal(123, 123)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Equal(a.t, expected, actual, msgAndArgs...)
+}
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// a.EqualError(err, expectedErrorString)
+func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualError(a.t, theError, errString, msgAndArgs...)
+}
+
+// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted")
+func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualErrorf(a.t, theError, errString, msg, args...)
+}
+
+// EqualValues asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// a.EqualValues(uint32(123), int32(123))
+func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualValues(a.t, expected, actual, msgAndArgs...)
+}
+
+// EqualValuesf asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
+func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualValuesf(a.t, expected, actual, msg, args...)
+}
+
+// Equalf asserts that two objects are equal.
+//
+// a.Equalf(123, 123, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Equalf(a.t, expected, actual, msg, args...)
+}
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.Error(err) {
+// assert.Equal(t, expectedError, err)
+// }
+func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Error(a.t, err, msgAndArgs...)
+}
+
+// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorAs(a.t, err, target, msgAndArgs...)
+}
+
+// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorAsf(a.t, err, target, msg, args...)
+}
+
+// ErrorContains asserts that a function returned an error (i.e. not `nil`)
+// and that the error contains the specified substring.
+//
+// actualObj, err := SomeFunction()
+// a.ErrorContains(err, expectedErrorSubString)
+func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorContains(a.t, theError, contains, msgAndArgs...)
+}
+
+// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
+// and that the error contains the specified substring.
+//
+// actualObj, err := SomeFunction()
+// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted")
+func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorContainsf(a.t, theError, contains, msg, args...)
+}
+
+// ErrorIs asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorIs(a.t, err, target, msgAndArgs...)
+}
+
+// ErrorIsf asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorIsf(a.t, err, target, msg, args...)
+}
+
+// Errorf asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.Errorf(err, "error message %s", "formatted") {
+// assert.Equal(t, expectedErrorf, err)
+// }
+func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Errorf(a.t, err, msg, args...)
+}
+
+// Eventually asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick.
+//
+// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond)
+func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
+}
+
+// Eventuallyf asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick.
+//
+// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Eventuallyf(a.t, condition, waitFor, tick, msg, args...)
+}
+
+// Exactly asserts that two objects are equal in value and type.
+//
+// a.Exactly(int32(123), int64(123))
+func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Exactly(a.t, expected, actual, msgAndArgs...)
+}
+
+// Exactlyf asserts that two objects are equal in value and type.
+//
+// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted")
+func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Exactlyf(a.t, expected, actual, msg, args...)
+}
+
+// Fail reports a failure through
+func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(a.t, failureMessage, msgAndArgs...)
+}
+
+// FailNow fails test
+func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return FailNow(a.t, failureMessage, msgAndArgs...)
+}
+
+// FailNowf fails test
+func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return FailNowf(a.t, failureMessage, msg, args...)
+}
+
+// Failf reports a failure through
+func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Failf(a.t, failureMessage, msg, args...)
+}
+
+// False asserts that the specified value is false.
+//
+// a.False(myBool)
+func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return False(a.t, value, msgAndArgs...)
+}
+
+// Falsef asserts that the specified value is false.
+//
+// a.Falsef(myBool, "error message %s", "formatted")
+func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Falsef(a.t, value, msg, args...)
+}
+
+// FileExists checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
+func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return FileExists(a.t, path, msgAndArgs...)
+}
+
+// FileExistsf checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
+func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return FileExistsf(a.t, path, msg, args...)
+}
+
+// Greater asserts that the first element is greater than the second
+//
+// a.Greater(2, 1)
+// a.Greater(float64(2), float64(1))
+// a.Greater("b", "a")
+func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Greater(a.t, e1, e2, msgAndArgs...)
+}
+
+// GreaterOrEqual asserts that the first element is greater than or equal to the second
+//
+// a.GreaterOrEqual(2, 1)
+// a.GreaterOrEqual(2, 2)
+// a.GreaterOrEqual("b", "a")
+// a.GreaterOrEqual("b", "b")
+func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return GreaterOrEqual(a.t, e1, e2, msgAndArgs...)
+}
+
+// GreaterOrEqualf asserts that the first element is greater than or equal to the second
+//
+// a.GreaterOrEqualf(2, 1, "error message %s", "formatted")
+// a.GreaterOrEqualf(2, 2, "error message %s", "formatted")
+// a.GreaterOrEqualf("b", "a", "error message %s", "formatted")
+// a.GreaterOrEqualf("b", "b", "error message %s", "formatted")
+func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return GreaterOrEqualf(a.t, e1, e2, msg, args...)
+}
+
+// Greaterf asserts that the first element is greater than the second
+//
+// a.Greaterf(2, 1, "error message %s", "formatted")
+// a.Greaterf(float64(2), float64(1), "error message %s", "formatted")
+// a.Greaterf("b", "a", "error message %s", "formatted")
+func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Greaterf(a.t, e1, e2, msg, args...)
+}
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...)
+}
+
+// HTTPBodyContainsf asserts that a specified handler returns a
+// body that contains a string.
+//
+// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...)
+}
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...)
+}
+
+// HTTPBodyNotContainsf asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...)
+}
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPError(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPErrorf asserts that a specified handler returns an error status code.
+//
+// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPErrorf(a.t, handler, method, url, values, msg, args...)
+}
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPRedirectf asserts that a specified handler returns a redirect status code.
+//
+// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
+}
+
+// HTTPStatusCode asserts that a specified handler returns a specified status code.
+//
+// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...)
+}
+
+// HTTPStatusCodef asserts that a specified handler returns a specified status code.
+//
+// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...)
+}
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPSuccessf asserts that a specified handler returns a success status code.
+//
+// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPSuccessf(a.t, handler, method, url, values, msg, args...)
+}
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// a.Implements((*MyInterface)(nil), new(MyObject))
+func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Implements(a.t, interfaceObject, object, msgAndArgs...)
+}
+
+// Implementsf asserts that an object is implemented by the specified interface.
+//
+// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
+func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Implementsf(a.t, interfaceObject, object, msg, args...)
+}
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// a.InDelta(math.Pi, 22/7.0, 0.01)
+func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDelta(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...)
+}
+
+// InDeltaSlice is the same as InDelta, except it compares two slices.
+func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaSlicef is the same as InDelta, except it compares two slices.
+func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaSlicef(a.t, expected, actual, delta, msg, args...)
+}
+
+// InDeltaf asserts that the two numerals are within delta of each other.
+//
+// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
+func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaf(a.t, expected, actual, delta, msg, args...)
+}
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
+}
+
+// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
+func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...)
+}
+
+// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
+func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...)
+}
+
+// InEpsilonf asserts that expected and actual have a relative error less than epsilon
+func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
+}
+
+// IsDecreasing asserts that the collection is decreasing
+//
+// a.IsDecreasing([]int{2, 1, 0})
+// a.IsDecreasing([]float{2, 1})
+// a.IsDecreasing([]string{"b", "a"})
+func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsDecreasing(a.t, object, msgAndArgs...)
+}
+
+// IsDecreasingf asserts that the collection is decreasing
+//
+// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted")
+// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted")
+// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted")
+func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsDecreasingf(a.t, object, msg, args...)
+}
+
+// IsIncreasing asserts that the collection is increasing
+//
+// a.IsIncreasing([]int{1, 2, 3})
+// a.IsIncreasing([]float{1, 2})
+// a.IsIncreasing([]string{"a", "b"})
+func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsIncreasing(a.t, object, msgAndArgs...)
+}
+
+// IsIncreasingf asserts that the collection is increasing
+//
+// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted")
+// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted")
+// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted")
+func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsIncreasingf(a.t, object, msg, args...)
+}
+
+// IsNonDecreasing asserts that the collection is not decreasing
+//
+// a.IsNonDecreasing([]int{1, 1, 2})
+// a.IsNonDecreasing([]float{1, 2})
+// a.IsNonDecreasing([]string{"a", "b"})
+func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsNonDecreasing(a.t, object, msgAndArgs...)
+}
+
+// IsNonDecreasingf asserts that the collection is not decreasing
+//
+// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted")
+// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted")
+// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted")
+func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsNonDecreasingf(a.t, object, msg, args...)
+}
+
+// IsNonIncreasing asserts that the collection is not increasing
+//
+// a.IsNonIncreasing([]int{2, 1, 1})
+// a.IsNonIncreasing([]float{2, 1})
+// a.IsNonIncreasing([]string{"b", "a"})
+func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsNonIncreasing(a.t, object, msgAndArgs...)
+}
+
+// IsNonIncreasingf asserts that the collection is not increasing
+//
+// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted")
+// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted")
+// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted")
+func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsNonIncreasingf(a.t, object, msg, args...)
+}
+
+// IsType asserts that the specified objects are of the same type.
+func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsType(a.t, expectedType, object, msgAndArgs...)
+}
+
+// IsTypef asserts that the specified objects are of the same type.
+func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsTypef(a.t, expectedType, object, msg, args...)
+}
+
+// JSONEq asserts that two JSON strings are equivalent.
+//
+// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return JSONEq(a.t, expected, actual, msgAndArgs...)
+}
+
+// JSONEqf asserts that two JSON strings are equivalent.
+//
+// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
+func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return JSONEqf(a.t, expected, actual, msg, args...)
+}
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// a.Len(mySlice, 3)
+func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Len(a.t, object, length, msgAndArgs...)
+}
+
+// Lenf asserts that the specified object has specific length.
+// Lenf also fails if the object has a type that len() not accept.
+//
+// a.Lenf(mySlice, 3, "error message %s", "formatted")
+func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Lenf(a.t, object, length, msg, args...)
+}
+
+// Less asserts that the first element is less than the second
+//
+// a.Less(1, 2)
+// a.Less(float64(1), float64(2))
+// a.Less("a", "b")
+func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Less(a.t, e1, e2, msgAndArgs...)
+}
+
+// LessOrEqual asserts that the first element is less than or equal to the second
+//
+// a.LessOrEqual(1, 2)
+// a.LessOrEqual(2, 2)
+// a.LessOrEqual("a", "b")
+// a.LessOrEqual("b", "b")
+func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return LessOrEqual(a.t, e1, e2, msgAndArgs...)
+}
+
+// LessOrEqualf asserts that the first element is less than or equal to the second
+//
+// a.LessOrEqualf(1, 2, "error message %s", "formatted")
+// a.LessOrEqualf(2, 2, "error message %s", "formatted")
+// a.LessOrEqualf("a", "b", "error message %s", "formatted")
+// a.LessOrEqualf("b", "b", "error message %s", "formatted")
+func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return LessOrEqualf(a.t, e1, e2, msg, args...)
+}
+
+// Lessf asserts that the first element is less than the second
+//
+// a.Lessf(1, 2, "error message %s", "formatted")
+// a.Lessf(float64(1), float64(2), "error message %s", "formatted")
+// a.Lessf("a", "b", "error message %s", "formatted")
+func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Lessf(a.t, e1, e2, msg, args...)
+}
+
+// Negative asserts that the specified element is negative
+//
+// a.Negative(-1)
+// a.Negative(-1.23)
+func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Negative(a.t, e, msgAndArgs...)
+}
+
+// Negativef asserts that the specified element is negative
+//
+// a.Negativef(-1, "error message %s", "formatted")
+// a.Negativef(-1.23, "error message %s", "formatted")
+func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Negativef(a.t, e, msg, args...)
+}
+
+// Never asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond)
+func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Never(a.t, condition, waitFor, tick, msgAndArgs...)
+}
+
+// Neverf asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Neverf(a.t, condition, waitFor, tick, msg, args...)
+}
+
+// Nil asserts that the specified object is nil.
+//
+// a.Nil(err)
+func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Nil(a.t, object, msgAndArgs...)
+}
+
+// Nilf asserts that the specified object is nil.
+//
+// a.Nilf(err, "error message %s", "formatted")
+func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Nilf(a.t, object, msg, args...)
+}
+
+// NoDirExists checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoDirExists(a.t, path, msgAndArgs...)
+}
+
+// NoDirExistsf checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoDirExistsf(a.t, path, msg, args...)
+}
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.NoError(err) {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoError(a.t, err, msgAndArgs...)
+}
+
+// NoErrorf asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.NoErrorf(err, "error message %s", "formatted") {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoErrorf(a.t, err, msg, args...)
+}
+
+// NoFileExists checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoFileExists(a.t, path, msgAndArgs...)
+}
+
+// NoFileExistsf checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoFileExistsf(a.t, path, msg, args...)
+}
+
+// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// a.NotContains("Hello World", "Earth")
+// a.NotContains(["Hello", "World"], "Earth")
+// a.NotContains({"Hello": "World"}, "Earth")
+func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotContains(a.t, s, contains, msgAndArgs...)
+}
+
+// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted")
+// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted")
+// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted")
+func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotContainsf(a.t, s, contains, msg, args...)
+}
+
+// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if a.NotEmpty(obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEmpty(a.t, object, msgAndArgs...)
+}
+
+// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if a.NotEmptyf(obj, "error message %s", "formatted") {
+// assert.Equal(t, "two", obj[1])
+// }
+func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEmptyf(a.t, object, msg, args...)
+}
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// a.NotEqual(obj1, obj2)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqual(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotEqualValues asserts that two objects are not equal even when converted to the same type
+//
+// a.NotEqualValues(obj1, obj2)
+func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqualValues(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotEqualValuesf asserts that two objects are not equal even when converted to the same type
+//
+// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted")
+func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqualValuesf(a.t, expected, actual, msg, args...)
+}
+
+// NotEqualf asserts that the specified values are NOT equal.
+//
+// a.NotEqualf(obj1, obj2, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqualf(a.t, expected, actual, msg, args...)
+}
+
+// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotErrorIs(a.t, err, target, msgAndArgs...)
+}
+
+// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotErrorIsf(a.t, err, target, msg, args...)
+}
+
+// NotNil asserts that the specified object is not nil.
+//
+// a.NotNil(err)
+func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotNil(a.t, object, msgAndArgs...)
+}
+
+// NotNilf asserts that the specified object is not nil.
+//
+// a.NotNilf(err, "error message %s", "formatted")
+func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotNilf(a.t, object, msg, args...)
+}
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// a.NotPanics(func(){ RemainCalm() })
+func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotPanics(a.t, f, msgAndArgs...)
+}
+
+// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted")
+func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotPanicsf(a.t, f, msg, args...)
+}
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
+// a.NotRegexp("^start", "it's not starting")
+func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotRegexp(a.t, rx, str, msgAndArgs...)
+}
+
+// NotRegexpf asserts that a specified regexp does not match a string.
+//
+// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
+// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
+func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotRegexpf(a.t, rx, str, msg, args...)
+}
+
+// NotSame asserts that two pointers do not reference the same object.
+//
+// a.NotSame(ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSame(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotSamef asserts that two pointers do not reference the same object.
+//
+// a.NotSamef(ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSamef(a.t, expected, actual, msg, args...)
+}
+
+// NotSubset asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
+func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSubset(a.t, list, subset, msgAndArgs...)
+}
+
+// NotSubsetf asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
+func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSubsetf(a.t, list, subset, msg, args...)
+}
+
+// NotZero asserts that i is not the zero value for its type.
+func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotZero(a.t, i, msgAndArgs...)
+}
+
+// NotZerof asserts that i is not the zero value for its type.
+func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotZerof(a.t, i, msg, args...)
+}
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// a.Panics(func(){ GoCrazy() })
+func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Panics(a.t, f, msgAndArgs...)
+}
+
+// PanicsWithError asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// a.PanicsWithError("crazy error", func(){ GoCrazy() })
+func (a *Assertions) PanicsWithError(errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithError(a.t, errString, f, msgAndArgs...)
+}
+
+// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) PanicsWithErrorf(errString string, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithErrorf(a.t, errString, f, msg, args...)
+}
+
+// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// a.PanicsWithValue("crazy error", func(){ GoCrazy() })
+func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithValue(a.t, expected, f, msgAndArgs...)
+}
+
+// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithValuef(a.t, expected, f, msg, args...)
+}
+
+// Panicsf asserts that the code inside the specified PanicTestFunc panics.
+//
+// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Panicsf(a.t, f, msg, args...)
+}
+
+// Positive asserts that the specified element is positive
+//
+// a.Positive(1)
+// a.Positive(1.23)
+func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Positive(a.t, e, msgAndArgs...)
+}
+
+// Positivef asserts that the specified element is positive
+//
+// a.Positivef(1, "error message %s", "formatted")
+// a.Positivef(1.23, "error message %s", "formatted")
+func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Positivef(a.t, e, msg, args...)
+}
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// a.Regexp(regexp.MustCompile("start"), "it's starting")
+// a.Regexp("start...$", "it's not starting")
+func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Regexp(a.t, rx, str, msgAndArgs...)
+}
+
+// Regexpf asserts that a specified regexp matches a string.
+//
+// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
+// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
+func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Regexpf(a.t, rx, str, msg, args...)
+}
+
+// Same asserts that two pointers reference the same object.
+//
+// a.Same(ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Same(a.t, expected, actual, msgAndArgs...)
+}
+
+// Samef asserts that two pointers reference the same object.
+//
+// a.Samef(ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Samef(a.t, expected, actual, msg, args...)
+}
+
+// Subset asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
+func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Subset(a.t, list, subset, msgAndArgs...)
+}
+
+// Subsetf asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
+func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Subsetf(a.t, list, subset, msg, args...)
+}
+
+// True asserts that the specified value is true.
+//
+// a.True(myBool)
+func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return True(a.t, value, msgAndArgs...)
+}
+
+// Truef asserts that the specified value is true.
+//
+// a.Truef(myBool, "error message %s", "formatted")
+func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Truef(a.t, value, msg, args...)
+}
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// a.WithinDuration(time.Now(), time.Now(), 10*time.Second)
+func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// WithinDurationf asserts that the two times are within duration delta of each other.
+//
+// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
+func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinDurationf(a.t, expected, actual, delta, msg, args...)
+}
+
+// WithinRange asserts that a time is within a time range (inclusive).
+//
+// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
+func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinRange(a.t, actual, start, end, msgAndArgs...)
+}
+
+// WithinRangef asserts that a time is within a time range (inclusive).
+//
+// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
+func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinRangef(a.t, actual, start, end, msg, args...)
+}
+
+// YAMLEq asserts that two YAML strings are equivalent.
+func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return YAMLEq(a.t, expected, actual, msgAndArgs...)
+}
+
+// YAMLEqf asserts that two YAML strings are equivalent.
+func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return YAMLEqf(a.t, expected, actual, msg, args...)
+}
+
+// Zero asserts that i is the zero value for its type.
+func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Zero(a.t, i, msgAndArgs...)
+}
+
+// Zerof asserts that i is the zero value for its type.
+func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Zerof(a.t, i, msg, args...)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
new file mode 100644
index 0000000..188bb9e
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
@@ -0,0 +1,5 @@
+{{.CommentWithoutT "a"}}
+func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool {
+ if h, ok := a.t.(tHelper); ok { h.Helper() }
+ return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_order.go b/vendor/github.com/stretchr/testify/assert/assertion_order.go
new file mode 100644
index 0000000..7594487
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_order.go
@@ -0,0 +1,81 @@
+package assert
+
+import (
+ "fmt"
+ "reflect"
+)
+
+// isOrdered checks that collection contains orderable elements.
+func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
+ objKind := reflect.TypeOf(object).Kind()
+ if objKind != reflect.Slice && objKind != reflect.Array {
+ return false
+ }
+
+ objValue := reflect.ValueOf(object)
+ objLen := objValue.Len()
+
+ if objLen <= 1 {
+ return true
+ }
+
+ value := objValue.Index(0)
+ valueInterface := value.Interface()
+ firstValueKind := value.Kind()
+
+ for i := 1; i < objLen; i++ {
+ prevValue := value
+ prevValueInterface := valueInterface
+
+ value = objValue.Index(i)
+ valueInterface = value.Interface()
+
+ compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind)
+
+ if !isComparable {
+ return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...)
+ }
+
+ if !containsValue(allowedComparesResults, compareResult) {
+ return Fail(t, fmt.Sprintf(failMessage, prevValue, value), msgAndArgs...)
+ }
+ }
+
+ return true
+}
+
+// IsIncreasing asserts that the collection is increasing
+//
+// assert.IsIncreasing(t, []int{1, 2, 3})
+// assert.IsIncreasing(t, []float{1, 2})
+// assert.IsIncreasing(t, []string{"a", "b"})
+func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
+}
+
+// IsNonIncreasing asserts that the collection is not increasing
+//
+// assert.IsNonIncreasing(t, []int{2, 1, 1})
+// assert.IsNonIncreasing(t, []float{2, 1})
+// assert.IsNonIncreasing(t, []string{"b", "a"})
+func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
+}
+
+// IsDecreasing asserts that the collection is decreasing
+//
+// assert.IsDecreasing(t, []int{2, 1, 0})
+// assert.IsDecreasing(t, []float{2, 1})
+// assert.IsDecreasing(t, []string{"b", "a"})
+func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
+}
+
+// IsNonDecreasing asserts that the collection is not decreasing
+//
+// assert.IsNonDecreasing(t, []int{1, 1, 2})
+// assert.IsNonDecreasing(t, []float{1, 2})
+// assert.IsNonDecreasing(t, []string{"a", "b"})
+func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go
new file mode 100644
index 0000000..2924cf3
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertions.go
@@ -0,0 +1,1856 @@
+package assert
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math"
+ "os"
+ "reflect"
+ "regexp"
+ "runtime"
+ "runtime/debug"
+ "strings"
+ "time"
+ "unicode"
+ "unicode/utf8"
+
+ "github.com/davecgh/go-spew/spew"
+ "github.com/pmezard/go-difflib/difflib"
+ yaml "gopkg.in/yaml.v3"
+)
+
+//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl"
+
+// TestingT is an interface wrapper around *testing.T
+type TestingT interface {
+ Errorf(format string, args ...interface{})
+}
+
+// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
+// for table driven tests.
+type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool
+
+// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
+// for table driven tests.
+type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool
+
+// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
+// for table driven tests.
+type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool
+
+// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful
+// for table driven tests.
+type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool
+
+// Comparison is a custom function that returns true on success and false on failure
+type Comparison func() (success bool)
+
+/*
+ Helper functions
+*/
+
+// ObjectsAreEqual determines if two objects are considered equal.
+//
+// This function does no assertion of any kind.
+func ObjectsAreEqual(expected, actual interface{}) bool {
+ if expected == nil || actual == nil {
+ return expected == actual
+ }
+
+ exp, ok := expected.([]byte)
+ if !ok {
+ return reflect.DeepEqual(expected, actual)
+ }
+
+ act, ok := actual.([]byte)
+ if !ok {
+ return false
+ }
+ if exp == nil || act == nil {
+ return exp == nil && act == nil
+ }
+ return bytes.Equal(exp, act)
+}
+
+// ObjectsAreEqualValues gets whether two objects are equal, or if their
+// values are equal.
+func ObjectsAreEqualValues(expected, actual interface{}) bool {
+ if ObjectsAreEqual(expected, actual) {
+ return true
+ }
+
+ actualType := reflect.TypeOf(actual)
+ if actualType == nil {
+ return false
+ }
+ expectedValue := reflect.ValueOf(expected)
+ if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
+ // Attempt comparison after type conversion
+ return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
+ }
+
+ return false
+}
+
+/* CallerInfo is necessary because the assert functions use the testing object
+internally, causing it to print the file:line of the assert method, rather than where
+the problem actually occurred in calling code.*/
+
+// CallerInfo returns an array of strings containing the file and line number
+// of each stack frame leading from the current test to the assert call that
+// failed.
+func CallerInfo() []string {
+
+ var pc uintptr
+ var ok bool
+ var file string
+ var line int
+ var name string
+
+ callers := []string{}
+ for i := 0; ; i++ {
+ pc, file, line, ok = runtime.Caller(i)
+ if !ok {
+ // The breaks below failed to terminate the loop, and we ran off the
+ // end of the call stack.
+ break
+ }
+
+ // This is a huge edge case, but it will panic if this is the case, see #180
+ if file == "<autogenerated>" {
+ break
+ }
+
+ f := runtime.FuncForPC(pc)
+ if f == nil {
+ break
+ }
+ name = f.Name()
+
+ // testing.tRunner is the standard library function that calls
+ // tests. Subtests are called directly by tRunner, without going through
+ // the Test/Benchmark/Example function that contains the t.Run calls, so
+ // with subtests we should break when we hit tRunner, without adding it
+ // to the list of callers.
+ if name == "testing.tRunner" {
+ break
+ }
+
+ parts := strings.Split(file, "/")
+ if len(parts) > 1 {
+ filename := parts[len(parts)-1]
+ dir := parts[len(parts)-2]
+ if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" {
+ callers = append(callers, fmt.Sprintf("%s:%d", file, line))
+ }
+ }
+
+ // Drop the package
+ segments := strings.Split(name, ".")
+ name = segments[len(segments)-1]
+ if isTest(name, "Test") ||
+ isTest(name, "Benchmark") ||
+ isTest(name, "Example") {
+ break
+ }
+ }
+
+ return callers
+}
+
+// Stolen from the `go test` tool.
+// isTest tells whether name looks like a test (or benchmark, according to prefix).
+// It is a Test (say) if there is a character after Test that is not a lower-case letter.
+// We don't want TesticularCancer.
+func isTest(name, prefix string) bool {
+ if !strings.HasPrefix(name, prefix) {
+ return false
+ }
+ if len(name) == len(prefix) { // "Test" is ok
+ return true
+ }
+ r, _ := utf8.DecodeRuneInString(name[len(prefix):])
+ return !unicode.IsLower(r)
+}
+
+func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
+ if len(msgAndArgs) == 0 || msgAndArgs == nil {
+ return ""
+ }
+ if len(msgAndArgs) == 1 {
+ msg := msgAndArgs[0]
+ if msgAsStr, ok := msg.(string); ok {
+ return msgAsStr
+ }
+ return fmt.Sprintf("%+v", msg)
+ }
+ if len(msgAndArgs) > 1 {
+ return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
+ }
+ return ""
+}
+
+// Aligns the provided message so that all lines after the first line start at the same location as the first line.
+// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab).
+// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the
+// basis on which the alignment occurs).
+func indentMessageLines(message string, longestLabelLen int) string {
+ outBuf := new(bytes.Buffer)
+
+ for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ {
+ // no need to align first line because it starts at the correct location (after the label)
+ if i != 0 {
+ // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab
+ outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
+ }
+ outBuf.WriteString(scanner.Text())
+ }
+
+ return outBuf.String()
+}
+
+type failNower interface {
+ FailNow()
+}
+
+// FailNow fails test
+func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ Fail(t, failureMessage, msgAndArgs...)
+
+ // We cannot extend TestingT with FailNow() and
+ // maintain backwards compatibility, so we fallback
+ // to panicking when FailNow is not available in
+ // TestingT.
+ // See issue #263
+
+ if t, ok := t.(failNower); ok {
+ t.FailNow()
+ } else {
+ panic("test failed and t is missing `FailNow()`")
+ }
+ return false
+}
+
+// Fail reports a failure through
+func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ content := []labeledContent{
+ {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")},
+ {"Error", failureMessage},
+ }
+
+ // Add test name if the Go version supports it
+ if n, ok := t.(interface {
+ Name() string
+ }); ok {
+ content = append(content, labeledContent{"Test", n.Name()})
+ }
+
+ message := messageFromMsgAndArgs(msgAndArgs...)
+ if len(message) > 0 {
+ content = append(content, labeledContent{"Messages", message})
+ }
+
+ t.Errorf("\n%s", ""+labeledOutput(content...))
+
+ return false
+}
+
+type labeledContent struct {
+ label string
+ content string
+}
+
+// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner:
+//
+// \t{{label}}:{{align_spaces}}\t{{content}}\n
+//
+// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label.
+// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this
+// alignment is achieved, "\t{{content}}\n" is added for the output.
+//
+// If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line.
+func labeledOutput(content ...labeledContent) string {
+ longestLabel := 0
+ for _, v := range content {
+ if len(v.label) > longestLabel {
+ longestLabel = len(v.label)
+ }
+ }
+ var output string
+ for _, v := range content {
+ output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n"
+ }
+ return output
+}
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// assert.Implements(t, (*MyInterface)(nil), new(MyObject))
+func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ interfaceType := reflect.TypeOf(interfaceObject).Elem()
+
+ if object == nil {
+ return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...)
+ }
+ if !reflect.TypeOf(object).Implements(interfaceType) {
+ return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...)
+ }
+
+ return true
+}
+
+// IsType asserts that the specified objects are of the same type.
+func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
+ return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
+ }
+
+ return true
+}
+
+// Equal asserts that two objects are equal.
+//
+// assert.Equal(t, 123, 123)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if err := validateEqualArgs(expected, actual); err != nil {
+ return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)",
+ expected, actual, err), msgAndArgs...)
+ }
+
+ if !ObjectsAreEqual(expected, actual) {
+ diff := diff(expected, actual)
+ expected, actual = formatUnequalValues(expected, actual)
+ return Fail(t, fmt.Sprintf("Not equal: \n"+
+ "expected: %s\n"+
+ "actual : %s%s", expected, actual, diff), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// validateEqualArgs checks whether provided arguments can be safely used in the
+// Equal/NotEqual functions.
+func validateEqualArgs(expected, actual interface{}) error {
+ if expected == nil && actual == nil {
+ return nil
+ }
+
+ if isFunction(expected) || isFunction(actual) {
+ return errors.New("cannot take func type as argument")
+ }
+ return nil
+}
+
+// Same asserts that two pointers reference the same object.
+//
+// assert.Same(t, ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if !samePointers(expected, actual) {
+ return Fail(t, fmt.Sprintf("Not same: \n"+
+ "expected: %p %#v\n"+
+ "actual : %p %#v", expected, expected, actual, actual), msgAndArgs...)
+ }
+
+ return true
+}
+
+// NotSame asserts that two pointers do not reference the same object.
+//
+// assert.NotSame(t, ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if samePointers(expected, actual) {
+ return Fail(t, fmt.Sprintf(
+ "Expected and actual point to the same object: %p %#v",
+ expected, expected), msgAndArgs...)
+ }
+ return true
+}
+
+// samePointers compares two generic interface objects and returns whether
+// they point to the same object
+func samePointers(first, second interface{}) bool {
+ firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second)
+ if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr {
+ return false
+ }
+
+ firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second)
+ if firstType != secondType {
+ return false
+ }
+
+ // compare pointer addresses
+ return first == second
+}
+
+// formatUnequalValues takes two values of arbitrary types and returns string
+// representations appropriate to be presented to the user.
+//
+// If the values are not of like type, the returned strings will be prefixed
+// with the type name, and the value will be enclosed in parenthesis similar
+// to a type conversion in the Go grammar.
+func formatUnequalValues(expected, actual interface{}) (e string, a string) {
+ if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
+ return fmt.Sprintf("%T(%s)", expected, truncatingFormat(expected)),
+ fmt.Sprintf("%T(%s)", actual, truncatingFormat(actual))
+ }
+ switch expected.(type) {
+ case time.Duration:
+ return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual)
+ }
+ return truncatingFormat(expected), truncatingFormat(actual)
+}
+
+// truncatingFormat formats the data and truncates it if it's too long.
+//
+// This helps keep formatted error messages lines from exceeding the
+// bufio.MaxScanTokenSize max line length that the go testing framework imposes.
+func truncatingFormat(data interface{}) string {
+ value := fmt.Sprintf("%#v", data)
+ max := bufio.MaxScanTokenSize - 100 // Give us some space the type info too if needed.
+ if len(value) > max {
+ value = value[0:max] + "<... truncated>"
+ }
+ return value
+}
+
+// EqualValues asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// assert.EqualValues(t, uint32(123), int32(123))
+func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if !ObjectsAreEqualValues(expected, actual) {
+ diff := diff(expected, actual)
+ expected, actual = formatUnequalValues(expected, actual)
+ return Fail(t, fmt.Sprintf("Not equal: \n"+
+ "expected: %s\n"+
+ "actual : %s%s", expected, actual, diff), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// Exactly asserts that two objects are equal in value and type.
+//
+// assert.Exactly(t, int32(123), int64(123))
+func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ aType := reflect.TypeOf(expected)
+ bType := reflect.TypeOf(actual)
+
+ if aType != bType {
+ return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
+ }
+
+ return Equal(t, expected, actual, msgAndArgs...)
+
+}
+
+// NotNil asserts that the specified object is not nil.
+//
+// assert.NotNil(t, err)
+func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if !isNil(object) {
+ return true
+ }
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, "Expected value not to be nil.", msgAndArgs...)
+}
+
+// containsKind checks if a specified kind in the slice of kinds.
+func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool {
+ for i := 0; i < len(kinds); i++ {
+ if kind == kinds[i] {
+ return true
+ }
+ }
+
+ return false
+}
+
+// isNil checks if a specified object is nil or not, without Failing.
+func isNil(object interface{}) bool {
+ if object == nil {
+ return true
+ }
+
+ value := reflect.ValueOf(object)
+ kind := value.Kind()
+ isNilableKind := containsKind(
+ []reflect.Kind{
+ reflect.Chan, reflect.Func,
+ reflect.Interface, reflect.Map,
+ reflect.Ptr, reflect.Slice, reflect.UnsafePointer},
+ kind)
+
+ if isNilableKind && value.IsNil() {
+ return true
+ }
+
+ return false
+}
+
+// Nil asserts that the specified object is nil.
+//
+// assert.Nil(t, err)
+func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if isNil(object) {
+ return true
+ }
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
+}
+
+// isEmpty gets whether the specified object is considered empty or not.
+func isEmpty(object interface{}) bool {
+
+ // get nil case out of the way
+ if object == nil {
+ return true
+ }
+
+ objValue := reflect.ValueOf(object)
+
+ switch objValue.Kind() {
+ // collection types are empty when they have no element
+ case reflect.Chan, reflect.Map, reflect.Slice:
+ return objValue.Len() == 0
+ // pointers are empty if nil or if the value they point to is empty
+ case reflect.Ptr:
+ if objValue.IsNil() {
+ return true
+ }
+ deref := objValue.Elem().Interface()
+ return isEmpty(deref)
+ // for all other types, compare against the zero value
+ // array types are empty when they match their zero-initialized state
+ default:
+ zero := reflect.Zero(objValue.Type())
+ return reflect.DeepEqual(object, zero.Interface())
+ }
+}
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// assert.Empty(t, obj)
+func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ pass := isEmpty(object)
+ if !pass {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
+ }
+
+ return pass
+
+}
+
+// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if assert.NotEmpty(t, obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ pass := !isEmpty(object)
+ if !pass {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
+ }
+
+ return pass
+
+}
+
+// getLen try to get length of object.
+// return (false, 0) if impossible.
+func getLen(x interface{}) (ok bool, length int) {
+ v := reflect.ValueOf(x)
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ }
+ }()
+ return true, v.Len()
+}
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// assert.Len(t, mySlice, 3)
+func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ ok, l := getLen(object)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...)
+ }
+
+ if l != length {
+ return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
+ }
+ return true
+}
+
+// True asserts that the specified value is true.
+//
+// assert.True(t, myBool)
+func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
+ if !value {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, "Should be true", msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// False asserts that the specified value is false.
+//
+// assert.False(t, myBool)
+func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
+ if value {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, "Should be false", msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// assert.NotEqual(t, obj1, obj2)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if err := validateEqualArgs(expected, actual); err != nil {
+ return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)",
+ expected, actual, err), msgAndArgs...)
+ }
+
+ if ObjectsAreEqual(expected, actual) {
+ return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// NotEqualValues asserts that two objects are not equal even when converted to the same type
+//
+// assert.NotEqualValues(t, obj1, obj2)
+func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if ObjectsAreEqualValues(expected, actual) {
+ return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
+ }
+
+ return true
+}
+
+// containsElement try loop over the list check if the list includes the element.
+// return (false, false) if impossible.
+// return (true, false) if element was not found.
+// return (true, true) if element was found.
+func containsElement(list interface{}, element interface{}) (ok, found bool) {
+
+ listValue := reflect.ValueOf(list)
+ listType := reflect.TypeOf(list)
+ if listType == nil {
+ return false, false
+ }
+ listKind := listType.Kind()
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ found = false
+ }
+ }()
+
+ if listKind == reflect.String {
+ elementValue := reflect.ValueOf(element)
+ return true, strings.Contains(listValue.String(), elementValue.String())
+ }
+
+ if listKind == reflect.Map {
+ mapKeys := listValue.MapKeys()
+ for i := 0; i < len(mapKeys); i++ {
+ if ObjectsAreEqual(mapKeys[i].Interface(), element) {
+ return true, true
+ }
+ }
+ return true, false
+ }
+
+ for i := 0; i < listValue.Len(); i++ {
+ if ObjectsAreEqual(listValue.Index(i).Interface(), element) {
+ return true, true
+ }
+ }
+ return true, false
+
+}
+
+// Contains asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// assert.Contains(t, "Hello World", "World")
+// assert.Contains(t, ["Hello", "World"], "World")
+// assert.Contains(t, {"Hello": "World"}, "Hello")
+func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ ok, found := containsElement(s, contains)
+ if !ok {
+ return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
+ }
+ if !found {
+ return Fail(t, fmt.Sprintf("%#v does not contain %#v", s, contains), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// assert.NotContains(t, "Hello World", "Earth")
+// assert.NotContains(t, ["Hello", "World"], "Earth")
+// assert.NotContains(t, {"Hello": "World"}, "Earth")
+func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ ok, found := containsElement(s, contains)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
+ }
+ if found {
+ return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// Subset asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
+func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if subset == nil {
+ return true // we consider nil to be equal to the nil set
+ }
+
+ listKind := reflect.TypeOf(list).Kind()
+ if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
+ }
+
+ subsetKind := reflect.TypeOf(subset).Kind()
+ if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
+ }
+
+ if subsetKind == reflect.Map && listKind == reflect.Map {
+ subsetMap := reflect.ValueOf(subset)
+ actualMap := reflect.ValueOf(list)
+
+ for _, k := range subsetMap.MapKeys() {
+ ev := subsetMap.MapIndex(k)
+ av := actualMap.MapIndex(k)
+
+ if !av.IsValid() {
+ return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
+ }
+ if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
+ return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
+ }
+ }
+
+ return true
+ }
+
+ subsetList := reflect.ValueOf(subset)
+ for i := 0; i < subsetList.Len(); i++ {
+ element := subsetList.Index(i).Interface()
+ ok, found := containsElement(list, element)
+ if !ok {
+ return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...)
+ }
+ if !found {
+ return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...)
+ }
+ }
+
+ return true
+}
+
+// NotSubset asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
+func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if subset == nil {
+ return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...)
+ }
+
+ listKind := reflect.TypeOf(list).Kind()
+ if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
+ }
+
+ subsetKind := reflect.TypeOf(subset).Kind()
+ if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
+ }
+
+ if subsetKind == reflect.Map && listKind == reflect.Map {
+ subsetMap := reflect.ValueOf(subset)
+ actualMap := reflect.ValueOf(list)
+
+ for _, k := range subsetMap.MapKeys() {
+ ev := subsetMap.MapIndex(k)
+ av := actualMap.MapIndex(k)
+
+ if !av.IsValid() {
+ return true
+ }
+ if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
+ return true
+ }
+ }
+
+ return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
+ }
+
+ subsetList := reflect.ValueOf(subset)
+ for i := 0; i < subsetList.Len(); i++ {
+ element := subsetList.Index(i).Interface()
+ ok, found := containsElement(list, element)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
+ }
+ if !found {
+ return true
+ }
+ }
+
+ return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
+}
+
+// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])
+func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if isEmpty(listA) && isEmpty(listB) {
+ return true
+ }
+
+ if !isList(t, listA, msgAndArgs...) || !isList(t, listB, msgAndArgs...) {
+ return false
+ }
+
+ extraA, extraB := diffLists(listA, listB)
+
+ if len(extraA) == 0 && len(extraB) == 0 {
+ return true
+ }
+
+ return Fail(t, formatListDiff(listA, listB, extraA, extraB), msgAndArgs...)
+}
+
+// isList checks that the provided value is array or slice.
+func isList(t TestingT, list interface{}, msgAndArgs ...interface{}) (ok bool) {
+ kind := reflect.TypeOf(list).Kind()
+ if kind != reflect.Array && kind != reflect.Slice {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s, expecting array or slice", list, kind),
+ msgAndArgs...)
+ }
+ return true
+}
+
+// diffLists diffs two arrays/slices and returns slices of elements that are only in A and only in B.
+// If some element is present multiple times, each instance is counted separately (e.g. if something is 2x in A and
+// 5x in B, it will be 0x in extraA and 3x in extraB). The order of items in both lists is ignored.
+func diffLists(listA, listB interface{}) (extraA, extraB []interface{}) {
+ aValue := reflect.ValueOf(listA)
+ bValue := reflect.ValueOf(listB)
+
+ aLen := aValue.Len()
+ bLen := bValue.Len()
+
+ // Mark indexes in bValue that we already used
+ visited := make([]bool, bLen)
+ for i := 0; i < aLen; i++ {
+ element := aValue.Index(i).Interface()
+ found := false
+ for j := 0; j < bLen; j++ {
+ if visited[j] {
+ continue
+ }
+ if ObjectsAreEqual(bValue.Index(j).Interface(), element) {
+ visited[j] = true
+ found = true
+ break
+ }
+ }
+ if !found {
+ extraA = append(extraA, element)
+ }
+ }
+
+ for j := 0; j < bLen; j++ {
+ if visited[j] {
+ continue
+ }
+ extraB = append(extraB, bValue.Index(j).Interface())
+ }
+
+ return
+}
+
+func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) string {
+ var msg bytes.Buffer
+
+ msg.WriteString("elements differ")
+ if len(extraA) > 0 {
+ msg.WriteString("\n\nextra elements in list A:\n")
+ msg.WriteString(spewConfig.Sdump(extraA))
+ }
+ if len(extraB) > 0 {
+ msg.WriteString("\n\nextra elements in list B:\n")
+ msg.WriteString(spewConfig.Sdump(extraB))
+ }
+ msg.WriteString("\n\nlistA:\n")
+ msg.WriteString(spewConfig.Sdump(listA))
+ msg.WriteString("\n\nlistB:\n")
+ msg.WriteString(spewConfig.Sdump(listB))
+
+ return msg.String()
+}
+
+// Condition uses a Comparison to assert a complex condition.
+func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ result := comp()
+ if !result {
+ Fail(t, "Condition failed!", msgAndArgs...)
+ }
+ return result
+}
+
+// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
+// methods, and represents a simple func that takes no arguments, and returns nothing.
+type PanicTestFunc func()
+
+// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
+func didPanic(f PanicTestFunc) (didPanic bool, message interface{}, stack string) {
+ didPanic = true
+
+ defer func() {
+ message = recover()
+ if didPanic {
+ stack = string(debug.Stack())
+ }
+ }()
+
+ // call the target function
+ f()
+ didPanic = false
+
+ return
+}
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panics(t, func(){ GoCrazy() })
+func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if funcDidPanic, panicValue, _ := didPanic(f); !funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
+ }
+
+ return true
+}
+
+// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() })
+func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ funcDidPanic, panicValue, panickedStack := didPanic(f)
+ if !funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
+ }
+ if panicValue != expected {
+ return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, expected, panicValue, panickedStack), msgAndArgs...)
+ }
+
+ return true
+}
+
+// PanicsWithError asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() })
+func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ funcDidPanic, panicValue, panickedStack := didPanic(f)
+ if !funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
+ }
+ panicErr, ok := panicValue.(error)
+ if !ok || panicErr.Error() != errString {
+ return Fail(t, fmt.Sprintf("func %#v should panic with error message:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, errString, panicValue, panickedStack), msgAndArgs...)
+ }
+
+ return true
+}
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanics(t, func(){ RemainCalm() })
+func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if funcDidPanic, panicValue, panickedStack := didPanic(f); funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v\n\tPanic stack:\t%s", f, panicValue, panickedStack), msgAndArgs...)
+ }
+
+ return true
+}
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second)
+func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ dt := expected.Sub(actual)
+ if dt < -delta || dt > delta {
+ return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
+ }
+
+ return true
+}
+
+// WithinRange asserts that a time is within a time range (inclusive).
+//
+// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
+func WithinRange(t TestingT, actual, start, end time.Time, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if end.Before(start) {
+ return Fail(t, "Start should be before end", msgAndArgs...)
+ }
+
+ if actual.Before(start) {
+ return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is before the range", actual, start, end), msgAndArgs...)
+ } else if actual.After(end) {
+ return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is after the range", actual, start, end), msgAndArgs...)
+ }
+
+ return true
+}
+
+func toFloat(x interface{}) (float64, bool) {
+ var xf float64
+ xok := true
+
+ switch xn := x.(type) {
+ case uint:
+ xf = float64(xn)
+ case uint8:
+ xf = float64(xn)
+ case uint16:
+ xf = float64(xn)
+ case uint32:
+ xf = float64(xn)
+ case uint64:
+ xf = float64(xn)
+ case int:
+ xf = float64(xn)
+ case int8:
+ xf = float64(xn)
+ case int16:
+ xf = float64(xn)
+ case int32:
+ xf = float64(xn)
+ case int64:
+ xf = float64(xn)
+ case float32:
+ xf = float64(xn)
+ case float64:
+ xf = xn
+ case time.Duration:
+ xf = float64(xn)
+ default:
+ xok = false
+ }
+
+ return xf, xok
+}
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// assert.InDelta(t, math.Pi, 22/7.0, 0.01)
+func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ af, aok := toFloat(expected)
+ bf, bok := toFloat(actual)
+
+ if !aok || !bok {
+ return Fail(t, "Parameters must be numerical", msgAndArgs...)
+ }
+
+ if math.IsNaN(af) && math.IsNaN(bf) {
+ return true
+ }
+
+ if math.IsNaN(af) {
+ return Fail(t, "Expected must not be NaN", msgAndArgs...)
+ }
+
+ if math.IsNaN(bf) {
+ return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...)
+ }
+
+ dt := af - bf
+ if dt < -delta || dt > delta {
+ return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
+ }
+
+ return true
+}
+
+// InDeltaSlice is the same as InDelta, except it compares two slices.
+func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if expected == nil || actual == nil ||
+ reflect.TypeOf(actual).Kind() != reflect.Slice ||
+ reflect.TypeOf(expected).Kind() != reflect.Slice {
+ return Fail(t, "Parameters must be slice", msgAndArgs...)
+ }
+
+ actualSlice := reflect.ValueOf(actual)
+ expectedSlice := reflect.ValueOf(expected)
+
+ for i := 0; i < actualSlice.Len(); i++ {
+ result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...)
+ if !result {
+ return result
+ }
+ }
+
+ return true
+}
+
+// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if expected == nil || actual == nil ||
+ reflect.TypeOf(actual).Kind() != reflect.Map ||
+ reflect.TypeOf(expected).Kind() != reflect.Map {
+ return Fail(t, "Arguments must be maps", msgAndArgs...)
+ }
+
+ expectedMap := reflect.ValueOf(expected)
+ actualMap := reflect.ValueOf(actual)
+
+ if expectedMap.Len() != actualMap.Len() {
+ return Fail(t, "Arguments must have the same number of keys", msgAndArgs...)
+ }
+
+ for _, k := range expectedMap.MapKeys() {
+ ev := expectedMap.MapIndex(k)
+ av := actualMap.MapIndex(k)
+
+ if !ev.IsValid() {
+ return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...)
+ }
+
+ if !av.IsValid() {
+ return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...)
+ }
+
+ if !InDelta(
+ t,
+ ev.Interface(),
+ av.Interface(),
+ delta,
+ msgAndArgs...,
+ ) {
+ return false
+ }
+ }
+
+ return true
+}
+
+func calcRelativeError(expected, actual interface{}) (float64, error) {
+ af, aok := toFloat(expected)
+ bf, bok := toFloat(actual)
+ if !aok || !bok {
+ return 0, fmt.Errorf("Parameters must be numerical")
+ }
+ if math.IsNaN(af) && math.IsNaN(bf) {
+ return 0, nil
+ }
+ if math.IsNaN(af) {
+ return 0, errors.New("expected value must not be NaN")
+ }
+ if af == 0 {
+ return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error")
+ }
+ if math.IsNaN(bf) {
+ return 0, errors.New("actual value must not be NaN")
+ }
+
+ return math.Abs(af-bf) / math.Abs(af), nil
+}
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if math.IsNaN(epsilon) {
+ return Fail(t, "epsilon must not be NaN")
+ }
+ actualEpsilon, err := calcRelativeError(expected, actual)
+ if err != nil {
+ return Fail(t, err.Error(), msgAndArgs...)
+ }
+ if actualEpsilon > epsilon {
+ return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
+ " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...)
+ }
+
+ return true
+}
+
+// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
+func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if expected == nil || actual == nil ||
+ reflect.TypeOf(actual).Kind() != reflect.Slice ||
+ reflect.TypeOf(expected).Kind() != reflect.Slice {
+ return Fail(t, "Parameters must be slice", msgAndArgs...)
+ }
+
+ actualSlice := reflect.ValueOf(actual)
+ expectedSlice := reflect.ValueOf(expected)
+
+ for i := 0; i < actualSlice.Len(); i++ {
+ result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon)
+ if !result {
+ return result
+ }
+ }
+
+ return true
+}
+
+/*
+ Errors
+*/
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoError(t, err) {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
+ if err != nil {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...)
+ }
+
+ return true
+}
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(t, err) {
+// assert.Equal(t, expectedError, err)
+// }
+func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
+ if err == nil {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, "An error is expected but got nil.", msgAndArgs...)
+ }
+
+ return true
+}
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// assert.EqualError(t, err, expectedErrorString)
+func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if !Error(t, theError, msgAndArgs...) {
+ return false
+ }
+ expected := errString
+ actual := theError.Error()
+ // don't need to use deep equals here, we know they are both strings
+ if expected != actual {
+ return Fail(t, fmt.Sprintf("Error message not equal:\n"+
+ "expected: %q\n"+
+ "actual : %q", expected, actual), msgAndArgs...)
+ }
+ return true
+}
+
+// ErrorContains asserts that a function returned an error (i.e. not `nil`)
+// and that the error contains the specified substring.
+//
+// actualObj, err := SomeFunction()
+// assert.ErrorContains(t, err, expectedErrorSubString)
+func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if !Error(t, theError, msgAndArgs...) {
+ return false
+ }
+
+ actual := theError.Error()
+ if !strings.Contains(actual, contains) {
+ return Fail(t, fmt.Sprintf("Error %#v does not contain %#v", actual, contains), msgAndArgs...)
+ }
+
+ return true
+}
+
+// matchRegexp return true if a specified regexp matches a string.
+func matchRegexp(rx interface{}, str interface{}) bool {
+
+ var r *regexp.Regexp
+ if rr, ok := rx.(*regexp.Regexp); ok {
+ r = rr
+ } else {
+ r = regexp.MustCompile(fmt.Sprint(rx))
+ }
+
+ return (r.FindStringIndex(fmt.Sprint(str)) != nil)
+
+}
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
+// assert.Regexp(t, "start...$", "it's not starting")
+func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ match := matchRegexp(rx, str)
+
+ if !match {
+ Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...)
+ }
+
+ return match
+}
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
+// assert.NotRegexp(t, "^start", "it's not starting")
+func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ match := matchRegexp(rx, str)
+
+ if match {
+ Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...)
+ }
+
+ return !match
+
+}
+
+// Zero asserts that i is the zero value for its type.
+func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
+ return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
+ }
+ return true
+}
+
+// NotZero asserts that i is not the zero value for its type.
+func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
+ return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...)
+ }
+ return true
+}
+
+// FileExists checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
+func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ info, err := os.Lstat(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...)
+ }
+ return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...)
+ }
+ if info.IsDir() {
+ return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...)
+ }
+ return true
+}
+
+// NoFileExists checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ info, err := os.Lstat(path)
+ if err != nil {
+ return true
+ }
+ if info.IsDir() {
+ return true
+ }
+ return Fail(t, fmt.Sprintf("file %q exists", path), msgAndArgs...)
+}
+
+// DirExists checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
+func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ info, err := os.Lstat(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...)
+ }
+ return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...)
+ }
+ if !info.IsDir() {
+ return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...)
+ }
+ return true
+}
+
+// NoDirExists checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ info, err := os.Lstat(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return true
+ }
+ return true
+ }
+ if !info.IsDir() {
+ return true
+ }
+ return Fail(t, fmt.Sprintf("directory %q exists", path), msgAndArgs...)
+}
+
+// JSONEq asserts that two JSON strings are equivalent.
+//
+// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ var expectedJSONAsInterface, actualJSONAsInterface interface{}
+
+ if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil {
+ return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...)
+ }
+
+ if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil {
+ return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...)
+ }
+
+ return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...)
+}
+
+// YAMLEq asserts that two YAML strings are equivalent.
+func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ var expectedYAMLAsInterface, actualYAMLAsInterface interface{}
+
+ if err := yaml.Unmarshal([]byte(expected), &expectedYAMLAsInterface); err != nil {
+ return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...)
+ }
+
+ if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil {
+ return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...)
+ }
+
+ return Equal(t, expectedYAMLAsInterface, actualYAMLAsInterface, msgAndArgs...)
+}
+
+func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
+ t := reflect.TypeOf(v)
+ k := t.Kind()
+
+ if k == reflect.Ptr {
+ t = t.Elem()
+ k = t.Kind()
+ }
+ return t, k
+}
+
+// diff returns a diff of both values as long as both are of the same type and
+// are a struct, map, slice, array or string. Otherwise it returns an empty string.
+func diff(expected interface{}, actual interface{}) string {
+ if expected == nil || actual == nil {
+ return ""
+ }
+
+ et, ek := typeAndKind(expected)
+ at, _ := typeAndKind(actual)
+
+ if et != at {
+ return ""
+ }
+
+ if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String {
+ return ""
+ }
+
+ var e, a string
+
+ switch et {
+ case reflect.TypeOf(""):
+ e = reflect.ValueOf(expected).String()
+ a = reflect.ValueOf(actual).String()
+ case reflect.TypeOf(time.Time{}):
+ e = spewConfigStringerEnabled.Sdump(expected)
+ a = spewConfigStringerEnabled.Sdump(actual)
+ default:
+ e = spewConfig.Sdump(expected)
+ a = spewConfig.Sdump(actual)
+ }
+
+ diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
+ A: difflib.SplitLines(e),
+ B: difflib.SplitLines(a),
+ FromFile: "Expected",
+ FromDate: "",
+ ToFile: "Actual",
+ ToDate: "",
+ Context: 1,
+ })
+
+ return "\n\nDiff:\n" + diff
+}
+
+func isFunction(arg interface{}) bool {
+ if arg == nil {
+ return false
+ }
+ return reflect.TypeOf(arg).Kind() == reflect.Func
+}
+
+var spewConfig = spew.ConfigState{
+ Indent: " ",
+ DisablePointerAddresses: true,
+ DisableCapacities: true,
+ SortKeys: true,
+ DisableMethods: true,
+ MaxDepth: 10,
+}
+
+var spewConfigStringerEnabled = spew.ConfigState{
+ Indent: " ",
+ DisablePointerAddresses: true,
+ DisableCapacities: true,
+ SortKeys: true,
+ MaxDepth: 10,
+}
+
+type tHelper interface {
+ Helper()
+}
+
+// Eventually asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick.
+//
+// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond)
+func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ ch := make(chan bool, 1)
+
+ timer := time.NewTimer(waitFor)
+ defer timer.Stop()
+
+ ticker := time.NewTicker(tick)
+ defer ticker.Stop()
+
+ for tick := ticker.C; ; {
+ select {
+ case <-timer.C:
+ return Fail(t, "Condition never satisfied", msgAndArgs...)
+ case <-tick:
+ tick = nil
+ go func() { ch <- condition() }()
+ case v := <-ch:
+ if v {
+ return true
+ }
+ tick = ticker.C
+ }
+ }
+}
+
+// Never asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond)
+func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ ch := make(chan bool, 1)
+
+ timer := time.NewTimer(waitFor)
+ defer timer.Stop()
+
+ ticker := time.NewTicker(tick)
+ defer ticker.Stop()
+
+ for tick := ticker.C; ; {
+ select {
+ case <-timer.C:
+ return true
+ case <-tick:
+ tick = nil
+ go func() { ch <- condition() }()
+ case v := <-ch:
+ if v {
+ return Fail(t, "Condition satisfied", msgAndArgs...)
+ }
+ tick = ticker.C
+ }
+ }
+}
+
+// ErrorIs asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if errors.Is(err, target) {
+ return true
+ }
+
+ var expectedText string
+ if target != nil {
+ expectedText = target.Error()
+ }
+
+ chain := buildErrorChainString(err)
+
+ return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+
+ "expected: %q\n"+
+ "in chain: %s", expectedText, chain,
+ ), msgAndArgs...)
+}
+
+// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if !errors.Is(err, target) {
+ return true
+ }
+
+ var expectedText string
+ if target != nil {
+ expectedText = target.Error()
+ }
+
+ chain := buildErrorChainString(err)
+
+ return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+
+ "found: %q\n"+
+ "in chain: %s", expectedText, chain,
+ ), msgAndArgs...)
+}
+
+// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if errors.As(err, target) {
+ return true
+ }
+
+ chain := buildErrorChainString(err)
+
+ return Fail(t, fmt.Sprintf("Should be in error chain:\n"+
+ "expected: %q\n"+
+ "in chain: %s", target, chain,
+ ), msgAndArgs...)
+}
+
+func buildErrorChainString(err error) string {
+ if err == nil {
+ return ""
+ }
+
+ e := errors.Unwrap(err)
+ chain := fmt.Sprintf("%q", err.Error())
+ for e != nil {
+ chain += fmt.Sprintf("\n\t%q", e.Error())
+ e = errors.Unwrap(e)
+ }
+ return chain
+}
diff --git a/vendor/github.com/stretchr/testify/assert/doc.go b/vendor/github.com/stretchr/testify/assert/doc.go
new file mode 100644
index 0000000..c9dccc4
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/doc.go
@@ -0,0 +1,45 @@
+// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
+//
+// Example Usage
+//
+// The following is a complete example using assert in a standard test function:
+// import (
+// "testing"
+// "github.com/stretchr/testify/assert"
+// )
+//
+// func TestSomething(t *testing.T) {
+//
+// var a string = "Hello"
+// var b string = "Hello"
+//
+// assert.Equal(t, a, b, "The two words should be the same.")
+//
+// }
+//
+// if you assert many times, use the format below:
+//
+// import (
+// "testing"
+// "github.com/stretchr/testify/assert"
+// )
+//
+// func TestSomething(t *testing.T) {
+// assert := assert.New(t)
+//
+// var a string = "Hello"
+// var b string = "Hello"
+//
+// assert.Equal(a, b, "The two words should be the same.")
+// }
+//
+// Assertions
+//
+// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
+// All assertion functions take, as the first argument, the `*testing.T` object provided by the
+// testing framework. This allows the assertion funcs to write the failings and other details to
+// the correct place.
+//
+// Every assertion function also takes an optional string message as the final argument,
+// allowing custom error messages to be appended to the message the assertion method outputs.
+package assert
diff --git a/vendor/github.com/stretchr/testify/assert/errors.go b/vendor/github.com/stretchr/testify/assert/errors.go
new file mode 100644
index 0000000..ac9dc9d
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/errors.go
@@ -0,0 +1,10 @@
+package assert
+
+import (
+ "errors"
+)
+
+// AnError is an error instance useful for testing. If the code does not care
+// about error specifics, and only needs to return the error for example, this
+// error should be used to make the test code more readable.
+var AnError = errors.New("assert.AnError general error for testing")
diff --git a/vendor/github.com/stretchr/testify/assert/forward_assertions.go b/vendor/github.com/stretchr/testify/assert/forward_assertions.go
new file mode 100644
index 0000000..df189d2
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/forward_assertions.go
@@ -0,0 +1,16 @@
+package assert
+
+// Assertions provides assertion methods around the
+// TestingT interface.
+type Assertions struct {
+ t TestingT
+}
+
+// New makes a new Assertions object for the specified TestingT.
+func New(t TestingT) *Assertions {
+ return &Assertions{
+ t: t,
+ }
+}
+
+//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs"
diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go
new file mode 100644
index 0000000..4ed341d
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go
@@ -0,0 +1,162 @@
+package assert
+
+import (
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "strings"
+)
+
+// httpCode is a helper that returns HTTP code of the response. It returns -1 and
+// an error if building a new request fails.
+func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
+ w := httptest.NewRecorder()
+ req, err := http.NewRequest(method, url, nil)
+ if err != nil {
+ return -1, err
+ }
+ req.URL.RawQuery = values.Encode()
+ handler(w, req)
+ return w.Code, nil
+}
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
+ }
+
+ isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
+ if !isSuccessCode {
+ Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code))
+ }
+
+ return isSuccessCode
+}
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
+ }
+
+ isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
+ if !isRedirectCode {
+ Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code))
+ }
+
+ return isRedirectCode
+}
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
+ }
+
+ isErrorCode := code >= http.StatusBadRequest
+ if !isErrorCode {
+ Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code))
+ }
+
+ return isErrorCode
+}
+
+// HTTPStatusCode asserts that a specified handler returns a specified status code.
+//
+// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
+ }
+
+ successful := code == statuscode
+ if !successful {
+ Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code))
+ }
+
+ return successful
+}
+
+// HTTPBody is a helper that returns HTTP body of the response. It returns
+// empty string if building a new request fails.
+func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
+ w := httptest.NewRecorder()
+ req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
+ if err != nil {
+ return ""
+ }
+ handler(w, req)
+ return w.Body.String()
+}
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ body := HTTPBody(handler, method, url, values)
+
+ contains := strings.Contains(body, fmt.Sprint(str))
+ if !contains {
+ Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
+ }
+
+ return contains
+}
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ body := HTTPBody(handler, method, url, values)
+
+ contains := strings.Contains(body, fmt.Sprint(str))
+ if contains {
+ Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
+ }
+
+ return !contains
+}
diff --git a/vendor/gopkg.in/yaml.v3/LICENSE b/vendor/gopkg.in/yaml.v3/LICENSE
new file mode 100644
index 0000000..2683e4b
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/LICENSE
@@ -0,0 +1,50 @@
+
+This project is covered by two different licenses: MIT and Apache.
+
+#### MIT License ####
+
+The following files were ported to Go from C files of libyaml, and thus
+are still covered by their original MIT license, with the additional
+copyright staring in 2011 when the project was ported over:
+
+ apic.go emitterc.go parserc.go readerc.go scannerc.go
+ writerc.go yamlh.go yamlprivateh.go
+
+Copyright (c) 2006-2010 Kirill Simonov
+Copyright (c) 2006-2011 Kirill Simonov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+### Apache License ###
+
+All the remaining project files are covered by the Apache license:
+
+Copyright (c) 2011-2019 Canonical Ltd
+
+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.
diff --git a/vendor/gopkg.in/yaml.v3/NOTICE b/vendor/gopkg.in/yaml.v3/NOTICE
new file mode 100644
index 0000000..866d74a
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/NOTICE
@@ -0,0 +1,13 @@
+Copyright 2011-2016 Canonical Ltd.
+
+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.
diff --git a/vendor/gopkg.in/yaml.v3/README.md b/vendor/gopkg.in/yaml.v3/README.md
new file mode 100644
index 0000000..08eb1ba
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/README.md
@@ -0,0 +1,150 @@
+# YAML support for the Go language
+
+Introduction
+------------
+
+The yaml package enables Go programs to comfortably encode and decode YAML
+values. It was developed within [Canonical](https://www.canonical.com) as
+part of the [juju](https://juju.ubuntu.com) project, and is based on a
+pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
+C library to parse and generate YAML data quickly and reliably.
+
+Compatibility
+-------------
+
+The yaml package supports most of YAML 1.2, but preserves some behavior
+from 1.1 for backwards compatibility.
+
+Specifically, as of v3 of the yaml package:
+
+ - YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being
+ decoded into a typed bool value. Otherwise they behave as a string. Booleans
+ in YAML 1.2 are _true/false_ only.
+ - Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_
+ as specified in YAML 1.2, because most parsers still use the old format.
+ Octals in the _0o777_ format are supported though, so new files work.
+ - Does not support base-60 floats. These are gone from YAML 1.2, and were
+ actually never supported by this package as it's clearly a poor choice.
+
+and offers backwards
+compatibility with YAML 1.1 in some cases.
+1.2, including support for
+anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
+implemented, and base-60 floats from YAML 1.1 are purposefully not
+supported since they're a poor design and are gone in YAML 1.2.
+
+Installation and usage
+----------------------
+
+The import path for the package is *gopkg.in/yaml.v3*.
+
+To install it, run:
+
+ go get gopkg.in/yaml.v3
+
+API documentation
+-----------------
+
+If opened in a browser, the import path itself leads to the API documentation:
+
+ - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3)
+
+API stability
+-------------
+
+The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in).
+
+
+License
+-------
+
+The yaml package is licensed under the MIT and Apache License 2.0 licenses.
+Please see the LICENSE file for details.
+
+
+Example
+-------
+
+```Go
+package main
+
+import (
+ "fmt"
+ "log"
+
+ "gopkg.in/yaml.v3"
+)
+
+var data = `
+a: Easy!
+b:
+ c: 2
+ d: [3, 4]
+`
+
+// Note: struct fields must be public in order for unmarshal to
+// correctly populate the data.
+type T struct {
+ A string
+ B struct {
+ RenamedC int `yaml:"c"`
+ D []int `yaml:",flow"`
+ }
+}
+
+func main() {
+ t := T{}
+
+ err := yaml.Unmarshal([]byte(data), &t)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- t:\n%v\n\n", t)
+
+ d, err := yaml.Marshal(&t)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- t dump:\n%s\n\n", string(d))
+
+ m := make(map[interface{}]interface{})
+
+ err = yaml.Unmarshal([]byte(data), &m)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- m:\n%v\n\n", m)
+
+ d, err = yaml.Marshal(&m)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- m dump:\n%s\n\n", string(d))
+}
+```
+
+This example will generate the following output:
+
+```
+--- t:
+{Easy! {2 [3 4]}}
+
+--- t dump:
+a: Easy!
+b:
+ c: 2
+ d: [3, 4]
+
+
+--- m:
+map[a:Easy! b:map[c:2 d:[3 4]]]
+
+--- m dump:
+a: Easy!
+b:
+ c: 2
+ d:
+ - 3
+ - 4
+```
+
diff --git a/vendor/gopkg.in/yaml.v3/apic.go b/vendor/gopkg.in/yaml.v3/apic.go
new file mode 100644
index 0000000..ae7d049
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/apic.go
@@ -0,0 +1,747 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "io"
+)
+
+func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
+ //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
+
+ // Check if we can move the queue at the beginning of the buffer.
+ if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
+ if parser.tokens_head != len(parser.tokens) {
+ copy(parser.tokens, parser.tokens[parser.tokens_head:])
+ }
+ parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
+ parser.tokens_head = 0
+ }
+ parser.tokens = append(parser.tokens, *token)
+ if pos < 0 {
+ return
+ }
+ copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
+ parser.tokens[parser.tokens_head+pos] = *token
+}
+
+// Create a new parser object.
+func yaml_parser_initialize(parser *yaml_parser_t) bool {
+ *parser = yaml_parser_t{
+ raw_buffer: make([]byte, 0, input_raw_buffer_size),
+ buffer: make([]byte, 0, input_buffer_size),
+ }
+ return true
+}
+
+// Destroy a parser object.
+func yaml_parser_delete(parser *yaml_parser_t) {
+ *parser = yaml_parser_t{}
+}
+
+// String read handler.
+func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+ if parser.input_pos == len(parser.input) {
+ return 0, io.EOF
+ }
+ n = copy(buffer, parser.input[parser.input_pos:])
+ parser.input_pos += n
+ return n, nil
+}
+
+// Reader read handler.
+func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+ return parser.input_reader.Read(buffer)
+}
+
+// Set a string input.
+func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
+ if parser.read_handler != nil {
+ panic("must set the input source only once")
+ }
+ parser.read_handler = yaml_string_read_handler
+ parser.input = input
+ parser.input_pos = 0
+}
+
+// Set a file input.
+func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) {
+ if parser.read_handler != nil {
+ panic("must set the input source only once")
+ }
+ parser.read_handler = yaml_reader_read_handler
+ parser.input_reader = r
+}
+
+// Set the source encoding.
+func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
+ if parser.encoding != yaml_ANY_ENCODING {
+ panic("must set the encoding only once")
+ }
+ parser.encoding = encoding
+}
+
+// Create a new emitter object.
+func yaml_emitter_initialize(emitter *yaml_emitter_t) {
+ *emitter = yaml_emitter_t{
+ buffer: make([]byte, output_buffer_size),
+ raw_buffer: make([]byte, 0, output_raw_buffer_size),
+ states: make([]yaml_emitter_state_t, 0, initial_stack_size),
+ events: make([]yaml_event_t, 0, initial_queue_size),
+ best_width: -1,
+ }
+}
+
+// Destroy an emitter object.
+func yaml_emitter_delete(emitter *yaml_emitter_t) {
+ *emitter = yaml_emitter_t{}
+}
+
+// String write handler.
+func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+ *emitter.output_buffer = append(*emitter.output_buffer, buffer...)
+ return nil
+}
+
+// yaml_writer_write_handler uses emitter.output_writer to write the
+// emitted text.
+func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+ _, err := emitter.output_writer.Write(buffer)
+ return err
+}
+
+// Set a string output.
+func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) {
+ if emitter.write_handler != nil {
+ panic("must set the output target only once")
+ }
+ emitter.write_handler = yaml_string_write_handler
+ emitter.output_buffer = output_buffer
+}
+
+// Set a file output.
+func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
+ if emitter.write_handler != nil {
+ panic("must set the output target only once")
+ }
+ emitter.write_handler = yaml_writer_write_handler
+ emitter.output_writer = w
+}
+
+// Set the output encoding.
+func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
+ if emitter.encoding != yaml_ANY_ENCODING {
+ panic("must set the output encoding only once")
+ }
+ emitter.encoding = encoding
+}
+
+// Set the canonical output style.
+func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
+ emitter.canonical = canonical
+}
+
+// Set the indentation increment.
+func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
+ if indent < 2 || indent > 9 {
+ indent = 2
+ }
+ emitter.best_indent = indent
+}
+
+// Set the preferred line width.
+func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
+ if width < 0 {
+ width = -1
+ }
+ emitter.best_width = width
+}
+
+// Set if unescaped non-ASCII characters are allowed.
+func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
+ emitter.unicode = unicode
+}
+
+// Set the preferred line break character.
+func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
+ emitter.line_break = line_break
+}
+
+///*
+// * Destroy a token object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_token_delete(yaml_token_t *token)
+//{
+// assert(token); // Non-NULL token object expected.
+//
+// switch (token.type)
+// {
+// case YAML_TAG_DIRECTIVE_TOKEN:
+// yaml_free(token.data.tag_directive.handle);
+// yaml_free(token.data.tag_directive.prefix);
+// break;
+//
+// case YAML_ALIAS_TOKEN:
+// yaml_free(token.data.alias.value);
+// break;
+//
+// case YAML_ANCHOR_TOKEN:
+// yaml_free(token.data.anchor.value);
+// break;
+//
+// case YAML_TAG_TOKEN:
+// yaml_free(token.data.tag.handle);
+// yaml_free(token.data.tag.suffix);
+// break;
+//
+// case YAML_SCALAR_TOKEN:
+// yaml_free(token.data.scalar.value);
+// break;
+//
+// default:
+// break;
+// }
+//
+// memset(token, 0, sizeof(yaml_token_t));
+//}
+//
+///*
+// * Check if a string is a valid UTF-8 sequence.
+// *
+// * Check 'reader.c' for more details on UTF-8 encoding.
+// */
+//
+//static int
+//yaml_check_utf8(yaml_char_t *start, size_t length)
+//{
+// yaml_char_t *end = start+length;
+// yaml_char_t *pointer = start;
+//
+// while (pointer < end) {
+// unsigned char octet;
+// unsigned int width;
+// unsigned int value;
+// size_t k;
+//
+// octet = pointer[0];
+// width = (octet & 0x80) == 0x00 ? 1 :
+// (octet & 0xE0) == 0xC0 ? 2 :
+// (octet & 0xF0) == 0xE0 ? 3 :
+// (octet & 0xF8) == 0xF0 ? 4 : 0;
+// value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+// (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+// (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+// if (!width) return 0;
+// if (pointer+width > end) return 0;
+// for (k = 1; k < width; k ++) {
+// octet = pointer[k];
+// if ((octet & 0xC0) != 0x80) return 0;
+// value = (value << 6) + (octet & 0x3F);
+// }
+// if (!((width == 1) ||
+// (width == 2 && value >= 0x80) ||
+// (width == 3 && value >= 0x800) ||
+// (width == 4 && value >= 0x10000))) return 0;
+//
+// pointer += width;
+// }
+//
+// return 1;
+//}
+//
+
+// Create STREAM-START.
+func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
+ *event = yaml_event_t{
+ typ: yaml_STREAM_START_EVENT,
+ encoding: encoding,
+ }
+}
+
+// Create STREAM-END.
+func yaml_stream_end_event_initialize(event *yaml_event_t) {
+ *event = yaml_event_t{
+ typ: yaml_STREAM_END_EVENT,
+ }
+}
+
+// Create DOCUMENT-START.
+func yaml_document_start_event_initialize(
+ event *yaml_event_t,
+ version_directive *yaml_version_directive_t,
+ tag_directives []yaml_tag_directive_t,
+ implicit bool,
+) {
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_START_EVENT,
+ version_directive: version_directive,
+ tag_directives: tag_directives,
+ implicit: implicit,
+ }
+}
+
+// Create DOCUMENT-END.
+func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_END_EVENT,
+ implicit: implicit,
+ }
+}
+
+// Create ALIAS.
+func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool {
+ *event = yaml_event_t{
+ typ: yaml_ALIAS_EVENT,
+ anchor: anchor,
+ }
+ return true
+}
+
+// Create SCALAR.
+func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ anchor: anchor,
+ tag: tag,
+ value: value,
+ implicit: plain_implicit,
+ quoted_implicit: quoted_implicit,
+ style: yaml_style_t(style),
+ }
+ return true
+}
+
+// Create SEQUENCE-START.
+func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(style),
+ }
+ return true
+}
+
+// Create SEQUENCE-END.
+func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ }
+ return true
+}
+
+// Create MAPPING-START.
+func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) {
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(style),
+ }
+}
+
+// Create MAPPING-END.
+func yaml_mapping_end_event_initialize(event *yaml_event_t) {
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ }
+}
+
+// Destroy an event object.
+func yaml_event_delete(event *yaml_event_t) {
+ *event = yaml_event_t{}
+}
+
+///*
+// * Create a document object.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_initialize(document *yaml_document_t,
+// version_directive *yaml_version_directive_t,
+// tag_directives_start *yaml_tag_directive_t,
+// tag_directives_end *yaml_tag_directive_t,
+// start_implicit int, end_implicit int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// struct {
+// start *yaml_node_t
+// end *yaml_node_t
+// top *yaml_node_t
+// } nodes = { NULL, NULL, NULL }
+// version_directive_copy *yaml_version_directive_t = NULL
+// struct {
+// start *yaml_tag_directive_t
+// end *yaml_tag_directive_t
+// top *yaml_tag_directive_t
+// } tag_directives_copy = { NULL, NULL, NULL }
+// value yaml_tag_directive_t = { NULL, NULL }
+// mark yaml_mark_t = { 0, 0, 0 }
+//
+// assert(document) // Non-NULL document object is expected.
+// assert((tag_directives_start && tag_directives_end) ||
+// (tag_directives_start == tag_directives_end))
+// // Valid tag directives are expected.
+//
+// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
+//
+// if (version_directive) {
+// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
+// if (!version_directive_copy) goto error
+// version_directive_copy.major = version_directive.major
+// version_directive_copy.minor = version_directive.minor
+// }
+//
+// if (tag_directives_start != tag_directives_end) {
+// tag_directive *yaml_tag_directive_t
+// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
+// goto error
+// for (tag_directive = tag_directives_start
+// tag_directive != tag_directives_end; tag_directive ++) {
+// assert(tag_directive.handle)
+// assert(tag_directive.prefix)
+// if (!yaml_check_utf8(tag_directive.handle,
+// strlen((char *)tag_directive.handle)))
+// goto error
+// if (!yaml_check_utf8(tag_directive.prefix,
+// strlen((char *)tag_directive.prefix)))
+// goto error
+// value.handle = yaml_strdup(tag_directive.handle)
+// value.prefix = yaml_strdup(tag_directive.prefix)
+// if (!value.handle || !value.prefix) goto error
+// if (!PUSH(&context, tag_directives_copy, value))
+// goto error
+// value.handle = NULL
+// value.prefix = NULL
+// }
+// }
+//
+// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
+// tag_directives_copy.start, tag_directives_copy.top,
+// start_implicit, end_implicit, mark, mark)
+//
+// return 1
+//
+//error:
+// STACK_DEL(&context, nodes)
+// yaml_free(version_directive_copy)
+// while (!STACK_EMPTY(&context, tag_directives_copy)) {
+// value yaml_tag_directive_t = POP(&context, tag_directives_copy)
+// yaml_free(value.handle)
+// yaml_free(value.prefix)
+// }
+// STACK_DEL(&context, tag_directives_copy)
+// yaml_free(value.handle)
+// yaml_free(value.prefix)
+//
+// return 0
+//}
+//
+///*
+// * Destroy a document object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_document_delete(document *yaml_document_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// tag_directive *yaml_tag_directive_t
+//
+// context.error = YAML_NO_ERROR // Eliminate a compiler warning.
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// while (!STACK_EMPTY(&context, document.nodes)) {
+// node yaml_node_t = POP(&context, document.nodes)
+// yaml_free(node.tag)
+// switch (node.type) {
+// case YAML_SCALAR_NODE:
+// yaml_free(node.data.scalar.value)
+// break
+// case YAML_SEQUENCE_NODE:
+// STACK_DEL(&context, node.data.sequence.items)
+// break
+// case YAML_MAPPING_NODE:
+// STACK_DEL(&context, node.data.mapping.pairs)
+// break
+// default:
+// assert(0) // Should not happen.
+// }
+// }
+// STACK_DEL(&context, document.nodes)
+//
+// yaml_free(document.version_directive)
+// for (tag_directive = document.tag_directives.start
+// tag_directive != document.tag_directives.end
+// tag_directive++) {
+// yaml_free(tag_directive.handle)
+// yaml_free(tag_directive.prefix)
+// }
+// yaml_free(document.tag_directives.start)
+//
+// memset(document, 0, sizeof(yaml_document_t))
+//}
+//
+///**
+// * Get a document node.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_node(document *yaml_document_t, index int)
+//{
+// assert(document) // Non-NULL document object is expected.
+//
+// if (index > 0 && document.nodes.start + index <= document.nodes.top) {
+// return document.nodes.start + index - 1
+// }
+// return NULL
+//}
+//
+///**
+// * Get the root object.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_root_node(document *yaml_document_t)
+//{
+// assert(document) // Non-NULL document object is expected.
+//
+// if (document.nodes.top != document.nodes.start) {
+// return document.nodes.start
+// }
+// return NULL
+//}
+//
+///*
+// * Add a scalar node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_scalar(document *yaml_document_t,
+// tag *yaml_char_t, value *yaml_char_t, length int,
+// style yaml_scalar_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// value_copy *yaml_char_t = NULL
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+// assert(value) // Non-NULL value is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (length < 0) {
+// length = strlen((char *)value)
+// }
+//
+// if (!yaml_check_utf8(value, length)) goto error
+// value_copy = yaml_malloc(length+1)
+// if (!value_copy) goto error
+// memcpy(value_copy, value, length)
+// value_copy[length] = '\0'
+//
+// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// yaml_free(tag_copy)
+// yaml_free(value_copy)
+//
+// return 0
+//}
+//
+///*
+// * Add a sequence node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_sequence(document *yaml_document_t,
+// tag *yaml_char_t, style yaml_sequence_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// struct {
+// start *yaml_node_item_t
+// end *yaml_node_item_t
+// top *yaml_node_item_t
+// } items = { NULL, NULL, NULL }
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
+//
+// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
+// style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// STACK_DEL(&context, items)
+// yaml_free(tag_copy)
+//
+// return 0
+//}
+//
+///*
+// * Add a mapping node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_mapping(document *yaml_document_t,
+// tag *yaml_char_t, style yaml_mapping_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// struct {
+// start *yaml_node_pair_t
+// end *yaml_node_pair_t
+// top *yaml_node_pair_t
+// } pairs = { NULL, NULL, NULL }
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
+//
+// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
+// style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// STACK_DEL(&context, pairs)
+// yaml_free(tag_copy)
+//
+// return 0
+//}
+//
+///*
+// * Append an item to a sequence node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_sequence_item(document *yaml_document_t,
+// sequence int, item int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+//
+// assert(document) // Non-NULL document is required.
+// assert(sequence > 0
+// && document.nodes.start + sequence <= document.nodes.top)
+// // Valid sequence id is required.
+// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
+// // A sequence node is required.
+// assert(item > 0 && document.nodes.start + item <= document.nodes.top)
+// // Valid item id is required.
+//
+// if (!PUSH(&context,
+// document.nodes.start[sequence-1].data.sequence.items, item))
+// return 0
+//
+// return 1
+//}
+//
+///*
+// * Append a pair of a key and a value to a mapping node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_mapping_pair(document *yaml_document_t,
+// mapping int, key int, value int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+//
+// pair yaml_node_pair_t
+//
+// assert(document) // Non-NULL document is required.
+// assert(mapping > 0
+// && document.nodes.start + mapping <= document.nodes.top)
+// // Valid mapping id is required.
+// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
+// // A mapping node is required.
+// assert(key > 0 && document.nodes.start + key <= document.nodes.top)
+// // Valid key id is required.
+// assert(value > 0 && document.nodes.start + value <= document.nodes.top)
+// // Valid value id is required.
+//
+// pair.key = key
+// pair.value = value
+//
+// if (!PUSH(&context,
+// document.nodes.start[mapping-1].data.mapping.pairs, pair))
+// return 0
+//
+// return 1
+//}
+//
+//
diff --git a/vendor/gopkg.in/yaml.v3/decode.go b/vendor/gopkg.in/yaml.v3/decode.go
new file mode 100644
index 0000000..0173b69
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/decode.go
@@ -0,0 +1,1000 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// 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 yaml
+
+import (
+ "encoding"
+ "encoding/base64"
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "strconv"
+ "time"
+)
+
+// ----------------------------------------------------------------------------
+// Parser, produces a node tree out of a libyaml event stream.
+
+type parser struct {
+ parser yaml_parser_t
+ event yaml_event_t
+ doc *Node
+ anchors map[string]*Node
+ doneInit bool
+ textless bool
+}
+
+func newParser(b []byte) *parser {
+ p := parser{}
+ if !yaml_parser_initialize(&p.parser) {
+ panic("failed to initialize YAML emitter")
+ }
+ if len(b) == 0 {
+ b = []byte{'\n'}
+ }
+ yaml_parser_set_input_string(&p.parser, b)
+ return &p
+}
+
+func newParserFromReader(r io.Reader) *parser {
+ p := parser{}
+ if !yaml_parser_initialize(&p.parser) {
+ panic("failed to initialize YAML emitter")
+ }
+ yaml_parser_set_input_reader(&p.parser, r)
+ return &p
+}
+
+func (p *parser) init() {
+ if p.doneInit {
+ return
+ }
+ p.anchors = make(map[string]*Node)
+ p.expect(yaml_STREAM_START_EVENT)
+ p.doneInit = true
+}
+
+func (p *parser) destroy() {
+ if p.event.typ != yaml_NO_EVENT {
+ yaml_event_delete(&p.event)
+ }
+ yaml_parser_delete(&p.parser)
+}
+
+// expect consumes an event from the event stream and
+// checks that it's of the expected type.
+func (p *parser) expect(e yaml_event_type_t) {
+ if p.event.typ == yaml_NO_EVENT {
+ if !yaml_parser_parse(&p.parser, &p.event) {
+ p.fail()
+ }
+ }
+ if p.event.typ == yaml_STREAM_END_EVENT {
+ failf("attempted to go past the end of stream; corrupted value?")
+ }
+ if p.event.typ != e {
+ p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
+ p.fail()
+ }
+ yaml_event_delete(&p.event)
+ p.event.typ = yaml_NO_EVENT
+}
+
+// peek peeks at the next event in the event stream,
+// puts the results into p.event and returns the event type.
+func (p *parser) peek() yaml_event_type_t {
+ if p.event.typ != yaml_NO_EVENT {
+ return p.event.typ
+ }
+ // It's curious choice from the underlying API to generally return a
+ // positive result on success, but on this case return true in an error
+ // scenario. This was the source of bugs in the past (issue #666).
+ if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR {
+ p.fail()
+ }
+ return p.event.typ
+}
+
+func (p *parser) fail() {
+ var where string
+ var line int
+ if p.parser.context_mark.line != 0 {
+ line = p.parser.context_mark.line
+ // Scanner errors don't iterate line before returning error
+ if p.parser.error == yaml_SCANNER_ERROR {
+ line++
+ }
+ } else if p.parser.problem_mark.line != 0 {
+ line = p.parser.problem_mark.line
+ // Scanner errors don't iterate line before returning error
+ if p.parser.error == yaml_SCANNER_ERROR {
+ line++
+ }
+ }
+ if line != 0 {
+ where = "line " + strconv.Itoa(line) + ": "
+ }
+ var msg string
+ if len(p.parser.problem) > 0 {
+ msg = p.parser.problem
+ } else {
+ msg = "unknown problem parsing YAML content"
+ }
+ failf("%s%s", where, msg)
+}
+
+func (p *parser) anchor(n *Node, anchor []byte) {
+ if anchor != nil {
+ n.Anchor = string(anchor)
+ p.anchors[n.Anchor] = n
+ }
+}
+
+func (p *parser) parse() *Node {
+ p.init()
+ switch p.peek() {
+ case yaml_SCALAR_EVENT:
+ return p.scalar()
+ case yaml_ALIAS_EVENT:
+ return p.alias()
+ case yaml_MAPPING_START_EVENT:
+ return p.mapping()
+ case yaml_SEQUENCE_START_EVENT:
+ return p.sequence()
+ case yaml_DOCUMENT_START_EVENT:
+ return p.document()
+ case yaml_STREAM_END_EVENT:
+ // Happens when attempting to decode an empty buffer.
+ return nil
+ case yaml_TAIL_COMMENT_EVENT:
+ panic("internal error: unexpected tail comment event (please report)")
+ default:
+ panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String())
+ }
+}
+
+func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node {
+ var style Style
+ if tag != "" && tag != "!" {
+ tag = shortTag(tag)
+ style = TaggedStyle
+ } else if defaultTag != "" {
+ tag = defaultTag
+ } else if kind == ScalarNode {
+ tag, _ = resolve("", value)
+ }
+ n := &Node{
+ Kind: kind,
+ Tag: tag,
+ Value: value,
+ Style: style,
+ }
+ if !p.textless {
+ n.Line = p.event.start_mark.line + 1
+ n.Column = p.event.start_mark.column + 1
+ n.HeadComment = string(p.event.head_comment)
+ n.LineComment = string(p.event.line_comment)
+ n.FootComment = string(p.event.foot_comment)
+ }
+ return n
+}
+
+func (p *parser) parseChild(parent *Node) *Node {
+ child := p.parse()
+ parent.Content = append(parent.Content, child)
+ return child
+}
+
+func (p *parser) document() *Node {
+ n := p.node(DocumentNode, "", "", "")
+ p.doc = n
+ p.expect(yaml_DOCUMENT_START_EVENT)
+ p.parseChild(n)
+ if p.peek() == yaml_DOCUMENT_END_EVENT {
+ n.FootComment = string(p.event.foot_comment)
+ }
+ p.expect(yaml_DOCUMENT_END_EVENT)
+ return n
+}
+
+func (p *parser) alias() *Node {
+ n := p.node(AliasNode, "", "", string(p.event.anchor))
+ n.Alias = p.anchors[n.Value]
+ if n.Alias == nil {
+ failf("unknown anchor '%s' referenced", n.Value)
+ }
+ p.expect(yaml_ALIAS_EVENT)
+ return n
+}
+
+func (p *parser) scalar() *Node {
+ var parsedStyle = p.event.scalar_style()
+ var nodeStyle Style
+ switch {
+ case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0:
+ nodeStyle = DoubleQuotedStyle
+ case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0:
+ nodeStyle = SingleQuotedStyle
+ case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0:
+ nodeStyle = LiteralStyle
+ case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0:
+ nodeStyle = FoldedStyle
+ }
+ var nodeValue = string(p.event.value)
+ var nodeTag = string(p.event.tag)
+ var defaultTag string
+ if nodeStyle == 0 {
+ if nodeValue == "<<" {
+ defaultTag = mergeTag
+ }
+ } else {
+ defaultTag = strTag
+ }
+ n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue)
+ n.Style |= nodeStyle
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_SCALAR_EVENT)
+ return n
+}
+
+func (p *parser) sequence() *Node {
+ n := p.node(SequenceNode, seqTag, string(p.event.tag), "")
+ if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 {
+ n.Style |= FlowStyle
+ }
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_SEQUENCE_START_EVENT)
+ for p.peek() != yaml_SEQUENCE_END_EVENT {
+ p.parseChild(n)
+ }
+ n.LineComment = string(p.event.line_comment)
+ n.FootComment = string(p.event.foot_comment)
+ p.expect(yaml_SEQUENCE_END_EVENT)
+ return n
+}
+
+func (p *parser) mapping() *Node {
+ n := p.node(MappingNode, mapTag, string(p.event.tag), "")
+ block := true
+ if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 {
+ block = false
+ n.Style |= FlowStyle
+ }
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_MAPPING_START_EVENT)
+ for p.peek() != yaml_MAPPING_END_EVENT {
+ k := p.parseChild(n)
+ if block && k.FootComment != "" {
+ // Must be a foot comment for the prior value when being dedented.
+ if len(n.Content) > 2 {
+ n.Content[len(n.Content)-3].FootComment = k.FootComment
+ k.FootComment = ""
+ }
+ }
+ v := p.parseChild(n)
+ if k.FootComment == "" && v.FootComment != "" {
+ k.FootComment = v.FootComment
+ v.FootComment = ""
+ }
+ if p.peek() == yaml_TAIL_COMMENT_EVENT {
+ if k.FootComment == "" {
+ k.FootComment = string(p.event.foot_comment)
+ }
+ p.expect(yaml_TAIL_COMMENT_EVENT)
+ }
+ }
+ n.LineComment = string(p.event.line_comment)
+ n.FootComment = string(p.event.foot_comment)
+ if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 {
+ n.Content[len(n.Content)-2].FootComment = n.FootComment
+ n.FootComment = ""
+ }
+ p.expect(yaml_MAPPING_END_EVENT)
+ return n
+}
+
+// ----------------------------------------------------------------------------
+// Decoder, unmarshals a node into a provided value.
+
+type decoder struct {
+ doc *Node
+ aliases map[*Node]bool
+ terrors []string
+
+ stringMapType reflect.Type
+ generalMapType reflect.Type
+
+ knownFields bool
+ uniqueKeys bool
+ decodeCount int
+ aliasCount int
+ aliasDepth int
+
+ mergedFields map[interface{}]bool
+}
+
+var (
+ nodeType = reflect.TypeOf(Node{})
+ durationType = reflect.TypeOf(time.Duration(0))
+ stringMapType = reflect.TypeOf(map[string]interface{}{})
+ generalMapType = reflect.TypeOf(map[interface{}]interface{}{})
+ ifaceType = generalMapType.Elem()
+ timeType = reflect.TypeOf(time.Time{})
+ ptrTimeType = reflect.TypeOf(&time.Time{})
+)
+
+func newDecoder() *decoder {
+ d := &decoder{
+ stringMapType: stringMapType,
+ generalMapType: generalMapType,
+ uniqueKeys: true,
+ }
+ d.aliases = make(map[*Node]bool)
+ return d
+}
+
+func (d *decoder) terror(n *Node, tag string, out reflect.Value) {
+ if n.Tag != "" {
+ tag = n.Tag
+ }
+ value := n.Value
+ if tag != seqTag && tag != mapTag {
+ if len(value) > 10 {
+ value = " `" + value[:7] + "...`"
+ } else {
+ value = " `" + value + "`"
+ }
+ }
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type()))
+}
+
+func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) {
+ err := u.UnmarshalYAML(n)
+ if e, ok := err.(*TypeError); ok {
+ d.terrors = append(d.terrors, e.Errors...)
+ return false
+ }
+ if err != nil {
+ fail(err)
+ }
+ return true
+}
+
+func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) {
+ terrlen := len(d.terrors)
+ err := u.UnmarshalYAML(func(v interface{}) (err error) {
+ defer handleErr(&err)
+ d.unmarshal(n, reflect.ValueOf(v))
+ if len(d.terrors) > terrlen {
+ issues := d.terrors[terrlen:]
+ d.terrors = d.terrors[:terrlen]
+ return &TypeError{issues}
+ }
+ return nil
+ })
+ if e, ok := err.(*TypeError); ok {
+ d.terrors = append(d.terrors, e.Errors...)
+ return false
+ }
+ if err != nil {
+ fail(err)
+ }
+ return true
+}
+
+// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
+// if a value is found to implement it.
+// It returns the initialized and dereferenced out value, whether
+// unmarshalling was already done by UnmarshalYAML, and if so whether
+// its types unmarshalled appropriately.
+//
+// If n holds a null value, prepare returns before doing anything.
+func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
+ if n.ShortTag() == nullTag {
+ return out, false, false
+ }
+ again := true
+ for again {
+ again = false
+ if out.Kind() == reflect.Ptr {
+ if out.IsNil() {
+ out.Set(reflect.New(out.Type().Elem()))
+ }
+ out = out.Elem()
+ again = true
+ }
+ if out.CanAddr() {
+ outi := out.Addr().Interface()
+ if u, ok := outi.(Unmarshaler); ok {
+ good = d.callUnmarshaler(n, u)
+ return out, true, good
+ }
+ if u, ok := outi.(obsoleteUnmarshaler); ok {
+ good = d.callObsoleteUnmarshaler(n, u)
+ return out, true, good
+ }
+ }
+ }
+ return out, false, false
+}
+
+func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) {
+ if n.ShortTag() == nullTag {
+ return reflect.Value{}
+ }
+ for _, num := range index {
+ for {
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ v = v.Elem()
+ continue
+ }
+ break
+ }
+ v = v.Field(num)
+ }
+ return v
+}
+
+const (
+ // 400,000 decode operations is ~500kb of dense object declarations, or
+ // ~5kb of dense object declarations with 10000% alias expansion
+ alias_ratio_range_low = 400000
+
+ // 4,000,000 decode operations is ~5MB of dense object declarations, or
+ // ~4.5MB of dense object declarations with 10% alias expansion
+ alias_ratio_range_high = 4000000
+
+ // alias_ratio_range is the range over which we scale allowed alias ratios
+ alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
+)
+
+func allowedAliasRatio(decodeCount int) float64 {
+ switch {
+ case decodeCount <= alias_ratio_range_low:
+ // allow 99% to come from alias expansion for small-to-medium documents
+ return 0.99
+ case decodeCount >= alias_ratio_range_high:
+ // allow 10% to come from alias expansion for very large documents
+ return 0.10
+ default:
+ // scale smoothly from 99% down to 10% over the range.
+ // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
+ // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
+ return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range)
+ }
+}
+
+func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) {
+ d.decodeCount++
+ if d.aliasDepth > 0 {
+ d.aliasCount++
+ }
+ if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) {
+ failf("document contains excessive aliasing")
+ }
+ if out.Type() == nodeType {
+ out.Set(reflect.ValueOf(n).Elem())
+ return true
+ }
+ switch n.Kind {
+ case DocumentNode:
+ return d.document(n, out)
+ case AliasNode:
+ return d.alias(n, out)
+ }
+ out, unmarshaled, good := d.prepare(n, out)
+ if unmarshaled {
+ return good
+ }
+ switch n.Kind {
+ case ScalarNode:
+ good = d.scalar(n, out)
+ case MappingNode:
+ good = d.mapping(n, out)
+ case SequenceNode:
+ good = d.sequence(n, out)
+ case 0:
+ if n.IsZero() {
+ return d.null(out)
+ }
+ fallthrough
+ default:
+ failf("cannot decode node with unknown kind %d", n.Kind)
+ }
+ return good
+}
+
+func (d *decoder) document(n *Node, out reflect.Value) (good bool) {
+ if len(n.Content) == 1 {
+ d.doc = n
+ d.unmarshal(n.Content[0], out)
+ return true
+ }
+ return false
+}
+
+func (d *decoder) alias(n *Node, out reflect.Value) (good bool) {
+ if d.aliases[n] {
+ // TODO this could actually be allowed in some circumstances.
+ failf("anchor '%s' value contains itself", n.Value)
+ }
+ d.aliases[n] = true
+ d.aliasDepth++
+ good = d.unmarshal(n.Alias, out)
+ d.aliasDepth--
+ delete(d.aliases, n)
+ return good
+}
+
+var zeroValue reflect.Value
+
+func resetMap(out reflect.Value) {
+ for _, k := range out.MapKeys() {
+ out.SetMapIndex(k, zeroValue)
+ }
+}
+
+func (d *decoder) null(out reflect.Value) bool {
+ if out.CanAddr() {
+ switch out.Kind() {
+ case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
+ out.Set(reflect.Zero(out.Type()))
+ return true
+ }
+ }
+ return false
+}
+
+func (d *decoder) scalar(n *Node, out reflect.Value) bool {
+ var tag string
+ var resolved interface{}
+ if n.indicatedString() {
+ tag = strTag
+ resolved = n.Value
+ } else {
+ tag, resolved = resolve(n.Tag, n.Value)
+ if tag == binaryTag {
+ data, err := base64.StdEncoding.DecodeString(resolved.(string))
+ if err != nil {
+ failf("!!binary value contains invalid base64 data")
+ }
+ resolved = string(data)
+ }
+ }
+ if resolved == nil {
+ return d.null(out)
+ }
+ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+ // We've resolved to exactly the type we want, so use that.
+ out.Set(resolvedv)
+ return true
+ }
+ // Perhaps we can use the value as a TextUnmarshaler to
+ // set its value.
+ if out.CanAddr() {
+ u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
+ if ok {
+ var text []byte
+ if tag == binaryTag {
+ text = []byte(resolved.(string))
+ } else {
+ // We let any value be unmarshaled into TextUnmarshaler.
+ // That might be more lax than we'd like, but the
+ // TextUnmarshaler itself should bowl out any dubious values.
+ text = []byte(n.Value)
+ }
+ err := u.UnmarshalText(text)
+ if err != nil {
+ fail(err)
+ }
+ return true
+ }
+ }
+ switch out.Kind() {
+ case reflect.String:
+ if tag == binaryTag {
+ out.SetString(resolved.(string))
+ return true
+ }
+ out.SetString(n.Value)
+ return true
+ case reflect.Interface:
+ out.Set(reflect.ValueOf(resolved))
+ return true
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ // This used to work in v2, but it's very unfriendly.
+ isDuration := out.Type() == durationType
+
+ switch resolved := resolved.(type) {
+ case int:
+ if !isDuration && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case int64:
+ if !isDuration && !out.OverflowInt(resolved) {
+ out.SetInt(resolved)
+ return true
+ }
+ case uint64:
+ if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case float64:
+ if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case string:
+ if out.Type() == durationType {
+ d, err := time.ParseDuration(resolved)
+ if err == nil {
+ out.SetInt(int64(d))
+ return true
+ }
+ }
+ }
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ switch resolved := resolved.(type) {
+ case int:
+ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case int64:
+ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case uint64:
+ if !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case float64:
+ if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ }
+ case reflect.Bool:
+ switch resolved := resolved.(type) {
+ case bool:
+ out.SetBool(resolved)
+ return true
+ case string:
+ // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html).
+ // It only works if explicitly attempting to unmarshal into a typed bool value.
+ switch resolved {
+ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
+ out.SetBool(true)
+ return true
+ case "n", "N", "no", "No", "NO", "off", "Off", "OFF":
+ out.SetBool(false)
+ return true
+ }
+ }
+ case reflect.Float32, reflect.Float64:
+ switch resolved := resolved.(type) {
+ case int:
+ out.SetFloat(float64(resolved))
+ return true
+ case int64:
+ out.SetFloat(float64(resolved))
+ return true
+ case uint64:
+ out.SetFloat(float64(resolved))
+ return true
+ case float64:
+ out.SetFloat(resolved)
+ return true
+ }
+ case reflect.Struct:
+ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+ out.Set(resolvedv)
+ return true
+ }
+ case reflect.Ptr:
+ panic("yaml internal error: please report the issue")
+ }
+ d.terror(n, tag, out)
+ return false
+}
+
+func settableValueOf(i interface{}) reflect.Value {
+ v := reflect.ValueOf(i)
+ sv := reflect.New(v.Type()).Elem()
+ sv.Set(v)
+ return sv
+}
+
+func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) {
+ l := len(n.Content)
+
+ var iface reflect.Value
+ switch out.Kind() {
+ case reflect.Slice:
+ out.Set(reflect.MakeSlice(out.Type(), l, l))
+ case reflect.Array:
+ if l != out.Len() {
+ failf("invalid array: want %d elements but got %d", out.Len(), l)
+ }
+ case reflect.Interface:
+ // No type hints. Will have to use a generic sequence.
+ iface = out
+ out = settableValueOf(make([]interface{}, l))
+ default:
+ d.terror(n, seqTag, out)
+ return false
+ }
+ et := out.Type().Elem()
+
+ j := 0
+ for i := 0; i < l; i++ {
+ e := reflect.New(et).Elem()
+ if ok := d.unmarshal(n.Content[i], e); ok {
+ out.Index(j).Set(e)
+ j++
+ }
+ }
+ if out.Kind() != reflect.Array {
+ out.Set(out.Slice(0, j))
+ }
+ if iface.IsValid() {
+ iface.Set(out)
+ }
+ return true
+}
+
+func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
+ l := len(n.Content)
+ if d.uniqueKeys {
+ nerrs := len(d.terrors)
+ for i := 0; i < l; i += 2 {
+ ni := n.Content[i]
+ for j := i + 2; j < l; j += 2 {
+ nj := n.Content[j]
+ if ni.Kind == nj.Kind && ni.Value == nj.Value {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line))
+ }
+ }
+ }
+ if len(d.terrors) > nerrs {
+ return false
+ }
+ }
+ switch out.Kind() {
+ case reflect.Struct:
+ return d.mappingStruct(n, out)
+ case reflect.Map:
+ // okay
+ case reflect.Interface:
+ iface := out
+ if isStringMap(n) {
+ out = reflect.MakeMap(d.stringMapType)
+ } else {
+ out = reflect.MakeMap(d.generalMapType)
+ }
+ iface.Set(out)
+ default:
+ d.terror(n, mapTag, out)
+ return false
+ }
+
+ outt := out.Type()
+ kt := outt.Key()
+ et := outt.Elem()
+
+ stringMapType := d.stringMapType
+ generalMapType := d.generalMapType
+ if outt.Elem() == ifaceType {
+ if outt.Key().Kind() == reflect.String {
+ d.stringMapType = outt
+ } else if outt.Key() == ifaceType {
+ d.generalMapType = outt
+ }
+ }
+
+ mergedFields := d.mergedFields
+ d.mergedFields = nil
+
+ var mergeNode *Node
+
+ mapIsNew := false
+ if out.IsNil() {
+ out.Set(reflect.MakeMap(outt))
+ mapIsNew = true
+ }
+ for i := 0; i < l; i += 2 {
+ if isMerge(n.Content[i]) {
+ mergeNode = n.Content[i+1]
+ continue
+ }
+ k := reflect.New(kt).Elem()
+ if d.unmarshal(n.Content[i], k) {
+ if mergedFields != nil {
+ ki := k.Interface()
+ if mergedFields[ki] {
+ continue
+ }
+ mergedFields[ki] = true
+ }
+ kkind := k.Kind()
+ if kkind == reflect.Interface {
+ kkind = k.Elem().Kind()
+ }
+ if kkind == reflect.Map || kkind == reflect.Slice {
+ failf("invalid map key: %#v", k.Interface())
+ }
+ e := reflect.New(et).Elem()
+ if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) {
+ out.SetMapIndex(k, e)
+ }
+ }
+ }
+
+ d.mergedFields = mergedFields
+ if mergeNode != nil {
+ d.merge(n, mergeNode, out)
+ }
+
+ d.stringMapType = stringMapType
+ d.generalMapType = generalMapType
+ return true
+}
+
+func isStringMap(n *Node) bool {
+ if n.Kind != MappingNode {
+ return false
+ }
+ l := len(n.Content)
+ for i := 0; i < l; i += 2 {
+ shortTag := n.Content[i].ShortTag()
+ if shortTag != strTag && shortTag != mergeTag {
+ return false
+ }
+ }
+ return true
+}
+
+func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
+ sinfo, err := getStructInfo(out.Type())
+ if err != nil {
+ panic(err)
+ }
+
+ var inlineMap reflect.Value
+ var elemType reflect.Type
+ if sinfo.InlineMap != -1 {
+ inlineMap = out.Field(sinfo.InlineMap)
+ elemType = inlineMap.Type().Elem()
+ }
+
+ for _, index := range sinfo.InlineUnmarshalers {
+ field := d.fieldByIndex(n, out, index)
+ d.prepare(n, field)
+ }
+
+ mergedFields := d.mergedFields
+ d.mergedFields = nil
+ var mergeNode *Node
+ var doneFields []bool
+ if d.uniqueKeys {
+ doneFields = make([]bool, len(sinfo.FieldsList))
+ }
+ name := settableValueOf("")
+ l := len(n.Content)
+ for i := 0; i < l; i += 2 {
+ ni := n.Content[i]
+ if isMerge(ni) {
+ mergeNode = n.Content[i+1]
+ continue
+ }
+ if !d.unmarshal(ni, name) {
+ continue
+ }
+ sname := name.String()
+ if mergedFields != nil {
+ if mergedFields[sname] {
+ continue
+ }
+ mergedFields[sname] = true
+ }
+ if info, ok := sinfo.FieldsMap[sname]; ok {
+ if d.uniqueKeys {
+ if doneFields[info.Id] {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
+ continue
+ }
+ doneFields[info.Id] = true
+ }
+ var field reflect.Value
+ if info.Inline == nil {
+ field = out.Field(info.Num)
+ } else {
+ field = d.fieldByIndex(n, out, info.Inline)
+ }
+ d.unmarshal(n.Content[i+1], field)
+ } else if sinfo.InlineMap != -1 {
+ if inlineMap.IsNil() {
+ inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
+ }
+ value := reflect.New(elemType).Elem()
+ d.unmarshal(n.Content[i+1], value)
+ inlineMap.SetMapIndex(name, value)
+ } else if d.knownFields {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
+ }
+ }
+
+ d.mergedFields = mergedFields
+ if mergeNode != nil {
+ d.merge(n, mergeNode, out)
+ }
+ return true
+}
+
+func failWantMap() {
+ failf("map merge requires map or sequence of maps as the value")
+}
+
+func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) {
+ mergedFields := d.mergedFields
+ if mergedFields == nil {
+ d.mergedFields = make(map[interface{}]bool)
+ for i := 0; i < len(parent.Content); i += 2 {
+ k := reflect.New(ifaceType).Elem()
+ if d.unmarshal(parent.Content[i], k) {
+ d.mergedFields[k.Interface()] = true
+ }
+ }
+ }
+
+ switch merge.Kind {
+ case MappingNode:
+ d.unmarshal(merge, out)
+ case AliasNode:
+ if merge.Alias != nil && merge.Alias.Kind != MappingNode {
+ failWantMap()
+ }
+ d.unmarshal(merge, out)
+ case SequenceNode:
+ for i := 0; i < len(merge.Content); i++ {
+ ni := merge.Content[i]
+ if ni.Kind == AliasNode {
+ if ni.Alias != nil && ni.Alias.Kind != MappingNode {
+ failWantMap()
+ }
+ } else if ni.Kind != MappingNode {
+ failWantMap()
+ }
+ d.unmarshal(ni, out)
+ }
+ default:
+ failWantMap()
+ }
+
+ d.mergedFields = mergedFields
+}
+
+func isMerge(n *Node) bool {
+ return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag)
+}
diff --git a/vendor/gopkg.in/yaml.v3/emitterc.go b/vendor/gopkg.in/yaml.v3/emitterc.go
new file mode 100644
index 0000000..0f47c9c
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/emitterc.go
@@ -0,0 +1,2020 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "bytes"
+ "fmt"
+)
+
+// Flush the buffer if needed.
+func flush(emitter *yaml_emitter_t) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) {
+ return yaml_emitter_flush(emitter)
+ }
+ return true
+}
+
+// Put a character to the output buffer.
+func put(emitter *yaml_emitter_t, value byte) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.buffer[emitter.buffer_pos] = value
+ emitter.buffer_pos++
+ emitter.column++
+ return true
+}
+
+// Put a line break to the output buffer.
+func put_break(emitter *yaml_emitter_t) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ switch emitter.line_break {
+ case yaml_CR_BREAK:
+ emitter.buffer[emitter.buffer_pos] = '\r'
+ emitter.buffer_pos += 1
+ case yaml_LN_BREAK:
+ emitter.buffer[emitter.buffer_pos] = '\n'
+ emitter.buffer_pos += 1
+ case yaml_CRLN_BREAK:
+ emitter.buffer[emitter.buffer_pos+0] = '\r'
+ emitter.buffer[emitter.buffer_pos+1] = '\n'
+ emitter.buffer_pos += 2
+ default:
+ panic("unknown line break setting")
+ }
+ if emitter.column == 0 {
+ emitter.space_above = true
+ }
+ emitter.column = 0
+ emitter.line++
+ // [Go] Do this here and below and drop from everywhere else (see commented lines).
+ emitter.indention = true
+ return true
+}
+
+// Copy a character from a string into buffer.
+func write(emitter *yaml_emitter_t, s []byte, i *int) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ p := emitter.buffer_pos
+ w := width(s[*i])
+ switch w {
+ case 4:
+ emitter.buffer[p+3] = s[*i+3]
+ fallthrough
+ case 3:
+ emitter.buffer[p+2] = s[*i+2]
+ fallthrough
+ case 2:
+ emitter.buffer[p+1] = s[*i+1]
+ fallthrough
+ case 1:
+ emitter.buffer[p+0] = s[*i+0]
+ default:
+ panic("unknown character width")
+ }
+ emitter.column++
+ emitter.buffer_pos += w
+ *i += w
+ return true
+}
+
+// Write a whole string into buffer.
+func write_all(emitter *yaml_emitter_t, s []byte) bool {
+ for i := 0; i < len(s); {
+ if !write(emitter, s, &i) {
+ return false
+ }
+ }
+ return true
+}
+
+// Copy a line break character from a string into buffer.
+func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
+ if s[*i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ *i++
+ } else {
+ if !write(emitter, s, i) {
+ return false
+ }
+ if emitter.column == 0 {
+ emitter.space_above = true
+ }
+ emitter.column = 0
+ emitter.line++
+ // [Go] Do this here and above and drop from everywhere else (see commented lines).
+ emitter.indention = true
+ }
+ return true
+}
+
+// Set an emitter error and return false.
+func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool {
+ emitter.error = yaml_EMITTER_ERROR
+ emitter.problem = problem
+ return false
+}
+
+// Emit an event.
+func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ emitter.events = append(emitter.events, *event)
+ for !yaml_emitter_need_more_events(emitter) {
+ event := &emitter.events[emitter.events_head]
+ if !yaml_emitter_analyze_event(emitter, event) {
+ return false
+ }
+ if !yaml_emitter_state_machine(emitter, event) {
+ return false
+ }
+ yaml_event_delete(event)
+ emitter.events_head++
+ }
+ return true
+}
+
+// Check if we need to accumulate more events before emitting.
+//
+// We accumulate extra
+// - 1 event for DOCUMENT-START
+// - 2 events for SEQUENCE-START
+// - 3 events for MAPPING-START
+//
+func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
+ if emitter.events_head == len(emitter.events) {
+ return true
+ }
+ var accumulate int
+ switch emitter.events[emitter.events_head].typ {
+ case yaml_DOCUMENT_START_EVENT:
+ accumulate = 1
+ break
+ case yaml_SEQUENCE_START_EVENT:
+ accumulate = 2
+ break
+ case yaml_MAPPING_START_EVENT:
+ accumulate = 3
+ break
+ default:
+ return false
+ }
+ if len(emitter.events)-emitter.events_head > accumulate {
+ return false
+ }
+ var level int
+ for i := emitter.events_head; i < len(emitter.events); i++ {
+ switch emitter.events[i].typ {
+ case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT:
+ level++
+ case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT:
+ level--
+ }
+ if level == 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// Append a directive to the directives stack.
+func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool {
+ for i := 0; i < len(emitter.tag_directives); i++ {
+ if bytes.Equal(value.handle, emitter.tag_directives[i].handle) {
+ if allow_duplicates {
+ return true
+ }
+ return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive")
+ }
+ }
+
+ // [Go] Do we actually need to copy this given garbage collection
+ // and the lack of deallocating destructors?
+ tag_copy := yaml_tag_directive_t{
+ handle: make([]byte, len(value.handle)),
+ prefix: make([]byte, len(value.prefix)),
+ }
+ copy(tag_copy.handle, value.handle)
+ copy(tag_copy.prefix, value.prefix)
+ emitter.tag_directives = append(emitter.tag_directives, tag_copy)
+ return true
+}
+
+// Increase the indentation level.
+func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
+ emitter.indents = append(emitter.indents, emitter.indent)
+ if emitter.indent < 0 {
+ if flow {
+ emitter.indent = emitter.best_indent
+ } else {
+ emitter.indent = 0
+ }
+ } else if !indentless {
+ // [Go] This was changed so that indentations are more regular.
+ if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE {
+ // The first indent inside a sequence will just skip the "- " indicator.
+ emitter.indent += 2
+ } else {
+ // Everything else aligns to the chosen indentation.
+ emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent)
+ }
+ }
+ return true
+}
+
+// State dispatcher.
+func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ switch emitter.state {
+ default:
+ case yaml_EMIT_STREAM_START_STATE:
+ return yaml_emitter_emit_stream_start(emitter, event)
+
+ case yaml_EMIT_FIRST_DOCUMENT_START_STATE:
+ return yaml_emitter_emit_document_start(emitter, event, true)
+
+ case yaml_EMIT_DOCUMENT_START_STATE:
+ return yaml_emitter_emit_document_start(emitter, event, false)
+
+ case yaml_EMIT_DOCUMENT_CONTENT_STATE:
+ return yaml_emitter_emit_document_content(emitter, event)
+
+ case yaml_EMIT_DOCUMENT_END_STATE:
+ return yaml_emitter_emit_document_end(emitter, event)
+
+ case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false)
+
+ case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true)
+
+ case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false)
+
+ case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false)
+
+ case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true)
+
+ case yaml_EMIT_FLOW_MAPPING_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false)
+
+ case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
+ return yaml_emitter_emit_flow_mapping_value(emitter, event, true)
+
+ case yaml_EMIT_FLOW_MAPPING_VALUE_STATE:
+ return yaml_emitter_emit_flow_mapping_value(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
+ return yaml_emitter_emit_block_sequence_item(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
+ return yaml_emitter_emit_block_sequence_item(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return yaml_emitter_emit_block_mapping_key(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_MAPPING_KEY_STATE:
+ return yaml_emitter_emit_block_mapping_key(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
+ return yaml_emitter_emit_block_mapping_value(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE:
+ return yaml_emitter_emit_block_mapping_value(emitter, event, false)
+
+ case yaml_EMIT_END_STATE:
+ return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END")
+ }
+ panic("invalid emitter state")
+}
+
+// Expect STREAM-START.
+func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if event.typ != yaml_STREAM_START_EVENT {
+ return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START")
+ }
+ if emitter.encoding == yaml_ANY_ENCODING {
+ emitter.encoding = event.encoding
+ if emitter.encoding == yaml_ANY_ENCODING {
+ emitter.encoding = yaml_UTF8_ENCODING
+ }
+ }
+ if emitter.best_indent < 2 || emitter.best_indent > 9 {
+ emitter.best_indent = 2
+ }
+ if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 {
+ emitter.best_width = 80
+ }
+ if emitter.best_width < 0 {
+ emitter.best_width = 1<<31 - 1
+ }
+ if emitter.line_break == yaml_ANY_BREAK {
+ emitter.line_break = yaml_LN_BREAK
+ }
+
+ emitter.indent = -1
+ emitter.line = 0
+ emitter.column = 0
+ emitter.whitespace = true
+ emitter.indention = true
+ emitter.space_above = true
+ emitter.foot_indent = -1
+
+ if emitter.encoding != yaml_UTF8_ENCODING {
+ if !yaml_emitter_write_bom(emitter) {
+ return false
+ }
+ }
+ emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE
+ return true
+}
+
+// Expect DOCUMENT-START or STREAM-END.
+func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+
+ if event.typ == yaml_DOCUMENT_START_EVENT {
+
+ if event.version_directive != nil {
+ if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) {
+ return false
+ }
+ }
+
+ for i := 0; i < len(event.tag_directives); i++ {
+ tag_directive := &event.tag_directives[i]
+ if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) {
+ return false
+ }
+ if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) {
+ return false
+ }
+ }
+
+ for i := 0; i < len(default_tag_directives); i++ {
+ tag_directive := &default_tag_directives[i]
+ if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) {
+ return false
+ }
+ }
+
+ implicit := event.implicit
+ if !first || emitter.canonical {
+ implicit = false
+ }
+
+ if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) {
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if event.version_directive != nil {
+ implicit = false
+ if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if len(event.tag_directives) > 0 {
+ implicit = false
+ for i := 0; i < len(event.tag_directives); i++ {
+ tag_directive := &event.tag_directives[i]
+ if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) {
+ return false
+ }
+ if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ }
+
+ if yaml_emitter_check_empty_document(emitter) {
+ implicit = false
+ }
+ if !implicit {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) {
+ return false
+ }
+ if emitter.canonical || true {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ }
+
+ if len(emitter.head_comment) > 0 {
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if !put_break(emitter) {
+ return false
+ }
+ }
+
+ emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE
+ return true
+ }
+
+ if event.typ == yaml_STREAM_END_EVENT {
+ if emitter.open_ended {
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.state = yaml_EMIT_END_STATE
+ return true
+ }
+
+ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END")
+}
+
+// Expect the root node.
+func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE)
+
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_emit_node(emitter, event, true, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+// Expect DOCUMENT-END.
+func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if event.typ != yaml_DOCUMENT_END_EVENT {
+ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END")
+ }
+ // [Go] Force document foot separation.
+ emitter.foot_indent = 0
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ emitter.foot_indent = -1
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !event.implicit {
+ // [Go] Allocate the slice elsewhere.
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.state = yaml_EMIT_DOCUMENT_START_STATE
+ emitter.tag_directives = emitter.tag_directives[:0]
+ return true
+}
+
+// Expect a flow item node.
+func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
+ if first {
+ if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false) {
+ return false
+ }
+ emitter.flow_level++
+ }
+
+ if event.typ == yaml_SEQUENCE_END_EVENT {
+ if emitter.canonical && !first && !trail {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ emitter.flow_level--
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ if emitter.column == 0 || emitter.canonical && !first {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+
+ return true
+ }
+
+ if !first && !trail {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if emitter.column == 0 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE)
+ } else {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE)
+ }
+ if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
+ return false
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+// Expect a flow key node.
+func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
+ if first {
+ if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false) {
+ return false
+ }
+ emitter.flow_level++
+ }
+
+ if event.typ == yaml_MAPPING_END_EVENT {
+ if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ emitter.flow_level--
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ if emitter.canonical && !first {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+
+ if !first && !trail {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+
+ if emitter.column == 0 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if !emitter.canonical && yaml_emitter_check_simple_key(emitter) {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a flow value node.
+func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+ if simple {
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+ return false
+ }
+ } else {
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) {
+ return false
+ }
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE)
+ } else {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE)
+ }
+ if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
+ return false
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+// Expect a block item node.
+func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ if !yaml_emitter_increase_indent(emitter, false, false) {
+ return false
+ }
+ }
+ if event.typ == yaml_SEQUENCE_END_EVENT {
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE)
+ if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+// Expect a block key node.
+func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ if !yaml_emitter_increase_indent(emitter, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if event.typ == yaml_MAPPING_END_EVENT {
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if len(emitter.line_comment) > 0 {
+ // [Go] A line comment was provided for the key. That's unusual as the
+ // scanner associates line comments with the value. Either way,
+ // save the line comment and render it appropriately later.
+ emitter.key_line_comment = emitter.line_comment
+ emitter.line_comment = nil
+ }
+ if yaml_emitter_check_simple_key(emitter) {
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a block value node.
+func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+ if simple {
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+ return false
+ }
+ } else {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) {
+ return false
+ }
+ }
+ if len(emitter.key_line_comment) > 0 {
+ // [Go] Line comments are generally associated with the value, but when there's
+ // no value on the same line as a mapping key they end up attached to the
+ // key itself.
+ if event.typ == yaml_SCALAR_EVENT {
+ if len(emitter.line_comment) == 0 {
+ // A scalar is coming and it has no line comments by itself yet,
+ // so just let it handle the line comment as usual. If it has a
+ // line comment, we can't have both so the one from the key is lost.
+ emitter.line_comment = emitter.key_line_comment
+ emitter.key_line_comment = nil
+ }
+ } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) {
+ // An indented block follows, so write the comment right now.
+ emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+ }
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
+ if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0
+}
+
+// Expect a node.
+func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
+ root bool, sequence bool, mapping bool, simple_key bool) bool {
+
+ emitter.root_context = root
+ emitter.sequence_context = sequence
+ emitter.mapping_context = mapping
+ emitter.simple_key_context = simple_key
+
+ switch event.typ {
+ case yaml_ALIAS_EVENT:
+ return yaml_emitter_emit_alias(emitter, event)
+ case yaml_SCALAR_EVENT:
+ return yaml_emitter_emit_scalar(emitter, event)
+ case yaml_SEQUENCE_START_EVENT:
+ return yaml_emitter_emit_sequence_start(emitter, event)
+ case yaml_MAPPING_START_EVENT:
+ return yaml_emitter_emit_mapping_start(emitter, event)
+ default:
+ return yaml_emitter_set_emitter_error(emitter,
+ fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ))
+ }
+}
+
+// Expect ALIAS.
+func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+}
+
+// Expect SCALAR.
+func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_select_scalar_style(emitter, event) {
+ return false
+ }
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false) {
+ return false
+ }
+ if !yaml_emitter_process_scalar(emitter) {
+ return false
+ }
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+}
+
+// Expect SEQUENCE-START.
+func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE ||
+ yaml_emitter_check_empty_sequence(emitter) {
+ emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
+ } else {
+ emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
+ }
+ return true
+}
+
+// Expect MAPPING-START.
+func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE ||
+ yaml_emitter_check_empty_mapping(emitter) {
+ emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
+ } else {
+ emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
+ }
+ return true
+}
+
+// Check if the document content is an empty scalar.
+func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool {
+ return false // [Go] Huh?
+}
+
+// Check if the next events represent an empty sequence.
+func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool {
+ if len(emitter.events)-emitter.events_head < 2 {
+ return false
+ }
+ return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT &&
+ emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT
+}
+
+// Check if the next events represent an empty mapping.
+func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool {
+ if len(emitter.events)-emitter.events_head < 2 {
+ return false
+ }
+ return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT &&
+ emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT
+}
+
+// Check if the next node can be expressed as a simple key.
+func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool {
+ length := 0
+ switch emitter.events[emitter.events_head].typ {
+ case yaml_ALIAS_EVENT:
+ length += len(emitter.anchor_data.anchor)
+ case yaml_SCALAR_EVENT:
+ if emitter.scalar_data.multiline {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix) +
+ len(emitter.scalar_data.value)
+ case yaml_SEQUENCE_START_EVENT:
+ if !yaml_emitter_check_empty_sequence(emitter) {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix)
+ case yaml_MAPPING_START_EVENT:
+ if !yaml_emitter_check_empty_mapping(emitter) {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix)
+ default:
+ return false
+ }
+ return length <= 128
+}
+
+// Determine an acceptable scalar style.
+func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+ no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0
+ if no_tag && !event.implicit && !event.quoted_implicit {
+ return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified")
+ }
+
+ style := event.scalar_style()
+ if style == yaml_ANY_SCALAR_STYLE {
+ style = yaml_PLAIN_SCALAR_STYLE
+ }
+ if emitter.canonical {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ if emitter.simple_key_context && emitter.scalar_data.multiline {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+
+ if style == yaml_PLAIN_SCALAR_STYLE {
+ if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed ||
+ emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ if no_tag && !event.implicit {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ }
+ if style == yaml_SINGLE_QUOTED_SCALAR_STYLE {
+ if !emitter.scalar_data.single_quoted_allowed {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ }
+ if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE {
+ if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ }
+
+ if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE {
+ emitter.tag_data.handle = []byte{'!'}
+ }
+ emitter.scalar_data.style = style
+ return true
+}
+
+// Write an anchor.
+func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
+ if emitter.anchor_data.anchor == nil {
+ return true
+ }
+ c := []byte{'&'}
+ if emitter.anchor_data.alias {
+ c[0] = '*'
+ }
+ if !yaml_emitter_write_indicator(emitter, c, true, false, false) {
+ return false
+ }
+ return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor)
+}
+
+// Write a tag.
+func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
+ if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 {
+ return true
+ }
+ if len(emitter.tag_data.handle) > 0 {
+ if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) {
+ return false
+ }
+ if len(emitter.tag_data.suffix) > 0 {
+ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+ return false
+ }
+ }
+ } else {
+ // [Go] Allocate these slices elsewhere.
+ if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) {
+ return false
+ }
+ }
+ return true
+}
+
+// Write a scalar.
+func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
+ switch emitter.scalar_data.style {
+ case yaml_PLAIN_SCALAR_STYLE:
+ return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_SINGLE_QUOTED_SCALAR_STYLE:
+ return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_DOUBLE_QUOTED_SCALAR_STYLE:
+ return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_LITERAL_SCALAR_STYLE:
+ return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value)
+
+ case yaml_FOLDED_SCALAR_STYLE:
+ return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value)
+ }
+ panic("unknown scalar style")
+}
+
+// Write a head comment.
+func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool {
+ if len(emitter.tail_comment) > 0 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.tail_comment) {
+ return false
+ }
+ emitter.tail_comment = emitter.tail_comment[:0]
+ emitter.foot_indent = emitter.indent
+ if emitter.foot_indent < 0 {
+ emitter.foot_indent = 0
+ }
+ }
+
+ if len(emitter.head_comment) == 0 {
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.head_comment) {
+ return false
+ }
+ emitter.head_comment = emitter.head_comment[:0]
+ return true
+}
+
+// Write an line comment.
+func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool {
+ if len(emitter.line_comment) == 0 {
+ return true
+ }
+ if !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.line_comment) {
+ return false
+ }
+ emitter.line_comment = emitter.line_comment[:0]
+ return true
+}
+
+// Write a foot comment.
+func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool {
+ if len(emitter.foot_comment) == 0 {
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.foot_comment) {
+ return false
+ }
+ emitter.foot_comment = emitter.foot_comment[:0]
+ emitter.foot_indent = emitter.indent
+ if emitter.foot_indent < 0 {
+ emitter.foot_indent = 0
+ }
+ return true
+}
+
+// Check if a %YAML directive is valid.
+func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool {
+ if version_directive.major != 1 || version_directive.minor != 1 {
+ return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive")
+ }
+ return true
+}
+
+// Check if a %TAG directive is valid.
+func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool {
+ handle := tag_directive.handle
+ prefix := tag_directive.prefix
+ if len(handle) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty")
+ }
+ if handle[0] != '!' {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'")
+ }
+ if handle[len(handle)-1] != '!' {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'")
+ }
+ for i := 1; i < len(handle)-1; i += width(handle[i]) {
+ if !is_alpha(handle, i) {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only")
+ }
+ }
+ if len(prefix) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty")
+ }
+ return true
+}
+
+// Check if an anchor is valid.
+func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool {
+ if len(anchor) == 0 {
+ problem := "anchor value must not be empty"
+ if alias {
+ problem = "alias value must not be empty"
+ }
+ return yaml_emitter_set_emitter_error(emitter, problem)
+ }
+ for i := 0; i < len(anchor); i += width(anchor[i]) {
+ if !is_alpha(anchor, i) {
+ problem := "anchor value must contain alphanumerical characters only"
+ if alias {
+ problem = "alias value must contain alphanumerical characters only"
+ }
+ return yaml_emitter_set_emitter_error(emitter, problem)
+ }
+ }
+ emitter.anchor_data.anchor = anchor
+ emitter.anchor_data.alias = alias
+ return true
+}
+
+// Check if a tag is valid.
+func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
+ if len(tag) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty")
+ }
+ for i := 0; i < len(emitter.tag_directives); i++ {
+ tag_directive := &emitter.tag_directives[i]
+ if bytes.HasPrefix(tag, tag_directive.prefix) {
+ emitter.tag_data.handle = tag_directive.handle
+ emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
+ return true
+ }
+ }
+ emitter.tag_data.suffix = tag
+ return true
+}
+
+// Check if a scalar is valid.
+func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ var (
+ block_indicators = false
+ flow_indicators = false
+ line_breaks = false
+ special_characters = false
+ tab_characters = false
+
+ leading_space = false
+ leading_break = false
+ trailing_space = false
+ trailing_break = false
+ break_space = false
+ space_break = false
+
+ preceded_by_whitespace = false
+ followed_by_whitespace = false
+ previous_space = false
+ previous_break = false
+ )
+
+ emitter.scalar_data.value = value
+
+ if len(value) == 0 {
+ emitter.scalar_data.multiline = false
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = true
+ emitter.scalar_data.single_quoted_allowed = true
+ emitter.scalar_data.block_allowed = false
+ return true
+ }
+
+ if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) {
+ block_indicators = true
+ flow_indicators = true
+ }
+
+ preceded_by_whitespace = true
+ for i, w := 0, 0; i < len(value); i += w {
+ w = width(value[i])
+ followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w)
+
+ if i == 0 {
+ switch value[i] {
+ case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`':
+ flow_indicators = true
+ block_indicators = true
+ case '?', ':':
+ flow_indicators = true
+ if followed_by_whitespace {
+ block_indicators = true
+ }
+ case '-':
+ if followed_by_whitespace {
+ flow_indicators = true
+ block_indicators = true
+ }
+ }
+ } else {
+ switch value[i] {
+ case ',', '?', '[', ']', '{', '}':
+ flow_indicators = true
+ case ':':
+ flow_indicators = true
+ if followed_by_whitespace {
+ block_indicators = true
+ }
+ case '#':
+ if preceded_by_whitespace {
+ flow_indicators = true
+ block_indicators = true
+ }
+ }
+ }
+
+ if value[i] == '\t' {
+ tab_characters = true
+ } else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode {
+ special_characters = true
+ }
+ if is_space(value, i) {
+ if i == 0 {
+ leading_space = true
+ }
+ if i+width(value[i]) == len(value) {
+ trailing_space = true
+ }
+ if previous_break {
+ break_space = true
+ }
+ previous_space = true
+ previous_break = false
+ } else if is_break(value, i) {
+ line_breaks = true
+ if i == 0 {
+ leading_break = true
+ }
+ if i+width(value[i]) == len(value) {
+ trailing_break = true
+ }
+ if previous_space {
+ space_break = true
+ }
+ previous_space = false
+ previous_break = true
+ } else {
+ previous_space = false
+ previous_break = false
+ }
+
+ // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition.
+ preceded_by_whitespace = is_blankz(value, i)
+ }
+
+ emitter.scalar_data.multiline = line_breaks
+ emitter.scalar_data.flow_plain_allowed = true
+ emitter.scalar_data.block_plain_allowed = true
+ emitter.scalar_data.single_quoted_allowed = true
+ emitter.scalar_data.block_allowed = true
+
+ if leading_space || leading_break || trailing_space || trailing_break {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ if trailing_space {
+ emitter.scalar_data.block_allowed = false
+ }
+ if break_space {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ emitter.scalar_data.single_quoted_allowed = false
+ }
+ if space_break || tab_characters || special_characters {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ emitter.scalar_data.single_quoted_allowed = false
+ }
+ if space_break || special_characters {
+ emitter.scalar_data.block_allowed = false
+ }
+ if line_breaks {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ if flow_indicators {
+ emitter.scalar_data.flow_plain_allowed = false
+ }
+ if block_indicators {
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ return true
+}
+
+// Check if the event data is valid.
+func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+ emitter.anchor_data.anchor = nil
+ emitter.tag_data.handle = nil
+ emitter.tag_data.suffix = nil
+ emitter.scalar_data.value = nil
+
+ if len(event.head_comment) > 0 {
+ emitter.head_comment = event.head_comment
+ }
+ if len(event.line_comment) > 0 {
+ emitter.line_comment = event.line_comment
+ }
+ if len(event.foot_comment) > 0 {
+ emitter.foot_comment = event.foot_comment
+ }
+ if len(event.tail_comment) > 0 {
+ emitter.tail_comment = event.tail_comment
+ }
+
+ switch event.typ {
+ case yaml_ALIAS_EVENT:
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) {
+ return false
+ }
+
+ case yaml_SCALAR_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+ if !yaml_emitter_analyze_scalar(emitter, event.value) {
+ return false
+ }
+
+ case yaml_SEQUENCE_START_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+
+ case yaml_MAPPING_START_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+// Write the BOM character.
+func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool {
+ if !flush(emitter) {
+ return false
+ }
+ pos := emitter.buffer_pos
+ emitter.buffer[pos+0] = '\xEF'
+ emitter.buffer[pos+1] = '\xBB'
+ emitter.buffer[pos+2] = '\xBF'
+ emitter.buffer_pos += 3
+ return true
+}
+
+func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
+ indent := emitter.indent
+ if indent < 0 {
+ indent = 0
+ }
+ if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ if emitter.foot_indent == indent {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ for emitter.column < indent {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ emitter.whitespace = true
+ //emitter.indention = true
+ emitter.space_above = false
+ emitter.foot_indent = -1
+ return true
+}
+
+func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool {
+ if need_whitespace && !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !write_all(emitter, indicator) {
+ return false
+ }
+ emitter.whitespace = is_whitespace
+ emitter.indention = (emitter.indention && is_indention)
+ emitter.open_ended = false
+ return true
+}
+
+func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool {
+ if !write_all(emitter, value) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool {
+ if !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !write_all(emitter, value) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool {
+ if need_whitespace && !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ for i := 0; i < len(value); {
+ var must_write bool
+ switch value[i] {
+ case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']':
+ must_write = true
+ default:
+ must_write = is_alpha(value, i)
+ }
+ if must_write {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ } else {
+ w := width(value[i])
+ for k := 0; k < w; k++ {
+ octet := value[i]
+ i++
+ if !put(emitter, '%') {
+ return false
+ }
+
+ c := octet >> 4
+ if c < 10 {
+ c += '0'
+ } else {
+ c += 'A' - 10
+ }
+ if !put(emitter, c) {
+ return false
+ }
+
+ c = octet & 0x0f
+ if c < 10 {
+ c += '0'
+ } else {
+ c += 'A' - 10
+ }
+ if !put(emitter, c) {
+ return false
+ }
+ }
+ }
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+ if len(value) > 0 && !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+
+ spaces := false
+ breaks := false
+ for i := 0; i < len(value); {
+ if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ spaces = true
+ } else if is_break(value, i) {
+ if !breaks && value[i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ spaces = false
+ breaks = false
+ }
+ }
+
+ if len(value) > 0 {
+ emitter.whitespace = false
+ }
+ emitter.indention = false
+ if emitter.root_context {
+ emitter.open_ended = true
+ }
+
+ return true
+}
+
+func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+
+ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) {
+ return false
+ }
+
+ spaces := false
+ breaks := false
+ for i := 0; i < len(value); {
+ if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ spaces = true
+ } else if is_break(value, i) {
+ if !breaks && value[i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if value[i] == '\'' {
+ if !put(emitter, '\'') {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ spaces = false
+ breaks = false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+ spaces := false
+ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) {
+ return false
+ }
+
+ for i := 0; i < len(value); {
+ if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) ||
+ is_bom(value, i) || is_break(value, i) ||
+ value[i] == '"' || value[i] == '\\' {
+
+ octet := value[i]
+
+ var w int
+ var v rune
+ switch {
+ case octet&0x80 == 0x00:
+ w, v = 1, rune(octet&0x7F)
+ case octet&0xE0 == 0xC0:
+ w, v = 2, rune(octet&0x1F)
+ case octet&0xF0 == 0xE0:
+ w, v = 3, rune(octet&0x0F)
+ case octet&0xF8 == 0xF0:
+ w, v = 4, rune(octet&0x07)
+ }
+ for k := 1; k < w; k++ {
+ octet = value[i+k]
+ v = (v << 6) + (rune(octet) & 0x3F)
+ }
+ i += w
+
+ if !put(emitter, '\\') {
+ return false
+ }
+
+ var ok bool
+ switch v {
+ case 0x00:
+ ok = put(emitter, '0')
+ case 0x07:
+ ok = put(emitter, 'a')
+ case 0x08:
+ ok = put(emitter, 'b')
+ case 0x09:
+ ok = put(emitter, 't')
+ case 0x0A:
+ ok = put(emitter, 'n')
+ case 0x0b:
+ ok = put(emitter, 'v')
+ case 0x0c:
+ ok = put(emitter, 'f')
+ case 0x0d:
+ ok = put(emitter, 'r')
+ case 0x1b:
+ ok = put(emitter, 'e')
+ case 0x22:
+ ok = put(emitter, '"')
+ case 0x5c:
+ ok = put(emitter, '\\')
+ case 0x85:
+ ok = put(emitter, 'N')
+ case 0xA0:
+ ok = put(emitter, '_')
+ case 0x2028:
+ ok = put(emitter, 'L')
+ case 0x2029:
+ ok = put(emitter, 'P')
+ default:
+ if v <= 0xFF {
+ ok = put(emitter, 'x')
+ w = 2
+ } else if v <= 0xFFFF {
+ ok = put(emitter, 'u')
+ w = 4
+ } else {
+ ok = put(emitter, 'U')
+ w = 8
+ }
+ for k := (w - 1) * 4; ok && k >= 0; k -= 4 {
+ digit := byte((v >> uint(k)) & 0x0F)
+ if digit < 10 {
+ ok = put(emitter, digit+'0')
+ } else {
+ ok = put(emitter, digit+'A'-10)
+ }
+ }
+ }
+ if !ok {
+ return false
+ }
+ spaces = false
+ } else if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if is_space(value, i+1) {
+ if !put(emitter, '\\') {
+ return false
+ }
+ }
+ i += width(value[i])
+ } else if !write(emitter, value, &i) {
+ return false
+ }
+ spaces = true
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ spaces = false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool {
+ if is_space(value, 0) || is_break(value, 0) {
+ indent_hint := []byte{'0' + byte(emitter.best_indent)}
+ if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) {
+ return false
+ }
+ }
+
+ emitter.open_ended = false
+
+ var chomp_hint [1]byte
+ if len(value) == 0 {
+ chomp_hint[0] = '-'
+ } else {
+ i := len(value) - 1
+ for value[i]&0xC0 == 0x80 {
+ i--
+ }
+ if !is_break(value, i) {
+ chomp_hint[0] = '-'
+ } else if i == 0 {
+ chomp_hint[0] = '+'
+ emitter.open_ended = true
+ } else {
+ i--
+ for value[i]&0xC0 == 0x80 {
+ i--
+ }
+ if is_break(value, i) {
+ chomp_hint[0] = '+'
+ emitter.open_ended = true
+ }
+ }
+ }
+ if chomp_hint[0] != 0 {
+ if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) {
+ return false
+ }
+ }
+ return true
+}
+
+func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ //emitter.indention = true
+ emitter.whitespace = true
+ breaks := true
+ for i := 0; i < len(value); {
+ if is_break(value, i) {
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+
+ return true
+}
+
+func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+
+ //emitter.indention = true
+ emitter.whitespace = true
+
+ breaks := true
+ leading_spaces := true
+ for i := 0; i < len(value); {
+ if is_break(value, i) {
+ if !breaks && !leading_spaces && value[i] == '\n' {
+ k := 0
+ for is_break(value, k) {
+ k += width(value[k])
+ }
+ if !is_blankz(value, k) {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ leading_spaces = is_blank(value, i)
+ }
+ if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+ return true
+}
+
+func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool {
+ breaks := false
+ pound := false
+ for i := 0; i < len(comment); {
+ if is_break(comment, i) {
+ if !write_break(emitter, comment, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ pound = false
+ } else {
+ if breaks && !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !pound {
+ if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) {
+ return false
+ }
+ pound = true
+ }
+ if !write(emitter, comment, &i) {
+ return false
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+ if !breaks && !put_break(emitter) {
+ return false
+ }
+
+ emitter.whitespace = true
+ //emitter.indention = true
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v3/encode.go b/vendor/gopkg.in/yaml.v3/encode.go
new file mode 100644
index 0000000..de9e72a
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/encode.go
@@ -0,0 +1,577 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// 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 yaml
+
+import (
+ "encoding"
+ "fmt"
+ "io"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+)
+
+type encoder struct {
+ emitter yaml_emitter_t
+ event yaml_event_t
+ out []byte
+ flow bool
+ indent int
+ doneInit bool
+}
+
+func newEncoder() *encoder {
+ e := &encoder{}
+ yaml_emitter_initialize(&e.emitter)
+ yaml_emitter_set_output_string(&e.emitter, &e.out)
+ yaml_emitter_set_unicode(&e.emitter, true)
+ return e
+}
+
+func newEncoderWithWriter(w io.Writer) *encoder {
+ e := &encoder{}
+ yaml_emitter_initialize(&e.emitter)
+ yaml_emitter_set_output_writer(&e.emitter, w)
+ yaml_emitter_set_unicode(&e.emitter, true)
+ return e
+}
+
+func (e *encoder) init() {
+ if e.doneInit {
+ return
+ }
+ if e.indent == 0 {
+ e.indent = 4
+ }
+ e.emitter.best_indent = e.indent
+ yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
+ e.emit()
+ e.doneInit = true
+}
+
+func (e *encoder) finish() {
+ e.emitter.open_ended = false
+ yaml_stream_end_event_initialize(&e.event)
+ e.emit()
+}
+
+func (e *encoder) destroy() {
+ yaml_emitter_delete(&e.emitter)
+}
+
+func (e *encoder) emit() {
+ // This will internally delete the e.event value.
+ e.must(yaml_emitter_emit(&e.emitter, &e.event))
+}
+
+func (e *encoder) must(ok bool) {
+ if !ok {
+ msg := e.emitter.problem
+ if msg == "" {
+ msg = "unknown problem generating YAML content"
+ }
+ failf("%s", msg)
+ }
+}
+
+func (e *encoder) marshalDoc(tag string, in reflect.Value) {
+ e.init()
+ var node *Node
+ if in.IsValid() {
+ node, _ = in.Interface().(*Node)
+ }
+ if node != nil && node.Kind == DocumentNode {
+ e.nodev(in)
+ } else {
+ yaml_document_start_event_initialize(&e.event, nil, nil, true)
+ e.emit()
+ e.marshal(tag, in)
+ yaml_document_end_event_initialize(&e.event, true)
+ e.emit()
+ }
+}
+
+func (e *encoder) marshal(tag string, in reflect.Value) {
+ tag = shortTag(tag)
+ if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
+ e.nilv()
+ return
+ }
+ iface := in.Interface()
+ switch value := iface.(type) {
+ case *Node:
+ e.nodev(in)
+ return
+ case Node:
+ if !in.CanAddr() {
+ var n = reflect.New(in.Type()).Elem()
+ n.Set(in)
+ in = n
+ }
+ e.nodev(in.Addr())
+ return
+ case time.Time:
+ e.timev(tag, in)
+ return
+ case *time.Time:
+ e.timev(tag, in.Elem())
+ return
+ case time.Duration:
+ e.stringv(tag, reflect.ValueOf(value.String()))
+ return
+ case Marshaler:
+ v, err := value.MarshalYAML()
+ if err != nil {
+ fail(err)
+ }
+ if v == nil {
+ e.nilv()
+ return
+ }
+ e.marshal(tag, reflect.ValueOf(v))
+ return
+ case encoding.TextMarshaler:
+ text, err := value.MarshalText()
+ if err != nil {
+ fail(err)
+ }
+ in = reflect.ValueOf(string(text))
+ case nil:
+ e.nilv()
+ return
+ }
+ switch in.Kind() {
+ case reflect.Interface:
+ e.marshal(tag, in.Elem())
+ case reflect.Map:
+ e.mapv(tag, in)
+ case reflect.Ptr:
+ e.marshal(tag, in.Elem())
+ case reflect.Struct:
+ e.structv(tag, in)
+ case reflect.Slice, reflect.Array:
+ e.slicev(tag, in)
+ case reflect.String:
+ e.stringv(tag, in)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ e.intv(tag, in)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ e.uintv(tag, in)
+ case reflect.Float32, reflect.Float64:
+ e.floatv(tag, in)
+ case reflect.Bool:
+ e.boolv(tag, in)
+ default:
+ panic("cannot marshal type: " + in.Type().String())
+ }
+}
+
+func (e *encoder) mapv(tag string, in reflect.Value) {
+ e.mappingv(tag, func() {
+ keys := keyList(in.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ e.marshal("", k)
+ e.marshal("", in.MapIndex(k))
+ }
+ })
+}
+
+func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) {
+ for _, num := range index {
+ for {
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ return reflect.Value{}
+ }
+ v = v.Elem()
+ continue
+ }
+ break
+ }
+ v = v.Field(num)
+ }
+ return v
+}
+
+func (e *encoder) structv(tag string, in reflect.Value) {
+ sinfo, err := getStructInfo(in.Type())
+ if err != nil {
+ panic(err)
+ }
+ e.mappingv(tag, func() {
+ for _, info := range sinfo.FieldsList {
+ var value reflect.Value
+ if info.Inline == nil {
+ value = in.Field(info.Num)
+ } else {
+ value = e.fieldByIndex(in, info.Inline)
+ if !value.IsValid() {
+ continue
+ }
+ }
+ if info.OmitEmpty && isZero(value) {
+ continue
+ }
+ e.marshal("", reflect.ValueOf(info.Key))
+ e.flow = info.Flow
+ e.marshal("", value)
+ }
+ if sinfo.InlineMap >= 0 {
+ m := in.Field(sinfo.InlineMap)
+ if m.Len() > 0 {
+ e.flow = false
+ keys := keyList(m.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ if _, found := sinfo.FieldsMap[k.String()]; found {
+ panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String()))
+ }
+ e.marshal("", k)
+ e.flow = false
+ e.marshal("", m.MapIndex(k))
+ }
+ }
+ }
+ })
+}
+
+func (e *encoder) mappingv(tag string, f func()) {
+ implicit := tag == ""
+ style := yaml_BLOCK_MAPPING_STYLE
+ if e.flow {
+ e.flow = false
+ style = yaml_FLOW_MAPPING_STYLE
+ }
+ yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
+ e.emit()
+ f()
+ yaml_mapping_end_event_initialize(&e.event)
+ e.emit()
+}
+
+func (e *encoder) slicev(tag string, in reflect.Value) {
+ implicit := tag == ""
+ style := yaml_BLOCK_SEQUENCE_STYLE
+ if e.flow {
+ e.flow = false
+ style = yaml_FLOW_SEQUENCE_STYLE
+ }
+ e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
+ e.emit()
+ n := in.Len()
+ for i := 0; i < n; i++ {
+ e.marshal("", in.Index(i))
+ }
+ e.must(yaml_sequence_end_event_initialize(&e.event))
+ e.emit()
+}
+
+// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
+//
+// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
+// in YAML 1.2 and by this package, but these should be marshalled quoted for
+// the time being for compatibility with other parsers.
+func isBase60Float(s string) (result bool) {
+ // Fast path.
+ if s == "" {
+ return false
+ }
+ c := s[0]
+ if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
+ return false
+ }
+ // Do the full match.
+ return base60float.MatchString(s)
+}
+
+// From http://yaml.org/type/float.html, except the regular expression there
+// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
+var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
+
+// isOldBool returns whether s is bool notation as defined in YAML 1.1.
+//
+// We continue to force strings that YAML 1.1 would interpret as booleans to be
+// rendered as quotes strings so that the marshalled output valid for YAML 1.1
+// parsing.
+func isOldBool(s string) (result bool) {
+ switch s {
+ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON",
+ "n", "N", "no", "No", "NO", "off", "Off", "OFF":
+ return true
+ default:
+ return false
+ }
+}
+
+func (e *encoder) stringv(tag string, in reflect.Value) {
+ var style yaml_scalar_style_t
+ s := in.String()
+ canUsePlain := true
+ switch {
+ case !utf8.ValidString(s):
+ if tag == binaryTag {
+ failf("explicitly tagged !!binary data must be base64-encoded")
+ }
+ if tag != "" {
+ failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
+ }
+ // It can't be encoded directly as YAML so use a binary tag
+ // and encode it as base64.
+ tag = binaryTag
+ s = encodeBase64(s)
+ case tag == "":
+ // Check to see if it would resolve to a specific
+ // tag when encoded unquoted. If it doesn't,
+ // there's no need to quote it.
+ rtag, _ := resolve("", s)
+ canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s))
+ }
+ // Note: it's possible for user code to emit invalid YAML
+ // if they explicitly specify a tag and a string containing
+ // text that's incompatible with that tag.
+ switch {
+ case strings.Contains(s, "\n"):
+ if e.flow {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ } else {
+ style = yaml_LITERAL_SCALAR_STYLE
+ }
+ case canUsePlain:
+ style = yaml_PLAIN_SCALAR_STYLE
+ default:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ e.emitScalar(s, "", tag, style, nil, nil, nil, nil)
+}
+
+func (e *encoder) boolv(tag string, in reflect.Value) {
+ var s string
+ if in.Bool() {
+ s = "true"
+ } else {
+ s = "false"
+ }
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) intv(tag string, in reflect.Value) {
+ s := strconv.FormatInt(in.Int(), 10)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) uintv(tag string, in reflect.Value) {
+ s := strconv.FormatUint(in.Uint(), 10)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) timev(tag string, in reflect.Value) {
+ t := in.Interface().(time.Time)
+ s := t.Format(time.RFC3339Nano)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) floatv(tag string, in reflect.Value) {
+ // Issue #352: When formatting, use the precision of the underlying value
+ precision := 64
+ if in.Kind() == reflect.Float32 {
+ precision = 32
+ }
+
+ s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
+ switch s {
+ case "+Inf":
+ s = ".inf"
+ case "-Inf":
+ s = "-.inf"
+ case "NaN":
+ s = ".nan"
+ }
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) nilv() {
+ e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) {
+ // TODO Kill this function. Replace all initialize calls by their underlining Go literals.
+ implicit := tag == ""
+ if !implicit {
+ tag = longTag(tag)
+ }
+ e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
+ e.event.head_comment = head
+ e.event.line_comment = line
+ e.event.foot_comment = foot
+ e.event.tail_comment = tail
+ e.emit()
+}
+
+func (e *encoder) nodev(in reflect.Value) {
+ e.node(in.Interface().(*Node), "")
+}
+
+func (e *encoder) node(node *Node, tail string) {
+ // Zero nodes behave as nil.
+ if node.Kind == 0 && node.IsZero() {
+ e.nilv()
+ return
+ }
+
+ // If the tag was not explicitly requested, and dropping it won't change the
+ // implicit tag of the value, don't include it in the presentation.
+ var tag = node.Tag
+ var stag = shortTag(tag)
+ var forceQuoting bool
+ if tag != "" && node.Style&TaggedStyle == 0 {
+ if node.Kind == ScalarNode {
+ if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 {
+ tag = ""
+ } else {
+ rtag, _ := resolve("", node.Value)
+ if rtag == stag {
+ tag = ""
+ } else if stag == strTag {
+ tag = ""
+ forceQuoting = true
+ }
+ }
+ } else {
+ var rtag string
+ switch node.Kind {
+ case MappingNode:
+ rtag = mapTag
+ case SequenceNode:
+ rtag = seqTag
+ }
+ if rtag == stag {
+ tag = ""
+ }
+ }
+ }
+
+ switch node.Kind {
+ case DocumentNode:
+ yaml_document_start_event_initialize(&e.event, nil, nil, true)
+ e.event.head_comment = []byte(node.HeadComment)
+ e.emit()
+ for _, node := range node.Content {
+ e.node(node, "")
+ }
+ yaml_document_end_event_initialize(&e.event, true)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case SequenceNode:
+ style := yaml_BLOCK_SEQUENCE_STYLE
+ if node.Style&FlowStyle != 0 {
+ style = yaml_FLOW_SEQUENCE_STYLE
+ }
+ e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style))
+ e.event.head_comment = []byte(node.HeadComment)
+ e.emit()
+ for _, node := range node.Content {
+ e.node(node, "")
+ }
+ e.must(yaml_sequence_end_event_initialize(&e.event))
+ e.event.line_comment = []byte(node.LineComment)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case MappingNode:
+ style := yaml_BLOCK_MAPPING_STYLE
+ if node.Style&FlowStyle != 0 {
+ style = yaml_FLOW_MAPPING_STYLE
+ }
+ yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)
+ e.event.tail_comment = []byte(tail)
+ e.event.head_comment = []byte(node.HeadComment)
+ e.emit()
+
+ // The tail logic below moves the foot comment of prior keys to the following key,
+ // since the value for each key may be a nested structure and the foot needs to be
+ // processed only the entirety of the value is streamed. The last tail is processed
+ // with the mapping end event.
+ var tail string
+ for i := 0; i+1 < len(node.Content); i += 2 {
+ k := node.Content[i]
+ foot := k.FootComment
+ if foot != "" {
+ kopy := *k
+ kopy.FootComment = ""
+ k = &kopy
+ }
+ e.node(k, tail)
+ tail = foot
+
+ v := node.Content[i+1]
+ e.node(v, "")
+ }
+
+ yaml_mapping_end_event_initialize(&e.event)
+ e.event.tail_comment = []byte(tail)
+ e.event.line_comment = []byte(node.LineComment)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case AliasNode:
+ yaml_alias_event_initialize(&e.event, []byte(node.Value))
+ e.event.head_comment = []byte(node.HeadComment)
+ e.event.line_comment = []byte(node.LineComment)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case ScalarNode:
+ value := node.Value
+ if !utf8.ValidString(value) {
+ if stag == binaryTag {
+ failf("explicitly tagged !!binary data must be base64-encoded")
+ }
+ if stag != "" {
+ failf("cannot marshal invalid UTF-8 data as %s", stag)
+ }
+ // It can't be encoded directly as YAML so use a binary tag
+ // and encode it as base64.
+ tag = binaryTag
+ value = encodeBase64(value)
+ }
+
+ style := yaml_PLAIN_SCALAR_STYLE
+ switch {
+ case node.Style&DoubleQuotedStyle != 0:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ case node.Style&SingleQuotedStyle != 0:
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ case node.Style&LiteralStyle != 0:
+ style = yaml_LITERAL_SCALAR_STYLE
+ case node.Style&FoldedStyle != 0:
+ style = yaml_FOLDED_SCALAR_STYLE
+ case strings.Contains(value, "\n"):
+ style = yaml_LITERAL_SCALAR_STYLE
+ case forceQuoting:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+
+ e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail))
+ default:
+ failf("cannot encode node with unknown kind %d", node.Kind)
+ }
+}
diff --git a/vendor/gopkg.in/yaml.v3/go.mod b/vendor/gopkg.in/yaml.v3/go.mod
new file mode 100644
index 0000000..f407ea3
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/go.mod
@@ -0,0 +1,5 @@
+module "gopkg.in/yaml.v3"
+
+require (
+ "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405
+)
diff --git a/vendor/gopkg.in/yaml.v3/parserc.go b/vendor/gopkg.in/yaml.v3/parserc.go
new file mode 100644
index 0000000..268558a
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/parserc.go
@@ -0,0 +1,1258 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "bytes"
+)
+
+// The parser implements the following grammar:
+//
+// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+// implicit_document ::= block_node DOCUMENT-END*
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// block_node_or_indentless_sequence ::=
+// ALIAS
+// | properties (block_content | indentless_block_sequence)?
+// | block_content
+// | indentless_block_sequence
+// block_node ::= ALIAS
+// | properties block_content?
+// | block_content
+// flow_node ::= ALIAS
+// | properties flow_content?
+// | flow_content
+// properties ::= TAG ANCHOR? | ANCHOR TAG?
+// block_content ::= block_collection | flow_collection | SCALAR
+// flow_content ::= flow_collection | SCALAR
+// block_collection ::= block_sequence | block_mapping
+// flow_collection ::= flow_sequence | flow_mapping
+// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+// block_mapping ::= BLOCK-MAPPING_START
+// ((KEY block_node_or_indentless_sequence?)?
+// (VALUE block_node_or_indentless_sequence?)?)*
+// BLOCK-END
+// flow_sequence ::= FLOW-SEQUENCE-START
+// (flow_sequence_entry FLOW-ENTRY)*
+// flow_sequence_entry?
+// FLOW-SEQUENCE-END
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// flow_mapping ::= FLOW-MAPPING-START
+// (flow_mapping_entry FLOW-ENTRY)*
+// flow_mapping_entry?
+// FLOW-MAPPING-END
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+
+// Peek the next token in the token queue.
+func peek_token(parser *yaml_parser_t) *yaml_token_t {
+ if parser.token_available || yaml_parser_fetch_more_tokens(parser) {
+ token := &parser.tokens[parser.tokens_head]
+ yaml_parser_unfold_comments(parser, token)
+ return token
+ }
+ return nil
+}
+
+// yaml_parser_unfold_comments walks through the comments queue and joins all
+// comments behind the position of the provided token into the respective
+// top-level comment slices in the parser.
+func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) {
+ for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index {
+ comment := &parser.comments[parser.comments_head]
+ if len(comment.head) > 0 {
+ if token.typ == yaml_BLOCK_END_TOKEN {
+ // No heads on ends, so keep comment.head for a follow up token.
+ break
+ }
+ if len(parser.head_comment) > 0 {
+ parser.head_comment = append(parser.head_comment, '\n')
+ }
+ parser.head_comment = append(parser.head_comment, comment.head...)
+ }
+ if len(comment.foot) > 0 {
+ if len(parser.foot_comment) > 0 {
+ parser.foot_comment = append(parser.foot_comment, '\n')
+ }
+ parser.foot_comment = append(parser.foot_comment, comment.foot...)
+ }
+ if len(comment.line) > 0 {
+ if len(parser.line_comment) > 0 {
+ parser.line_comment = append(parser.line_comment, '\n')
+ }
+ parser.line_comment = append(parser.line_comment, comment.line...)
+ }
+ *comment = yaml_comment_t{}
+ parser.comments_head++
+ }
+}
+
+// Remove the next token from the queue (must be called after peek_token).
+func skip_token(parser *yaml_parser_t) {
+ parser.token_available = false
+ parser.tokens_parsed++
+ parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN
+ parser.tokens_head++
+}
+
+// Get the next event.
+func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool {
+ // Erase the event object.
+ *event = yaml_event_t{}
+
+ // No events after the end of the stream or error.
+ if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE {
+ return true
+ }
+
+ // Generate the next event.
+ return yaml_parser_state_machine(parser, event)
+}
+
+// Set parser error.
+func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool {
+ parser.error = yaml_PARSER_ERROR
+ parser.problem = problem
+ parser.problem_mark = problem_mark
+ return false
+}
+
+func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool {
+ parser.error = yaml_PARSER_ERROR
+ parser.context = context
+ parser.context_mark = context_mark
+ parser.problem = problem
+ parser.problem_mark = problem_mark
+ return false
+}
+
+// State dispatcher.
+func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool {
+ //trace("yaml_parser_state_machine", "state:", parser.state.String())
+
+ switch parser.state {
+ case yaml_PARSE_STREAM_START_STATE:
+ return yaml_parser_parse_stream_start(parser, event)
+
+ case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+ return yaml_parser_parse_document_start(parser, event, true)
+
+ case yaml_PARSE_DOCUMENT_START_STATE:
+ return yaml_parser_parse_document_start(parser, event, false)
+
+ case yaml_PARSE_DOCUMENT_CONTENT_STATE:
+ return yaml_parser_parse_document_content(parser, event)
+
+ case yaml_PARSE_DOCUMENT_END_STATE:
+ return yaml_parser_parse_document_end(parser, event)
+
+ case yaml_PARSE_BLOCK_NODE_STATE:
+ return yaml_parser_parse_node(parser, event, true, false)
+
+ case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+ return yaml_parser_parse_node(parser, event, true, true)
+
+ case yaml_PARSE_FLOW_NODE_STATE:
+ return yaml_parser_parse_node(parser, event, false, false)
+
+ case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+ return yaml_parser_parse_block_sequence_entry(parser, event, true)
+
+ case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_block_sequence_entry(parser, event, false)
+
+ case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_indentless_sequence_entry(parser, event)
+
+ case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return yaml_parser_parse_block_mapping_key(parser, event, true)
+
+ case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
+ return yaml_parser_parse_block_mapping_key(parser, event, false)
+
+ case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_block_mapping_value(parser, event)
+
+ case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+ return yaml_parser_parse_flow_sequence_entry(parser, event, true)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_flow_sequence_entry(parser, event, false)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event)
+
+ case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+ return yaml_parser_parse_flow_mapping_key(parser, event, true)
+
+ case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
+ return yaml_parser_parse_flow_mapping_key(parser, event, false)
+
+ case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_flow_mapping_value(parser, event, false)
+
+ case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+ return yaml_parser_parse_flow_mapping_value(parser, event, true)
+
+ default:
+ panic("invalid parser state")
+ }
+}
+
+// Parse the production:
+// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+// ************
+func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_STREAM_START_TOKEN {
+ return yaml_parser_set_parser_error(parser, "did not find expected <stream-start>", token.start_mark)
+ }
+ parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE
+ *event = yaml_event_t{
+ typ: yaml_STREAM_START_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ encoding: token.encoding,
+ }
+ skip_token(parser)
+ return true
+}
+
+// Parse the productions:
+// implicit_document ::= block_node DOCUMENT-END*
+// *
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// *************************
+func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ // Parse extra document end indicators.
+ if !implicit {
+ for token.typ == yaml_DOCUMENT_END_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+ }
+
+ if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN &&
+ token.typ != yaml_TAG_DIRECTIVE_TOKEN &&
+ token.typ != yaml_DOCUMENT_START_TOKEN &&
+ token.typ != yaml_STREAM_END_TOKEN {
+ // Parse an implicit document.
+ if !yaml_parser_process_directives(parser, nil, nil) {
+ return false
+ }
+ parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
+ parser.state = yaml_PARSE_BLOCK_NODE_STATE
+
+ var head_comment []byte
+ if len(parser.head_comment) > 0 {
+ // [Go] Scan the header comment backwards, and if an empty line is found, break
+ // the header so the part before the last empty line goes into the
+ // document header, while the bottom of it goes into a follow up event.
+ for i := len(parser.head_comment) - 1; i > 0; i-- {
+ if parser.head_comment[i] == '\n' {
+ if i == len(parser.head_comment)-1 {
+ head_comment = parser.head_comment[:i]
+ parser.head_comment = parser.head_comment[i+1:]
+ break
+ } else if parser.head_comment[i-1] == '\n' {
+ head_comment = parser.head_comment[:i-1]
+ parser.head_comment = parser.head_comment[i+1:]
+ break
+ }
+ }
+ }
+ }
+
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_START_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+
+ head_comment: head_comment,
+ }
+
+ } else if token.typ != yaml_STREAM_END_TOKEN {
+ // Parse an explicit document.
+ var version_directive *yaml_version_directive_t
+ var tag_directives []yaml_tag_directive_t
+ start_mark := token.start_mark
+ if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) {
+ return false
+ }
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_DOCUMENT_START_TOKEN {
+ yaml_parser_set_parser_error(parser,
+ "did not find expected <document start>", token.start_mark)
+ return false
+ }
+ parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
+ parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE
+ end_mark := token.end_mark
+
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ version_directive: version_directive,
+ tag_directives: tag_directives,
+ implicit: false,
+ }
+ skip_token(parser)
+
+ } else {
+ // Parse the stream end.
+ parser.state = yaml_PARSE_END_STATE
+ *event = yaml_event_t{
+ typ: yaml_STREAM_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ skip_token(parser)
+ }
+
+ return true
+}
+
+// Parse the productions:
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// ***********
+//
+func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_VERSION_DIRECTIVE_TOKEN ||
+ token.typ == yaml_TAG_DIRECTIVE_TOKEN ||
+ token.typ == yaml_DOCUMENT_START_TOKEN ||
+ token.typ == yaml_DOCUMENT_END_TOKEN ||
+ token.typ == yaml_STREAM_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ return yaml_parser_process_empty_scalar(parser, event,
+ token.start_mark)
+ }
+ return yaml_parser_parse_node(parser, event, true, false)
+}
+
+// Parse the productions:
+// implicit_document ::= block_node DOCUMENT-END*
+// *************
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+//
+func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ start_mark := token.start_mark
+ end_mark := token.start_mark
+
+ implicit := true
+ if token.typ == yaml_DOCUMENT_END_TOKEN {
+ end_mark = token.end_mark
+ skip_token(parser)
+ implicit = false
+ }
+
+ parser.tag_directives = parser.tag_directives[:0]
+
+ parser.state = yaml_PARSE_DOCUMENT_START_STATE
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_END_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ implicit: implicit,
+ }
+ yaml_parser_set_event_comments(parser, event)
+ if len(event.head_comment) > 0 && len(event.foot_comment) == 0 {
+ event.foot_comment = event.head_comment
+ event.head_comment = nil
+ }
+ return true
+}
+
+func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) {
+ event.head_comment = parser.head_comment
+ event.line_comment = parser.line_comment
+ event.foot_comment = parser.foot_comment
+ parser.head_comment = nil
+ parser.line_comment = nil
+ parser.foot_comment = nil
+ parser.tail_comment = nil
+ parser.stem_comment = nil
+}
+
+// Parse the productions:
+// block_node_or_indentless_sequence ::=
+// ALIAS
+// *****
+// | properties (block_content | indentless_block_sequence)?
+// ********** *
+// | block_content | indentless_block_sequence
+// *
+// block_node ::= ALIAS
+// *****
+// | properties block_content?
+// ********** *
+// | block_content
+// *
+// flow_node ::= ALIAS
+// *****
+// | properties flow_content?
+// ********** *
+// | flow_content
+// *
+// properties ::= TAG ANCHOR? | ANCHOR TAG?
+// *************************
+// block_content ::= block_collection | flow_collection | SCALAR
+// ******
+// flow_content ::= flow_collection | SCALAR
+// ******
+func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
+ //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_ALIAS_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ *event = yaml_event_t{
+ typ: yaml_ALIAS_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ anchor: token.value,
+ }
+ yaml_parser_set_event_comments(parser, event)
+ skip_token(parser)
+ return true
+ }
+
+ start_mark := token.start_mark
+ end_mark := token.start_mark
+
+ var tag_token bool
+ var tag_handle, tag_suffix, anchor []byte
+ var tag_mark yaml_mark_t
+ if token.typ == yaml_ANCHOR_TOKEN {
+ anchor = token.value
+ start_mark = token.start_mark
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_TAG_TOKEN {
+ tag_token = true
+ tag_handle = token.value
+ tag_suffix = token.suffix
+ tag_mark = token.start_mark
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+ } else if token.typ == yaml_TAG_TOKEN {
+ tag_token = true
+ tag_handle = token.value
+ tag_suffix = token.suffix
+ start_mark = token.start_mark
+ tag_mark = token.start_mark
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_ANCHOR_TOKEN {
+ anchor = token.value
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+ }
+
+ var tag []byte
+ if tag_token {
+ if len(tag_handle) == 0 {
+ tag = tag_suffix
+ tag_suffix = nil
+ } else {
+ for i := range parser.tag_directives {
+ if bytes.Equal(parser.tag_directives[i].handle, tag_handle) {
+ tag = append([]byte(nil), parser.tag_directives[i].prefix...)
+ tag = append(tag, tag_suffix...)
+ break
+ }
+ }
+ if len(tag) == 0 {
+ yaml_parser_set_parser_error_context(parser,
+ "while parsing a node", start_mark,
+ "found undefined tag handle", tag_mark)
+ return false
+ }
+ }
+ }
+
+ implicit := len(tag) == 0
+ if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
+ }
+ return true
+ }
+ if token.typ == yaml_SCALAR_TOKEN {
+ var plain_implicit, quoted_implicit bool
+ end_mark = token.end_mark
+ if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') {
+ plain_implicit = true
+ } else if len(tag) == 0 {
+ quoted_implicit = true
+ }
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ value: token.value,
+ implicit: plain_implicit,
+ quoted_implicit: quoted_implicit,
+ style: yaml_style_t(token.style),
+ }
+ yaml_parser_set_event_comments(parser, event)
+ skip_token(parser)
+ return true
+ }
+ if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN {
+ // [Go] Some of the events below can be merged as they differ only on style.
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE),
+ }
+ yaml_parser_set_event_comments(parser, event)
+ return true
+ }
+ if token.typ == yaml_FLOW_MAPPING_START_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_FLOW_MAPPING_STYLE),
+ }
+ yaml_parser_set_event_comments(parser, event)
+ return true
+ }
+ if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
+ }
+ if parser.stem_comment != nil {
+ event.head_comment = parser.stem_comment
+ parser.stem_comment = nil
+ }
+ return true
+ }
+ if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE),
+ }
+ if parser.stem_comment != nil {
+ event.head_comment = parser.stem_comment
+ parser.stem_comment = nil
+ }
+ return true
+ }
+ if len(anchor) > 0 || len(tag) > 0 {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ quoted_implicit: false,
+ style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
+ }
+ return true
+ }
+
+ context := "while parsing a flow node"
+ if block {
+ context = "while parsing a block node"
+ }
+ yaml_parser_set_parser_error_context(parser, context, start_mark,
+ "did not find expected node content", token.start_mark)
+ return false
+}
+
+// Parse the productions:
+// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+// ******************** *********** * *********
+//
+func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_BLOCK_ENTRY_TOKEN {
+ mark := token.end_mark
+ prior_head_len := len(parser.head_comment)
+ skip_token(parser)
+ yaml_parser_split_stem_comment(parser, prior_head_len)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)
+ return yaml_parser_parse_node(parser, event, true, false)
+ } else {
+ parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ }
+ if token.typ == yaml_BLOCK_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+
+ skip_token(parser)
+ return true
+ }
+
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a block collection", context_mark,
+ "did not find expected '-' indicator", token.start_mark)
+}
+
+// Parse the productions:
+// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+// *********** *
+func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_BLOCK_ENTRY_TOKEN {
+ mark := token.end_mark
+ prior_head_len := len(parser.head_comment)
+ skip_token(parser)
+ yaml_parser_split_stem_comment(parser, prior_head_len)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_BLOCK_ENTRY_TOKEN &&
+ token.typ != yaml_KEY_TOKEN &&
+ token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)
+ return yaml_parser_parse_node(parser, event, true, false)
+ }
+ parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark?
+ }
+ return true
+}
+
+// Split stem comment from head comment.
+//
+// When a sequence or map is found under a sequence entry, the former head comment
+// is assigned to the underlying sequence or map as a whole, not the individual
+// sequence or map entry as would be expected otherwise. To handle this case the
+// previous head comment is moved aside as the stem comment.
+func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
+ if stem_len == 0 {
+ return
+ }
+
+ token := peek_token(parser)
+ if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
+ return
+ }
+
+ parser.stem_comment = parser.head_comment[:stem_len]
+ if len(parser.head_comment) == stem_len {
+ parser.head_comment = nil
+ } else {
+ // Copy suffix to prevent very strange bugs if someone ever appends
+ // further bytes to the prefix in the stem_comment slice above.
+ parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...)
+ }
+}
+
+// Parse the productions:
+// block_mapping ::= BLOCK-MAPPING_START
+// *******************
+// ((KEY block_node_or_indentless_sequence?)?
+// *** *
+// (VALUE block_node_or_indentless_sequence?)?)*
+//
+// BLOCK-END
+// *********
+//
+func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ // [Go] A tail comment was left from the prior mapping value processed. Emit an event
+ // as it needs to be processed with that value and not the following key.
+ if len(parser.tail_comment) > 0 {
+ *event = yaml_event_t{
+ typ: yaml_TAIL_COMMENT_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ foot_comment: parser.tail_comment,
+ }
+ parser.tail_comment = nil
+ return true
+ }
+
+ if token.typ == yaml_KEY_TOKEN {
+ mark := token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_KEY_TOKEN &&
+ token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, true, true)
+ } else {
+ parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ } else if token.typ == yaml_BLOCK_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ yaml_parser_set_event_comments(parser, event)
+ skip_token(parser)
+ return true
+ }
+
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a block mapping", context_mark,
+ "did not find expected key", token.start_mark)
+}
+
+// Parse the productions:
+// block_mapping ::= BLOCK-MAPPING_START
+//
+// ((KEY block_node_or_indentless_sequence?)?
+//
+// (VALUE block_node_or_indentless_sequence?)?)*
+// ***** *
+// BLOCK-END
+//
+//
+func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_VALUE_TOKEN {
+ mark := token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_KEY_TOKEN &&
+ token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE)
+ return yaml_parser_parse_node(parser, event, true, true)
+ }
+ parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Parse the productions:
+// flow_sequence ::= FLOW-SEQUENCE-START
+// *******************
+// (flow_sequence_entry FLOW-ENTRY)*
+// * **********
+// flow_sequence_entry?
+// *
+// FLOW-SEQUENCE-END
+// *****************
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *
+//
+func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ if !first {
+ if token.typ == yaml_FLOW_ENTRY_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ } else {
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a flow sequence", context_mark,
+ "did not find expected ',' or ']'", token.start_mark)
+ }
+ }
+
+ if token.typ == yaml_KEY_TOKEN {
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ implicit: true,
+ style: yaml_style_t(yaml_FLOW_MAPPING_STYLE),
+ }
+ skip_token(parser)
+ return true
+ } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ yaml_parser_set_event_comments(parser, event)
+
+ skip_token(parser)
+ return true
+}
+
+//
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *** *
+//
+func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_FLOW_ENTRY_TOKEN &&
+ token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ mark := token.end_mark
+ skip_token(parser)
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+}
+
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// ***** *
+//
+func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_VALUE_TOKEN {
+ skip_token(parser)
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *
+//
+func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.start_mark, // [Go] Shouldn't this be end_mark?
+ }
+ return true
+}
+
+// Parse the productions:
+// flow_mapping ::= FLOW-MAPPING-START
+// ******************
+// (flow_mapping_entry FLOW-ENTRY)*
+// * **********
+// flow_mapping_entry?
+// ******************
+// FLOW-MAPPING-END
+// ****************
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// * *** *
+//
+func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ if !first {
+ if token.typ == yaml_FLOW_ENTRY_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ } else {
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a flow mapping", context_mark,
+ "did not find expected ',' or '}'", token.start_mark)
+ }
+ }
+
+ if token.typ == yaml_KEY_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_FLOW_ENTRY_TOKEN &&
+ token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ } else {
+ parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+ }
+ } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ yaml_parser_set_event_comments(parser, event)
+ skip_token(parser)
+ return true
+}
+
+// Parse the productions:
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// * ***** *
+//
+func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if empty {
+ parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+ }
+ if token.typ == yaml_VALUE_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+ parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Generate an empty scalar event.
+func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ start_mark: mark,
+ end_mark: mark,
+ value: nil, // Empty
+ implicit: true,
+ style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
+ }
+ return true
+}
+
+var default_tag_directives = []yaml_tag_directive_t{
+ {[]byte("!"), []byte("!")},
+ {[]byte("!!"), []byte("tag:yaml.org,2002:")},
+}
+
+// Parse directives.
+func yaml_parser_process_directives(parser *yaml_parser_t,
+ version_directive_ref **yaml_version_directive_t,
+ tag_directives_ref *[]yaml_tag_directive_t) bool {
+
+ var version_directive *yaml_version_directive_t
+ var tag_directives []yaml_tag_directive_t
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN {
+ if token.typ == yaml_VERSION_DIRECTIVE_TOKEN {
+ if version_directive != nil {
+ yaml_parser_set_parser_error(parser,
+ "found duplicate %YAML directive", token.start_mark)
+ return false
+ }
+ if token.major != 1 || token.minor != 1 {
+ yaml_parser_set_parser_error(parser,
+ "found incompatible YAML document", token.start_mark)
+ return false
+ }
+ version_directive = &yaml_version_directive_t{
+ major: token.major,
+ minor: token.minor,
+ }
+ } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN {
+ value := yaml_tag_directive_t{
+ handle: token.value,
+ prefix: token.prefix,
+ }
+ if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) {
+ return false
+ }
+ tag_directives = append(tag_directives, value)
+ }
+
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+
+ for i := range default_tag_directives {
+ if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) {
+ return false
+ }
+ }
+
+ if version_directive_ref != nil {
+ *version_directive_ref = version_directive
+ }
+ if tag_directives_ref != nil {
+ *tag_directives_ref = tag_directives
+ }
+ return true
+}
+
+// Append a tag directive to the directives stack.
+func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool {
+ for i := range parser.tag_directives {
+ if bytes.Equal(value.handle, parser.tag_directives[i].handle) {
+ if allow_duplicates {
+ return true
+ }
+ return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark)
+ }
+ }
+
+ // [Go] I suspect the copy is unnecessary. This was likely done
+ // because there was no way to track ownership of the data.
+ value_copy := yaml_tag_directive_t{
+ handle: make([]byte, len(value.handle)),
+ prefix: make([]byte, len(value.prefix)),
+ }
+ copy(value_copy.handle, value.handle)
+ copy(value_copy.prefix, value.prefix)
+ parser.tag_directives = append(parser.tag_directives, value_copy)
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v3/readerc.go b/vendor/gopkg.in/yaml.v3/readerc.go
new file mode 100644
index 0000000..b7de0a8
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/readerc.go
@@ -0,0 +1,434 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "io"
+)
+
+// Set the reader error and return 0.
+func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool {
+ parser.error = yaml_READER_ERROR
+ parser.problem = problem
+ parser.problem_offset = offset
+ parser.problem_value = value
+ return false
+}
+
+// Byte order marks.
+const (
+ bom_UTF8 = "\xef\xbb\xbf"
+ bom_UTF16LE = "\xff\xfe"
+ bom_UTF16BE = "\xfe\xff"
+)
+
+// Determine the input stream encoding by checking the BOM symbol. If no BOM is
+// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
+func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
+ // Ensure that we had enough bytes in the raw buffer.
+ for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
+ if !yaml_parser_update_raw_buffer(parser) {
+ return false
+ }
+ }
+
+ // Determine the encoding.
+ buf := parser.raw_buffer
+ pos := parser.raw_buffer_pos
+ avail := len(buf) - pos
+ if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
+ parser.encoding = yaml_UTF16LE_ENCODING
+ parser.raw_buffer_pos += 2
+ parser.offset += 2
+ } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
+ parser.encoding = yaml_UTF16BE_ENCODING
+ parser.raw_buffer_pos += 2
+ parser.offset += 2
+ } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
+ parser.encoding = yaml_UTF8_ENCODING
+ parser.raw_buffer_pos += 3
+ parser.offset += 3
+ } else {
+ parser.encoding = yaml_UTF8_ENCODING
+ }
+ return true
+}
+
+// Update the raw buffer.
+func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
+ size_read := 0
+
+ // Return if the raw buffer is full.
+ if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
+ return true
+ }
+
+ // Return on EOF.
+ if parser.eof {
+ return true
+ }
+
+ // Move the remaining bytes in the raw buffer to the beginning.
+ if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
+ copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
+ }
+ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
+ parser.raw_buffer_pos = 0
+
+ // Call the read handler to fill the buffer.
+ size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
+ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
+ if err == io.EOF {
+ parser.eof = true
+ } else if err != nil {
+ return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1)
+ }
+ return true
+}
+
+// Ensure that the buffer contains at least `length` characters.
+// Return true on success, false on failure.
+//
+// The length is supposed to be significantly less that the buffer size.
+func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
+ if parser.read_handler == nil {
+ panic("read handler must be set")
+ }
+
+ // [Go] This function was changed to guarantee the requested length size at EOF.
+ // The fact we need to do this is pretty awful, but the description above implies
+ // for that to be the case, and there are tests
+
+ // If the EOF flag is set and the raw buffer is empty, do nothing.
+ if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
+ // [Go] ACTUALLY! Read the documentation of this function above.
+ // This is just broken. To return true, we need to have the
+ // given length in the buffer. Not doing that means every single
+ // check that calls this function to make sure the buffer has a
+ // given length is Go) panicking; or C) accessing invalid memory.
+ //return true
+ }
+
+ // Return if the buffer contains enough characters.
+ if parser.unread >= length {
+ return true
+ }
+
+ // Determine the input encoding if it is not known yet.
+ if parser.encoding == yaml_ANY_ENCODING {
+ if !yaml_parser_determine_encoding(parser) {
+ return false
+ }
+ }
+
+ // Move the unread characters to the beginning of the buffer.
+ buffer_len := len(parser.buffer)
+ if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
+ copy(parser.buffer, parser.buffer[parser.buffer_pos:])
+ buffer_len -= parser.buffer_pos
+ parser.buffer_pos = 0
+ } else if parser.buffer_pos == buffer_len {
+ buffer_len = 0
+ parser.buffer_pos = 0
+ }
+
+ // Open the whole buffer for writing, and cut it before returning.
+ parser.buffer = parser.buffer[:cap(parser.buffer)]
+
+ // Fill the buffer until it has enough characters.
+ first := true
+ for parser.unread < length {
+
+ // Fill the raw buffer if necessary.
+ if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
+ if !yaml_parser_update_raw_buffer(parser) {
+ parser.buffer = parser.buffer[:buffer_len]
+ return false
+ }
+ }
+ first = false
+
+ // Decode the raw buffer.
+ inner:
+ for parser.raw_buffer_pos != len(parser.raw_buffer) {
+ var value rune
+ var width int
+
+ raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
+
+ // Decode the next character.
+ switch parser.encoding {
+ case yaml_UTF8_ENCODING:
+ // Decode a UTF-8 character. Check RFC 3629
+ // (http://www.ietf.org/rfc/rfc3629.txt) for more details.
+ //
+ // The following table (taken from the RFC) is used for
+ // decoding.
+ //
+ // Char. number range | UTF-8 octet sequence
+ // (hexadecimal) | (binary)
+ // --------------------+------------------------------------
+ // 0000 0000-0000 007F | 0xxxxxxx
+ // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
+ // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
+ // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ //
+ // Additionally, the characters in the range 0xD800-0xDFFF
+ // are prohibited as they are reserved for use with UTF-16
+ // surrogate pairs.
+
+ // Determine the length of the UTF-8 sequence.
+ octet := parser.raw_buffer[parser.raw_buffer_pos]
+ switch {
+ case octet&0x80 == 0x00:
+ width = 1
+ case octet&0xE0 == 0xC0:
+ width = 2
+ case octet&0xF0 == 0xE0:
+ width = 3
+ case octet&0xF8 == 0xF0:
+ width = 4
+ default:
+ // The leading octet is invalid.
+ return yaml_parser_set_reader_error(parser,
+ "invalid leading UTF-8 octet",
+ parser.offset, int(octet))
+ }
+
+ // Check if the raw buffer contains an incomplete character.
+ if width > raw_unread {
+ if parser.eof {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-8 octet sequence",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Decode the leading octet.
+ switch {
+ case octet&0x80 == 0x00:
+ value = rune(octet & 0x7F)
+ case octet&0xE0 == 0xC0:
+ value = rune(octet & 0x1F)
+ case octet&0xF0 == 0xE0:
+ value = rune(octet & 0x0F)
+ case octet&0xF8 == 0xF0:
+ value = rune(octet & 0x07)
+ default:
+ value = 0
+ }
+
+ // Check and decode the trailing octets.
+ for k := 1; k < width; k++ {
+ octet = parser.raw_buffer[parser.raw_buffer_pos+k]
+
+ // Check if the octet is valid.
+ if (octet & 0xC0) != 0x80 {
+ return yaml_parser_set_reader_error(parser,
+ "invalid trailing UTF-8 octet",
+ parser.offset+k, int(octet))
+ }
+
+ // Decode the octet.
+ value = (value << 6) + rune(octet&0x3F)
+ }
+
+ // Check the length of the sequence against the value.
+ switch {
+ case width == 1:
+ case width == 2 && value >= 0x80:
+ case width == 3 && value >= 0x800:
+ case width == 4 && value >= 0x10000:
+ default:
+ return yaml_parser_set_reader_error(parser,
+ "invalid length of a UTF-8 sequence",
+ parser.offset, -1)
+ }
+
+ // Check the range of the value.
+ if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
+ return yaml_parser_set_reader_error(parser,
+ "invalid Unicode character",
+ parser.offset, int(value))
+ }
+
+ case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING:
+ var low, high int
+ if parser.encoding == yaml_UTF16LE_ENCODING {
+ low, high = 0, 1
+ } else {
+ low, high = 1, 0
+ }
+
+ // The UTF-16 encoding is not as simple as one might
+ // naively think. Check RFC 2781
+ // (http://www.ietf.org/rfc/rfc2781.txt).
+ //
+ // Normally, two subsequent bytes describe a Unicode
+ // character. However a special technique (called a
+ // surrogate pair) is used for specifying character
+ // values larger than 0xFFFF.
+ //
+ // A surrogate pair consists of two pseudo-characters:
+ // high surrogate area (0xD800-0xDBFF)
+ // low surrogate area (0xDC00-0xDFFF)
+ //
+ // The following formulas are used for decoding
+ // and encoding characters using surrogate pairs:
+ //
+ // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
+ // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
+ // W1 = 110110yyyyyyyyyy
+ // W2 = 110111xxxxxxxxxx
+ //
+ // where U is the character value, W1 is the high surrogate
+ // area, W2 is the low surrogate area.
+
+ // Check for incomplete UTF-16 character.
+ if raw_unread < 2 {
+ if parser.eof {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-16 character",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Get the character.
+ value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
+ (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
+
+ // Check for unexpected low surrogate area.
+ if value&0xFC00 == 0xDC00 {
+ return yaml_parser_set_reader_error(parser,
+ "unexpected low surrogate area",
+ parser.offset, int(value))
+ }
+
+ // Check for a high surrogate area.
+ if value&0xFC00 == 0xD800 {
+ width = 4
+
+ // Check for incomplete surrogate pair.
+ if raw_unread < 4 {
+ if parser.eof {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-16 surrogate pair",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Get the next character.
+ value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
+ (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
+
+ // Check for a low surrogate area.
+ if value2&0xFC00 != 0xDC00 {
+ return yaml_parser_set_reader_error(parser,
+ "expected low surrogate area",
+ parser.offset+2, int(value2))
+ }
+
+ // Generate the value of the surrogate pair.
+ value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
+ } else {
+ width = 2
+ }
+
+ default:
+ panic("impossible")
+ }
+
+ // Check if the character is in the allowed range:
+ // #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
+ // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
+ // | [#x10000-#x10FFFF] (32 bit)
+ switch {
+ case value == 0x09:
+ case value == 0x0A:
+ case value == 0x0D:
+ case value >= 0x20 && value <= 0x7E:
+ case value == 0x85:
+ case value >= 0xA0 && value <= 0xD7FF:
+ case value >= 0xE000 && value <= 0xFFFD:
+ case value >= 0x10000 && value <= 0x10FFFF:
+ default:
+ return yaml_parser_set_reader_error(parser,
+ "control characters are not allowed",
+ parser.offset, int(value))
+ }
+
+ // Move the raw pointers.
+ parser.raw_buffer_pos += width
+ parser.offset += width
+
+ // Finally put the character into the buffer.
+ if value <= 0x7F {
+ // 0000 0000-0000 007F . 0xxxxxxx
+ parser.buffer[buffer_len+0] = byte(value)
+ buffer_len += 1
+ } else if value <= 0x7FF {
+ // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
+ parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
+ buffer_len += 2
+ } else if value <= 0xFFFF {
+ // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
+ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
+ parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
+ buffer_len += 3
+ } else {
+ // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
+ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
+ parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
+ parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
+ buffer_len += 4
+ }
+
+ parser.unread++
+ }
+
+ // On EOF, put NUL into the buffer and return.
+ if parser.eof {
+ parser.buffer[buffer_len] = 0
+ buffer_len++
+ parser.unread++
+ break
+ }
+ }
+ // [Go] Read the documentation of this function above. To return true,
+ // we need to have the given length in the buffer. Not doing that means
+ // every single check that calls this function to make sure the buffer
+ // has a given length is Go) panicking; or C) accessing invalid memory.
+ // This happens here due to the EOF above breaking early.
+ for buffer_len < length {
+ parser.buffer[buffer_len] = 0
+ buffer_len++
+ }
+ parser.buffer = parser.buffer[:buffer_len]
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v3/resolve.go b/vendor/gopkg.in/yaml.v3/resolve.go
new file mode 100644
index 0000000..64ae888
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/resolve.go
@@ -0,0 +1,326 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// 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 yaml
+
+import (
+ "encoding/base64"
+ "math"
+ "regexp"
+ "strconv"
+ "strings"
+ "time"
+)
+
+type resolveMapItem struct {
+ value interface{}
+ tag string
+}
+
+var resolveTable = make([]byte, 256)
+var resolveMap = make(map[string]resolveMapItem)
+
+func init() {
+ t := resolveTable
+ t[int('+')] = 'S' // Sign
+ t[int('-')] = 'S'
+ for _, c := range "0123456789" {
+ t[int(c)] = 'D' // Digit
+ }
+ for _, c := range "yYnNtTfFoO~" {
+ t[int(c)] = 'M' // In map
+ }
+ t[int('.')] = '.' // Float (potentially in map)
+
+ var resolveMapList = []struct {
+ v interface{}
+ tag string
+ l []string
+ }{
+ {true, boolTag, []string{"true", "True", "TRUE"}},
+ {false, boolTag, []string{"false", "False", "FALSE"}},
+ {nil, nullTag, []string{"", "~", "null", "Null", "NULL"}},
+ {math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}},
+ {math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}},
+ {math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}},
+ {math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}},
+ {"<<", mergeTag, []string{"<<"}},
+ }
+
+ m := resolveMap
+ for _, item := range resolveMapList {
+ for _, s := range item.l {
+ m[s] = resolveMapItem{item.v, item.tag}
+ }
+ }
+}
+
+const (
+ nullTag = "!!null"
+ boolTag = "!!bool"
+ strTag = "!!str"
+ intTag = "!!int"
+ floatTag = "!!float"
+ timestampTag = "!!timestamp"
+ seqTag = "!!seq"
+ mapTag = "!!map"
+ binaryTag = "!!binary"
+ mergeTag = "!!merge"
+)
+
+var longTags = make(map[string]string)
+var shortTags = make(map[string]string)
+
+func init() {
+ for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} {
+ ltag := longTag(stag)
+ longTags[stag] = ltag
+ shortTags[ltag] = stag
+ }
+}
+
+const longTagPrefix = "tag:yaml.org,2002:"
+
+func shortTag(tag string) string {
+ if strings.HasPrefix(tag, longTagPrefix) {
+ if stag, ok := shortTags[tag]; ok {
+ return stag
+ }
+ return "!!" + tag[len(longTagPrefix):]
+ }
+ return tag
+}
+
+func longTag(tag string) string {
+ if strings.HasPrefix(tag, "!!") {
+ if ltag, ok := longTags[tag]; ok {
+ return ltag
+ }
+ return longTagPrefix + tag[2:]
+ }
+ return tag
+}
+
+func resolvableTag(tag string) bool {
+ switch tag {
+ case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag:
+ return true
+ }
+ return false
+}
+
+var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`)
+
+func resolve(tag string, in string) (rtag string, out interface{}) {
+ tag = shortTag(tag)
+ if !resolvableTag(tag) {
+ return tag, in
+ }
+
+ defer func() {
+ switch tag {
+ case "", rtag, strTag, binaryTag:
+ return
+ case floatTag:
+ if rtag == intTag {
+ switch v := out.(type) {
+ case int64:
+ rtag = floatTag
+ out = float64(v)
+ return
+ case int:
+ rtag = floatTag
+ out = float64(v)
+ return
+ }
+ }
+ }
+ failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
+ }()
+
+ // Any data is accepted as a !!str or !!binary.
+ // Otherwise, the prefix is enough of a hint about what it might be.
+ hint := byte('N')
+ if in != "" {
+ hint = resolveTable[in[0]]
+ }
+ if hint != 0 && tag != strTag && tag != binaryTag {
+ // Handle things we can lookup in a map.
+ if item, ok := resolveMap[in]; ok {
+ return item.tag, item.value
+ }
+
+ // Base 60 floats are a bad idea, were dropped in YAML 1.2, and
+ // are purposefully unsupported here. They're still quoted on
+ // the way out for compatibility with other parser, though.
+
+ switch hint {
+ case 'M':
+ // We've already checked the map above.
+
+ case '.':
+ // Not in the map, so maybe a normal float.
+ floatv, err := strconv.ParseFloat(in, 64)
+ if err == nil {
+ return floatTag, floatv
+ }
+
+ case 'D', 'S':
+ // Int, float, or timestamp.
+ // Only try values as a timestamp if the value is unquoted or there's an explicit
+ // !!timestamp tag.
+ if tag == "" || tag == timestampTag {
+ t, ok := parseTimestamp(in)
+ if ok {
+ return timestampTag, t
+ }
+ }
+
+ plain := strings.Replace(in, "_", "", -1)
+ intv, err := strconv.ParseInt(plain, 0, 64)
+ if err == nil {
+ if intv == int64(int(intv)) {
+ return intTag, int(intv)
+ } else {
+ return intTag, intv
+ }
+ }
+ uintv, err := strconv.ParseUint(plain, 0, 64)
+ if err == nil {
+ return intTag, uintv
+ }
+ if yamlStyleFloat.MatchString(plain) {
+ floatv, err := strconv.ParseFloat(plain, 64)
+ if err == nil {
+ return floatTag, floatv
+ }
+ }
+ if strings.HasPrefix(plain, "0b") {
+ intv, err := strconv.ParseInt(plain[2:], 2, 64)
+ if err == nil {
+ if intv == int64(int(intv)) {
+ return intTag, int(intv)
+ } else {
+ return intTag, intv
+ }
+ }
+ uintv, err := strconv.ParseUint(plain[2:], 2, 64)
+ if err == nil {
+ return intTag, uintv
+ }
+ } else if strings.HasPrefix(plain, "-0b") {
+ intv, err := strconv.ParseInt("-"+plain[3:], 2, 64)
+ if err == nil {
+ if true || intv == int64(int(intv)) {
+ return intTag, int(intv)
+ } else {
+ return intTag, intv
+ }
+ }
+ }
+ // Octals as introduced in version 1.2 of the spec.
+ // Octals from the 1.1 spec, spelled as 0777, are still
+ // decoded by default in v3 as well for compatibility.
+ // May be dropped in v4 depending on how usage evolves.
+ if strings.HasPrefix(plain, "0o") {
+ intv, err := strconv.ParseInt(plain[2:], 8, 64)
+ if err == nil {
+ if intv == int64(int(intv)) {
+ return intTag, int(intv)
+ } else {
+ return intTag, intv
+ }
+ }
+ uintv, err := strconv.ParseUint(plain[2:], 8, 64)
+ if err == nil {
+ return intTag, uintv
+ }
+ } else if strings.HasPrefix(plain, "-0o") {
+ intv, err := strconv.ParseInt("-"+plain[3:], 8, 64)
+ if err == nil {
+ if true || intv == int64(int(intv)) {
+ return intTag, int(intv)
+ } else {
+ return intTag, intv
+ }
+ }
+ }
+ default:
+ panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")")
+ }
+ }
+ return strTag, in
+}
+
+// encodeBase64 encodes s as base64 that is broken up into multiple lines
+// as appropriate for the resulting length.
+func encodeBase64(s string) string {
+ const lineLen = 70
+ encLen := base64.StdEncoding.EncodedLen(len(s))
+ lines := encLen/lineLen + 1
+ buf := make([]byte, encLen*2+lines)
+ in := buf[0:encLen]
+ out := buf[encLen:]
+ base64.StdEncoding.Encode(in, []byte(s))
+ k := 0
+ for i := 0; i < len(in); i += lineLen {
+ j := i + lineLen
+ if j > len(in) {
+ j = len(in)
+ }
+ k += copy(out[k:], in[i:j])
+ if lines > 1 {
+ out[k] = '\n'
+ k++
+ }
+ }
+ return string(out[:k])
+}
+
+// This is a subset of the formats allowed by the regular expression
+// defined at http://yaml.org/type/timestamp.html.
+var allowedTimestampFormats = []string{
+ "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
+ "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
+ "2006-1-2 15:4:5.999999999", // space separated with no time zone
+ "2006-1-2", // date only
+ // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
+ // from the set of examples.
+}
+
+// parseTimestamp parses s as a timestamp string and
+// returns the timestamp and reports whether it succeeded.
+// Timestamp formats are defined at http://yaml.org/type/timestamp.html
+func parseTimestamp(s string) (time.Time, bool) {
+ // TODO write code to check all the formats supported by
+ // http://yaml.org/type/timestamp.html instead of using time.Parse.
+
+ // Quick check: all date formats start with YYYY-.
+ i := 0
+ for ; i < len(s); i++ {
+ if c := s[i]; c < '0' || c > '9' {
+ break
+ }
+ }
+ if i != 4 || i == len(s) || s[i] != '-' {
+ return time.Time{}, false
+ }
+ for _, format := range allowedTimestampFormats {
+ if t, err := time.Parse(format, s); err == nil {
+ return t, true
+ }
+ }
+ return time.Time{}, false
+}
diff --git a/vendor/gopkg.in/yaml.v3/scannerc.go b/vendor/gopkg.in/yaml.v3/scannerc.go
new file mode 100644
index 0000000..ca00701
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/scannerc.go
@@ -0,0 +1,3038 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "bytes"
+ "fmt"
+)
+
+// Introduction
+// ************
+//
+// The following notes assume that you are familiar with the YAML specification
+// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in
+// some cases we are less restrictive that it requires.
+//
+// The process of transforming a YAML stream into a sequence of events is
+// divided on two steps: Scanning and Parsing.
+//
+// The Scanner transforms the input stream into a sequence of tokens, while the
+// parser transform the sequence of tokens produced by the Scanner into a
+// sequence of parsing events.
+//
+// The Scanner is rather clever and complicated. The Parser, on the contrary,
+// is a straightforward implementation of a recursive-descendant parser (or,
+// LL(1) parser, as it is usually called).
+//
+// Actually there are two issues of Scanning that might be called "clever", the
+// rest is quite straightforward. The issues are "block collection start" and
+// "simple keys". Both issues are explained below in details.
+//
+// Here the Scanning step is explained and implemented. We start with the list
+// of all the tokens produced by the Scanner together with short descriptions.
+//
+// Now, tokens:
+//
+// STREAM-START(encoding) # The stream start.
+// STREAM-END # The stream end.
+// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive.
+// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive.
+// DOCUMENT-START # '---'
+// DOCUMENT-END # '...'
+// BLOCK-SEQUENCE-START # Indentation increase denoting a block
+// BLOCK-MAPPING-START # sequence or a block mapping.
+// BLOCK-END # Indentation decrease.
+// FLOW-SEQUENCE-START # '['
+// FLOW-SEQUENCE-END # ']'
+// BLOCK-SEQUENCE-START # '{'
+// BLOCK-SEQUENCE-END # '}'
+// BLOCK-ENTRY # '-'
+// FLOW-ENTRY # ','
+// KEY # '?' or nothing (simple keys).
+// VALUE # ':'
+// ALIAS(anchor) # '*anchor'
+// ANCHOR(anchor) # '&anchor'
+// TAG(handle,suffix) # '!handle!suffix'
+// SCALAR(value,style) # A scalar.
+//
+// The following two tokens are "virtual" tokens denoting the beginning and the
+// end of the stream:
+//
+// STREAM-START(encoding)
+// STREAM-END
+//
+// We pass the information about the input stream encoding with the
+// STREAM-START token.
+//
+// The next two tokens are responsible for tags:
+//
+// VERSION-DIRECTIVE(major,minor)
+// TAG-DIRECTIVE(handle,prefix)
+//
+// Example:
+//
+// %YAML 1.1
+// %TAG ! !foo
+// %TAG !yaml! tag:yaml.org,2002:
+// ---
+//
+// The correspoding sequence of tokens:
+//
+// STREAM-START(utf-8)
+// VERSION-DIRECTIVE(1,1)
+// TAG-DIRECTIVE("!","!foo")
+// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
+// DOCUMENT-START
+// STREAM-END
+//
+// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
+// line.
+//
+// The document start and end indicators are represented by:
+//
+// DOCUMENT-START
+// DOCUMENT-END
+//
+// Note that if a YAML stream contains an implicit document (without '---'
+// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
+// produced.
+//
+// In the following examples, we present whole documents together with the
+// produced tokens.
+//
+// 1. An implicit document:
+//
+// 'a scalar'
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// SCALAR("a scalar",single-quoted)
+// STREAM-END
+//
+// 2. An explicit document:
+//
+// ---
+// 'a scalar'
+// ...
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// DOCUMENT-START
+// SCALAR("a scalar",single-quoted)
+// DOCUMENT-END
+// STREAM-END
+//
+// 3. Several documents in a stream:
+//
+// 'a scalar'
+// ---
+// 'another scalar'
+// ---
+// 'yet another scalar'
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// SCALAR("a scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("another scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("yet another scalar",single-quoted)
+// STREAM-END
+//
+// We have already introduced the SCALAR token above. The following tokens are
+// used to describe aliases, anchors, tag, and scalars:
+//
+// ALIAS(anchor)
+// ANCHOR(anchor)
+// TAG(handle,suffix)
+// SCALAR(value,style)
+//
+// The following series of examples illustrate the usage of these tokens:
+//
+// 1. A recursive sequence:
+//
+// &A [ *A ]
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// ANCHOR("A")
+// FLOW-SEQUENCE-START
+// ALIAS("A")
+// FLOW-SEQUENCE-END
+// STREAM-END
+//
+// 2. A tagged scalar:
+//
+// !!float "3.14" # A good approximation.
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// TAG("!!","float")
+// SCALAR("3.14",double-quoted)
+// STREAM-END
+//
+// 3. Various scalar styles:
+//
+// --- # Implicit empty plain scalars do not produce tokens.
+// --- a plain scalar
+// --- 'a single-quoted scalar'
+// --- "a double-quoted scalar"
+// --- |-
+// a literal scalar
+// --- >-
+// a folded
+// scalar
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// DOCUMENT-START
+// DOCUMENT-START
+// SCALAR("a plain scalar",plain)
+// DOCUMENT-START
+// SCALAR("a single-quoted scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("a double-quoted scalar",double-quoted)
+// DOCUMENT-START
+// SCALAR("a literal scalar",literal)
+// DOCUMENT-START
+// SCALAR("a folded scalar",folded)
+// STREAM-END
+//
+// Now it's time to review collection-related tokens. We will start with
+// flow collections:
+//
+// FLOW-SEQUENCE-START
+// FLOW-SEQUENCE-END
+// FLOW-MAPPING-START
+// FLOW-MAPPING-END
+// FLOW-ENTRY
+// KEY
+// VALUE
+//
+// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
+// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
+// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the
+// indicators '?' and ':', which are used for denoting mapping keys and values,
+// are represented by the KEY and VALUE tokens.
+//
+// The following examples show flow collections:
+//
+// 1. A flow sequence:
+//
+// [item 1, item 2, item 3]
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// FLOW-SEQUENCE-START
+// SCALAR("item 1",plain)
+// FLOW-ENTRY
+// SCALAR("item 2",plain)
+// FLOW-ENTRY
+// SCALAR("item 3",plain)
+// FLOW-SEQUENCE-END
+// STREAM-END
+//
+// 2. A flow mapping:
+//
+// {
+// a simple key: a value, # Note that the KEY token is produced.
+// ? a complex key: another value,
+// }
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// FLOW-MAPPING-START
+// KEY
+// SCALAR("a simple key",plain)
+// VALUE
+// SCALAR("a value",plain)
+// FLOW-ENTRY
+// KEY
+// SCALAR("a complex key",plain)
+// VALUE
+// SCALAR("another value",plain)
+// FLOW-ENTRY
+// FLOW-MAPPING-END
+// STREAM-END
+//
+// A simple key is a key which is not denoted by the '?' indicator. Note that
+// the Scanner still produce the KEY token whenever it encounters a simple key.
+//
+// For scanning block collections, the following tokens are used (note that we
+// repeat KEY and VALUE here):
+//
+// BLOCK-SEQUENCE-START
+// BLOCK-MAPPING-START
+// BLOCK-END
+// BLOCK-ENTRY
+// KEY
+// VALUE
+//
+// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
+// increase that precedes a block collection (cf. the INDENT token in Python).
+// The token BLOCK-END denote indentation decrease that ends a block collection
+// (cf. the DEDENT token in Python). However YAML has some syntax pecularities
+// that makes detections of these tokens more complex.
+//
+// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
+// '-', '?', and ':' correspondingly.
+//
+// The following examples show how the tokens BLOCK-SEQUENCE-START,
+// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
+//
+// 1. Block sequences:
+//
+// - item 1
+// - item 2
+// -
+// - item 3.1
+// - item 3.2
+// -
+// key 1: value 1
+// key 2: value 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-ENTRY
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 3.1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 3.2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// 2. Block mappings:
+//
+// a simple key: a value # The KEY token is produced here.
+// ? a complex key
+// : another value
+// a mapping:
+// key 1: value 1
+// key 2: value 2
+// a sequence:
+// - item 1
+// - item 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("a simple key",plain)
+// VALUE
+// SCALAR("a value",plain)
+// KEY
+// SCALAR("a complex key",plain)
+// VALUE
+// SCALAR("another value",plain)
+// KEY
+// SCALAR("a mapping",plain)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// KEY
+// SCALAR("a sequence",plain)
+// VALUE
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// YAML does not always require to start a new block collection from a new
+// line. If the current line contains only '-', '?', and ':' indicators, a new
+// block collection may start at the current line. The following examples
+// illustrate this case:
+//
+// 1. Collections in a sequence:
+//
+// - - item 1
+// - item 2
+// - key 1: value 1
+// key 2: value 2
+// - ? complex key
+// : complex value
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("complex key")
+// VALUE
+// SCALAR("complex value")
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// 2. Collections in a mapping:
+//
+// ? a sequence
+// : - item 1
+// - item 2
+// ? a mapping
+// : key 1: value 1
+// key 2: value 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("a sequence",plain)
+// VALUE
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// KEY
+// SCALAR("a mapping",plain)
+// VALUE
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// YAML also permits non-indented sequences if they are included into a block
+// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced:
+//
+// key:
+// - item 1 # BLOCK-SEQUENCE-START is NOT produced here.
+// - item 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key",plain)
+// VALUE
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+//
+
+// Ensure that the buffer contains the required number of characters.
+// Return true on success, false on failure (reader error or memory error).
+func cache(parser *yaml_parser_t, length int) bool {
+ // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B)
+ return parser.unread >= length || yaml_parser_update_buffer(parser, length)
+}
+
+// Advance the buffer pointer.
+func skip(parser *yaml_parser_t) {
+ if !is_blank(parser.buffer, parser.buffer_pos) {
+ parser.newlines = 0
+ }
+ parser.mark.index++
+ parser.mark.column++
+ parser.unread--
+ parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+}
+
+func skip_line(parser *yaml_parser_t) {
+ if is_crlf(parser.buffer, parser.buffer_pos) {
+ parser.mark.index += 2
+ parser.mark.column = 0
+ parser.mark.line++
+ parser.unread -= 2
+ parser.buffer_pos += 2
+ parser.newlines++
+ } else if is_break(parser.buffer, parser.buffer_pos) {
+ parser.mark.index++
+ parser.mark.column = 0
+ parser.mark.line++
+ parser.unread--
+ parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+ parser.newlines++
+ }
+}
+
+// Copy a character to a string buffer and advance pointers.
+func read(parser *yaml_parser_t, s []byte) []byte {
+ if !is_blank(parser.buffer, parser.buffer_pos) {
+ parser.newlines = 0
+ }
+ w := width(parser.buffer[parser.buffer_pos])
+ if w == 0 {
+ panic("invalid character sequence")
+ }
+ if len(s) == 0 {
+ s = make([]byte, 0, 32)
+ }
+ if w == 1 && len(s)+w <= cap(s) {
+ s = s[:len(s)+1]
+ s[len(s)-1] = parser.buffer[parser.buffer_pos]
+ parser.buffer_pos++
+ } else {
+ s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...)
+ parser.buffer_pos += w
+ }
+ parser.mark.index++
+ parser.mark.column++
+ parser.unread--
+ return s
+}
+
+// Copy a line break character to a string buffer and advance pointers.
+func read_line(parser *yaml_parser_t, s []byte) []byte {
+ buf := parser.buffer
+ pos := parser.buffer_pos
+ switch {
+ case buf[pos] == '\r' && buf[pos+1] == '\n':
+ // CR LF . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 2
+ parser.mark.index++
+ parser.unread--
+ case buf[pos] == '\r' || buf[pos] == '\n':
+ // CR|LF . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 1
+ case buf[pos] == '\xC2' && buf[pos+1] == '\x85':
+ // NEL . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 2
+ case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'):
+ // LS|PS . LS|PS
+ s = append(s, buf[parser.buffer_pos:pos+3]...)
+ parser.buffer_pos += 3
+ default:
+ return s
+ }
+ parser.mark.index++
+ parser.mark.column = 0
+ parser.mark.line++
+ parser.unread--
+ parser.newlines++
+ return s
+}
+
+// Get the next token.
+func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool {
+ // Erase the token object.
+ *token = yaml_token_t{} // [Go] Is this necessary?
+
+ // No tokens after STREAM-END or error.
+ if parser.stream_end_produced || parser.error != yaml_NO_ERROR {
+ return true
+ }
+
+ // Ensure that the tokens queue contains enough tokens.
+ if !parser.token_available {
+ if !yaml_parser_fetch_more_tokens(parser) {
+ return false
+ }
+ }
+
+ // Fetch the next token from the queue.
+ *token = parser.tokens[parser.tokens_head]
+ parser.tokens_head++
+ parser.tokens_parsed++
+ parser.token_available = false
+
+ if token.typ == yaml_STREAM_END_TOKEN {
+ parser.stream_end_produced = true
+ }
+ return true
+}
+
+// Set the scanner error and return false.
+func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool {
+ parser.error = yaml_SCANNER_ERROR
+ parser.context = context
+ parser.context_mark = context_mark
+ parser.problem = problem
+ parser.problem_mark = parser.mark
+ return false
+}
+
+func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool {
+ context := "while parsing a tag"
+ if directive {
+ context = "while parsing a %TAG directive"
+ }
+ return yaml_parser_set_scanner_error(parser, context, context_mark, problem)
+}
+
+func trace(args ...interface{}) func() {
+ pargs := append([]interface{}{"+++"}, args...)
+ fmt.Println(pargs...)
+ pargs = append([]interface{}{"---"}, args...)
+ return func() { fmt.Println(pargs...) }
+}
+
+// Ensure that the tokens queue contains at least one token which can be
+// returned to the Parser.
+func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
+ // While we need more tokens to fetch, do it.
+ for {
+ // [Go] The comment parsing logic requires a lookahead of two tokens
+ // so that foot comments may be parsed in time of associating them
+ // with the tokens that are parsed before them, and also for line
+ // comments to be transformed into head comments in some edge cases.
+ if parser.tokens_head < len(parser.tokens)-2 {
+ // If a potential simple key is at the head position, we need to fetch
+ // the next token to disambiguate it.
+ head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed]
+ if !ok {
+ break
+ } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok {
+ return false
+ } else if !valid {
+ break
+ }
+ }
+ // Fetch the next token.
+ if !yaml_parser_fetch_next_token(parser) {
+ return false
+ }
+ }
+
+ parser.token_available = true
+ return true
+}
+
+// The dispatcher for token fetchers.
+func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) {
+ // Ensure that the buffer is initialized.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // Check if we just started scanning. Fetch STREAM-START then.
+ if !parser.stream_start_produced {
+ return yaml_parser_fetch_stream_start(parser)
+ }
+
+ scan_mark := parser.mark
+
+ // Eat whitespaces and comments until we reach the next token.
+ if !yaml_parser_scan_to_next_token(parser) {
+ return false
+ }
+
+ // [Go] While unrolling indents, transform the head comments of prior
+ // indentation levels observed after scan_start into foot comments at
+ // the respective indexes.
+
+ // Check the indentation level against the current column.
+ if !yaml_parser_unroll_indent(parser, parser.mark.column, scan_mark) {
+ return false
+ }
+
+ // Ensure that the buffer contains at least 4 characters. 4 is the length
+ // of the longest indicators ('--- ' and '... ').
+ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+ return false
+ }
+
+ // Is it the end of the stream?
+ if is_z(parser.buffer, parser.buffer_pos) {
+ return yaml_parser_fetch_stream_end(parser)
+ }
+
+ // Is it a directive?
+ if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' {
+ return yaml_parser_fetch_directive(parser)
+ }
+
+ buf := parser.buffer
+ pos := parser.buffer_pos
+
+ // Is it the document start indicator?
+ if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) {
+ return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN)
+ }
+
+ // Is it the document end indicator?
+ if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) {
+ return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN)
+ }
+
+ comment_mark := parser.mark
+ if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') {
+ // Associate any following comments with the prior token.
+ comment_mark = parser.tokens[len(parser.tokens)-1].start_mark
+ }
+ defer func() {
+ if !ok {
+ return
+ }
+ if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN {
+ // Sequence indicators alone have no line comments. It becomes
+ // a head comment for whatever follows.
+ return
+ }
+ if !yaml_parser_scan_line_comment(parser, comment_mark) {
+ ok = false
+ return
+ }
+ }()
+
+ // Is it the flow sequence start indicator?
+ if buf[pos] == '[' {
+ return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN)
+ }
+
+ // Is it the flow mapping start indicator?
+ if parser.buffer[parser.buffer_pos] == '{' {
+ return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN)
+ }
+
+ // Is it the flow sequence end indicator?
+ if parser.buffer[parser.buffer_pos] == ']' {
+ return yaml_parser_fetch_flow_collection_end(parser,
+ yaml_FLOW_SEQUENCE_END_TOKEN)
+ }
+
+ // Is it the flow mapping end indicator?
+ if parser.buffer[parser.buffer_pos] == '}' {
+ return yaml_parser_fetch_flow_collection_end(parser,
+ yaml_FLOW_MAPPING_END_TOKEN)
+ }
+
+ // Is it the flow entry indicator?
+ if parser.buffer[parser.buffer_pos] == ',' {
+ return yaml_parser_fetch_flow_entry(parser)
+ }
+
+ // Is it the block entry indicator?
+ if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) {
+ return yaml_parser_fetch_block_entry(parser)
+ }
+
+ // Is it the key indicator?
+ if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
+ return yaml_parser_fetch_key(parser)
+ }
+
+ // Is it the value indicator?
+ if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
+ return yaml_parser_fetch_value(parser)
+ }
+
+ // Is it an alias?
+ if parser.buffer[parser.buffer_pos] == '*' {
+ return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN)
+ }
+
+ // Is it an anchor?
+ if parser.buffer[parser.buffer_pos] == '&' {
+ return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN)
+ }
+
+ // Is it a tag?
+ if parser.buffer[parser.buffer_pos] == '!' {
+ return yaml_parser_fetch_tag(parser)
+ }
+
+ // Is it a literal scalar?
+ if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 {
+ return yaml_parser_fetch_block_scalar(parser, true)
+ }
+
+ // Is it a folded scalar?
+ if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 {
+ return yaml_parser_fetch_block_scalar(parser, false)
+ }
+
+ // Is it a single-quoted scalar?
+ if parser.buffer[parser.buffer_pos] == '\'' {
+ return yaml_parser_fetch_flow_scalar(parser, true)
+ }
+
+ // Is it a double-quoted scalar?
+ if parser.buffer[parser.buffer_pos] == '"' {
+ return yaml_parser_fetch_flow_scalar(parser, false)
+ }
+
+ // Is it a plain scalar?
+ //
+ // A plain scalar may start with any non-blank characters except
+ //
+ // '-', '?', ':', ',', '[', ']', '{', '}',
+ // '#', '&', '*', '!', '|', '>', '\'', '\"',
+ // '%', '@', '`'.
+ //
+ // In the block context (and, for the '-' indicator, in the flow context
+ // too), it may also start with the characters
+ //
+ // '-', '?', ':'
+ //
+ // if it is followed by a non-space character.
+ //
+ // The last rule is more restrictive than the specification requires.
+ // [Go] TODO Make this logic more reasonable.
+ //switch parser.buffer[parser.buffer_pos] {
+ //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`':
+ //}
+ if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' ||
+ parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' ||
+ parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+ parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' ||
+ parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' ||
+ parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' ||
+ parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' ||
+ parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' ||
+ parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') ||
+ (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) ||
+ (parser.flow_level == 0 &&
+ (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') &&
+ !is_blankz(parser.buffer, parser.buffer_pos+1)) {
+ return yaml_parser_fetch_plain_scalar(parser)
+ }
+
+ // If we don't determine the token type so far, it is an error.
+ return yaml_parser_set_scanner_error(parser,
+ "while scanning for the next token", parser.mark,
+ "found character that cannot start any token")
+}
+
+func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) {
+ if !simple_key.possible {
+ return false, true
+ }
+
+ // The 1.2 specification says:
+ //
+ // "If the ? indicator is omitted, parsing needs to see past the
+ // implicit key to recognize it as such. To limit the amount of
+ // lookahead required, the “:” indicator must appear at most 1024
+ // Unicode characters beyond the start of the key. In addition, the key
+ // is restricted to a single line."
+ //
+ if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index {
+ // Check if the potential simple key to be removed is required.
+ if simple_key.required {
+ return false, yaml_parser_set_scanner_error(parser,
+ "while scanning a simple key", simple_key.mark,
+ "could not find expected ':'")
+ }
+ simple_key.possible = false
+ return false, true
+ }
+ return true, true
+}
+
+// Check if a simple key may start at the current position and add it if
+// needed.
+func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
+ // A simple key is required at the current position if the scanner is in
+ // the block context and the current column coincides with the indentation
+ // level.
+
+ required := parser.flow_level == 0 && parser.indent == parser.mark.column
+
+ //
+ // If the current position may start a simple key, save it.
+ //
+ if parser.simple_key_allowed {
+ simple_key := yaml_simple_key_t{
+ possible: true,
+ required: required,
+ token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
+ mark: parser.mark,
+ }
+
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+ parser.simple_keys[len(parser.simple_keys)-1] = simple_key
+ parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1
+ }
+ return true
+}
+
+// Remove a potential simple key at the current flow level.
+func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool {
+ i := len(parser.simple_keys) - 1
+ if parser.simple_keys[i].possible {
+ // If the key is required, it is an error.
+ if parser.simple_keys[i].required {
+ return yaml_parser_set_scanner_error(parser,
+ "while scanning a simple key", parser.simple_keys[i].mark,
+ "could not find expected ':'")
+ }
+ // Remove the key from the stack.
+ parser.simple_keys[i].possible = false
+ delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number)
+ }
+ return true
+}
+
+// max_flow_level limits the flow_level
+const max_flow_level = 10000
+
+// Increase the flow level and resize the simple key list if needed.
+func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {
+ // Reset the simple key on the next level.
+ parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{
+ possible: false,
+ required: false,
+ token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
+ mark: parser.mark,
+ })
+
+ // Increase the flow level.
+ parser.flow_level++
+ if parser.flow_level > max_flow_level {
+ return yaml_parser_set_scanner_error(parser,
+ "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark,
+ fmt.Sprintf("exceeded max depth of %d", max_flow_level))
+ }
+ return true
+}
+
+// Decrease the flow level.
+func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool {
+ if parser.flow_level > 0 {
+ parser.flow_level--
+ last := len(parser.simple_keys) - 1
+ delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number)
+ parser.simple_keys = parser.simple_keys[:last]
+ }
+ return true
+}
+
+// max_indents limits the indents stack size
+const max_indents = 10000
+
+// Push the current indentation level to the stack and set the new level
+// the current column is greater than the indentation level. In this case,
+// append or insert the specified token into the token queue.
+func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool {
+ // In the flow context, do nothing.
+ if parser.flow_level > 0 {
+ return true
+ }
+
+ if parser.indent < column {
+ // Push the current indentation level to the stack and set the new
+ // indentation level.
+ parser.indents = append(parser.indents, parser.indent)
+ parser.indent = column
+ if len(parser.indents) > max_indents {
+ return yaml_parser_set_scanner_error(parser,
+ "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark,
+ fmt.Sprintf("exceeded max depth of %d", max_indents))
+ }
+
+ // Create a token and insert it into the queue.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: mark,
+ end_mark: mark,
+ }
+ if number > -1 {
+ number -= parser.tokens_parsed
+ }
+ yaml_insert_token(parser, number, &token)
+ }
+ return true
+}
+
+// Pop indentation levels from the indents stack until the current level
+// becomes less or equal to the column. For each indentation level, append
+// the BLOCK-END token.
+func yaml_parser_unroll_indent(parser *yaml_parser_t, column int, scan_mark yaml_mark_t) bool {
+ // In the flow context, do nothing.
+ if parser.flow_level > 0 {
+ return true
+ }
+
+ block_mark := scan_mark
+ block_mark.index--
+
+ // Loop through the indentation levels in the stack.
+ for parser.indent > column {
+
+ // [Go] Reposition the end token before potential following
+ // foot comments of parent blocks. For that, search
+ // backwards for recent comments that were at the same
+ // indent as the block that is ending now.
+ stop_index := block_mark.index
+ for i := len(parser.comments) - 1; i >= 0; i-- {
+ comment := &parser.comments[i]
+
+ if comment.end_mark.index < stop_index {
+ // Don't go back beyond the start of the comment/whitespace scan, unless column < 0.
+ // If requested indent column is < 0, then the document is over and everything else
+ // is a foot anyway.
+ break
+ }
+ if comment.start_mark.column == parser.indent+1 {
+ // This is a good match. But maybe there's a former comment
+ // at that same indent level, so keep searching.
+ block_mark = comment.start_mark
+ }
+
+ // While the end of the former comment matches with
+ // the start of the following one, we know there's
+ // nothing in between and scanning is still safe.
+ stop_index = comment.scan_mark.index
+ }
+
+ // Create a token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_BLOCK_END_TOKEN,
+ start_mark: block_mark,
+ end_mark: block_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+
+ // Pop the indentation level.
+ parser.indent = parser.indents[len(parser.indents)-1]
+ parser.indents = parser.indents[:len(parser.indents)-1]
+ }
+ return true
+}
+
+// Initialize the scanner and produce the STREAM-START token.
+func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool {
+
+ // Set the initial indentation.
+ parser.indent = -1
+
+ // Initialize the simple key stack.
+ parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{})
+
+ parser.simple_keys_by_tok = make(map[int]int)
+
+ // A simple key is allowed at the beginning of the stream.
+ parser.simple_key_allowed = true
+
+ // We have started.
+ parser.stream_start_produced = true
+
+ // Create the STREAM-START token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_STREAM_START_TOKEN,
+ start_mark: parser.mark,
+ end_mark: parser.mark,
+ encoding: parser.encoding,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the STREAM-END token and shut down the scanner.
+func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {
+
+ // Force new line.
+ if parser.mark.column != 0 {
+ parser.mark.column = 0
+ parser.mark.line++
+ }
+
+ // Reset the indentation level.
+ if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
+ return false
+ }
+
+ // Reset simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ parser.simple_key_allowed = false
+
+ // Create the STREAM-END token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_STREAM_END_TOKEN,
+ start_mark: parser.mark,
+ end_mark: parser.mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.
+func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {
+ // Reset the indentation level.
+ if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
+ return false
+ }
+
+ // Reset simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ parser.simple_key_allowed = false
+
+ // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token.
+ token := yaml_token_t{}
+ if !yaml_parser_scan_directive(parser, &token) {
+ return false
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the DOCUMENT-START or DOCUMENT-END token.
+func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // Reset the indentation level.
+ if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
+ return false
+ }
+
+ // Reset simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ parser.simple_key_allowed = false
+
+ // Consume the token.
+ start_mark := parser.mark
+
+ skip(parser)
+ skip(parser)
+ skip(parser)
+
+ end_mark := parser.mark
+
+ // Create the DOCUMENT-START or DOCUMENT-END token.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
+func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+
+ // The indicators '[' and '{' may start a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // Increase the flow level.
+ if !yaml_parser_increase_flow_level(parser) {
+ return false
+ }
+
+ // A simple key may follow the indicators '[' and '{'.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
+func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // Reset any potential simple key on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Decrease the flow level.
+ if !yaml_parser_decrease_flow_level(parser) {
+ return false
+ }
+
+ // No simple keys after the indicators ']' and '}'.
+ parser.simple_key_allowed = false
+
+ // Consume the token.
+
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the FLOW-ENTRY token.
+func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool {
+ // Reset any potential simple keys on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Simple keys are allowed after ','.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the FLOW-ENTRY token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_FLOW_ENTRY_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the BLOCK-ENTRY token.
+func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool {
+ // Check if the scanner is in the block context.
+ if parser.flow_level == 0 {
+ // Check if we are allowed to start a new entry.
+ if !parser.simple_key_allowed {
+ return yaml_parser_set_scanner_error(parser, "", parser.mark,
+ "block sequence entries are not allowed in this context")
+ }
+ // Add the BLOCK-SEQUENCE-START token if needed.
+ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) {
+ return false
+ }
+ } else {
+ // It is an error for the '-' indicator to occur in the flow context,
+ // but we let the Parser detect and report about it because the Parser
+ // is able to point to the context.
+ }
+
+ // Reset any potential simple keys on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Simple keys are allowed after '-'.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the BLOCK-ENTRY token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_BLOCK_ENTRY_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the KEY token.
+func yaml_parser_fetch_key(parser *yaml_parser_t) bool {
+
+ // In the block context, additional checks are required.
+ if parser.flow_level == 0 {
+ // Check if we are allowed to start a new key (not nessesary simple).
+ if !parser.simple_key_allowed {
+ return yaml_parser_set_scanner_error(parser, "", parser.mark,
+ "mapping keys are not allowed in this context")
+ }
+ // Add the BLOCK-MAPPING-START token if needed.
+ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
+ return false
+ }
+ }
+
+ // Reset any potential simple keys on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Simple keys are allowed after '?' in the block context.
+ parser.simple_key_allowed = parser.flow_level == 0
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the KEY token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_KEY_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the VALUE token.
+func yaml_parser_fetch_value(parser *yaml_parser_t) bool {
+
+ simple_key := &parser.simple_keys[len(parser.simple_keys)-1]
+
+ // Have we found a simple key?
+ if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok {
+ return false
+
+ } else if valid {
+
+ // Create the KEY token and insert it into the queue.
+ token := yaml_token_t{
+ typ: yaml_KEY_TOKEN,
+ start_mark: simple_key.mark,
+ end_mark: simple_key.mark,
+ }
+ yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token)
+
+ // In the block context, we may need to add the BLOCK-MAPPING-START token.
+ if !yaml_parser_roll_indent(parser, simple_key.mark.column,
+ simple_key.token_number,
+ yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) {
+ return false
+ }
+
+ // Remove the simple key.
+ simple_key.possible = false
+ delete(parser.simple_keys_by_tok, simple_key.token_number)
+
+ // A simple key cannot follow another simple key.
+ parser.simple_key_allowed = false
+
+ } else {
+ // The ':' indicator follows a complex key.
+
+ // In the block context, extra checks are required.
+ if parser.flow_level == 0 {
+
+ // Check if we are allowed to start a complex value.
+ if !parser.simple_key_allowed {
+ return yaml_parser_set_scanner_error(parser, "", parser.mark,
+ "mapping values are not allowed in this context")
+ }
+
+ // Add the BLOCK-MAPPING-START token if needed.
+ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
+ return false
+ }
+ }
+
+ // Simple keys after ':' are allowed in the block context.
+ parser.simple_key_allowed = parser.flow_level == 0
+ }
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the VALUE token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_VALUE_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the ALIAS or ANCHOR token.
+func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // An anchor or an alias could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow an anchor or an alias.
+ parser.simple_key_allowed = false
+
+ // Create the ALIAS or ANCHOR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_anchor(parser, &token, typ) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the TAG token.
+func yaml_parser_fetch_tag(parser *yaml_parser_t) bool {
+ // A tag could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow a tag.
+ parser.simple_key_allowed = false
+
+ // Create the TAG token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_tag(parser, &token) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
+func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool {
+ // Remove any potential simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // A simple key may follow a block scalar.
+ parser.simple_key_allowed = true
+
+ // Create the SCALAR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_block_scalar(parser, &token, literal) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
+func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool {
+ // A plain scalar could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow a flow scalar.
+ parser.simple_key_allowed = false
+
+ // Create the SCALAR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_flow_scalar(parser, &token, single) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the SCALAR(...,plain) token.
+func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool {
+ // A plain scalar could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow a flow scalar.
+ parser.simple_key_allowed = false
+
+ // Create the SCALAR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_plain_scalar(parser, &token) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Eat whitespaces and comments until the next token is found.
+func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
+
+ scan_mark := parser.mark
+
+ // Until the next token is not found.
+ for {
+ // Allow the BOM mark to start a line.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ }
+
+ // Eat whitespaces.
+ // Tabs are allowed:
+ // - in the flow context
+ // - in the block context, but not at the beginning of the line or
+ // after '-', '?', or ':' (complex value).
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if we just had a line comment under a sequence entry that
+ // looks more like a header to the following content. Similar to this:
+ //
+ // - # The comment
+ // - Some data
+ //
+ // If so, transform the line comment to a head comment and reposition.
+ if len(parser.comments) > 0 && len(parser.tokens) > 1 {
+ tokenA := parser.tokens[len(parser.tokens)-2]
+ tokenB := parser.tokens[len(parser.tokens)-1]
+ comment := &parser.comments[len(parser.comments)-1]
+ if tokenA.typ == yaml_BLOCK_SEQUENCE_START_TOKEN && tokenB.typ == yaml_BLOCK_ENTRY_TOKEN && len(comment.line) > 0 && !is_break(parser.buffer, parser.buffer_pos) {
+ // If it was in the prior line, reposition so it becomes a
+ // header of the follow up token. Otherwise, keep it in place
+ // so it becomes a header of the former.
+ comment.head = comment.line
+ comment.line = nil
+ if comment.start_mark.line == parser.mark.line-1 {
+ comment.token_mark = parser.mark
+ }
+ }
+ }
+
+ // Eat a comment until a line break.
+ if parser.buffer[parser.buffer_pos] == '#' {
+ if !yaml_parser_scan_comments(parser, scan_mark) {
+ return false
+ }
+ }
+
+ // If it is a line break, eat it.
+ if is_break(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+
+ // In the block context, a new line may start a simple key.
+ if parser.flow_level == 0 {
+ parser.simple_key_allowed = true
+ }
+ } else {
+ break // We have found a token.
+ }
+ }
+
+ return true
+}
+
+// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool {
+ // Eat '%'.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Scan the directive name.
+ var name []byte
+ if !yaml_parser_scan_directive_name(parser, start_mark, &name) {
+ return false
+ }
+
+ // Is it a YAML directive?
+ if bytes.Equal(name, []byte("YAML")) {
+ // Scan the VERSION directive value.
+ var major, minor int8
+ if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) {
+ return false
+ }
+ end_mark := parser.mark
+
+ // Create a VERSION-DIRECTIVE token.
+ *token = yaml_token_t{
+ typ: yaml_VERSION_DIRECTIVE_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ major: major,
+ minor: minor,
+ }
+
+ // Is it a TAG directive?
+ } else if bytes.Equal(name, []byte("TAG")) {
+ // Scan the TAG directive value.
+ var handle, prefix []byte
+ if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) {
+ return false
+ }
+ end_mark := parser.mark
+
+ // Create a TAG-DIRECTIVE token.
+ *token = yaml_token_t{
+ typ: yaml_TAG_DIRECTIVE_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: handle,
+ prefix: prefix,
+ }
+
+ // Unknown directive.
+ } else {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "found unknown directive name")
+ return false
+ }
+
+ // Eat the rest of the line including any comments.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ if parser.buffer[parser.buffer_pos] == '#' {
+ // [Go] Discard this inline comment for the time being.
+ //if !yaml_parser_scan_line_comment(parser, start_mark) {
+ // return false
+ //}
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ }
+
+ // Check if we are at the end of the line.
+ if !is_breakz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "did not find expected comment or line break")
+ return false
+ }
+
+ // Eat a line break.
+ if is_break(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ }
+
+ return true
+}
+
+// Scan the directive name.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^^^^
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^
+//
+func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool {
+ // Consume the directive name.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ var s []byte
+ for is_alpha(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if the name is empty.
+ if len(s) == 0 {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "could not find expected directive name")
+ return false
+ }
+
+ // Check for an blank character after the name.
+ if !is_blankz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "found unexpected non-alphabetical character")
+ return false
+ }
+ *name = s
+ return true
+}
+
+// Scan the value of VERSION-DIRECTIVE.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^^^^^^
+func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool {
+ // Eat whitespaces.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Consume the major version number.
+ if !yaml_parser_scan_version_directive_number(parser, start_mark, major) {
+ return false
+ }
+
+ // Eat '.'.
+ if parser.buffer[parser.buffer_pos] != '.' {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "did not find expected digit or '.' character")
+ }
+
+ skip(parser)
+
+ // Consume the minor version number.
+ if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) {
+ return false
+ }
+ return true
+}
+
+const max_number_length = 2
+
+// Scan the version number of VERSION-DIRECTIVE.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^
+// %YAML 1.1 # a comment \n
+// ^
+func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool {
+
+ // Repeat while the next character is digit.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ var value, length int8
+ for is_digit(parser.buffer, parser.buffer_pos) {
+ // Check if the number is too long.
+ length++
+ if length > max_number_length {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "found extremely long version number")
+ }
+ value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos))
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if the number was present.
+ if length == 0 {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "did not find expected version number")
+ }
+ *number = value
+ return true
+}
+
+// Scan the value of a TAG-DIRECTIVE token.
+//
+// Scope:
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool {
+ var handle_value, prefix_value []byte
+
+ // Eat whitespaces.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Scan a handle.
+ if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) {
+ return false
+ }
+
+ // Expect a whitespace.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if !is_blank(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+ start_mark, "did not find expected whitespace")
+ return false
+ }
+
+ // Eat whitespaces.
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Scan a prefix.
+ if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) {
+ return false
+ }
+
+ // Expect a whitespace or line break.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if !is_blankz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+ start_mark, "did not find expected whitespace or line break")
+ return false
+ }
+
+ *handle = handle_value
+ *prefix = prefix_value
+ return true
+}
+
+func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool {
+ var s []byte
+
+ // Eat the indicator character.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Consume the value.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_alpha(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ end_mark := parser.mark
+
+ /*
+ * Check if length of the anchor is greater than 0 and it is followed by
+ * a whitespace character or one of the indicators:
+ *
+ * '?', ':', ',', ']', '}', '%', '@', '`'.
+ */
+
+ if len(s) == 0 ||
+ !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' ||
+ parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' ||
+ parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' ||
+ parser.buffer[parser.buffer_pos] == '`') {
+ context := "while scanning an alias"
+ if typ == yaml_ANCHOR_TOKEN {
+ context = "while scanning an anchor"
+ }
+ yaml_parser_set_scanner_error(parser, context, start_mark,
+ "did not find expected alphabetic or numeric character")
+ return false
+ }
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ }
+
+ return true
+}
+
+/*
+ * Scan a TAG token.
+ */
+
+func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool {
+ var handle, suffix []byte
+
+ start_mark := parser.mark
+
+ // Check if the tag is in the canonical form.
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ if parser.buffer[parser.buffer_pos+1] == '<' {
+ // Keep the handle as ''
+
+ // Eat '!<'
+ skip(parser)
+ skip(parser)
+
+ // Consume the tag value.
+ if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
+ return false
+ }
+
+ // Check for '>' and eat it.
+ if parser.buffer[parser.buffer_pos] != '>' {
+ yaml_parser_set_scanner_error(parser, "while scanning a tag",
+ start_mark, "did not find the expected '>'")
+ return false
+ }
+
+ skip(parser)
+ } else {
+ // The tag has either the '!suffix' or the '!handle!suffix' form.
+
+ // First, try to scan a handle.
+ if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) {
+ return false
+ }
+
+ // Check if it is, indeed, handle.
+ if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' {
+ // Scan the suffix now.
+ if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
+ return false
+ }
+ } else {
+ // It wasn't a handle after all. Scan the rest of the tag.
+ if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) {
+ return false
+ }
+
+ // Set the handle to '!'.
+ handle = []byte{'!'}
+
+ // A special case: the '!' tag. Set the handle to '' and the
+ // suffix to '!'.
+ if len(suffix) == 0 {
+ handle, suffix = suffix, handle
+ }
+ }
+ }
+
+ // Check the character which ends the tag.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if !is_blankz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a tag",
+ start_mark, "did not find expected whitespace or line break")
+ return false
+ }
+
+ end_mark := parser.mark
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_TAG_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: handle,
+ suffix: suffix,
+ }
+ return true
+}
+
+// Scan a tag handle.
+func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool {
+ // Check the initial '!' character.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if parser.buffer[parser.buffer_pos] != '!' {
+ yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find expected '!'")
+ return false
+ }
+
+ var s []byte
+
+ // Copy the '!' character.
+ s = read(parser, s)
+
+ // Copy all subsequent alphabetical and numerical characters.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for is_alpha(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if the trailing character is '!' and copy it.
+ if parser.buffer[parser.buffer_pos] == '!' {
+ s = read(parser, s)
+ } else {
+ // It's either the '!' tag or not really a tag handle. If it's a %TAG
+ // directive, it's an error. If it's a tag token, it must be a part of URI.
+ if directive && string(s) != "!" {
+ yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find expected '!'")
+ return false
+ }
+ }
+
+ *handle = s
+ return true
+}
+
+// Scan a tag.
+func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool {
+ //size_t length = head ? strlen((char *)head) : 0
+ var s []byte
+ hasTag := len(head) > 0
+
+ // Copy the head if needed.
+ //
+ // Note that we don't copy the leading '!' character.
+ if len(head) > 1 {
+ s = append(s, head[1:]...)
+ }
+
+ // Scan the tag.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // The set of characters that may appear in URI is as follows:
+ //
+ // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
+ // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
+ // '%'.
+ // [Go] TODO Convert this into more reasonable logic.
+ for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' ||
+ parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' ||
+ parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' ||
+ parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' ||
+ parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' ||
+ parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' ||
+ parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' ||
+ parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' ||
+ parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' ||
+ parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' ||
+ parser.buffer[parser.buffer_pos] == '%' {
+ // Check if it is a URI-escape sequence.
+ if parser.buffer[parser.buffer_pos] == '%' {
+ if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) {
+ return false
+ }
+ } else {
+ s = read(parser, s)
+ }
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ hasTag = true
+ }
+
+ if !hasTag {
+ yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find expected tag URI")
+ return false
+ }
+ *uri = s
+ return true
+}
+
+// Decode an URI-escape sequence corresponding to a single UTF-8 character.
+func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool {
+
+ // Decode the required number of characters.
+ w := 1024
+ for w > 0 {
+ // Check for a URI-escaped octet.
+ if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
+ return false
+ }
+
+ if !(parser.buffer[parser.buffer_pos] == '%' &&
+ is_hex(parser.buffer, parser.buffer_pos+1) &&
+ is_hex(parser.buffer, parser.buffer_pos+2)) {
+ return yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find URI escaped octet")
+ }
+
+ // Get the octet.
+ octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2))
+
+ // If it is the leading octet, determine the length of the UTF-8 sequence.
+ if w == 1024 {
+ w = width(octet)
+ if w == 0 {
+ return yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "found an incorrect leading UTF-8 octet")
+ }
+ } else {
+ // Check if the trailing octet is correct.
+ if octet&0xC0 != 0x80 {
+ return yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "found an incorrect trailing UTF-8 octet")
+ }
+ }
+
+ // Copy the octet and move the pointers.
+ *s = append(*s, octet)
+ skip(parser)
+ skip(parser)
+ skip(parser)
+ w--
+ }
+ return true
+}
+
+// Scan a block scalar.
+func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool {
+ // Eat the indicator '|' or '>'.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Scan the additional block scalar indicators.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // Check for a chomping indicator.
+ var chomping, increment int
+ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+ // Set the chomping method and eat the indicator.
+ if parser.buffer[parser.buffer_pos] == '+' {
+ chomping = +1
+ } else {
+ chomping = -1
+ }
+ skip(parser)
+
+ // Check for an indentation indicator.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if is_digit(parser.buffer, parser.buffer_pos) {
+ // Check that the indentation is greater than 0.
+ if parser.buffer[parser.buffer_pos] == '0' {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found an indentation indicator equal to 0")
+ return false
+ }
+
+ // Get the indentation level and eat the indicator.
+ increment = as_digit(parser.buffer, parser.buffer_pos)
+ skip(parser)
+ }
+
+ } else if is_digit(parser.buffer, parser.buffer_pos) {
+ // Do the same as above, but in the opposite order.
+
+ if parser.buffer[parser.buffer_pos] == '0' {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found an indentation indicator equal to 0")
+ return false
+ }
+ increment = as_digit(parser.buffer, parser.buffer_pos)
+ skip(parser)
+
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+ if parser.buffer[parser.buffer_pos] == '+' {
+ chomping = +1
+ } else {
+ chomping = -1
+ }
+ skip(parser)
+ }
+ }
+
+ // Eat whitespaces and comments to the end of the line.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ if parser.buffer[parser.buffer_pos] == '#' {
+ if !yaml_parser_scan_line_comment(parser, start_mark) {
+ return false
+ }
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ }
+
+ // Check if we are at the end of the line.
+ if !is_breakz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "did not find expected comment or line break")
+ return false
+ }
+
+ // Eat a line break.
+ if is_break(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ }
+
+ end_mark := parser.mark
+
+ // Set the indentation level if it was specified.
+ var indent int
+ if increment > 0 {
+ if parser.indent >= 0 {
+ indent = parser.indent + increment
+ } else {
+ indent = increment
+ }
+ }
+
+ // Scan the leading line breaks and determine the indentation level if needed.
+ var s, leading_break, trailing_breaks []byte
+ if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
+ return false
+ }
+
+ // Scan the block scalar content.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ var leading_blank, trailing_blank bool
+ for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) {
+ // We are at the beginning of a non-empty line.
+
+ // Is it a trailing whitespace?
+ trailing_blank = is_blank(parser.buffer, parser.buffer_pos)
+
+ // Check if we need to fold the leading line break.
+ if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' {
+ // Do we need to join the lines by space?
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ }
+ } else {
+ s = append(s, leading_break...)
+ }
+ leading_break = leading_break[:0]
+
+ // Append the remaining line breaks.
+ s = append(s, trailing_breaks...)
+ trailing_breaks = trailing_breaks[:0]
+
+ // Is it a leading whitespace?
+ leading_blank = is_blank(parser.buffer, parser.buffer_pos)
+
+ // Consume the current line.
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Consume the line break.
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ leading_break = read_line(parser, leading_break)
+
+ // Eat the following indentation spaces and line breaks.
+ if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
+ return false
+ }
+ }
+
+ // Chomp the tail.
+ if chomping != -1 {
+ s = append(s, leading_break...)
+ }
+ if chomping == 1 {
+ s = append(s, trailing_breaks...)
+ }
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_SCALAR_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ style: yaml_LITERAL_SCALAR_STYLE,
+ }
+ if !literal {
+ token.style = yaml_FOLDED_SCALAR_STYLE
+ }
+ return true
+}
+
+// Scan indentation spaces and line breaks for a block scalar. Determine the
+// indentation level if needed.
+func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool {
+ *end_mark = parser.mark
+
+ // Eat the indentation spaces and line breaks.
+ max_indent := 0
+ for {
+ // Eat the indentation spaces.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ if parser.mark.column > max_indent {
+ max_indent = parser.mark.column
+ }
+
+ // Check for a tab character messing the indentation.
+ if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) {
+ return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found a tab character where an indentation space is expected")
+ }
+
+ // Have we found a non-empty line?
+ if !is_break(parser.buffer, parser.buffer_pos) {
+ break
+ }
+
+ // Consume the line break.
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ // [Go] Should really be returning breaks instead.
+ *breaks = read_line(parser, *breaks)
+ *end_mark = parser.mark
+ }
+
+ // Determine the indentation level if needed.
+ if *indent == 0 {
+ *indent = max_indent
+ if *indent < parser.indent+1 {
+ *indent = parser.indent + 1
+ }
+ if *indent < 1 {
+ *indent = 1
+ }
+ }
+ return true
+}
+
+// Scan a quoted scalar.
+func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool {
+ // Eat the left quote.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Consume the content of the quoted scalar.
+ var s, leading_break, trailing_breaks, whitespaces []byte
+ for {
+ // Check that there are no document indicators at the beginning of the line.
+ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+ return false
+ }
+
+ if parser.mark.column == 0 &&
+ ((parser.buffer[parser.buffer_pos+0] == '-' &&
+ parser.buffer[parser.buffer_pos+1] == '-' &&
+ parser.buffer[parser.buffer_pos+2] == '-') ||
+ (parser.buffer[parser.buffer_pos+0] == '.' &&
+ parser.buffer[parser.buffer_pos+1] == '.' &&
+ parser.buffer[parser.buffer_pos+2] == '.')) &&
+ is_blankz(parser.buffer, parser.buffer_pos+3) {
+ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+ start_mark, "found unexpected document indicator")
+ return false
+ }
+
+ // Check for EOF.
+ if is_z(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+ start_mark, "found unexpected end of stream")
+ return false
+ }
+
+ // Consume non-blank characters.
+ leading_blanks := false
+ for !is_blankz(parser.buffer, parser.buffer_pos) {
+ if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' {
+ // Is is an escaped single quote.
+ s = append(s, '\'')
+ skip(parser)
+ skip(parser)
+
+ } else if single && parser.buffer[parser.buffer_pos] == '\'' {
+ // It is a right single quote.
+ break
+ } else if !single && parser.buffer[parser.buffer_pos] == '"' {
+ // It is a right double quote.
+ break
+
+ } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) {
+ // It is an escaped line break.
+ if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
+ return false
+ }
+ skip(parser)
+ skip_line(parser)
+ leading_blanks = true
+ break
+
+ } else if !single && parser.buffer[parser.buffer_pos] == '\\' {
+ // It is an escape sequence.
+ code_length := 0
+
+ // Check the escape character.
+ switch parser.buffer[parser.buffer_pos+1] {
+ case '0':
+ s = append(s, 0)
+ case 'a':
+ s = append(s, '\x07')
+ case 'b':
+ s = append(s, '\x08')
+ case 't', '\t':
+ s = append(s, '\x09')
+ case 'n':
+ s = append(s, '\x0A')
+ case 'v':
+ s = append(s, '\x0B')
+ case 'f':
+ s = append(s, '\x0C')
+ case 'r':
+ s = append(s, '\x0D')
+ case 'e':
+ s = append(s, '\x1B')
+ case ' ':
+ s = append(s, '\x20')
+ case '"':
+ s = append(s, '"')
+ case '\'':
+ s = append(s, '\'')
+ case '\\':
+ s = append(s, '\\')
+ case 'N': // NEL (#x85)
+ s = append(s, '\xC2')
+ s = append(s, '\x85')
+ case '_': // #xA0
+ s = append(s, '\xC2')
+ s = append(s, '\xA0')
+ case 'L': // LS (#x2028)
+ s = append(s, '\xE2')
+ s = append(s, '\x80')
+ s = append(s, '\xA8')
+ case 'P': // PS (#x2029)
+ s = append(s, '\xE2')
+ s = append(s, '\x80')
+ s = append(s, '\xA9')
+ case 'x':
+ code_length = 2
+ case 'u':
+ code_length = 4
+ case 'U':
+ code_length = 8
+ default:
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "found unknown escape character")
+ return false
+ }
+
+ skip(parser)
+ skip(parser)
+
+ // Consume an arbitrary escape code.
+ if code_length > 0 {
+ var value int
+
+ // Scan the character value.
+ if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) {
+ return false
+ }
+ for k := 0; k < code_length; k++ {
+ if !is_hex(parser.buffer, parser.buffer_pos+k) {
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "did not find expected hexdecimal number")
+ return false
+ }
+ value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k)
+ }
+
+ // Check the value and write the character.
+ if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF {
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "found invalid Unicode character escape code")
+ return false
+ }
+ if value <= 0x7F {
+ s = append(s, byte(value))
+ } else if value <= 0x7FF {
+ s = append(s, byte(0xC0+(value>>6)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ } else if value <= 0xFFFF {
+ s = append(s, byte(0xE0+(value>>12)))
+ s = append(s, byte(0x80+((value>>6)&0x3F)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ } else {
+ s = append(s, byte(0xF0+(value>>18)))
+ s = append(s, byte(0x80+((value>>12)&0x3F)))
+ s = append(s, byte(0x80+((value>>6)&0x3F)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ }
+
+ // Advance the pointer.
+ for k := 0; k < code_length; k++ {
+ skip(parser)
+ }
+ }
+ } else {
+ // It is a non-escaped non-blank character.
+ s = read(parser, s)
+ }
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ }
+
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // Check if we are at the end of the scalar.
+ if single {
+ if parser.buffer[parser.buffer_pos] == '\'' {
+ break
+ }
+ } else {
+ if parser.buffer[parser.buffer_pos] == '"' {
+ break
+ }
+ }
+
+ // Consume blank characters.
+ for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
+ if is_blank(parser.buffer, parser.buffer_pos) {
+ // Consume a space or a tab character.
+ if !leading_blanks {
+ whitespaces = read(parser, whitespaces)
+ } else {
+ skip(parser)
+ }
+ } else {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ // Check if it is a first line break.
+ if !leading_blanks {
+ whitespaces = whitespaces[:0]
+ leading_break = read_line(parser, leading_break)
+ leading_blanks = true
+ } else {
+ trailing_breaks = read_line(parser, trailing_breaks)
+ }
+ }
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Join the whitespaces or fold line breaks.
+ if leading_blanks {
+ // Do we need to fold line breaks?
+ if len(leading_break) > 0 && leading_break[0] == '\n' {
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ } else {
+ s = append(s, trailing_breaks...)
+ }
+ } else {
+ s = append(s, leading_break...)
+ s = append(s, trailing_breaks...)
+ }
+ trailing_breaks = trailing_breaks[:0]
+ leading_break = leading_break[:0]
+ } else {
+ s = append(s, whitespaces...)
+ whitespaces = whitespaces[:0]
+ }
+ }
+
+ // Eat the right quote.
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_SCALAR_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ style: yaml_SINGLE_QUOTED_SCALAR_STYLE,
+ }
+ if !single {
+ token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ return true
+}
+
+// Scan a plain scalar.
+func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool {
+
+ var s, leading_break, trailing_breaks, whitespaces []byte
+ var leading_blanks bool
+ var indent = parser.indent + 1
+
+ start_mark := parser.mark
+ end_mark := parser.mark
+
+ // Consume the content of the plain scalar.
+ for {
+ // Check for a document indicator.
+ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+ return false
+ }
+ if parser.mark.column == 0 &&
+ ((parser.buffer[parser.buffer_pos+0] == '-' &&
+ parser.buffer[parser.buffer_pos+1] == '-' &&
+ parser.buffer[parser.buffer_pos+2] == '-') ||
+ (parser.buffer[parser.buffer_pos+0] == '.' &&
+ parser.buffer[parser.buffer_pos+1] == '.' &&
+ parser.buffer[parser.buffer_pos+2] == '.')) &&
+ is_blankz(parser.buffer, parser.buffer_pos+3) {
+ break
+ }
+
+ // Check for a comment.
+ if parser.buffer[parser.buffer_pos] == '#' {
+ break
+ }
+
+ // Consume non-blank characters.
+ for !is_blankz(parser.buffer, parser.buffer_pos) {
+
+ // Check for indicators that may end a plain scalar.
+ if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) ||
+ (parser.flow_level > 0 &&
+ (parser.buffer[parser.buffer_pos] == ',' ||
+ parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+ parser.buffer[parser.buffer_pos] == '}')) {
+ break
+ }
+
+ // Check if we need to join whitespaces and breaks.
+ if leading_blanks || len(whitespaces) > 0 {
+ if leading_blanks {
+ // Do we need to fold line breaks?
+ if leading_break[0] == '\n' {
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ } else {
+ s = append(s, trailing_breaks...)
+ }
+ } else {
+ s = append(s, leading_break...)
+ s = append(s, trailing_breaks...)
+ }
+ trailing_breaks = trailing_breaks[:0]
+ leading_break = leading_break[:0]
+ leading_blanks = false
+ } else {
+ s = append(s, whitespaces...)
+ whitespaces = whitespaces[:0]
+ }
+ }
+
+ // Copy the character.
+ s = read(parser, s)
+
+ end_mark = parser.mark
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ }
+
+ // Is it the end?
+ if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) {
+ break
+ }
+
+ // Consume blank characters.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
+ if is_blank(parser.buffer, parser.buffer_pos) {
+
+ // Check for tab characters that abuse indentation.
+ if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
+ start_mark, "found a tab character that violates indentation")
+ return false
+ }
+
+ // Consume a space or a tab character.
+ if !leading_blanks {
+ whitespaces = read(parser, whitespaces)
+ } else {
+ skip(parser)
+ }
+ } else {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ // Check if it is a first line break.
+ if !leading_blanks {
+ whitespaces = whitespaces[:0]
+ leading_break = read_line(parser, leading_break)
+ leading_blanks = true
+ } else {
+ trailing_breaks = read_line(parser, trailing_breaks)
+ }
+ }
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check indentation level.
+ if parser.flow_level == 0 && parser.mark.column < indent {
+ break
+ }
+ }
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_SCALAR_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ style: yaml_PLAIN_SCALAR_STYLE,
+ }
+
+ // Note that we change the 'simple_key_allowed' flag.
+ if leading_blanks {
+ parser.simple_key_allowed = true
+ }
+ return true
+}
+
+func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool {
+ if parser.newlines > 0 {
+ return true
+ }
+
+ var start_mark yaml_mark_t
+ var text []byte
+
+ for peek := 0; peek < 512; peek++ {
+ if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) {
+ break
+ }
+ if is_blank(parser.buffer, parser.buffer_pos+peek) {
+ continue
+ }
+ if parser.buffer[parser.buffer_pos+peek] == '#' {
+ seen := parser.mark.index+peek
+ for {
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if is_breakz(parser.buffer, parser.buffer_pos) {
+ if parser.mark.index >= seen {
+ break
+ }
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ } else if parser.mark.index >= seen {
+ if len(text) == 0 {
+ start_mark = parser.mark
+ }
+ text = read(parser, text)
+ } else {
+ skip(parser)
+ }
+ }
+ }
+ break
+ }
+ if len(text) > 0 {
+ parser.comments = append(parser.comments, yaml_comment_t{
+ token_mark: token_mark,
+ start_mark: start_mark,
+ line: text,
+ })
+ }
+ return true
+}
+
+func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) bool {
+ token := parser.tokens[len(parser.tokens)-1]
+
+ if token.typ == yaml_FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 {
+ token = parser.tokens[len(parser.tokens)-2]
+ }
+
+ var token_mark = token.start_mark
+ var start_mark yaml_mark_t
+ var next_indent = parser.indent
+ if next_indent < 0 {
+ next_indent = 0
+ }
+
+ var recent_empty = false
+ var first_empty = parser.newlines <= 1
+
+ var line = parser.mark.line
+ var column = parser.mark.column
+
+ var text []byte
+
+ // The foot line is the place where a comment must start to
+ // still be considered as a foot of the prior content.
+ // If there's some content in the currently parsed line, then
+ // the foot is the line below it.
+ var foot_line = -1
+ if scan_mark.line > 0 {
+ foot_line = parser.mark.line-parser.newlines+1
+ if parser.newlines == 0 && parser.mark.column > 1 {
+ foot_line++
+ }
+ }
+
+ var peek = 0
+ for ; peek < 512; peek++ {
+ if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) {
+ break
+ }
+ column++
+ if is_blank(parser.buffer, parser.buffer_pos+peek) {
+ continue
+ }
+ c := parser.buffer[parser.buffer_pos+peek]
+ var close_flow = parser.flow_level > 0 && (c == ']' || c == '}')
+ if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) {
+ // Got line break or terminator.
+ if close_flow || !recent_empty {
+ if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) {
+ // This is the first empty line and there were no empty lines before,
+ // so this initial part of the comment is a foot of the prior token
+ // instead of being a head for the following one. Split it up.
+ // Alternatively, this might also be the last comment inside a flow
+ // scope, so it must be a footer.
+ if len(text) > 0 {
+ if start_mark.column-1 < next_indent {
+ // If dedented it's unrelated to the prior token.
+ token_mark = start_mark
+ }
+ parser.comments = append(parser.comments, yaml_comment_t{
+ scan_mark: scan_mark,
+ token_mark: token_mark,
+ start_mark: start_mark,
+ end_mark: yaml_mark_t{parser.mark.index + peek, line, column},
+ foot: text,
+ })
+ scan_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+ token_mark = scan_mark
+ text = nil
+ }
+ } else {
+ if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 {
+ text = append(text, '\n')
+ }
+ }
+ }
+ if !is_break(parser.buffer, parser.buffer_pos+peek) {
+ break
+ }
+ first_empty = false
+ recent_empty = true
+ column = 0
+ line++
+ continue
+ }
+
+ if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) {
+ // The comment at the different indentation is a foot of the
+ // preceding data rather than a head of the upcoming one.
+ parser.comments = append(parser.comments, yaml_comment_t{
+ scan_mark: scan_mark,
+ token_mark: token_mark,
+ start_mark: start_mark,
+ end_mark: yaml_mark_t{parser.mark.index + peek, line, column},
+ foot: text,
+ })
+ scan_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+ token_mark = scan_mark
+ text = nil
+ }
+
+ if parser.buffer[parser.buffer_pos+peek] != '#' {
+ break
+ }
+
+ if len(text) == 0 {
+ start_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+ } else {
+ text = append(text, '\n')
+ }
+
+ recent_empty = false
+
+ // Consume until after the consumed comment line.
+ seen := parser.mark.index+peek
+ for {
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if is_breakz(parser.buffer, parser.buffer_pos) {
+ if parser.mark.index >= seen {
+ break
+ }
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ } else if parser.mark.index >= seen {
+ text = read(parser, text)
+ } else {
+ skip(parser)
+ }
+ }
+
+ peek = 0
+ column = 0
+ line = parser.mark.line
+ next_indent = parser.indent
+ if next_indent < 0 {
+ next_indent = 0
+ }
+ }
+
+ if len(text) > 0 {
+ parser.comments = append(parser.comments, yaml_comment_t{
+ scan_mark: scan_mark,
+ token_mark: start_mark,
+ start_mark: start_mark,
+ end_mark: yaml_mark_t{parser.mark.index + peek - 1, line, column},
+ head: text,
+ })
+ }
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v3/sorter.go b/vendor/gopkg.in/yaml.v3/sorter.go
new file mode 100644
index 0000000..9210ece
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/sorter.go
@@ -0,0 +1,134 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// 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 yaml
+
+import (
+ "reflect"
+ "unicode"
+)
+
+type keyList []reflect.Value
+
+func (l keyList) Len() int { return len(l) }
+func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l keyList) Less(i, j int) bool {
+ a := l[i]
+ b := l[j]
+ ak := a.Kind()
+ bk := b.Kind()
+ for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
+ a = a.Elem()
+ ak = a.Kind()
+ }
+ for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
+ b = b.Elem()
+ bk = b.Kind()
+ }
+ af, aok := keyFloat(a)
+ bf, bok := keyFloat(b)
+ if aok && bok {
+ if af != bf {
+ return af < bf
+ }
+ if ak != bk {
+ return ak < bk
+ }
+ return numLess(a, b)
+ }
+ if ak != reflect.String || bk != reflect.String {
+ return ak < bk
+ }
+ ar, br := []rune(a.String()), []rune(b.String())
+ digits := false
+ for i := 0; i < len(ar) && i < len(br); i++ {
+ if ar[i] == br[i] {
+ digits = unicode.IsDigit(ar[i])
+ continue
+ }
+ al := unicode.IsLetter(ar[i])
+ bl := unicode.IsLetter(br[i])
+ if al && bl {
+ return ar[i] < br[i]
+ }
+ if al || bl {
+ if digits {
+ return al
+ } else {
+ return bl
+ }
+ }
+ var ai, bi int
+ var an, bn int64
+ if ar[i] == '0' || br[i] == '0' {
+ for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
+ if ar[j] != '0' {
+ an = 1
+ bn = 1
+ break
+ }
+ }
+ }
+ for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
+ an = an*10 + int64(ar[ai]-'0')
+ }
+ for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
+ bn = bn*10 + int64(br[bi]-'0')
+ }
+ if an != bn {
+ return an < bn
+ }
+ if ai != bi {
+ return ai < bi
+ }
+ return ar[i] < br[i]
+ }
+ return len(ar) < len(br)
+}
+
+// keyFloat returns a float value for v if it is a number/bool
+// and whether it is a number/bool or not.
+func keyFloat(v reflect.Value) (f float64, ok bool) {
+ switch v.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return float64(v.Int()), true
+ case reflect.Float32, reflect.Float64:
+ return v.Float(), true
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return float64(v.Uint()), true
+ case reflect.Bool:
+ if v.Bool() {
+ return 1, true
+ }
+ return 0, true
+ }
+ return 0, false
+}
+
+// numLess returns whether a < b.
+// a and b must necessarily have the same kind.
+func numLess(a, b reflect.Value) bool {
+ switch a.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return a.Int() < b.Int()
+ case reflect.Float32, reflect.Float64:
+ return a.Float() < b.Float()
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return a.Uint() < b.Uint()
+ case reflect.Bool:
+ return !a.Bool() && b.Bool()
+ }
+ panic("not a number")
+}
diff --git a/vendor/gopkg.in/yaml.v3/writerc.go b/vendor/gopkg.in/yaml.v3/writerc.go
new file mode 100644
index 0000000..b8a116b
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/writerc.go
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+// Set the writer error and return false.
+func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
+ emitter.error = yaml_WRITER_ERROR
+ emitter.problem = problem
+ return false
+}
+
+// Flush the output buffer.
+func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
+ if emitter.write_handler == nil {
+ panic("write handler not set")
+ }
+
+ // Check if the buffer is empty.
+ if emitter.buffer_pos == 0 {
+ return true
+ }
+
+ if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
+ return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
+ }
+ emitter.buffer_pos = 0
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v3/yaml.go b/vendor/gopkg.in/yaml.v3/yaml.go
new file mode 100644
index 0000000..8cec6da
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/yaml.go
@@ -0,0 +1,698 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// 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 yaml implements YAML support for the Go language.
+//
+// Source code and other details for the project are available at GitHub:
+//
+// https://github.com/go-yaml/yaml
+//
+package yaml
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+ "strings"
+ "sync"
+ "unicode/utf8"
+)
+
+// The Unmarshaler interface may be implemented by types to customize their
+// behavior when being unmarshaled from a YAML document.
+type Unmarshaler interface {
+ UnmarshalYAML(value *Node) error
+}
+
+type obsoleteUnmarshaler interface {
+ UnmarshalYAML(unmarshal func(interface{}) error) error
+}
+
+// The Marshaler interface may be implemented by types to customize their
+// behavior when being marshaled into a YAML document. The returned value
+// is marshaled in place of the original value implementing Marshaler.
+//
+// If an error is returned by MarshalYAML, the marshaling procedure stops
+// and returns with the provided error.
+type Marshaler interface {
+ MarshalYAML() (interface{}, error)
+}
+
+// Unmarshal decodes the first document found within the in byte slice
+// and assigns decoded values into the out value.
+//
+// Maps and pointers (to a struct, string, int, etc) are accepted as out
+// values. If an internal pointer within a struct is not initialized,
+// the yaml package will initialize it if necessary for unmarshalling
+// the provided data. The out parameter must not be nil.
+//
+// The type of the decoded values should be compatible with the respective
+// values in out. If one or more values cannot be decoded due to a type
+// mismatches, decoding continues partially until the end of the YAML
+// content, and a *yaml.TypeError is returned with details for all
+// missed values.
+//
+// Struct fields are only unmarshalled if they are exported (have an
+// upper case first letter), and are unmarshalled using the field name
+// lowercased as the default key. Custom keys may be defined via the
+// "yaml" name in the field tag: the content preceding the first comma
+// is used as the key, and the following comma-separated options are
+// used to tweak the marshalling process (see Marshal).
+// Conflicting names result in a runtime error.
+//
+// For example:
+//
+// type T struct {
+// F int `yaml:"a,omitempty"`
+// B int
+// }
+// var t T
+// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
+//
+// See the documentation of Marshal for the format of tags and a list of
+// supported tag options.
+//
+func Unmarshal(in []byte, out interface{}) (err error) {
+ return unmarshal(in, out, false)
+}
+
+// A Decoder reads and decodes YAML values from an input stream.
+type Decoder struct {
+ parser *parser
+ knownFields bool
+}
+
+// NewDecoder returns a new decoder that reads from r.
+//
+// The decoder introduces its own buffering and may read
+// data from r beyond the YAML values requested.
+func NewDecoder(r io.Reader) *Decoder {
+ return &Decoder{
+ parser: newParserFromReader(r),
+ }
+}
+
+// KnownFields ensures that the keys in decoded mappings to
+// exist as fields in the struct being decoded into.
+func (dec *Decoder) KnownFields(enable bool) {
+ dec.knownFields = enable
+}
+
+// Decode reads the next YAML-encoded value from its input
+// and stores it in the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (dec *Decoder) Decode(v interface{}) (err error) {
+ d := newDecoder()
+ d.knownFields = dec.knownFields
+ defer handleErr(&err)
+ node := dec.parser.parse()
+ if node == nil {
+ return io.EOF
+ }
+ out := reflect.ValueOf(v)
+ if out.Kind() == reflect.Ptr && !out.IsNil() {
+ out = out.Elem()
+ }
+ d.unmarshal(node, out)
+ if len(d.terrors) > 0 {
+ return &TypeError{d.terrors}
+ }
+ return nil
+}
+
+// Decode decodes the node and stores its data into the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (n *Node) Decode(v interface{}) (err error) {
+ d := newDecoder()
+ defer handleErr(&err)
+ out := reflect.ValueOf(v)
+ if out.Kind() == reflect.Ptr && !out.IsNil() {
+ out = out.Elem()
+ }
+ d.unmarshal(n, out)
+ if len(d.terrors) > 0 {
+ return &TypeError{d.terrors}
+ }
+ return nil
+}
+
+func unmarshal(in []byte, out interface{}, strict bool) (err error) {
+ defer handleErr(&err)
+ d := newDecoder()
+ p := newParser(in)
+ defer p.destroy()
+ node := p.parse()
+ if node != nil {
+ v := reflect.ValueOf(out)
+ if v.Kind() == reflect.Ptr && !v.IsNil() {
+ v = v.Elem()
+ }
+ d.unmarshal(node, v)
+ }
+ if len(d.terrors) > 0 {
+ return &TypeError{d.terrors}
+ }
+ return nil
+}
+
+// Marshal serializes the value provided into a YAML document. The structure
+// of the generated document will reflect the structure of the value itself.
+// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
+//
+// Struct fields are only marshalled if they are exported (have an upper case
+// first letter), and are marshalled using the field name lowercased as the
+// default key. Custom keys may be defined via the "yaml" name in the field
+// tag: the content preceding the first comma is used as the key, and the
+// following comma-separated options are used to tweak the marshalling process.
+// Conflicting names result in a runtime error.
+//
+// The field tag format accepted is:
+//
+// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
+//
+// The following flags are currently supported:
+//
+// omitempty Only include the field if it's not set to the zero
+// value for the type or to empty slices or maps.
+// Zero valued structs will be omitted if all their public
+// fields are zero, unless they implement an IsZero
+// method (see the IsZeroer interface type), in which
+// case the field will be excluded if IsZero returns true.
+//
+// flow Marshal using a flow style (useful for structs,
+// sequences and maps).
+//
+// inline Inline the field, which must be a struct or a map,
+// causing all of its fields or keys to be processed as if
+// they were part of the outer struct. For maps, keys must
+// not conflict with the yaml keys of other struct fields.
+//
+// In addition, if the key is "-", the field is ignored.
+//
+// For example:
+//
+// type T struct {
+// F int `yaml:"a,omitempty"`
+// B int
+// }
+// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
+// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
+//
+func Marshal(in interface{}) (out []byte, err error) {
+ defer handleErr(&err)
+ e := newEncoder()
+ defer e.destroy()
+ e.marshalDoc("", reflect.ValueOf(in))
+ e.finish()
+ out = e.out
+ return
+}
+
+// An Encoder writes YAML values to an output stream.
+type Encoder struct {
+ encoder *encoder
+}
+
+// NewEncoder returns a new encoder that writes to w.
+// The Encoder should be closed after use to flush all data
+// to w.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{
+ encoder: newEncoderWithWriter(w),
+ }
+}
+
+// Encode writes the YAML encoding of v to the stream.
+// If multiple items are encoded to the stream, the
+// second and subsequent document will be preceded
+// with a "---" document separator, but the first will not.
+//
+// See the documentation for Marshal for details about the conversion of Go
+// values to YAML.
+func (e *Encoder) Encode(v interface{}) (err error) {
+ defer handleErr(&err)
+ e.encoder.marshalDoc("", reflect.ValueOf(v))
+ return nil
+}
+
+// Encode encodes value v and stores its representation in n.
+//
+// See the documentation for Marshal for details about the
+// conversion of Go values into YAML.
+func (n *Node) Encode(v interface{}) (err error) {
+ defer handleErr(&err)
+ e := newEncoder()
+ defer e.destroy()
+ e.marshalDoc("", reflect.ValueOf(v))
+ e.finish()
+ p := newParser(e.out)
+ p.textless = true
+ defer p.destroy()
+ doc := p.parse()
+ *n = *doc.Content[0]
+ return nil
+}
+
+// SetIndent changes the used indentation used when encoding.
+func (e *Encoder) SetIndent(spaces int) {
+ if spaces < 0 {
+ panic("yaml: cannot indent to a negative number of spaces")
+ }
+ e.encoder.indent = spaces
+}
+
+// Close closes the encoder by writing any remaining data.
+// It does not write a stream terminating string "...".
+func (e *Encoder) Close() (err error) {
+ defer handleErr(&err)
+ e.encoder.finish()
+ return nil
+}
+
+func handleErr(err *error) {
+ if v := recover(); v != nil {
+ if e, ok := v.(yamlError); ok {
+ *err = e.err
+ } else {
+ panic(v)
+ }
+ }
+}
+
+type yamlError struct {
+ err error
+}
+
+func fail(err error) {
+ panic(yamlError{err})
+}
+
+func failf(format string, args ...interface{}) {
+ panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
+}
+
+// A TypeError is returned by Unmarshal when one or more fields in
+// the YAML document cannot be properly decoded into the requested
+// types. When this error is returned, the value is still
+// unmarshaled partially.
+type TypeError struct {
+ Errors []string
+}
+
+func (e *TypeError) Error() string {
+ return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
+}
+
+type Kind uint32
+
+const (
+ DocumentNode Kind = 1 << iota
+ SequenceNode
+ MappingNode
+ ScalarNode
+ AliasNode
+)
+
+type Style uint32
+
+const (
+ TaggedStyle Style = 1 << iota
+ DoubleQuotedStyle
+ SingleQuotedStyle
+ LiteralStyle
+ FoldedStyle
+ FlowStyle
+)
+
+// Node represents an element in the YAML document hierarchy. While documents
+// are typically encoded and decoded into higher level types, such as structs
+// and maps, Node is an intermediate representation that allows detailed
+// control over the content being decoded or encoded.
+//
+// It's worth noting that although Node offers access into details such as
+// line numbers, colums, and comments, the content when re-encoded will not
+// have its original textual representation preserved. An effort is made to
+// render the data plesantly, and to preserve comments near the data they
+// describe, though.
+//
+// Values that make use of the Node type interact with the yaml package in the
+// same way any other type would do, by encoding and decoding yaml data
+// directly or indirectly into them.
+//
+// For example:
+//
+// var person struct {
+// Name string
+// Address yaml.Node
+// }
+// err := yaml.Unmarshal(data, &person)
+//
+// Or by itself:
+//
+// var person Node
+// err := yaml.Unmarshal(data, &person)
+//
+type Node struct {
+ // Kind defines whether the node is a document, a mapping, a sequence,
+ // a scalar value, or an alias to another node. The specific data type of
+ // scalar nodes may be obtained via the ShortTag and LongTag methods.
+ Kind Kind
+
+ // Style allows customizing the apperance of the node in the tree.
+ Style Style
+
+ // Tag holds the YAML tag defining the data type for the value.
+ // When decoding, this field will always be set to the resolved tag,
+ // even when it wasn't explicitly provided in the YAML content.
+ // When encoding, if this field is unset the value type will be
+ // implied from the node properties, and if it is set, it will only
+ // be serialized into the representation if TaggedStyle is used or
+ // the implicit tag diverges from the provided one.
+ Tag string
+
+ // Value holds the unescaped and unquoted represenation of the value.
+ Value string
+
+ // Anchor holds the anchor name for this node, which allows aliases to point to it.
+ Anchor string
+
+ // Alias holds the node that this alias points to. Only valid when Kind is AliasNode.
+ Alias *Node
+
+ // Content holds contained nodes for documents, mappings, and sequences.
+ Content []*Node
+
+ // HeadComment holds any comments in the lines preceding the node and
+ // not separated by an empty line.
+ HeadComment string
+
+ // LineComment holds any comments at the end of the line where the node is in.
+ LineComment string
+
+ // FootComment holds any comments following the node and before empty lines.
+ FootComment string
+
+ // Line and Column hold the node position in the decoded YAML text.
+ // These fields are not respected when encoding the node.
+ Line int
+ Column int
+}
+
+// IsZero returns whether the node has all of its fields unset.
+func (n *Node) IsZero() bool {
+ return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil &&
+ n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0
+}
+
+
+// LongTag returns the long form of the tag that indicates the data type for
+// the node. If the Tag field isn't explicitly defined, one will be computed
+// based on the node properties.
+func (n *Node) LongTag() string {
+ return longTag(n.ShortTag())
+}
+
+// ShortTag returns the short form of the YAML tag that indicates data type for
+// the node. If the Tag field isn't explicitly defined, one will be computed
+// based on the node properties.
+func (n *Node) ShortTag() string {
+ if n.indicatedString() {
+ return strTag
+ }
+ if n.Tag == "" || n.Tag == "!" {
+ switch n.Kind {
+ case MappingNode:
+ return mapTag
+ case SequenceNode:
+ return seqTag
+ case AliasNode:
+ if n.Alias != nil {
+ return n.Alias.ShortTag()
+ }
+ case ScalarNode:
+ tag, _ := resolve("", n.Value)
+ return tag
+ case 0:
+ // Special case to make the zero value convenient.
+ if n.IsZero() {
+ return nullTag
+ }
+ }
+ return ""
+ }
+ return shortTag(n.Tag)
+}
+
+func (n *Node) indicatedString() bool {
+ return n.Kind == ScalarNode &&
+ (shortTag(n.Tag) == strTag ||
+ (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0)
+}
+
+// SetString is a convenience function that sets the node to a string value
+// and defines its style in a pleasant way depending on its content.
+func (n *Node) SetString(s string) {
+ n.Kind = ScalarNode
+ if utf8.ValidString(s) {
+ n.Value = s
+ n.Tag = strTag
+ } else {
+ n.Value = encodeBase64(s)
+ n.Tag = binaryTag
+ }
+ if strings.Contains(n.Value, "\n") {
+ n.Style = LiteralStyle
+ }
+}
+
+// --------------------------------------------------------------------------
+// Maintain a mapping of keys to structure field indexes
+
+// The code in this section was copied from mgo/bson.
+
+// structInfo holds details for the serialization of fields of
+// a given struct.
+type structInfo struct {
+ FieldsMap map[string]fieldInfo
+ FieldsList []fieldInfo
+
+ // InlineMap is the number of the field in the struct that
+ // contains an ,inline map, or -1 if there's none.
+ InlineMap int
+
+ // InlineUnmarshalers holds indexes to inlined fields that
+ // contain unmarshaler values.
+ InlineUnmarshalers [][]int
+}
+
+type fieldInfo struct {
+ Key string
+ Num int
+ OmitEmpty bool
+ Flow bool
+ // Id holds the unique field identifier, so we can cheaply
+ // check for field duplicates without maintaining an extra map.
+ Id int
+
+ // Inline holds the field index if the field is part of an inlined struct.
+ Inline []int
+}
+
+var structMap = make(map[reflect.Type]*structInfo)
+var fieldMapMutex sync.RWMutex
+var unmarshalerType reflect.Type
+
+func init() {
+ var v Unmarshaler
+ unmarshalerType = reflect.ValueOf(&v).Elem().Type()
+}
+
+func getStructInfo(st reflect.Type) (*structInfo, error) {
+ fieldMapMutex.RLock()
+ sinfo, found := structMap[st]
+ fieldMapMutex.RUnlock()
+ if found {
+ return sinfo, nil
+ }
+
+ n := st.NumField()
+ fieldsMap := make(map[string]fieldInfo)
+ fieldsList := make([]fieldInfo, 0, n)
+ inlineMap := -1
+ inlineUnmarshalers := [][]int(nil)
+ for i := 0; i != n; i++ {
+ field := st.Field(i)
+ if field.PkgPath != "" && !field.Anonymous {
+ continue // Private field
+ }
+
+ info := fieldInfo{Num: i}
+
+ tag := field.Tag.Get("yaml")
+ if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
+ tag = string(field.Tag)
+ }
+ if tag == "-" {
+ continue
+ }
+
+ inline := false
+ fields := strings.Split(tag, ",")
+ if len(fields) > 1 {
+ for _, flag := range fields[1:] {
+ switch flag {
+ case "omitempty":
+ info.OmitEmpty = true
+ case "flow":
+ info.Flow = true
+ case "inline":
+ inline = true
+ default:
+ return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st))
+ }
+ }
+ tag = fields[0]
+ }
+
+ if inline {
+ switch field.Type.Kind() {
+ case reflect.Map:
+ if inlineMap >= 0 {
+ return nil, errors.New("multiple ,inline maps in struct " + st.String())
+ }
+ if field.Type.Key() != reflect.TypeOf("") {
+ return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String())
+ }
+ inlineMap = info.Num
+ case reflect.Struct, reflect.Ptr:
+ ftype := field.Type
+ for ftype.Kind() == reflect.Ptr {
+ ftype = ftype.Elem()
+ }
+ if ftype.Kind() != reflect.Struct {
+ return nil, errors.New("option ,inline may only be used on a struct or map field")
+ }
+ if reflect.PtrTo(ftype).Implements(unmarshalerType) {
+ inlineUnmarshalers = append(inlineUnmarshalers, []int{i})
+ } else {
+ sinfo, err := getStructInfo(ftype)
+ if err != nil {
+ return nil, err
+ }
+ for _, index := range sinfo.InlineUnmarshalers {
+ inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...))
+ }
+ for _, finfo := range sinfo.FieldsList {
+ if _, found := fieldsMap[finfo.Key]; found {
+ msg := "duplicated key '" + finfo.Key + "' in struct " + st.String()
+ return nil, errors.New(msg)
+ }
+ if finfo.Inline == nil {
+ finfo.Inline = []int{i, finfo.Num}
+ } else {
+ finfo.Inline = append([]int{i}, finfo.Inline...)
+ }
+ finfo.Id = len(fieldsList)
+ fieldsMap[finfo.Key] = finfo
+ fieldsList = append(fieldsList, finfo)
+ }
+ }
+ default:
+ return nil, errors.New("option ,inline may only be used on a struct or map field")
+ }
+ continue
+ }
+
+ if tag != "" {
+ info.Key = tag
+ } else {
+ info.Key = strings.ToLower(field.Name)
+ }
+
+ if _, found = fieldsMap[info.Key]; found {
+ msg := "duplicated key '" + info.Key + "' in struct " + st.String()
+ return nil, errors.New(msg)
+ }
+
+ info.Id = len(fieldsList)
+ fieldsList = append(fieldsList, info)
+ fieldsMap[info.Key] = info
+ }
+
+ sinfo = &structInfo{
+ FieldsMap: fieldsMap,
+ FieldsList: fieldsList,
+ InlineMap: inlineMap,
+ InlineUnmarshalers: inlineUnmarshalers,
+ }
+
+ fieldMapMutex.Lock()
+ structMap[st] = sinfo
+ fieldMapMutex.Unlock()
+ return sinfo, nil
+}
+
+// IsZeroer is used to check whether an object is zero to
+// determine whether it should be omitted when marshaling
+// with the omitempty flag. One notable implementation
+// is time.Time.
+type IsZeroer interface {
+ IsZero() bool
+}
+
+func isZero(v reflect.Value) bool {
+ kind := v.Kind()
+ if z, ok := v.Interface().(IsZeroer); ok {
+ if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
+ return true
+ }
+ return z.IsZero()
+ }
+ switch kind {
+ case reflect.String:
+ return len(v.String()) == 0
+ case reflect.Interface, reflect.Ptr:
+ return v.IsNil()
+ case reflect.Slice:
+ return v.Len() == 0
+ case reflect.Map:
+ return v.Len() == 0
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Struct:
+ vt := v.Type()
+ for i := v.NumField() - 1; i >= 0; i-- {
+ if vt.Field(i).PkgPath != "" {
+ continue // Private field
+ }
+ if !isZero(v.Field(i)) {
+ return false
+ }
+ }
+ return true
+ }
+ return false
+}
diff --git a/vendor/gopkg.in/yaml.v3/yamlh.go b/vendor/gopkg.in/yaml.v3/yamlh.go
new file mode 100644
index 0000000..7c6d007
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/yamlh.go
@@ -0,0 +1,807 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "fmt"
+ "io"
+)
+
+// The version directive data.
+type yaml_version_directive_t struct {
+ major int8 // The major version number.
+ minor int8 // The minor version number.
+}
+
+// The tag directive data.
+type yaml_tag_directive_t struct {
+ handle []byte // The tag handle.
+ prefix []byte // The tag prefix.
+}
+
+type yaml_encoding_t int
+
+// The stream encoding.
+const (
+ // Let the parser choose the encoding.
+ yaml_ANY_ENCODING yaml_encoding_t = iota
+
+ yaml_UTF8_ENCODING // The default UTF-8 encoding.
+ yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM.
+ yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM.
+)
+
+type yaml_break_t int
+
+// Line break types.
+const (
+ // Let the parser choose the break type.
+ yaml_ANY_BREAK yaml_break_t = iota
+
+ yaml_CR_BREAK // Use CR for line breaks (Mac style).
+ yaml_LN_BREAK // Use LN for line breaks (Unix style).
+ yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style).
+)
+
+type yaml_error_type_t int
+
+// Many bad things could happen with the parser and emitter.
+const (
+ // No error is produced.
+ yaml_NO_ERROR yaml_error_type_t = iota
+
+ yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory.
+ yaml_READER_ERROR // Cannot read or decode the input stream.
+ yaml_SCANNER_ERROR // Cannot scan the input stream.
+ yaml_PARSER_ERROR // Cannot parse the input stream.
+ yaml_COMPOSER_ERROR // Cannot compose a YAML document.
+ yaml_WRITER_ERROR // Cannot write to the output stream.
+ yaml_EMITTER_ERROR // Cannot emit a YAML stream.
+)
+
+// The pointer position.
+type yaml_mark_t struct {
+ index int // The position index.
+ line int // The position line.
+ column int // The position column.
+}
+
+// Node Styles
+
+type yaml_style_t int8
+
+type yaml_scalar_style_t yaml_style_t
+
+// Scalar styles.
+const (
+ // Let the emitter choose the style.
+ yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0
+
+ yaml_PLAIN_SCALAR_STYLE yaml_scalar_style_t = 1 << iota // The plain scalar style.
+ yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style.
+ yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style.
+ yaml_LITERAL_SCALAR_STYLE // The literal scalar style.
+ yaml_FOLDED_SCALAR_STYLE // The folded scalar style.
+)
+
+type yaml_sequence_style_t yaml_style_t
+
+// Sequence styles.
+const (
+ // Let the emitter choose the style.
+ yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
+
+ yaml_BLOCK_SEQUENCE_STYLE // The block sequence style.
+ yaml_FLOW_SEQUENCE_STYLE // The flow sequence style.
+)
+
+type yaml_mapping_style_t yaml_style_t
+
+// Mapping styles.
+const (
+ // Let the emitter choose the style.
+ yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
+
+ yaml_BLOCK_MAPPING_STYLE // The block mapping style.
+ yaml_FLOW_MAPPING_STYLE // The flow mapping style.
+)
+
+// Tokens
+
+type yaml_token_type_t int
+
+// Token types.
+const (
+ // An empty token.
+ yaml_NO_TOKEN yaml_token_type_t = iota
+
+ yaml_STREAM_START_TOKEN // A STREAM-START token.
+ yaml_STREAM_END_TOKEN // A STREAM-END token.
+
+ yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token.
+ yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token.
+ yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token.
+ yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token.
+
+ yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token.
+ yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token.
+ yaml_BLOCK_END_TOKEN // A BLOCK-END token.
+
+ yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token.
+ yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token.
+ yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token.
+ yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token.
+
+ yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token.
+ yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token.
+ yaml_KEY_TOKEN // A KEY token.
+ yaml_VALUE_TOKEN // A VALUE token.
+
+ yaml_ALIAS_TOKEN // An ALIAS token.
+ yaml_ANCHOR_TOKEN // An ANCHOR token.
+ yaml_TAG_TOKEN // A TAG token.
+ yaml_SCALAR_TOKEN // A SCALAR token.
+)
+
+func (tt yaml_token_type_t) String() string {
+ switch tt {
+ case yaml_NO_TOKEN:
+ return "yaml_NO_TOKEN"
+ case yaml_STREAM_START_TOKEN:
+ return "yaml_STREAM_START_TOKEN"
+ case yaml_STREAM_END_TOKEN:
+ return "yaml_STREAM_END_TOKEN"
+ case yaml_VERSION_DIRECTIVE_TOKEN:
+ return "yaml_VERSION_DIRECTIVE_TOKEN"
+ case yaml_TAG_DIRECTIVE_TOKEN:
+ return "yaml_TAG_DIRECTIVE_TOKEN"
+ case yaml_DOCUMENT_START_TOKEN:
+ return "yaml_DOCUMENT_START_TOKEN"
+ case yaml_DOCUMENT_END_TOKEN:
+ return "yaml_DOCUMENT_END_TOKEN"
+ case yaml_BLOCK_SEQUENCE_START_TOKEN:
+ return "yaml_BLOCK_SEQUENCE_START_TOKEN"
+ case yaml_BLOCK_MAPPING_START_TOKEN:
+ return "yaml_BLOCK_MAPPING_START_TOKEN"
+ case yaml_BLOCK_END_TOKEN:
+ return "yaml_BLOCK_END_TOKEN"
+ case yaml_FLOW_SEQUENCE_START_TOKEN:
+ return "yaml_FLOW_SEQUENCE_START_TOKEN"
+ case yaml_FLOW_SEQUENCE_END_TOKEN:
+ return "yaml_FLOW_SEQUENCE_END_TOKEN"
+ case yaml_FLOW_MAPPING_START_TOKEN:
+ return "yaml_FLOW_MAPPING_START_TOKEN"
+ case yaml_FLOW_MAPPING_END_TOKEN:
+ return "yaml_FLOW_MAPPING_END_TOKEN"
+ case yaml_BLOCK_ENTRY_TOKEN:
+ return "yaml_BLOCK_ENTRY_TOKEN"
+ case yaml_FLOW_ENTRY_TOKEN:
+ return "yaml_FLOW_ENTRY_TOKEN"
+ case yaml_KEY_TOKEN:
+ return "yaml_KEY_TOKEN"
+ case yaml_VALUE_TOKEN:
+ return "yaml_VALUE_TOKEN"
+ case yaml_ALIAS_TOKEN:
+ return "yaml_ALIAS_TOKEN"
+ case yaml_ANCHOR_TOKEN:
+ return "yaml_ANCHOR_TOKEN"
+ case yaml_TAG_TOKEN:
+ return "yaml_TAG_TOKEN"
+ case yaml_SCALAR_TOKEN:
+ return "yaml_SCALAR_TOKEN"
+ }
+ return "<unknown token>"
+}
+
+// The token structure.
+type yaml_token_t struct {
+ // The token type.
+ typ yaml_token_type_t
+
+ // The start/end of the token.
+ start_mark, end_mark yaml_mark_t
+
+ // The stream encoding (for yaml_STREAM_START_TOKEN).
+ encoding yaml_encoding_t
+
+ // The alias/anchor/scalar value or tag/tag directive handle
+ // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN).
+ value []byte
+
+ // The tag suffix (for yaml_TAG_TOKEN).
+ suffix []byte
+
+ // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN).
+ prefix []byte
+
+ // The scalar style (for yaml_SCALAR_TOKEN).
+ style yaml_scalar_style_t
+
+ // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN).
+ major, minor int8
+}
+
+// Events
+
+type yaml_event_type_t int8
+
+// Event types.
+const (
+ // An empty event.
+ yaml_NO_EVENT yaml_event_type_t = iota
+
+ yaml_STREAM_START_EVENT // A STREAM-START event.
+ yaml_STREAM_END_EVENT // A STREAM-END event.
+ yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event.
+ yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event.
+ yaml_ALIAS_EVENT // An ALIAS event.
+ yaml_SCALAR_EVENT // A SCALAR event.
+ yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event.
+ yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event.
+ yaml_MAPPING_START_EVENT // A MAPPING-START event.
+ yaml_MAPPING_END_EVENT // A MAPPING-END event.
+ yaml_TAIL_COMMENT_EVENT
+)
+
+var eventStrings = []string{
+ yaml_NO_EVENT: "none",
+ yaml_STREAM_START_EVENT: "stream start",
+ yaml_STREAM_END_EVENT: "stream end",
+ yaml_DOCUMENT_START_EVENT: "document start",
+ yaml_DOCUMENT_END_EVENT: "document end",
+ yaml_ALIAS_EVENT: "alias",
+ yaml_SCALAR_EVENT: "scalar",
+ yaml_SEQUENCE_START_EVENT: "sequence start",
+ yaml_SEQUENCE_END_EVENT: "sequence end",
+ yaml_MAPPING_START_EVENT: "mapping start",
+ yaml_MAPPING_END_EVENT: "mapping end",
+ yaml_TAIL_COMMENT_EVENT: "tail comment",
+}
+
+func (e yaml_event_type_t) String() string {
+ if e < 0 || int(e) >= len(eventStrings) {
+ return fmt.Sprintf("unknown event %d", e)
+ }
+ return eventStrings[e]
+}
+
+// The event structure.
+type yaml_event_t struct {
+
+ // The event type.
+ typ yaml_event_type_t
+
+ // The start and end of the event.
+ start_mark, end_mark yaml_mark_t
+
+ // The document encoding (for yaml_STREAM_START_EVENT).
+ encoding yaml_encoding_t
+
+ // The version directive (for yaml_DOCUMENT_START_EVENT).
+ version_directive *yaml_version_directive_t
+
+ // The list of tag directives (for yaml_DOCUMENT_START_EVENT).
+ tag_directives []yaml_tag_directive_t
+
+ // The comments
+ head_comment []byte
+ line_comment []byte
+ foot_comment []byte
+ tail_comment []byte
+
+ // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT).
+ anchor []byte
+
+ // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
+ tag []byte
+
+ // The scalar value (for yaml_SCALAR_EVENT).
+ value []byte
+
+ // Is the document start/end indicator implicit, or the tag optional?
+ // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT).
+ implicit bool
+
+ // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT).
+ quoted_implicit bool
+
+ // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
+ style yaml_style_t
+}
+
+func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) }
+func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) }
+func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) }
+
+// Nodes
+
+const (
+ yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null.
+ yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false.
+ yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values.
+ yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values.
+ yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values.
+ yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values.
+
+ yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
+ yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
+
+ // Not in original libyaml.
+ yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
+ yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
+
+ yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str.
+ yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
+ yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map.
+)
+
+type yaml_node_type_t int
+
+// Node types.
+const (
+ // An empty node.
+ yaml_NO_NODE yaml_node_type_t = iota
+
+ yaml_SCALAR_NODE // A scalar node.
+ yaml_SEQUENCE_NODE // A sequence node.
+ yaml_MAPPING_NODE // A mapping node.
+)
+
+// An element of a sequence node.
+type yaml_node_item_t int
+
+// An element of a mapping node.
+type yaml_node_pair_t struct {
+ key int // The key of the element.
+ value int // The value of the element.
+}
+
+// The node structure.
+type yaml_node_t struct {
+ typ yaml_node_type_t // The node type.
+ tag []byte // The node tag.
+
+ // The node data.
+
+ // The scalar parameters (for yaml_SCALAR_NODE).
+ scalar struct {
+ value []byte // The scalar value.
+ length int // The length of the scalar value.
+ style yaml_scalar_style_t // The scalar style.
+ }
+
+ // The sequence parameters (for YAML_SEQUENCE_NODE).
+ sequence struct {
+ items_data []yaml_node_item_t // The stack of sequence items.
+ style yaml_sequence_style_t // The sequence style.
+ }
+
+ // The mapping parameters (for yaml_MAPPING_NODE).
+ mapping struct {
+ pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value).
+ pairs_start *yaml_node_pair_t // The beginning of the stack.
+ pairs_end *yaml_node_pair_t // The end of the stack.
+ pairs_top *yaml_node_pair_t // The top of the stack.
+ style yaml_mapping_style_t // The mapping style.
+ }
+
+ start_mark yaml_mark_t // The beginning of the node.
+ end_mark yaml_mark_t // The end of the node.
+
+}
+
+// The document structure.
+type yaml_document_t struct {
+
+ // The document nodes.
+ nodes []yaml_node_t
+
+ // The version directive.
+ version_directive *yaml_version_directive_t
+
+ // The list of tag directives.
+ tag_directives_data []yaml_tag_directive_t
+ tag_directives_start int // The beginning of the tag directives list.
+ tag_directives_end int // The end of the tag directives list.
+
+ start_implicit int // Is the document start indicator implicit?
+ end_implicit int // Is the document end indicator implicit?
+
+ // The start/end of the document.
+ start_mark, end_mark yaml_mark_t
+}
+
+// The prototype of a read handler.
+//
+// The read handler is called when the parser needs to read more bytes from the
+// source. The handler should write not more than size bytes to the buffer.
+// The number of written bytes should be set to the size_read variable.
+//
+// [in,out] data A pointer to an application data specified by
+// yaml_parser_set_input().
+// [out] buffer The buffer to write the data from the source.
+// [in] size The size of the buffer.
+// [out] size_read The actual number of bytes read from the source.
+//
+// On success, the handler should return 1. If the handler failed,
+// the returned value should be 0. On EOF, the handler should set the
+// size_read to 0 and return 1.
+type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
+
+// This structure holds information about a potential simple key.
+type yaml_simple_key_t struct {
+ possible bool // Is a simple key possible?
+ required bool // Is a simple key required?
+ token_number int // The number of the token.
+ mark yaml_mark_t // The position mark.
+}
+
+// The states of the parser.
+type yaml_parser_state_t int
+
+const (
+ yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
+
+ yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document.
+ yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START.
+ yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document.
+ yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END.
+ yaml_PARSE_BLOCK_NODE_STATE // Expect a block node.
+ yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence.
+ yaml_PARSE_FLOW_NODE_STATE // Expect a flow node.
+ yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence.
+ yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence.
+ yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence.
+ yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
+ yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key.
+ yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value.
+ yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry.
+ yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
+ yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
+ yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
+ yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping.
+ yaml_PARSE_END_STATE // Expect nothing.
+)
+
+func (ps yaml_parser_state_t) String() string {
+ switch ps {
+ case yaml_PARSE_STREAM_START_STATE:
+ return "yaml_PARSE_STREAM_START_STATE"
+ case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+ return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE"
+ case yaml_PARSE_DOCUMENT_START_STATE:
+ return "yaml_PARSE_DOCUMENT_START_STATE"
+ case yaml_PARSE_DOCUMENT_CONTENT_STATE:
+ return "yaml_PARSE_DOCUMENT_CONTENT_STATE"
+ case yaml_PARSE_DOCUMENT_END_STATE:
+ return "yaml_PARSE_DOCUMENT_END_STATE"
+ case yaml_PARSE_BLOCK_NODE_STATE:
+ return "yaml_PARSE_BLOCK_NODE_STATE"
+ case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+ return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE"
+ case yaml_PARSE_FLOW_NODE_STATE:
+ return "yaml_PARSE_FLOW_NODE_STATE"
+ case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+ return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE"
+ case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+ return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE"
+ case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+ return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE"
+ case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE"
+ case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
+ return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE"
+ case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
+ return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE"
+ case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE"
+ case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_KEY_STATE"
+ case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE"
+ case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE"
+ case yaml_PARSE_END_STATE:
+ return "yaml_PARSE_END_STATE"
+ }
+ return "<unknown parser state>"
+}
+
+// This structure holds aliases data.
+type yaml_alias_data_t struct {
+ anchor []byte // The anchor.
+ index int // The node id.
+ mark yaml_mark_t // The anchor mark.
+}
+
+// The parser structure.
+//
+// All members are internal. Manage the structure using the
+// yaml_parser_ family of functions.
+type yaml_parser_t struct {
+
+ // Error handling
+
+ error yaml_error_type_t // Error type.
+
+ problem string // Error description.
+
+ // The byte about which the problem occurred.
+ problem_offset int
+ problem_value int
+ problem_mark yaml_mark_t
+
+ // The error context.
+ context string
+ context_mark yaml_mark_t
+
+ // Reader stuff
+
+ read_handler yaml_read_handler_t // Read handler.
+
+ input_reader io.Reader // File input data.
+ input []byte // String input data.
+ input_pos int
+
+ eof bool // EOF flag
+
+ buffer []byte // The working buffer.
+ buffer_pos int // The current position of the buffer.
+
+ unread int // The number of unread characters in the buffer.
+
+ newlines int // The number of line breaks since last non-break/non-blank character
+
+ raw_buffer []byte // The raw buffer.
+ raw_buffer_pos int // The current position of the buffer.
+
+ encoding yaml_encoding_t // The input encoding.
+
+ offset int // The offset of the current position (in bytes).
+ mark yaml_mark_t // The mark of the current position.
+
+ // Comments
+
+ head_comment []byte // The current head comments
+ line_comment []byte // The current line comments
+ foot_comment []byte // The current foot comments
+ tail_comment []byte // Foot comment that happens at the end of a block.
+ stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc)
+
+ comments []yaml_comment_t // The folded comments for all parsed tokens
+ comments_head int
+
+ // Scanner stuff
+
+ stream_start_produced bool // Have we started to scan the input stream?
+ stream_end_produced bool // Have we reached the end of the input stream?
+
+ flow_level int // The number of unclosed '[' and '{' indicators.
+
+ tokens []yaml_token_t // The tokens queue.
+ tokens_head int // The head of the tokens queue.
+ tokens_parsed int // The number of tokens fetched from the queue.
+ token_available bool // Does the tokens queue contain a token ready for dequeueing.
+
+ indent int // The current indentation level.
+ indents []int // The indentation levels stack.
+
+ simple_key_allowed bool // May a simple key occur at the current position?
+ simple_keys []yaml_simple_key_t // The stack of simple keys.
+ simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number
+
+ // Parser stuff
+
+ state yaml_parser_state_t // The current parser state.
+ states []yaml_parser_state_t // The parser states stack.
+ marks []yaml_mark_t // The stack of marks.
+ tag_directives []yaml_tag_directive_t // The list of TAG directives.
+
+ // Dumper stuff
+
+ aliases []yaml_alias_data_t // The alias data.
+
+ document *yaml_document_t // The currently parsed document.
+}
+
+type yaml_comment_t struct {
+
+ scan_mark yaml_mark_t // Position where scanning for comments started
+ token_mark yaml_mark_t // Position after which tokens will be associated with this comment
+ start_mark yaml_mark_t // Position of '#' comment mark
+ end_mark yaml_mark_t // Position where comment terminated
+
+ head []byte
+ line []byte
+ foot []byte
+}
+
+// Emitter Definitions
+
+// The prototype of a write handler.
+//
+// The write handler is called when the emitter needs to flush the accumulated
+// characters to the output. The handler should write @a size bytes of the
+// @a buffer to the output.
+//
+// @param[in,out] data A pointer to an application data specified by
+// yaml_emitter_set_output().
+// @param[in] buffer The buffer with bytes to be written.
+// @param[in] size The size of the buffer.
+//
+// @returns On success, the handler should return @c 1. If the handler failed,
+// the returned value should be @c 0.
+//
+type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
+
+type yaml_emitter_state_t int
+
+// The emitter states.
+const (
+ // Expect STREAM-START.
+ yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
+
+ yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END.
+ yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END.
+ yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document.
+ yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END.
+ yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence.
+ yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out
+ yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence.
+ yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
+ yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out
+ yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
+ yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping.
+ yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
+ yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence.
+ yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence.
+ yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
+ yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping.
+ yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping.
+ yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping.
+ yaml_EMIT_END_STATE // Expect nothing.
+)
+
+// The emitter structure.
+//
+// All members are internal. Manage the structure using the @c yaml_emitter_
+// family of functions.
+type yaml_emitter_t struct {
+
+ // Error handling
+
+ error yaml_error_type_t // Error type.
+ problem string // Error description.
+
+ // Writer stuff
+
+ write_handler yaml_write_handler_t // Write handler.
+
+ output_buffer *[]byte // String output data.
+ output_writer io.Writer // File output data.
+
+ buffer []byte // The working buffer.
+ buffer_pos int // The current position of the buffer.
+
+ raw_buffer []byte // The raw buffer.
+ raw_buffer_pos int // The current position of the buffer.
+
+ encoding yaml_encoding_t // The stream encoding.
+
+ // Emitter stuff
+
+ canonical bool // If the output is in the canonical style?
+ best_indent int // The number of indentation spaces.
+ best_width int // The preferred width of the output lines.
+ unicode bool // Allow unescaped non-ASCII characters?
+ line_break yaml_break_t // The preferred line break.
+
+ state yaml_emitter_state_t // The current emitter state.
+ states []yaml_emitter_state_t // The stack of states.
+
+ events []yaml_event_t // The event queue.
+ events_head int // The head of the event queue.
+
+ indents []int // The stack of indentation levels.
+
+ tag_directives []yaml_tag_directive_t // The list of tag directives.
+
+ indent int // The current indentation level.
+
+ flow_level int // The current flow level.
+
+ root_context bool // Is it the document root context?
+ sequence_context bool // Is it a sequence context?
+ mapping_context bool // Is it a mapping context?
+ simple_key_context bool // Is it a simple mapping key context?
+
+ line int // The current line.
+ column int // The current column.
+ whitespace bool // If the last character was a whitespace?
+ indention bool // If the last character was an indentation character (' ', '-', '?', ':')?
+ open_ended bool // If an explicit document end is required?
+
+ space_above bool // Is there's an empty line above?
+ foot_indent int // The indent used to write the foot comment above, or -1 if none.
+
+ // Anchor analysis.
+ anchor_data struct {
+ anchor []byte // The anchor value.
+ alias bool // Is it an alias?
+ }
+
+ // Tag analysis.
+ tag_data struct {
+ handle []byte // The tag handle.
+ suffix []byte // The tag suffix.
+ }
+
+ // Scalar analysis.
+ scalar_data struct {
+ value []byte // The scalar value.
+ multiline bool // Does the scalar contain line breaks?
+ flow_plain_allowed bool // Can the scalar be expessed in the flow plain style?
+ block_plain_allowed bool // Can the scalar be expressed in the block plain style?
+ single_quoted_allowed bool // Can the scalar be expressed in the single quoted style?
+ block_allowed bool // Can the scalar be expressed in the literal or folded styles?
+ style yaml_scalar_style_t // The output style.
+ }
+
+ // Comments
+ head_comment []byte
+ line_comment []byte
+ foot_comment []byte
+ tail_comment []byte
+
+ key_line_comment []byte
+
+ // Dumper stuff
+
+ opened bool // If the stream was already opened?
+ closed bool // If the stream was already closed?
+
+ // The information associated with the document nodes.
+ anchors *struct {
+ references int // The number of references.
+ anchor int // The anchor id.
+ serialized bool // If the node has been emitted?
+ }
+
+ last_anchor_id int // The last assigned anchor id.
+
+ document *yaml_document_t // The currently emitted document.
+}
diff --git a/vendor/gopkg.in/yaml.v3/yamlprivateh.go b/vendor/gopkg.in/yaml.v3/yamlprivateh.go
new file mode 100644
index 0000000..e88f9c5
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/yamlprivateh.go
@@ -0,0 +1,198 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+const (
+ // The size of the input raw buffer.
+ input_raw_buffer_size = 512
+
+ // The size of the input buffer.
+ // It should be possible to decode the whole raw buffer.
+ input_buffer_size = input_raw_buffer_size * 3
+
+ // The size of the output buffer.
+ output_buffer_size = 128
+
+ // The size of the output raw buffer.
+ // It should be possible to encode the whole output buffer.
+ output_raw_buffer_size = (output_buffer_size*2 + 2)
+
+ // The size of other stacks and queues.
+ initial_stack_size = 16
+ initial_queue_size = 16
+ initial_string_size = 16
+)
+
+// Check if the character at the specified position is an alphabetical
+// character, a digit, '_', or '-'.
+func is_alpha(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
+}
+
+// Check if the character at the specified position is a digit.
+func is_digit(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9'
+}
+
+// Get the value of a digit.
+func as_digit(b []byte, i int) int {
+ return int(b[i]) - '0'
+}
+
+// Check if the character at the specified position is a hex-digit.
+func is_hex(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
+}
+
+// Get the value of a hex-digit.
+func as_hex(b []byte, i int) int {
+ bi := b[i]
+ if bi >= 'A' && bi <= 'F' {
+ return int(bi) - 'A' + 10
+ }
+ if bi >= 'a' && bi <= 'f' {
+ return int(bi) - 'a' + 10
+ }
+ return int(bi) - '0'
+}
+
+// Check if the character is ASCII.
+func is_ascii(b []byte, i int) bool {
+ return b[i] <= 0x7F
+}
+
+// Check if the character at the start of the buffer can be printed unescaped.
+func is_printable(b []byte, i int) bool {
+ return ((b[i] == 0x0A) || // . == #x0A
+ (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
+ (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
+ (b[i] > 0xC2 && b[i] < 0xED) ||
+ (b[i] == 0xED && b[i+1] < 0xA0) ||
+ (b[i] == 0xEE) ||
+ (b[i] == 0xEF && // #xE000 <= . <= #xFFFD
+ !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
+ !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
+}
+
+// Check if the character at the specified position is NUL.
+func is_z(b []byte, i int) bool {
+ return b[i] == 0x00
+}
+
+// Check if the beginning of the buffer is a BOM.
+func is_bom(b []byte, i int) bool {
+ return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
+}
+
+// Check if the character at the specified position is space.
+func is_space(b []byte, i int) bool {
+ return b[i] == ' '
+}
+
+// Check if the character at the specified position is tab.
+func is_tab(b []byte, i int) bool {
+ return b[i] == '\t'
+}
+
+// Check if the character at the specified position is blank (space or tab).
+func is_blank(b []byte, i int) bool {
+ //return is_space(b, i) || is_tab(b, i)
+ return b[i] == ' ' || b[i] == '\t'
+}
+
+// Check if the character at the specified position is a line break.
+func is_break(b []byte, i int) bool {
+ return (b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
+}
+
+func is_crlf(b []byte, i int) bool {
+ return b[i] == '\r' && b[i+1] == '\n'
+}
+
+// Check if the character is a line break or NUL.
+func is_breakz(b []byte, i int) bool {
+ //return is_break(b, i) || is_z(b, i)
+ return (
+ // is_break:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ // is_z:
+ b[i] == 0)
+}
+
+// Check if the character is a line break, space, or NUL.
+func is_spacez(b []byte, i int) bool {
+ //return is_space(b, i) || is_breakz(b, i)
+ return (
+ // is_space:
+ b[i] == ' ' ||
+ // is_breakz:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ b[i] == 0)
+}
+
+// Check if the character is a line break, space, tab, or NUL.
+func is_blankz(b []byte, i int) bool {
+ //return is_blank(b, i) || is_breakz(b, i)
+ return (
+ // is_blank:
+ b[i] == ' ' || b[i] == '\t' ||
+ // is_breakz:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ b[i] == 0)
+}
+
+// Determine the width of the character.
+func width(b byte) int {
+ // Don't replace these by a switch without first
+ // confirming that it is being inlined.
+ if b&0x80 == 0x00 {
+ return 1
+ }
+ if b&0xE0 == 0xC0 {
+ return 2
+ }
+ if b&0xF0 == 0xE0 {
+ return 3
+ }
+ if b&0xF8 == 0xF0 {
+ return 4
+ }
+ return 0
+
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index fd94487..3be3101 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -24,6 +24,8 @@
github.com/coreos/go-systemd/journal
# github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f
github.com/coreos/pkg/capnslog
+# github.com/davecgh/go-spew v1.1.1
+github.com/davecgh/go-spew/spew
# github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f
github.com/dgryski/go-rendezvous
# github.com/go-redis/redis/v8 v8.11.5
@@ -40,6 +42,9 @@
github.com/gogo/protobuf/gogoproto
github.com/gogo/protobuf/proto
github.com/gogo/protobuf/protoc-gen-gogo/descriptor
+# github.com/golang/mock v1.4.4
+## explicit
+github.com/golang/mock/gomock
# github.com/golang/protobuf v1.5.2
## explicit
github.com/golang/protobuf/proto
@@ -86,12 +91,15 @@
github.com/opentracing/opentracing-go/log
# github.com/pkg/errors v0.9.1
github.com/pkg/errors
+# github.com/pmezard/go-difflib v1.0.0
+github.com/pmezard/go-difflib/difflib
# github.com/rivo/uniseg v0.1.0
github.com/rivo/uniseg
# github.com/sirupsen/logrus v1.8.1
## explicit
-# github.com/stretchr/testify v1.7.1
+# github.com/stretchr/testify v1.8.2
## explicit
+github.com/stretchr/testify/assert
# github.com/uber/jaeger-client-go v2.29.1+incompatible
github.com/uber/jaeger-client-go
github.com/uber/jaeger-client-go/config
@@ -217,6 +225,8 @@
google.golang.org/protobuf/types/known/durationpb
google.golang.org/protobuf/types/known/emptypb
google.golang.org/protobuf/types/known/timestamppb
+# gopkg.in/yaml.v3 v3.0.1
+gopkg.in/yaml.v3
# github.com/coreos/bbolt v1.3.4 => go.etcd.io/bbolt v1.3.4
# github.com/google/gopacket => github.com/tinojj/gopacket v1.1.20-0.20220525133109-3e65a52a1a61
# go.etcd.io/bbolt v1.3.4 => github.com/coreos/bbolt v1.3.4
diff --git a/voltha-go-controller/nbi/bwprofile_test.go b/voltha-go-controller/nbi/bwprofile_test.go
new file mode 100644
index 0000000..3684c39
--- /dev/null
+++ b/voltha-go-controller/nbi/bwprofile_test.go
@@ -0,0 +1,120 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 nbi
+
+import (
+ "bytes"
+ "context"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/gorilla/mux"
+)
+
+func TestProfileHandle_GetProfile(t *testing.T) {
+ req, err := http.NewRequest("GET", "/get_profile/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ req.Header.Set("Content-Type", "application/json")
+
+ vars := map[string]string{
+ "id": "upstream_bw_profile_gpon",
+ }
+ req = mux.SetURLVars(req, vars)
+
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ cntx context.Context
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "GetProfile",
+ args: args{
+ cntx: context.Background(),
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ mh := &ProfileHandle{}
+ mh.GetProfile(tt.args.cntx, tt.args.w, tt.args.r)
+ })
+ }
+}
+
+func TestProfileHandle_DelProfile(t *testing.T) {
+ var jsonStr = []byte(`{"id":"test_id"}`)
+
+ req, err := http.NewRequest("DELETE", "/del_profile/", bytes.NewBuffer(jsonStr))
+ if err != nil {
+ t.Fatal(err)
+ }
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ cntx context.Context
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ mh *ProfileHandle
+ args args
+ }{
+ {
+ name: "DelProfile",
+ args: args{
+ cntx: context.Background(),
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ mh := &ProfileHandle{}
+ mh.DelProfile(tt.args.cntx, tt.args.w, tt.args.r)
+ })
+ }
+}
+
+func TestProfileHandle_AddProfile(t *testing.T) {
+ var jsonStr = []byte(`{"id": "upstream_bw_profile_gpon", "cir":"1000"}`)
+ req, err := http.NewRequest("POST", "/profiles/upstream_bw_profile_gpon", bytes.NewBuffer(jsonStr))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+ handler := http.HandlerFunc((&ProfileHandle{}).ServeHTTP)
+ handler.ServeHTTP(rr, req)
+ if status := rr.Code; status != http.StatusConflict {
+ t.Errorf("handler returned wrong status code: got %v want %v",
+ status, http.StatusOK)
+ }
+}
diff --git a/voltha-go-controller/nbi/device_info_test.go b/voltha-go-controller/nbi/device_info_test.go
new file mode 100644
index 0000000..36e1db4
--- /dev/null
+++ b/voltha-go-controller/nbi/device_info_test.go
@@ -0,0 +1,92 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 nbi
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/gorilla/mux"
+)
+
+func TestDeviceInfoHandle_ServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("GET", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ vars := map[string]string{
+ "id": "1",
+ }
+ req = mux.SetURLVars(req, vars)
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "DeviceInfoHandle_ServeHTTP",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ dh := &DeviceInfoHandle{}
+ dh.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
+
+func TestGetDeviceInfoPositive(t *testing.T) {
+ req, err := http.NewRequest("GET", "/device-info/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ rr := httptest.NewRecorder()
+ handler := http.HandlerFunc((&DeviceInfoHandle{}).ServeHTTP)
+ handler.ServeHTTP(rr, req)
+ if status := rr.Code; status != http.StatusOK {
+ t.Errorf("handler returned wrong status code: got %v want %v",
+ status, http.StatusOK)
+ }
+}
+
+func TestGetDeviceInfoUnsupportedReq(t *testing.T) {
+ req, err := http.NewRequest("UNSUPPORTED", "/device-info/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ rr := httptest.NewRecorder()
+ handler := http.HandlerFunc((&DeviceInfoHandle{}).ServeHTTP)
+ handler.ServeHTTP(rr, req)
+ if status := rr.Code; status != http.StatusOK {
+ t.Errorf("handler returned wrong status code: got %v want %v",
+ status, http.StatusOK)
+ }
+}
diff --git a/voltha-go-controller/nbi/dhcp_session_test.go b/voltha-go-controller/nbi/dhcp_session_test.go
new file mode 100644
index 0000000..99ec776
--- /dev/null
+++ b/voltha-go-controller/nbi/dhcp_session_test.go
@@ -0,0 +1,65 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 nbi
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/gorilla/mux"
+)
+
+func TestDHCPSessionInfoHandle_ServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("GET", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ vars := map[string]string{
+ "id": "1",
+ "mac": "test_mac",
+ "svlan": "test_svlan",
+ "cvlan": "test_cvlan",
+ }
+ req = mux.SetURLVars(req, vars)
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "DHCPSessionInfoHandle_ServeHTTP",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ dh := &DHCPSessionInfoHandle{}
+ dh.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
diff --git a/voltha-go-controller/nbi/get_device_id_list_test.go b/voltha-go-controller/nbi/get_device_id_list_test.go
new file mode 100644
index 0000000..b33512f
--- /dev/null
+++ b/voltha-go-controller/nbi/get_device_id_list_test.go
@@ -0,0 +1,69 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 nbi
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+)
+
+func TestDeviceIDListHandle_ServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("GET", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "DeviceIDListHandle_ServeHTTP",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ dh := &DeviceIDListHandle{}
+ dh.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
+
+func TestDeviceIDListUnsupportedReq(t *testing.T) {
+ req, err := http.NewRequest("UNSUPPORTED", "/device-id-list/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ rr := httptest.NewRecorder()
+ handler := http.HandlerFunc((&DeviceIDListHandle{}).ServeHTTP)
+ handler.ServeHTTP(rr, req)
+ if status := rr.Code; status != http.StatusOK {
+ t.Errorf("handler returned wrong status code: got %v want %v",
+ status, http.StatusOK)
+ }
+}
diff --git a/voltha-go-controller/nbi/mvlan_test.go b/voltha-go-controller/nbi/mvlan_test.go
new file mode 100644
index 0000000..284f49a
--- /dev/null
+++ b/voltha-go-controller/nbi/mvlan_test.go
@@ -0,0 +1,100 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 nbi
+
+import (
+ "bytes"
+ "context"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/gorilla/mux"
+)
+
+func TestMulticastHandle_ServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("DELETE", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ vars := map[string]string{
+ "egressvlan": "1",
+ }
+ req = mux.SetURLVars(req, vars)
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "MulticastHandle_ServeHTTP",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ iph := &MulticastHandle{}
+ iph.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
+
+func TestMulticastHandle_AddMvlanInfo(t *testing.T) {
+ var jsonStr = []byte(`{"ingressvlan":1,"egressvlan":2,"egressinnervlan":3,}`)
+ req, err := http.NewRequest("POST", "/add_mvlan_info/", bytes.NewBuffer(jsonStr))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ cntx context.Context
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "AddMvlanInfo unmarshal error",
+ args: args{
+ cntx: context.Background(),
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ iph := &MulticastHandle{}
+ iph.AddMvlanInfo(tt.args.cntx, tt.args.w, tt.args.r)
+ })
+ }
+}
diff --git a/voltha-go-controller/nbi/subscriber_test.go b/voltha-go-controller/nbi/subscriber_test.go
new file mode 100644
index 0000000..8951f7e
--- /dev/null
+++ b/voltha-go-controller/nbi/subscriber_test.go
@@ -0,0 +1,60 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 nbi
+
+import (
+ "bytes"
+ "context"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+)
+
+func TestSubscriberHandle_DelSubscriberInfo(t *testing.T) {
+ var jsonStr = []byte(`{"id":"test_id"}`)
+
+ req, err := http.NewRequest("DELETE", "/subscriber_device_info/", bytes.NewBuffer(jsonStr))
+ if err != nil {
+ t.Fatal(err)
+ }
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ cntx context.Context
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "SubscriberHandle_DelSubscriberInfo",
+ args: args{
+ cntx: context.Background(),
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ sh := &SubscriberHandle{}
+ sh.DelSubscriberInfo(tt.args.cntx, tt.args.w, tt.args.r)
+ })
+ }
+}
diff --git a/voltha-go-controller/nbi/task_list_test.go b/voltha-go-controller/nbi/task_list_test.go
new file mode 100644
index 0000000..2a44f30
--- /dev/null
+++ b/voltha-go-controller/nbi/task_list_test.go
@@ -0,0 +1,62 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 nbi
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/gorilla/mux"
+)
+
+func TestTaskListHandle_ServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("GET", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ vars := map[string]string{
+ "id": "1",
+ }
+ req = mux.SetURLVars(req, vars)
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "GetTaskList invalid input",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ dh := &TaskListHandle{}
+ dh.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
diff --git a/voltha-go-controller/onos_nbi/deviceconfig_test.go b/voltha-go-controller/onos_nbi/deviceconfig_test.go
new file mode 100644
index 0000000..476f15b
--- /dev/null
+++ b/voltha-go-controller/onos_nbi/deviceconfig_test.go
@@ -0,0 +1,62 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 onosnbi
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/gorilla/mux"
+)
+
+func TestDeviceConfigHandle_ServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("GET", "/feth_device_config/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ vars := map[string]string{
+ "id": "1",
+ }
+ req = mux.SetURLVars(req, vars)
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "DeviceConfigHandle_ServeHTTP",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ oh := &DeviceConfigHandle{}
+ oh.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
diff --git a/voltha-go-controller/onos_nbi/deviceportadapter_test.go b/voltha-go-controller/onos_nbi/deviceportadapter_test.go
new file mode 100644
index 0000000..734ca39
--- /dev/null
+++ b/voltha-go-controller/onos_nbi/deviceportadapter_test.go
@@ -0,0 +1,121 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 onosnbi
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+)
+
+func TestDeviceHandle_ServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("GET", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "DeviceHandle_ServeHTTP",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ dh := &DeviceHandle{}
+ dh.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
+
+func TestDevicePortHandle_ServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("GET", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "DevicePortHandle_ServeHTTP",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ dh := &DevicePortHandle{}
+ dh.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
+
+func TestDevicePortHandle_ServeHTTPWithDeviceID(t *testing.T) {
+ req, err := http.NewRequest("GET", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "DevicePortHandle_ServeHTTPWithDeviceID",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ dh := &DevicePortHandle{}
+ dh.ServeHTTPWithDeviceID(tt.args.w, tt.args.r)
+ })
+ }
+}
diff --git a/voltha-go-controller/onos_nbi/dhcprelayadapter_test.go b/voltha-go-controller/onos_nbi/dhcprelayadapter_test.go
new file mode 100644
index 0000000..7a57a50
--- /dev/null
+++ b/voltha-go-controller/onos_nbi/dhcprelayadapter_test.go
@@ -0,0 +1,62 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 onosnbi
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/gorilla/mux"
+)
+
+func TestDhcpRelayHandle_ServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("GET", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ vars := map[string]string{
+ "deviceId": "1",
+ }
+ req = mux.SetURLVars(req, vars)
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "DhcpRelayHandle_ServeHTTP",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ dh := &DhcpRelayHandle{}
+ dh.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
diff --git a/voltha-go-controller/onos_nbi/maclearning_info_test.go b/voltha-go-controller/onos_nbi/maclearning_info_test.go
new file mode 100644
index 0000000..7535f31
--- /dev/null
+++ b/voltha-go-controller/onos_nbi/maclearning_info_test.go
@@ -0,0 +1,97 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 onosnbi
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/gorilla/mux"
+)
+
+func TestMacLearnerHandle_ServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("GET", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ vars := map[string]string{
+ "deviceId": "1",
+ "portNumber": "2",
+ "vlanId": "3",
+ }
+ req = mux.SetURLVars(req, vars)
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "MacLearnerHandle_ServeHTTP",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ mlh := &MacLearnerHandle{}
+ mlh.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
+
+func TestMacLearnerHandle_GetAllMacLearnerInfo_ServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("GET", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "MacLearnerHandle_GetAllMacLearnerInfo_ServeHTTP",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ mlh := &MacLearnerHandle{}
+ mlh.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
diff --git a/voltha-go-controller/onos_nbi/oltapprestadapter_test.go b/voltha-go-controller/onos_nbi/oltapprestadapter_test.go
new file mode 100644
index 0000000..c9bd54d
--- /dev/null
+++ b/voltha-go-controller/onos_nbi/oltapprestadapter_test.go
@@ -0,0 +1,105 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 onosnbi
+
+import (
+ "bytes"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/gorilla/mux"
+)
+
+func TestServiceAdapter_ServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("GET", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ vars := map[string]string{
+ "device": "test_device",
+ "port": "test_port",
+ }
+ req = mux.SetURLVars(req, vars)
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "ServiceAdapter_ServeHTTP",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ sa := &ServiceAdapter{}
+ sa.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
+
+func TestServiceAdapter_DeactivateService_ServeHTTP(t *testing.T) {
+ var jsonStr = []byte(`{"device":"test_device","port":"test_port"}`)
+
+ req, err := http.NewRequest("DELETE", "/serve_http/", bytes.NewBuffer(jsonStr))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ vars := map[string]string{
+ "device": "test_device",
+ "port": "test_port",
+ }
+ req = mux.SetURLVars(req, vars)
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Invalid port number",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ sa := &ServiceAdapter{}
+ sa.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
diff --git a/voltha-go-controller/onos_nbi/oltflowservice_test.go b/voltha-go-controller/onos_nbi/oltflowservice_test.go
new file mode 100644
index 0000000..6b78cc9
--- /dev/null
+++ b/voltha-go-controller/onos_nbi/oltflowservice_test.go
@@ -0,0 +1,56 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 onosnbi
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+)
+
+func TestOltFlowServiceHandle_ServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("GET", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ oh *OltFlowServiceHandle
+ args args
+ }{
+ {
+ name: "OltFlowServiceHandle_ServeHTTP",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ oh := &OltFlowServiceHandle{}
+ oh.ServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}
diff --git a/voltha-go-controller/onos_nbi/portIgnored_test.go b/voltha-go-controller/onos_nbi/portIgnored_test.go
new file mode 100644
index 0000000..6f0a0c2
--- /dev/null
+++ b/voltha-go-controller/onos_nbi/portIgnored_test.go
@@ -0,0 +1,56 @@
+/*
+* Copyright 2023-present Open Networking Foundation
+* 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 onosnbi
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+)
+
+func TestPortIgnoredHandle_PortsIgnoredServeHTTP(t *testing.T) {
+ req, err := http.NewRequest("GET", "/serve_http/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ req.Header.Set("Content-Type", "application/json")
+ rr := httptest.NewRecorder()
+
+ type args struct {
+ w http.ResponseWriter
+ r *http.Request
+ }
+ tests := []struct {
+ name string
+ pih *PortIgnoredHandle
+ args args
+ }{
+ {
+ name: "PortIgnoredHandle_PortsIgnoredServeHTTP",
+ args: args{
+ w: rr,
+ r: req,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ pih := &PortIgnoredHandle{}
+ pih.PortsIgnoredServeHTTP(tt.args.w, tt.args.r)
+ })
+ }
+}