Update to pion/transport@v0.8.10

Tests now assert for routine leaks on startup as well
This commit is contained in:
Sean DuBois
2019-10-31 01:00:28 -07:00
committed by Sean DuBois
parent c571ca90fe
commit e161aa966e
9 changed files with 121 additions and 101 deletions
+10
View File
@@ -331,6 +331,13 @@ func NewAgent(config *AgentConfig) (*Agent, error) {
if err != nil {
return nil, err
}
closeMDNSConn := func() {
if mDNSConn != nil {
if mdnsCloseErr := mDNSConn.Close(); mdnsCloseErr != nil {
log.Warnf("Failed to close mDNS: %v", mdnsCloseErr)
}
}
}
a := &Agent{
tieBreaker: rand.New(rand.NewSource(time.Now().UnixNano())).Uint64(),
@@ -384,14 +391,17 @@ func NewAgent(config *AgentConfig) (*Agent, error) {
a.buffer.SetLimitSize(maxBufferSize)
if a.lite && (len(a.candidateTypes) != 1 || a.candidateTypes[0] != CandidateTypeHost) {
closeMDNSConn()
return nil, ErrLiteUsingNonHostCandidates
}
if config.Urls != nil && len(config.Urls) > 0 && !containsCandidateType(CandidateTypeServerReflexive, a.candidateTypes) && !containsCandidateType(CandidateTypeRelay, a.candidateTypes) {
closeMDNSConn()
return nil, ErrUselessUrlsProvided
}
if err = a.initExtIPMapping(config); err != nil {
closeMDNSConn()
return nil, err
}
+60 -55
View File
@@ -47,11 +47,7 @@ func TestPairSearch(t *testing.T) {
t.Fatalf("No Candidate pairs should exist")
}
err = a.Close()
if err != nil {
t.Fatalf("Close agent emits error %v", err)
}
assert.NoError(t, a.Close())
}
func TestPairPriority(t *testing.T) {
@@ -138,9 +134,7 @@ func TestPairPriority(t *testing.T) {
}
}
if err := a.Close(); err != nil {
t.Fatalf("Error on agent.Close(): %s", err)
}
assert.NoError(t, a.Close())
}
func TestOnSelectedCandidatePairChange(t *testing.T) {
@@ -192,6 +186,7 @@ func TestOnSelectedCandidatePairChange(t *testing.T) {
// ensure that the callback fired on setting the pair
<-callbackCalled
assert.NoError(t, a.Close())
}
type BadAddr struct{}
@@ -213,6 +208,8 @@ func runAgentTest(t *testing.T, config *AgentConfig, task func(a *Agent)) {
if err := a.run(task); err != nil {
t.Fatalf("Agent run failure: %v", err)
}
assert.NoError(t, a.Close())
}
func TestHandlePeerReflexive(t *testing.T) {
@@ -220,6 +217,9 @@ func TestHandlePeerReflexive(t *testing.T) {
lim := test.TimeOut(time.Second * 2)
defer lim.Stop()
report := test.CheckRoutines(t)
defer report()
t.Run("UDP pflx candidate from handleInbound()", func(t *testing.T) {
var config AgentConfig
runAgentTest(t, &config, func(a *Agent) {
@@ -278,11 +278,6 @@ func TestHandlePeerReflexive(t *testing.T) {
if c.Port() != 999 {
t.Fatal("Port number mismatch")
}
err = a.Close()
if err != nil {
t.Fatalf("Close agent emits error %v", err)
}
})
})
@@ -310,11 +305,6 @@ func TestHandlePeerReflexive(t *testing.T) {
if len(a.remoteCandidates) != 0 {
t.Fatal("bad address should not be added to the remote candidate list")
}
err = a.Close()
if err != nil {
t.Fatalf("Close agent emits error %v", err)
}
})
})
@@ -361,6 +351,9 @@ func TestHandlePeerReflexive(t *testing.T) {
// Assert that Agent on startup sends message, and doesn't wait for connectivityTicker to fire
// github.com/pion/ice/issues/15
func TestConnectivityOnStartup(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
stunServerURL := &URL{
Scheme: SchemeTypeSTUN,
Host: "1.2.3.4",
@@ -435,6 +428,9 @@ func TestConnectivityOnStartup(t *testing.T) {
}
func TestConnectivityLite(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
stunServerURL := &URL{
Scheme: SchemeTypeSTUN,
Host: "1.2.3.4",
@@ -511,6 +507,9 @@ func TestConnectivityLite(t *testing.T) {
}
func TestInboundValidity(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
buildMsg := func(class stun.MessageClass, username, key string) *stun.Message {
msg, err := stun.Build(stun.NewType(stun.MethodBinding, class), stun.TransactionID,
stun.NewUsername(username),
@@ -553,6 +552,7 @@ func TestInboundValidity(t *testing.T) {
t.Fatal("Binding with invalid MessageIntegrity was able to create prflx candidate")
}
assert.NoError(t, a.Close())
})
t.Run("Invalid Binding success responses should be discarded", func(t *testing.T) {
@@ -565,6 +565,8 @@ func TestInboundValidity(t *testing.T) {
if len(a.remoteCandidates) == 1 {
t.Fatal("Binding with invalid MessageIntegrity was able to create prflx candidate")
}
assert.NoError(t, a.Close())
})
t.Run("Discard non-binding messages", func(t *testing.T) {
@@ -577,6 +579,8 @@ func TestInboundValidity(t *testing.T) {
if len(a.remoteCandidates) == 1 {
t.Fatal("non-binding message was able to create prflxRemote")
}
assert.NoError(t, a.Close())
})
t.Run("Valid bind request", func(t *testing.T) {
@@ -594,9 +598,8 @@ func TestInboundValidity(t *testing.T) {
}
})
if err != nil {
t.Fatalf("Agent run failure: %v", err)
}
assert.NoError(t, err)
assert.NoError(t, a.Close())
})
t.Run("Valid bind without fingerprint", func(t *testing.T) {
@@ -644,23 +647,24 @@ func TestInboundValidity(t *testing.T) {
stun.NewShortTermIntegrity(a.remotePwd),
stun.Fingerprint,
)
if err != nil {
t.Fatal(err)
}
assert.NoError(t, err)
a.handleInbound(msg, local, remote)
if len(a.remoteCandidates) != 0 {
t.Fatal("unknown remote was able to create a candidate")
}
assert.NoError(t, a.Close())
})
}
func TestInvalidAgentStarts(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
a, err := NewAgent(&AgentConfig{})
if err != nil {
t.Fatal(err)
}
assert.NoError(t, err)
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
@@ -681,6 +685,8 @@ func TestInvalidAgentStarts(t *testing.T) {
if _, err = a.Dial(context.TODO(), "foo", "bar"); err != nil && err != ErrMultipleStart {
t.Fatal(err)
}
assert.NoError(t, a.Close())
}
// Assert that Agent emits Connecting/Connected/Disconnected/Closed messages
@@ -688,6 +694,9 @@ func TestConnectionStateCallback(t *testing.T) {
lim := test.TimeOut(time.Second * 5)
defer lim.Stop()
report := test.CheckRoutines(t)
defer report()
var wg sync.WaitGroup
wg.Add(2)
@@ -762,13 +771,9 @@ func TestConnectionStateCallback(t *testing.T) {
<-isChecking
<-isConnected
<-isDisconnected
if err = aAgent.Close(); err != nil {
t.Error(err)
}
if err = bAgent.Close(); err != nil {
t.Error(err)
}
assert.NoError(t, aAgent.Close())
assert.NoError(t, bAgent.Close())
<-isClosed
}
@@ -784,10 +789,14 @@ func TestInvalidGather(t *testing.T) {
if err != ErrNoOnCandidateHandler {
t.Fatal("trickle GatherCandidates succeeded without OnCandidate")
}
assert.NoError(t, a.Close())
})
}
func TestCandidatePairStats(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
// avoid deadlocks?
defer test.TimeOut(1 * time.Second).Stop()
@@ -914,12 +923,13 @@ func TestCandidatePairStats(t *testing.T) {
prflxPairStat.State.String())
}
if err := a.Close(); err != nil {
t.Fatalf("Error on agent.Close(): %s", err)
}
assert.NoError(t, a.Close())
}
func TestLocalCandidateStats(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
// avoid deadlocks?
defer test.TimeOut(1 * time.Second).Stop()
@@ -994,12 +1004,13 @@ func TestLocalCandidateStats(t *testing.T) {
t.Fatal("missing srflx local stat")
}
if err := a.Close(); err != nil {
t.Fatalf("Error on agent.Close(): %s", err)
}
assert.NoError(t, a.Close())
}
func TestRemoteCandidateStats(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
// avoid deadlocks?
defer test.TimeOut(1 * time.Second).Stop()
@@ -1113,25 +1124,15 @@ func TestRemoteCandidateStats(t *testing.T) {
t.Fatal("missing host remote stat")
}
if err := a.Close(); err != nil {
t.Fatalf("Error on agent.Close(): %s", err)
}
assert.NoError(t, a.Close())
}
func TestInitExtIPMapping(t *testing.T) {
var a *Agent
var err error
var closeAgent = func() {
if a != nil {
if err = a.Close(); err != nil {
t.Fatalf("failed to close agent: %v", err)
}
}
}
report := test.CheckRoutines(t)
defer report()
// a.extIPMapper should be nil by default
a, err = NewAgent(&AgentConfig{
a, err := NewAgent(&AgentConfig{
Trickle: true, // to avoid starting gathering candidates
})
if err != nil {
@@ -1140,7 +1141,7 @@ func TestInitExtIPMapping(t *testing.T) {
if a.extIPMapper != nil {
t.Fatal("a.extIPMapper should be nil by default")
}
closeAgent()
assert.NoError(t, a.Close())
// a.extIPMapper should be nil when NAT1To1IPs is a non-nil empty array
a, err = NewAgent(&AgentConfig{
@@ -1154,7 +1155,7 @@ func TestInitExtIPMapping(t *testing.T) {
if a.extIPMapper != nil {
t.Fatal("a.extIPMapper should be nil by default")
}
closeAgent()
assert.NoError(t, a.Close())
// NewAgent should return an error when 1:1 NAT for host candidate is enabled
// but the candidate type does not appear in the CandidateTypes.
@@ -1204,6 +1205,9 @@ func TestInitExtIPMapping(t *testing.T) {
}
func TestBindingRequestTimeout(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
const expectedRemovalCount = 2
a, err := NewAgent(&AgentConfig{})
@@ -1225,4 +1229,5 @@ func TestBindingRequestTimeout(t *testing.T) {
a.invalidatePendingBindingRequests(now)
assert.Equal(t, len(a.pendingBindingRequests), expectedRemovalCount, "Binding invalidation due to timeout did not remove the correct number of binding requests")
assert.NoError(t, a.Close())
}
+4 -9
View File
@@ -8,6 +8,7 @@ import (
"github.com/pion/logging"
"github.com/pion/transport/test"
"github.com/pion/turn"
"github.com/stretchr/testify/assert"
)
func optimisticAuthHandler(username string, srcAddr net.Addr) (password string, ok bool) {
@@ -80,13 +81,7 @@ func TestRelayOnlyConnection(t *testing.T) {
<-aConnected
<-bConnected
if err = aAgent.Close(); err != nil {
t.Fatal(err)
}
if err = bAgent.Close(); err != nil {
t.Fatal(err)
}
if err = server.Close(); err != nil {
t.Fatal(err)
}
assert.NoError(t, aAgent.Close())
assert.NoError(t, bAgent.Close())
assert.NoError(t, server.Close())
}
+4
View File
@@ -8,6 +8,7 @@ import (
"time"
"github.com/pion/logging"
"github.com/pion/transport/test"
"github.com/pion/transport/vnet"
"github.com/pion/turn"
"github.com/stretchr/testify/assert"
@@ -297,6 +298,9 @@ func closePipe(t *testing.T, ca *Conn, cb *Conn) bool {
}
func TestConnectivityVNet(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
stunServerURL := &URL{
Scheme: SchemeTypeSTUN,
Host: "1.2.3.4",
+4
View File
@@ -6,6 +6,8 @@ import (
"sort"
"strconv"
"testing"
"github.com/stretchr/testify/assert"
)
func TestListenUDP(t *testing.T) {
@@ -90,4 +92,6 @@ func TestListenUDP(t *testing.T) {
if err != ErrPort {
t.Fatalf("listenUDP with port restriction [%d, %d], did not return ErrPort", portMin, portMax)
}
assert.NoError(t, a.Close())
}
+25 -16
View File
@@ -6,11 +6,15 @@ import (
"testing"
"github.com/pion/logging"
"github.com/pion/transport/test"
"github.com/pion/transport/vnet"
"github.com/stretchr/testify/assert"
)
func TestVNetGather(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
loggerFactory := logging.NewDefaultLoggerFactory()
//log := loggerFactory.NewLogger("test")
@@ -18,9 +22,7 @@ func TestVNetGather(t *testing.T) {
a, err := NewAgent(&AgentConfig{
Net: vnet.NewNet(&vnet.NetConfig{}),
})
if err != nil {
t.Fatalf("Failed to create agent: %s", err)
}
assert.NoError(t, err)
localIPs, err := a.localInterfaces([]NetworkType{NetworkTypeUDP4})
if len(localIPs) > 0 {
@@ -28,6 +30,8 @@ func TestVNetGather(t *testing.T) {
} else if err != nil {
t.Fatal(err)
}
assert.NoError(t, a.Close())
})
t.Run("Gather a dynamic IP address", func(t *testing.T) {
@@ -58,9 +62,7 @@ func TestVNetGather(t *testing.T) {
a, err := NewAgent(&AgentConfig{
Net: nw,
})
if err != nil {
t.Fatalf("Failed to create agent: %s", err)
}
assert.NoError(t, err)
localIPs, err := a.localInterfaces([]NetworkType{NetworkTypeUDP4})
if len(localIPs) == 0 {
@@ -77,6 +79,8 @@ func TestVNetGather(t *testing.T) {
t.Fatal("should be contained in the CIDR")
}
}
assert.NoError(t, a.Close())
})
t.Run("listenUDP", func(t *testing.T) {
@@ -141,14 +145,16 @@ func TestVNetGather(t *testing.T) {
} else if port != "5000" {
t.Fatalf("listenUDP with port restriction of 5000 listened on incorrect port (%s)", port)
}
err = conn.Close()
if err != nil {
t.Fatalf("failed to close conn")
}
assert.NoError(t, conn.Close())
assert.NoError(t, a.Close())
})
}
func TestVNetGatherWithNAT1To1(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
loggerFactory := logging.NewDefaultLoggerFactory()
log := loggerFactory.NewLogger("test")
@@ -345,6 +351,9 @@ func TestVNetGatherWithNAT1To1(t *testing.T) {
}
func TestVNetGatherWithInterfaceFilter(t *testing.T) {
report := test.CheckRoutines(t)
defer report()
loggerFactory := logging.NewDefaultLoggerFactory()
r, err := vnet.NewRouter(&vnet.RouterConfig{
CIDR: "1.2.3.0/24",
@@ -371,9 +380,7 @@ func TestVNetGatherWithInterfaceFilter(t *testing.T) {
return false
},
})
if err != nil {
t.Fatalf("Failed to create agent: %s", err)
}
assert.NoError(t, err)
localIPs, err := a.localInterfaces([]NetworkType{NetworkTypeUDP4})
if err != nil {
@@ -381,6 +388,8 @@ func TestVNetGatherWithInterfaceFilter(t *testing.T) {
} else if len(localIPs) != 0 {
t.Fatal("InterfaceFilter should have excluded everything")
}
assert.NoError(t, a.Close())
})
t.Run("InterfaceFilter should not exclude the interface", func(t *testing.T) {
@@ -391,9 +400,7 @@ func TestVNetGatherWithInterfaceFilter(t *testing.T) {
return true
},
})
if err != nil {
t.Fatalf("Failed to create agent: %s", err)
}
assert.NoError(t, err)
localIPs, err := a.localInterfaces([]NetworkType{NetworkTypeUDP4})
if err != nil {
@@ -401,5 +408,7 @@ func TestVNetGatherWithInterfaceFilter(t *testing.T) {
} else if len(localIPs) == 0 {
t.Fatal("InterfaceFilter should not have excluded anything")
}
assert.NoError(t, a.Close())
})
}
+3 -3
View File
@@ -6,9 +6,9 @@ require (
github.com/pion/logging v0.2.2
github.com/pion/mdns v0.0.3
github.com/pion/stun v0.3.3
github.com/pion/transport v0.8.9
github.com/pion/transport v0.8.10
github.com/pion/turn v1.4.0
github.com/stretchr/testify v1.4.0
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24 // indirect
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c // indirect
)
+6 -6
View File
@@ -15,8 +15,9 @@ github.com/pion/mdns v0.0.3 h1:DxdOYd0pgwLKiDlIIxfU0qdG5iWh1Xn6CsS9vc6cMAY=
github.com/pion/mdns v0.0.3/go.mod h1:VrN3wefVgtfL8QgpEblPUC46ag1reLIfpqekCnKunLE=
github.com/pion/stun v0.3.3 h1:brYuPl9bN9w/VM7OdNzRSLoqsnwlyNvD9MVeJrHjDQw=
github.com/pion/stun v0.3.3/go.mod h1:xrCld6XM+6GWDZdvjPlLMsTU21rNxnO6UO8XsAvHr/M=
github.com/pion/transport v0.8.9 h1:3PUZULb0WZd/QNfXKKMwcUHzLR+XfNem6lF2M9UrxSU=
github.com/pion/transport v0.8.9/go.mod h1:lpeSM6KJFejVtZf8k0fgeN7zE73APQpTF83WvA1FVP8=
github.com/pion/transport v0.8.10 h1:lTiobMEw2PG6BH/mgIVqTV2mBp/mPT+IJLaN8ZxgdHk=
github.com/pion/transport v0.8.10/go.mod h1:tBmha/UCjpum5hqTWhfAEs3CO4/tHSg0MYRhSzR+CZ8=
github.com/pion/turn v1.4.0 h1:7NUMRehQz4fIo53Qv9ui1kJ0Kr1CA82I81RHKHCeM80=
github.com/pion/turn v1.4.0/go.mod h1:aDSi6hWX/hd1+gKia9cExZOR0MU95O7zX9p3Gw/P2aU=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
@@ -24,19 +25,18 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b h1:lkjdUzSyJ5P1+eal9fxXX9Xg2BTfswsonKUse48C0uE=
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA=
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271 h1:N66aaryRB3Ax92gH0v3hp1QYZ3zWWCCUR/j8Ifh45Ss=
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24 h1:R8bzl0244nw47n1xKs1MUMAaTNgjavKcN/aX2Ss3+Fo=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c h1:S/FtSvpNLtFBgjTqcKsRpsa6aVsI6iztaz1bQd9BJwE=
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
+5 -12
View File
@@ -5,6 +5,7 @@ import (
"time"
"github.com/pion/transport/test"
"github.com/stretchr/testify/assert"
)
func TestMulticastDNSOnlyConnection(t *testing.T) {
@@ -45,12 +46,8 @@ func TestMulticastDNSOnlyConnection(t *testing.T) {
<-aConnected
<-bConnected
if err = aAgent.Close(); err != nil {
t.Fatal(err)
}
if err = bAgent.Close(); err != nil {
t.Fatal(err)
}
assert.NoError(t, aAgent.Close())
assert.NoError(t, bAgent.Close())
}
func TestMulticastDNSMixedConnection(t *testing.T) {
@@ -93,10 +90,6 @@ func TestMulticastDNSMixedConnection(t *testing.T) {
<-aConnected
<-bConnected
if err = aAgent.Close(); err != nil {
t.Fatal(err)
}
if err = bAgent.Close(); err != nil {
t.Fatal(err)
}
assert.NoError(t, aAgent.Close())
assert.NoError(t, bAgent.Close())
}