test(gateway): observe qualification batch pacing
Verify Data Plane / gateway (push) Failing after 1m31s
Verify Data Plane / gateway (push) Failing after 1m31s
This commit is contained in:
@@ -100,6 +100,15 @@ func TestQualificationApolloFixturePacesSourceShapedVideo(t *testing.T) {
|
|||||||
fixture := &qualificationApolloFixture{video: sender, failures: make(chan error, 1)}
|
fixture := &qualificationApolloFixture{video: sender, failures: make(chan error, 1)}
|
||||||
remote := *receiver.LocalAddr().(*net.UDPAddr)
|
remote := *receiver.LocalAddr().(*net.UDPAddr)
|
||||||
fixture.videoRemote.Store(&remote)
|
fixture.videoRemote.Store(&remote)
|
||||||
|
var batchIndices []int
|
||||||
|
var batchStarts []time.Duration
|
||||||
|
var started time.Time
|
||||||
|
fixture.observeVideoBatch = func(index int, at time.Time) {
|
||||||
|
if len(batchIndices) < 3 {
|
||||||
|
batchIndices = append(batchIndices, index)
|
||||||
|
batchStarts = append(batchStarts, at.Sub(started))
|
||||||
|
}
|
||||||
|
}
|
||||||
drained := make(chan struct{})
|
drained := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
defer close(drained)
|
defer close(drained)
|
||||||
@@ -111,7 +120,7 @@ func TestQualificationApolloFixturePacesSourceShapedVideo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
started := time.Now()
|
started = time.Now()
|
||||||
if err := fixture.sendVideo(context.Background(), packets); err != nil {
|
if err := fixture.sendVideo(context.Background(), packets); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -120,9 +129,22 @@ func TestQualificationApolloFixturePacesSourceShapedVideo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
elapsed := time.Since(started)
|
elapsed := time.Since(started)
|
||||||
wantCarry := qualificationApolloVideoOffset(len(packets), packetsPerMillisecond)
|
wantCarry := qualificationApolloVideoOffset(len(packets), packetsPerMillisecond)
|
||||||
|
if wantCarry != 10416666*time.Nanosecond {
|
||||||
|
t.Fatalf("1000-packet carry = %s, want 10.416666 ms", wantCarry)
|
||||||
|
}
|
||||||
if elapsed < wantCarry {
|
if elapsed < wantCarry {
|
||||||
t.Fatalf("source fixture sent the next frame after %s, before Apollo pacing carry %s", elapsed, wantCarry)
|
t.Fatalf("source fixture sent the next frame after %s, before Apollo pacing carry %s", elapsed, wantCarry)
|
||||||
}
|
}
|
||||||
|
wantIndices := []int{0, 63, 126}
|
||||||
|
wantStarts := []time.Duration{0, 656250 * time.Nanosecond, 1312500 * time.Nanosecond}
|
||||||
|
if len(batchIndices) != len(wantIndices) {
|
||||||
|
t.Fatalf("observed %d batch starts, want %d", len(batchIndices), len(wantIndices))
|
||||||
|
}
|
||||||
|
for index := range wantIndices {
|
||||||
|
if batchIndices[index] != wantIndices[index] || batchStarts[index] < wantStarts[index] {
|
||||||
|
t.Fatalf("batch starts = indices %v at %v; want indices %v no earlier than %v", batchIndices, batchStarts, wantIndices, wantStarts)
|
||||||
|
}
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case <-drained:
|
case <-drained:
|
||||||
case <-time.After(time.Second):
|
case <-time.After(time.Second):
|
||||||
|
|||||||
@@ -414,22 +414,23 @@ func (b *qualificationTracingBackend) session(sessionID string) *nativeApolloSes
|
|||||||
}
|
}
|
||||||
|
|
||||||
type qualificationApolloFixture struct {
|
type qualificationApolloFixture struct {
|
||||||
sessionID string
|
sessionID string
|
||||||
management *httptest.Server
|
management *httptest.Server
|
||||||
stream net.Listener
|
stream net.Listener
|
||||||
control *net.UDPConn
|
control *net.UDPConn
|
||||||
audio *net.UDPConn
|
audio *net.UDPConn
|
||||||
video *net.UDPConn
|
video *net.UDPConn
|
||||||
videoRemote atomic.Pointer[net.UDPAddr]
|
videoRemote atomic.Pointer[net.UDPAddr]
|
||||||
key atomic.Pointer[[]byte]
|
key atomic.Pointer[[]byte]
|
||||||
keyReady chan []byte
|
keyReady chan []byte
|
||||||
failures chan error
|
failures chan error
|
||||||
closed atomic.Bool
|
closed atomic.Bool
|
||||||
closeOnce sync.Once
|
closeOnce sync.Once
|
||||||
sentPackets atomic.Uint64
|
sentPackets atomic.Uint64
|
||||||
work protocol.ProviderSessionWork
|
work protocol.ProviderSessionWork
|
||||||
videoPaceMu sync.Mutex
|
videoPaceMu sync.Mutex
|
||||||
videoNext time.Time
|
videoNext time.Time
|
||||||
|
observeVideoBatch func(int, time.Time)
|
||||||
|
|
||||||
controlImpairmentMu sync.Mutex
|
controlImpairmentMu sync.Mutex
|
||||||
controlRTT time.Duration
|
controlRTT time.Duration
|
||||||
@@ -775,11 +776,14 @@ func (f *qualificationApolloFixture) sendVideo(ctx context.Context, packets [][]
|
|||||||
}
|
}
|
||||||
framePackets := 0
|
framePackets := 0
|
||||||
for batchStart := 0; batchStart < len(packets); batchStart += batchSize {
|
for batchStart := 0; batchStart < len(packets); batchStart += batchSize {
|
||||||
|
batchEnd := min(batchStart+batchSize, len(packets))
|
||||||
due := frameStart.Add(qualificationApolloVideoOffset(framePackets, packetsPerMillisecond))
|
due := frameStart.Add(qualificationApolloVideoOffset(framePackets, packetsPerMillisecond))
|
||||||
if err := qualificationWaitContext(ctx, due); err != nil {
|
if err := qualificationWaitContext(ctx, due); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
batchEnd := min(batchStart+batchSize, len(packets))
|
if f.observeVideoBatch != nil {
|
||||||
|
f.observeVideoBatch(framePackets, time.Now())
|
||||||
|
}
|
||||||
for _, packet := range packets[batchStart:batchEnd] {
|
for _, packet := range packets[batchStart:batchEnd] {
|
||||||
if len(packet) != len(packets[0]) {
|
if len(packet) != len(packets[0]) {
|
||||||
return ErrProviderMalformed
|
return ErrProviderMalformed
|
||||||
|
|||||||
Reference in New Issue
Block a user