mirror of
https://github.com/status-im/consul.git
synced 2025-02-25 11:55:41 +00:00
Peer replication is intended to be between separate Consul installs and effectively should be considered "external". This PR moves the peer stream replication bidirectional RPC endpoint to the external gRPC server and ensures that things continue to function.
165 lines
3.4 KiB
Go
165 lines
3.4 KiB
Go
package peerstream
|
|
|
|
import (
|
|
"sort"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/hashicorp/consul/sdk/testutil"
|
|
)
|
|
|
|
func TestTracker_EnsureConnectedDisconnected(t *testing.T) {
|
|
tracker := NewTracker()
|
|
peerID := "63b60245-c475-426b-b314-4588d210859d"
|
|
|
|
it := incrementalTime{
|
|
base: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC),
|
|
}
|
|
tracker.timeNow = it.Now
|
|
|
|
var (
|
|
statusPtr *MutableStatus
|
|
err error
|
|
)
|
|
|
|
testutil.RunStep(t, "new stream", func(t *testing.T) {
|
|
statusPtr, err = tracker.Connected(peerID)
|
|
require.NoError(t, err)
|
|
|
|
expect := Status{
|
|
Connected: true,
|
|
}
|
|
|
|
status, ok := tracker.StreamStatus(peerID)
|
|
require.True(t, ok)
|
|
require.Equal(t, expect, status)
|
|
})
|
|
|
|
testutil.RunStep(t, "duplicate gets rejected", func(t *testing.T) {
|
|
_, err := tracker.Connected(peerID)
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), `there is an active stream for the given PeerID "63b60245-c475-426b-b314-4588d210859d"`)
|
|
})
|
|
|
|
var sequence uint64
|
|
var lastSuccess time.Time
|
|
|
|
testutil.RunStep(t, "stream updated", func(t *testing.T) {
|
|
statusPtr.TrackAck()
|
|
sequence++
|
|
|
|
status, ok := tracker.StreamStatus(peerID)
|
|
require.True(t, ok)
|
|
|
|
lastSuccess = it.base.Add(time.Duration(sequence) * time.Second).UTC()
|
|
expect := Status{
|
|
Connected: true,
|
|
LastAck: lastSuccess,
|
|
}
|
|
require.Equal(t, expect, status)
|
|
})
|
|
|
|
testutil.RunStep(t, "disconnect", func(t *testing.T) {
|
|
tracker.Disconnected(peerID)
|
|
sequence++
|
|
|
|
expect := Status{
|
|
Connected: false,
|
|
DisconnectTime: it.base.Add(time.Duration(sequence) * time.Second).UTC(),
|
|
LastAck: lastSuccess,
|
|
}
|
|
status, ok := tracker.StreamStatus(peerID)
|
|
require.True(t, ok)
|
|
require.Equal(t, expect, status)
|
|
})
|
|
|
|
testutil.RunStep(t, "re-connect", func(t *testing.T) {
|
|
_, err := tracker.Connected(peerID)
|
|
require.NoError(t, err)
|
|
|
|
expect := Status{
|
|
Connected: true,
|
|
LastAck: lastSuccess,
|
|
|
|
// DisconnectTime gets cleared on re-connect.
|
|
}
|
|
|
|
status, ok := tracker.StreamStatus(peerID)
|
|
require.True(t, ok)
|
|
require.Equal(t, expect, status)
|
|
})
|
|
|
|
testutil.RunStep(t, "delete", func(t *testing.T) {
|
|
tracker.DeleteStatus(peerID)
|
|
|
|
status, ok := tracker.StreamStatus(peerID)
|
|
require.False(t, ok)
|
|
require.Zero(t, status)
|
|
})
|
|
}
|
|
|
|
func TestTracker_connectedStreams(t *testing.T) {
|
|
type testCase struct {
|
|
name string
|
|
setup func(t *testing.T, s *Tracker)
|
|
expect []string
|
|
}
|
|
|
|
run := func(t *testing.T, tc testCase) {
|
|
tracker := NewTracker()
|
|
if tc.setup != nil {
|
|
tc.setup(t, tracker)
|
|
}
|
|
|
|
streams := tracker.ConnectedStreams()
|
|
|
|
var keys []string
|
|
for key := range streams {
|
|
keys = append(keys, key)
|
|
}
|
|
sort.Strings(keys)
|
|
|
|
require.Equal(t, tc.expect, keys)
|
|
}
|
|
|
|
tt := []testCase{
|
|
{
|
|
name: "no streams",
|
|
expect: nil,
|
|
},
|
|
{
|
|
name: "all streams active",
|
|
setup: func(t *testing.T, s *Tracker) {
|
|
_, err := s.Connected("foo")
|
|
require.NoError(t, err)
|
|
|
|
_, err = s.Connected("bar")
|
|
require.NoError(t, err)
|
|
},
|
|
expect: []string{"bar", "foo"},
|
|
},
|
|
{
|
|
name: "mixed active and inactive",
|
|
setup: func(t *testing.T, s *Tracker) {
|
|
status, err := s.Connected("foo")
|
|
require.NoError(t, err)
|
|
|
|
// Mark foo as disconnected to avoid showing it as an active stream
|
|
status.TrackDisconnected()
|
|
|
|
_, err = s.Connected("bar")
|
|
require.NoError(t, err)
|
|
},
|
|
expect: []string{"bar"},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
run(t, tc)
|
|
})
|
|
}
|
|
}
|