package failover import ( "context" "errors" "io" "testing" "time" "codeberg.org/eduVPN/eduvpn-common/internal/test" ) // mockedPinger is a ping sender that always returns nil for sending // but returns EOF for reading type mockedPinger struct { cleanRead bool } func (mp *mockedPinger) Read(_ time.Time) error { if mp.cleanRead { return nil } 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") }, mockedPinger: func(_ string, _ int) (sender, error) { return &mockedPinger{}, nil }, wantDropped: false, wantErr: "error test", }, // default case, not dropped { mockedPinger: func(_ string, _ int) (sender, error) { return &mockedPinger{}, nil }, }, // default case where it could read a ping response, and read rx bytes always returns 0 // should be not dropped { readRxBytes: func() (int64, error) { return 0, nil }, mockedPinger: func(_ string, _ int) (sender, error) { return &mockedPinger{cleanRead: true}, nil }, }, // 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.Millisecond } 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) } }