File size: 2,630 Bytes
6a7089a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package allocation_test

import (
	"testing"

	"github.com/pinchtab/pinchtab/internal/allocation"
	"github.com/pinchtab/pinchtab/internal/bridge"
)

func candidates(ids ...string) []bridge.Instance {
	out := make([]bridge.Instance, len(ids))
	for i, id := range ids {
		out[i] = bridge.Instance{ID: id, Status: "running"}
	}
	return out
}

func TestFCFS_SelectsFirst(t *testing.T) {
	p := &allocation.FCFS{}
	got, err := p.Select(candidates("a", "b", "c"))
	if err != nil {
		t.Fatal(err)
	}
	if got.ID != "a" {
		t.Errorf("expected a, got %s", got.ID)
	}
}

func TestFCFS_EmptyReturnsError(t *testing.T) {
	p := &allocation.FCFS{}
	_, err := p.Select(nil)
	if err != allocation.ErrNoCandidates {
		t.Errorf("expected ErrNoCandidates, got %v", err)
	}
}

func TestRoundRobin_Cycles(t *testing.T) {
	p := allocation.NewRoundRobin()
	c := candidates("a", "b", "c")

	expected := []string{"a", "b", "c", "a", "b", "c"}
	for i, want := range expected {
		got, err := p.Select(c)
		if err != nil {
			t.Fatal(err)
		}
		if got.ID != want {
			t.Errorf("call %d: expected %s, got %s", i, want, got.ID)
		}
	}
}

func TestRoundRobin_EmptyReturnsError(t *testing.T) {
	p := allocation.NewRoundRobin()
	_, err := p.Select(nil)
	if err != allocation.ErrNoCandidates {
		t.Errorf("expected ErrNoCandidates, got %v", err)
	}
}

func TestRandom_SelectsFromCandidates(t *testing.T) {
	p := &allocation.Random{}
	c := candidates("a", "b", "c")

	// Run enough times to verify it doesn't panic and returns valid candidates.
	seen := map[string]bool{}
	for range 100 {
		got, err := p.Select(c)
		if err != nil {
			t.Fatal(err)
		}
		seen[got.ID] = true
	}
	// With 100 tries and 3 candidates, we should see at least 2.
	if len(seen) < 2 {
		t.Errorf("random policy only selected %d unique candidates in 100 tries", len(seen))
	}
}

func TestRandom_EmptyReturnsError(t *testing.T) {
	p := &allocation.Random{}
	_, err := p.Select(nil)
	if err != allocation.ErrNoCandidates {
		t.Errorf("expected ErrNoCandidates, got %v", err)
	}
}

func TestNew_KnownPolicies(t *testing.T) {
	tests := []struct {
		name     string
		wantName string
	}{
		{"fcfs", "fcfs"},
		{"", "fcfs"},
		{"round_robin", "round_robin"},
		{"random", "random"},
	}
	for _, tt := range tests {
		p, err := allocation.New(tt.name)
		if err != nil {
			t.Errorf("New(%q): %v", tt.name, err)
			continue
		}
		if p.Name() != tt.wantName {
			t.Errorf("New(%q).Name() = %q, want %q", tt.name, p.Name(), tt.wantName)
		}
	}
}

func TestNew_UnknownPolicy(t *testing.T) {
	_, err := allocation.New("does_not_exist")
	if err == nil {
		t.Error("expected error for unknown policy")
	}
}