mirror of
https://github.com/gortc/stun.git
synced 2025-10-05 16:47:09 +08:00
195 lines
3.7 KiB
Go
195 lines
3.7 KiB
Go
package stun
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
type TestAgent struct {
|
|
f chan Handler
|
|
}
|
|
|
|
func (n *TestAgent) Close() error {
|
|
close(n.f)
|
|
return nil
|
|
}
|
|
|
|
func (TestAgent) Collect(time.Time) error { return nil }
|
|
|
|
func (TestAgent) Process(m *Message) error { return nil }
|
|
|
|
func (n *TestAgent) Start(id [TransactionIDSize]byte, deadline time.Time, f Handler) error {
|
|
n.f <- f
|
|
return nil
|
|
}
|
|
|
|
func (n *TestAgent) Stop([TransactionIDSize]byte) error {
|
|
return nil
|
|
}
|
|
|
|
type noopConnection struct{}
|
|
|
|
func (noopConnection) Write(b []byte) (int, error) {
|
|
return len(b), nil
|
|
}
|
|
|
|
func (noopConnection) Read(b []byte) (int, error) {
|
|
time.Sleep(time.Millisecond)
|
|
return 0, io.EOF
|
|
}
|
|
|
|
func (noopConnection) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func BenchmarkClient_Do(b *testing.B) {
|
|
b.ReportAllocs()
|
|
agent := &TestAgent{
|
|
f: make(chan Handler, 1000),
|
|
}
|
|
client := NewClient(ClientOptions{
|
|
Agent: agent,
|
|
Connection: noopConnection{},
|
|
})
|
|
defer client.Close()
|
|
go func() {
|
|
e := Event{
|
|
Error: nil,
|
|
Message: nil,
|
|
}
|
|
for f := range agent.f {
|
|
f.HandleEvent(e)
|
|
}
|
|
}()
|
|
m := new(Message)
|
|
m.Encode()
|
|
noopF := func(event Event) {
|
|
// pass
|
|
}
|
|
for i := 0; i < b.N; i++ {
|
|
if err := client.Do(m, time.Time{}, noopF); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
type testConnection struct {
|
|
write func([]byte) (int, error)
|
|
b []byte
|
|
stopped bool
|
|
}
|
|
|
|
func (t *testConnection) Write(b []byte) (int, error) {
|
|
return t.write(b)
|
|
}
|
|
|
|
func (t *testConnection) Close() error {
|
|
if t.stopped {
|
|
return errors.New("already stopped")
|
|
}
|
|
t.stopped = true
|
|
return nil
|
|
}
|
|
|
|
func (t *testConnection) Read(b []byte) (int, error) {
|
|
if t.stopped {
|
|
return 0, io.EOF
|
|
}
|
|
return copy(b, t.b), nil
|
|
}
|
|
|
|
func TestClosedOrPanic(t *testing.T) {
|
|
closedOrPanic(nil)
|
|
closedOrPanic(ErrAgentClosed)
|
|
func() {
|
|
defer func() {
|
|
r := recover()
|
|
if r != io.EOF {
|
|
t.Error(r)
|
|
}
|
|
}()
|
|
closedOrPanic(io.EOF)
|
|
}()
|
|
}
|
|
|
|
func TestClient_Do(t *testing.T) {
|
|
response := MustBuild(TransactionID, BindingSuccess)
|
|
response.Encode()
|
|
conn := &testConnection{
|
|
b: response.Raw,
|
|
write: func(bytes []byte) (int, error) {
|
|
return len(bytes), nil
|
|
},
|
|
}
|
|
c := NewClient(ClientOptions{
|
|
Connection: conn,
|
|
})
|
|
defer func() {
|
|
if err := c.Close(); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := c.Close(); err == nil {
|
|
t.Error("second close should fail")
|
|
}
|
|
}()
|
|
m := MustBuild(
|
|
NewTransactionIDSetter(response.TransactionID),
|
|
)
|
|
d := time.Now().Add(time.Second)
|
|
if err := c.Do(m, d, func(event Event) {
|
|
if event.Error != nil {
|
|
t.Error(event.Error)
|
|
}
|
|
}); err != nil {
|
|
t.Error(err)
|
|
}
|
|
m = MustBuild(TransactionID)
|
|
if err := c.Do(m, d, nil); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestCloseErr_Error(t *testing.T) {
|
|
for id, c := range []struct {
|
|
Err CloseErr
|
|
Out string
|
|
}{
|
|
{CloseErr{}, "failed to close: <nil> (connection), <nil> (agent)"},
|
|
{CloseErr{
|
|
AgentErr: io.ErrUnexpectedEOF,
|
|
}, "failed to close: <nil> (connection), unexpected EOF (agent)"},
|
|
{CloseErr{
|
|
ConnectionErr: io.ErrUnexpectedEOF,
|
|
}, "failed to close: unexpected EOF (connection), <nil> (agent)"},
|
|
} {
|
|
if out := c.Err.Error(); out != c.Out {
|
|
t.Errorf("[%d]: Error(%#v) %q (got) != %q (expected)",
|
|
id, c.Err, out, c.Out,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStopErr_Error(t *testing.T) {
|
|
for id, c := range []struct {
|
|
Err StopErr
|
|
Out string
|
|
}{
|
|
{StopErr{}, "error while stopping due to <nil>: <nil>"},
|
|
{StopErr{
|
|
Err: io.ErrUnexpectedEOF,
|
|
}, "error while stopping due to <nil>: unexpected EOF"},
|
|
{StopErr{
|
|
Cause: io.ErrUnexpectedEOF,
|
|
}, "error while stopping due to unexpected EOF: <nil>"},
|
|
} {
|
|
if out := c.Err.Error(); out != c.Out {
|
|
t.Errorf("[%d]: Error(%#v) %q (got) != %q (expected)",
|
|
id, c.Err, out, c.Out,
|
|
)
|
|
}
|
|
}
|
|
}
|