github.com/docker/compose-on-kubernetes@v0.5.0/internal/controller/stacklistener_test.go (about)

     1  package controller
     2  
     3  import (
     4  	"sync"
     5  	"testing"
     6  
     7  	"github.com/docker/compose-on-kubernetes/api/compose/latest"
     8  	"github.com/stretchr/testify/assert"
     9  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  	"k8s.io/client-go/rest"
    11  	"k8s.io/client-go/tools/cache"
    12  )
    13  
    14  type dummyOwnerCache struct {
    15  	mut  sync.Mutex
    16  	data map[string]stackOwnerCacheEntry
    17  }
    18  
    19  func (s *dummyOwnerCache) remove(key string) {
    20  	s.mut.Lock()
    21  	defer s.mut.Unlock()
    22  	delete(s.data, key)
    23  }
    24  
    25  func (s *dummyOwnerCache) setDirty(key string) {
    26  	s.mut.Lock()
    27  	defer s.mut.Unlock()
    28  	if entry, ok := s.data[key]; ok {
    29  		entry.dirty = true
    30  		s.data[key] = entry
    31  	}
    32  }
    33  
    34  func (s *dummyOwnerCache) getWithRetries(stack *latest.Stack, acceptDirty bool) (rest.ImpersonationConfig, error) {
    35  	return rest.ImpersonationConfig{}, nil
    36  }
    37  func TestStackListenerCacheInvalidation(t *testing.T) {
    38  	cache := &dummyOwnerCache{
    39  		data: map[string]stackOwnerCacheEntry{
    40  			"ns/test-add":    {config: rest.ImpersonationConfig{UserName: "test"}},
    41  			"ns/test-update": {config: rest.ImpersonationConfig{UserName: "test"}},
    42  			"ns/test-delete": {config: rest.ImpersonationConfig{UserName: "test"}},
    43  		},
    44  	}
    45  	reconcileQueue := make(chan string)
    46  	defer close(reconcileQueue)
    47  	deleteQueue := make(chan *latest.Stack)
    48  	defer close(deleteQueue)
    49  	go func() {
    50  		for range reconcileQueue {
    51  		}
    52  	}()
    53  	go func() {
    54  		for range deleteQueue {
    55  		}
    56  	}()
    57  	testee := &StackListener{
    58  		reconcileQueue:         reconcileQueue,
    59  		reconcileDeletionQueue: deleteQueue,
    60  		ownerCache:             cache,
    61  	}
    62  	testee.onAdd(&latest.Stack{
    63  		ObjectMeta: metav1.ObjectMeta{
    64  			Namespace: "ns",
    65  			Name:      "test-add",
    66  		},
    67  	})
    68  	testee.onUpdate(nil, &latest.Stack{
    69  		ObjectMeta: metav1.ObjectMeta{
    70  			Namespace: "ns",
    71  			Name:      "test-update",
    72  		},
    73  	})
    74  	testee.onDelete(&latest.Stack{
    75  		ObjectMeta: metav1.ObjectMeta{
    76  			Namespace: "ns",
    77  			Name:      "test-delete",
    78  		},
    79  	})
    80  
    81  	// delete should not invalidate cache (to make children deletion possible)
    82  	// add and update should
    83  
    84  	addEntry, hasAdd := cache.data["ns/test-add"]
    85  	updateEntry, hasUpdate := cache.data["ns/test-update"]
    86  	deleteEntry, hasDelete := cache.data["ns/test-delete"]
    87  	assert.True(t, hasAdd)
    88  	assert.True(t, addEntry.dirty)
    89  	assert.True(t, hasUpdate)
    90  	assert.True(t, updateEntry.dirty)
    91  	assert.True(t, hasDelete)
    92  	assert.False(t, deleteEntry.dirty)
    93  }
    94  
    95  type testStore struct {
    96  	store cache.Store
    97  }
    98  
    99  func (s *testStore) GetStore() cache.Store {
   100  	return s.store
   101  }
   102  
   103  func (s *testStore) Run(<-chan struct{}) {
   104  }
   105  
   106  func TestStackListenerGetByKey(t *testing.T) {
   107  	storeMock := &testStore{store: cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc)}
   108  	storeMock.store.Add(&latest.Stack{
   109  		ObjectMeta: metav1.ObjectMeta{
   110  			Namespace: "test-ns",
   111  			Name:      "test-name",
   112  		},
   113  	})
   114  	testee := &StackListener{stacks: storeMock}
   115  
   116  	v, err := testee.get("test-ns/test-name")
   117  	assert.NoError(t, err)
   118  	assert.NotNil(t, v)
   119  	_, err = testee.get("test-ns/no-exists")
   120  	assert.EqualError(t, err, "not found: test-ns/no-exists")
   121  }