Files
worker/checks/cping/ping_test.go
Gleb Tv 2c884c5612
Некоторые проверки не удались
CI / test (push) Successful in 2m5s
Docker / Build and publish worker image (push) Failing after 31s
refactor: adopt worker module path
2026-07-13 17:56:12 +03:00

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))
}
}