84 lines
3.3 KiB
Go
84 lines
3.3 KiB
Go
package choose_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.wntrmute.dev/kyle/crossbar/internal/choose"
|
|
)
|
|
|
|
func infoFor(m map[string]choose.Info) func(string) (choose.Info, bool) {
|
|
return func(name string) (choose.Info, bool) { i, ok := m[name]; return i, ok }
|
|
}
|
|
|
|
func TestMostFreeSlotsTimesWeightWins(t *testing.T) {
|
|
info := infoFor(map[string]choose.Info{
|
|
"alpha": {Healthy: true, Loaded: true, CanServe: true, Free: 3, Weight: 1.0},
|
|
"beta": {Healthy: true, Loaded: true, CanServe: true, Free: 2, Weight: 2.0}, // 4 > 3
|
|
"gamma": {Healthy: true, Loaded: true, CanServe: true, Free: 4, Weight: 0.5}, // 2
|
|
})
|
|
got, ok := choose.Best([]string{"alpha", "beta", "gamma"}, info)
|
|
if !ok || got != "beta" {
|
|
t.Errorf("got %q %v, want beta", got, ok)
|
|
}
|
|
}
|
|
|
|
func TestTieGoesToShortestQueueThenListOrder(t *testing.T) {
|
|
info := infoFor(map[string]choose.Info{
|
|
"alpha": {Healthy: true, Loaded: true, CanServe: true, Free: 2, Weight: 1, Queued: 3},
|
|
"beta": {Healthy: true, Loaded: true, CanServe: true, Free: 2, Weight: 1, Queued: 1},
|
|
"gamma": {Healthy: true, Loaded: true, CanServe: true, Free: 2, Weight: 1, Queued: 1},
|
|
})
|
|
if got, _ := choose.Best([]string{"alpha", "beta", "gamma"}, info); got != "beta" {
|
|
t.Errorf("tie on score: shortest queue wins, then list order; got %q", got)
|
|
}
|
|
if got, _ := choose.Best([]string{"gamma", "beta"}, info); got != "gamma" {
|
|
t.Errorf("full tie: first in list order wins; got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestLoadedBeatsMerelyCapable(t *testing.T) {
|
|
info := infoFor(map[string]choose.Info{
|
|
"alpha": {Healthy: true, Loaded: false, CanServe: true, Free: 8, Weight: 4},
|
|
"beta": {Healthy: true, Loaded: true, CanServe: true, Free: 1, Weight: 1},
|
|
})
|
|
got, ok := choose.Best([]string{"alpha", "beta"}, info)
|
|
if !ok || got != "beta" {
|
|
t.Errorf("a host that has the model loaded wins over one that would have to load it; got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestFallsBackToCapableHost(t *testing.T) {
|
|
info := infoFor(map[string]choose.Info{
|
|
"alpha": {Healthy: true, Loaded: false, CanServe: true, Free: 1, Weight: 1},
|
|
"beta": {Healthy: true, Loaded: false, CanServe: false, Free: 9, Weight: 9},
|
|
})
|
|
got, ok := choose.Best([]string{"beta", "alpha"}, info)
|
|
if !ok || got != "alpha" {
|
|
t.Errorf("only a host configured to serve the model may load it; got %q %v", got, ok)
|
|
}
|
|
}
|
|
|
|
func TestSkipsUnhealthyDrainingUnknownAndFull(t *testing.T) {
|
|
info := infoFor(map[string]choose.Info{
|
|
"down": {Healthy: false, Loaded: true, CanServe: true, Free: 9, Weight: 9},
|
|
"drain": {Healthy: true, Draining: true, Loaded: true, CanServe: true, Free: 9, Weight: 9},
|
|
"full": {Healthy: true, Loaded: true, CanServe: true, Free: 0, Weight: 9, Queued: 0},
|
|
"ok": {Healthy: true, Loaded: true, CanServe: true, Free: 1, Weight: 1},
|
|
})
|
|
got, ok := choose.Best([]string{"down", "drain", "missing", "full", "ok"}, info)
|
|
if !ok || got != "ok" {
|
|
t.Errorf("got %q %v, want ok", got, ok)
|
|
}
|
|
// A full host is still better than nothing: it gets the request (it will queue).
|
|
got, ok = choose.Best([]string{"down", "full"}, info)
|
|
if !ok || got != "full" {
|
|
t.Errorf("with only a full host left it must still be chosen; got %q %v", got, ok)
|
|
}
|
|
if _, ok := choose.Best([]string{"down", "drain", "missing"}, info); ok {
|
|
t.Errorf("nothing usable must give ok=false")
|
|
}
|
|
if _, ok := choose.Best(nil, info); ok {
|
|
t.Errorf("empty candidates must give ok=false")
|
|
}
|
|
}
|