// TestSelectorUpdate ensures that from two overlapping deployments, the one that is working won't
// be marked as overlapping if its selector is updated but still overlaps with the other one.
func TestSelectorUpdate(t *testing.T) {
	f := newFixture(t)
	now := metav1.Now()
	later := metav1.Time{Time: now.Add(time.Minute)}
	selectorUpdated := metav1.Time{Time: later.Add(time.Minute)}

	foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
	foo.CreationTimestamp = now
	foo.Annotations = map[string]string{util.SelectorUpdateAnnotation: selectorUpdated.Format(time.RFC3339)}
	bar := newDeployment("bar", 1, nil, nil, nil, map[string]string{"foo": "bar", "app": "baz"})
	bar.CreationTimestamp = later
	bar.Annotations = map[string]string{util.OverlapAnnotation: "foo"}

	f.dLister = append(f.dLister, foo, bar)
	f.objects = append(f.objects, foo, bar)

	f.expectCreateRSAction(newReplicaSet(foo, "foo-rs", 1))
	f.expectUpdateDeploymentStatusAction(foo)
	f.expectUpdateDeploymentStatusAction(foo)
	f.run(getKey(foo, t))

	for _, a := range filterInformerActions(f.client.Actions()) {
		action, ok := a.(core.UpdateAction)
		if !ok {
			continue
		}
		d, ok := action.GetObject().(*extensions.Deployment)
		if !ok {
			continue
		}

		if d.Name == "foo" && len(d.Annotations[util.OverlapAnnotation]) > 0 {
			t.Errorf("deployment %q should not have the overlapping annotation", d.Name)
		}
		if d.Name == "bar" && len(d.Annotations[util.OverlapAnnotation]) == 0 {
			t.Errorf("deployment %q should have the overlapping annotation", d.Name)
		}
	}
}
func TestSelectorUpdatedBefore(t *testing.T) {
	now := metav1.Now()
	later := metav1.Time{Time: now.Add(time.Minute)}
	selectorUpdated := metav1.Time{Time: later.Add(time.Minute)}
	selectorUpdatedLater := metav1.Time{Time: selectorUpdated.Add(time.Minute)}

	tests := []struct {
		name string

		d1                 extensions.Deployment
		creationTimestamp1 *metav1.Time
		selectorUpdated1   *metav1.Time

		d2                 extensions.Deployment
		creationTimestamp2 *metav1.Time
		selectorUpdated2   *metav1.Time

		expected bool
	}{
		{
			name: "d1 created before d2",

			d1:                 generateDeployment("foo"),
			creationTimestamp1: &now,

			d2:                 generateDeployment("bar"),
			creationTimestamp2: &later,

			expected: true,
		},
		{
			name: "d1 created after d2",

			d1:                 generateDeployment("foo"),
			creationTimestamp1: &later,

			d2:                 generateDeployment("bar"),
			creationTimestamp2: &now,

			expected: false,
		},
		{
			// Think of the following scenario:
			// d1 is created first, d2 is created after and its selector overlaps
			// with d1. d2 is marked as overlapping correctly. If d1's selector is
			// updated and continues to overlap with the selector of d2 then d1 is
			// now marked overlapping and d2 is cleaned up. Proved by the following
			// test case. Callers of SelectorUpdatedBefore should first check for
			// the existence of the overlapping annotation in any of the two deployments
			// prior to comparing their timestamps and as a matter of fact this is
			// now handled in `(dc *DeploymentController) handleOverlap`.
			name: "d1 created before d2 but updated its selector afterwards",

			d1:                 generateDeployment("foo"),
			creationTimestamp1: &now,
			selectorUpdated1:   &selectorUpdated,

			d2:                 generateDeployment("bar"),
			creationTimestamp2: &later,

			expected: false,
		},
		{
			name: "d1 selector is older than d2",

			d1:               generateDeployment("foo"),
			selectorUpdated1: &selectorUpdated,

			d2:               generateDeployment("bar"),
			selectorUpdated2: &selectorUpdatedLater,

			expected: true,
		},
		{
			name: "d1 selector is younger than d2",

			d1:               generateDeployment("foo"),
			selectorUpdated1: &selectorUpdatedLater,

			d2:               generateDeployment("bar"),
			selectorUpdated2: &selectorUpdated,

			expected: false,
		},
	}

	for _, test := range tests {
		t.Logf("running scenario %q", test.name)

		if test.creationTimestamp1 != nil {
			test.d1.CreationTimestamp = *test.creationTimestamp1
		}
		if test.creationTimestamp2 != nil {
			test.d2.CreationTimestamp = *test.creationTimestamp2
		}
		if test.selectorUpdated1 != nil {
			test.d1.Annotations[SelectorUpdateAnnotation] = test.selectorUpdated1.Format(time.RFC3339)
		}
		if test.selectorUpdated2 != nil {
			test.d2.Annotations[SelectorUpdateAnnotation] = test.selectorUpdated2.Format(time.RFC3339)
		}

		if got := SelectorUpdatedBefore(&test.d1, &test.d2); got != test.expected {
			t.Errorf("expected d1 selector to be updated before d2: %t, got: %t", test.expected, got)
		}
	}
}