mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			211 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			211 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
Copyright 2015 The Kubernetes Authors.
 | 
						|
 | 
						|
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 container
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"strconv"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/stretchr/testify/assert"
 | 
						|
	"k8s.io/apimachinery/pkg/types"
 | 
						|
)
 | 
						|
 | 
						|
func newTestCache() *cache {
 | 
						|
	c := NewCache()
 | 
						|
	return c.(*cache)
 | 
						|
}
 | 
						|
 | 
						|
func TestCacheNotInitialized(t *testing.T) {
 | 
						|
	cache := newTestCache()
 | 
						|
	// If the global timestamp is not set, always return nil.
 | 
						|
	d := cache.getIfNewerThan(types.UID("1234"), time.Time{})
 | 
						|
	assert.True(t, d == nil, "should return nil since cache is not initialized")
 | 
						|
}
 | 
						|
 | 
						|
func getTestPodIDAndStatus(numContainers int) (types.UID, *PodStatus) {
 | 
						|
	id := types.UID(strconv.FormatInt(time.Now().UnixNano(), 10))
 | 
						|
	name := fmt.Sprintf("cache-foo-%s", string(id))
 | 
						|
	namespace := "ns"
 | 
						|
	var status *PodStatus
 | 
						|
	if numContainers > 0 {
 | 
						|
		status = &PodStatus{ID: id, Name: name, Namespace: namespace}
 | 
						|
	} else {
 | 
						|
		status = &PodStatus{ID: id}
 | 
						|
	}
 | 
						|
	for i := 0; i < numContainers; i++ {
 | 
						|
		status.ContainerStatuses = append(status.ContainerStatuses, &Status{Name: strconv.Itoa(i)})
 | 
						|
	}
 | 
						|
	return id, status
 | 
						|
}
 | 
						|
 | 
						|
func TestGetIfNewerThanWhenPodExists(t *testing.T) {
 | 
						|
	cache := newTestCache()
 | 
						|
	timestamp := time.Now()
 | 
						|
 | 
						|
	cases := []struct {
 | 
						|
		cacheTime time.Time
 | 
						|
		modified  time.Time
 | 
						|
		expected  bool
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			// Both the global cache timestamp and the modified time are newer
 | 
						|
			// than the timestamp.
 | 
						|
			cacheTime: timestamp.Add(time.Second),
 | 
						|
			modified:  timestamp,
 | 
						|
			expected:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			// Global cache timestamp is newer, but the pod entry modified
 | 
						|
			// time is older than the given timestamp. This means that the
 | 
						|
			// entry is up-to-date even though it hasn't changed for a while.
 | 
						|
			cacheTime: timestamp.Add(time.Second),
 | 
						|
			modified:  timestamp.Add(-time.Second * 10),
 | 
						|
			expected:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			// Global cache timestamp is older, but the pod entry modified
 | 
						|
			// time is newer than the given timestamp. This means that the
 | 
						|
			// entry is up-to-date but the rest of the cache are still being
 | 
						|
			// updated.
 | 
						|
			cacheTime: timestamp.Add(-time.Second),
 | 
						|
			modified:  timestamp.Add(time.Second * 3),
 | 
						|
			expected:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			// Both the global cache timestamp and the modified time are older
 | 
						|
			// than the given timestamp.
 | 
						|
			cacheTime: timestamp.Add(-time.Second),
 | 
						|
			modified:  timestamp.Add(-time.Second),
 | 
						|
			expected:  false,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	for i, c := range cases {
 | 
						|
		podID, status := getTestPodIDAndStatus(2)
 | 
						|
		cache.UpdateTime(c.cacheTime)
 | 
						|
		cache.Set(podID, status, nil, c.modified)
 | 
						|
		d := cache.getIfNewerThan(podID, timestamp)
 | 
						|
		assert.Equal(t, c.expected, d != nil, "test[%d]", i)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestGetPodNewerThanWhenPodDoesNotExist(t *testing.T) {
 | 
						|
	cache := newTestCache()
 | 
						|
	cacheTime := time.Now()
 | 
						|
	cache.UpdateTime(cacheTime)
 | 
						|
	podID := types.UID("1234")
 | 
						|
 | 
						|
	cases := []struct {
 | 
						|
		timestamp time.Time
 | 
						|
		expected  bool
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			timestamp: cacheTime.Add(-time.Second),
 | 
						|
			expected:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			timestamp: cacheTime.Add(time.Second),
 | 
						|
			expected:  false,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	for i, c := range cases {
 | 
						|
		d := cache.getIfNewerThan(podID, c.timestamp)
 | 
						|
		assert.Equal(t, c.expected, d != nil, "test[%d]", i)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestCacheSetAndGet(t *testing.T) {
 | 
						|
	cache := NewCache()
 | 
						|
	cases := []struct {
 | 
						|
		numContainers int
 | 
						|
		error         error
 | 
						|
	}{
 | 
						|
		{numContainers: 3, error: nil},
 | 
						|
		{numContainers: 2, error: fmt.Errorf("unable to get status")},
 | 
						|
		{numContainers: 0, error: nil},
 | 
						|
	}
 | 
						|
	for i, c := range cases {
 | 
						|
		podID, status := getTestPodIDAndStatus(c.numContainers)
 | 
						|
		cache.Set(podID, status, c.error, time.Time{})
 | 
						|
		// Read back the status and error stored in cache and make sure they
 | 
						|
		// match the original ones.
 | 
						|
		actualStatus, actualErr := cache.Get(podID)
 | 
						|
		assert.Equal(t, status, actualStatus, "test[%d]", i)
 | 
						|
		assert.Equal(t, c.error, actualErr, "test[%d]", i)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestCacheGetPodDoesNotExist(t *testing.T) {
 | 
						|
	cache := NewCache()
 | 
						|
	podID, status := getTestPodIDAndStatus(0)
 | 
						|
	// If the pod does not exist in cache, cache should return an status
 | 
						|
	// object with id filled.
 | 
						|
	actualStatus, actualErr := cache.Get(podID)
 | 
						|
	assert.Equal(t, status, actualStatus)
 | 
						|
	assert.Equal(t, nil, actualErr)
 | 
						|
}
 | 
						|
 | 
						|
func TestDelete(t *testing.T) {
 | 
						|
	cache := &cache{pods: map[types.UID]*data{}}
 | 
						|
	// Write a new pod status into the cache.
 | 
						|
	podID, status := getTestPodIDAndStatus(3)
 | 
						|
	cache.Set(podID, status, nil, time.Time{})
 | 
						|
	actualStatus, actualErr := cache.Get(podID)
 | 
						|
	assert.Equal(t, status, actualStatus)
 | 
						|
	assert.Equal(t, nil, actualErr)
 | 
						|
	// Delete the pod from cache, and verify that we get an empty status.
 | 
						|
	cache.Delete(podID)
 | 
						|
	expectedStatus := &PodStatus{ID: podID}
 | 
						|
	actualStatus, actualErr = cache.Get(podID)
 | 
						|
	assert.Equal(t, expectedStatus, actualStatus)
 | 
						|
	assert.Equal(t, nil, actualErr)
 | 
						|
}
 | 
						|
 | 
						|
func verifyNotification(t *testing.T, ch chan *data, expectNotification bool) {
 | 
						|
	if expectNotification {
 | 
						|
		assert.True(t, len(ch) > 0, "Did not receive notification")
 | 
						|
	} else {
 | 
						|
		assert.True(t, len(ch) < 1, "Should not have triggered the notification")
 | 
						|
	}
 | 
						|
	// Drain the channel.
 | 
						|
	for i := 0; i < len(ch); i++ {
 | 
						|
		<-ch
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestRegisterNotification(t *testing.T) {
 | 
						|
	cache := newTestCache()
 | 
						|
	cacheTime := time.Now()
 | 
						|
	cache.UpdateTime(cacheTime)
 | 
						|
 | 
						|
	podID, status := getTestPodIDAndStatus(1)
 | 
						|
	ch := cache.subscribe(podID, cacheTime.Add(time.Second))
 | 
						|
	verifyNotification(t, ch, false)
 | 
						|
	cache.Set(podID, status, nil, cacheTime.Add(time.Second))
 | 
						|
	// The Set operation should've triggered the notification.
 | 
						|
	verifyNotification(t, ch, true)
 | 
						|
 | 
						|
	podID, _ = getTestPodIDAndStatus(1)
 | 
						|
 | 
						|
	ch = cache.subscribe(podID, cacheTime.Add(time.Second))
 | 
						|
	verifyNotification(t, ch, false)
 | 
						|
	cache.UpdateTime(cacheTime.Add(time.Second * 2))
 | 
						|
	// The advance of cache timestamp should've triggered the notification.
 | 
						|
	verifyNotification(t, ch, true)
 | 
						|
}
 |