Skip to content

Commit

Permalink
Increasing test coverage (#401)
Browse files Browse the repository at this point in the history
* Increasing test coverage

- k8s enrichment
- convert utils

* addressing feedback
  • Loading branch information
jotak authored Mar 9, 2023
1 parent 665de17 commit 0269dcc
Show file tree
Hide file tree
Showing 3 changed files with 279 additions and 52 deletions.
108 changes: 107 additions & 1 deletion pkg/pipeline/transform/kubernetes/kubernetes-mock.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package kubernetes

import "github.com/stretchr/testify/mock"
import (
"github.com/stretchr/testify/mock"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/cache"
)

type KubeDataMock struct {
mock.Mock
Expand All @@ -11,3 +15,105 @@ func (o *KubeDataMock) InitFromConfig(kubeConfigPath string) error {
args := o.Called(kubeConfigPath)
return args.Error(0)
}

type IndexerMock struct {
mock.Mock
cache.Indexer
}

type InformerMock struct {
mock.Mock
InformerInterface
}

type InformerInterface interface {
cache.SharedInformer
AddIndexers(indexers cache.Indexers) error
GetIndexer() cache.Indexer
}

func (m *IndexerMock) ByIndex(indexName, indexedValue string) ([]interface{}, error) {
args := m.Called(indexName, indexedValue)
return args.Get(0).([]interface{}), args.Error(1)
}

func (m *IndexerMock) GetByKey(key string) (interface{}, bool, error) {
args := m.Called(key)
return args.Get(0), args.Bool(1), args.Error(2)
}

func (m *InformerMock) GetIndexer() cache.Indexer {
args := m.Called()
return args.Get(0).(cache.Indexer)
}

func (m *IndexerMock) MockPod(ip, name, namespace, nodeIP string, owner *Owner) {
var ownerRef []metav1.OwnerReference
if owner != nil {
ownerRef = []metav1.OwnerReference{{
Kind: owner.Type,
Name: owner.Name,
}}
}
m.On("ByIndex", IndexIP, ip).Return([]interface{}{&Info{
Type: "Pod",
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
OwnerReferences: ownerRef,
},
HostIP: nodeIP,
}}, nil)
}

func (m *IndexerMock) MockNode(ip, name string) {
m.On("ByIndex", IndexIP, ip).Return([]interface{}{&Info{
Type: "Node",
ObjectMeta: metav1.ObjectMeta{Name: name},
}}, nil)
}

func (m *IndexerMock) MockService(ip, name, namespace string) {
m.On("ByIndex", IndexIP, ip).Return([]interface{}{&Info{
Type: "Service",
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace},
}}, nil)
}

func (m *IndexerMock) MockReplicaSet(name, namespace string, owner Owner) {
m.On("GetByKey", namespace+"/"+name).Return(&metav1.ObjectMeta{
Name: name,
OwnerReferences: []metav1.OwnerReference{{
Kind: owner.Type,
Name: owner.Name,
}},
}, true, nil)
}

func (m *IndexerMock) FallbackNotFound() {
m.On("ByIndex", IndexIP, mock.Anything).Return([]interface{}{}, nil)
}

func SetupIndexerMocks(kd *KubeData) (pods, nodes, svc, rs *IndexerMock) {
// pods informer
pods = &IndexerMock{}
pim := InformerMock{}
pim.On("GetIndexer").Return(pods)
kd.pods = &pim
// nodes informer
nodes = &IndexerMock{}
him := InformerMock{}
him.On("GetIndexer").Return(nodes)
kd.nodes = &him
// svc informer
svc = &IndexerMock{}
sim := InformerMock{}
sim.On("GetIndexer").Return(svc)
kd.services = &sim
// rs informer
rs = &IndexerMock{}
rim := InformerMock{}
rim.On("GetIndexer").Return(rs)
kd.replicaSets = &rim
return
}
109 changes: 58 additions & 51 deletions pkg/pipeline/transform/kubernetes/kubernetes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,77 +20,84 @@ package kubernetes
import (
"testing"

"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/cache"
)

type IndexerMock struct {
mock.Mock
cache.Indexer
}

type InformerMock struct {
mock.Mock
InformerInterface
}
func TestGetInfo(t *testing.T) {
kubeData := KubeData{}
pidx, hidx, sidx, ridx := SetupIndexerMocks(&kubeData)
pidx.MockPod("1.2.3.4", "pod1", "podNamespace", "10.0.0.1", nil)
pidx.MockPod("1.2.3.5", "pod2", "podNamespace", "10.0.0.1", &Owner{Name: "rs1", Type: "ReplicaSet"})
pidx.FallbackNotFound()
ridx.MockReplicaSet("rs1", "podNamespace", Owner{Name: "dep1", Type: "Deployment"})
ridx.FallbackNotFound()
sidx.MockService("1.2.3.100", "svc1", "svcNamespace")
sidx.FallbackNotFound()
hidx.MockNode("10.0.0.1", "node1")
hidx.FallbackNotFound()

type InformerInterface interface {
cache.SharedInformer
AddIndexers(indexers cache.Indexers) error
GetIndexer() cache.Indexer
}
// Test get orphan pod
info, err := kubeData.GetInfo("1.2.3.4")
require.NoError(t, err)

func (indexMock *IndexerMock) ByIndex(indexName, indexedValue string) ([]interface{}, error) {
args := indexMock.Called(indexName, indexedValue)
return args.Get(0).([]interface{}), args.Error(1)
}
require.Equal(t, *info, Info{
Type: "Pod",
ObjectMeta: metav1.ObjectMeta{
Name: "pod1",
Namespace: "podNamespace",
},
HostName: "node1",
HostIP: "10.0.0.1",
Owner: Owner{Name: "pod1", Type: "Pod"},
})

func (informerMock *InformerMock) GetIndexer() cache.Indexer {
args := informerMock.Called()
return args.Get(0).(cache.Indexer)
}
// Test get pod owned
info, err = kubeData.GetInfo("1.2.3.5")
require.NoError(t, err)

func TestGetInfoPods(t *testing.T) {
kubeData := KubeData{}
// pods informer
pidx := IndexerMock{}
pidx.On("ByIndex", IndexIP, "1.2.3.4").Return([]interface{}{&Info{
require.Equal(t, *info, Info{
Type: "Pod",
ObjectMeta: metav1.ObjectMeta{
Name: "podName",
Name: "pod2",
Namespace: "podNamespace",
OwnerReferences: []metav1.OwnerReference{{
Kind: "ReplicaSet",
Name: "rs1",
}},
},
HostIP: "10.0.0.1",
Owner: Owner{Name: "podName", Type: "Pod"},
}}, nil)
pim := InformerMock{}
pim.On("GetIndexer").Return(&pidx)
// nodes informer
hidx := IndexerMock{}
hidx.On("ByIndex", IndexIP, "10.0.0.1").Return([]interface{}{&Info{
HostName: "node1",
HostIP: "10.0.0.1",
Owner: Owner{Name: "dep1", Type: "Deployment"},
})

// Test get node
info, err = kubeData.GetInfo("10.0.0.1")
require.NoError(t, err)

require.Equal(t, *info, Info{
Type: "Node",
ObjectMeta: metav1.ObjectMeta{
Name: "nodeName",
Name: "node1",
},
}}, nil)
him := InformerMock{}
him.On("GetIndexer").Return(&hidx)
Owner: Owner{Name: "node1", Type: "Node"},
})

kubeData.pods = &pim
kubeData.nodes = &him
info, err := kubeData.GetInfo("1.2.3.4")
// Test get service
info, err = kubeData.GetInfo("1.2.3.100")
require.NoError(t, err)

require.Equal(t, *info, Info{
Type: "Pod",
Type: "Service",
ObjectMeta: metav1.ObjectMeta{
Name: "podName",
Namespace: "podNamespace",
Name: "svc1",
Namespace: "svcNamespace",
},
HostName: "nodeName",
HostIP: "10.0.0.1",
Owner: Owner{Name: "podName", Type: "Pod"},
Owner: Owner{Name: "svc1", Type: "Service"},
})

// Test no match
info, err = kubeData.GetInfo("1.2.3.200")
require.NotNil(t, err)
require.Nil(t, info)
}
114 changes: 114 additions & 0 deletions pkg/utils/convert_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package utils

import (
"fmt"
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestConvert(t *testing.T) {
type tt struct {
input interface{}
wantf64 float64
wantu32 uint32
wantu64 uint64
wanti64 int64
wanti int
}
cases := []tt{{
input: float64(1.1),
wantf64: 1.1,
wantu32: 1,
wantu64: 1,
wanti64: 1,
wanti: 1,
}, {
input: float32(1.1),
wantf64: 1.1,
wantu32: 1,
wantu64: 1,
wanti64: 1,
wanti: 1,
}, {
input: "1",
wantf64: 1.0,
wantu32: 1,
wantu64: 1,
wanti64: 1,
wanti: 1,
}, {
input: int32(1),
wantf64: 1.0,
wantu32: 1,
wantu64: 1,
wanti64: 1,
wanti: 1,
}, {
input: int64(1),
wantf64: 1.0,
wantu32: 1,
wantu64: 1,
wanti64: 1,
wanti: 1,
}, {
input: int(1),
wantf64: 1.0,
wantu32: 1,
wantu64: 1,
wanti64: 1,
wanti: 1,
}, {
input: uint32(1),
wantf64: 1.0,
wantu32: 1,
wantu64: 1,
wanti64: 1,
wanti: 1,
}, {
input: uint64(1),
wantf64: 1.0,
wantu32: 1,
wantu64: 1,
wanti64: 1,
wanti: 1,
}, {
input: uint(1),
wantf64: 1.0,
wantu32: 1,
wantu64: 1,
wanti64: 1,
wanti: 1,
}, {
input: time.Duration(42),
wantf64: 42.0,
wantu32: 42,
wantu64: 42,
wanti64: 42,
wanti: 42,
}}
for _, tc := range cases {
t.Run(fmt.Sprintf("%T", tc.input), func(t *testing.T) {
f, err := ConvertToFloat64(tc.input)
assert.NoError(t, err)
assert.InDelta(t, tc.wantf64, f, 0.001, fmt.Sprintf("%T -> float64 failed", tc.input))

u64, err := ConvertToUint64(tc.input)
assert.NoError(t, err)
assert.Equal(t, tc.wantu64, u64, fmt.Sprintf("%T -> uint64 failed", tc.input))

u32, err := ConvertToUint32(tc.input)
assert.NoError(t, err)
assert.Equal(t, tc.wantu32, u32, fmt.Sprintf("%T -> uint32 failed", tc.input))

i64, err := ConvertToInt64(tc.input)
assert.NoError(t, err)
assert.Equal(t, tc.wanti64, i64, fmt.Sprintf("%T -> int64 failed", tc.input))

i, err := ConvertToInt(tc.input)
assert.NoError(t, err)
assert.Equal(t, tc.wanti, i, fmt.Sprintf("%T -> int failed", tc.input))
})
}
}

0 comments on commit 0269dcc

Please sign in to comment.