-
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathproxyHandler_test.go
More file actions
135 lines (123 loc) · 3.39 KB
/
proxyHandler_test.go
File metadata and controls
135 lines (123 loc) · 3.39 KB
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package main
import (
"database/sql"
"errors"
"net/http"
"net/http/httputil"
"testing"
"github.com/ether/etherpad-proxy/models"
"go.uber.org/zap"
)
type fakeDB struct {
pads map[string]string
clashes map[string][]string
assignCalls int
}
func newFakeDB() *fakeDB {
return &fakeDB{pads: map[string]string{}, clashes: map[string][]string{}}
}
func (f *fakeDB) Close() error { return nil }
func (f *fakeDB) Get(id string) (*models.DBBackend, error) {
if b, ok := f.pads[id]; ok {
return &models.DBBackend{Backend: b}, nil
}
return nil, sql.ErrNoRows
}
func (f *fakeDB) CleanUpPads(_ []string, _ string) error { return nil }
func (f *fakeDB) RecordClash(id string, data string) error {
f.clashes[id] = append(f.clashes[id], data)
return nil
}
func (f *fakeDB) Set(id string, backend models.DBBackend) error {
f.pads[id] = backend.Backend
return nil
}
func (f *fakeDB) GetAllPads() (map[string]string, error) { return f.pads, nil }
func (f *fakeDB) GetClashByPadID(id string) ([]string, error) {
return f.clashes[id], nil
}
func (f *fakeDB) Assign(id string, candidate string) (string, error) {
f.assignCalls++
if b, ok := f.pads[id]; ok {
return b, nil
}
f.pads[id] = candidate
return candidate, nil
}
func newTestHandler(db *fakeDB, available, up []string) *ProxyHandler {
state := &models.BackendState{}
state.SetState(available, up)
return &ProxyHandler{
p: map[string]httputil.ReverseProxy{},
logger: zap.NewNop().Sugar(),
db: db,
state: state,
static: newStaticResources(),
}
}
func mustReq(path string) *http.Request {
r, _ := http.NewRequest("GET", path, nil)
return r
}
func TestChooseBackendNoBackends(t *testing.T) {
h := newTestHandler(newFakeDB(), nil, nil)
pad := "pad1"
if _, err := h.chooseBackend(&pad, mustReq("/p/pad1")); err == nil {
t.Fatal("expected error when no backends available")
}
}
func TestChooseBackendAssignsNewPad(t *testing.T) {
db := newFakeDB()
h := newTestHandler(db, []string{"b1"}, []string{"b1"})
pad := "pad1"
got, err := h.chooseBackend(&pad, mustReq("/p/pad1"))
if err != nil {
t.Fatalf("chooseBackend: %v", err)
}
if got != "b1" {
t.Fatalf("expected b1, got %s", got)
}
if db.assignCalls != 1 {
t.Fatalf("expected Assign called once, got %d", db.assignCalls)
}
}
func TestChooseBackendUsesStoredWhenUp(t *testing.T) {
db := newFakeDB()
db.pads["pad1"] = "b2"
h := newTestHandler(db, []string{"b1"}, []string{"b1", "b2"})
pad := "pad1"
got, err := h.chooseBackend(&pad, mustReq("/p/pad1"))
if err != nil {
t.Fatalf("chooseBackend: %v", err)
}
if got != "b2" {
t.Fatalf("expected stored backend b2, got %s", got)
}
}
func TestChooseBackendReassignsWhenStoredDown(t *testing.T) {
db := newFakeDB()
db.pads["pad1"] = "down"
h := newTestHandler(db, []string{"b1"}, []string{"b1"})
pad := "pad1"
got, err := h.chooseBackend(&pad, mustReq("/p/pad1"))
if err != nil {
t.Fatalf("chooseBackend: %v", err)
}
if got != "b1" {
t.Fatalf("expected reassign to b1, got %s", got)
}
if db.pads["pad1"] != "b1" {
t.Fatalf("expected DB updated to b1, got %s", db.pads["pad1"])
}
}
func TestChooseBackendClash(t *testing.T) {
db := newFakeDB()
db.clashes["pad1"] = []string{"b1", "b2"}
h := newTestHandler(db, []string{"b1"}, []string{"b1"})
pad := "pad1"
_, err := h.chooseBackend(&pad, mustReq("/p/pad1"))
var clash *ClashInPadId
if !errors.As(err, &clash) {
t.Fatalf("expected ClashInPadId, got %v", err)
}
}