Некоторые проверки не удались
CI / test (push) Successful in 2m5s
Docker / Build and publish worker image (push) Failing after 31s
171 строка
4.2 KiB
Go
171 строка
4.2 KiB
Go
package cudp
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"gorm.io/datatypes"
|
|
|
|
"rocketgit.ru/rsmon/worker/app/models"
|
|
)
|
|
|
|
type settings struct {
|
|
Host string `json:"host,omitempty"`
|
|
Port string `json:"port,omitempty"`
|
|
Timeout int `json:"timeout,omitempty"`
|
|
Count int `json:"count,omitempty"`
|
|
PacketSize int `json:"packet_size,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: %v", err)
|
|
}
|
|
return &models.Check{
|
|
Kind: "udp",
|
|
Monitor: &models.Monitor{Host: host},
|
|
Settings: datatypes.JSON(raw),
|
|
}
|
|
}
|
|
|
|
// startEchoUDP brings up a UDP listener on 127.0.0.1:0 that echoes
|
|
// the first byte back to the sender. Returns the listener and the
|
|
// resolved address. Stop it with the returned cleanup.
|
|
func startEchoUDP(t *testing.T) (cleanup func(), addr string) {
|
|
t.Helper()
|
|
conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 0})
|
|
if err != nil {
|
|
t.Fatalf("listen udp: %v", err)
|
|
}
|
|
stop := make(chan struct{})
|
|
var wg sync.WaitGroup
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
buf := make([]byte, 1500)
|
|
for {
|
|
select {
|
|
case <-stop:
|
|
return
|
|
default:
|
|
}
|
|
_ = conn.SetReadDeadline(time.Now().Add(50 * time.Millisecond))
|
|
n, src, err := conn.ReadFromUDP(buf)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if n == 0 {
|
|
continue
|
|
}
|
|
_, _ = conn.WriteToUDP(buf[:1], src)
|
|
}
|
|
}()
|
|
return func() {
|
|
close(stop)
|
|
wg.Wait()
|
|
_ = conn.Close()
|
|
}, conn.LocalAddr().String()
|
|
}
|
|
|
|
func TestPerformOKWhenServerReplies(t *testing.T) {
|
|
cleanup, addr := startEchoUDP(t)
|
|
defer cleanup()
|
|
host, port, err := net.SplitHostPort(addr)
|
|
if err != nil {
|
|
t.Fatalf("split: %v", err)
|
|
}
|
|
c := newCheck(t, settings{Port: port, Timeout: 2}, host)
|
|
r := Perform(c)
|
|
if r.State != stateOK {
|
|
t.Fatalf("expected OK when the server echoes back, got %s (err=%v, warn=%v)", r.State, r.Error, r.Warnings)
|
|
}
|
|
if r.RemoteAddr == "" {
|
|
t.Fatalf("expected RemoteAddr, got %q", r.RemoteAddr)
|
|
}
|
|
}
|
|
|
|
func TestPerformWarnWhenNoReply(t *testing.T) {
|
|
// Open a UDP listener that never replies; the probe should
|
|
// time out and the check should report WARN to signal "reachable,
|
|
// ambiguous service".
|
|
conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 0})
|
|
if err != nil {
|
|
t.Fatalf("listen: %v", err)
|
|
}
|
|
defer conn.Close()
|
|
// Drain the listener so the kernel knows the port is in use but
|
|
// never reply; just close the read side and let the kernel drop
|
|
// incoming datagrams.
|
|
go func() {
|
|
buf := make([]byte, 1500)
|
|
for {
|
|
_, _, _ = conn.ReadFromUDP(buf)
|
|
}
|
|
}()
|
|
|
|
host, port, _ := net.SplitHostPort(conn.LocalAddr().String())
|
|
c := newCheck(t, settings{Port: port, Timeout: 1}, host)
|
|
r := Perform(c)
|
|
if r.State != stateWARN {
|
|
t.Fatalf("expected WARN when the server is silent, got %s (err=%v)", r.State, r.Error)
|
|
}
|
|
if len(r.Warnings) == 0 {
|
|
t.Fatalf("expected a warning describing the silence, got %v", r.Warnings)
|
|
}
|
|
}
|
|
|
|
func TestPerformUnreachable(t *testing.T) {
|
|
c := newCheck(t, settings{Port: "65530", Timeout: 1}, "127.0.0.99")
|
|
r := Perform(c)
|
|
if r.State == stateOK {
|
|
t.Fatalf("expected ERR/WARN, got OK")
|
|
}
|
|
}
|
|
|
|
func TestPerformEmptyHost(t *testing.T) {
|
|
c := newCheck(t, settings{Port: "53", Timeout: 1}, "")
|
|
r := Perform(c)
|
|
if r.State != stateERR {
|
|
t.Fatalf("expected ERR on empty host, got %s", r.State)
|
|
}
|
|
}
|
|
|
|
func TestIsTimeout(t *testing.T) {
|
|
if isTimeout(nil) {
|
|
t.Fatalf("isTimeout(nil) should be false")
|
|
}
|
|
if !isTimeout(timeoutErr{}) {
|
|
t.Fatalf("isTimeout(timeoutErr) should be true")
|
|
}
|
|
if isTimeout(plainErr{}) {
|
|
t.Fatalf("isTimeout(plainErr) should be false")
|
|
}
|
|
}
|
|
|
|
type timeoutErr struct{}
|
|
|
|
func (timeoutErr) Error() string { return "i/o timeout" }
|
|
func (timeoutErr) Timeout() bool { return true }
|
|
func (timeoutErr) Temporary() bool { return true }
|
|
|
|
type plainErr struct{}
|
|
|
|
func (plainErr) Error() string { return "boom" }
|
|
|
|
func TestMin(t *testing.T) {
|
|
if got := minInt(1, 2); got != 1 {
|
|
t.Fatalf("minInt(1,2) = %d, want 1", got)
|
|
}
|
|
if got := minInt(2, 1); got != 1 {
|
|
t.Fatalf("minInt(2,1) = %d, want 1", got)
|
|
}
|
|
if got := minInt(0, 0); got != 0 {
|
|
t.Fatalf("minInt(0,0) = %d, want 0", got)
|
|
}
|
|
}
|