fix: close stream adaptive gaps and switch notify to stario v0.1.1
- make stream fast path honor adaptive soft payload limits end-to-end - split oversized fast-stream payloads into sequential frames before batching - use adaptive soft cap when encoding stream batch payloads - move timeout-like error detection into production code for adaptive tx - tune notify FrameReader read size explicitly to avoid throughput regression - drop local stario replace and depend on released b612.me/stario v0.1.1
This commit is contained in:
+320
-3
@@ -109,6 +109,9 @@ func TestBulkOpenRoundTripTCP(t *testing.T) {
|
||||
if !clientSnapshots[0].BindingAlive || !clientSnapshots[0].BindingCurrent || !clientSnapshots[0].TransportAttached || !clientSnapshots[0].TransportCurrent {
|
||||
t.Fatalf("client bulk binding snapshot mismatch: %+v", clientSnapshots[0])
|
||||
}
|
||||
if got, want := clientSnapshots[0].BindingBulkAdaptiveSoftPayloadBytes, bulkAdaptiveSoftPayloadStartBytes; got != want {
|
||||
t.Fatalf("client bulk BindingBulkAdaptiveSoftPayloadBytes = %d, want %d", got, want)
|
||||
}
|
||||
serverSnapshots, err := GetServerBulkSnapshots(server)
|
||||
if err != nil {
|
||||
t.Fatalf("GetServerBulkSnapshots failed: %v", err)
|
||||
@@ -119,6 +122,9 @@ func TestBulkOpenRoundTripTCP(t *testing.T) {
|
||||
if got, want := serverSnapshots[0].BindingOwner, "server-transport"; got != want {
|
||||
t.Fatalf("server bulk BindingOwner = %q, want %q", got, want)
|
||||
}
|
||||
if got, want := serverSnapshots[0].BindingBulkAdaptiveSoftPayloadBytes, bulkAdaptiveSoftPayloadStartBytes; got != want {
|
||||
t.Fatalf("server bulk BindingBulkAdaptiveSoftPayloadBytes = %d, want %d", got, want)
|
||||
}
|
||||
if !serverSnapshots[0].BindingAlive || !serverSnapshots[0].BindingCurrent || !serverSnapshots[0].TransportAttached || !serverSnapshots[0].TransportCurrent {
|
||||
t.Fatalf("server bulk binding snapshot mismatch: %+v", serverSnapshots[0])
|
||||
}
|
||||
@@ -135,6 +141,314 @@ func TestBulkOpenRoundTripTCP(t *testing.T) {
|
||||
waitForBulkContextDone(t, bulk.Context(), 2*time.Second)
|
||||
}
|
||||
|
||||
func TestDedicatedBulkOpenUnblocksSynchronousReadHandler(t *testing.T) {
|
||||
server := NewServer().(*ServerCommon)
|
||||
if err := UseModernPSKServer(server, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UseModernPSKServer failed: %v", err)
|
||||
}
|
||||
|
||||
readCh := make(chan string, 1)
|
||||
server.SetBulkHandler(func(info BulkAcceptInfo) error {
|
||||
defer func() {
|
||||
_ = info.Bulk.Close()
|
||||
}()
|
||||
buf := make([]byte, 5)
|
||||
if _, err := io.ReadFull(info.Bulk, buf); err != nil {
|
||||
return err
|
||||
}
|
||||
readCh <- string(buf)
|
||||
return nil
|
||||
})
|
||||
|
||||
if err := server.Listen("tcp", "127.0.0.1:0"); err != nil {
|
||||
t.Fatalf("server Listen failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = server.Stop()
|
||||
}()
|
||||
|
||||
client := NewClient().(*ClientCommon)
|
||||
if err := UseModernPSKClient(client, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UseModernPSKClient failed: %v", err)
|
||||
}
|
||||
if err := client.Connect("tcp", server.listener.Addr().String()); err != nil {
|
||||
t.Fatalf("client Connect failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = client.Stop()
|
||||
}()
|
||||
|
||||
type openResult struct {
|
||||
bulk Bulk
|
||||
err error
|
||||
}
|
||||
openCh := make(chan openResult, 1)
|
||||
go func() {
|
||||
bulk, err := client.OpenDedicatedBulk(context.Background(), BulkOpenOptions{
|
||||
ID: "sync-read-handler",
|
||||
Range: BulkRange{
|
||||
Offset: 0,
|
||||
Length: 5,
|
||||
},
|
||||
})
|
||||
openCh <- openResult{bulk: bulk, err: err}
|
||||
}()
|
||||
|
||||
var bulk Bulk
|
||||
select {
|
||||
case result := <-openCh:
|
||||
if result.err != nil {
|
||||
t.Fatalf("client OpenDedicatedBulk failed: %v", result.err)
|
||||
}
|
||||
bulk = result.bulk
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("client OpenDedicatedBulk timed out while remote handler was synchronously reading")
|
||||
}
|
||||
defer func() {
|
||||
if bulk != nil {
|
||||
_ = bulk.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err := bulk.Write([]byte("hello")); err != nil {
|
||||
t.Fatalf("client dedicated bulk Write failed: %v", err)
|
||||
}
|
||||
select {
|
||||
case got := <-readCh:
|
||||
if got != "hello" {
|
||||
t.Fatalf("server handler read %q, want %q", got, "hello")
|
||||
}
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("timed out waiting for synchronous handler read")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDedicatedBulkOpenUnblocksOnBlockingFirstWrite(t *testing.T) {
|
||||
server := NewServer().(*ServerCommon)
|
||||
if err := UseModernPSKServer(server, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UseModernPSKServer failed: %v", err)
|
||||
}
|
||||
|
||||
payload := strings.Repeat("w", 16)
|
||||
writeDone := make(chan error, 1)
|
||||
server.SetBulkHandler(func(info BulkAcceptInfo) error {
|
||||
_, err := io.WriteString(info.Bulk, payload)
|
||||
if err == nil {
|
||||
err = info.Bulk.CloseWrite()
|
||||
}
|
||||
writeDone <- err
|
||||
return err
|
||||
})
|
||||
|
||||
if err := server.Listen("tcp", "127.0.0.1:0"); err != nil {
|
||||
t.Fatalf("server Listen failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = server.Stop()
|
||||
}()
|
||||
|
||||
client := NewClient().(*ClientCommon)
|
||||
if err := UseModernPSKClient(client, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UseModernPSKClient failed: %v", err)
|
||||
}
|
||||
if err := client.Connect("tcp", server.listener.Addr().String()); err != nil {
|
||||
t.Fatalf("client Connect failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = client.Stop()
|
||||
}()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
bulk, err := client.OpenDedicatedBulk(ctx, BulkOpenOptions{
|
||||
ID: "blocking-write-ready",
|
||||
Range: BulkRange{
|
||||
Offset: 0,
|
||||
Length: int64(len(payload)),
|
||||
},
|
||||
ChunkSize: 4,
|
||||
WindowBytes: 4,
|
||||
MaxInFlight: 1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("client OpenDedicatedBulk failed: %v", err)
|
||||
}
|
||||
|
||||
readBulkExactly(t, bulk, payload, 2*time.Second)
|
||||
waitForBulkReadEOF(t, bulk, 2*time.Second)
|
||||
|
||||
select {
|
||||
case err := <-writeDone:
|
||||
if err != nil {
|
||||
t.Fatalf("server handler write failed: %v", err)
|
||||
}
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("timed out waiting for blocking first write to finish")
|
||||
}
|
||||
|
||||
if err := bulk.Close(); err != nil {
|
||||
t.Fatalf("client dedicated bulk Close failed: %v", err)
|
||||
}
|
||||
waitForBulkContextDone(t, bulk.Context(), 2*time.Second)
|
||||
}
|
||||
|
||||
func TestServerOpenBulkLogicalDedicatedUnblocksOnBlockingFirstRead(t *testing.T) {
|
||||
server := NewServer().(*ServerCommon)
|
||||
if err := UseModernPSKServer(server, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UseModernPSKServer failed: %v", err)
|
||||
}
|
||||
|
||||
if err := server.Listen("tcp", "127.0.0.1:0"); err != nil {
|
||||
t.Fatalf("server Listen failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = server.Stop()
|
||||
}()
|
||||
|
||||
client := NewClient().(*ClientCommon)
|
||||
if err := UseModernPSKClient(client, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UseModernPSKClient failed: %v", err)
|
||||
}
|
||||
readCh := make(chan string, 1)
|
||||
client.SetBulkHandler(func(info BulkAcceptInfo) error {
|
||||
defer func() {
|
||||
_ = info.Bulk.Close()
|
||||
}()
|
||||
buf := make([]byte, 5)
|
||||
if _, err := io.ReadFull(info.Bulk, buf); err != nil {
|
||||
return err
|
||||
}
|
||||
readCh <- string(buf)
|
||||
return nil
|
||||
})
|
||||
if err := client.Connect("tcp", server.listener.Addr().String()); err != nil {
|
||||
t.Fatalf("client Connect failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = client.Stop()
|
||||
}()
|
||||
|
||||
logical := waitForTransferControlLogicalConn(t, server, 2*time.Second)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
bulk, err := server.OpenBulkLogical(ctx, logical, BulkOpenOptions{
|
||||
ID: "server-blocking-read-ready",
|
||||
Range: BulkRange{
|
||||
Offset: 0,
|
||||
Length: 5,
|
||||
},
|
||||
Dedicated: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("server OpenBulkLogical dedicated failed: %v", err)
|
||||
}
|
||||
|
||||
if _, err := bulk.Write([]byte("hello")); err != nil {
|
||||
t.Fatalf("server dedicated bulk Write failed: %v", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case got := <-readCh:
|
||||
if got != "hello" {
|
||||
t.Fatalf("client handler read %q, want %q", got, "hello")
|
||||
}
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("timed out waiting for blocking first read to finish")
|
||||
}
|
||||
|
||||
if err := bulk.Close(); err != nil {
|
||||
t.Fatalf("server dedicated bulk Close failed: %v", err)
|
||||
}
|
||||
waitForBulkContextDone(t, bulk.Context(), 2*time.Second)
|
||||
}
|
||||
|
||||
func TestDedicatedBulkOpenReturnsHandlerFailureAfterAccepted(t *testing.T) {
|
||||
server := NewServer().(*ServerCommon)
|
||||
if err := UseModernPSKServer(server, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UseModernPSKServer failed: %v", err)
|
||||
}
|
||||
|
||||
server.SetBulkHandler(func(info BulkAcceptInfo) error {
|
||||
time.Sleep(80 * time.Millisecond)
|
||||
return errors.New("dedicated handler failed after accept")
|
||||
})
|
||||
|
||||
if err := server.Listen("tcp", "127.0.0.1:0"); err != nil {
|
||||
t.Fatalf("server Listen failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = server.Stop()
|
||||
}()
|
||||
|
||||
client := NewClient().(*ClientCommon)
|
||||
if err := UseModernPSKClient(client, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UseModernPSKClient failed: %v", err)
|
||||
}
|
||||
if err := client.Connect("tcp", server.listener.Addr().String()); err != nil {
|
||||
t.Fatalf("client Connect failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = client.Stop()
|
||||
}()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
_, err := client.OpenDedicatedBulk(ctx, BulkOpenOptions{
|
||||
ID: "accepted-then-fail",
|
||||
Range: BulkRange{
|
||||
Offset: 0,
|
||||
Length: 1,
|
||||
},
|
||||
})
|
||||
if err == nil || !strings.Contains(err.Error(), "dedicated handler failed after accept") {
|
||||
t.Fatalf("client OpenDedicatedBulk error = %v, want dedicated handler failure after accept", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerOpenBulkLogicalDedicatedReturnsHandlerFailureAfterAccepted(t *testing.T) {
|
||||
server := NewServer().(*ServerCommon)
|
||||
if err := UseModernPSKServer(server, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UseModernPSKServer failed: %v", err)
|
||||
}
|
||||
|
||||
if err := server.Listen("tcp", "127.0.0.1:0"); err != nil {
|
||||
t.Fatalf("server Listen failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = server.Stop()
|
||||
}()
|
||||
|
||||
client := NewClient().(*ClientCommon)
|
||||
if err := UseModernPSKClient(client, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UseModernPSKClient failed: %v", err)
|
||||
}
|
||||
client.SetBulkHandler(func(info BulkAcceptInfo) error {
|
||||
time.Sleep(80 * time.Millisecond)
|
||||
return errors.New("client dedicated handler failed after accept")
|
||||
})
|
||||
if err := client.Connect("tcp", server.listener.Addr().String()); err != nil {
|
||||
t.Fatalf("client Connect failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = client.Stop()
|
||||
}()
|
||||
|
||||
logical := waitForTransferControlLogicalConn(t, server, 2*time.Second)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
_, err := server.OpenBulkLogical(ctx, logical, BulkOpenOptions{
|
||||
ID: "server-accepted-then-fail",
|
||||
Range: BulkRange{
|
||||
Offset: 0,
|
||||
Length: 1,
|
||||
},
|
||||
Dedicated: true,
|
||||
})
|
||||
if err == nil || !strings.Contains(err.Error(), "client dedicated handler failed after accept") {
|
||||
t.Fatalf("server OpenBulkLogical dedicated error = %v, want client dedicated handler failure after accept", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBulkOpenRoundTripServerLogicalTCP(t *testing.T) {
|
||||
server := NewServer().(*ServerCommon)
|
||||
if err := UseModernPSKServer(server, integrationSharedSecret, integrationModernPSKOptions()); err != nil {
|
||||
@@ -532,15 +846,18 @@ func TestDedicatedBulkWritePrefersClosedPipeOverContextCanceled(t *testing.T) {
|
||||
MaxInFlight: 4,
|
||||
}, 0, nil, nil, 0, nil, nil, func(context.Context, *bulkHandle, []byte) error {
|
||||
return nil
|
||||
}, func(ctx context.Context, bulk *bulkHandle, payload []byte) (int, error) {
|
||||
}, func(ctx context.Context, bulk *bulkHandle, startSeq uint64, payload []byte, payloadOwned bool) (int, error) {
|
||||
bulk.markPeerClosed()
|
||||
<-ctx.Done()
|
||||
return 0, ctx.Err()
|
||||
}, nil)
|
||||
|
||||
_, err := bulk.Write([]byte("abcdefgh"))
|
||||
if !errors.Is(err, io.ErrClosedPipe) {
|
||||
t.Fatalf("bulk Write error = %v, want %v", err, io.ErrClosedPipe)
|
||||
if err != nil && !errors.Is(err, io.ErrClosedPipe) {
|
||||
t.Fatalf("bulk Write error = %v, want nil or %v", err, io.ErrClosedPipe)
|
||||
}
|
||||
if err := bulk.waitPendingAsyncWrites(context.Background()); err != nil && !errors.Is(err, io.ErrClosedPipe) {
|
||||
t.Fatalf("bulk waitPendingAsyncWrites error = %v, want nil or %v", err, io.ErrClosedPipe)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user