From a8d3dd79eef198039803a063c77b1d6f3b1fa4c5 Mon Sep 17 00:00:00 2001
From: shivdudhani <shivkumar@nirmata.com>
Date: Tue, 11 Jun 2019 14:35:26 -0700
Subject: [PATCH 1/6] initial client & controller test

---
 pkg/controller/controller_test.go | 104 ++++++++++++++++++++
 pkg/dclient/client.go             |  58 +++++------
 pkg/dclient/client_test.go        | 154 ++++++++++++++++++++++++++++++
 pkg/dclient/utils.go              |  49 ++++++++++
 pkg/sharedinformer/utils.go       |  15 +++
 5 files changed, 352 insertions(+), 28 deletions(-)
 create mode 100644 pkg/sharedinformer/utils.go

diff --git a/pkg/controller/controller_test.go b/pkg/controller/controller_test.go
index b0b429f899..8a300f1683 100644
--- a/pkg/controller/controller_test.go
+++ b/pkg/controller/controller_test.go
@@ -1 +1,105 @@
 package controller
+
+import (
+	"testing"
+
+	"github.com/golang/glog"
+	types "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
+	client "github.com/nirmata/kyverno/pkg/dclient"
+	"github.com/nirmata/kyverno/pkg/sharedinformer"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/sample-controller/pkg/signals"
+)
+
+func TestCreatePolicy(t *testing.T) {
+	f := newFixture(t)
+	// new policy is added to policy lister and explictly passed to sync-handler
+	// to process the existing
+	policy := newPolicy("test-policy")
+	f.policyLister = append(f.policyLister, policy)
+	f.objects = append(f.objects, policy)
+	// run controller
+	f.runControler("test-policy")
+}
+
+func (f *fixture) runControler(policyName string) {
+	policyInformerFactory, err := sharedinformer.NewFakeSharedInformerFactory()
+	if err != nil {
+		f.t.Fatal(err)
+	}
+	// new controller
+	policyController := NewPolicyController(
+		f.Client,
+		policyInformerFactory,
+		nil,
+		nil)
+
+	stopCh := signals.SetupSignalHandler()
+	// start informer & controller
+	policyInformerFactory.Run(stopCh)
+	if err = policyController.Run(stopCh); err != nil {
+		glog.Fatalf("Error running PolicyController: %v\n", err)
+	}
+	// add policy to the informer
+	for _, p := range f.policyLister {
+		policyInformerFactory.GetInfomer().GetIndexer().Add(p)
+	}
+
+	// sync handler
+	// reads the policy from the policy lister and processes them
+	err = policyController.syncHandler(policyName)
+	if err != nil {
+		f.t.Fatal(err)
+	}
+	policyController.Stop()
+
+}
+
+type fixture struct {
+	t            *testing.T
+	Client       *client.Client
+	policyLister []*types.Policy
+	objects      []runtime.Object
+}
+
+func newFixture(t *testing.T) *fixture {
+	f := &fixture{}
+	f.t = t
+	return f
+}
+
+// create mock client with initial resouces
+// set registered resources for gvr
+func (f *fixture) setupFixture() {
+	scheme := runtime.NewScheme()
+	fclient, err := client.NewMockClient(scheme, f.objects...)
+	if err != nil {
+		f.t.Fatal(err)
+	}
+	regresource := map[string]string{"kyverno.io/v1alpha1": "policys"}
+	fclient.SetDiscovery(client.NewFakeDiscoveryClient(regresource))
+}
+
+func newPolicy(name string) *types.Policy {
+	return &types.Policy{
+		TypeMeta: metav1.TypeMeta{APIVersion: types.SchemeGroupVersion.String()},
+		ObjectMeta: metav1.ObjectMeta{
+			Name: name,
+		},
+	}
+}
+
+func newUnstructured(apiVersion, kind, namespace, name string) *unstructured.Unstructured {
+	return &unstructured.Unstructured{
+		Object: map[string]interface{}{
+			"apiVersion": apiVersion,
+			"kind":       kind,
+			"metadata": map[string]interface{}{
+				"namespace": namespace,
+				"name":      name,
+			},
+		},
+	}
+}
diff --git a/pkg/dclient/client.go b/pkg/dclient/client.go
index ee504644ed..fae5c44793 100644
--- a/pkg/dclient/client.go
+++ b/pkg/dclient/client.go
@@ -27,15 +27,16 @@ import (
 
 //Client enables interaction with k8 resource
 type Client struct {
-	client       dynamic.Interface
-	cachedClient discovery.CachedDiscoveryInterface
-	clientConfig *rest.Config
-	kclient      *kubernetes.Clientset
+	client          dynamic.Interface
+	cachedClient    discovery.CachedDiscoveryInterface
+	clientConfig    *rest.Config
+	kclient         kubernetes.Interface
+	discoveryClient IDiscovery
 }
 
 //NewClient creates new instance of client
 func NewClient(config *rest.Config) (*Client, error) {
-	client, err := dynamic.NewForConfig(config)
+	dclient, err := dynamic.NewForConfig(config)
 	if err != nil {
 		return nil, err
 	}
@@ -44,13 +45,15 @@ func NewClient(config *rest.Config) (*Client, error) {
 	if err != nil {
 		return nil, err
 	}
-
-	return &Client{
-		client:       client,
+	client := Client{
+		client:       dclient,
 		clientConfig: config,
 		kclient:      kclient,
-		cachedClient: memory.NewMemCacheClient(kclient.Discovery()),
-	}, nil
+	}
+	// Set discovery client
+	discoveryClient := ServerPreferredResources{memory.NewMemCacheClient(kclient.Discovery())}
+	client.SetDiscovery(discoveryClient)
+	return &client, nil
 }
 
 //GetKubePolicyDeployment returns kube policy depoyment value
@@ -100,7 +103,7 @@ func (c *Client) getGroupVersionMapper(resource string) schema.GroupVersionResou
 	//TODO: add checks to see if the resource is supported
 	//TODO: build the resource list dynamically( by querying the registered resources)
 	//TODO: the error scenarios
-	return c.getGVR(resource)
+	return c.discoveryClient.getGVR(resource)
 }
 
 // GetResource returns the resource in unstructured/json format
@@ -156,24 +159,10 @@ func convertToUnstructured(obj interface{}) *unstructured.Unstructured {
 	return &unstructured.Unstructured{Object: unstructuredObj}
 }
 
-//ConvertToRuntimeObject converts unstructed to runtime.Object runtime instance
-func ConvertToRuntimeObject(obj *unstructured.Unstructured) (*runtime.Object, error) {
-	scheme := runtime.NewScheme()
-	gvk := obj.GroupVersionKind()
-	runtimeObj, err := scheme.New(gvk)
-	if err != nil {
-		return nil, err
-	}
-	if err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &runtimeObj); err != nil {
-		return nil, err
-	}
-	return &runtimeObj, nil
-}
-
 // GenerateResource creates resource of the specified kind(supports 'clone' & 'data')
 func (c *Client) GenerateResource(generator types.Generation, namespace string) error {
 	var err error
-	rGVR := c.getGVRFromKind(generator.Kind)
+	rGVR := c.discoveryClient.getGVRFromKind(generator.Kind)
 	resource := &unstructured.Unstructured{}
 
 	var rdata map[string]interface{}
@@ -244,7 +233,20 @@ func (c *Client) waitUntilNamespaceIsCreated(name string) error {
 	return lastError
 }
 
-func (c *Client) getGVR(resource string) schema.GroupVersionResource {
+type IDiscovery interface {
+	getGVR(resource string) schema.GroupVersionResource
+	getGVRFromKind(kind string) schema.GroupVersionResource
+}
+
+func (c *Client) SetDiscovery(discoveryClient IDiscovery) {
+	c.discoveryClient = discoveryClient
+}
+
+type ServerPreferredResources struct {
+	cachedClient discovery.CachedDiscoveryInterface
+}
+
+func (c ServerPreferredResources) getGVR(resource string) schema.GroupVersionResource {
 	emptyGVR := schema.GroupVersionResource{}
 	serverresources, err := c.cachedClient.ServerPreferredResources()
 	if err != nil {
@@ -268,7 +270,7 @@ func (c *Client) getGVR(resource string) schema.GroupVersionResource {
 
 //To-do: measure performance
 //To-do: evaluate DefaultRESTMapper to fetch kind->resource mapping
-func (c *Client) getGVRFromKind(kind string) schema.GroupVersionResource {
+func (c ServerPreferredResources) getGVRFromKind(kind string) schema.GroupVersionResource {
 	emptyGVR := schema.GroupVersionResource{}
 	serverresources, err := c.cachedClient.ServerPreferredResources()
 	if err != nil {
diff --git a/pkg/dclient/client_test.go b/pkg/dclient/client_test.go
index 75f509ff84..984c316203 100644
--- a/pkg/dclient/client_test.go
+++ b/pkg/dclient/client_test.go
@@ -1,6 +1,160 @@
 package client
 
+import (
+	"fmt"
+	"testing"
+
+	policytypes "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
+
+	meta "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/runtime"
+)
+
 // GetResource
 // ListResource
 // CreateResource
 // getGroupVersionMapper (valid and invalid resources)
+
+//NewMockClient creates a mock client
+// - dynamic client
+// - kubernetes client
+// - objects to initialize the client
+
+func newUnstructured(apiVersion, kind, namespace, name string) *unstructured.Unstructured {
+	return &unstructured.Unstructured{
+		Object: map[string]interface{}{
+			"apiVersion": apiVersion,
+			"kind":       kind,
+			"metadata": map[string]interface{}{
+				"namespace": namespace,
+				"name":      name,
+			},
+		},
+	}
+}
+
+func newUnstructuredWithSpec(apiVersion, kind, namespace, name string, spec map[string]interface{}) *unstructured.Unstructured {
+	u := newUnstructured(apiVersion, kind, namespace, name)
+	u.Object["spec"] = spec
+	return u
+}
+
+func TestClient(t *testing.T) {
+	scheme := runtime.NewScheme()
+	// init groupversion
+	regresource := map[string]string{"group/version": "thekinds",
+		"group2/version": "thekinds",
+		"v1":             "namespaces",
+		"apps/v1":        "deployments"}
+	// init resources
+	objects := []runtime.Object{newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
+		newUnstructured("group2/version", "TheKind", "ns-foo", "name2-foo"),
+		newUnstructured("group/version", "TheKind", "ns-foo", "name-bar"),
+		newUnstructured("group/version", "TheKind", "ns-foo", "name-baz"),
+		newUnstructured("group2/version", "TheKind", "ns-foo", "name2-baz"),
+		newUnstructured("apps/v1", "Deployment", "kyverno", "kyverno-deployment"),
+	}
+
+	// Mock Client
+	client, err := NewMockClient(scheme, objects...)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// set discovery Client
+	client.SetDiscovery(NewFakeDiscoveryClient(regresource))
+	// Get Resource
+	res, err := client.GetResource("thekinds", "ns-foo", "name-foo")
+	if err != nil {
+		t.Fatal(err)
+	}
+	fmt.Println(res)
+	// List Resources
+	list, err := client.ListResource("thekinds", "ns-foo")
+	if err != nil {
+		t.Fatal(err)
+	}
+	fmt.Println(len(list.Items))
+	// DeleteResouce
+	err = client.DeleteResouce("thekinds", "ns-foo", "name-bar")
+	if err != nil {
+		t.Fatal(err)
+	}
+	// CreateResource
+	res, err = client.CreateResource("thekinds", "ns-foo", newUnstructured("group/version", "TheKind", "ns-foo", "name-foo1"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	//	UpdateResource
+	res, err = client.UpdateResource("thekinds", "ns-foo", newUnstructuredWithSpec("group/version", "TheKind", "ns-foo", "name-foo1", map[string]interface{}{"foo": "bar"}))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// UpdateStatusResource
+	res, err = client.UpdateStatusResource("thekinds", "ns-foo", newUnstructuredWithSpec("group/version", "TheKind", "ns-foo", "name-foo1", map[string]interface{}{"foo": "status"}))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	iEvent, err := client.GetEventsInterface()
+	if err != nil {
+		t.Fatal(err)
+	}
+	eventList, err := iEvent.List(meta.ListOptions{})
+	if err != nil {
+		t.Fatal(err)
+	}
+	fmt.Println(eventList.Items)
+
+	iCSR, err := client.GetCSRInterface()
+	if err != nil {
+		t.Fatal(err)
+	}
+	csrList, err := iCSR.List(meta.ListOptions{})
+	if err != nil {
+		t.Fatal(err)
+	}
+	fmt.Println(csrList.Items)
+
+	//GenerateResource -> copy From
+	// 1 create namespace
+	// 2 generate resource
+
+	// create namespace
+	ns, err := client.CreateResource("namespaces", "", newUnstructured("v1", "Namespace", "", "ns1"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	gen := policytypes.Generation{Kind: "TheKind",
+		Name:  "gen-kind",
+		Clone: &policytypes.CloneFrom{Namespace: "ns-foo", Name: "name-foo"}}
+	err = client.GenerateResource(gen, ns.GetName())
+	if err != nil {
+		t.Fatal(err)
+	}
+	res, err = client.GetResource("thekinds", "ns1", "gen-kind")
+	if err != nil {
+		t.Fatal(err)
+	}
+	// GenerateResource -> data
+	gen = policytypes.Generation{Kind: "TheKind",
+		Name: "name2-baz-new",
+		Data: newUnstructured("group2/version", "TheKind", "ns1", "name2-baz-new")}
+	err = client.GenerateResource(gen, ns.GetName())
+	if err != nil {
+		t.Fatal(err)
+	}
+	res, err = client.GetResource("thekinds", "ns1", "name2-baz-new")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Get Kube Policy Deployment
+	deploy, err := client.GetKubePolicyDeployment()
+	if err != nil {
+		t.Fatal(err)
+	}
+	fmt.Println(deploy.GetName())
+}
diff --git a/pkg/dclient/utils.go b/pkg/dclient/utils.go
index 5057e797c1..080f2739c6 100644
--- a/pkg/dclient/utils.go
+++ b/pkg/dclient/utils.go
@@ -1,7 +1,13 @@
 package client
 
 import (
+	"strings"
 	"time"
+
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/client-go/dynamic/fake"
+	kubernetesfake "k8s.io/client-go/kubernetes/fake"
 )
 
 const (
@@ -16,3 +22,46 @@ const (
 )
 const namespaceCreationMaxWaitTime time.Duration = 30 * time.Second
 const namespaceCreationWaitInterval time.Duration = 100 * time.Millisecond
+
+//---testing utilities
+func NewMockClient(scheme *runtime.Scheme, objects ...runtime.Object) (*Client, error) {
+	client := fake.NewSimpleDynamicClient(scheme, objects...)
+	// the typed and dynamic client are initalized with similar resources
+	kclient := kubernetesfake.NewSimpleClientset(objects...)
+	return &Client{
+		client:  client,
+		kclient: kclient,
+	}, nil
+
+}
+
+// NewFakeDiscoveryClient returns a fakediscovery client
+func NewFakeDiscoveryClient(regResources map[string]string) *fakeDiscoveryClient {
+	registeredResources := make([]schema.GroupVersionResource, len(regResources))
+	for groupVersion, resource := range regResources {
+		gv, err := schema.ParseGroupVersion(groupVersion)
+		if err != nil {
+			continue
+		}
+		registeredResources = append(registeredResources, gv.WithResource(resource))
+	}
+	return &fakeDiscoveryClient{registeredResouces: registeredResources}
+}
+
+type fakeDiscoveryClient struct {
+	registeredResouces []schema.GroupVersionResource
+}
+
+func (c *fakeDiscoveryClient) getGVR(resource string) schema.GroupVersionResource {
+	for _, gvr := range c.registeredResouces {
+		if gvr.Resource == resource {
+			return gvr
+		}
+	}
+	return schema.GroupVersionResource{}
+}
+
+func (c *fakeDiscoveryClient) getGVRFromKind(kind string) schema.GroupVersionResource {
+	resource := strings.ToLower(kind) + "s"
+	return c.getGVR(resource)
+}
diff --git a/pkg/sharedinformer/utils.go b/pkg/sharedinformer/utils.go
new file mode 100644
index 0000000000..804be21665
--- /dev/null
+++ b/pkg/sharedinformer/utils.go
@@ -0,0 +1,15 @@
+package sharedinformer
+
+import (
+	"github.com/nirmata/kyverno/pkg/client/clientset/versioned/fake"
+	informers "github.com/nirmata/kyverno/pkg/client/informers/externalversions"
+	"k8s.io/apimachinery/pkg/runtime"
+)
+
+func NewFakeSharedInformerFactory(objects ...runtime.Object) (SharedInfomer, error) {
+	fakePolicyClient := fake.NewSimpleClientset(objects...)
+	policyInformerFactory := informers.NewSharedInformerFactory(fakePolicyClient, 0)
+	return &sharedInfomer{
+		policyInformerFactory: policyInformerFactory,
+	}, nil
+}

From 45d44cef88d557e193ad1d58d1ec77451d077c88 Mon Sep 17 00:00:00 2001
From: shivdudhani <shivkumar@nirmata.com>
Date: Fri, 14 Jun 2019 16:02:28 -0700
Subject: [PATCH 2/6] re-structure unit tests

---
 pkg/dclient/client_test.go | 136 ++++++++++++++++++-------------------
 pkg/dclient/utils.go       |  20 ++++++
 2 files changed, 88 insertions(+), 68 deletions(-)

diff --git a/pkg/dclient/client_test.go b/pkg/dclient/client_test.go
index 984c316203..b3a7c7df6f 100644
--- a/pkg/dclient/client_test.go
+++ b/pkg/dclient/client_test.go
@@ -1,13 +1,11 @@
 package client
 
 import (
-	"fmt"
 	"testing"
 
 	policytypes "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
 
 	meta "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
 )
 
@@ -21,33 +19,19 @@ import (
 // - kubernetes client
 // - objects to initialize the client
 
-func newUnstructured(apiVersion, kind, namespace, name string) *unstructured.Unstructured {
-	return &unstructured.Unstructured{
-		Object: map[string]interface{}{
-			"apiVersion": apiVersion,
-			"kind":       kind,
-			"metadata": map[string]interface{}{
-				"namespace": namespace,
-				"name":      name,
-			},
-		},
-	}
+type fixture struct {
+	t            *testing.T
+	regresources map[string]string
+	objects      []runtime.Object
+	client       *Client
 }
 
-func newUnstructuredWithSpec(apiVersion, kind, namespace, name string, spec map[string]interface{}) *unstructured.Unstructured {
-	u := newUnstructured(apiVersion, kind, namespace, name)
-	u.Object["spec"] = spec
-	return u
-}
-
-func TestClient(t *testing.T) {
-	scheme := runtime.NewScheme()
-	// init groupversion
+func newFixture(t *testing.T) *fixture {
 	regresource := map[string]string{"group/version": "thekinds",
 		"group2/version": "thekinds",
 		"v1":             "namespaces",
 		"apps/v1":        "deployments"}
-	// init resources
+
 	objects := []runtime.Object{newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
 		newUnstructured("group2/version", "TheKind", "ns-foo", "name2-foo"),
 		newUnstructured("group/version", "TheKind", "ns-foo", "name-bar"),
@@ -55,8 +39,8 @@ func TestClient(t *testing.T) {
 		newUnstructured("group2/version", "TheKind", "ns-foo", "name2-baz"),
 		newUnstructured("apps/v1", "Deployment", "kyverno", "kyverno-deployment"),
 	}
-
-	// Mock Client
+	scheme := runtime.NewScheme()
+	// Create mock client
 	client, err := NewMockClient(scheme, objects...)
 	if err != nil {
 		t.Fatal(err)
@@ -64,77 +48,92 @@ func TestClient(t *testing.T) {
 
 	// set discovery Client
 	client.SetDiscovery(NewFakeDiscoveryClient(regresource))
+
+	f := fixture{
+		t:            t,
+		regresources: regresource,
+		objects:      objects,
+		client:       client,
+	}
+	return &f
+
+}
+
+func TestCRUDResource(t *testing.T) {
+	f := newFixture(t)
 	// Get Resource
-	res, err := client.GetResource("thekinds", "ns-foo", "name-foo")
+	_, err := f.client.GetResource("thekinds", "ns-foo", "name-foo")
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("GetResource not working: %s", err)
 	}
-	fmt.Println(res)
 	// List Resources
-	list, err := client.ListResource("thekinds", "ns-foo")
+	_, err = f.client.ListResource("thekinds", "ns-foo")
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("ListResource not working: %s", err)
 	}
-	fmt.Println(len(list.Items))
 	// DeleteResouce
-	err = client.DeleteResouce("thekinds", "ns-foo", "name-bar")
+	err = f.client.DeleteResouce("thekinds", "ns-foo", "name-bar")
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("DeleteResouce not working: %s", err)
 	}
 	// CreateResource
-	res, err = client.CreateResource("thekinds", "ns-foo", newUnstructured("group/version", "TheKind", "ns-foo", "name-foo1"))
+	_, err = f.client.CreateResource("thekinds", "ns-foo", newUnstructured("group/version", "TheKind", "ns-foo", "name-foo1"))
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("CreateResource not working: %s", err)
 	}
 	//	UpdateResource
-	res, err = client.UpdateResource("thekinds", "ns-foo", newUnstructuredWithSpec("group/version", "TheKind", "ns-foo", "name-foo1", map[string]interface{}{"foo": "bar"}))
+	_, err = f.client.UpdateResource("thekinds", "ns-foo", newUnstructuredWithSpec("group/version", "TheKind", "ns-foo", "name-foo1", map[string]interface{}{"foo": "bar"}))
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("UpdateResource not working: %s", err)
 	}
-
 	// UpdateStatusResource
-	res, err = client.UpdateStatusResource("thekinds", "ns-foo", newUnstructuredWithSpec("group/version", "TheKind", "ns-foo", "name-foo1", map[string]interface{}{"foo": "status"}))
+	_, err = f.client.UpdateStatusResource("thekinds", "ns-foo", newUnstructuredWithSpec("group/version", "TheKind", "ns-foo", "name-foo1", map[string]interface{}{"foo": "status"}))
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("UpdateStatusResource not working: %s", err)
 	}
+}
 
-	iEvent, err := client.GetEventsInterface()
+func TestEventInterface(t *testing.T) {
+	f := newFixture(t)
+	iEvent, err := f.client.GetEventsInterface()
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("GetEventsInterface not working: %s", err)
 	}
-	eventList, err := iEvent.List(meta.ListOptions{})
+	_, err = iEvent.List(meta.ListOptions{})
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("Testing Event interface not working: %s", err)
 	}
-	fmt.Println(eventList.Items)
-
-	iCSR, err := client.GetCSRInterface()
-	if err != nil {
-		t.Fatal(err)
-	}
-	csrList, err := iCSR.List(meta.ListOptions{})
-	if err != nil {
-		t.Fatal(err)
-	}
-	fmt.Println(csrList.Items)
+}
+func TestCSRInterface(t *testing.T) {
+	f := newFixture(t)
+	iCSR, err := f.client.GetCSRInterface()
+	if err != nil {
+		t.Errorf("GetCSRInterface not working: %s", err)
+	}
+	_, err = iCSR.List(meta.ListOptions{})
+	if err != nil {
+		t.Errorf("Testing CSR interface not working: %s", err)
+	}
+}
 
+func TestGenerateResource(t *testing.T) {
+	f := newFixture(t)
 	//GenerateResource -> copy From
 	// 1 create namespace
 	// 2 generate resource
-
 	// create namespace
-	ns, err := client.CreateResource("namespaces", "", newUnstructured("v1", "Namespace", "", "ns1"))
+	ns, err := f.client.CreateResource("namespaces", "", newUnstructured("v1", "Namespace", "", "ns1"))
 	if err != nil {
 		t.Fatal(err)
 	}
 	gen := policytypes.Generation{Kind: "TheKind",
 		Name:  "gen-kind",
 		Clone: &policytypes.CloneFrom{Namespace: "ns-foo", Name: "name-foo"}}
-	err = client.GenerateResource(gen, ns.GetName())
+	err = f.client.GenerateResource(gen, ns.GetName())
 	if err != nil {
 		t.Fatal(err)
 	}
-	res, err = client.GetResource("thekinds", "ns1", "gen-kind")
+	_, err = f.client.GetResource("thekinds", "ns1", "gen-kind")
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -142,19 +141,20 @@ func TestClient(t *testing.T) {
 	gen = policytypes.Generation{Kind: "TheKind",
 		Name: "name2-baz-new",
 		Data: newUnstructured("group2/version", "TheKind", "ns1", "name2-baz-new")}
-	err = client.GenerateResource(gen, ns.GetName())
+	err = f.client.GenerateResource(gen, ns.GetName())
 	if err != nil {
 		t.Fatal(err)
 	}
-	res, err = client.GetResource("thekinds", "ns1", "name2-baz-new")
+	_, err = f.client.GetResource("thekinds", "ns1", "name2-baz-new")
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestKubePolicyDeployment(t *testing.T) {
+	f := newFixture(t)
+	_, err := f.client.GetKubePolicyDeployment()
 	if err != nil {
 		t.Fatal(err)
 	}
-
-	// Get Kube Policy Deployment
-	deploy, err := client.GetKubePolicyDeployment()
-	if err != nil {
-		t.Fatal(err)
-	}
-	fmt.Println(deploy.GetName())
 }
diff --git a/pkg/dclient/utils.go b/pkg/dclient/utils.go
index 080f2739c6..1650f20081 100644
--- a/pkg/dclient/utils.go
+++ b/pkg/dclient/utils.go
@@ -4,6 +4,7 @@ import (
 	"strings"
 	"time"
 
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/client-go/dynamic/fake"
@@ -65,3 +66,22 @@ func (c *fakeDiscoveryClient) getGVRFromKind(kind string) schema.GroupVersionRes
 	resource := strings.ToLower(kind) + "s"
 	return c.getGVR(resource)
 }
+
+func newUnstructured(apiVersion, kind, namespace, name string) *unstructured.Unstructured {
+	return &unstructured.Unstructured{
+		Object: map[string]interface{}{
+			"apiVersion": apiVersion,
+			"kind":       kind,
+			"metadata": map[string]interface{}{
+				"namespace": namespace,
+				"name":      name,
+			},
+		},
+	}
+}
+
+func newUnstructuredWithSpec(apiVersion, kind, namespace, name string, spec map[string]interface{}) *unstructured.Unstructured {
+	u := newUnstructured(apiVersion, kind, namespace, name)
+	u.Object["spec"] = spec
+	return u
+}

From b3bf9b02d27938ecf37ad6e8c89c469d387bc2ff Mon Sep 17 00:00:00 2001
From: shivdudhani <shivkumar@nirmata.com>
Date: Fri, 14 Jun 2019 16:15:23 -0700
Subject: [PATCH 3/6] skip test due to random fails

---
 pkg/dclient/client_test.go | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/pkg/dclient/client_test.go b/pkg/dclient/client_test.go
index b3a7c7df6f..5c7cd6577e 100644
--- a/pkg/dclient/client_test.go
+++ b/pkg/dclient/client_test.go
@@ -60,6 +60,7 @@ func newFixture(t *testing.T) *fixture {
 }
 
 func TestCRUDResource(t *testing.T) {
+	t.Skip("Under Development. Reason: delay in generation of resources, so test fails at times")
 	f := newFixture(t)
 	// Get Resource
 	_, err := f.client.GetResource("thekinds", "ns-foo", "name-foo")
@@ -117,6 +118,8 @@ func TestCSRInterface(t *testing.T) {
 }
 
 func TestGenerateResource(t *testing.T) {
+	t.Skip("Under Development. Reason: delay in generation of resources, so test fails at times")
+
 	f := newFixture(t)
 	//GenerateResource -> copy From
 	// 1 create namespace
@@ -124,18 +127,18 @@ func TestGenerateResource(t *testing.T) {
 	// create namespace
 	ns, err := f.client.CreateResource("namespaces", "", newUnstructured("v1", "Namespace", "", "ns1"))
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("CreateResource not working: %s", err)
 	}
 	gen := policytypes.Generation{Kind: "TheKind",
 		Name:  "gen-kind",
 		Clone: &policytypes.CloneFrom{Namespace: "ns-foo", Name: "name-foo"}}
 	err = f.client.GenerateResource(gen, ns.GetName())
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("GenerateResource not working: %s", err)
 	}
 	_, err = f.client.GetResource("thekinds", "ns1", "gen-kind")
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("GetResource not working: %s", err)
 	}
 	// GenerateResource -> data
 	gen = policytypes.Generation{Kind: "TheKind",
@@ -143,11 +146,11 @@ func TestGenerateResource(t *testing.T) {
 		Data: newUnstructured("group2/version", "TheKind", "ns1", "name2-baz-new")}
 	err = f.client.GenerateResource(gen, ns.GetName())
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("GenerateResource not working: %s", err)
 	}
 	_, err = f.client.GetResource("thekinds", "ns1", "name2-baz-new")
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("GetResource not working: %s", err)
 	}
 }
 

From 640ffd7258edb7ad765117b4dfd8260a4bd24afb Mon Sep 17 00:00:00 2001
From: shivdudhani <shivkumar@nirmata.com>
Date: Mon, 17 Jun 2019 10:31:51 -0700
Subject: [PATCH 4/6] re factor

---
 pkg/dclient/client_test.go | 33 +++++++++++++++---------------
 pkg/dclient/utils.go       | 42 ++++++++++++++++++++++++++++++--------
 2 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/pkg/dclient/client_test.go b/pkg/dclient/client_test.go
index 5c7cd6577e..62b798382e 100644
--- a/pkg/dclient/client_test.go
+++ b/pkg/dclient/client_test.go
@@ -7,6 +7,7 @@ import (
 
 	meta "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
 )
 
 // GetResource
@@ -20,18 +21,19 @@ import (
 // - objects to initialize the client
 
 type fixture struct {
-	t            *testing.T
-	regresources map[string]string
-	objects      []runtime.Object
-	client       *Client
+	t       *testing.T
+	objects []runtime.Object
+	client  *Client
 }
 
 func newFixture(t *testing.T) *fixture {
-	regresource := map[string]string{"group/version": "thekinds",
-		"group2/version": "thekinds",
-		"v1":             "namespaces",
-		"apps/v1":        "deployments"}
-
+	// init groupversion
+	regResource := []schema.GroupVersionResource{
+		schema.GroupVersionResource{Group: "group", Version: "version", Resource: "thekinds"},
+		schema.GroupVersionResource{Group: "group2", Version: "version", Resource: "thekinds"},
+		schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespaces"},
+		schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
+	}
 	objects := []runtime.Object{newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
 		newUnstructured("group2/version", "TheKind", "ns-foo", "name2-foo"),
 		newUnstructured("group/version", "TheKind", "ns-foo", "name-bar"),
@@ -47,20 +49,19 @@ func newFixture(t *testing.T) *fixture {
 	}
 
 	// set discovery Client
-	client.SetDiscovery(NewFakeDiscoveryClient(regresource))
+	client.SetDiscovery(NewFakeDiscoveryClient(regResource))
 
 	f := fixture{
-		t:            t,
-		regresources: regresource,
-		objects:      objects,
-		client:       client,
+		t:       t,
+		objects: objects,
+		client:  client,
 	}
 	return &f
 
 }
 
 func TestCRUDResource(t *testing.T) {
-	t.Skip("Under Development. Reason: delay in generation of resources, so test fails at times")
+	//	t.Skip("Under Development. Reason: delay in generation of resources, so test fails at times")
 	f := newFixture(t)
 	// Get Resource
 	_, err := f.client.GetResource("thekinds", "ns-foo", "name-foo")
@@ -118,7 +119,7 @@ func TestCSRInterface(t *testing.T) {
 }
 
 func TestGenerateResource(t *testing.T) {
-	t.Skip("Under Development. Reason: delay in generation of resources, so test fails at times")
+	//	t.Skip("Under Development. Reason: delay in generation of resources, so test fails at times")
 
 	f := newFixture(t)
 	//GenerateResource -> copy From
diff --git a/pkg/dclient/utils.go b/pkg/dclient/utils.go
index 1650f20081..c87030a563 100644
--- a/pkg/dclient/utils.go
+++ b/pkg/dclient/utils.go
@@ -37,16 +37,21 @@ func NewMockClient(scheme *runtime.Scheme, objects ...runtime.Object) (*Client,
 }
 
 // NewFakeDiscoveryClient returns a fakediscovery client
-func NewFakeDiscoveryClient(regResources map[string]string) *fakeDiscoveryClient {
-	registeredResources := make([]schema.GroupVersionResource, len(regResources))
-	for groupVersion, resource := range regResources {
-		gv, err := schema.ParseGroupVersion(groupVersion)
-		if err != nil {
-			continue
-		}
-		registeredResources = append(registeredResources, gv.WithResource(resource))
+func NewFakeDiscoveryClient(registeredResouces []schema.GroupVersionResource) *fakeDiscoveryClient {
+	// Load some-preregistd resources
+	res := []schema.GroupVersionResource{
+		schema.GroupVersionResource{Version: "v1", Resource: "configmaps"},
+		schema.GroupVersionResource{Version: "v1", Resource: "endpoints"},
+		schema.GroupVersionResource{Version: "v1", Resource: "namespaces"},
+		schema.GroupVersionResource{Version: "v1", Resource: "resourcequotas"},
+		schema.GroupVersionResource{Version: "v1", Resource: "secrets"},
+		schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"},
+		schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "daemonsets"},
+		schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
+		schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "statefulsets"},
 	}
-	return &fakeDiscoveryClient{registeredResouces: registeredResources}
+	registeredResouces = append(registeredResouces, res...)
+	return &fakeDiscoveryClient{registeredResouces: registeredResouces}
 }
 
 type fakeDiscoveryClient struct {
@@ -85,3 +90,22 @@ func newUnstructuredWithSpec(apiVersion, kind, namespace, name string, spec map[
 	u.Object["spec"] = spec
 	return u
 }
+
+func retry(attempts int, sleep time.Duration, fn func() error) error {
+	if err := fn(); err != nil {
+		if s, ok := err.(stop); ok {
+			return s.error
+		}
+		if attempts--; attempts > 0 {
+			time.Sleep(sleep)
+			return retry(attempts, 2*sleep, fn)
+		}
+		return err
+	}
+	return nil
+}
+
+// Custom error
+type stop struct {
+	error
+}

From 860d2f8df18b5a8ff2e81af3817cdd65af95c3cf Mon Sep 17 00:00:00 2001
From: shivdudhani <shivkumar@nirmata.com>
Date: Mon, 17 Jun 2019 18:35:40 -0700
Subject: [PATCH 5/6] enable test

---
 pkg/dclient/client_test.go | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/pkg/dclient/client_test.go b/pkg/dclient/client_test.go
index 62b798382e..a7526c2c51 100644
--- a/pkg/dclient/client_test.go
+++ b/pkg/dclient/client_test.go
@@ -61,7 +61,6 @@ func newFixture(t *testing.T) *fixture {
 }
 
 func TestCRUDResource(t *testing.T) {
-	//	t.Skip("Under Development. Reason: delay in generation of resources, so test fails at times")
 	f := newFixture(t)
 	// Get Resource
 	_, err := f.client.GetResource("thekinds", "ns-foo", "name-foo")
@@ -119,8 +118,6 @@ func TestCSRInterface(t *testing.T) {
 }
 
 func TestGenerateResource(t *testing.T) {
-	//	t.Skip("Under Development. Reason: delay in generation of resources, so test fails at times")
-
 	f := newFixture(t)
 	//GenerateResource -> copy From
 	// 1 create namespace

From ba43509b4390ca5317f2750b59bcdb2c14cf26f5 Mon Sep 17 00:00:00 2001
From: shivdudhani <shivkumar@nirmata.com>
Date: Mon, 17 Jun 2019 18:42:23 -0700
Subject: [PATCH 6/6] fix format

---
 pkg/controller/controller_test.go | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/pkg/controller/controller_test.go b/pkg/controller/controller_test.go
index 8a300f1683..95223e0ffb 100644
--- a/pkg/controller/controller_test.go
+++ b/pkg/controller/controller_test.go
@@ -10,6 +10,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/sample-controller/pkg/signals"
 )
 
@@ -78,7 +79,10 @@ func (f *fixture) setupFixture() {
 	if err != nil {
 		f.t.Fatal(err)
 	}
-	regresource := map[string]string{"kyverno.io/v1alpha1": "policys"}
+	regresource := []schema.GroupVersionResource{
+		schema.GroupVersionResource{Group: "kyverno.io",
+			Version:  "v1alpha1",
+			Resource: "policys"}}
 	fclient.SetDiscovery(client.NewFakeDiscoveryClient(regresource))
 }