212 lines
5.9 KiB
Go
212 lines
5.9 KiB
Go
// Copyright 2019 The gVisor Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package flipcall
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
var testPacketWindowSize = pageSize
|
|
|
|
func testSendRecv(t *testing.T, ctrlMode ControlMode) {
|
|
pwa, err := NewPacketWindowAllocator()
|
|
if err != nil {
|
|
t.Fatalf("failed to create PacketWindowAllocator: %v", err)
|
|
}
|
|
defer pwa.Destroy()
|
|
pwd, err := pwa.Allocate(testPacketWindowSize)
|
|
if err != nil {
|
|
t.Fatalf("PacketWindowAllocator.Allocate() failed: %v", err)
|
|
}
|
|
|
|
sendEP, err := NewEndpoint(ctrlMode, pwd)
|
|
if err != nil {
|
|
t.Fatalf("failed to create Endpoint: %v", err)
|
|
}
|
|
defer sendEP.Destroy()
|
|
recvEP, err := NewEndpoint(ctrlMode, pwd)
|
|
if err != nil {
|
|
t.Fatalf("failed to create Endpoint: %v", err)
|
|
}
|
|
defer recvEP.Destroy()
|
|
|
|
otherThreadDone := make(chan struct{})
|
|
go func() {
|
|
defer func() { otherThreadDone <- struct{}{} }()
|
|
t.Logf("initially-inactive Endpoint waiting for packet 1")
|
|
if _, err := recvEP.RecvFirst(); err != nil {
|
|
t.Fatalf("initially-inactive Endpoint.RecvFirst() failed: %v", err)
|
|
}
|
|
t.Logf("initially-inactive Endpoint got packet 1, sending packet 2 and waiting for packet 3")
|
|
if _, err := recvEP.SendRecv(0); err != nil {
|
|
t.Fatalf("initially-inactive Endpoint.SendRecv() failed: %v", err)
|
|
}
|
|
t.Logf("initially-inactive Endpoint got packet 3")
|
|
}()
|
|
defer func() {
|
|
t.Logf("waiting for initially-inactive Endpoint goroutine to complete")
|
|
<-otherThreadDone
|
|
}()
|
|
|
|
t.Logf("initially-active Endpoint sending packet 1 and waiting for packet 2")
|
|
if _, err := sendEP.SendRecv(0); err != nil {
|
|
t.Fatalf("initially-active Endpoint.SendRecv() failed: %v", err)
|
|
}
|
|
t.Logf("initially-active Endpoint got packet 2, sending packet 3")
|
|
if err := sendEP.SendLast(0); err != nil {
|
|
t.Fatalf("initially-active Endpoint.SendLast() failed: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestFutexSendRecv(t *testing.T) {
|
|
testSendRecv(t, ControlModeFutex)
|
|
}
|
|
|
|
func testRecvFirstShutdown(t *testing.T, ctrlMode ControlMode) {
|
|
pwa, err := NewPacketWindowAllocator()
|
|
if err != nil {
|
|
t.Fatalf("failed to create PacketWindowAllocator: %v", err)
|
|
}
|
|
defer pwa.Destroy()
|
|
pwd, err := pwa.Allocate(testPacketWindowSize)
|
|
if err != nil {
|
|
t.Fatalf("PacketWindowAllocator.Allocate() failed: %v", err)
|
|
}
|
|
|
|
ep, err := NewEndpoint(ctrlMode, pwd)
|
|
if err != nil {
|
|
t.Fatalf("failed to create Endpoint: %v", err)
|
|
}
|
|
defer ep.Destroy()
|
|
|
|
otherThreadDone := make(chan struct{})
|
|
go func() {
|
|
defer func() { otherThreadDone <- struct{}{} }()
|
|
_, err := ep.RecvFirst()
|
|
if err == nil {
|
|
t.Errorf("Endpoint.RecvFirst() succeeded unexpectedly")
|
|
}
|
|
}()
|
|
|
|
time.Sleep(time.Second) // to ensure ep.RecvFirst() has blocked
|
|
ep.Shutdown()
|
|
<-otherThreadDone
|
|
}
|
|
|
|
func TestFutexRecvFirstShutdown(t *testing.T) {
|
|
testRecvFirstShutdown(t, ControlModeFutex)
|
|
}
|
|
|
|
func testSendRecvShutdown(t *testing.T, ctrlMode ControlMode) {
|
|
pwa, err := NewPacketWindowAllocator()
|
|
if err != nil {
|
|
t.Fatalf("failed to create PacketWindowAllocator: %v", err)
|
|
}
|
|
defer pwa.Destroy()
|
|
pwd, err := pwa.Allocate(testPacketWindowSize)
|
|
if err != nil {
|
|
t.Fatalf("PacketWindowAllocator.Allocate() failed: %v", err)
|
|
}
|
|
|
|
sendEP, err := NewEndpoint(ctrlMode, pwd)
|
|
if err != nil {
|
|
t.Fatalf("failed to create Endpoint: %v", err)
|
|
}
|
|
defer sendEP.Destroy()
|
|
recvEP, err := NewEndpoint(ctrlMode, pwd)
|
|
if err != nil {
|
|
t.Fatalf("failed to create Endpoint: %v", err)
|
|
}
|
|
defer recvEP.Destroy()
|
|
|
|
otherThreadDone := make(chan struct{})
|
|
go func() {
|
|
defer func() { otherThreadDone <- struct{}{} }()
|
|
if _, err := recvEP.RecvFirst(); err != nil {
|
|
t.Fatalf("initially-inactive Endpoint.RecvFirst() failed: %v", err)
|
|
}
|
|
if _, err := recvEP.SendRecv(0); err == nil {
|
|
t.Errorf("initially-inactive Endpoint.SendRecv() succeeded unexpectedly")
|
|
}
|
|
}()
|
|
|
|
if _, err := sendEP.SendRecv(0); err != nil {
|
|
t.Fatalf("initially-active Endpoint.SendRecv() failed: %v", err)
|
|
}
|
|
time.Sleep(time.Second) // to ensure recvEP.SendRecv() has blocked
|
|
recvEP.Shutdown()
|
|
<-otherThreadDone
|
|
}
|
|
|
|
func TestFutexSendRecvShutdown(t *testing.T) {
|
|
testSendRecvShutdown(t, ControlModeFutex)
|
|
}
|
|
|
|
func benchmarkSendRecv(b *testing.B, ctrlMode ControlMode) {
|
|
pwa, err := NewPacketWindowAllocator()
|
|
if err != nil {
|
|
b.Fatalf("failed to create PacketWindowAllocator: %v", err)
|
|
}
|
|
defer pwa.Destroy()
|
|
pwd, err := pwa.Allocate(testPacketWindowSize)
|
|
if err != nil {
|
|
b.Fatalf("PacketWindowAllocator.Allocate() failed: %v", err)
|
|
}
|
|
|
|
sendEP, err := NewEndpoint(ctrlMode, pwd)
|
|
if err != nil {
|
|
b.Fatalf("failed to create Endpoint: %v", err)
|
|
}
|
|
defer sendEP.Destroy()
|
|
recvEP, err := NewEndpoint(ctrlMode, pwd)
|
|
if err != nil {
|
|
b.Fatalf("failed to create Endpoint: %v", err)
|
|
}
|
|
defer recvEP.Destroy()
|
|
|
|
otherThreadDone := make(chan struct{})
|
|
go func() {
|
|
defer func() { otherThreadDone <- struct{}{} }()
|
|
if b.N == 0 {
|
|
return
|
|
}
|
|
if _, err := recvEP.RecvFirst(); err != nil {
|
|
b.Fatalf("initially-inactive Endpoint.RecvFirst() failed: %v", err)
|
|
}
|
|
for i := 1; i < b.N; i++ {
|
|
if _, err := recvEP.SendRecv(0); err != nil {
|
|
b.Fatalf("initially-inactive Endpoint.SendRecv() failed: %v", err)
|
|
}
|
|
}
|
|
if err := recvEP.SendLast(0); err != nil {
|
|
b.Fatalf("initially-inactive Endpoint.SendLast() failed: %v", err)
|
|
}
|
|
}()
|
|
defer func() { <-otherThreadDone }()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
if _, err := sendEP.SendRecv(0); err != nil {
|
|
b.Fatalf("initially-active Endpoint.SendRecv() failed: %v", err)
|
|
}
|
|
}
|
|
b.StopTimer()
|
|
}
|
|
|
|
func BenchmarkFutexSendRecv(b *testing.B) {
|
|
benchmarkSendRecv(b, ControlModeFutex)
|
|
}
|