Skip to content

Commit

Permalink
failover: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jwijenbergh committed Aug 27, 2024
1 parent c20b1f7 commit 26d2b81
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 2 deletions.
14 changes: 12 additions & 2 deletions internal/failover/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import (
"github.com/eduvpn/eduvpn-common/internal/log"
)

type sender interface {
Read(deadline time.Time) error
Send(wq int) error
}

// The DroppedConMon is a connection monitor that checks for an increase in rx bytes in certain intervals
type DroppedConMon struct {
// pInterval means how the interval in which to send pings
Expand All @@ -17,14 +22,19 @@ type DroppedConMon struct {
// The function that reads Rx bytes
// If this function returns an error, the monitor exits
readRxBytes func() (int64, error)
// newPinger creates a new pinger
// This gets used in the tests to mock the Ping sender interface
newPinger func(gateway string, mtu int) (sender, error)
}

// NewDroppedMonitor creates a new failover monitor
// `pingInterval` is the interval in which to send pings
// `pDropped` is how many pings we need to send before we deem it is dropped
// `readRxBytes` is a function that gets the rx bytes from the client
func NewDroppedMonitor(pingInterval time.Duration, pDropped int, readRxBytes func() (int64, error)) *DroppedConMon {
return &DroppedConMon{pInterval: pingInterval, pDropped: pDropped, readRxBytes: readRxBytes}
return &DroppedConMon{pInterval: pingInterval, pDropped: pDropped, readRxBytes: readRxBytes, newPinger: func(gateway string, mtu int) (sender, error) {
return NewPinger(gateway, mtu)
}}
}

// Dropped checks whether or not the connection is 'dropped'
Expand All @@ -47,7 +57,7 @@ func (m *DroppedConMon) Start(ctx context.Context, gateway string, mtuSize int)
}

// Create a ping struct with our mtu size
p, err := NewPinger(gateway, mtuSize)
p, err := m.newPinger(gateway, mtuSize)
if err != nil {
return false, err
}
Expand Down
106 changes: 106 additions & 0 deletions internal/failover/monitor_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package failover

import (
"context"
"errors"
"io"
"testing"
"time"

"github.com/eduvpn/eduvpn-common/internal/test"
)

// mockedPinger is a ping sender that always returns nil for sending
// but returns EOF for reading
type mockedPinger struct{}

func (mp *mockedPinger) Read(_ time.Time) error {
return io.EOF
}

func (mp *mockedPinger) Send(_ int) error {
return nil
}

func TestMonitor(t *testing.T) {
cases := []struct {
interval time.Duration
pDropped int
readRxBytes func() (int64, error)
gateway string
mtuSize int
disableDefaults bool
mockedPinger func(gateway string, mtu int) (sender, error)
wantDropped bool
wantErr string
}{
{
mtuSize: 1,
wantDropped: false,
wantErr: "invalid MTU size given, MTU has to be at least: 28 bytes",
},
{
readRxBytes: func() (int64, error) {
return 0, errors.New("error test")
},
wantDropped: false,
wantErr: "error test",
},
// default case, not dropped
{},
// readRxBytes always returns 0
// still we do not want a drop because we get a pong from 127.0.0.1
{
readRxBytes: func() (int64, error) {
return 0, nil
},
wantDropped: false,
},
// readRxBytes always returns 0
// we want dropped as the mock pinger does nothing
{
readRxBytes: func() (int64, error) {
return 0, nil
},
gateway: "127.0.0.1",
mockedPinger: func(_ string, _ int) (sender, error) {
return &mockedPinger{}, nil
},
wantDropped: true,
},
}

for _, c := range cases {
var counter int64
// some defaults
if c.interval == 0 {
c.interval = 2 * time.Second
}
if c.pDropped == 0 {
c.pDropped = 5
}
if c.gateway == "" {
c.gateway = "127.0.0.1"
}
if c.mtuSize == 0 {
c.mtuSize = 28
}
if c.readRxBytes == nil {
c.readRxBytes = func() (int64, error) {
defer func() {
counter++
}()
return counter, nil
}
}
dcm := NewDroppedMonitor(c.interval, c.pDropped, c.readRxBytes)
if c.mockedPinger != nil {
dcm.newPinger = c.mockedPinger
}
dropped, err := dcm.Start(context.Background(), c.gateway, c.mtuSize)
if dropped != c.wantDropped {
t.Fatalf("dropped is not equal to want dropped, got: %v, want: %v", dropped, c.wantDropped)
}
test.AssertError(t, err, c.wantErr)
}
}

0 comments on commit 26d2b81

Please sign in to comment.