Example #1
0
func testHealthScheduler(t test.Tester) {
	now := time.Now()
	var scenarios = []struct {
		futureHealthState []TargetState
		preloadedTimes    []time.Time
		expectedSchedule  []time.Time
	}{
		// The behavior discussed in healthScheduler.Reschedule should be read
		// fully to understand the whys and wherefores.
		{
			futureHealthState: []TargetState{UNKNOWN, ALIVE, ALIVE},
			preloadedTimes:    []time.Time{now, now.Add(time.Minute), now.Add(time.Minute * 2)},
			expectedSchedule:  []time.Time{now, now.Add(time.Minute), now.Add(time.Minute * 2)},
		},
		{
			futureHealthState: []TargetState{UNKNOWN, UNREACHABLE, UNREACHABLE},
			preloadedTimes:    []time.Time{now, now.Add(time.Minute), now.Add(time.Minute * 2)},
			expectedSchedule:  []time.Time{now, now.Add(time.Second * 2), now.Add(time.Minute).Add(time.Second * 4)},
		},
		{
			futureHealthState: []TargetState{UNKNOWN, UNREACHABLE, ALIVE},
			preloadedTimes:    []time.Time{now, now.Add(time.Minute), now.Add(time.Minute * 2)},
			expectedSchedule:  []time.Time{now, now.Add(time.Second * 2), now.Add(time.Minute * 2)},
		},
		{
			futureHealthState: []TargetState{UNKNOWN, UNREACHABLE, UNREACHABLE, UNREACHABLE, UNREACHABLE, UNREACHABLE, UNREACHABLE, UNREACHABLE, UNREACHABLE, UNREACHABLE, UNREACHABLE, UNREACHABLE, UNREACHABLE},
			preloadedTimes:    []time.Time{now, now.Add(time.Minute), now.Add(time.Minute * 2), now.Add(time.Minute * 3), now.Add(time.Minute * 4), now.Add(time.Minute * 5), now.Add(time.Minute * 6), now.Add(time.Minute * 7), now.Add(time.Minute * 8), now.Add(time.Minute * 9), now.Add(time.Minute * 10), now.Add(time.Minute * 11), now.Add(time.Minute * 12)},
			expectedSchedule:  []time.Time{now, now.Add(time.Second * 2), now.Add(time.Minute * 1).Add(time.Second * 4), now.Add(time.Minute * 2).Add(time.Second * 8), now.Add(time.Minute * 3).Add(time.Second * 16), now.Add(time.Minute * 4).Add(time.Second * 32), now.Add(time.Minute * 5).Add(time.Second * 64), now.Add(time.Minute * 6).Add(time.Second * 128), now.Add(time.Minute * 7).Add(time.Second * 256), now.Add(time.Minute * 8).Add(time.Second * 512), now.Add(time.Minute * 9).Add(time.Second * 1024), now.Add(time.Minute * 10).Add(time.Minute * 30), now.Add(time.Minute * 11).Add(time.Minute * 30)},
		},
	}

	for i, scenario := range scenarios {
		provider := &fakeTimeProvider{}
		for _, time := range scenario.preloadedTimes {
			provider.timeQueue = append(provider.timeQueue, time)
		}

		reporter := fakeHealthReporter{}
		for _, state := range scenario.futureHealthState {
			reporter.stateQueue = append(reporter.stateQueue, state)
		}
		if len(scenario.preloadedTimes) != len(scenario.futureHealthState) || len(scenario.futureHealthState) != len(scenario.expectedSchedule) {
			t.Fatalf("%d. times and health reports and next time lengths were not equal.", i)
		}

		timer := timer{
			provider: provider,
		}

		scheduler := healthScheduler{
			timer:        timer,
			target:       reporter,
			scheduledFor: now,
		}

		for j := 0; j < len(scenario.preloadedTimes); j++ {
			futureState := scenario.futureHealthState[j]
			scheduler.Reschedule(scenario.preloadedTimes[j], futureState)
			nextSchedule := scheduler.ScheduledFor()
			if nextSchedule != scenario.expectedSchedule[j] {
				t.Errorf("%d.%d. Expected to be scheduled to %s, got %s", i, j, scenario.expectedSchedule[j], nextSchedule)
			}
		}
	}
}
Example #2
0
func testTargetPool(t test.Tester) {
	type expectation struct {
		size int
	}

	type input struct {
		address      string
		scheduledFor time.Time
	}

	type output struct {
		address string
	}

	var scenarios = []struct {
		name    string
		outputs []output
		inputs  []input
	}{
		{
			name:    "empty",
			inputs:  []input{},
			outputs: []output{},
		},
		{
			name: "single element",
			inputs: []input{
				{
					address: "http://single.com",
				},
			},
			outputs: []output{
				{
					address: "http://single.com",
				},
			},
		},
		{
			name: "plural descending schedules",
			inputs: []input{
				{
					address:      "http://plural-descending.com",
					scheduledFor: time.Date(2013, 1, 4, 12, 0, 0, 0, time.UTC),
				},
				{
					address:      "http://plural-descending.net",
					scheduledFor: time.Date(2013, 1, 4, 11, 0, 0, 0, time.UTC),
				},
			},
			outputs: []output{
				{
					address: "http://plural-descending.net",
				},
				{
					address: "http://plural-descending.com",
				},
			},
		},
		{
			name: "plural ascending schedules",
			inputs: []input{
				{
					address:      "http://plural-ascending.net",
					scheduledFor: time.Date(2013, 1, 4, 11, 0, 0, 0, time.UTC),
				},
				{
					address:      "http://plural-ascending.com",
					scheduledFor: time.Date(2013, 1, 4, 12, 0, 0, 0, time.UTC),
				},
			},
			outputs: []output{
				{
					address: "http://plural-ascending.net",
				},
				{
					address: "http://plural-ascending.com",
				},
			},
		},
	}

	for i, scenario := range scenarios {
		pool := TargetPool{}

		for _, input := range scenario.inputs {
			target := target{
				address:   input.address,
				scheduler: literalScheduler(input.scheduledFor),
			}

			heap.Push(&pool, &target)
		}

		targets := []Target{}

		if pool.Len() != len(scenario.outputs) {
			t.Errorf("%s %d. expected TargetPool size to be %d but was %d", scenario.name, i, len(scenario.outputs), pool.Len())
		} else {
			for j, output := range scenario.outputs {
				target := heap.Pop(&pool).(Target)

				if target.Address() != output.address {
					t.Errorf("%s %d.%d. expected Target address to be %s but was %s", scenario.name, i, j, output.address, target.Address())

				}
				targets = append(targets, target)
			}

			if pool.Len() != 0 {
				t.Errorf("%s %d. expected pool to be empty, had %d", scenario.name, i, pool.Len())
			}

			if len(targets) != len(scenario.outputs) {
				t.Errorf("%s %d. expected to receive %d elements, got %d", scenario.name, i, len(scenario.outputs), len(targets))
			}

			for _, target := range targets {
				heap.Push(&pool, target)
			}

			if pool.Len() != len(scenario.outputs) {
				t.Errorf("%s %d. expected to repopulated with %d elements, got %d", scenario.name, i, len(scenario.outputs), pool.Len())
			}
		}
	}
}