func TestHealthy(t *testing.T) { testPleg := newTestGenericPLEG() pleg, _, clock := testPleg.pleg, testPleg.runtime, testPleg.clock ok, _ := pleg.Healthy() assert.True(t, ok, "pleg should be healthy") // Advance the clock without any relisting. clock.Step(time.Minute * 10) ok, _ = pleg.Healthy() assert.False(t, ok, "pleg should be unhealthy") // Relist and than advance the time by 1 minute. pleg should be healthy // because this is within the allowed limit. pleg.relist() clock.Step(time.Minute * 1) ok, _ = pleg.Healthy() assert.True(t, ok, "pleg should be healthy") }
func TestRepositoryBucketAddOversize(t *testing.T) { clock := clock.NewFakeClock(time.Now()) b := repositoryBucket{ clock: clock, } i := 0 for ; i < bucketSize; i++ { ttl := time.Duration(uint64(ttl5m) * uint64(i)) b.Add(ttl, fmt.Sprintf("%d", i)) } if len(b.list) != bucketSize { t.Fatalf("unexpected number of items: %d != %d", len(b.list), bucketSize) } // make first three stale clock.Step(ttl5m * 3) if !b.Has("3") { t.Fatalf("bucket does not contain repository 3") } if len(b.list) != bucketSize-3 { t.Fatalf("unexpected number of items: %d != %d", len(b.list), bucketSize-3) } // add few repos one by one for ; i < bucketSize+5; i++ { ttl := time.Duration(uint64(ttl5m) * uint64(i)) b.Add(ttl, fmt.Sprintf("%d", i)) } if len(b.list) != bucketSize { t.Fatalf("unexpected number of items: %d != %d", len(b.list), bucketSize) } // add few repos at once newRepos := []string{} for ; i < bucketSize+10; i++ { newRepos = append(newRepos, fmt.Sprintf("%d", i)) } b.Add(ttl5m, newRepos...) if len(b.list) != bucketSize { t.Fatalf("unexpected number of items: %d != %d", len(b.list), bucketSize) } for j := 0; j < bucketSize; j++ { expected := fmt.Sprintf("%d", i-bucketSize+j) if b.list[j].repository != expected { t.Fatalf("unexpected repository on index %d: %s != %s", j, b.list[j].repository, expected) } } }
func TestGetWork(t *testing.T) { q, clock := newTestBasicWorkQueue() q.Enqueue(types.UID("foo1"), -1*time.Minute) q.Enqueue(types.UID("foo2"), -1*time.Minute) q.Enqueue(types.UID("foo3"), 1*time.Minute) q.Enqueue(types.UID("foo4"), 1*time.Minute) expected := []types.UID{types.UID("foo1"), types.UID("foo2")} compareResults(t, expected, q.GetWork()) compareResults(t, []types.UID{}, q.GetWork()) // Dial the time to 1 hour ahead. clock.Step(time.Hour) expected = []types.UID{types.UID("foo3"), types.UID("foo4")} compareResults(t, expected, q.GetWork()) compareResults(t, []types.UID{}, q.GetWork()) }
func TestMultiSinkCache(t *testing.T) { testPod := &v1.Pod{ ObjectMeta: v1.ObjectMeta{ SelfLink: "/api/version/pods/foo", Name: "foo", Namespace: "baz", UID: "bar", }, } testPod2 := &v1.Pod{ ObjectMeta: v1.ObjectMeta{ SelfLink: "/api/version/pods/foo", Name: "foo", Namespace: "baz", UID: "differentUid", }, } testRef, err := v1.GetPartialReference(testPod, "spec.containers[2]") testRef2, err := v1.GetPartialReference(testPod2, "spec.containers[3]") if err != nil { t.Fatal(err) } table := []struct { obj k8sruntime.Object eventtype string reason string messageFmt string elements []interface{} expect *v1.Event expectLog string expectUpdate bool }{ { obj: testRef, eventtype: v1.EventTypeNormal, reason: "Started", messageFmt: "some verbose message: %v", elements: []interface{}{1}, expect: &v1.Event{ ObjectMeta: v1.ObjectMeta{ Name: "foo", Namespace: "baz", }, InvolvedObject: v1.ObjectReference{ Kind: "Pod", Name: "foo", Namespace: "baz", UID: "bar", APIVersion: "version", FieldPath: "spec.containers[2]", }, Reason: "Started", Message: "some verbose message: 1", Source: v1.EventSource{Component: "eventTest"}, Count: 1, Type: v1.EventTypeNormal, }, expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, expectUpdate: false, }, { obj: testPod, eventtype: v1.EventTypeNormal, reason: "Killed", messageFmt: "some other verbose message: %v", elements: []interface{}{1}, expect: &v1.Event{ ObjectMeta: v1.ObjectMeta{ Name: "foo", Namespace: "baz", }, InvolvedObject: v1.ObjectReference{ Kind: "Pod", Name: "foo", Namespace: "baz", UID: "bar", APIVersion: "version", }, Reason: "Killed", Message: "some other verbose message: 1", Source: v1.EventSource{Component: "eventTest"}, Count: 1, Type: v1.EventTypeNormal, }, expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:""}): type: 'Normal' reason: 'Killed' some other verbose message: 1`, expectUpdate: false, }, { obj: testRef, eventtype: v1.EventTypeNormal, reason: "Started", messageFmt: "some verbose message: %v", elements: []interface{}{1}, expect: &v1.Event{ ObjectMeta: v1.ObjectMeta{ Name: "foo", Namespace: "baz", }, InvolvedObject: v1.ObjectReference{ Kind: "Pod", Name: "foo", Namespace: "baz", UID: "bar", APIVersion: "version", FieldPath: "spec.containers[2]", }, Reason: "Started", Message: "some verbose message: 1", Source: v1.EventSource{Component: "eventTest"}, Count: 2, Type: v1.EventTypeNormal, }, expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, expectUpdate: true, }, { obj: testRef2, eventtype: v1.EventTypeNormal, reason: "Started", messageFmt: "some verbose message: %v", elements: []interface{}{1}, expect: &v1.Event{ ObjectMeta: v1.ObjectMeta{ Name: "foo", Namespace: "baz", }, InvolvedObject: v1.ObjectReference{ Kind: "Pod", Name: "foo", Namespace: "baz", UID: "differentUid", APIVersion: "version", FieldPath: "spec.containers[3]", }, Reason: "Started", Message: "some verbose message: 1", Source: v1.EventSource{Component: "eventTest"}, Count: 1, Type: v1.EventTypeNormal, }, expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, expectUpdate: false, }, { obj: testRef, eventtype: v1.EventTypeNormal, reason: "Started", messageFmt: "some verbose message: %v", elements: []interface{}{1}, expect: &v1.Event{ ObjectMeta: v1.ObjectMeta{ Name: "foo", Namespace: "baz", }, InvolvedObject: v1.ObjectReference{ Kind: "Pod", Name: "foo", Namespace: "baz", UID: "bar", APIVersion: "version", FieldPath: "spec.containers[2]", }, Reason: "Started", Message: "some verbose message: 1", Source: v1.EventSource{Component: "eventTest"}, Count: 3, Type: v1.EventTypeNormal, }, expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, expectUpdate: true, }, { obj: testRef2, eventtype: v1.EventTypeNormal, reason: "Stopped", messageFmt: "some verbose message: %v", elements: []interface{}{1}, expect: &v1.Event{ ObjectMeta: v1.ObjectMeta{ Name: "foo", Namespace: "baz", }, InvolvedObject: v1.ObjectReference{ Kind: "Pod", Name: "foo", Namespace: "baz", UID: "differentUid", APIVersion: "version", FieldPath: "spec.containers[3]", }, Reason: "Stopped", Message: "some verbose message: 1", Source: v1.EventSource{Component: "eventTest"}, Count: 1, Type: v1.EventTypeNormal, }, expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`, expectUpdate: false, }, { obj: testRef2, eventtype: v1.EventTypeNormal, reason: "Stopped", messageFmt: "some verbose message: %v", elements: []interface{}{1}, expect: &v1.Event{ ObjectMeta: v1.ObjectMeta{ Name: "foo", Namespace: "baz", }, InvolvedObject: v1.ObjectReference{ Kind: "Pod", Name: "foo", Namespace: "baz", UID: "differentUid", APIVersion: "version", FieldPath: "spec.containers[3]", }, Reason: "Stopped", Message: "some verbose message: 1", Source: v1.EventSource{Component: "eventTest"}, Count: 2, Type: v1.EventTypeNormal, }, expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`, expectUpdate: true, }, } testCache := map[string]*v1.Event{} createEvent := make(chan *v1.Event) updateEvent := make(chan *v1.Event) patchEvent := make(chan *v1.Event) testEvents := testEventSink{ OnCreate: OnCreateFactory(testCache, createEvent), OnUpdate: func(event *v1.Event) (*v1.Event, error) { updateEvent <- event return event, nil }, OnPatch: OnPatchFactory(testCache, patchEvent), } testCache2 := map[string]*v1.Event{} createEvent2 := make(chan *v1.Event) updateEvent2 := make(chan *v1.Event) patchEvent2 := make(chan *v1.Event) testEvents2 := testEventSink{ OnCreate: OnCreateFactory(testCache2, createEvent2), OnUpdate: func(event *v1.Event) (*v1.Event, error) { updateEvent2 <- event return event, nil }, OnPatch: OnPatchFactory(testCache2, patchEvent2), } eventBroadcaster := NewBroadcasterForTests(0) clock := clock.NewFakeClock(time.Now()) recorder := recorderWithFakeClock(v1.EventSource{Component: "eventTest"}, eventBroadcaster, clock) sinkWatcher := eventBroadcaster.StartRecordingToSink(&testEvents) for index, item := range table { clock.Step(1 * time.Second) recorder.Eventf(item.obj, item.eventtype, item.reason, item.messageFmt, item.elements...) // validate event if item.expectUpdate { actualEvent := <-patchEvent validateEvent(strconv.Itoa(index), actualEvent, item.expect, t) } else { actualEvent := <-createEvent validateEvent(strconv.Itoa(index), actualEvent, item.expect, t) } } // Another StartRecordingToSink call should start to record events with new clean cache. sinkWatcher2 := eventBroadcaster.StartRecordingToSink(&testEvents2) for index, item := range table { clock.Step(1 * time.Second) recorder.Eventf(item.obj, item.eventtype, item.reason, item.messageFmt, item.elements...) // validate event if item.expectUpdate { actualEvent := <-patchEvent2 validateEvent(strconv.Itoa(index), actualEvent, item.expect, t) } else { actualEvent := <-createEvent2 validateEvent(strconv.Itoa(index), actualEvent, item.expect, t) } } sinkWatcher.Stop() sinkWatcher2.Stop() }
func TestEventfNoNamespace(t *testing.T) { testPod := &v1.Pod{ ObjectMeta: v1.ObjectMeta{ SelfLink: "/api/version/pods/foo", Name: "foo", UID: "bar", }, } testRef, err := v1.GetPartialReference(testPod, "spec.containers[2]") if err != nil { t.Fatal(err) } table := []struct { obj k8sruntime.Object eventtype string reason string messageFmt string elements []interface{} expect *v1.Event expectLog string expectUpdate bool }{ { obj: testRef, eventtype: v1.EventTypeNormal, reason: "Started", messageFmt: "some verbose message: %v", elements: []interface{}{1}, expect: &v1.Event{ ObjectMeta: v1.ObjectMeta{ Name: "foo", Namespace: "default", }, InvolvedObject: v1.ObjectReference{ Kind: "Pod", Name: "foo", Namespace: "", UID: "bar", APIVersion: "version", FieldPath: "spec.containers[2]", }, Reason: "Started", Message: "some verbose message: 1", Source: v1.EventSource{Component: "eventTest"}, Count: 1, Type: v1.EventTypeNormal, }, expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, expectUpdate: false, }, } testCache := map[string]*v1.Event{} logCalled := make(chan struct{}) createEvent := make(chan *v1.Event) updateEvent := make(chan *v1.Event) patchEvent := make(chan *v1.Event) testEvents := testEventSink{ OnCreate: OnCreateFactory(testCache, createEvent), OnUpdate: func(event *v1.Event) (*v1.Event, error) { updateEvent <- event return event, nil }, OnPatch: OnPatchFactory(testCache, patchEvent), } eventBroadcaster := NewBroadcasterForTests(0) sinkWatcher := eventBroadcaster.StartRecordingToSink(&testEvents) clock := clock.NewFakeClock(time.Now()) recorder := recorderWithFakeClock(v1.EventSource{Component: "eventTest"}, eventBroadcaster, clock) for index, item := range table { clock.Step(1 * time.Second) logWatcher := eventBroadcaster.StartLogging(func(formatter string, args ...interface{}) { if e, a := item.expectLog, fmt.Sprintf(formatter, args...); e != a { t.Errorf("Expected '%v', got '%v'", e, a) } logCalled <- struct{}{} }) recorder.Eventf(item.obj, item.eventtype, item.reason, item.messageFmt, item.elements...) <-logCalled // validate event if item.expectUpdate { actualEvent := <-patchEvent validateEvent(strconv.Itoa(index), actualEvent, item.expect, t) } else { actualEvent := <-createEvent validateEvent(strconv.Itoa(index), actualEvent, item.expect, t) } logWatcher.Stop() } sinkWatcher.Stop() }