Некоторые проверки не удались
CI / test (push) Successful in 2m5s
Docker / Build and publish worker image (push) Failing after 31s
165 строки
4.2 KiB
Go
165 строки
4.2 KiB
Go
package ctcp
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net"
|
|
"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: "tcp",
|
|
Monitor: &models.Monitor{Host: host},
|
|
Settings: datatypes.JSON(raw),
|
|
}
|
|
}
|
|
|
|
// startListener brings up a TCP listener on 127.0.0.1:0 so tests can
|
|
// reach a real port. Returns the listener and the resolved address.
|
|
func startListener(t *testing.T) (net.Listener, string) {
|
|
t.Helper()
|
|
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatalf("listen: %v", err)
|
|
}
|
|
return ln, ln.Addr().String()
|
|
}
|
|
|
|
func TestPerformOK(t *testing.T) {
|
|
ln, addr := startListener(t)
|
|
defer ln.Close()
|
|
|
|
host, port, err := net.SplitHostPort(addr)
|
|
if err != nil {
|
|
t.Fatalf("split addr: %v", err)
|
|
}
|
|
c := newCheck(t, settings{Port: port, Timeout: 1}, host)
|
|
r := Perform(c)
|
|
if r.State != stateOK {
|
|
t.Fatalf("expected OK, got %s (err=%v)", r.State, r.Error)
|
|
}
|
|
if r.RemoteAddr == "" {
|
|
t.Fatalf("expected RemoteAddr to be populated, got %q", r.RemoteAddr)
|
|
}
|
|
if !contains(r.Infos[0], "tcp") {
|
|
t.Fatalf("expected info line about tcp probe, got %v", r.Infos)
|
|
}
|
|
}
|
|
|
|
func TestPerformRefused(t *testing.T) {
|
|
// Bind to 127.0.0.1:0 to find a free port, close immediately so
|
|
// the next dial gets RST/CONNREFUSED.
|
|
ln, addr := startListener(t)
|
|
host, port, _ := net.SplitHostPort(addr)
|
|
_ = ln.Close()
|
|
|
|
// On some runners the OS reassigns the just-closed port to a
|
|
// listener before our dial. Retry up to a few times to stabilise.
|
|
var final net.Listener
|
|
for i := 0; i < 3; i++ {
|
|
l, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
continue
|
|
}
|
|
addr2 := l.Addr().String()
|
|
h, p, _ := net.SplitHostPort(addr2)
|
|
_ = l.Close()
|
|
// Replace what we are about to dial with one we just freed.
|
|
addr = addr2
|
|
host = h
|
|
port = p
|
|
break
|
|
}
|
|
_ = final
|
|
|
|
c := newCheck(t, settings{Port: port, Timeout: 1}, host)
|
|
r := Perform(c)
|
|
if r.State != stateERR {
|
|
t.Fatalf("expected ERR, got %s (err=%v)", r.State, r.Error)
|
|
}
|
|
if r.Error == nil {
|
|
t.Fatalf("expected error, got nil")
|
|
}
|
|
}
|
|
|
|
func TestPerformUnreachable(t *testing.T) {
|
|
// 127.0.0.0/8 — using 127.0.0.99 should resolve but be a hard
|
|
// "no route" on most platforms. The check should fail fast.
|
|
c := newCheck(t, settings{Port: "65530", Timeout: 1}, "127.0.0.99")
|
|
// Use a short timeout so the test does not hang on slow CI.
|
|
r := Perform(c)
|
|
if r.State == stateOK {
|
|
t.Fatalf("expected ERR/WARN, got OK (this loopback should not answer)")
|
|
}
|
|
}
|
|
|
|
func TestPerformDefaultPort(t *testing.T) {
|
|
ln, addr := startListener(t)
|
|
defer ln.Close()
|
|
host, _, _ := net.SplitHostPort(addr)
|
|
c := newCheck(t, settings{}, host) // port empty -> defaults to 80
|
|
r := Perform(c)
|
|
// 80 is unlikely to answer on the loopback; we only care that
|
|
// the check did not panic and reported something on failure.
|
|
if r.State == "" {
|
|
t.Fatalf("expected non-empty state, got %q", r.State)
|
|
}
|
|
}
|
|
|
|
func TestPerformEmptyHost(t *testing.T) {
|
|
c := newCheck(t, settings{Port: "80", Timeout: 1}, "")
|
|
r := Perform(c)
|
|
if r.State != stateERR {
|
|
t.Fatalf("expected ERR on empty host, got %s", r.State)
|
|
}
|
|
if r.Error == nil {
|
|
t.Fatalf("expected error, got nil")
|
|
}
|
|
}
|
|
|
|
func TestPerformClampsTimeout(t *testing.T) {
|
|
// Already covered indirectly by TestPerformDefaultPort but
|
|
// assert the dialer budget is at least 1s even with Timeout=0.
|
|
ln, addr := startListener(t)
|
|
defer ln.Close()
|
|
host, port, _ := net.SplitHostPort(addr)
|
|
|
|
start := time.Now()
|
|
c := newCheck(t, settings{Port: port, Timeout: 0}, host)
|
|
r := Perform(c)
|
|
elapsed := time.Since(start)
|
|
if elapsed > 2*time.Second {
|
|
t.Fatalf("default timeout exceeded 2s, got %v", elapsed)
|
|
}
|
|
if r.State != stateOK {
|
|
t.Fatalf("expected OK against local listener, got %s", r.State)
|
|
}
|
|
}
|
|
|
|
func contains(s, sub string) bool {
|
|
for i := 0; i+len(sub) <= len(s); i++ {
|
|
if s[i:i+len(sub)] == sub {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|