package agent
|
|
import (
|
"bytes"
|
"log"
|
"os"
|
"testing"
|
"time"
|
|
"basic.com/valib/serf.git/client"
|
"basic.com/valib/serf.git/testutil"
|
"github.com/mitchellh/cli"
|
)
|
|
func TestCommandRun(t *testing.T) {
|
shutdownCh := make(chan struct{})
|
defer close(shutdownCh)
|
|
ui := new(cli.MockUi)
|
c := &Command{
|
ShutdownCh: shutdownCh,
|
Ui: ui,
|
}
|
|
ip1, returnFn1 := testutil.TakeIP()
|
defer returnFn1()
|
|
ip2, returnFn2 := testutil.TakeIP()
|
defer returnFn2()
|
|
rpcAddr := ip2.String() + ":11111"
|
|
args := []string{
|
"-bind", ip1.String(),
|
"-rpc-addr", rpcAddr,
|
}
|
|
resultCh := make(chan int)
|
go func() {
|
resultCh <- c.Run(args)
|
}()
|
|
testutil.Yield()
|
|
// Verify it runs "forever"
|
select {
|
case <-resultCh:
|
t.Fatalf("ended too soon, err: %v", ui.ErrorWriter.String())
|
case <-time.After(50 * time.Millisecond):
|
}
|
|
// Send a shutdown request
|
shutdownCh <- struct{}{}
|
|
select {
|
case code := <-resultCh:
|
if code != 0 {
|
t.Fatalf("bad code: %d", code)
|
}
|
case <-time.After(2 * time.Second):
|
t.Fatalf("timeout")
|
}
|
}
|
|
func TestCommandRun_rpc(t *testing.T) {
|
doneCh := make(chan struct{})
|
shutdownCh := make(chan struct{})
|
defer func() {
|
close(shutdownCh)
|
<-doneCh
|
}()
|
|
c := &Command{
|
ShutdownCh: shutdownCh,
|
Ui: new(cli.MockUi),
|
}
|
|
ip1, returnFn1 := testutil.TakeIP()
|
defer returnFn1()
|
|
ip2, returnFn2 := testutil.TakeIP()
|
defer returnFn2()
|
|
rpcAddr := ip2.String() + ":11111"
|
|
args := []string{
|
"-bind", ip1.String(),
|
"-rpc-addr", rpcAddr,
|
}
|
|
go func() {
|
code := c.Run(args)
|
if code != 0 {
|
log.Printf("bad: %d", code)
|
}
|
|
close(doneCh)
|
}()
|
|
testutil.Yield()
|
|
client, err := client.NewRPCClient(rpcAddr)
|
if err != nil {
|
t.Fatalf("err: %v", err)
|
}
|
defer client.Close()
|
|
members, err := client.Members()
|
if err != nil {
|
t.Fatalf("err: %v", err)
|
}
|
|
if len(members) != 1 {
|
t.Fatalf("bad: %#v", members)
|
}
|
}
|
|
func TestCommandRun_join(t *testing.T) {
|
ip1, returnFn1 := testutil.TakeIP()
|
defer returnFn1()
|
|
ip2, returnFn2 := testutil.TakeIP()
|
defer returnFn2()
|
|
a1 := testAgent(t, ip1, nil)
|
if err := a1.Start(); err != nil {
|
t.Fatalf("err: %v", err)
|
}
|
defer a1.Shutdown()
|
|
doneCh := make(chan struct{})
|
shutdownCh := make(chan struct{})
|
defer func() {
|
close(shutdownCh)
|
<-doneCh
|
}()
|
|
c := &Command{
|
ShutdownCh: shutdownCh,
|
Ui: new(cli.MockUi),
|
}
|
|
args := []string{
|
"-bind", ip2.String(),
|
"-join", a1.conf.MemberlistConfig.BindAddr,
|
"-replay",
|
}
|
|
go func() {
|
code := c.Run(args)
|
if code != 0 {
|
log.Printf("bad: %d", code)
|
}
|
|
close(doneCh)
|
}()
|
|
testutil.Yield()
|
|
if len(a1.Serf().Members()) != 2 {
|
t.Fatalf("bad: %#v", a1.Serf().Members())
|
}
|
}
|
|
func TestCommandRun_joinFail(t *testing.T) {
|
ip1, returnFn1 := testutil.TakeIP()
|
defer returnFn1()
|
|
ip2, returnFn2 := testutil.TakeIP()
|
defer returnFn2()
|
|
shutdownCh := make(chan struct{})
|
defer close(shutdownCh)
|
|
c := &Command{
|
ShutdownCh: shutdownCh,
|
Ui: new(cli.MockUi),
|
}
|
|
args := []string{
|
"-bind", ip1.String(),
|
"-join", ip2.String(),
|
}
|
|
code := c.Run(args)
|
if code == 0 {
|
t.Fatal("should fail")
|
}
|
}
|
|
func TestCommandRun_advertiseAddr(t *testing.T) {
|
doneCh := make(chan struct{})
|
shutdownCh := make(chan struct{})
|
defer func() {
|
close(shutdownCh)
|
<-doneCh
|
}()
|
|
c := &Command{
|
ShutdownCh: shutdownCh,
|
Ui: new(cli.MockUi),
|
}
|
|
ip1, returnFn1 := testutil.TakeIP()
|
defer returnFn1()
|
|
ip2, returnFn2 := testutil.TakeIP()
|
defer returnFn2()
|
|
rpcAddr := ip2.String() + ":11111"
|
args := []string{
|
"-bind", ip1.String(),
|
"-rpc-addr", rpcAddr,
|
"-advertise", "127.0.0.10:12345",
|
}
|
|
go func() {
|
code := c.Run(args)
|
if code != 0 {
|
log.Printf("bad: %d", code)
|
}
|
|
close(doneCh)
|
}()
|
|
testutil.Yield()
|
|
client, err := client.NewRPCClient(rpcAddr)
|
if err != nil {
|
t.Fatalf("err: %v", err)
|
}
|
defer client.Close()
|
|
members, err := client.Members()
|
if err != nil {
|
t.Fatalf("err: %v", err)
|
}
|
|
if len(members) != 1 {
|
t.Fatalf("bad: %#v", members)
|
}
|
|
// Check the addr and port is as advertised!
|
m := members[0]
|
if bytes.Compare(m.Addr, []byte{127, 0, 0, 10}) != 0 {
|
t.Fatalf("bad: %#v", m)
|
}
|
if m.Port != 12345 {
|
t.Fatalf("bad: %#v", m)
|
}
|
}
|
|
func TestCommandRun_mDNS(t *testing.T) {
|
// mDNS does not work in travis
|
if os.Getenv("TRAVIS") != "" {
|
t.SkipNow()
|
}
|
|
// Start an agent
|
doneCh := make(chan struct{})
|
shutdownCh := make(chan struct{})
|
defer func() {
|
close(shutdownCh)
|
<-doneCh
|
}()
|
|
c := &Command{
|
ShutdownCh: shutdownCh,
|
Ui: new(cli.MockUi),
|
}
|
|
ip1, returnFn1 := testutil.TakeIP()
|
defer returnFn1()
|
|
ip2, returnFn2 := testutil.TakeIP()
|
defer returnFn2()
|
|
ip3, returnFn3 := testutil.TakeIP()
|
defer returnFn3()
|
|
ip4, returnFn4 := testutil.TakeIP()
|
defer returnFn4()
|
|
rpcAddr1 := ip2.String() + ":11111"
|
rpcAddr2 := ip4.String() + ":11111"
|
|
args := []string{
|
"-node", "foo",
|
"-bind", ip1.String(),
|
"-discover", "test",
|
"-rpc-addr", rpcAddr1,
|
}
|
|
go func() {
|
code := c.Run(args)
|
if code != 0 {
|
log.Printf("bad: %d", code)
|
}
|
close(doneCh)
|
}()
|
|
// Start a second agent
|
doneCh2 := make(chan struct{})
|
shutdownCh2 := make(chan struct{})
|
defer func() {
|
close(shutdownCh2)
|
<-doneCh2
|
}()
|
|
c2 := &Command{
|
ShutdownCh: shutdownCh2,
|
Ui: new(cli.MockUi),
|
}
|
|
args2 := []string{
|
"-node", "bar",
|
"-bind", ip3.String(),
|
"-discover", "test",
|
"-rpc-addr", rpcAddr2,
|
}
|
|
go func() {
|
code := c2.Run(args2)
|
if code != 0 {
|
log.Printf("bad: %d", code)
|
}
|
close(doneCh2)
|
}()
|
|
time.Sleep(150 * time.Millisecond)
|
|
client, err := client.NewRPCClient(rpcAddr2)
|
if err != nil {
|
t.Fatalf("err: %v", err)
|
}
|
defer client.Close()
|
|
members, err := client.Members()
|
if err != nil {
|
t.Fatalf("err: %v", err)
|
}
|
|
if len(members) != 2 {
|
t.Fatalf("bad: %#v", members)
|
}
|
}
|
|
func TestCommandRun_retry_join(t *testing.T) {
|
ip1, returnFn1 := testutil.TakeIP()
|
defer returnFn1()
|
|
ip2, returnFn2 := testutil.TakeIP()
|
defer returnFn2()
|
|
a1 := testAgent(t, ip1, nil)
|
if err := a1.Start(); err != nil {
|
t.Fatalf("err: %v", err)
|
}
|
defer a1.Shutdown()
|
|
doneCh := make(chan struct{})
|
shutdownCh := make(chan struct{})
|
defer func() {
|
close(shutdownCh)
|
<-doneCh
|
}()
|
|
c := &Command{
|
ShutdownCh: shutdownCh,
|
Ui: new(cli.MockUi),
|
}
|
|
args := []string{
|
"-bind", ip2.String(),
|
"-retry-join", a1.conf.MemberlistConfig.BindAddr,
|
"-replay",
|
}
|
|
go func() {
|
code := c.Run(args)
|
if code != 0 {
|
log.Printf("bad: %d", code)
|
}
|
|
close(doneCh)
|
}()
|
|
testutil.Yield()
|
|
if len(a1.Serf().Members()) != 2 {
|
t.Fatalf("bad: %#v", a1.Serf().Members())
|
}
|
}
|
|
func TestCommandRun_retry_joinFail(t *testing.T) {
|
shutdownCh := make(chan struct{})
|
defer close(shutdownCh)
|
|
c := &Command{
|
ShutdownCh: shutdownCh,
|
Ui: new(cli.MockUi),
|
}
|
|
ip1, returnFn1 := testutil.TakeIP()
|
defer returnFn1()
|
|
ip2, returnFn2 := testutil.TakeIP()
|
defer returnFn2()
|
|
args := []string{
|
"-bind", ip1.String(),
|
"-retry-join", ip2.String(),
|
"-retry-interval", "1s",
|
"-retry-max", "1",
|
}
|
|
code := c.Run(args)
|
if code == 0 {
|
t.Fatal("should fail")
|
}
|
}
|