92 lines
2.5 KiB
Go
92 lines
2.5 KiB
Go
package mtprotoedge
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestBulkRPCSchedulerKeepsOverflowBehindGate(t *testing.T) {
|
|
scheduler := newBulkRPCScheduler(2)
|
|
first := scheduler.reserve()
|
|
second := scheduler.reserve()
|
|
third := scheduler.reserve()
|
|
woken := make(chan bool, 1)
|
|
third.subscribe(func(success bool) { woken <- success })
|
|
select {
|
|
case <-woken:
|
|
t.Fatal("overflow bulk handler became runnable before a slot was released")
|
|
default:
|
|
}
|
|
first.release()
|
|
select {
|
|
case success := <-woken:
|
|
if !success {
|
|
t.Fatal("overflow bulk handler was canceled instead of admitted")
|
|
}
|
|
case <-time.After(time.Second):
|
|
t.Fatal("overflow bulk handler did not become runnable")
|
|
}
|
|
second.release()
|
|
third.release()
|
|
}
|
|
|
|
func TestBulkRPCSchedulerCloseCancelsWaiters(t *testing.T) {
|
|
scheduler := newBulkRPCScheduler(1)
|
|
active := scheduler.reserve()
|
|
waiting := scheduler.reserve()
|
|
woken := make(chan bool, 1)
|
|
waiting.subscribe(func(success bool) { woken <- success })
|
|
scheduler.close()
|
|
select {
|
|
case success := <-woken:
|
|
if success {
|
|
t.Fatal("closed bulk scheduler granted a waiting handler")
|
|
}
|
|
case <-time.After(time.Second):
|
|
t.Fatal("closed bulk scheduler did not cancel waiter")
|
|
}
|
|
active.release()
|
|
}
|
|
|
|
func TestBulkRPCAdmissionDoesNotReserveGlobalSlotBeforeSessionCredit(t *testing.T) {
|
|
scheduler := newBulkRPCScheduler(1)
|
|
state := newOutboundStateWithLimits(newOutboundTrackedBudget(1<<20), 128, 1<<20)
|
|
state.bulkMax = 1
|
|
activeCredit := state.reserveBulkCredit()
|
|
waitingCredit := state.reserveBulkCredit()
|
|
admission := newBulkRPCAdmission(scheduler)
|
|
woken := make(chan bool, 1)
|
|
admission.subscribeAfter(waitingCredit.credit, func(success bool) { woken <- success })
|
|
|
|
scheduler.mu.Lock()
|
|
inUseBeforeCredit := scheduler.inUse
|
|
scheduler.mu.Unlock()
|
|
if inUseBeforeCredit != 0 {
|
|
t.Fatalf("credit-blocked request reserved %d global slots, want 0", inUseBeforeCredit)
|
|
}
|
|
select {
|
|
case <-woken:
|
|
t.Fatal("credit-blocked request became runnable")
|
|
default:
|
|
}
|
|
|
|
activeCredit.releaseIfOwned()
|
|
select {
|
|
case success := <-woken:
|
|
if !success {
|
|
t.Fatal("request was canceled after session credit became available")
|
|
}
|
|
case <-time.After(time.Second):
|
|
t.Fatal("request did not enter global scheduler after session credit")
|
|
}
|
|
scheduler.mu.Lock()
|
|
inUseAfterCredit := scheduler.inUse
|
|
scheduler.mu.Unlock()
|
|
if inUseAfterCredit != 1 {
|
|
t.Fatalf("admitted request reserved %d global slots, want 1", inUseAfterCredit)
|
|
}
|
|
|
|
admission.release()
|
|
waitingCredit.releaseIfOwned()
|
|
state.closeBulkWindow()
|
|
}
|