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