mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-22 11:10:12 +00:00
test(agentcompat): add integration scenarios
Co-authored-by: naiba/CloudCode <hi+cloudcode@nai.ba>
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
//go:build linux && agentcompat
|
||||
|
||||
package scenario
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nezhahq/nezha/integration/agentcompat/internal/fixture"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNAT_HTTPRequestObservesPeerWriteCloseAfterDeclaredBody(t *testing.T) {
|
||||
// Given
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { require.NoError(t, listener.Close()) })
|
||||
serverDone := make(chan error, 1)
|
||||
go func() {
|
||||
connection, acceptErr := listener.Accept()
|
||||
if acceptErr != nil {
|
||||
serverDone <- acceptErr
|
||||
return
|
||||
}
|
||||
defer connection.Close()
|
||||
request, readErr := http.ReadRequest(bufio.NewReader(connection))
|
||||
if readErr != nil {
|
||||
serverDone <- readErr
|
||||
return
|
||||
}
|
||||
_, readErr = io.Copy(io.Discard, request.Body)
|
||||
if closeErr := request.Body.Close(); readErr == nil {
|
||||
readErr = closeErr
|
||||
}
|
||||
if readErr != nil {
|
||||
serverDone <- readErr
|
||||
return
|
||||
}
|
||||
body := "closed"
|
||||
if _, writeErr := fmt.Fprintf(connection, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s%s", len(body), body, io.EOF.Error()); writeErr != nil {
|
||||
serverDone <- writeErr
|
||||
return
|
||||
}
|
||||
tcpConnection, ok := connection.(*net.TCPConn)
|
||||
if !ok {
|
||||
serverDone <- errors.New("test listener did not accept TCP connection")
|
||||
return
|
||||
}
|
||||
serverDone <- tcpConnection.CloseWrite()
|
||||
}()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// When
|
||||
response, err := natHTTPRequest(ctx, natHTTPRequestSpec{Endpoint: listener.Addr().String(), Host: natTestDomain, Method: http.MethodGet, Path: "/"})
|
||||
|
||||
// Then
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, http.StatusOK, response.Status)
|
||||
require.Equal(t, "closed", response.Body)
|
||||
require.Equal(t, io.EOF.Error(), response.LegacyCloseMarker)
|
||||
require.True(t, response.PeerWriteClosed)
|
||||
require.NoError(t, <-serverDone)
|
||||
}
|
||||
|
||||
func TestNAT_ParseResponsePreservesExactRequestFields(t *testing.T) {
|
||||
// Given
|
||||
body := natExpectedBody(natHTTPRequestSpec{Host: natTestDomain, Method: http.MethodPatch, Path: "/nat?case=ordinary", Body: "ordinary"})
|
||||
|
||||
// When
|
||||
record, err := parseNATResponse(body)
|
||||
|
||||
// Then
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, http.MethodPatch, record.Method)
|
||||
require.Equal(t, "/nat?case=ordinary", record.Path)
|
||||
require.Equal(t, natTestDomain, record.Host)
|
||||
require.Equal(t, "fixture", record.HeaderValue)
|
||||
require.Equal(t, []byte("ordinary"), record.Body)
|
||||
}
|
||||
|
||||
func TestNAT_ParseResponseRejectsMissingEvidence(t *testing.T) {
|
||||
// Given
|
||||
body := "method=GET\npath=/\n"
|
||||
|
||||
// When
|
||||
_, err := parseNATResponse(body)
|
||||
|
||||
// Then
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestNAT_ExactRequestObservedRejectsMismatchedHalfCloseEvidence(t *testing.T) {
|
||||
// Given
|
||||
request := natHTTPRequestSpec{Host: natHalfCloseTestDomain, Method: http.MethodPost, Path: "/nat?case=half-close", Body: "half-closed"}
|
||||
exact := fixture.NATEchoRecord{Method: request.Method, Path: request.Path, Host: request.Host, HeaderValue: natEchoHeaderValue, Body: []byte(request.Body)}
|
||||
mismatched := exact
|
||||
mismatched.Host = natTestDomain
|
||||
|
||||
// When
|
||||
observed := natExactRequestObserved(request, exact, mismatched)
|
||||
|
||||
// Then
|
||||
require.False(t, observed)
|
||||
}
|
||||
|
||||
func TestNAT_DeletedRouteObservedRequiresFallbackStatusAndBody(t *testing.T) {
|
||||
// Given
|
||||
request := natHTTPRequestSpec{Host: natTestDomain, Method: http.MethodGet, Path: "/"}
|
||||
|
||||
// When
|
||||
observed := natDeletedRouteObserved(natRawResponse{Status: http.StatusOK, Body: "dashboard fallback"}, nil, request)
|
||||
echoObserved := natDeletedRouteObserved(natRawResponse{Status: http.StatusOK, Body: natExpectedBody(request)}, nil, request)
|
||||
rejectedObserved := natDeletedRouteObserved(natRawResponse{Status: http.StatusNotFound, Body: "not found"}, nil, request)
|
||||
|
||||
// Then
|
||||
require.True(t, observed)
|
||||
require.False(t, echoObserved)
|
||||
require.False(t, rejectedObserved)
|
||||
}
|
||||
|
||||
func TestNAT_FinishReturnsTypedFailedAssertion(t *testing.T) {
|
||||
// Given
|
||||
assertions := NewAssertionSet()
|
||||
assertions.Record("deleted profile no longer routes", false, "backend connection observed")
|
||||
|
||||
// When
|
||||
result, err := finishNAT(assertions, nil)
|
||||
|
||||
// Then
|
||||
require.EqualError(t, err, "deleted profile no longer routes: backend connection observed")
|
||||
require.Equal(t, "nat", result.Name)
|
||||
require.False(t, result.Passed)
|
||||
require.False(t, result.CleanupOK)
|
||||
}
|
||||
|
||||
func TestNAT_FinishPreservesRuntimeError(t *testing.T) {
|
||||
// Given
|
||||
runtimeErr := errors.New("NAT runtime failed")
|
||||
|
||||
// When
|
||||
result, err := finishNAT(NewAssertionSet(), runtimeErr)
|
||||
|
||||
// Then
|
||||
require.ErrorIs(t, err, runtimeErr)
|
||||
require.Equal(t, "NAT runtime failed", result.Error)
|
||||
}
|
||||
Reference in New Issue
Block a user