86 lines
3.1 KiB
Go
86 lines
3.1 KiB
Go
package probe
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
|
|
controlplanev1 "proxy-pool/gen/controlplane/v1"
|
|
|
|
"google.golang.org/protobuf/types/known/durationpb"
|
|
"google.golang.org/protobuf/types/known/timestamppb"
|
|
)
|
|
|
|
func TestExecutorBasicConfirmsProxyHandshakeEvenWhenProbeTargetFails(t *testing.T) {
|
|
proxy := httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
|
|
if request.URL.String() != "http://example.invalid/" {
|
|
t.Errorf("proxy request URL = %q", request.URL)
|
|
}
|
|
if value := request.Header.Get("Proxy-Authorization"); value != "Basic dXNlcjpzZWNyZXQ=" {
|
|
t.Errorf("Proxy-Authorization = %q", value)
|
|
}
|
|
response.WriteHeader(http.StatusBadGateway)
|
|
}))
|
|
defer proxy.Close()
|
|
task := validTask(t, proxy.URL, controlplanev1.CheckLevel_CHECK_LEVEL_BASIC)
|
|
result := NewExecutor().Execute(context.Background(), task)
|
|
if !result.Success || result.FailureClass != "" || result.Latency <= 0 {
|
|
t.Fatalf("Execute(BASIC) = %+v", result)
|
|
}
|
|
}
|
|
|
|
func splitProxyAddress(t *testing.T, address string) (string, uint32) {
|
|
t.Helper()
|
|
host, rawPort, err := net.SplitHostPort(address[len("http://"):])
|
|
if err != nil {
|
|
t.Fatalf("net.SplitHostPort(%q): %v", address, err)
|
|
}
|
|
port, err := strconv.ParseUint(rawPort, 10, 16)
|
|
if err != nil {
|
|
t.Fatalf("strconv.ParseUint(%q): %v", rawPort, err)
|
|
}
|
|
return host, uint32(port)
|
|
}
|
|
|
|
func TestExecutorTargetReportsHTTPFailureAsFact(t *testing.T) {
|
|
proxy := httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, _ *http.Request) {
|
|
response.WriteHeader(http.StatusServiceUnavailable)
|
|
}))
|
|
defer proxy.Close()
|
|
task := validTask(t, proxy.URL, controlplanev1.CheckLevel_CHECK_LEVEL_TARGET)
|
|
task.RoutingName = "route-a"
|
|
task.TargetUrl = "http://target.example/check"
|
|
result := NewExecutor().Execute(context.Background(), task)
|
|
if result.Success || result.FailureClass != FailureTargetHTTPStatus || result.Latency <= 0 {
|
|
t.Fatalf("Execute(TARGET) = %+v", result)
|
|
}
|
|
}
|
|
|
|
func TestExecutorReportsUnsupportedProtocolAsFact(t *testing.T) {
|
|
now := time.Now().UTC()
|
|
result := NewExecutor().Execute(context.Background(), &controlplanev1.CheckTask{
|
|
TaskId: "task-a", ProxyId: "proxy-a", Protocol: controlplanev1.ProxyProtocol_PROXY_PROTOCOL_SOCKS5,
|
|
Host: "proxy.example", Port: 1080, Level: controlplanev1.CheckLevel_CHECK_LEVEL_BASIC,
|
|
Timeout: durationpb.New(time.Second), Attempt: 1, MaxAttempts: 1, Deadline: timestamppb.New(now.Add(time.Second)),
|
|
})
|
|
if result.Success || result.FailureClass != FailureUnsupportedProxy {
|
|
t.Fatalf("Execute(SOCKS5) = %+v", result)
|
|
}
|
|
}
|
|
|
|
func validTask(t *testing.T, proxyAddress string, level controlplanev1.CheckLevel) *controlplanev1.CheckTask {
|
|
t.Helper()
|
|
host, port := splitProxyAddress(t, proxyAddress)
|
|
now := time.Now().UTC()
|
|
return &controlplanev1.CheckTask{
|
|
TaskId: "task-a", ProxyId: "proxy-a", Protocol: controlplanev1.ProxyProtocol_PROXY_PROTOCOL_HTTP,
|
|
Host: host, Port: port, Level: level, Username: "user", Password: "secret",
|
|
Timeout: durationpb.New(time.Second), Attempt: 1, MaxAttempts: 1,
|
|
Deadline: timestamppb.New(now.Add(time.Second)),
|
|
}
|
|
}
|