Некоторые проверки не удались
CI / test (push) Successful in 2m5s
Docker / Build and publish worker image (push) Failing after 31s
160 строки
4.1 KiB
Go
160 строки
4.1 KiB
Go
package cping
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"gorm.io/datatypes"
|
|
|
|
"rocketgit.ru/rsmon/worker/app/models"
|
|
)
|
|
|
|
// settings mirrors models.CheckSettings so the test can build a
|
|
// CheckSettings JSON without pulling in the entire model package.
|
|
type settings struct {
|
|
Host string `json:"host,omitempty"`
|
|
Count int `json:"count,omitempty"`
|
|
Timeout int `json:"timeout,omitempty"`
|
|
PacketSize int `json:"packet_size,omitempty"`
|
|
Port string `json:"port,omitempty"`
|
|
}
|
|
|
|
func newCheck(t *testing.T, s settings, host string) *models.Check {
|
|
t.Helper()
|
|
raw, err := json.Marshal(s)
|
|
if err != nil {
|
|
t.Fatalf("marshal settings: %v", err)
|
|
}
|
|
if host == "" {
|
|
host = "127.0.0.1"
|
|
}
|
|
return &models.Check{
|
|
Kind: "ping",
|
|
Monitor: &models.Monitor{Host: host},
|
|
Settings: datatypes.JSON(raw),
|
|
}
|
|
}
|
|
|
|
// fakePinger returns canned stats without touching the network so the
|
|
// state machine in Perform() can be exercised in CI environments
|
|
// without CAP_NET_RAW.
|
|
type fakePinger struct {
|
|
stats Stats
|
|
}
|
|
|
|
func (f *fakePinger) Run(host string, count int, timeout time.Duration, payloadSize int) Stats {
|
|
return f.stats
|
|
}
|
|
|
|
func TestPerformOK(t *testing.T) {
|
|
SetPinger(&fakePinger{stats: Stats{PacketsSent: 3, PacketsRecv: 3, AvgRtt: 4 * time.Millisecond}})
|
|
defer SetPinger(&realPinger{})
|
|
|
|
c := newCheck(t, settings{Count: 3}, "")
|
|
r := Perform(c)
|
|
if r.State != stateOK {
|
|
t.Fatalf("expected OK, got %s (err=%v)", r.State, r.Error)
|
|
}
|
|
if r.PacketsSent != 3 || r.PacketsRecv != 3 {
|
|
t.Fatalf("packet counts wrong: sent=%d recv=%d", r.PacketsSent, r.PacketsRecv)
|
|
}
|
|
if r.AvgRttMs < 1 {
|
|
t.Fatalf("expected RTT > 0, got %v", r.AvgRttMs)
|
|
}
|
|
if len(r.Infos) == 0 || !strings.Contains(r.Infos[0], "rtt=") {
|
|
t.Fatalf("expected rtt info line, got %v", r.Infos)
|
|
}
|
|
}
|
|
|
|
func TestPerformNoReply(t *testing.T) {
|
|
SetPinger(&fakePinger{stats: Stats{PacketsSent: 3, PacketsRecv: 0, Err: errors.New("i/o timeout")}})
|
|
defer SetPinger(&realPinger{})
|
|
|
|
c := newCheck(t, settings{}, "")
|
|
r := Perform(c)
|
|
if r.State != stateERR {
|
|
t.Fatalf("expected ERR, got %s", r.State)
|
|
}
|
|
if r.PacketsSent == 0 {
|
|
t.Fatalf("expected PacketsSent to be incremented even on failure")
|
|
}
|
|
if r.Error == nil {
|
|
t.Fatalf("expected error, got nil")
|
|
}
|
|
}
|
|
|
|
func TestPerformUnsupported(t *testing.T) {
|
|
SetPinger(&fakePinger{stats: Stats{Err: errors.New("socket: operation not permitted (cap_net_raw)")}})
|
|
defer SetPinger(&realPinger{})
|
|
|
|
c := newCheck(t, settings{}, "")
|
|
r := Perform(c)
|
|
if r.State != stateFail {
|
|
t.Fatalf("expected FAIL when raw ICMP is not allowed, got %s", r.State)
|
|
}
|
|
}
|
|
|
|
func TestPerformEmptyHost(t *testing.T) {
|
|
c := &models.Check{
|
|
Kind: "ping",
|
|
Monitor: &models.Monitor{Host: ""},
|
|
Settings: datatypes.JSON("{}"),
|
|
}
|
|
r := Perform(c)
|
|
if r.State != stateFail {
|
|
t.Fatalf("expected FAIL on empty host, got %s", r.State)
|
|
}
|
|
}
|
|
|
|
func TestIsUnsupported(t *testing.T) {
|
|
cases := []struct {
|
|
err error
|
|
want bool
|
|
}{
|
|
{err: nil, want: false},
|
|
{err: errors.New(""), want: false},
|
|
{err: errors.New("permission denied"), want: true},
|
|
{err: errors.New("icmp listen: cap_net_raw required"), want: true},
|
|
{err: errors.New("i/o timeout"), want: false},
|
|
{err: errors.New("no route to host"), want: false},
|
|
}
|
|
for _, tc := range cases {
|
|
if got := isUnsupported(tc.err); got != tc.want {
|
|
t.Errorf("isUnsupported(%q) = %v, want %v", tc.err, got, tc.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLossPercent(t *testing.T) {
|
|
cases := []struct {
|
|
sent, recv int
|
|
want int64
|
|
}{
|
|
{sent: 0, recv: 0, want: 0},
|
|
{sent: 5, recv: 5, want: 0},
|
|
{sent: 5, recv: 3, want: 40},
|
|
{sent: 5, recv: 0, want: 100},
|
|
}
|
|
for _, tc := range cases {
|
|
if got := lossPercent(tc.sent, tc.recv); got != tc.want {
|
|
t.Errorf("lossPercent(%d,%d) = %d, want %d", tc.sent, tc.recv, got, tc.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMakeBytes(t *testing.T) {
|
|
if got := makeBytes(0); len(got) != 0 {
|
|
t.Fatalf("expected empty slice, got %d bytes", len(got))
|
|
}
|
|
if got := makeBytes(-1); len(got) != 0 {
|
|
t.Fatalf("expected empty slice for negative size, got %d bytes", len(got))
|
|
}
|
|
got := makeBytes(3)
|
|
if len(got) != 3 || string(got) != "abc" {
|
|
t.Fatalf("expected 'abc', got %q", string(got))
|
|
}
|
|
}
|