Skip to content

Commit

Permalink
Move additional core/v1 mocks into tests package
Browse files Browse the repository at this point in the history
Convert nodepassword tests to use shared mocks

Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
  • Loading branch information
brandond committed Dec 18, 2024
1 parent 8de0756 commit 0ca3cae
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 106 deletions.
115 changes: 31 additions & 84 deletions pkg/nodepassword/nodepassword_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"testing"

"github.com/golang/mock/gomock"
"github.com/rancher/wrangler/v3/pkg/generic/fake"
"github.com/k3s-io/k3s/tests/mock"
v1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -28,10 +28,11 @@ func Test_UnitAsserts(t *testing.T) {
func Test_UnitEnsureDelete(t *testing.T) {
logMemUsage(t)

ctrl := gomock.NewController(t)
secretClient := fake.NewMockControllerInterface[*v1.Secret, *v1.SecretList](ctrl)
secretCache := fake.NewMockCacheInterface[*v1.Secret](ctrl)
secretStore := &mockSecretStore{}
v1Mock := mock.NewV1(gomock.NewController(t))

secretClient := v1Mock.SecretMock
secretCache := v1Mock.SecretCache
secretStore := &mock.SecretStore{}

// Set up expected call counts for tests
// Expect to see 2 creates, any number of cache gets, and 2 deletes.
Expand Down Expand Up @@ -59,15 +60,15 @@ func Test_UnitMigrateFile(t *testing.T) {
nodePasswordFile := generateNodePasswordFile(migrateNumNodes)
defer os.Remove(nodePasswordFile)

ctrl := gomock.NewController(t)
v1Mock := mock.NewV1(gomock.NewController(t))

secretClient := fake.NewMockControllerInterface[*v1.Secret, *v1.SecretList](ctrl)
secretCache := fake.NewMockCacheInterface[*v1.Secret](ctrl)
secretStore := &mockSecretStore{}
secretClient := v1Mock.SecretMock
secretCache := v1Mock.SecretCache
secretStore := &mock.SecretStore{}

nodeClient := fake.NewMockNonNamespacedControllerInterface[*v1.Node, *v1.NodeList](ctrl)
nodeCache := fake.NewMockNonNamespacedCacheInterface[*v1.Node](ctrl)
nodeStore := &mockNodeStore{}
nodeClient := v1Mock.NodeMock
nodeCache := v1Mock.NodeCache
nodeStore := &mock.NodeStore{}

// Set up expected call counts for tests
// Expect to see 1 node list, any number of cache gets, and however many
Expand All @@ -93,19 +94,20 @@ func Test_UnitMigrateFileNodes(t *testing.T) {
nodePasswordFile := generateNodePasswordFile(migrateNumNodes)
defer os.Remove(nodePasswordFile)

ctrl := gomock.NewController(t)
v1Mock := mock.NewV1(gomock.NewController(t))

secretClient := fake.NewMockControllerInterface[*v1.Secret, *v1.SecretList](ctrl)
secretCache := fake.NewMockCacheInterface[*v1.Secret](ctrl)
secretStore := &mockSecretStore{}
secretClient := v1Mock.SecretMock
secretCache := v1Mock.SecretCache
secretStore := &mock.SecretStore{}

nodeClient := fake.NewMockNonNamespacedControllerInterface[*v1.Node, *v1.NodeList](ctrl)
nodeCache := fake.NewMockNonNamespacedCacheInterface[*v1.Node](ctrl)
nodeStore := &mockNodeStore{}
nodeClient := v1Mock.NodeMock
nodeCache := v1Mock.NodeCache
nodeStore := &mock.NodeStore{}

nodeStore.nodes = make([]v1.Node, createNumNodes, createNumNodes)
for i := range nodeStore.nodes {
nodeStore.nodes[i].Name = fmt.Sprintf("node%d", i+1)
for i := 0; i < createNumNodes; i++ {
if _, err := nodeStore.Create(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("node%d", i+1)}}); err != nil {
t.Fatal(err)
}
}

// Set up expected call counts for tests
Expand All @@ -124,9 +126,13 @@ func Test_UnitMigrateFileNodes(t *testing.T) {
}
logMemUsage(t)

for _, node := range nodeStore.nodes {
assertNotEqual(t, Ensure(secretClient, node.Name, "wrong-password"), nil)
assertEqual(t, Ensure(secretClient, node.Name, node.Name), nil)
if nodes, err := nodeStore.List(labels.Everything()); err != nil {
t.Fatal(err)
} else {
for _, node := range nodes {
assertNotEqual(t, Ensure(secretClient, node.Name, "wrong-password"), nil)
assertEqual(t, Ensure(secretClient, node.Name, node.Name), nil)
}
}

newNode := fmt.Sprintf("node%d", migrateNumNodes+1)
Expand All @@ -141,65 +147,6 @@ func Test_PasswordError(t *testing.T) {
assertNotEqual(t, errors.Unwrap(err), nil)
}

// --------------------------
// mock secret store interface

type mockSecretStore struct {
entries map[string]map[string]v1.Secret
}

func (m *mockSecretStore) Create(secret *v1.Secret) (*v1.Secret, error) {
if m.entries == nil {
m.entries = map[string]map[string]v1.Secret{}
}
if _, ok := m.entries[secret.Namespace]; !ok {
m.entries[secret.Namespace] = map[string]v1.Secret{}
}
if _, ok := m.entries[secret.Namespace][secret.Name]; ok {
return nil, errorAlreadyExists()
}
m.entries[secret.Namespace][secret.Name] = *secret
return secret, nil
}

func (m *mockSecretStore) Delete(namespace, name string, options *metav1.DeleteOptions) error {
if m.entries == nil {
return errorNotFound()
}
if _, ok := m.entries[namespace]; !ok {
return errorNotFound()
}
if _, ok := m.entries[namespace][name]; !ok {
return errorNotFound()
}
delete(m.entries[namespace], name)
return nil
}

func (m *mockSecretStore) Get(namespace, name string) (*v1.Secret, error) {
if m.entries == nil {
return nil, errorNotFound()
}
if _, ok := m.entries[namespace]; !ok {
return nil, errorNotFound()
}
if secret, ok := m.entries[namespace][name]; ok {
return &secret, nil
}
return nil, errorNotFound()
}

// --------------------------
// mock node store interface

type mockNodeStore struct {
nodes []v1.Node
}

func (m *mockNodeStore) List(ls labels.Selector) ([]v1.Node, error) {
return m.nodes, nil
}

// --------------------------
// utility functions

Expand Down
151 changes: 129 additions & 22 deletions tests/mock/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"github.com/rancher/wrangler/v3/pkg/generic/fake"
v1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
)

Expand Down Expand Up @@ -35,32 +37,54 @@ func (m *CoreMock) V1() corev1.Interface {
var _ corev1.Interface = &V1Mock{}

type V1Mock struct {
ConfigMapMock *fake.MockControllerInterface[*v1.ConfigMap, *v1.ConfigMapList]
EndpointsMock *fake.MockControllerInterface[*v1.Endpoints, *v1.EndpointsList]
EventMock *fake.MockControllerInterface[*v1.Event, *v1.EventList]
NamespaceMock *fake.MockNonNamespacedControllerInterface[*v1.Namespace, *v1.NamespaceList]
NodeMock *fake.MockNonNamespacedControllerInterface[*v1.Node, *v1.NodeList]
PersistentVolumeMock *fake.MockNonNamespacedControllerInterface[*v1.PersistentVolume, *v1.PersistentVolumeList]
PersistentVolumeClaimMock *fake.MockControllerInterface[*v1.PersistentVolumeClaim, *v1.PersistentVolumeClaimList]
PodMock *fake.MockControllerInterface[*v1.Pod, *v1.PodList]
SecretMock *fake.MockControllerInterface[*v1.Secret, *v1.SecretList]
ServiceMock *fake.MockControllerInterface[*v1.Service, *v1.ServiceList]
ServiceAccountMock *fake.MockControllerInterface[*v1.ServiceAccount, *v1.ServiceAccountList]
ConfigMapMock *fake.MockControllerInterface[*v1.ConfigMap, *v1.ConfigMapList]
ConfigMapCache *fake.MockCacheInterface[*v1.ConfigMap]
EndpointsMock *fake.MockControllerInterface[*v1.Endpoints, *v1.EndpointsList]
EndpointsCache *fake.MockCacheInterface[*v1.Endpoints]
EventMock *fake.MockControllerInterface[*v1.Event, *v1.EventList]
EventCache *fake.MockCacheInterface[*v1.Event]
NamespaceMock *fake.MockNonNamespacedControllerInterface[*v1.Namespace, *v1.NamespaceList]
NamespaceCache *fake.MockNonNamespacedCacheInterface[*v1.Namespace]
NodeMock *fake.MockNonNamespacedControllerInterface[*v1.Node, *v1.NodeList]
NodeCache *fake.MockNonNamespacedCacheInterface[*v1.Node]
PersistentVolumeMock *fake.MockNonNamespacedControllerInterface[*v1.PersistentVolume, *v1.PersistentVolumeList]
PersistentVolumeCache *fake.MockNonNamespacedCacheInterface[*v1.PersistentVolume]
PersistentVolumeClaimMock *fake.MockControllerInterface[*v1.PersistentVolumeClaim, *v1.PersistentVolumeClaimList]
PersistentVolumeClaimCache *fake.MockCacheInterface[*v1.PersistentVolumeClaim]
PodMock *fake.MockControllerInterface[*v1.Pod, *v1.PodList]
PodCache *fake.MockCacheInterface[*v1.Pod]
SecretMock *fake.MockControllerInterface[*v1.Secret, *v1.SecretList]
SecretCache *fake.MockCacheInterface[*v1.Secret]
ServiceMock *fake.MockControllerInterface[*v1.Service, *v1.ServiceList]
ServiceCache *fake.MockCacheInterface[*v1.Service]
ServiceAccountMock *fake.MockControllerInterface[*v1.ServiceAccount, *v1.ServiceAccountList]
ServiceAccountCache *fake.MockCacheInterface[*v1.ServiceAccount]
}

func NewV1(c *gomock.Controller) *V1Mock {
return &V1Mock{
ConfigMapMock: fake.NewMockControllerInterface[*v1.ConfigMap, *v1.ConfigMapList](c),
EndpointsMock: fake.NewMockControllerInterface[*v1.Endpoints, *v1.EndpointsList](c),
EventMock: fake.NewMockControllerInterface[*v1.Event, *v1.EventList](c),
NamespaceMock: fake.NewMockNonNamespacedControllerInterface[*v1.Namespace, *v1.NamespaceList](c),
NodeMock: fake.NewMockNonNamespacedControllerInterface[*v1.Node, *v1.NodeList](c),
PersistentVolumeMock: fake.NewMockNonNamespacedControllerInterface[*v1.PersistentVolume, *v1.PersistentVolumeList](c),
PersistentVolumeClaimMock: fake.NewMockControllerInterface[*v1.PersistentVolumeClaim, *v1.PersistentVolumeClaimList](c),
PodMock: fake.NewMockControllerInterface[*v1.Pod, *v1.PodList](c),
SecretMock: fake.NewMockControllerInterface[*v1.Secret, *v1.SecretList](c),
ServiceMock: fake.NewMockControllerInterface[*v1.Service, *v1.ServiceList](c),
ServiceAccountMock: fake.NewMockControllerInterface[*v1.ServiceAccount, *v1.ServiceAccountList](c),
ConfigMapMock: fake.NewMockControllerInterface[*v1.ConfigMap, *v1.ConfigMapList](c),
ConfigMapCache: fake.NewMockCacheInterface[*v1.ConfigMap](c),
EndpointsMock: fake.NewMockControllerInterface[*v1.Endpoints, *v1.EndpointsList](c),
EndpointsCache: fake.NewMockCacheInterface[*v1.Endpoints](c),
EventMock: fake.NewMockControllerInterface[*v1.Event, *v1.EventList](c),
EventCache: fake.NewMockCacheInterface[*v1.Event](c),
NamespaceMock: fake.NewMockNonNamespacedControllerInterface[*v1.Namespace, *v1.NamespaceList](c),
NamespaceCache: fake.NewMockNonNamespacedCacheInterface[*v1.Namespace](c),
NodeMock: fake.NewMockNonNamespacedControllerInterface[*v1.Node, *v1.NodeList](c),
NodeCache: fake.NewMockNonNamespacedCacheInterface[*v1.Node](c),
PersistentVolumeMock: fake.NewMockNonNamespacedControllerInterface[*v1.PersistentVolume, *v1.PersistentVolumeList](c),
PersistentVolumeCache: fake.NewMockNonNamespacedCacheInterface[*v1.PersistentVolume](c),
PersistentVolumeClaimMock: fake.NewMockControllerInterface[*v1.PersistentVolumeClaim, *v1.PersistentVolumeClaimList](c),
PersistentVolumeClaimCache: fake.NewMockCacheInterface[*v1.PersistentVolumeClaim](c),
PodMock: fake.NewMockControllerInterface[*v1.Pod, *v1.PodList](c),
PodCache: fake.NewMockCacheInterface[*v1.Pod](c),
SecretMock: fake.NewMockControllerInterface[*v1.Secret, *v1.SecretList](c),
SecretCache: fake.NewMockCacheInterface[*v1.Secret](c),
ServiceMock: fake.NewMockControllerInterface[*v1.Service, *v1.ServiceList](c),
ServiceCache: fake.NewMockCacheInterface[*v1.Service](c),
ServiceAccountMock: fake.NewMockControllerInterface[*v1.ServiceAccount, *v1.ServiceAccountList](c),
ServiceAccountCache: fake.NewMockCacheInterface[*v1.ServiceAccount](c),
}
}

Expand Down Expand Up @@ -108,6 +132,89 @@ func (m *V1Mock) ServiceAccount() corev1.ServiceAccountController {
return m.ServiceAccountMock
}

// mock secret store interface

type SecretStore struct {
secrets map[string]map[string]v1.Secret
}

func (m *SecretStore) Create(secret *v1.Secret) (*v1.Secret, error) {
if m.secrets == nil {
m.secrets = map[string]map[string]v1.Secret{}
}
if _, ok := m.secrets[secret.Namespace]; !ok {
m.secrets[secret.Namespace] = map[string]v1.Secret{}
}
if _, ok := m.secrets[secret.Namespace][secret.Name]; ok {
return nil, ErrorAlreadyExists("secret", secret.Name)
}
m.secrets[secret.Namespace][secret.Name] = *secret
return secret, nil
}

func (m *SecretStore) Delete(namespace, name string, options *metav1.DeleteOptions) error {
if m.secrets == nil {
return ErrorNotFound("secret", name)
}
if _, ok := m.secrets[namespace]; !ok {
return ErrorNotFound("secret", name)
}
if _, ok := m.secrets[namespace][name]; !ok {
return ErrorNotFound("secret", name)
}
delete(m.secrets[namespace], name)
return nil
}

func (m *SecretStore) Get(namespace, name string) (*v1.Secret, error) {
if m.secrets == nil {
return nil, ErrorNotFound("secret", name)
}
if _, ok := m.secrets[namespace]; !ok {
return nil, ErrorNotFound("secret", name)
}
if secret, ok := m.secrets[namespace][name]; ok {
return &secret, nil
}
return nil, ErrorNotFound("secret", name)
}

// mock node store interface

type NodeStore struct {
nodes map[string]v1.Node
}

func (m *NodeStore) Create(node *v1.Node) (*v1.Node, error) {
if m.nodes == nil {
m.nodes = map[string]v1.Node{}
}
if _, ok := m.nodes[node.Name]; ok {
return nil, ErrorAlreadyExists("node", node.Name)
}
m.nodes[node.Name] = *node
return node, nil
}

func (m *NodeStore) List(ls labels.Selector) ([]v1.Node, error) {
nodes := []v1.Node{}
if ls == nil {
ls = labels.Everything()
}
for _, node := range m.nodes {
if ls.Matches(labels.Set(node.Labels)) {
nodes = append(nodes, node)
}
}
return nodes, nil
}

// utility functions

func ErrorNotFound(gv, name string) error {
return apierrors.NewNotFound(schema.ParseGroupResource(gv), name)
}

func ErrorAlreadyExists(gv, name string) error {
return apierrors.NewAlreadyExists(schema.ParseGroupResource(gv), name)
}

0 comments on commit 0ca3cae

Please sign in to comment.