Add TestSystem

This commit is contained in:
Ian Gulliver
2023-06-04 10:43:32 -07:00
parent 0b9c2543e4
commit bce6488620
3 changed files with 61 additions and 27 deletions

View File

@@ -1,32 +1,17 @@
package elect_test package elect_test
import ( import (
"fmt"
"testing" "testing"
"time" "time"
"github.com/dchest/uniuri"
"github.com/gopatchy/elect"
"github.com/gopatchy/proxy"
"github.com/samber/lo"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestSimple(t *testing.T) { func TestOne(t *testing.T) {
t.Parallel() t.Parallel()
signingKey := uniuri.New() ts := NewTestSystem(t, 1)
ts := NewTestServer(t, signingKey)
defer ts.Stop() defer ts.Stop()
p := lo.Must(proxy.NewProxy(t, ts.Addr())) require.Eventually(t, ts.Candidate(0).IsLeader, 15*time.Second, 100*time.Millisecond)
defer p.Close()
url := fmt.Sprintf("http://%s/", p.Addr())
v := elect.NewVoter(url, signingKey)
defer v.Stop()
require.Eventually(t, ts.Candidate.IsLeader, 15*time.Second, 100*time.Millisecond)
} }

View File

@@ -1,12 +1,15 @@
package elect_test package elect_test
import ( import (
"fmt"
"net" "net"
"net/http" "net/http"
"testing" "testing"
"time" "time"
"github.com/dchest/uniuri"
"github.com/gopatchy/elect" "github.com/gopatchy/elect"
"github.com/gopatchy/proxy"
"github.com/samber/lo" "github.com/samber/lo"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@@ -18,6 +21,13 @@ type TestServer struct {
srv *http.Server srv *http.Server
} }
type TestSystem struct {
signingKey string
servers []*TestServer
voters []*elect.Voter
proxy *proxy.Proxy
}
func NewTestServer(t *testing.T, signingKey string) *TestServer { func NewTestServer(t *testing.T, signingKey string) *TestServer {
ts := &TestServer{ ts := &TestServer{
Candidate: elect.NewCandidate(1, signingKey), Candidate: elect.NewCandidate(1, signingKey),
@@ -45,3 +55,47 @@ func (ts *TestServer) Stop() {
func (ts *TestServer) Addr() *net.TCPAddr { func (ts *TestServer) Addr() *net.TCPAddr {
return ts.listener.Addr().(*net.TCPAddr) return ts.listener.Addr().(*net.TCPAddr)
} }
func NewTestSystem(t *testing.T, num int) *TestSystem {
ts := &TestSystem{
signingKey: uniuri.New(),
}
for i := 0; i < num; i++ {
ts.servers = append(ts.servers, NewTestServer(t, ts.signingKey))
}
ts.proxy = lo.Must(proxy.NewProxy(t, ts.Server(0).Addr()))
url := fmt.Sprintf("http://%s/", ts.proxy.Addr())
for i := 0; i < num; i++ {
ts.voters = append(ts.voters, elect.NewVoter(url, ts.signingKey, ts.Candidate(i)))
}
return ts
}
func (ts *TestSystem) Stop() {
for _, s := range ts.servers {
s.Stop()
}
for _, v := range ts.voters {
v.Stop()
}
ts.proxy.Close()
}
func (ts *TestSystem) Server(i int) *TestServer {
return ts.servers[i]
}
func (ts *TestSystem) Candidate(i int) *elect.Candidate {
return ts.servers[i].Candidate
}
func (ts *TestSystem) Voter(i int) *elect.Voter {
return ts.voters[i]
}

View File

@@ -20,8 +20,8 @@ type Voter struct {
// used by loop() goroutine only // used by loop() goroutine only
client *resty.Client client *resty.Client
signingKey []byte signingKey []byte
candidate *Candidate
vote vote vote vote
candidates []*Candidate
period time.Duration period time.Duration
} }
@@ -40,12 +40,13 @@ type voteResponse struct {
ResponseSent time.Time `json:"responseSent"` ResponseSent time.Time `json:"responseSent"`
} }
func NewVoter(url string, signingKey string) *Voter { func NewVoter(url string, signingKey string, candidate *Candidate) *Voter {
v := &Voter{ v := &Voter{
client: resty.New(). client: resty.New().
SetCloseConnection(true). SetCloseConnection(true).
SetBaseURL(url), SetBaseURL(url),
signingKey: []byte(signingKey), signingKey: []byte(signingKey),
candidate: candidate,
update: make(chan time.Duration), update: make(chan time.Duration),
done: make(chan bool), done: make(chan bool),
vote: vote{ vote: vote{
@@ -64,10 +65,6 @@ func (v *Voter) Stop() {
<-v.done <-v.done
} }
func (v *Voter) AddCandidate(c *Candidate) {
v.candidates = append(v.candidates, c)
}
func (v *Voter) loop() { func (v *Voter) loop() {
defer close(v.done) defer close(v.done)
@@ -111,9 +108,7 @@ func (v *Voter) poll() bool {
func (v *Voter) sendVote() { func (v *Voter) sendVote() {
v.vote.VoteSent = time.Now().UTC() v.vote.VoteSent = time.Now().UTC()
for _, c := range v.candidates { v.candidate.voteIfNo(&v.vote)
c.voteIfNo(&v.vote)
}
js := lo.Must(json.Marshal(v.vote)) js := lo.Must(json.Marshal(v.vote))