build: remove dep meta files, readd vendor directory
This commit is contained in:
parent
a74d57e7fc
commit
1c6e3b1c9d
39
Gopkg.lock
generated
39
Gopkg.lock
generated
@ -1,39 +0,0 @@
|
|||||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
|
||||||
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "code.ivysaur.me/libnmdc"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "a23cc9e61d24bb9b16b1126bdddd514e01d64792"
|
|
||||||
version = "v0.16.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/cxmcc/tiger"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "bde35e2713d7f674987c2ecb21a6b0fc33749516"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/googollee/go-engine.io"
|
|
||||||
packages = [".","message","parser","polling","transport","websocket"]
|
|
||||||
revision = "80ae0e43aca17b4c5a6834999d0f2eaa16b9afda"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/googollee/go-socket.io"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "5447e71f36d394766bf855d5714a487596809f0d"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/gorilla/websocket"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
|
|
||||||
version = "v1.2.0"
|
|
||||||
|
|
||||||
[solve-meta]
|
|
||||||
analyzer-name = "dep"
|
|
||||||
analyzer-version = 1
|
|
||||||
inputs-digest = "7ac2438222289730d49b803fd1c631629921f95fd406c3154a54d34e11fb6947"
|
|
||||||
solver-name = "gps-cdcl"
|
|
||||||
solver-version = 1
|
|
30
Gopkg.toml
30
Gopkg.toml
@ -1,30 +0,0 @@
|
|||||||
|
|
||||||
# Gopkg.toml example
|
|
||||||
#
|
|
||||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
|
||||||
# for detailed Gopkg.toml documentation.
|
|
||||||
#
|
|
||||||
# required = ["github.com/user/thing/cmd/thing"]
|
|
||||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
|
||||||
#
|
|
||||||
# [[constraint]]
|
|
||||||
# name = "github.com/user/project"
|
|
||||||
# version = "1.0.0"
|
|
||||||
#
|
|
||||||
# [[constraint]]
|
|
||||||
# name = "github.com/user/project2"
|
|
||||||
# branch = "dev"
|
|
||||||
# source = "github.com/myfork/project2"
|
|
||||||
#
|
|
||||||
# [[override]]
|
|
||||||
# name = "github.com/x/y"
|
|
||||||
# version = "2.4.0"
|
|
||||||
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "code.ivysaur.me/libnmdc"
|
|
||||||
version = "0.16.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/googollee/go-socket.io"
|
|
58
vendor/code.ivysaur.me/libnmdc/Example_test.go
generated
vendored
58
vendor/code.ivysaur.me/libnmdc/Example_test.go
generated
vendored
@ -1,58 +0,0 @@
|
|||||||
package libnmdc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleHubConnectionOptions_Connect() {
|
|
||||||
opts := HubConnectionOptions{
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Self: NewUserInfo("slowpoke9"),
|
|
||||||
}
|
|
||||||
|
|
||||||
events := make(chan HubEvent, 0)
|
|
||||||
hub := ConnectAsync(&opts, events)
|
|
||||||
|
|
||||||
for event := range events {
|
|
||||||
switch event.EventType {
|
|
||||||
case EVENT_CONNECTION_STATE_CHANGED:
|
|
||||||
fmt.Printf("Connection -- %s (%s)\n", event.StateChange, event.Message)
|
|
||||||
|
|
||||||
case EVENT_PUBLIC:
|
|
||||||
fmt.Printf("Message from '%s': '%s'\n", event.Nick, event.Message)
|
|
||||||
if event.Message == "how are you" {
|
|
||||||
hub.SayPublic("good thanks!")
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
fmt.Printf("%+v\n", event)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleHubConnectionOptions_ConnectSync() {
|
|
||||||
cb := func(hub *HubConnection, event HubEvent) {
|
|
||||||
switch event.EventType {
|
|
||||||
case EVENT_CONNECTION_STATE_CHANGED:
|
|
||||||
fmt.Printf("Connection -- %s (%s)\n", event.StateChange, event.Message)
|
|
||||||
|
|
||||||
case EVENT_PUBLIC:
|
|
||||||
fmt.Printf("Message from '%s': '%s'\n", event.Nick, event.Message)
|
|
||||||
if event.Message == "how are you" {
|
|
||||||
hub.SayPublic("good thanks!")
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
fmt.Printf("%+v\n", event)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
opts := HubConnectionOptions{
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Self: NewUserInfo("slowpoke9"),
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectSync(&opts, cb) // blocking
|
|
||||||
}
|
|
97
vendor/code.ivysaur.me/libnmdc/NmdcProtocol_test.go
generated
vendored
97
vendor/code.ivysaur.me/libnmdc/NmdcProtocol_test.go
generated
vendored
@ -1,97 +0,0 @@
|
|||||||
package libnmdc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMyINFOParse(t *testing.T) {
|
|
||||||
|
|
||||||
np := NewNmdcProtocol(nil).(*NmdcProtocol)
|
|
||||||
|
|
||||||
type myInfoTestPair struct {
|
|
||||||
in string
|
|
||||||
expect UserInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
cases := []myInfoTestPair{
|
|
||||||
|
|
||||||
myInfoTestPair{
|
|
||||||
in: "$ALL Bxxxy description<ApexDC++ V:1.4.3,M:P,H:9/0/2,S:1>$ $0.01\x01$xyz@example.com$53054999578$",
|
|
||||||
expect: UserInfo{
|
|
||||||
Nick: "Bxxxy",
|
|
||||||
Description: "description",
|
|
||||||
ClientTag: "ApexDC++",
|
|
||||||
ClientVersion: "1.4.3",
|
|
||||||
Email: "xyz@example.com",
|
|
||||||
ShareSize: 53054999578,
|
|
||||||
Flag: FLAG_NORMAL,
|
|
||||||
Slots: 1,
|
|
||||||
HubsUnregistered: 9,
|
|
||||||
HubsRegistered: 0,
|
|
||||||
HubsOperator: 2,
|
|
||||||
UserInfo_NMDCOnly: UserInfo_NMDCOnly{
|
|
||||||
ConnectionMode: CONNECTIONMODE_PASSIVE,
|
|
||||||
Speed: "0.0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
myInfoTestPair{
|
|
||||||
in: "$ALL ixxxxxxx0 $P$10A$$0$",
|
|
||||||
expect: UserInfo{
|
|
||||||
Nick: "ixxxxxxx0",
|
|
||||||
ClientVersion: "0", // Auto-inserted by the parser for short-format MyINFO strings
|
|
||||||
Flag: UserFlag(rune('A')),
|
|
||||||
UserInfo_NMDCOnly: UserInfo_NMDCOnly{
|
|
||||||
ConnectionMode: CONNECTIONMODE_PASSIVE,
|
|
||||||
Speed: "1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
myInfoTestPair{
|
|
||||||
in: "$ALL SXXXX_XXXXXXR <ncdc V:1.19.1-12-g5561,M:P,H:1/0/0,S:10>$ $0.005Q$$0$",
|
|
||||||
expect: UserInfo{
|
|
||||||
Nick: "SXXXX_XXXXXXR",
|
|
||||||
ClientTag: "ncdc",
|
|
||||||
ClientVersion: "1.19.1-12-g5561",
|
|
||||||
Flag: UserFlag(rune('Q')),
|
|
||||||
Slots: 10,
|
|
||||||
HubsUnregistered: 1,
|
|
||||||
UserInfo_NMDCOnly: UserInfo_NMDCOnly{
|
|
||||||
ConnectionMode: CONNECTIONMODE_PASSIVE,
|
|
||||||
Speed: "0.00",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
myInfoTestPair{
|
|
||||||
in: "$ALL mxxxu desccccc<HexChat V:2.12.1,M:P,H:1/0/0,S:0>$ $p$$0$",
|
|
||||||
expect: UserInfo{
|
|
||||||
Nick: "mxxxu",
|
|
||||||
Description: "desccccc",
|
|
||||||
ClientTag: "HexChat",
|
|
||||||
ClientVersion: "2.12.1",
|
|
||||||
Flag: UserFlag(rune('p')),
|
|
||||||
HubsUnregistered: 1,
|
|
||||||
Slots: 0,
|
|
||||||
UserInfo_NMDCOnly: UserInfo_NMDCOnly{
|
|
||||||
ConnectionMode: CONNECTIONMODE_PASSIVE,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range cases {
|
|
||||||
|
|
||||||
got, err := np.parseMyINFO(v.in)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("MyINFO parse warning (%s)", err.Error())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if *got != v.expect {
|
|
||||||
t.Errorf("MyINFO parse failure\nExpected:\n%+v\nGot:\n%+v\n", v.expect, got)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
98
vendor/code.ivysaur.me/libnmdc/__dist/README.txt
generated
vendored
98
vendor/code.ivysaur.me/libnmdc/__dist/README.txt
generated
vendored
@ -1,98 +0,0 @@
|
|||||||
An NMDC / ADC client protocol library for Golang.
|
|
||||||
|
|
||||||
Written in golang
|
|
||||||
Tags: nmdc
|
|
||||||
|
|
||||||
=FEATURES=
|
|
||||||
|
|
||||||
- Connect to NMDC and ADC hubs
|
|
||||||
- SSL (NMDCS/ADCS) with option to ignore certificate validity
|
|
||||||
- Autodetect NMDC/ADC protocol by timeout
|
|
||||||
- Send public and private chat messages, UserCommand support
|
|
||||||
- Protocol keepalives
|
|
||||||
- Parse user details (including UserIP2 for NMDC)
|
|
||||||
- Fast NMDC login via NoHello and QuickList
|
|
||||||
- Both synchronous (callback) and asynchronous (channel) -based APIs, including example
|
|
||||||
|
|
||||||
=GO GET=
|
|
||||||
|
|
||||||
This package can be installed via go get: `go get code.ivysaur.me/libnmdc`
|
|
||||||
[go-get]code.ivysaur.me/libnmdc git https://git.ivysaur.me/code.ivysaur.me/libnmdc.git[/go-get]
|
|
||||||
|
|
||||||
=CHANGELOG=
|
|
||||||
|
|
||||||
2017-11-26 0.16
|
|
||||||
- Feature: Support connecting to ADC hubs
|
|
||||||
- BREAKING: Simplify connection API
|
|
||||||
- Vendor new dependency on github.com/cxmcc/tiger (MIT license)
|
|
||||||
|
|
||||||
2017-11-14 0.15
|
|
||||||
- Feature: Fallback reconnection if no data (not even keepalives) are recieved from the hub in 24 hours
|
|
||||||
- Fix an issue with detecting protocol messages inside multi-line chat messages
|
|
||||||
- Update examples and the default client version number
|
|
||||||
|
|
||||||
2017-02-09 0.14
|
|
||||||
- Fix an issue with crashing on malformed IP addresses supplied by the hub
|
|
||||||
|
|
||||||
2017-02-09 0.13
|
|
||||||
- Feature: Implement UserIP2 extension, to retrieve IP addresses of other users
|
|
||||||
- Enhancement: Implement QuickList extension (reduce one network roundtrip during initial connection)
|
|
||||||
- Enhancement: Implement NoHello extension (faster connection performance)
|
|
||||||
- Enhancement: Implement ChatOnly extension
|
|
||||||
- Fix an issue with not notifying client on all MyINFO updates
|
|
||||||
|
|
||||||
2017-02-05 0.12
|
|
||||||
- Fix an issue with mutex deadlock when accessing user information from a callback
|
|
||||||
- Fix an issue with silent disconnection if a password was required but not present
|
|
||||||
|
|
||||||
2016-11-29 0.11
|
|
||||||
- BREAKING: Remove some exported methods
|
|
||||||
- BREAKING: Fix an issue with missing sufficient parameters in the synchronous API
|
|
||||||
- Enhancement: Improve output under godoc
|
|
||||||
- Fix an issue with special characters appearing in recieved private messages
|
|
||||||
- Fix an issue with parsing active/passive connection modes
|
|
||||||
- Fix an issue with errors appearing on stdout
|
|
||||||
|
|
||||||
2016-10-08 r10
|
|
||||||
- Feature: Support `$UserCommand`
|
|
||||||
|
|
||||||
2016-08-27 r9
|
|
||||||
- Fix an issue with parsing MyINFO strings with zero-length speed descriptions
|
|
||||||
- Fix an issue with not storing updated profile information
|
|
||||||
|
|
||||||
2016-05-10 r8
|
|
||||||
- Enhancement: Separate `ClientTag` and `ClientVersion` in `UserInfo` structs
|
|
||||||
|
|
||||||
2016-05-08 r7
|
|
||||||
- BREAKING: Remove direct access to `HubConnection.Users` map
|
|
||||||
- Feature: Threadsafe user map accessor
|
|
||||||
- Feature: Option to disable auto-reconnection
|
|
||||||
- Feature: New `Disconnect()`, `UserCount()`, `UserExists()` functions
|
|
||||||
- Enhancement: Support `$OpList`, add `IsOperator` member to `UserInfo` structs
|
|
||||||
- Refactor into multiple files
|
|
||||||
|
|
||||||
2016-04-16 r6
|
|
||||||
- Fix an issue with calling `panic()` on certain types of abnormal network failure
|
|
||||||
|
|
||||||
2016-04-04 r5
|
|
||||||
- Enhancement: Support protocol keepalives
|
|
||||||
- Enhancement: Support hub redirects (`$ForceMove`)
|
|
||||||
|
|
||||||
2016-04-03 r4
|
|
||||||
- Feature: Add synchronous API
|
|
||||||
- Fix an issue with reading HubConnection's state parameter
|
|
||||||
- Fix an issue with buffered protocol commands
|
|
||||||
|
|
||||||
2016-04-03 r3
|
|
||||||
- Feature: Add `SkipVerifyTLS` option
|
|
||||||
- Fix an issue with calling `panic()` if connection failed
|
|
||||||
|
|
||||||
2016-04-02 r2
|
|
||||||
- Enhancement: Support NMDC-over-TLS (NMDCS)
|
|
||||||
- Fix an issue recieving private messages
|
|
||||||
- Fix an issue with calling `panic()` if connection failed
|
|
||||||
- Fix an issue parsing URIs without a specified port
|
|
||||||
- Move sample content into directory with excluded build
|
|
||||||
|
|
||||||
2016-02-12 r1
|
|
||||||
- Initial public release
|
|
36
vendor/code.ivysaur.me/libnmdc/tth_test.go
generated
vendored
36
vendor/code.ivysaur.me/libnmdc/tth_test.go
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
package libnmdc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTTH(t *testing.T) {
|
|
||||||
|
|
||||||
// echo -n 'hello world' | tthsum
|
|
||||||
testCases := [][2]string{
|
|
||||||
[2]string{"hello world", "ZIIVRZDR2FD3W4KKNMNYUU3765LPPK7BWY64CHI"},
|
|
||||||
[2]string{"", "LWPNACQDBZRYXW3VHJVCJ64QBZNGHOHHHZWCLNQ"},
|
|
||||||
[2]string{"\x00", "VK54ZIEEVTWNAUI5D5RDFIL37LX2IQNSTAXFKSA"},
|
|
||||||
[2]string{strings.Repeat("A", 1024), "L66Q4YVNAFWVS23X2HJIRA5ZJ7WXR3F26RSASFA"},
|
|
||||||
}
|
|
||||||
|
|
||||||
short := func(s string) string {
|
|
||||||
if len(s) > 15 {
|
|
||||||
return s[0:15] + "..."
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
|
||||||
input, expected := testCase[0], testCase[1]
|
|
||||||
result, err := TTH(input)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error getting TTH for '%s': %s", short(input), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if Base32(result) != expected {
|
|
||||||
t.Fatalf("Wrong TTH for '%s' (got '%s' expected '%s')", short(input), result, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
144
vendor/github.com/cxmcc/tiger/tiger_test.go
generated
vendored
144
vendor/github.com/cxmcc/tiger/tiger_test.go
generated
vendored
@ -1,144 +0,0 @@
|
|||||||
package tiger
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Test struct {
|
|
||||||
out string
|
|
||||||
in string
|
|
||||||
}
|
|
||||||
|
|
||||||
var golden = []Test{
|
|
||||||
{"3293ac630c13f0245f92bbb1766e16167a4e58492dde73f3", ""},
|
|
||||||
{"77befbef2e7ef8ab2ec8f93bf587a7fc613e247f5f247809", "a"},
|
|
||||||
{"2aab1484e8c158f2bfb8c5ff41b57a525129131c957b5f93", "abc"},
|
|
||||||
{"d981f8cb78201a950dcf3048751e441c517fca1aa55a29f6", "message digest"},
|
|
||||||
{"1714a472eee57d30040412bfcc55032a0b11602ff37beee9", "abcdefghijklmnopqrstuvwxyz"},
|
|
||||||
{"0f7bf9a19b9c58f2b7610df7e84f0ac3a71c631e7b53f78e", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
|
|
||||||
{"8dcea680a17583ee502ba38a3c368651890ffbccdc49a8cc", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
|
|
||||||
{"1c14795529fd9f207a958f84c52f11e887fa0cabdfd91bfd", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"},
|
|
||||||
{"cdf0990c5c6b6b0bddd63a75ed20e2d448bf44e15fde0df4", strings.Repeat("A", 1024)},
|
|
||||||
{"89292aee0f82842abc080c57b3aadd9ca84d66bf0cae77aa", strings.Repeat("A", 1025)},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGolden(t *testing.T) {
|
|
||||||
for i := 0; i < len(golden); i++ {
|
|
||||||
g := golden[i]
|
|
||||||
c := New()
|
|
||||||
buf := make([]byte, len(g.in)+4)
|
|
||||||
for j := 0; j < 7; j++ {
|
|
||||||
if j < 2 {
|
|
||||||
io.WriteString(c, g.in)
|
|
||||||
} else if j == 2 {
|
|
||||||
io.WriteString(c, g.in[0:len(g.in)/2])
|
|
||||||
c.Sum(nil)
|
|
||||||
io.WriteString(c, g.in[len(g.in)/2:])
|
|
||||||
} else if j > 2 {
|
|
||||||
// test unaligned write
|
|
||||||
buf = buf[1:]
|
|
||||||
copy(buf, g.in)
|
|
||||||
c.Write(buf[:len(g.in)])
|
|
||||||
}
|
|
||||||
s := fmt.Sprintf("%x", c.Sum(nil))
|
|
||||||
if s != g.out {
|
|
||||||
t.Fatalf("tiger[%d](%s) = %s want %s", j, g.in, s, g.out)
|
|
||||||
}
|
|
||||||
c.Reset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type WriteTest struct {
|
|
||||||
out int
|
|
||||||
in string
|
|
||||||
}
|
|
||||||
|
|
||||||
var writeTestVectors = []WriteTest{
|
|
||||||
{0, ""},
|
|
||||||
{1, "A"},
|
|
||||||
{2, "AA"},
|
|
||||||
{10, strings.Repeat("A", 10)},
|
|
||||||
{1024, strings.Repeat("A", 1024)},
|
|
||||||
{1025, strings.Repeat("A", 1025)},
|
|
||||||
{0, ""},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWriteReturnsCorrectSize(t *testing.T) {
|
|
||||||
c := New()
|
|
||||||
for i := 0; i < len(writeTestVectors); i++ {
|
|
||||||
v := writeTestVectors[i]
|
|
||||||
b := []byte(v.in)
|
|
||||||
length, err := c.Write(b[:len(v.in)])
|
|
||||||
if length != v.out {
|
|
||||||
t.Fatalf("Write() = %d want %d", length, v.out)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Write(%s) failed.", v.in)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleNew() {
|
|
||||||
h := New()
|
|
||||||
io.WriteString(h, "It's the eye of the tiger, it's the thrill of the fight")
|
|
||||||
io.WriteString(h, "Rising up to the challenge of our rival!")
|
|
||||||
fmt.Printf("%x", h.Sum(nil))
|
|
||||||
// Output: a7bbad36cc17918e399ae8ee893e4595e4d24e1639fe822c
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleNew2() {
|
|
||||||
h := New2()
|
|
||||||
io.WriteString(h, "It's the eye of the tiger, it's the thrill of the fight")
|
|
||||||
io.WriteString(h, "Rising up to the challenge of our rival!")
|
|
||||||
fmt.Printf("%x", h.Sum(nil))
|
|
||||||
// Output: c86695c2a639506682de2c12c2d23b61a12db78ea1ee1001
|
|
||||||
}
|
|
||||||
|
|
||||||
var bench = New()
|
|
||||||
var buf = make([]byte, 8192+1)
|
|
||||||
var sum = make([]byte, bench.Size())
|
|
||||||
|
|
||||||
func benchmarkSize(b *testing.B, size int, unaligned bool) {
|
|
||||||
b.SetBytes(int64(size))
|
|
||||||
buf := buf
|
|
||||||
if unaligned {
|
|
||||||
if uintptr(unsafe.Pointer(&buf[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
|
|
||||||
buf = buf[1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
bench.Reset()
|
|
||||||
bench.Write(buf[:size])
|
|
||||||
bench.Sum(sum[:0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkHash8Bytes(b *testing.B) {
|
|
||||||
benchmarkSize(b, 8, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkHash1K(b *testing.B) {
|
|
||||||
benchmarkSize(b, 1024, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkHash8K(b *testing.B) {
|
|
||||||
benchmarkSize(b, 8192, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkHash8BytesUnaligned(b *testing.B) {
|
|
||||||
benchmarkSize(b, 8, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkHash1KUnaligned(b *testing.B) {
|
|
||||||
benchmarkSize(b, 1024, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkHash8KUnaligned(b *testing.B) {
|
|
||||||
benchmarkSize(b, 8192, true)
|
|
||||||
}
|
|
14
vendor/github.com/googollee/go-engine.io/example/asset/index.html
generated
vendored
14
vendor/github.com/googollee/go-engine.io/example/asset/index.html
generated
vendored
@ -1,14 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>EIO Latency</title>
|
|
||||||
<link rel="stylesheet" href="/style.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>EIO Latency <span id="latency"></span></h1>
|
|
||||||
<h2 id="transport">(connecting)</h2>
|
|
||||||
<canvas id="chart" height="200"></canvas>
|
|
||||||
|
|
||||||
<script src="/index.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
4137
vendor/github.com/googollee/go-engine.io/example/asset/index.js
generated
vendored
4137
vendor/github.com/googollee/go-engine.io/example/asset/index.js
generated
vendored
File diff suppressed because it is too large
Load Diff
5
vendor/github.com/googollee/go-engine.io/example/asset/style.css
generated
vendored
5
vendor/github.com/googollee/go-engine.io/example/asset/style.css
generated
vendored
@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
body { margin: 0; padding: 0; font-family: Helvetica Neue; }
|
|
||||||
h1 { margin: 100px 100px 10px; }
|
|
||||||
h2 { color: #999; margin: 0 100px 30px; font-weight: normal; }
|
|
||||||
#latency { color: red; }
|
|
60
vendor/github.com/googollee/go-engine.io/example/main.go
generated
vendored
60
vendor/github.com/googollee/go-engine.io/example/main.go
generated
vendored
@ -1,60 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/googollee/go-engine.io"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
server, err := engineio.NewServer(nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
server.SetPingInterval(time.Second * 2)
|
|
||||||
server.SetPingTimeout(time.Second * 3)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
conn, _ := server.Accept()
|
|
||||||
go func() {
|
|
||||||
log.Println("connected:", conn.Id())
|
|
||||||
defer func() {
|
|
||||||
conn.Close()
|
|
||||||
log.Println("disconnected:", conn.Id())
|
|
||||||
}()
|
|
||||||
for {
|
|
||||||
t, r, err := conn.NextReader()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r.Close()
|
|
||||||
if t == engineio.MessageText {
|
|
||||||
log.Println(t, string(b))
|
|
||||||
} else {
|
|
||||||
log.Println(t, hex.EncodeToString(b))
|
|
||||||
}
|
|
||||||
w, err := conn.NextWriter(t)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Write([]byte("pong"))
|
|
||||||
w.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
http.Handle("/engine.io/", server)
|
|
||||||
http.Handle("/", http.FileServer(http.Dir("./asset")))
|
|
||||||
log.Println("Serving at localhost:4000...")
|
|
||||||
log.Fatal(http.ListenAndServe(":4000", nil))
|
|
||||||
}
|
|
123
vendor/github.com/googollee/go-engine.io/ioutil_test.go
generated
vendored
123
vendor/github.com/googollee/go-engine.io/ioutil_test.go
generated
vendored
@ -1,123 +0,0 @@
|
|||||||
package engineio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"github.com/googollee/go-engine.io/parser"
|
|
||||||
"io"
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestConnIoutil(t *testing.T) {
|
|
||||||
|
|
||||||
Convey("Reader", t, func() {
|
|
||||||
Convey("Normal read", func() {
|
|
||||||
r := bytes.NewBufferString("\x34\xe6\xb5\x8b\xe8\xaf\x95")
|
|
||||||
decoder, err := parser.NewDecoder(r)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
closeChan := make(chan struct{})
|
|
||||||
reader := newConnReader(decoder, closeChan)
|
|
||||||
b := make([]byte, 1024)
|
|
||||||
n, err := reader.Read(b)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(string(b[:n]), ShouldEqual, "测试")
|
|
||||||
n, err = reader.Read(b)
|
|
||||||
So(err, ShouldEqual, io.EOF)
|
|
||||||
|
|
||||||
Convey("Wait close", func() {
|
|
||||||
check := make(chan int)
|
|
||||||
go func() {
|
|
||||||
err := reader.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
check <- 1
|
|
||||||
}()
|
|
||||||
|
|
||||||
time.Sleep(time.Second / 10) // wait goroutine start
|
|
||||||
select {
|
|
||||||
case <-check:
|
|
||||||
So("should not run here", ShouldEqual, "")
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
<-closeChan
|
|
||||||
time.Sleep(time.Second / 10) // wait goroutine end
|
|
||||||
select {
|
|
||||||
case <-check:
|
|
||||||
default:
|
|
||||||
So("should not run here", ShouldEqual, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("Close again", func() {
|
|
||||||
err := reader.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Wrtier", t, func() {
|
|
||||||
|
|
||||||
Convey("Normal write", func() {
|
|
||||||
locker := sync.Mutex{}
|
|
||||||
w := bytes.NewBuffer(nil)
|
|
||||||
locker.Lock()
|
|
||||||
writer := newConnWriter(writeCloser{w}, &locker)
|
|
||||||
|
|
||||||
_, err := writer.Write([]byte("abc"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(w.String(), ShouldEqual, "abc")
|
|
||||||
writer.Close()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Sync", func() {
|
|
||||||
locker := sync.Mutex{}
|
|
||||||
w1 := bytes.NewBuffer(nil)
|
|
||||||
locker.Lock()
|
|
||||||
writer1 := newConnWriter(writeCloser{w1}, &locker)
|
|
||||||
check := make(chan int)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
w2 := bytes.NewBuffer(nil)
|
|
||||||
locker.Lock()
|
|
||||||
writer2 := newConnWriter(writeCloser{w2}, &locker)
|
|
||||||
defer writer2.Close()
|
|
||||||
check <- 1
|
|
||||||
}()
|
|
||||||
|
|
||||||
time.Sleep(time.Second / 10)
|
|
||||||
select {
|
|
||||||
case <-check:
|
|
||||||
So("should not run here", ShouldEqual, "")
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
err := writer1.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
time.Sleep(time.Second / 10) // wait goroutine end
|
|
||||||
select {
|
|
||||||
case <-check:
|
|
||||||
default:
|
|
||||||
So("should not run here", ShouldEqual, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("Close again", func() {
|
|
||||||
err := writer1.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type writeCloser struct {
|
|
||||||
io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w writeCloser) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
58
vendor/github.com/googollee/go-engine.io/parser/limit_reader_test.go
generated
vendored
58
vendor/github.com/googollee/go-engine.io/parser/limit_reader_test.go
generated
vendored
@ -1,58 +0,0 @@
|
|||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLimitReader(t *testing.T) {
|
|
||||||
|
|
||||||
Convey("Read to limit", t, func() {
|
|
||||||
b := bytes.NewBufferString("1234567890")
|
|
||||||
r := newLimitReader(b, 5)
|
|
||||||
p := make([]byte, 1024)
|
|
||||||
n, err := r.Read(p)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(string(p[:n]), ShouldEqual, "12345")
|
|
||||||
n, err = r.Read(p)
|
|
||||||
So(err, ShouldEqual, io.EOF)
|
|
||||||
err = r.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(b.String(), ShouldEqual, "67890")
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Read some and close", t, func() {
|
|
||||||
b := bytes.NewBufferString("1234567890")
|
|
||||||
r := newLimitReader(b, 5)
|
|
||||||
p := make([]byte, 3)
|
|
||||||
n, err := r.Read(p)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(string(p[:n]), ShouldEqual, "123")
|
|
||||||
err = r.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(b.String(), ShouldEqual, "67890")
|
|
||||||
err = r.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Close with error", t, func() {
|
|
||||||
er := errorReader{}
|
|
||||||
r := newLimitReader(er, 5)
|
|
||||||
err := r.Close()
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type errorReader struct{}
|
|
||||||
|
|
||||||
func (r errorReader) Read(p []byte) (int, error) {
|
|
||||||
return 0, errors.New("error")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r errorReader) Close() error {
|
|
||||||
return errors.New("error")
|
|
||||||
}
|
|
297
vendor/github.com/googollee/go-engine.io/parser/packet_test.go
generated
vendored
297
vendor/github.com/googollee/go-engine.io/parser/packet_test.go
generated
vendored
@ -1,297 +0,0 @@
|
|||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/googollee/go-engine.io/message"
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPacketType(t *testing.T) {
|
|
||||||
|
|
||||||
Convey("Byte to type", t, func() {
|
|
||||||
|
|
||||||
Convey("Open", func() {
|
|
||||||
t, err := ByteToType(0)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(t, ShouldEqual, OPEN)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Close", func() {
|
|
||||||
t, err := ByteToType(1)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(t, ShouldEqual, CLOSE)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Ping", func() {
|
|
||||||
t, err := ByteToType(2)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(t, ShouldEqual, PING)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Pong", func() {
|
|
||||||
t, err := ByteToType(3)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(t, ShouldEqual, PONG)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Message", func() {
|
|
||||||
t, err := ByteToType(4)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(t, ShouldEqual, MESSAGE)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Upgrade", func() {
|
|
||||||
t, err := ByteToType(5)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(t, ShouldEqual, UPGRADE)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Noop", func() {
|
|
||||||
t, err := ByteToType(6)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(t, ShouldEqual, NOOP)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Error", func() {
|
|
||||||
_, err := ByteToType(7)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Type to byte", t, func() {
|
|
||||||
|
|
||||||
Convey("Open", func() {
|
|
||||||
So(OPEN.Byte(), ShouldEqual, 0)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Close", func() {
|
|
||||||
So(CLOSE.Byte(), ShouldEqual, 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Ping", func() {
|
|
||||||
So(PING.Byte(), ShouldEqual, 2)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Pong", func() {
|
|
||||||
So(PONG.Byte(), ShouldEqual, 3)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Message", func() {
|
|
||||||
So(MESSAGE.Byte(), ShouldEqual, 4)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Upgrade", func() {
|
|
||||||
So(UPGRADE.Byte(), ShouldEqual, 5)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Noop", func() {
|
|
||||||
So(NOOP.Byte(), ShouldEqual, 6)
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStringParser(t *testing.T) {
|
|
||||||
type Test struct {
|
|
||||||
name string
|
|
||||||
t PacketType
|
|
||||||
data []byte
|
|
||||||
output string
|
|
||||||
}
|
|
||||||
var tests = []Test{
|
|
||||||
{"without data", OPEN, nil, "0"},
|
|
||||||
{"with data", MESSAGE, []byte("测试"), "\x34\xe6\xb5\x8b\xe8\xaf\x95"},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
|
|
||||||
Convey("Given a packet type "+test.name, t, func() {
|
|
||||||
|
|
||||||
Convey("Create encoder", func() {
|
|
||||||
encoder, err := NewStringEncoder(buf, test.t)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(encoder, ShouldImplement, (*io.WriteCloser)(nil))
|
|
||||||
|
|
||||||
Convey("Encoded", func() {
|
|
||||||
for d := test.data; len(d) > 0; {
|
|
||||||
n, err := encoder.Write(d)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
d = d[n:]
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("End", func() {
|
|
||||||
err := encoder.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(buf.String(), ShouldEqual, test.output)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Create decoder", func() {
|
|
||||||
decoder, err := NewDecoder(buf)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(decoder, ShouldImplement, (*io.ReadCloser)(nil))
|
|
||||||
So(decoder.MessageType(), ShouldEqual, message.MessageText)
|
|
||||||
|
|
||||||
Convey("Decoded", func() {
|
|
||||||
So(decoder.Type(), ShouldEqual, test.t)
|
|
||||||
|
|
||||||
decoded := make([]byte, len(test.data)+1)
|
|
||||||
n, err := decoder.Read(decoded)
|
|
||||||
if n > 0 {
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(decoded[:n], ShouldResemble, test.data)
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("End", func() {
|
|
||||||
_, err := decoder.Read(decoded[:])
|
|
||||||
So(err, ShouldEqual, io.EOF)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBinaryParser(t *testing.T) {
|
|
||||||
type Test struct {
|
|
||||||
name string
|
|
||||||
t PacketType
|
|
||||||
data []byte
|
|
||||||
output string
|
|
||||||
}
|
|
||||||
var tests = []Test{
|
|
||||||
{"without data", OPEN, nil, "\x00"},
|
|
||||||
{"with data", MESSAGE, []byte("测试"), "\x04\xe6\xb5\x8b\xe8\xaf\x95"},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
|
|
||||||
Convey("Given a packet type "+test.name, t, func() {
|
|
||||||
|
|
||||||
Convey("Create Encoder", func() {
|
|
||||||
encoder, err := NewBinaryEncoder(buf, test.t)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(encoder, ShouldImplement, (*io.WriteCloser)(nil))
|
|
||||||
|
|
||||||
Convey("Encoded", func() {
|
|
||||||
for d := test.data; len(d) > 0; {
|
|
||||||
n, err := encoder.Write(d)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
d = d[n:]
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("End", func() {
|
|
||||||
err := encoder.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(buf.String(), ShouldEqual, test.output)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Create decoder", func() {
|
|
||||||
decoder, err := NewDecoder(buf)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(decoder, ShouldImplement, (*io.ReadCloser)(nil))
|
|
||||||
So(decoder.MessageType(), ShouldEqual, message.MessageBinary)
|
|
||||||
|
|
||||||
Convey("Decoded", func() {
|
|
||||||
So(decoder.Type(), ShouldEqual, test.t)
|
|
||||||
decoded := make([]byte, len(test.data)+1)
|
|
||||||
n, err := decoder.Read(decoded[:])
|
|
||||||
if n > 0 {
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(decoded[:n], ShouldResemble, test.data)
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("End", func() {
|
|
||||||
_, err := decoder.Read(decoded[:])
|
|
||||||
So(err, ShouldEqual, io.EOF)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBase64Parser(t *testing.T) {
|
|
||||||
type Test struct {
|
|
||||||
name string
|
|
||||||
t PacketType
|
|
||||||
data []byte
|
|
||||||
output string
|
|
||||||
}
|
|
||||||
var tests = []Test{
|
|
||||||
{"without data", OPEN, nil, "b0"},
|
|
||||||
{"with data", MESSAGE, []byte("测试"), "b45rWL6K+V"},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
|
|
||||||
Convey("Given a packet type "+test.name, t, func() {
|
|
||||||
|
|
||||||
Convey("Create Encoder", func() {
|
|
||||||
encoder, err := NewB64Encoder(buf, test.t)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(encoder, ShouldImplement, (*io.WriteCloser)(nil))
|
|
||||||
|
|
||||||
Convey("Encoded", func() {
|
|
||||||
for d := test.data; len(d) > 0; {
|
|
||||||
n, err := encoder.Write(d)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
d = d[n:]
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("End", func() {
|
|
||||||
err := encoder.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(buf.String(), ShouldEqual, test.output)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Create decoder", func() {
|
|
||||||
decoder, err := NewDecoder(buf)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(decoder, ShouldImplement, (*io.ReadCloser)(nil))
|
|
||||||
So(decoder.MessageType(), ShouldEqual, message.MessageBinary)
|
|
||||||
|
|
||||||
Convey("Decoded", func() {
|
|
||||||
So(decoder.Type(), ShouldEqual, test.t)
|
|
||||||
decoded := make([]byte, len(test.data)+1)
|
|
||||||
n, err := decoder.Read(decoded[:])
|
|
||||||
if n > 0 {
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(decoded[:n], ShouldResemble, test.data)
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("End", func() {
|
|
||||||
_, err := decoder.Read(decoded[:])
|
|
||||||
So(err, ShouldEqual, io.EOF)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLimitReaderDecoder(t *testing.T) {
|
|
||||||
Convey("Test decoder with limit reader", t, func() {
|
|
||||||
buf := bytes.NewBufferString("\x34\xe6\xb5\x8b\xe8\xaf\x95123")
|
|
||||||
reader := newLimitReader(buf, 7)
|
|
||||||
decoder, err := NewDecoder(reader)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(decoder.Type(), ShouldEqual, MESSAGE)
|
|
||||||
err = decoder.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(buf.String(), ShouldEqual, "123")
|
|
||||||
})
|
|
||||||
}
|
|
212
vendor/github.com/googollee/go-engine.io/parser/payload_test.go
generated
vendored
212
vendor/github.com/googollee/go-engine.io/parser/payload_test.go
generated
vendored
@ -1,212 +0,0 @@
|
|||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestStringPayload(t *testing.T) {
|
|
||||||
type packet struct {
|
|
||||||
Type PacketType
|
|
||||||
Data []byte
|
|
||||||
IsString bool
|
|
||||||
}
|
|
||||||
type Test struct {
|
|
||||||
name string
|
|
||||||
packets []packet
|
|
||||||
output string
|
|
||||||
}
|
|
||||||
var tests = []Test{
|
|
||||||
{"all in one", []packet{packet{OPEN, nil, true}, packet{MESSAGE, []byte("测试"), true}, packet{MESSAGE, []byte("测试"), false}}, "\x31\x3a\x30\x37\x3a\x34\xe6\xb5\x8b\xe8\xaf\x95\x31\x30\x3a\x62\x34\x35\x72\x57\x4c\x36\x4b\x2b\x56"},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
|
|
||||||
Convey("Given an array of packet "+test.name, t, func() {
|
|
||||||
|
|
||||||
Convey("Create encoder", func() {
|
|
||||||
encoder := NewStringPayloadEncoder()
|
|
||||||
So(encoder.IsString(), ShouldBeTrue)
|
|
||||||
|
|
||||||
Convey("Encoded", func() {
|
|
||||||
for _, p := range test.packets {
|
|
||||||
var e io.WriteCloser
|
|
||||||
var err error
|
|
||||||
if p.IsString {
|
|
||||||
e, err = encoder.NextString(p.Type)
|
|
||||||
} else {
|
|
||||||
e, err = encoder.NextBinary(p.Type)
|
|
||||||
}
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
for d := p.Data; len(d) > 0; {
|
|
||||||
n, err := e.Write(d)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
d = d[n:]
|
|
||||||
}
|
|
||||||
err = e.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("End", func() {
|
|
||||||
err := encoder.EncodeTo(buf)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(buf.String(), ShouldEqual, test.output)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Create decoder", func() {
|
|
||||||
decoder := NewPayloadDecoder(buf)
|
|
||||||
|
|
||||||
Convey("Decode", func() {
|
|
||||||
for i := 0; ; i++ {
|
|
||||||
d, err := decoder.Next()
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(d.Type(), ShouldEqual, test.packets[i].Type)
|
|
||||||
|
|
||||||
if l := len(test.packets[i].Data); l > 0 {
|
|
||||||
buf := make([]byte, len(test.packets[i].Data)+1)
|
|
||||||
n, err := d.Read(buf)
|
|
||||||
if n > 0 {
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(buf[:n], ShouldResemble, test.packets[i].Data)
|
|
||||||
}
|
|
||||||
_, err = d.Read(buf)
|
|
||||||
So(err, ShouldEqual, io.EOF)
|
|
||||||
}
|
|
||||||
err = d.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBinaryPayload(t *testing.T) {
|
|
||||||
type packet struct {
|
|
||||||
Type PacketType
|
|
||||||
Data []byte
|
|
||||||
IsString bool
|
|
||||||
}
|
|
||||||
type Test struct {
|
|
||||||
name string
|
|
||||||
packets []packet
|
|
||||||
output string
|
|
||||||
}
|
|
||||||
var tests = []Test{
|
|
||||||
{"all in one", []packet{packet{OPEN, nil, true}, packet{MESSAGE, []byte("测试"), true}, packet{MESSAGE, []byte("测试"), false}}, "\x00\x01\xff\x30\x00\x07\xff\x34\xe6\xb5\x8b\xe8\xaf\x95\x01\x07\xff\x04\xe6\xb5\x8b\xe8\xaf\x95"},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
|
|
||||||
Convey("Given an array of packet "+test.name, t, func() {
|
|
||||||
|
|
||||||
Convey("Create encoder", func() {
|
|
||||||
encoder := NewBinaryPayloadEncoder()
|
|
||||||
So(encoder.IsString(), ShouldBeFalse)
|
|
||||||
|
|
||||||
Convey("Encoded", func() {
|
|
||||||
for _, p := range test.packets {
|
|
||||||
var e io.WriteCloser
|
|
||||||
var err error
|
|
||||||
if p.IsString {
|
|
||||||
e, err = encoder.NextString(p.Type)
|
|
||||||
} else {
|
|
||||||
e, err = encoder.NextBinary(p.Type)
|
|
||||||
}
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
for d := p.Data; len(d) > 0; {
|
|
||||||
n, err := e.Write(d)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
d = d[n:]
|
|
||||||
}
|
|
||||||
err = e.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("End", func() {
|
|
||||||
err := encoder.EncodeTo(buf)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(buf.String(), ShouldEqual, test.output)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Create decoder", func() {
|
|
||||||
decoder := NewPayloadDecoder(buf)
|
|
||||||
|
|
||||||
Convey("Decode", func() {
|
|
||||||
for i := 0; ; i++ {
|
|
||||||
d, err := decoder.Next()
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(d.Type(), ShouldEqual, test.packets[i].Type)
|
|
||||||
|
|
||||||
if l := len(test.packets[i].Data); l > 0 {
|
|
||||||
buf := make([]byte, len(test.packets[i].Data)+1)
|
|
||||||
n, err := d.Read(buf)
|
|
||||||
if n > 0 {
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(buf[:n], ShouldResemble, test.packets[i].Data)
|
|
||||||
}
|
|
||||||
_, err = d.Read(buf)
|
|
||||||
So(err, ShouldEqual, io.EOF)
|
|
||||||
}
|
|
||||||
err = d.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParallelEncode(t *testing.T) {
|
|
||||||
prev := runtime.GOMAXPROCS(10)
|
|
||||||
defer runtime.GOMAXPROCS(prev)
|
|
||||||
|
|
||||||
Convey("Test parallel encode", t, func() {
|
|
||||||
c := make(chan int)
|
|
||||||
max := 1000
|
|
||||||
buf1 := bytes.NewBuffer(nil)
|
|
||||||
buf2 := bytes.NewBuffer(nil)
|
|
||||||
encoder := NewStringPayloadEncoder()
|
|
||||||
for i := 0; i < max; i++ {
|
|
||||||
go func() {
|
|
||||||
e, _ := encoder.NextString(MESSAGE)
|
|
||||||
e.Write([]byte("1234"))
|
|
||||||
e.Close()
|
|
||||||
c <- 1
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
for i := 0; i < max/2; i++ {
|
|
||||||
<-c
|
|
||||||
}
|
|
||||||
err := encoder.EncodeTo(buf1)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
for i := 0; i < max/2; i++ {
|
|
||||||
<-c
|
|
||||||
}
|
|
||||||
err = encoder.EncodeTo(buf2)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
for s := buf1.String(); len(s) > 0; {
|
|
||||||
So(s, ShouldStartWith, "5:41234")
|
|
||||||
s = s[len("5:41234"):]
|
|
||||||
}
|
|
||||||
for s := buf2.String(); len(s) > 0; {
|
|
||||||
So(s, ShouldStartWith, "5:41234")
|
|
||||||
s = s[len("5:41234"):]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
231
vendor/github.com/googollee/go-engine.io/polling/polling_test.go
generated
vendored
231
vendor/github.com/googollee/go-engine.io/polling/polling_test.go
generated
vendored
@ -1,231 +0,0 @@
|
|||||||
package polling
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/googollee/go-engine.io/message"
|
|
||||||
"github.com/googollee/go-engine.io/parser"
|
|
||||||
"github.com/googollee/go-engine.io/transport"
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPolling(t *testing.T) {
|
|
||||||
|
|
||||||
Convey("Normal", t, func() {
|
|
||||||
s := newServer()
|
|
||||||
server := httptest.NewServer(s)
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", server.URL, nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
client, err := NewClient(req)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
So(client.Response(), ShouldBeNil)
|
|
||||||
|
|
||||||
sync := make(chan int)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
<-s.callback.onPacket
|
|
||||||
sync <- 1
|
|
||||||
}()
|
|
||||||
|
|
||||||
{
|
|
||||||
w, err := client.NextWriter(message.MessageBinary, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = w.Write([]byte("123"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = w.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
<-sync
|
|
||||||
So(s.callback.messageType, ShouldEqual, message.MessageBinary)
|
|
||||||
So(s.callback.packetType, ShouldEqual, parser.MESSAGE)
|
|
||||||
So(s.callback.body, ShouldResemble, []byte("123"))
|
|
||||||
}
|
|
||||||
|
|
||||||
So(client.Response(), ShouldNotBeNil)
|
|
||||||
So(client.Response().StatusCode, ShouldEqual, http.StatusOK)
|
|
||||||
So(client.Response().Header.Get("Custom"), ShouldEqual, "value")
|
|
||||||
|
|
||||||
{
|
|
||||||
w, err := s.server.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = w.Write([]byte("abc1"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = w.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
w, err = s.server.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = w.Write([]byte("abc2"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = w.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
r, err := client.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
b, err := ioutil.ReadAll(r)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(b, ShouldResemble, []byte("abc1"))
|
|
||||||
err = r.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
r, err = client.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
b, err = ioutil.ReadAll(r)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(b, ShouldResemble, []byte("abc2"))
|
|
||||||
err = r.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
w, err := s.server.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = w.Write([]byte("abc"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = w.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
r, err := client.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
b, err := ioutil.ReadAll(r)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(b, ShouldResemble, []byte("abc"))
|
|
||||||
err = r.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
client.Close()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Normal b64", t, func() {
|
|
||||||
s := newServer()
|
|
||||||
server := httptest.NewServer(s)
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", server.URL+"?b64", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
client, err := NewClient(req)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
So(client.Response(), ShouldBeNil)
|
|
||||||
|
|
||||||
sync := make(chan int)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
<-s.callback.onPacket
|
|
||||||
sync <- 1
|
|
||||||
}()
|
|
||||||
|
|
||||||
{
|
|
||||||
w, err := client.NextWriter(message.MessageBinary, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = w.Write([]byte("123"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = w.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
<-sync
|
|
||||||
So(s.callback.messageType, ShouldEqual, message.MessageBinary)
|
|
||||||
So(s.callback.packetType, ShouldEqual, parser.MESSAGE)
|
|
||||||
So(s.callback.body, ShouldResemble, []byte("123"))
|
|
||||||
}
|
|
||||||
|
|
||||||
So(client.Response(), ShouldNotBeNil)
|
|
||||||
So(client.Response().StatusCode, ShouldEqual, http.StatusOK)
|
|
||||||
So(client.Response().Header.Get("Custom"), ShouldEqual, "value")
|
|
||||||
|
|
||||||
{
|
|
||||||
w, err := s.server.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = w.Write([]byte("abc1"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = w.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
w, err = s.server.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = w.Write([]byte("abc2"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = w.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
r, err := client.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
b, err := ioutil.ReadAll(r)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(b, ShouldResemble, []byte("abc1"))
|
|
||||||
err = r.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
r, err = client.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
b, err = ioutil.ReadAll(r)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(b, ShouldResemble, []byte("abc2"))
|
|
||||||
err = r.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
w, err := s.server.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = w.Write([]byte("abc"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = w.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
r, err := client.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
b, err := ioutil.ReadAll(r)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(b, ShouldResemble, []byte("abc"))
|
|
||||||
err = r.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
client.Close()
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type server struct {
|
|
||||||
server transport.Server
|
|
||||||
callback *fakeCallback
|
|
||||||
}
|
|
||||||
|
|
||||||
func newServer() *server {
|
|
||||||
return &server{
|
|
||||||
callback: newFakeCallback(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if s.server == nil {
|
|
||||||
var err error
|
|
||||||
s.server, err = NewServer(w, r, s.callback)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.Header().Set("Custom", "value")
|
|
||||||
s.server.ServeHTTP(w, r)
|
|
||||||
}
|
|
507
vendor/github.com/googollee/go-engine.io/polling/server_test.go
generated
vendored
507
vendor/github.com/googollee/go-engine.io/polling/server_test.go
generated
vendored
@ -1,507 +0,0 @@
|
|||||||
package polling
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/googollee/go-engine.io/message"
|
|
||||||
"github.com/googollee/go-engine.io/parser"
|
|
||||||
"github.com/googollee/go-engine.io/transport"
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestServer(t *testing.T) {
|
|
||||||
Convey("Test polling", t, func() {
|
|
||||||
|
|
||||||
Convey("Overlay get", func() {
|
|
||||||
sync := make(chan int)
|
|
||||||
f := newFakeCallback()
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server, err := NewServer(w, r, f)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, _ := http.NewRequest("GET", "/", nil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
}()
|
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
|
|
||||||
{
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
So(w.Code, ShouldEqual, http.StatusBadRequest)
|
|
||||||
So(w.Body.String(), ShouldEqual, "overlay get\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
server.Close()
|
|
||||||
<-sync
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Overlay post", func() {
|
|
||||||
sync := make(chan int)
|
|
||||||
f := newFakeCallback()
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server, err := NewServer(w, r, f)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, _ := http.NewRequest("POST", "/", bytes.NewBufferString("\x00\x07\xff4测试"))
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
}()
|
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
|
|
||||||
{
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("POST", "/", bytes.NewBufferString("\x00\x07\xff4测试"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
So(w.Code, ShouldEqual, http.StatusBadRequest)
|
|
||||||
So(w.Body.String(), ShouldEqual, "overlay post\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
<-f.onPacket
|
|
||||||
server.Close()
|
|
||||||
<-sync
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Get", func() {
|
|
||||||
f := newFakeCallback()
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server, err := NewServer(w, r, f)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
{
|
|
||||||
writer, err := server.NextWriter(message.MessageBinary, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = writer.Write([]byte("测试"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = writer.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
So(w.Code, ShouldEqual, http.StatusOK)
|
|
||||||
So(w.Header().Get("Content-Type"), ShouldEqual, "application/octet-stream")
|
|
||||||
So(hex.EncodeToString(w.Body.Bytes()), ShouldEqual, "0107ff04e6b58be8af95")
|
|
||||||
So(w.Body.String(), ShouldEqual, "\x01\x07\xff\x04测试")
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
writer, err := server.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = writer.Write([]byte("测试"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = writer.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
So(w.Code, ShouldEqual, http.StatusOK)
|
|
||||||
So(w.Header().Get("Content-Type"), ShouldEqual, "application/octet-stream")
|
|
||||||
So(hex.EncodeToString(w.Body.Bytes()), ShouldEqual, "0007ff34e6b58be8af95")
|
|
||||||
So(w.Body.String(), ShouldEqual, "\x00\x07\xff4测试")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = server.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
{
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
So(w.Code, ShouldEqual, http.StatusBadRequest)
|
|
||||||
So(w.Body.String(), ShouldEqual, "closed\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
writer, err := server.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
So(err, ShouldEqual, io.EOF)
|
|
||||||
So(writer, ShouldBeNil)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Get b64", func() {
|
|
||||||
f := newFakeCallback()
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/?b64", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server, err := NewServer(w, r, f)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
{
|
|
||||||
writer, err := server.NextWriter(message.MessageBinary, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = writer.Write([]byte("测试"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = writer.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
So(w.Code, ShouldEqual, http.StatusOK)
|
|
||||||
So(w.Header().Get("Content-Type"), ShouldEqual, "text/plain; charset=UTF-8")
|
|
||||||
So(w.Body.String(), ShouldEqual, "10:b45rWL6K+V")
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
writer, err := server.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = writer.Write([]byte("测试"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = writer.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
So(w.Code, ShouldEqual, http.StatusOK)
|
|
||||||
So(w.Header().Get("Content-Type"), ShouldEqual, "text/plain; charset=UTF-8")
|
|
||||||
So(w.Body.String(), ShouldEqual, "7:4测试")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = server.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
{
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
So(w.Code, ShouldEqual, http.StatusBadRequest)
|
|
||||||
So(w.Body.String(), ShouldEqual, "closed\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
writer, err := server.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
So(err, ShouldEqual, io.EOF)
|
|
||||||
So(writer, ShouldBeNil)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Post", func() {
|
|
||||||
f := newFakeCallback()
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server, err := NewServer(w, r, f)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
<-f.onPacket
|
|
||||||
}()
|
|
||||||
|
|
||||||
{
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("POST", "/", bytes.NewBufferString("\x00\x07\xff4测试"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
So(w.Code, ShouldEqual, http.StatusOK)
|
|
||||||
So(w.Body.String(), ShouldEqual, "ok")
|
|
||||||
So(hex.EncodeToString(f.body), ShouldEqual, "e6b58be8af95")
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("POST", "/", bytes.NewBufferString("\x00\xff4测试"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
So(w.Code, ShouldEqual, http.StatusBadRequest)
|
|
||||||
So(w.Body.String(), ShouldEqual, "invalid input\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = server.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
{
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("POST", "/", bytes.NewBufferString("\x00\x07\xff4测试"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
So(w.Code, ShouldEqual, http.StatusBadRequest)
|
|
||||||
So(w.Body.String(), ShouldEqual, "closed\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Closing", func() {
|
|
||||||
Convey("No get no post", func() {
|
|
||||||
f := newFakeCallback()
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server, err := NewServer(w, r, f)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 0)
|
|
||||||
err = server.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 1)
|
|
||||||
So(f.closeServer, ShouldEqual, server)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("No get has post", func() {
|
|
||||||
f := newFakeCallback()
|
|
||||||
sync := make(chan int)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server, err := NewServer(w, r, f)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, _ := http.NewRequest("POST", "/", bytes.NewBufferString("\x00\x07\xff4测试"))
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
sync <- 1
|
|
||||||
}()
|
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 0)
|
|
||||||
err = server.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 0)
|
|
||||||
<-f.onPacket
|
|
||||||
<-sync
|
|
||||||
So(f.closeServer, ShouldEqual, server)
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("has get no post", func() {
|
|
||||||
f := newFakeCallback()
|
|
||||||
sync := make(chan int)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server, err := NewServer(w, r, f)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, _ := http.NewRequest("GET", "/", nil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
}()
|
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 0)
|
|
||||||
err = server.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
<-sync
|
|
||||||
So(f.closeServer, ShouldEqual, server)
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("has get has post", func() {
|
|
||||||
f := newFakeCallback()
|
|
||||||
sync := make(chan int)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server, err := NewServer(w, r, f)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, _ := http.NewRequest("GET", "/", nil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, _ = http.NewRequest("POST", "/", bytes.NewBufferString("\x00\x07\xff4测试"))
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
sync <- 1
|
|
||||||
}()
|
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 0)
|
|
||||||
err = server.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 0)
|
|
||||||
<-f.onPacket
|
|
||||||
<-sync
|
|
||||||
<-sync
|
|
||||||
So(f.closeServer, ShouldEqual, server)
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Multi-close", func() {
|
|
||||||
f := newFakeCallback()
|
|
||||||
sync := make(chan int)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server, err := NewServer(w, r, f)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, _ := http.NewRequest("GET", "/", nil)
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, _ := http.NewRequest("POST", "/", bytes.NewBufferString("\x00\x07\xff4测试"))
|
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
|
||||||
sync <- 1
|
|
||||||
}()
|
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 0)
|
|
||||||
err = server.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 0)
|
|
||||||
<-f.onPacket
|
|
||||||
<-sync
|
|
||||||
<-sync
|
|
||||||
So(f.closeServer, ShouldEqual, server)
|
|
||||||
server.Close()
|
|
||||||
server.Close()
|
|
||||||
server.Close()
|
|
||||||
server.Close()
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Closed before writer closed", func() {
|
|
||||||
f := newFakeCallback()
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
server, err := NewServer(w, r, f)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
writer, err := server.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = server.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = writer.Close()
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type fakeCallback struct {
|
|
||||||
onPacket chan bool
|
|
||||||
messageType message.MessageType
|
|
||||||
packetType parser.PacketType
|
|
||||||
body []byte
|
|
||||||
err error
|
|
||||||
closedCount int
|
|
||||||
countLocker sync.Mutex
|
|
||||||
closeServer transport.Server
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFakeCallback() *fakeCallback {
|
|
||||||
return &fakeCallback{
|
|
||||||
onPacket: make(chan bool),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fakeCallback) OnPacket(r *parser.PacketDecoder) {
|
|
||||||
f.packetType = r.Type()
|
|
||||||
f.messageType = r.MessageType()
|
|
||||||
f.body, f.err = ioutil.ReadAll(r)
|
|
||||||
f.onPacket <- true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fakeCallback) OnClose(s transport.Server) {
|
|
||||||
f.countLocker.Lock()
|
|
||||||
defer f.countLocker.Unlock()
|
|
||||||
f.closedCount++
|
|
||||||
f.closeServer = s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fakeCallback) ClosedCount() int {
|
|
||||||
f.countLocker.Lock()
|
|
||||||
defer f.countLocker.Unlock()
|
|
||||||
return f.closedCount
|
|
||||||
}
|
|
47
vendor/github.com/googollee/go-engine.io/polling/try_locker_test.go
generated
vendored
47
vendor/github.com/googollee/go-engine.io/polling/try_locker_test.go
generated
vendored
@ -1,47 +0,0 @@
|
|||||||
package polling
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTryLocker(t *testing.T) {
|
|
||||||
|
|
||||||
Convey("Lock/Unlock", t, func() {
|
|
||||||
locker := NewLocker()
|
|
||||||
sync := make(chan int)
|
|
||||||
go func() {
|
|
||||||
locker.Lock()
|
|
||||||
sync <- 1
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
locker.Unlock()
|
|
||||||
}()
|
|
||||||
<-sync
|
|
||||||
start := time.Now()
|
|
||||||
locker.Lock()
|
|
||||||
now := time.Now()
|
|
||||||
So(now.Sub(start), ShouldBeGreaterThanOrEqualTo, time.Second)
|
|
||||||
locker.Unlock()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("TryLock/Unlock", t, func() {
|
|
||||||
locker := NewLocker()
|
|
||||||
sync := make(chan int)
|
|
||||||
go func() {
|
|
||||||
locker.Lock()
|
|
||||||
sync <- 1
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
locker.Unlock()
|
|
||||||
}()
|
|
||||||
<-sync
|
|
||||||
ok := locker.TryLock()
|
|
||||||
So(ok, ShouldBeFalse)
|
|
||||||
time.Sleep(time.Second * 3 / 2)
|
|
||||||
ok = locker.TryLock()
|
|
||||||
So(ok, ShouldBeTrue)
|
|
||||||
locker.Unlock()
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
89
vendor/github.com/googollee/go-engine.io/polling/writer_test.go
generated
vendored
89
vendor/github.com/googollee/go-engine.io/polling/writer_test.go
generated
vendored
@ -1,89 +0,0 @@
|
|||||||
package polling
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestWriter(t *testing.T) {
|
|
||||||
p := &Polling{
|
|
||||||
state: stateNormal,
|
|
||||||
sendChan: MakeSendChan(),
|
|
||||||
}
|
|
||||||
sendChan := p.sendChan
|
|
||||||
|
|
||||||
Convey("Wait close", t, func() {
|
|
||||||
w := newFakeWriteCloser()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-sendChan:
|
|
||||||
panic("should not run here")
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
writer := NewWriter(w, p)
|
|
||||||
err := writer.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-sendChan:
|
|
||||||
default:
|
|
||||||
panic("should not run here")
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-sendChan:
|
|
||||||
panic("should not run here")
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Many writer with close", t, func() {
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
w := newFakeWriteCloser()
|
|
||||||
writer := NewWriter(w, p)
|
|
||||||
err := writer.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-sendChan:
|
|
||||||
default:
|
|
||||||
panic("should not run here")
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-sendChan:
|
|
||||||
panic("should not run here")
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Close with not normal", t, func() {
|
|
||||||
p := &Polling{
|
|
||||||
state: stateClosing,
|
|
||||||
sendChan: MakeSendChan(),
|
|
||||||
}
|
|
||||||
|
|
||||||
w := newFakeWriteCloser()
|
|
||||||
writer := NewWriter(w, p)
|
|
||||||
err := writer.Close()
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type fakeWriteCloser struct {
|
|
||||||
*bytes.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFakeWriteCloser() *fakeWriteCloser {
|
|
||||||
return &fakeWriteCloser{
|
|
||||||
Buffer: bytes.NewBuffer(nil),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fakeWriteCloser) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
377
vendor/github.com/googollee/go-engine.io/server_conn_test.go
generated
vendored
377
vendor/github.com/googollee/go-engine.io/server_conn_test.go
generated
vendored
@ -1,377 +0,0 @@
|
|||||||
package engineio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"net/url"
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/googollee/go-engine.io/message"
|
|
||||||
"github.com/googollee/go-engine.io/parser"
|
|
||||||
"github.com/googollee/go-engine.io/polling"
|
|
||||||
"github.com/googollee/go-engine.io/websocket"
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FakeServer struct {
|
|
||||||
config *config
|
|
||||||
creaters transportCreaters
|
|
||||||
closed map[string]int
|
|
||||||
closedLocker sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFakeServer() *FakeServer {
|
|
||||||
return &FakeServer{
|
|
||||||
config: &config{
|
|
||||||
PingTimeout: time.Second * 2,
|
|
||||||
PingInterval: time.Second * 1,
|
|
||||||
AllowUpgrades: true,
|
|
||||||
},
|
|
||||||
creaters: transportCreaters{
|
|
||||||
"polling": polling.Creater,
|
|
||||||
"websocket": websocket.Creater,
|
|
||||||
},
|
|
||||||
closed: make(map[string]int),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeServer) configure() config {
|
|
||||||
return *f.config
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeServer) transports() transportCreaters {
|
|
||||||
return f.creaters
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeServer) onClose(sid string) {
|
|
||||||
f.closedLocker.Lock()
|
|
||||||
defer f.closedLocker.Unlock()
|
|
||||||
f.closed[sid] = f.closed[sid] + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConn(t *testing.T) {
|
|
||||||
Convey("Create conn", t, func() {
|
|
||||||
Convey("without transport", func() {
|
|
||||||
server := newFakeServer()
|
|
||||||
req, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
resp := httptest.NewRecorder()
|
|
||||||
_, err = newServerConn("id", resp, req, server)
|
|
||||||
So(err, ShouldEqual, InvalidError)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("with invalid transport", func() {
|
|
||||||
server := newFakeServer()
|
|
||||||
req, err := http.NewRequest("GET", "/?transport=websocket", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
resp := httptest.NewRecorder()
|
|
||||||
_, err = newServerConn("id", resp, req, server)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("ok", func() {
|
|
||||||
Convey("with polling", func() {
|
|
||||||
server := newFakeServer()
|
|
||||||
req, err := http.NewRequest("GET", "/?transport=polling", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
resp := httptest.NewRecorder()
|
|
||||||
conn, err := newServerConn("id", resp, req, server)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(conn.Id(), ShouldEqual, "id")
|
|
||||||
So(conn.Request(), ShouldEqual, req)
|
|
||||||
conn.Close()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("with websocket", func() {
|
|
||||||
server := newFakeServer()
|
|
||||||
h := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
conn, err := newServerConn("id", w, r, server)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
if conn.Id() != "id" {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if conn.Request() != r {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
defer h.Close()
|
|
||||||
|
|
||||||
u, _ := url.Parse(h.URL)
|
|
||||||
u.Scheme = "ws"
|
|
||||||
req, err := http.NewRequest("GET", u.String()+"/?transport=websocket", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(req, ShouldNotBeNil)
|
|
||||||
|
|
||||||
c, err := websocket.NewClient(req)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
defer c.Close()
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Upgrade conn", t, func() {
|
|
||||||
Convey("polling to websocket", func() {
|
|
||||||
server := newFakeServer()
|
|
||||||
id := "id"
|
|
||||||
var conn *serverConn
|
|
||||||
|
|
||||||
h := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if conn == nil {
|
|
||||||
var err error
|
|
||||||
conn, err = newServerConn(id, w, r, server)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.ServeHTTP(w, r)
|
|
||||||
}))
|
|
||||||
defer h.Close()
|
|
||||||
|
|
||||||
u, err := url.Parse(h.URL)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", u.String()+"/?transport=polling", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
pc, err := polling.NewClient(req)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
decoder, err := pc.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(pc.Response().StatusCode, ShouldEqual, http.StatusOK)
|
|
||||||
|
|
||||||
So(conn, ShouldNotBeNil)
|
|
||||||
So(conn, ShouldImplement, (*Conn)(nil))
|
|
||||||
|
|
||||||
So(decoder.MessageType(), ShouldEqual, message.MessageText)
|
|
||||||
So(decoder.Type(), ShouldEqual, parser.OPEN)
|
|
||||||
|
|
||||||
So(conn.getCurrent(), ShouldNotBeNil)
|
|
||||||
So(conn.getUpgrade(), ShouldBeNil)
|
|
||||||
|
|
||||||
u.Scheme = "ws"
|
|
||||||
req, err = http.NewRequest("GET", u.String()+"/?transport=websocket", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
wc, err := websocket.NewClient(req)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
So(conn.getCurrent(), ShouldNotBeNil)
|
|
||||||
So(conn.getUpgrade(), ShouldNotBeNil)
|
|
||||||
|
|
||||||
encoder, err := wc.NextWriter(message.MessageBinary, parser.PING)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
encoder.Write([]byte("probe"))
|
|
||||||
encoder.Close()
|
|
||||||
|
|
||||||
decoder, err = wc.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(wc.Response().StatusCode, ShouldEqual, http.StatusSwitchingProtocols)
|
|
||||||
|
|
||||||
So(decoder.MessageType(), ShouldEqual, message.MessageText)
|
|
||||||
So(decoder.Type(), ShouldEqual, parser.PONG)
|
|
||||||
|
|
||||||
pc.Close()
|
|
||||||
|
|
||||||
encoder, err = wc.NextWriter(message.MessageBinary, parser.UPGRADE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
encoder.Close()
|
|
||||||
|
|
||||||
decoder, err = wc.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(pc.Response().StatusCode, ShouldEqual, http.StatusOK)
|
|
||||||
|
|
||||||
So(decoder.MessageType(), ShouldEqual, message.MessageText)
|
|
||||||
So(decoder.Type(), ShouldEqual, parser.PING)
|
|
||||||
|
|
||||||
So(conn.getCurrent(), ShouldNotBeNil)
|
|
||||||
So(conn.getUpgrade(), ShouldBeNil)
|
|
||||||
|
|
||||||
wc.Close()
|
|
||||||
|
|
||||||
conn.Close()
|
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
|
|
||||||
server.closedLocker.Lock()
|
|
||||||
So(server.closed[id], ShouldEqual, 1)
|
|
||||||
server.closedLocker.Unlock()
|
|
||||||
|
|
||||||
err = conn.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
|
|
||||||
server.closedLocker.Lock()
|
|
||||||
So(server.closed[id], ShouldEqual, 1)
|
|
||||||
server.closedLocker.Unlock()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("close when upgrading", func() {
|
|
||||||
server := newFakeServer()
|
|
||||||
id := "id"
|
|
||||||
var conn *serverConn
|
|
||||||
|
|
||||||
h := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if conn == nil {
|
|
||||||
var err error
|
|
||||||
conn, err = newServerConn(id, w, r, server)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.ServeHTTP(w, r)
|
|
||||||
}))
|
|
||||||
defer h.Close()
|
|
||||||
|
|
||||||
u, err := url.Parse(h.URL)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", u.String()+"/?transport=polling", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
pc, err := polling.NewClient(req)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
decoder, err := pc.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(pc.Response().StatusCode, ShouldEqual, http.StatusOK)
|
|
||||||
|
|
||||||
So(conn, ShouldNotBeNil)
|
|
||||||
So(conn, ShouldImplement, (*Conn)(nil))
|
|
||||||
|
|
||||||
So(decoder.MessageType(), ShouldEqual, message.MessageText)
|
|
||||||
So(decoder.Type(), ShouldEqual, parser.OPEN)
|
|
||||||
|
|
||||||
So(conn.getCurrent(), ShouldNotBeNil)
|
|
||||||
So(conn.getUpgrade(), ShouldBeNil)
|
|
||||||
|
|
||||||
u.Scheme = "ws"
|
|
||||||
req, err = http.NewRequest("GET", u.String()+"/?transport=websocket", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
wc, err := websocket.NewClient(req)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
So(conn.getCurrent(), ShouldNotBeNil)
|
|
||||||
So(conn.getUpgrade(), ShouldNotBeNil)
|
|
||||||
|
|
||||||
encoder, err := wc.NextWriter(message.MessageBinary, parser.PING)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
encoder.Write([]byte("probe"))
|
|
||||||
encoder.Close()
|
|
||||||
|
|
||||||
decoder, err = wc.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(wc.Response().StatusCode, ShouldEqual, http.StatusSwitchingProtocols)
|
|
||||||
|
|
||||||
err = conn.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
wc.Close()
|
|
||||||
pc.Close()
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
|
|
||||||
server.closedLocker.Lock()
|
|
||||||
So(server.closed[id], ShouldEqual, 1)
|
|
||||||
server.closedLocker.Unlock()
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Closing", t, func() {
|
|
||||||
Convey("close timeout by polling", func() {
|
|
||||||
server := newFakeServer()
|
|
||||||
id := "id"
|
|
||||||
var conn *serverConn
|
|
||||||
|
|
||||||
h := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if conn == nil {
|
|
||||||
var err error
|
|
||||||
conn, err = newServerConn(id, w, r, server)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.ServeHTTP(w, r)
|
|
||||||
}))
|
|
||||||
defer h.Close()
|
|
||||||
|
|
||||||
u, err := url.Parse(h.URL)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", u.String()+"/?transport=polling", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
pc, err := polling.NewClient(req)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
decoder, err := pc.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
So(decoder.MessageType(), ShouldEqual, message.MessageText)
|
|
||||||
So(decoder.Type(), ShouldEqual, parser.OPEN)
|
|
||||||
|
|
||||||
pc.Close()
|
|
||||||
|
|
||||||
time.Sleep(time.Second * 3)
|
|
||||||
|
|
||||||
server.closedLocker.Lock()
|
|
||||||
So(server.closed[id], ShouldEqual, 1)
|
|
||||||
server.closedLocker.Unlock()
|
|
||||||
|
|
||||||
err = conn.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("close by websocket", func() {
|
|
||||||
server := newFakeServer()
|
|
||||||
id := "id"
|
|
||||||
var conn *serverConn
|
|
||||||
var locker sync.Mutex
|
|
||||||
|
|
||||||
h := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
locker.Lock()
|
|
||||||
defer locker.Unlock()
|
|
||||||
if conn == nil {
|
|
||||||
var err error
|
|
||||||
conn, err = newServerConn(id, w, r, server)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.ServeHTTP(w, r)
|
|
||||||
}))
|
|
||||||
defer h.Close()
|
|
||||||
|
|
||||||
u, err := url.Parse(h.URL)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
u.Scheme = "ws"
|
|
||||||
req, err := http.NewRequest("GET", u.String()+"/?transport=websocket", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
wc, err := websocket.NewClient(req)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
wc.Close()
|
|
||||||
|
|
||||||
time.Sleep(time.Second / 2)
|
|
||||||
|
|
||||||
server.closedLocker.Lock()
|
|
||||||
So(server.closed[id], ShouldEqual, 1)
|
|
||||||
server.closedLocker.Unlock()
|
|
||||||
|
|
||||||
locker.Lock()
|
|
||||||
err = conn.Close()
|
|
||||||
locker.Unlock()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
92
vendor/github.com/googollee/go-engine.io/server_test.go
generated
vendored
92
vendor/github.com/googollee/go-engine.io/server_test.go
generated
vendored
@ -1,92 +0,0 @@
|
|||||||
package engineio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/googollee/go-engine.io/parser"
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestServer(t *testing.T) {
|
|
||||||
Convey("Setup server", t, func() {
|
|
||||||
server, err := NewServer(nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
server.SetPingInterval(time.Second)
|
|
||||||
So(server.config.PingInterval, ShouldEqual, time.Second)
|
|
||||||
server.SetPingTimeout(10 * time.Second)
|
|
||||||
So(server.config.PingTimeout, ShouldEqual, 10*time.Second)
|
|
||||||
f := func(*http.Request) error { return nil }
|
|
||||||
server.SetAllowRequest(f)
|
|
||||||
So(server.config.AllowRequest, ShouldEqual, f)
|
|
||||||
server.SetAllowUpgrades(false)
|
|
||||||
So(server.config.AllowUpgrades, ShouldBeFalse)
|
|
||||||
server.SetCookie("prefix")
|
|
||||||
So(server.config.Cookie, ShouldEqual, "prefix")
|
|
||||||
So(server.GetMaxConnection(), ShouldEqual, 1000)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Create server", t, func() {
|
|
||||||
|
|
||||||
Convey("Test new id", func() {
|
|
||||||
req, err := http.NewRequest("GET", "/", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
id1 := newId(req)
|
|
||||||
id2 := newId(req)
|
|
||||||
So(id1, ShouldNotEqual, id2)
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Max connections", t, func() {
|
|
||||||
server, _ := NewServer(nil)
|
|
||||||
server.SetMaxConnection(1)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for i := 0; i < 3; i++ {
|
|
||||||
server.Accept()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
req1 := newOpenReq()
|
|
||||||
res1 := httptest.NewRecorder()
|
|
||||||
server.ServeHTTP(res1, req1)
|
|
||||||
So(res1.Code, ShouldEqual, 200)
|
|
||||||
|
|
||||||
req2 := newOpenReq()
|
|
||||||
res2 := httptest.NewRecorder()
|
|
||||||
server.ServeHTTP(res2, req2)
|
|
||||||
So(res2.Code, ShouldEqual, 503)
|
|
||||||
So(strings.TrimSpace(string(res2.Body.Bytes())), ShouldEqual, "too many connections")
|
|
||||||
|
|
||||||
server.onClose(extractSid(res1.Body))
|
|
||||||
|
|
||||||
req3 := newOpenReq()
|
|
||||||
res3 := httptest.NewRecorder()
|
|
||||||
server.ServeHTTP(res3, req3)
|
|
||||||
So(res3.Code, ShouldEqual, 200)
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func newOpenReq() *http.Request {
|
|
||||||
openReq, _ := http.NewRequest("GET", "/", bytes.NewBuffer([]byte{}))
|
|
||||||
q := openReq.URL.Query()
|
|
||||||
q.Set("transport", "polling")
|
|
||||||
openReq.URL.RawQuery = q.Encode()
|
|
||||||
return openReq
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractSid(body io.Reader) string {
|
|
||||||
payload := parser.NewPayloadDecoder(body)
|
|
||||||
packet, _ := payload.Next()
|
|
||||||
openRes := map[string]interface{}{}
|
|
||||||
json.NewDecoder(packet).Decode(&openRes)
|
|
||||||
return openRes["sid"].(string)
|
|
||||||
}
|
|
25
vendor/github.com/googollee/go-engine.io/sessions_test.go
generated
vendored
25
vendor/github.com/googollee/go-engine.io/sessions_test.go
generated
vendored
@ -1,25 +0,0 @@
|
|||||||
package engineio
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestServerSessions(t *testing.T) {
|
|
||||||
Convey("Server sessions", t, func() {
|
|
||||||
sessions := newServerSessions()
|
|
||||||
|
|
||||||
So(sessions.Get("a"), ShouldBeNil)
|
|
||||||
|
|
||||||
sessions.Set("b", new(serverConn))
|
|
||||||
So(sessions.Get("b"), ShouldNotBeNil)
|
|
||||||
|
|
||||||
So(sessions.Get("a"), ShouldBeNil)
|
|
||||||
|
|
||||||
sessions.Set("c", new(serverConn))
|
|
||||||
So(sessions.Get("c"), ShouldNotBeNil)
|
|
||||||
|
|
||||||
sessions.Remove("b")
|
|
||||||
So(sessions.Get("b"), ShouldBeNil)
|
|
||||||
})
|
|
||||||
}
|
|
458
vendor/github.com/googollee/go-engine.io/websocket/websocket_test.go
generated
vendored
458
vendor/github.com/googollee/go-engine.io/websocket/websocket_test.go
generated
vendored
@ -1,458 +0,0 @@
|
|||||||
package websocket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"net/url"
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/googollee/go-engine.io/transport"
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
|
|
||||||
"github.com/googollee/go-engine.io/message"
|
|
||||||
"github.com/googollee/go-engine.io/parser"
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestWebsocket(t *testing.T) {
|
|
||||||
|
|
||||||
Convey("Creater", t, func() {
|
|
||||||
So(Creater.Name, ShouldEqual, "websocket")
|
|
||||||
So(Creater.Server, ShouldEqual, NewServer)
|
|
||||||
So(Creater.Client, ShouldEqual, NewClient)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Normal work, server part", t, func() {
|
|
||||||
sync := make(chan int)
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
f := newFakeCallback()
|
|
||||||
s, err := NewServer(w, r, f)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
{
|
|
||||||
req, err := http.NewRequest("GET", "/", nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
recoder := httptest.NewRecorder()
|
|
||||||
s.ServeHTTP(recoder, req)
|
|
||||||
if recoder.Code != http.StatusBadRequest {
|
|
||||||
t.Fatal(recoder.Code, "!=", http.StatusBadRequest)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
w, err := s.NextWriter(message.MessageText, parser.OPEN)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
err = w.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
<-f.onPacket
|
|
||||||
if f.messageType != message.MessageBinary {
|
|
||||||
t.Fatal(f.messageType, "!=", message.MessageBinary)
|
|
||||||
}
|
|
||||||
if f.packetType != parser.MESSAGE {
|
|
||||||
t.Fatal(f.packetType, "!=", parser.MESSAGE)
|
|
||||||
}
|
|
||||||
if f.err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if body := string(f.body); body != "测试" {
|
|
||||||
t.Fatal(body, "!=", "测试")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<-sync
|
|
||||||
sync <- 1
|
|
||||||
|
|
||||||
<-sync
|
|
||||||
sync <- 1
|
|
||||||
|
|
||||||
{
|
|
||||||
w, err := s.NextWriter(message.MessageBinary, parser.NOOP)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
err = w.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<-sync
|
|
||||||
sync <- 1
|
|
||||||
|
|
||||||
{
|
|
||||||
<-f.onPacket
|
|
||||||
if f.messageType != message.MessageText {
|
|
||||||
t.Fatal(f.messageType, "!=", message.MessageText)
|
|
||||||
}
|
|
||||||
if f.packetType != parser.MESSAGE {
|
|
||||||
t.Fatal(f.packetType, "!=", parser.MESSAGE)
|
|
||||||
}
|
|
||||||
if f.err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if body := hex.EncodeToString(f.body); body != "e697a5e69cace8aa9e" {
|
|
||||||
t.Fatal(body, "!=", "e697a5e69cace8aa9e")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<-sync
|
|
||||||
sync <- 1
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
u, _ := url.Parse(server.URL)
|
|
||||||
u.Scheme = "ws"
|
|
||||||
req, err := http.NewRequest("GET", u.String(), nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
c, _ := NewClient(req)
|
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
{
|
|
||||||
w, _ := c.NextWriter(message.MessageBinary, parser.MESSAGE)
|
|
||||||
w.Write([]byte("测试"))
|
|
||||||
w.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
<-sync
|
|
||||||
|
|
||||||
{
|
|
||||||
decoder, _ := c.NextReader()
|
|
||||||
defer decoder.Close()
|
|
||||||
ioutil.ReadAll(decoder)
|
|
||||||
}
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
<-sync
|
|
||||||
|
|
||||||
{
|
|
||||||
decoder, _ := c.NextReader()
|
|
||||||
defer decoder.Close()
|
|
||||||
ioutil.ReadAll(decoder)
|
|
||||||
}
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
<-sync
|
|
||||||
|
|
||||||
{
|
|
||||||
w, _ := c.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
w.Write([]byte("日本語"))
|
|
||||||
w.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
<-sync
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Normal work, client part", t, func() {
|
|
||||||
sync := make(chan int)
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
f := newFakeCallback()
|
|
||||||
if v := r.URL.Query().Get("key"); v != "value" {
|
|
||||||
t.Fatal(v, "!=", "value")
|
|
||||||
}
|
|
||||||
s, _ := NewServer(w, r, f)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
{
|
|
||||||
w, _ := s.NextWriter(message.MessageText, parser.OPEN)
|
|
||||||
w.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
<-f.onPacket
|
|
||||||
}
|
|
||||||
|
|
||||||
<-sync
|
|
||||||
sync <- 1
|
|
||||||
|
|
||||||
<-sync
|
|
||||||
sync <- 1
|
|
||||||
|
|
||||||
{
|
|
||||||
w, _ := s.NextWriter(message.MessageBinary, parser.NOOP)
|
|
||||||
w.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
<-sync
|
|
||||||
sync <- 1
|
|
||||||
|
|
||||||
{
|
|
||||||
<-f.onPacket
|
|
||||||
}
|
|
||||||
|
|
||||||
<-sync
|
|
||||||
sync <- 1
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
u, err := url.Parse(server.URL)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
u.Scheme = "ws"
|
|
||||||
req, err := http.NewRequest("GET", u.String()+"/?key=value", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
c, err := NewClient(req)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
So(c.Response(), ShouldNotBeNil)
|
|
||||||
So(c.Response().StatusCode, ShouldEqual, http.StatusSwitchingProtocols)
|
|
||||||
|
|
||||||
{
|
|
||||||
w, err := c.NextWriter(message.MessageBinary, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = w.Write([]byte("测试"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = w.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
<-sync
|
|
||||||
|
|
||||||
{
|
|
||||||
decoder, err := c.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
defer decoder.Close()
|
|
||||||
So(decoder.MessageType(), ShouldEqual, message.MessageText)
|
|
||||||
So(decoder.Type(), ShouldEqual, parser.OPEN)
|
|
||||||
b, err := ioutil.ReadAll(decoder)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(string(b), ShouldEqual, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
<-sync
|
|
||||||
|
|
||||||
{
|
|
||||||
decoder, err := c.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
defer decoder.Close()
|
|
||||||
So(decoder.MessageType(), ShouldEqual, message.MessageBinary)
|
|
||||||
So(decoder.Type(), ShouldEqual, parser.NOOP)
|
|
||||||
b, err := ioutil.ReadAll(decoder)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(string(b), ShouldEqual, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
<-sync
|
|
||||||
|
|
||||||
{
|
|
||||||
w, err := c.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
_, err = w.Write([]byte("日本語"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = w.Close()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
<-sync
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Packet content", t, func() {
|
|
||||||
sync := make(chan int)
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
f := newFakeCallback()
|
|
||||||
s, _ := NewServer(w, r, f)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
{
|
|
||||||
w, _ := s.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
w.Write([]byte("日本語"))
|
|
||||||
w.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
sync <- 1
|
|
||||||
<-sync
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
u, err := url.Parse(server.URL)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
u.Scheme = "ws"
|
|
||||||
req, err := http.NewRequest("GET", u.String(), nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
c, err := NewClient(req)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
{
|
|
||||||
client := c.(*client)
|
|
||||||
t, r, err := client.conn.NextReader()
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(t, ShouldEqual, websocket.TextMessage)
|
|
||||||
b, err := ioutil.ReadAll(r)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(string(b), ShouldEqual, "4日本語")
|
|
||||||
So(hex.EncodeToString(b), ShouldEqual, "34e697a5e69cace8aa9e")
|
|
||||||
}
|
|
||||||
|
|
||||||
<-sync
|
|
||||||
sync <- 1
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Close", t, func() {
|
|
||||||
f := newFakeCallback()
|
|
||||||
var s transport.Server
|
|
||||||
sync := make(chan int)
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
s, _ = NewServer(w, r, f)
|
|
||||||
s.Close()
|
|
||||||
s.Close()
|
|
||||||
s.Close()
|
|
||||||
sync <- 1
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
u, err := url.Parse(server.URL)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
u.Scheme = "ws"
|
|
||||||
req, err := http.NewRequest("GET", u.String(), nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
c, err := NewClient(req)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
<-sync
|
|
||||||
|
|
||||||
waitForClose(f)
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 1)
|
|
||||||
So(f.closeServer, ShouldEqual, s)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Closing by disconnected", t, func() {
|
|
||||||
f := newFakeCallback()
|
|
||||||
sync := make(chan int)
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
s, _ := NewServer(w, r, f)
|
|
||||||
server := s.(*Server)
|
|
||||||
server.conn.Close()
|
|
||||||
sync <- 1
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
u, err := url.Parse(server.URL)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
u.Scheme = "ws"
|
|
||||||
req, err := http.NewRequest("GET", u.String(), nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
c, err := NewClient(req)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
<-sync
|
|
||||||
waitForClose(f)
|
|
||||||
So(f.ClosedCount(), ShouldEqual, 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Closing writer after closed", t, func() {
|
|
||||||
f := newFakeCallback()
|
|
||||||
sync := make(chan int)
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
s, err := NewServer(w, r, f)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
writer, err := s.NextWriter(message.MessageText, parser.MESSAGE)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
err = s.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
err = writer.Close()
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("err should not be nil")
|
|
||||||
}
|
|
||||||
sync <- 1
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
u, _ := url.Parse(server.URL)
|
|
||||||
u.Scheme = "ws"
|
|
||||||
req, _ := http.NewRequest("GET", u.String(), nil)
|
|
||||||
|
|
||||||
c, _ := NewClient(req)
|
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
<-sync
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func waitForClose(f *fakeCallback) {
|
|
||||||
timeout := time.After(5 * time.Second)
|
|
||||||
|
|
||||||
var closed bool
|
|
||||||
select {
|
|
||||||
case <-f.closedChan:
|
|
||||||
closed = true
|
|
||||||
case <-timeout:
|
|
||||||
}
|
|
||||||
So(closed, ShouldBeTrue)
|
|
||||||
}
|
|
||||||
|
|
||||||
type fakeCallback struct {
|
|
||||||
onPacket chan bool
|
|
||||||
messageType message.MessageType
|
|
||||||
packetType parser.PacketType
|
|
||||||
body []byte
|
|
||||||
err error
|
|
||||||
closedCount int
|
|
||||||
countLocker sync.Mutex
|
|
||||||
closeServer transport.Server
|
|
||||||
closedChan chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFakeCallback() *fakeCallback {
|
|
||||||
return &fakeCallback{
|
|
||||||
onPacket: make(chan bool),
|
|
||||||
closedChan: make(chan struct{}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fakeCallback) OnPacket(r *parser.PacketDecoder) {
|
|
||||||
f.packetType = r.Type()
|
|
||||||
f.messageType = r.MessageType()
|
|
||||||
f.body, f.err = ioutil.ReadAll(r)
|
|
||||||
f.onPacket <- true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fakeCallback) OnClose(s transport.Server) {
|
|
||||||
f.countLocker.Lock()
|
|
||||||
defer f.countLocker.Unlock()
|
|
||||||
f.closedCount++
|
|
||||||
f.closeServer = s
|
|
||||||
if f.closedCount == 1 {
|
|
||||||
close(f.closedChan)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fakeCallback) ClosedCount() int {
|
|
||||||
f.countLocker.Lock()
|
|
||||||
defer f.countLocker.Unlock()
|
|
||||||
return f.closedCount
|
|
||||||
}
|
|
184
vendor/github.com/googollee/go-socket.io/attachment_test.go
generated
vendored
184
vendor/github.com/googollee/go-socket.io/attachment_test.go
generated
vendored
@ -1,184 +0,0 @@
|
|||||||
package socketio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"io"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
type NoAttachment struct {
|
|
||||||
I int `json:"i"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HaveAttachment struct {
|
|
||||||
NoAttachment
|
|
||||||
A *Attachment `json:"a"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEncodeAttachments(t *testing.T) {
|
|
||||||
var input interface{}
|
|
||||||
var target []io.Reader
|
|
||||||
buf1 := bytes.NewBufferString("data1")
|
|
||||||
buf2 := bytes.NewBufferString("data2")
|
|
||||||
attachment1 := &Attachment{Data: buf1}
|
|
||||||
attachment2 := &Attachment{Data: buf2}
|
|
||||||
|
|
||||||
test := func() {
|
|
||||||
attachment1.num = -1
|
|
||||||
attachment2.num = -1
|
|
||||||
attachments := encodeAttachments(input)
|
|
||||||
if len(attachments)+len(target) > 0 {
|
|
||||||
So(attachments, ShouldResemble, target)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("No attachment", t, func() {
|
|
||||||
input = &NoAttachment{}
|
|
||||||
target = nil
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Many attachment", t, func() {
|
|
||||||
input = &HaveAttachment{A: attachment1}
|
|
||||||
target = []io.Reader{buf1}
|
|
||||||
|
|
||||||
test()
|
|
||||||
|
|
||||||
So(attachment1.num, ShouldEqual, 0)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Array of attachments", t, func() {
|
|
||||||
input = [...]interface{}{HaveAttachment{A: attachment1}, &HaveAttachment{A: attachment2}}
|
|
||||||
target = []io.Reader{buf1, buf2}
|
|
||||||
|
|
||||||
test()
|
|
||||||
|
|
||||||
So(attachment1.num, ShouldEqual, 0)
|
|
||||||
So(attachment2.num, ShouldEqual, 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Slice of attachments", t, func() {
|
|
||||||
input = []interface{}{HaveAttachment{A: attachment1}, &HaveAttachment{A: attachment2}}
|
|
||||||
target = []io.Reader{buf1, buf2}
|
|
||||||
|
|
||||||
test()
|
|
||||||
|
|
||||||
So(attachment1.num, ShouldEqual, 0)
|
|
||||||
So(attachment2.num, ShouldEqual, 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Map of attachments", t, func() {
|
|
||||||
input = map[string]interface{}{"test": HaveAttachment{A: attachment1}, "testp": &HaveAttachment{A: attachment2}}
|
|
||||||
|
|
||||||
attachment1.num = -1
|
|
||||||
attachment2.num = -1
|
|
||||||
attachments := encodeAttachments(input)
|
|
||||||
|
|
||||||
So(attachment1.num, ShouldBeIn, []int{0, 1})
|
|
||||||
switch attachment1.num {
|
|
||||||
case 0:
|
|
||||||
So(attachment2.num, ShouldEqual, 1)
|
|
||||||
target = []io.Reader{buf1, buf2}
|
|
||||||
So(attachments, ShouldResemble, target)
|
|
||||||
case 1:
|
|
||||||
So(attachment2.num, ShouldEqual, 0)
|
|
||||||
target = []io.Reader{buf2, buf1}
|
|
||||||
So(attachments, ShouldResemble, target)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Encode attachment", t, func() {
|
|
||||||
input = map[string]interface{}{"test": HaveAttachment{A: attachment1}}
|
|
||||||
|
|
||||||
attachment1.num = -1
|
|
||||||
encodeAttachments(input)
|
|
||||||
|
|
||||||
b, err := json.Marshal(input)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(string(b), ShouldEqual, `{"test":{"i":0,"a":{"_placeholder":true,"num":0}}}`)
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDecodeAttachments(t *testing.T) {
|
|
||||||
var input [][]byte
|
|
||||||
var v interface{}
|
|
||||||
buf1 := bytes.NewBuffer(nil)
|
|
||||||
buf2 := bytes.NewBuffer(nil)
|
|
||||||
var attachment1 *Attachment
|
|
||||||
var attachment2 *Attachment
|
|
||||||
|
|
||||||
test := func() {
|
|
||||||
err := decodeAttachments(v, input)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
if attachment1 != nil {
|
|
||||||
So(buf1.String(), ShouldEqual, "data1")
|
|
||||||
}
|
|
||||||
if attachment2 != nil {
|
|
||||||
So(buf2.String(), ShouldEqual, "data2")
|
|
||||||
}
|
|
||||||
buf1.Reset()
|
|
||||||
buf2.Reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("No attachment", t, func() {
|
|
||||||
input = nil
|
|
||||||
v = NoAttachment{}
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Many attachment", t, func() {
|
|
||||||
input = [][]byte{[]byte("data1")}
|
|
||||||
attachment1 = &Attachment{Data: buf1}
|
|
||||||
attachment1.num = 0
|
|
||||||
v = HaveAttachment{A: attachment1}
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Array of attachments", t, func() {
|
|
||||||
input = [][]byte{[]byte("data1"), []byte("data2")}
|
|
||||||
attachment1 = &Attachment{Data: buf1}
|
|
||||||
attachment1.num = 0
|
|
||||||
attachment2 = &Attachment{Data: buf2}
|
|
||||||
attachment2.num = 1
|
|
||||||
v = [...]interface{}{HaveAttachment{A: attachment1}, &HaveAttachment{A: attachment2}}
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Slice of attachments", t, func() {
|
|
||||||
input = [][]byte{[]byte("data1"), []byte("data2")}
|
|
||||||
attachment1 = &Attachment{Data: buf1}
|
|
||||||
attachment1.num = 0
|
|
||||||
attachment2 = &Attachment{Data: buf2}
|
|
||||||
attachment2.num = 1
|
|
||||||
v = []interface{}{HaveAttachment{A: attachment1}, &HaveAttachment{A: attachment2}}
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Map of attachments", t, func() {
|
|
||||||
input = [][]byte{[]byte("data1"), []byte("data2")}
|
|
||||||
attachment1 = &Attachment{Data: buf1}
|
|
||||||
attachment1.num = 0
|
|
||||||
attachment2 = &Attachment{Data: buf2}
|
|
||||||
attachment2.num = 1
|
|
||||||
v = map[string]interface{}{"test": HaveAttachment{A: attachment1}, "testp": &HaveAttachment{A: attachment2}}
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Deocde json", t, func() {
|
|
||||||
b := []byte(`{"i":0,"a":{"_placeholder":true,"num":2}}`)
|
|
||||||
v := &HaveAttachment{}
|
|
||||||
err := json.Unmarshal(b, &v)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(v.A.num, ShouldEqual, 2)
|
|
||||||
})
|
|
||||||
}
|
|
38
vendor/github.com/googollee/go-socket.io/example/asset/index.html
generated
vendored
38
vendor/github.com/googollee/go-socket.io/example/asset/index.html
generated
vendored
@ -1,38 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Socket.IO chat</title>
|
|
||||||
<style>
|
|
||||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
||||||
body { font: 13px Helvetica, Arial; }
|
|
||||||
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
|
|
||||||
form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
|
|
||||||
form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
|
|
||||||
#messages { list-style-type: none; margin: 0; padding: 0; }
|
|
||||||
#messages li { padding: 5px 10px; }
|
|
||||||
#messages li:nth-child(odd) { background: #eee; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<ul id="messages"></ul>
|
|
||||||
<form action="">
|
|
||||||
<input id="m" autocomplete="off" /><button>Send</button>
|
|
||||||
</form>
|
|
||||||
<script src="/socket.io-1.3.7.js"></script>
|
|
||||||
<script src="/jquery-1.11.1.js"></script>
|
|
||||||
<script>
|
|
||||||
var socket = io();
|
|
||||||
$('form').submit(function(){
|
|
||||||
socket.emit('chat message with ack', $('#m').val(), function(data){
|
|
||||||
$('#messages').append($('<li>').text('ACK CALLBACK: ' + data));
|
|
||||||
});
|
|
||||||
socket.emit('chat message', $('#m').val());
|
|
||||||
$('#m').val('');
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
socket.on('chat message', function(msg){
|
|
||||||
$('#messages').append($('<li>').text(msg));
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
10308
vendor/github.com/googollee/go-socket.io/example/asset/jquery-1.11.1.js
generated
vendored
10308
vendor/github.com/googollee/go-socket.io/example/asset/jquery-1.11.1.js
generated
vendored
File diff suppressed because it is too large
Load Diff
3
vendor/github.com/googollee/go-socket.io/example/asset/socket.io-1.3.7.js
generated
vendored
3
vendor/github.com/googollee/go-socket.io/example/asset/socket.io-1.3.7.js
generated
vendored
File diff suppressed because one or more lines are too long
53
vendor/github.com/googollee/go-socket.io/example/main.go
generated
vendored
53
vendor/github.com/googollee/go-socket.io/example/main.go
generated
vendored
@ -1,53 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/googollee/go-socket.io"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
server, err := socketio.NewServer(nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
server.On("connection", func(so socketio.Socket) {
|
|
||||||
log.Println("on connection")
|
|
||||||
so.Join("chat")
|
|
||||||
so.On("chat message", func(msg string) {
|
|
||||||
m := make(map[string]interface{})
|
|
||||||
m["a"] = "你好"
|
|
||||||
e := so.Emit("cn1111", m)
|
|
||||||
//这个没有问题
|
|
||||||
fmt.Println("\n\n")
|
|
||||||
|
|
||||||
b := make(map[string]string)
|
|
||||||
b["u-a"] = "中文内容" //这个不能是中文
|
|
||||||
m["b-c"] = b
|
|
||||||
e = so.Emit("cn2222", m)
|
|
||||||
log.Println(e)
|
|
||||||
|
|
||||||
log.Println("emit:", so.Emit("chat message", msg))
|
|
||||||
so.BroadcastTo("chat", "chat message", msg)
|
|
||||||
})
|
|
||||||
// Socket.io acknowledgement example
|
|
||||||
// The return type may vary depending on whether you will return
|
|
||||||
// For this example it is "string" type
|
|
||||||
so.On("chat message with ack", func(msg string) string {
|
|
||||||
return msg
|
|
||||||
})
|
|
||||||
so.On("disconnection", func() {
|
|
||||||
log.Println("on disconnect")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
server.On("error", func(so socketio.Socket, err error) {
|
|
||||||
log.Println("error:", err)
|
|
||||||
})
|
|
||||||
|
|
||||||
http.Handle("/socket.io/", server)
|
|
||||||
http.Handle("/", http.FileServer(http.Dir("./asset")))
|
|
||||||
log.Println("Serving at localhost:5000...")
|
|
||||||
log.Fatal(http.ListenAndServe(":5000", nil))
|
|
||||||
}
|
|
105
vendor/github.com/googollee/go-socket.io/handler_test.go
generated
vendored
105
vendor/github.com/googollee/go-socket.io/handler_test.go
generated
vendored
@ -1,105 +0,0 @@
|
|||||||
package socketio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
"net/http"
|
|
||||||
"io"
|
|
||||||
"github.com/googollee/go-engine.io"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FakeBroadcastAdaptor struct {}
|
|
||||||
|
|
||||||
func (f *FakeBroadcastAdaptor) Join(room string, socket Socket) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeBroadcastAdaptor) Leave(room string, socket Socket) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeBroadcastAdaptor) Send(ignore Socket, room, event string, args ...interface{}) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type FakeReadCloser struct {}
|
|
||||||
|
|
||||||
func (fr *FakeReadCloser) Read(p []byte) (n int, err error) {
|
|
||||||
p = append(p, byte(128))
|
|
||||||
return 1, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fr *FakeReadCloser) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type FakeWriteCloser struct {}
|
|
||||||
|
|
||||||
func (fr *FakeWriteCloser) Write(p []byte) (n int, err error) {
|
|
||||||
return len(p), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fr *FakeWriteCloser) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type FakeSockConnection struct {}
|
|
||||||
|
|
||||||
func (f *FakeSockConnection) Id() string {
|
|
||||||
return "test1"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeSockConnection) Request() *http.Request {
|
|
||||||
return &http.Request{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeSockConnection) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeSockConnection) NextReader() (engineio.MessageType, io.ReadCloser, error) {
|
|
||||||
return engineio.MessageText, &FakeReadCloser{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeSockConnection) NextWriter(messageType engineio.MessageType) (io.WriteCloser, error) {
|
|
||||||
return &FakeWriteCloser{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func TestHandler(t *testing.T) {
|
|
||||||
//BugFix missed
|
|
||||||
//Method: handler.onPacket
|
|
||||||
//Reason: missed fallthrough after case _ACK:
|
|
||||||
//
|
|
||||||
// case _ACK:
|
|
||||||
// fallthrough <---- fixed problem
|
|
||||||
//
|
|
||||||
Convey("Call ACK handler by ACK id received from client", t, func() {
|
|
||||||
saver := &FrameSaver{}
|
|
||||||
var handlerCalled bool
|
|
||||||
baseHandlerInstance := newBaseHandler("some:event", &FakeBroadcastAdaptor{})
|
|
||||||
socketInstance := newSocket(&FakeSockConnection{}, baseHandlerInstance)
|
|
||||||
c, _ := newCaller(func () {handlerCalled = true})
|
|
||||||
|
|
||||||
socketInstance.acks[0] = c
|
|
||||||
socketInstance.onPacket(newDecoder(saver), &packet{Type:_ACK, Id:0, Data:"[]", NSP:"/"})
|
|
||||||
|
|
||||||
So(len(socketInstance.acks), ShouldEqual, 0)
|
|
||||||
So(handlerCalled, ShouldBeTrue)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Call BINARY ACK handler by BINARY ACK id received from client", t, func() {
|
|
||||||
saver := &FrameSaver{}
|
|
||||||
var handlerCalled bool
|
|
||||||
baseHandlerInstance := newBaseHandler("some:event", &FakeBroadcastAdaptor{})
|
|
||||||
socketInstance := newSocket(&FakeSockConnection{}, baseHandlerInstance)
|
|
||||||
c, _ := newCaller(func () {handlerCalled = true})
|
|
||||||
|
|
||||||
socketInstance.acks[0] = c
|
|
||||||
socketInstance.onPacket(newDecoder(saver), &packet{Type:_BINARY_ACK, Id:0, Data:"[]", NSP:"/"})
|
|
||||||
|
|
||||||
So(len(socketInstance.acks), ShouldEqual, 0)
|
|
||||||
So(handlerCalled, ShouldBeTrue)
|
|
||||||
})
|
|
||||||
}
|
|
50
vendor/github.com/googollee/go-socket.io/helper_test.go
generated
vendored
50
vendor/github.com/googollee/go-socket.io/helper_test.go
generated
vendored
@ -1,50 +0,0 @@
|
|||||||
package socketio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"github.com/googollee/go-engine.io"
|
|
||||||
)
|
|
||||||
|
|
||||||
type WriterNopCloser struct {
|
|
||||||
io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewWriterNopCloser(w io.Writer) io.WriteCloser {
|
|
||||||
return WriterNopCloser{
|
|
||||||
Writer: w,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w WriterNopCloser) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type FrameData struct {
|
|
||||||
Buffer *bytes.Buffer
|
|
||||||
Type engineio.MessageType
|
|
||||||
}
|
|
||||||
|
|
||||||
type FrameSaver struct {
|
|
||||||
data []FrameData
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FrameSaver) NextWriter(t engineio.MessageType) (io.WriteCloser, error) {
|
|
||||||
data := FrameData{
|
|
||||||
Buffer: bytes.NewBuffer(nil),
|
|
||||||
Type: t,
|
|
||||||
}
|
|
||||||
f.data = append(f.data, data)
|
|
||||||
return NewWriterNopCloser(data.Buffer), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FrameSaver) NextReader() (engineio.MessageType, io.ReadCloser, error) {
|
|
||||||
if len(f.data) == 0 {
|
|
||||||
return engineio.MessageText, nil, io.EOF
|
|
||||||
}
|
|
||||||
ret := f.data[0]
|
|
||||||
f.data = f.data[1:]
|
|
||||||
return ret.Type, ioutil.NopCloser(ret.Buffer), nil
|
|
||||||
}
|
|
54
vendor/github.com/googollee/go-socket.io/message_reader_test.go
generated
vendored
54
vendor/github.com/googollee/go-socket.io/message_reader_test.go
generated
vendored
@ -1,54 +0,0 @@
|
|||||||
package socketio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMessageReader(t *testing.T) {
|
|
||||||
|
|
||||||
Convey("Read with args", t, func() {
|
|
||||||
buf := bufio.NewReader(bytes.NewBufferString(`["message",1]`))
|
|
||||||
reader, err := newMessageReader(buf)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(reader.Message(), ShouldEqual, "message")
|
|
||||||
b, err := ioutil.ReadAll(reader)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(string(b), ShouldEqual, "[1]")
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Read with args, space", t, func() {
|
|
||||||
buf := bufio.NewReader(bytes.NewBufferString(`["message" , 1]`))
|
|
||||||
reader, err := newMessageReader(buf)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(reader.Message(), ShouldEqual, "message")
|
|
||||||
b, err := ioutil.ReadAll(reader)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(string(b), ShouldEqual, "[ 1]")
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Read only message", t, func() {
|
|
||||||
buf := bufio.NewReader(bytes.NewBufferString(`["message"]`))
|
|
||||||
reader, err := newMessageReader(buf)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(reader.Message(), ShouldEqual, "message")
|
|
||||||
b, err := ioutil.ReadAll(reader)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(string(b), ShouldEqual, "[]")
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Read only message", t, func() {
|
|
||||||
buf := bufio.NewReader(bytes.NewBufferString(`["message" ]`))
|
|
||||||
reader, err := newMessageReader(buf)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(reader.Message(), ShouldEqual, "message")
|
|
||||||
b, err := ioutil.ReadAll(reader)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(string(b), ShouldEqual, "[]")
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
191
vendor/github.com/googollee/go-socket.io/parser_test.go
generated
vendored
191
vendor/github.com/googollee/go-socket.io/parser_test.go
generated
vendored
@ -1,191 +0,0 @@
|
|||||||
package socketio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"github.com/googollee/go-engine.io"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPacketType(t *testing.T) {
|
|
||||||
|
|
||||||
Convey("Type string", t, func() {
|
|
||||||
So(_CONNECT, ShouldEqual, 0)
|
|
||||||
So(_CONNECT.String(), ShouldEqual, "connect")
|
|
||||||
So(_DISCONNECT, ShouldEqual, 1)
|
|
||||||
So(_DISCONNECT.String(), ShouldEqual, "disconnect")
|
|
||||||
So(_EVENT, ShouldEqual, 2)
|
|
||||||
So(_EVENT.String(), ShouldEqual, "event")
|
|
||||||
So(_ACK, ShouldEqual, 3)
|
|
||||||
So(_ACK.String(), ShouldEqual, "ack")
|
|
||||||
So(_ERROR, ShouldEqual, 4)
|
|
||||||
So(_ERROR.String(), ShouldEqual, "error")
|
|
||||||
So(_BINARY_EVENT, ShouldEqual, 5)
|
|
||||||
So(_BINARY_EVENT.String(), ShouldEqual, "binary_event")
|
|
||||||
So(_BINARY_ACK, ShouldEqual, 6)
|
|
||||||
So(_BINARY_ACK.String(), ShouldEqual, "binary_ack")
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParser(t *testing.T) {
|
|
||||||
p := packet{}
|
|
||||||
var decodeData interface{}
|
|
||||||
output := ""
|
|
||||||
message := ""
|
|
||||||
|
|
||||||
test := func() {
|
|
||||||
saver := &FrameSaver{}
|
|
||||||
encoder := newEncoder(saver)
|
|
||||||
err := encoder.Encode(p)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(len(saver.data), ShouldBeGreaterThan, 0)
|
|
||||||
So(saver.data[0].Buffer.String(), ShouldEqual, output)
|
|
||||||
So(saver.data[0].Type, ShouldEqual, engineio.MessageText)
|
|
||||||
if len(saver.data) > 1 {
|
|
||||||
So(saver.data[1].Buffer.String(), ShouldEqual, "data")
|
|
||||||
So(saver.data[1].Type, ShouldEqual, engineio.MessageBinary)
|
|
||||||
}
|
|
||||||
|
|
||||||
d := packet{Data: decodeData}
|
|
||||||
decoder := newDecoder(saver)
|
|
||||||
err = decoder.Decode(&d)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(d.Id, ShouldEqual, p.Id)
|
|
||||||
So(d.NSP, ShouldEqual, p.NSP)
|
|
||||||
if decodeData == nil {
|
|
||||||
So(d.Data, ShouldBeNil)
|
|
||||||
}
|
|
||||||
So(decoder.Message(), ShouldEqual, message)
|
|
||||||
err = decoder.DecodeData(&d)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(d.Type, ShouldEqual, p.Type)
|
|
||||||
So(decoder.current, ShouldBeNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("Only type", t, func() {
|
|
||||||
p = packet{
|
|
||||||
Type: _CONNECT,
|
|
||||||
Id: -1,
|
|
||||||
}
|
|
||||||
decodeData = nil
|
|
||||||
output = "0"
|
|
||||||
message = ""
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Type and id", t, func() {
|
|
||||||
p = packet{
|
|
||||||
Type: _EVENT,
|
|
||||||
Id: 1,
|
|
||||||
}
|
|
||||||
decodeData = nil
|
|
||||||
output = "21"
|
|
||||||
message = ""
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Type and namespace", t, func() {
|
|
||||||
p = packet{
|
|
||||||
Type: _EVENT,
|
|
||||||
Id: -1,
|
|
||||||
NSP: "/abc",
|
|
||||||
}
|
|
||||||
decodeData = nil
|
|
||||||
output = "2/abc"
|
|
||||||
message = ""
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Type, id and namespace", t, func() {
|
|
||||||
p = packet{
|
|
||||||
Type: _EVENT,
|
|
||||||
Id: 1,
|
|
||||||
NSP: "/abc",
|
|
||||||
}
|
|
||||||
decodeData = nil
|
|
||||||
output = "2/abc,1"
|
|
||||||
message = ""
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Type, namespace and data", t, func() {
|
|
||||||
p = packet{
|
|
||||||
Type: _EVENT,
|
|
||||||
Id: -1,
|
|
||||||
NSP: "/abc",
|
|
||||||
Data: []interface{}{"numbers", 1, 2, 3},
|
|
||||||
}
|
|
||||||
var i1, i2, i3 int
|
|
||||||
decodeData = &[]interface{}{&i1, &i2, &i3}
|
|
||||||
output = "2/abc,[\"numbers\",1,2,3]"
|
|
||||||
message = "numbers"
|
|
||||||
|
|
||||||
test()
|
|
||||||
|
|
||||||
So(i1, ShouldEqual, 1)
|
|
||||||
So(i2, ShouldEqual, 2)
|
|
||||||
So(i3, ShouldEqual, 3)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Type, namespace, id and data", t, func() {
|
|
||||||
p = packet{
|
|
||||||
Type: _EVENT,
|
|
||||||
Id: 1,
|
|
||||||
NSP: "/abc",
|
|
||||||
Data: []interface{}{"numbers", 1, 2, 3},
|
|
||||||
}
|
|
||||||
var i1, i2, i3 int
|
|
||||||
decodeData = &[]interface{}{&i1, &i2, &i3}
|
|
||||||
output = "2/abc,1[\"numbers\",1,2,3]"
|
|
||||||
message = "numbers"
|
|
||||||
|
|
||||||
test()
|
|
||||||
|
|
||||||
So(i1, ShouldEqual, 1)
|
|
||||||
So(i2, ShouldEqual, 2)
|
|
||||||
So(i3, ShouldEqual, 3)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Type, namespace, id and data(ack)", t, func() {
|
|
||||||
p = packet{
|
|
||||||
Type: _ACK,
|
|
||||||
Id: 1,
|
|
||||||
NSP: "/abc",
|
|
||||||
Data: []interface{}{1, 2, 3},
|
|
||||||
}
|
|
||||||
var i1, i2, i3 int
|
|
||||||
decodeData = &[]interface{}{&i1, &i2, &i3}
|
|
||||||
output = "3/abc,1[1,2,3]"
|
|
||||||
message = ""
|
|
||||||
|
|
||||||
test()
|
|
||||||
|
|
||||||
So(i1, ShouldEqual, 1)
|
|
||||||
So(i2, ShouldEqual, 2)
|
|
||||||
So(i3, ShouldEqual, 3)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Binary type with attachment", t, func() {
|
|
||||||
p = packet{
|
|
||||||
Type: _EVENT,
|
|
||||||
Id: 1,
|
|
||||||
NSP: "/abc",
|
|
||||||
Data: []interface{}{"binary", &Attachment{Data: bytes.NewBufferString("data")}},
|
|
||||||
}
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
decodeData = &[]interface{}{&Attachment{Data: buf}}
|
|
||||||
output = `51-/abc,1["binary",{"_placeholder":true,"num":0}]`
|
|
||||||
message = "binary"
|
|
||||||
|
|
||||||
test()
|
|
||||||
|
|
||||||
So(buf.String(), ShouldEqual, "data")
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
64
vendor/github.com/googollee/go-socket.io/trim_writer_test.go
generated
vendored
64
vendor/github.com/googollee/go-socket.io/trim_writer_test.go
generated
vendored
@ -1,64 +0,0 @@
|
|||||||
package socketio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTrimWriter(t *testing.T) {
|
|
||||||
var inputs []string
|
|
||||||
var target string
|
|
||||||
var trim string
|
|
||||||
|
|
||||||
test := func() {
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
w := newTrimWriter(buf, trim)
|
|
||||||
for _, str := range inputs {
|
|
||||||
_, err := w.Write([]byte(str))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
}
|
|
||||||
So(buf.String(), ShouldEqual, target)
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("Trim nothing", t, func() {
|
|
||||||
inputs = []string{"1234", "2234"}
|
|
||||||
target = "12342234"
|
|
||||||
trim = ""
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Trim something", t, func() {
|
|
||||||
trim = "34"
|
|
||||||
|
|
||||||
Convey("Something at the end of final packet", func() {
|
|
||||||
inputs = []string{"1234", "2234"}
|
|
||||||
target = "123422"
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Something at the multiple packets", func() {
|
|
||||||
inputs = []string{"1234", "3434"}
|
|
||||||
target = "12"
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Something in the middle of packets", func() {
|
|
||||||
inputs = []string{"1234", "3434", "5678"}
|
|
||||||
target = "123434345678"
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Something in the middle and end of packets", func() {
|
|
||||||
inputs = []string{"1234", "3434", "5678", "9034"}
|
|
||||||
target = "12343434567890"
|
|
||||||
|
|
||||||
test()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
512
vendor/github.com/gorilla/websocket/client_server_test.go
generated
vendored
512
vendor/github.com/gorilla/websocket/client_server_test.go
generated
vendored
@ -1,512 +0,0 @@
|
|||||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package websocket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/base64"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/http/cookiejar"
|
|
||||||
"net/http/httptest"
|
|
||||||
"net/url"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var cstUpgrader = Upgrader{
|
|
||||||
Subprotocols: []string{"p0", "p1"},
|
|
||||||
ReadBufferSize: 1024,
|
|
||||||
WriteBufferSize: 1024,
|
|
||||||
EnableCompression: true,
|
|
||||||
Error: func(w http.ResponseWriter, r *http.Request, status int, reason error) {
|
|
||||||
http.Error(w, reason.Error(), status)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var cstDialer = Dialer{
|
|
||||||
Subprotocols: []string{"p1", "p2"},
|
|
||||||
ReadBufferSize: 1024,
|
|
||||||
WriteBufferSize: 1024,
|
|
||||||
}
|
|
||||||
|
|
||||||
type cstHandler struct{ *testing.T }
|
|
||||||
|
|
||||||
type cstServer struct {
|
|
||||||
*httptest.Server
|
|
||||||
URL string
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
cstPath = "/a/b"
|
|
||||||
cstRawQuery = "x=y"
|
|
||||||
cstRequestURI = cstPath + "?" + cstRawQuery
|
|
||||||
)
|
|
||||||
|
|
||||||
func newServer(t *testing.T) *cstServer {
|
|
||||||
var s cstServer
|
|
||||||
s.Server = httptest.NewServer(cstHandler{t})
|
|
||||||
s.Server.URL += cstRequestURI
|
|
||||||
s.URL = makeWsProto(s.Server.URL)
|
|
||||||
return &s
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTLSServer(t *testing.T) *cstServer {
|
|
||||||
var s cstServer
|
|
||||||
s.Server = httptest.NewTLSServer(cstHandler{t})
|
|
||||||
s.Server.URL += cstRequestURI
|
|
||||||
s.URL = makeWsProto(s.Server.URL)
|
|
||||||
return &s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t cstHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.URL.Path != cstPath {
|
|
||||||
t.Logf("path=%v, want %v", r.URL.Path, cstPath)
|
|
||||||
http.Error(w, "bad path", 400)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.URL.RawQuery != cstRawQuery {
|
|
||||||
t.Logf("query=%v, want %v", r.URL.RawQuery, cstRawQuery)
|
|
||||||
http.Error(w, "bad path", 400)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
subprotos := Subprotocols(r)
|
|
||||||
if !reflect.DeepEqual(subprotos, cstDialer.Subprotocols) {
|
|
||||||
t.Logf("subprotols=%v, want %v", subprotos, cstDialer.Subprotocols)
|
|
||||||
http.Error(w, "bad protocol", 400)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ws, err := cstUpgrader.Upgrade(w, r, http.Header{"Set-Cookie": {"sessionID=1234"}})
|
|
||||||
if err != nil {
|
|
||||||
t.Logf("Upgrade: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer ws.Close()
|
|
||||||
|
|
||||||
if ws.Subprotocol() != "p1" {
|
|
||||||
t.Logf("Subprotocol() = %s, want p1", ws.Subprotocol())
|
|
||||||
ws.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
op, rd, err := ws.NextReader()
|
|
||||||
if err != nil {
|
|
||||||
t.Logf("NextReader: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
wr, err := ws.NextWriter(op)
|
|
||||||
if err != nil {
|
|
||||||
t.Logf("NextWriter: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, err = io.Copy(wr, rd); err != nil {
|
|
||||||
t.Logf("NextWriter: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := wr.Close(); err != nil {
|
|
||||||
t.Logf("Close: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeWsProto(s string) string {
|
|
||||||
return "ws" + strings.TrimPrefix(s, "http")
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendRecv(t *testing.T, ws *Conn) {
|
|
||||||
const message = "Hello World!"
|
|
||||||
if err := ws.SetWriteDeadline(time.Now().Add(time.Second)); err != nil {
|
|
||||||
t.Fatalf("SetWriteDeadline: %v", err)
|
|
||||||
}
|
|
||||||
if err := ws.WriteMessage(TextMessage, []byte(message)); err != nil {
|
|
||||||
t.Fatalf("WriteMessage: %v", err)
|
|
||||||
}
|
|
||||||
if err := ws.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
|
|
||||||
t.Fatalf("SetReadDeadline: %v", err)
|
|
||||||
}
|
|
||||||
_, p, err := ws.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadMessage: %v", err)
|
|
||||||
}
|
|
||||||
if string(p) != message {
|
|
||||||
t.Fatalf("message=%s, want %s", p, message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProxyDial(t *testing.T) {
|
|
||||||
|
|
||||||
s := newServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
surl, _ := url.Parse(s.URL)
|
|
||||||
|
|
||||||
cstDialer.Proxy = http.ProxyURL(surl)
|
|
||||||
|
|
||||||
connect := false
|
|
||||||
origHandler := s.Server.Config.Handler
|
|
||||||
|
|
||||||
// Capture the request Host header.
|
|
||||||
s.Server.Config.Handler = http.HandlerFunc(
|
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method == "CONNECT" {
|
|
||||||
connect = true
|
|
||||||
w.WriteHeader(200)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !connect {
|
|
||||||
t.Log("connect not recieved")
|
|
||||||
http.Error(w, "connect not recieved", 405)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
origHandler.ServeHTTP(w, r)
|
|
||||||
})
|
|
||||||
|
|
||||||
ws, _, err := cstDialer.Dial(s.URL, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Dial: %v", err)
|
|
||||||
}
|
|
||||||
defer ws.Close()
|
|
||||||
sendRecv(t, ws)
|
|
||||||
|
|
||||||
cstDialer.Proxy = http.ProxyFromEnvironment
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProxyAuthorizationDial(t *testing.T) {
|
|
||||||
s := newServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
surl, _ := url.Parse(s.URL)
|
|
||||||
surl.User = url.UserPassword("username", "password")
|
|
||||||
cstDialer.Proxy = http.ProxyURL(surl)
|
|
||||||
|
|
||||||
connect := false
|
|
||||||
origHandler := s.Server.Config.Handler
|
|
||||||
|
|
||||||
// Capture the request Host header.
|
|
||||||
s.Server.Config.Handler = http.HandlerFunc(
|
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
proxyAuth := r.Header.Get("Proxy-Authorization")
|
|
||||||
expectedProxyAuth := "Basic " + base64.StdEncoding.EncodeToString([]byte("username:password"))
|
|
||||||
if r.Method == "CONNECT" && proxyAuth == expectedProxyAuth {
|
|
||||||
connect = true
|
|
||||||
w.WriteHeader(200)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !connect {
|
|
||||||
t.Log("connect with proxy authorization not recieved")
|
|
||||||
http.Error(w, "connect with proxy authorization not recieved", 405)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
origHandler.ServeHTTP(w, r)
|
|
||||||
})
|
|
||||||
|
|
||||||
ws, _, err := cstDialer.Dial(s.URL, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Dial: %v", err)
|
|
||||||
}
|
|
||||||
defer ws.Close()
|
|
||||||
sendRecv(t, ws)
|
|
||||||
|
|
||||||
cstDialer.Proxy = http.ProxyFromEnvironment
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDial(t *testing.T) {
|
|
||||||
s := newServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
ws, _, err := cstDialer.Dial(s.URL, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Dial: %v", err)
|
|
||||||
}
|
|
||||||
defer ws.Close()
|
|
||||||
sendRecv(t, ws)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDialCookieJar(t *testing.T) {
|
|
||||||
s := newServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
jar, _ := cookiejar.New(nil)
|
|
||||||
d := cstDialer
|
|
||||||
d.Jar = jar
|
|
||||||
|
|
||||||
u, _ := parseURL(s.URL)
|
|
||||||
|
|
||||||
switch u.Scheme {
|
|
||||||
case "ws":
|
|
||||||
u.Scheme = "http"
|
|
||||||
case "wss":
|
|
||||||
u.Scheme = "https"
|
|
||||||
}
|
|
||||||
|
|
||||||
cookies := []*http.Cookie{&http.Cookie{Name: "gorilla", Value: "ws", Path: "/"}}
|
|
||||||
d.Jar.SetCookies(u, cookies)
|
|
||||||
|
|
||||||
ws, _, err := d.Dial(s.URL, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Dial: %v", err)
|
|
||||||
}
|
|
||||||
defer ws.Close()
|
|
||||||
|
|
||||||
var gorilla string
|
|
||||||
var sessionID string
|
|
||||||
for _, c := range d.Jar.Cookies(u) {
|
|
||||||
if c.Name == "gorilla" {
|
|
||||||
gorilla = c.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Name == "sessionID" {
|
|
||||||
sessionID = c.Value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if gorilla != "ws" {
|
|
||||||
t.Error("Cookie not present in jar.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if sessionID != "1234" {
|
|
||||||
t.Error("Set-Cookie not received from the server.")
|
|
||||||
}
|
|
||||||
|
|
||||||
sendRecv(t, ws)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDialTLS(t *testing.T) {
|
|
||||||
s := newTLSServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
certs := x509.NewCertPool()
|
|
||||||
for _, c := range s.TLS.Certificates {
|
|
||||||
roots, err := x509.ParseCertificates(c.Certificate[len(c.Certificate)-1])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error parsing server's root cert: %v", err)
|
|
||||||
}
|
|
||||||
for _, root := range roots {
|
|
||||||
certs.AddCert(root)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
d := cstDialer
|
|
||||||
d.TLSClientConfig = &tls.Config{RootCAs: certs}
|
|
||||||
ws, _, err := d.Dial(s.URL, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Dial: %v", err)
|
|
||||||
}
|
|
||||||
defer ws.Close()
|
|
||||||
sendRecv(t, ws)
|
|
||||||
}
|
|
||||||
|
|
||||||
func xTestDialTLSBadCert(t *testing.T) {
|
|
||||||
// This test is deactivated because of noisy logging from the net/http package.
|
|
||||||
s := newTLSServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
ws, _, err := cstDialer.Dial(s.URL, nil)
|
|
||||||
if err == nil {
|
|
||||||
ws.Close()
|
|
||||||
t.Fatalf("Dial: nil")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDialTLSNoVerify(t *testing.T) {
|
|
||||||
s := newTLSServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
d := cstDialer
|
|
||||||
d.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
|
||||||
ws, _, err := d.Dial(s.URL, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Dial: %v", err)
|
|
||||||
}
|
|
||||||
defer ws.Close()
|
|
||||||
sendRecv(t, ws)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDialTimeout(t *testing.T) {
|
|
||||||
s := newServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
d := cstDialer
|
|
||||||
d.HandshakeTimeout = -1
|
|
||||||
ws, _, err := d.Dial(s.URL, nil)
|
|
||||||
if err == nil {
|
|
||||||
ws.Close()
|
|
||||||
t.Fatalf("Dial: nil")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDialBadScheme(t *testing.T) {
|
|
||||||
s := newServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
ws, _, err := cstDialer.Dial(s.Server.URL, nil)
|
|
||||||
if err == nil {
|
|
||||||
ws.Close()
|
|
||||||
t.Fatalf("Dial: nil")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDialBadOrigin(t *testing.T) {
|
|
||||||
s := newServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
ws, resp, err := cstDialer.Dial(s.URL, http.Header{"Origin": {"bad"}})
|
|
||||||
if err == nil {
|
|
||||||
ws.Close()
|
|
||||||
t.Fatalf("Dial: nil")
|
|
||||||
}
|
|
||||||
if resp == nil {
|
|
||||||
t.Fatalf("resp=nil, err=%v", err)
|
|
||||||
}
|
|
||||||
if resp.StatusCode != http.StatusForbidden {
|
|
||||||
t.Fatalf("status=%d, want %d", resp.StatusCode, http.StatusForbidden)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDialBadHeader(t *testing.T) {
|
|
||||||
s := newServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
for _, k := range []string{"Upgrade",
|
|
||||||
"Connection",
|
|
||||||
"Sec-Websocket-Key",
|
|
||||||
"Sec-Websocket-Version",
|
|
||||||
"Sec-Websocket-Protocol"} {
|
|
||||||
h := http.Header{}
|
|
||||||
h.Set(k, "bad")
|
|
||||||
ws, _, err := cstDialer.Dial(s.URL, http.Header{"Origin": {"bad"}})
|
|
||||||
if err == nil {
|
|
||||||
ws.Close()
|
|
||||||
t.Errorf("Dial with header %s returned nil", k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBadMethod(t *testing.T) {
|
|
||||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
ws, err := cstUpgrader.Upgrade(w, r, nil)
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("handshake succeeded, expect fail")
|
|
||||||
ws.Close()
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
resp, err := http.PostForm(s.URL, url.Values{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("PostForm returned error %v", err)
|
|
||||||
}
|
|
||||||
resp.Body.Close()
|
|
||||||
if resp.StatusCode != http.StatusMethodNotAllowed {
|
|
||||||
t.Errorf("Status = %d, want %d", resp.StatusCode, http.StatusMethodNotAllowed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHandshake(t *testing.T) {
|
|
||||||
s := newServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
ws, resp, err := cstDialer.Dial(s.URL, http.Header{"Origin": {s.URL}})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Dial: %v", err)
|
|
||||||
}
|
|
||||||
defer ws.Close()
|
|
||||||
|
|
||||||
var sessionID string
|
|
||||||
for _, c := range resp.Cookies() {
|
|
||||||
if c.Name == "sessionID" {
|
|
||||||
sessionID = c.Value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if sessionID != "1234" {
|
|
||||||
t.Error("Set-Cookie not received from the server.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ws.Subprotocol() != "p1" {
|
|
||||||
t.Errorf("ws.Subprotocol() = %s, want p1", ws.Subprotocol())
|
|
||||||
}
|
|
||||||
sendRecv(t, ws)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRespOnBadHandshake(t *testing.T) {
|
|
||||||
const expectedStatus = http.StatusGone
|
|
||||||
const expectedBody = "This is the response body."
|
|
||||||
|
|
||||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.WriteHeader(expectedStatus)
|
|
||||||
io.WriteString(w, expectedBody)
|
|
||||||
}))
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
ws, resp, err := cstDialer.Dial(makeWsProto(s.URL), nil)
|
|
||||||
if err == nil {
|
|
||||||
ws.Close()
|
|
||||||
t.Fatalf("Dial: nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp == nil {
|
|
||||||
t.Fatalf("resp=nil, err=%v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != expectedStatus {
|
|
||||||
t.Errorf("resp.StatusCode=%d, want %d", resp.StatusCode, expectedStatus)
|
|
||||||
}
|
|
||||||
|
|
||||||
p, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadFull(resp.Body) returned error %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if string(p) != expectedBody {
|
|
||||||
t.Errorf("resp.Body=%s, want %s", p, expectedBody)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestHostHeader confirms that the host header provided in the call to Dial is
|
|
||||||
// sent to the server.
|
|
||||||
func TestHostHeader(t *testing.T) {
|
|
||||||
s := newServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
specifiedHost := make(chan string, 1)
|
|
||||||
origHandler := s.Server.Config.Handler
|
|
||||||
|
|
||||||
// Capture the request Host header.
|
|
||||||
s.Server.Config.Handler = http.HandlerFunc(
|
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
specifiedHost <- r.Host
|
|
||||||
origHandler.ServeHTTP(w, r)
|
|
||||||
})
|
|
||||||
|
|
||||||
ws, _, err := cstDialer.Dial(s.URL, http.Header{"Host": {"testhost"}})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Dial: %v", err)
|
|
||||||
}
|
|
||||||
defer ws.Close()
|
|
||||||
|
|
||||||
if gotHost := <-specifiedHost; gotHost != "testhost" {
|
|
||||||
t.Fatalf("gotHost = %q, want \"testhost\"", gotHost)
|
|
||||||
}
|
|
||||||
|
|
||||||
sendRecv(t, ws)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDialCompression(t *testing.T) {
|
|
||||||
s := newServer(t)
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
dialer := cstDialer
|
|
||||||
dialer.EnableCompression = true
|
|
||||||
ws, _, err := dialer.Dial(s.URL, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Dial: %v", err)
|
|
||||||
}
|
|
||||||
defer ws.Close()
|
|
||||||
sendRecv(t, ws)
|
|
||||||
}
|
|
72
vendor/github.com/gorilla/websocket/client_test.go
generated
vendored
72
vendor/github.com/gorilla/websocket/client_test.go
generated
vendored
@ -1,72 +0,0 @@
|
|||||||
// Copyright 2014 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package websocket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/url"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var parseURLTests = []struct {
|
|
||||||
s string
|
|
||||||
u *url.URL
|
|
||||||
rui string
|
|
||||||
}{
|
|
||||||
{"ws://example.com/", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}, "/"},
|
|
||||||
{"ws://example.com", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}, "/"},
|
|
||||||
{"ws://example.com:7777/", &url.URL{Scheme: "ws", Host: "example.com:7777", Opaque: "/"}, "/"},
|
|
||||||
{"wss://example.com/", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/"}, "/"},
|
|
||||||
{"wss://example.com/a/b", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b"}, "/a/b"},
|
|
||||||
{"ss://example.com/a/b", nil, ""},
|
|
||||||
{"ws://webmaster@example.com/", nil, ""},
|
|
||||||
{"wss://example.com/a/b?x=y", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b", RawQuery: "x=y"}, "/a/b?x=y"},
|
|
||||||
{"wss://example.com?x=y", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/", RawQuery: "x=y"}, "/?x=y"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseURL(t *testing.T) {
|
|
||||||
for _, tt := range parseURLTests {
|
|
||||||
u, err := parseURL(tt.s)
|
|
||||||
if tt.u != nil && err != nil {
|
|
||||||
t.Errorf("parseURL(%q) returned error %v", tt.s, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if tt.u == nil {
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("parseURL(%q) did not return error", tt.s)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(u, tt.u) {
|
|
||||||
t.Errorf("parseURL(%q) = %v, want %v", tt.s, u, tt.u)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if u.RequestURI() != tt.rui {
|
|
||||||
t.Errorf("parseURL(%q).RequestURI() = %v, want %v", tt.s, u.RequestURI(), tt.rui)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var hostPortNoPortTests = []struct {
|
|
||||||
u *url.URL
|
|
||||||
hostPort, hostNoPort string
|
|
||||||
}{
|
|
||||||
{&url.URL{Scheme: "ws", Host: "example.com"}, "example.com:80", "example.com"},
|
|
||||||
{&url.URL{Scheme: "wss", Host: "example.com"}, "example.com:443", "example.com"},
|
|
||||||
{&url.URL{Scheme: "ws", Host: "example.com:7777"}, "example.com:7777", "example.com"},
|
|
||||||
{&url.URL{Scheme: "wss", Host: "example.com:7777"}, "example.com:7777", "example.com"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHostPortNoPort(t *testing.T) {
|
|
||||||
for _, tt := range hostPortNoPortTests {
|
|
||||||
hostPort, hostNoPort := hostPortNoPort(tt.u)
|
|
||||||
if hostPort != tt.hostPort {
|
|
||||||
t.Errorf("hostPortNoPort(%v) returned hostPort %q, want %q", tt.u, hostPort, tt.hostPort)
|
|
||||||
}
|
|
||||||
if hostNoPort != tt.hostNoPort {
|
|
||||||
t.Errorf("hostPortNoPort(%v) returned hostNoPort %q, want %q", tt.u, hostNoPort, tt.hostNoPort)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
80
vendor/github.com/gorilla/websocket/compression_test.go
generated
vendored
80
vendor/github.com/gorilla/websocket/compression_test.go
generated
vendored
@ -1,80 +0,0 @@
|
|||||||
package websocket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type nopCloser struct{ io.Writer }
|
|
||||||
|
|
||||||
func (nopCloser) Close() error { return nil }
|
|
||||||
|
|
||||||
func TestTruncWriter(t *testing.T) {
|
|
||||||
const data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijlkmnopqrstuvwxyz987654321"
|
|
||||||
for n := 1; n <= 10; n++ {
|
|
||||||
var b bytes.Buffer
|
|
||||||
w := &truncWriter{w: nopCloser{&b}}
|
|
||||||
p := []byte(data)
|
|
||||||
for len(p) > 0 {
|
|
||||||
m := len(p)
|
|
||||||
if m > n {
|
|
||||||
m = n
|
|
||||||
}
|
|
||||||
w.Write(p[:m])
|
|
||||||
p = p[m:]
|
|
||||||
}
|
|
||||||
if b.String() != data[:len(data)-len(w.p)] {
|
|
||||||
t.Errorf("%d: %q", n, b.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func textMessages(num int) [][]byte {
|
|
||||||
messages := make([][]byte, num)
|
|
||||||
for i := 0; i < num; i++ {
|
|
||||||
msg := fmt.Sprintf("planet: %d, country: %d, city: %d, street: %d", i, i, i, i)
|
|
||||||
messages[i] = []byte(msg)
|
|
||||||
}
|
|
||||||
return messages
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkWriteNoCompression(b *testing.B) {
|
|
||||||
w := ioutil.Discard
|
|
||||||
c := newConn(fakeNetConn{Reader: nil, Writer: w}, false, 1024, 1024)
|
|
||||||
messages := textMessages(100)
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
c.WriteMessage(TextMessage, messages[i%len(messages)])
|
|
||||||
}
|
|
||||||
b.ReportAllocs()
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkWriteWithCompression(b *testing.B) {
|
|
||||||
w := ioutil.Discard
|
|
||||||
c := newConn(fakeNetConn{Reader: nil, Writer: w}, false, 1024, 1024)
|
|
||||||
messages := textMessages(100)
|
|
||||||
c.enableWriteCompression = true
|
|
||||||
c.newCompressionWriter = compressNoContextTakeover
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
c.WriteMessage(TextMessage, messages[i%len(messages)])
|
|
||||||
}
|
|
||||||
b.ReportAllocs()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidCompressionLevel(t *testing.T) {
|
|
||||||
c := newConn(fakeNetConn{}, false, 1024, 1024)
|
|
||||||
for _, level := range []int{minCompressionLevel - 1, maxCompressionLevel + 1} {
|
|
||||||
if err := c.SetCompressionLevel(level); err == nil {
|
|
||||||
t.Errorf("no error for level %d", level)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, level := range []int{minCompressionLevel, maxCompressionLevel} {
|
|
||||||
if err := c.SetCompressionLevel(level); err != nil {
|
|
||||||
t.Errorf("error for level %d", level)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
134
vendor/github.com/gorilla/websocket/conn_broadcast_test.go
generated
vendored
134
vendor/github.com/gorilla/websocket/conn_broadcast_test.go
generated
vendored
@ -1,134 +0,0 @@
|
|||||||
// Copyright 2017 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build go1.7
|
|
||||||
|
|
||||||
package websocket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"sync/atomic"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// broadcastBench allows to run broadcast benchmarks.
|
|
||||||
// In every broadcast benchmark we create many connections, then send the same
|
|
||||||
// message into every connection and wait for all writes complete. This emulates
|
|
||||||
// an application where many connections listen to the same data - i.e. PUB/SUB
|
|
||||||
// scenarios with many subscribers in one channel.
|
|
||||||
type broadcastBench struct {
|
|
||||||
w io.Writer
|
|
||||||
message *broadcastMessage
|
|
||||||
closeCh chan struct{}
|
|
||||||
doneCh chan struct{}
|
|
||||||
count int32
|
|
||||||
conns []*broadcastConn
|
|
||||||
compression bool
|
|
||||||
usePrepared bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type broadcastMessage struct {
|
|
||||||
payload []byte
|
|
||||||
prepared *PreparedMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
type broadcastConn struct {
|
|
||||||
conn *Conn
|
|
||||||
msgCh chan *broadcastMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
func newBroadcastConn(c *Conn) *broadcastConn {
|
|
||||||
return &broadcastConn{
|
|
||||||
conn: c,
|
|
||||||
msgCh: make(chan *broadcastMessage, 1),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newBroadcastBench(usePrepared, compression bool) *broadcastBench {
|
|
||||||
bench := &broadcastBench{
|
|
||||||
w: ioutil.Discard,
|
|
||||||
doneCh: make(chan struct{}),
|
|
||||||
closeCh: make(chan struct{}),
|
|
||||||
usePrepared: usePrepared,
|
|
||||||
compression: compression,
|
|
||||||
}
|
|
||||||
msg := &broadcastMessage{
|
|
||||||
payload: textMessages(1)[0],
|
|
||||||
}
|
|
||||||
if usePrepared {
|
|
||||||
pm, _ := NewPreparedMessage(TextMessage, msg.payload)
|
|
||||||
msg.prepared = pm
|
|
||||||
}
|
|
||||||
bench.message = msg
|
|
||||||
bench.makeConns(10000)
|
|
||||||
return bench
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *broadcastBench) makeConns(numConns int) {
|
|
||||||
conns := make([]*broadcastConn, numConns)
|
|
||||||
|
|
||||||
for i := 0; i < numConns; i++ {
|
|
||||||
c := newConn(fakeNetConn{Reader: nil, Writer: b.w}, true, 1024, 1024)
|
|
||||||
if b.compression {
|
|
||||||
c.enableWriteCompression = true
|
|
||||||
c.newCompressionWriter = compressNoContextTakeover
|
|
||||||
}
|
|
||||||
conns[i] = newBroadcastConn(c)
|
|
||||||
go func(c *broadcastConn) {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case msg := <-c.msgCh:
|
|
||||||
if b.usePrepared {
|
|
||||||
c.conn.WritePreparedMessage(msg.prepared)
|
|
||||||
} else {
|
|
||||||
c.conn.WriteMessage(TextMessage, msg.payload)
|
|
||||||
}
|
|
||||||
val := atomic.AddInt32(&b.count, 1)
|
|
||||||
if val%int32(numConns) == 0 {
|
|
||||||
b.doneCh <- struct{}{}
|
|
||||||
}
|
|
||||||
case <-b.closeCh:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}(conns[i])
|
|
||||||
}
|
|
||||||
b.conns = conns
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *broadcastBench) close() {
|
|
||||||
close(b.closeCh)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *broadcastBench) runOnce() {
|
|
||||||
for _, c := range b.conns {
|
|
||||||
c.msgCh <- b.message
|
|
||||||
}
|
|
||||||
<-b.doneCh
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkBroadcast(b *testing.B) {
|
|
||||||
benchmarks := []struct {
|
|
||||||
name string
|
|
||||||
usePrepared bool
|
|
||||||
compression bool
|
|
||||||
}{
|
|
||||||
{"NoCompression", false, false},
|
|
||||||
{"WithCompression", false, true},
|
|
||||||
{"NoCompressionPrepared", true, false},
|
|
||||||
{"WithCompressionPrepared", true, true},
|
|
||||||
}
|
|
||||||
for _, bm := range benchmarks {
|
|
||||||
b.Run(bm.name, func(b *testing.B) {
|
|
||||||
bench := newBroadcastBench(bm.usePrepared, bm.compression)
|
|
||||||
defer bench.close()
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
bench.runOnce()
|
|
||||||
}
|
|
||||||
b.ReportAllocs()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
497
vendor/github.com/gorilla/websocket/conn_test.go
generated
vendored
497
vendor/github.com/gorilla/websocket/conn_test.go
generated
vendored
@ -1,497 +0,0 @@
|
|||||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package websocket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
"testing/iotest"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ net.Error = errWriteTimeout
|
|
||||||
|
|
||||||
type fakeNetConn struct {
|
|
||||||
io.Reader
|
|
||||||
io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c fakeNetConn) Close() error { return nil }
|
|
||||||
func (c fakeNetConn) LocalAddr() net.Addr { return localAddr }
|
|
||||||
func (c fakeNetConn) RemoteAddr() net.Addr { return remoteAddr }
|
|
||||||
func (c fakeNetConn) SetDeadline(t time.Time) error { return nil }
|
|
||||||
func (c fakeNetConn) SetReadDeadline(t time.Time) error { return nil }
|
|
||||||
func (c fakeNetConn) SetWriteDeadline(t time.Time) error { return nil }
|
|
||||||
|
|
||||||
type fakeAddr int
|
|
||||||
|
|
||||||
var (
|
|
||||||
localAddr = fakeAddr(1)
|
|
||||||
remoteAddr = fakeAddr(2)
|
|
||||||
)
|
|
||||||
|
|
||||||
func (a fakeAddr) Network() string {
|
|
||||||
return "net"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a fakeAddr) String() string {
|
|
||||||
return "str"
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFraming(t *testing.T) {
|
|
||||||
frameSizes := []int{0, 1, 2, 124, 125, 126, 127, 128, 129, 65534, 65535, 65536, 65537}
|
|
||||||
var readChunkers = []struct {
|
|
||||||
name string
|
|
||||||
f func(io.Reader) io.Reader
|
|
||||||
}{
|
|
||||||
{"half", iotest.HalfReader},
|
|
||||||
{"one", iotest.OneByteReader},
|
|
||||||
{"asis", func(r io.Reader) io.Reader { return r }},
|
|
||||||
}
|
|
||||||
writeBuf := make([]byte, 65537)
|
|
||||||
for i := range writeBuf {
|
|
||||||
writeBuf[i] = byte(i)
|
|
||||||
}
|
|
||||||
var writers = []struct {
|
|
||||||
name string
|
|
||||||
f func(w io.Writer, n int) (int, error)
|
|
||||||
}{
|
|
||||||
{"iocopy", func(w io.Writer, n int) (int, error) {
|
|
||||||
nn, err := io.Copy(w, bytes.NewReader(writeBuf[:n]))
|
|
||||||
return int(nn), err
|
|
||||||
}},
|
|
||||||
{"write", func(w io.Writer, n int) (int, error) {
|
|
||||||
return w.Write(writeBuf[:n])
|
|
||||||
}},
|
|
||||||
{"string", func(w io.Writer, n int) (int, error) {
|
|
||||||
return io.WriteString(w, string(writeBuf[:n]))
|
|
||||||
}},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, compress := range []bool{false, true} {
|
|
||||||
for _, isServer := range []bool{true, false} {
|
|
||||||
for _, chunker := range readChunkers {
|
|
||||||
|
|
||||||
var connBuf bytes.Buffer
|
|
||||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &connBuf}, isServer, 1024, 1024)
|
|
||||||
rc := newConn(fakeNetConn{Reader: chunker.f(&connBuf), Writer: nil}, !isServer, 1024, 1024)
|
|
||||||
if compress {
|
|
||||||
wc.newCompressionWriter = compressNoContextTakeover
|
|
||||||
rc.newDecompressionReader = decompressNoContextTakeover
|
|
||||||
}
|
|
||||||
for _, n := range frameSizes {
|
|
||||||
for _, writer := range writers {
|
|
||||||
name := fmt.Sprintf("z:%v, s:%v, r:%s, n:%d w:%s", compress, isServer, chunker.name, n, writer.name)
|
|
||||||
|
|
||||||
w, err := wc.NextWriter(TextMessage)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: wc.NextWriter() returned %v", name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
nn, err := writer.f(w, n)
|
|
||||||
if err != nil || nn != n {
|
|
||||||
t.Errorf("%s: w.Write(writeBuf[:n]) returned %d, %v", name, nn, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
err = w.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: w.Close() returned %v", name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
opCode, r, err := rc.NextReader()
|
|
||||||
if err != nil || opCode != TextMessage {
|
|
||||||
t.Errorf("%s: NextReader() returned %d, r, %v", name, opCode, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
rbuf, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: ReadFull() returned rbuf, %v", name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rbuf) != n {
|
|
||||||
t.Errorf("%s: len(rbuf) is %d, want %d", name, len(rbuf), n)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, b := range rbuf {
|
|
||||||
if byte(i) != b {
|
|
||||||
t.Errorf("%s: bad byte at offset %d", name, i)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestControl(t *testing.T) {
|
|
||||||
const message = "this is a ping/pong messsage"
|
|
||||||
for _, isServer := range []bool{true, false} {
|
|
||||||
for _, isWriteControl := range []bool{true, false} {
|
|
||||||
name := fmt.Sprintf("s:%v, wc:%v", isServer, isWriteControl)
|
|
||||||
var connBuf bytes.Buffer
|
|
||||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &connBuf}, isServer, 1024, 1024)
|
|
||||||
rc := newConn(fakeNetConn{Reader: &connBuf, Writer: nil}, !isServer, 1024, 1024)
|
|
||||||
if isWriteControl {
|
|
||||||
wc.WriteControl(PongMessage, []byte(message), time.Now().Add(time.Second))
|
|
||||||
} else {
|
|
||||||
w, err := wc.NextWriter(PongMessage)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: wc.NextWriter() returned %v", name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte(message)); err != nil {
|
|
||||||
t.Errorf("%s: w.Write() returned %v", name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := w.Close(); err != nil {
|
|
||||||
t.Errorf("%s: w.Close() returned %v", name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var actualMessage string
|
|
||||||
rc.SetPongHandler(func(s string) error { actualMessage = s; return nil })
|
|
||||||
rc.NextReader()
|
|
||||||
if actualMessage != message {
|
|
||||||
t.Errorf("%s: pong=%q, want %q", name, actualMessage, message)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCloseFrameBeforeFinalMessageFrame(t *testing.T) {
|
|
||||||
const bufSize = 512
|
|
||||||
|
|
||||||
expectedErr := &CloseError{Code: CloseNormalClosure, Text: "hello"}
|
|
||||||
|
|
||||||
var b1, b2 bytes.Buffer
|
|
||||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &b1}, false, 1024, bufSize)
|
|
||||||
rc := newConn(fakeNetConn{Reader: &b1, Writer: &b2}, true, 1024, 1024)
|
|
||||||
|
|
||||||
w, _ := wc.NextWriter(BinaryMessage)
|
|
||||||
w.Write(make([]byte, bufSize+bufSize/2))
|
|
||||||
wc.WriteControl(CloseMessage, FormatCloseMessage(expectedErr.Code, expectedErr.Text), time.Now().Add(10*time.Second))
|
|
||||||
w.Close()
|
|
||||||
|
|
||||||
op, r, err := rc.NextReader()
|
|
||||||
if op != BinaryMessage || err != nil {
|
|
||||||
t.Fatalf("NextReader() returned %d, %v", op, err)
|
|
||||||
}
|
|
||||||
_, err = io.Copy(ioutil.Discard, r)
|
|
||||||
if !reflect.DeepEqual(err, expectedErr) {
|
|
||||||
t.Fatalf("io.Copy() returned %v, want %v", err, expectedErr)
|
|
||||||
}
|
|
||||||
_, _, err = rc.NextReader()
|
|
||||||
if !reflect.DeepEqual(err, expectedErr) {
|
|
||||||
t.Fatalf("NextReader() returned %v, want %v", err, expectedErr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEOFWithinFrame(t *testing.T) {
|
|
||||||
const bufSize = 64
|
|
||||||
|
|
||||||
for n := 0; ; n++ {
|
|
||||||
var b bytes.Buffer
|
|
||||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &b}, false, 1024, 1024)
|
|
||||||
rc := newConn(fakeNetConn{Reader: &b, Writer: nil}, true, 1024, 1024)
|
|
||||||
|
|
||||||
w, _ := wc.NextWriter(BinaryMessage)
|
|
||||||
w.Write(make([]byte, bufSize))
|
|
||||||
w.Close()
|
|
||||||
|
|
||||||
if n >= b.Len() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
b.Truncate(n)
|
|
||||||
|
|
||||||
op, r, err := rc.NextReader()
|
|
||||||
if err == errUnexpectedEOF {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if op != BinaryMessage || err != nil {
|
|
||||||
t.Fatalf("%d: NextReader() returned %d, %v", n, op, err)
|
|
||||||
}
|
|
||||||
_, err = io.Copy(ioutil.Discard, r)
|
|
||||||
if err != errUnexpectedEOF {
|
|
||||||
t.Fatalf("%d: io.Copy() returned %v, want %v", n, err, errUnexpectedEOF)
|
|
||||||
}
|
|
||||||
_, _, err = rc.NextReader()
|
|
||||||
if err != errUnexpectedEOF {
|
|
||||||
t.Fatalf("%d: NextReader() returned %v, want %v", n, err, errUnexpectedEOF)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEOFBeforeFinalFrame(t *testing.T) {
|
|
||||||
const bufSize = 512
|
|
||||||
|
|
||||||
var b1, b2 bytes.Buffer
|
|
||||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &b1}, false, 1024, bufSize)
|
|
||||||
rc := newConn(fakeNetConn{Reader: &b1, Writer: &b2}, true, 1024, 1024)
|
|
||||||
|
|
||||||
w, _ := wc.NextWriter(BinaryMessage)
|
|
||||||
w.Write(make([]byte, bufSize+bufSize/2))
|
|
||||||
|
|
||||||
op, r, err := rc.NextReader()
|
|
||||||
if op != BinaryMessage || err != nil {
|
|
||||||
t.Fatalf("NextReader() returned %d, %v", op, err)
|
|
||||||
}
|
|
||||||
_, err = io.Copy(ioutil.Discard, r)
|
|
||||||
if err != errUnexpectedEOF {
|
|
||||||
t.Fatalf("io.Copy() returned %v, want %v", err, errUnexpectedEOF)
|
|
||||||
}
|
|
||||||
_, _, err = rc.NextReader()
|
|
||||||
if err != errUnexpectedEOF {
|
|
||||||
t.Fatalf("NextReader() returned %v, want %v", err, errUnexpectedEOF)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWriteAfterMessageWriterClose(t *testing.T) {
|
|
||||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &bytes.Buffer{}}, false, 1024, 1024)
|
|
||||||
w, _ := wc.NextWriter(BinaryMessage)
|
|
||||||
io.WriteString(w, "hello")
|
|
||||||
if err := w.Close(); err != nil {
|
|
||||||
t.Fatalf("unxpected error closing message writer, %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := io.WriteString(w, "world"); err == nil {
|
|
||||||
t.Fatalf("no error writing after close")
|
|
||||||
}
|
|
||||||
|
|
||||||
w, _ = wc.NextWriter(BinaryMessage)
|
|
||||||
io.WriteString(w, "hello")
|
|
||||||
|
|
||||||
// close w by getting next writer
|
|
||||||
_, err := wc.NextWriter(BinaryMessage)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error getting next writer, %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := io.WriteString(w, "world"); err == nil {
|
|
||||||
t.Fatalf("no error writing after close")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReadLimit(t *testing.T) {
|
|
||||||
|
|
||||||
const readLimit = 512
|
|
||||||
message := make([]byte, readLimit+1)
|
|
||||||
|
|
||||||
var b1, b2 bytes.Buffer
|
|
||||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &b1}, false, 1024, readLimit-2)
|
|
||||||
rc := newConn(fakeNetConn{Reader: &b1, Writer: &b2}, true, 1024, 1024)
|
|
||||||
rc.SetReadLimit(readLimit)
|
|
||||||
|
|
||||||
// Send message at the limit with interleaved pong.
|
|
||||||
w, _ := wc.NextWriter(BinaryMessage)
|
|
||||||
w.Write(message[:readLimit-1])
|
|
||||||
wc.WriteControl(PongMessage, []byte("this is a pong"), time.Now().Add(10*time.Second))
|
|
||||||
w.Write(message[:1])
|
|
||||||
w.Close()
|
|
||||||
|
|
||||||
// Send message larger than the limit.
|
|
||||||
wc.WriteMessage(BinaryMessage, message[:readLimit+1])
|
|
||||||
|
|
||||||
op, _, err := rc.NextReader()
|
|
||||||
if op != BinaryMessage || err != nil {
|
|
||||||
t.Fatalf("1: NextReader() returned %d, %v", op, err)
|
|
||||||
}
|
|
||||||
op, r, err := rc.NextReader()
|
|
||||||
if op != BinaryMessage || err != nil {
|
|
||||||
t.Fatalf("2: NextReader() returned %d, %v", op, err)
|
|
||||||
}
|
|
||||||
_, err = io.Copy(ioutil.Discard, r)
|
|
||||||
if err != ErrReadLimit {
|
|
||||||
t.Fatalf("io.Copy() returned %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddrs(t *testing.T) {
|
|
||||||
c := newConn(&fakeNetConn{}, true, 1024, 1024)
|
|
||||||
if c.LocalAddr() != localAddr {
|
|
||||||
t.Errorf("LocalAddr = %v, want %v", c.LocalAddr(), localAddr)
|
|
||||||
}
|
|
||||||
if c.RemoteAddr() != remoteAddr {
|
|
||||||
t.Errorf("RemoteAddr = %v, want %v", c.RemoteAddr(), remoteAddr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnderlyingConn(t *testing.T) {
|
|
||||||
var b1, b2 bytes.Buffer
|
|
||||||
fc := fakeNetConn{Reader: &b1, Writer: &b2}
|
|
||||||
c := newConn(fc, true, 1024, 1024)
|
|
||||||
ul := c.UnderlyingConn()
|
|
||||||
if ul != fc {
|
|
||||||
t.Fatalf("Underlying conn is not what it should be.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBufioReadBytes(t *testing.T) {
|
|
||||||
|
|
||||||
// Test calling bufio.ReadBytes for value longer than read buffer size.
|
|
||||||
|
|
||||||
m := make([]byte, 512)
|
|
||||||
m[len(m)-1] = '\n'
|
|
||||||
|
|
||||||
var b1, b2 bytes.Buffer
|
|
||||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &b1}, false, len(m)+64, len(m)+64)
|
|
||||||
rc := newConn(fakeNetConn{Reader: &b1, Writer: &b2}, true, len(m)-64, len(m)-64)
|
|
||||||
|
|
||||||
w, _ := wc.NextWriter(BinaryMessage)
|
|
||||||
w.Write(m)
|
|
||||||
w.Close()
|
|
||||||
|
|
||||||
op, r, err := rc.NextReader()
|
|
||||||
if op != BinaryMessage || err != nil {
|
|
||||||
t.Fatalf("NextReader() returned %d, %v", op, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
br := bufio.NewReader(r)
|
|
||||||
p, err := br.ReadBytes('\n')
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadBytes() returned %v", err)
|
|
||||||
}
|
|
||||||
if len(p) != len(m) {
|
|
||||||
t.Fatalf("read returnd %d bytes, want %d bytes", len(p), len(m))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var closeErrorTests = []struct {
|
|
||||||
err error
|
|
||||||
codes []int
|
|
||||||
ok bool
|
|
||||||
}{
|
|
||||||
{&CloseError{Code: CloseNormalClosure}, []int{CloseNormalClosure}, true},
|
|
||||||
{&CloseError{Code: CloseNormalClosure}, []int{CloseNoStatusReceived}, false},
|
|
||||||
{&CloseError{Code: CloseNormalClosure}, []int{CloseNoStatusReceived, CloseNormalClosure}, true},
|
|
||||||
{errors.New("hello"), []int{CloseNormalClosure}, false},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCloseError(t *testing.T) {
|
|
||||||
for _, tt := range closeErrorTests {
|
|
||||||
ok := IsCloseError(tt.err, tt.codes...)
|
|
||||||
if ok != tt.ok {
|
|
||||||
t.Errorf("IsCloseError(%#v, %#v) returned %v, want %v", tt.err, tt.codes, ok, tt.ok)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var unexpectedCloseErrorTests = []struct {
|
|
||||||
err error
|
|
||||||
codes []int
|
|
||||||
ok bool
|
|
||||||
}{
|
|
||||||
{&CloseError{Code: CloseNormalClosure}, []int{CloseNormalClosure}, false},
|
|
||||||
{&CloseError{Code: CloseNormalClosure}, []int{CloseNoStatusReceived}, true},
|
|
||||||
{&CloseError{Code: CloseNormalClosure}, []int{CloseNoStatusReceived, CloseNormalClosure}, false},
|
|
||||||
{errors.New("hello"), []int{CloseNormalClosure}, false},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnexpectedCloseErrors(t *testing.T) {
|
|
||||||
for _, tt := range unexpectedCloseErrorTests {
|
|
||||||
ok := IsUnexpectedCloseError(tt.err, tt.codes...)
|
|
||||||
if ok != tt.ok {
|
|
||||||
t.Errorf("IsUnexpectedCloseError(%#v, %#v) returned %v, want %v", tt.err, tt.codes, ok, tt.ok)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type blockingWriter struct {
|
|
||||||
c1, c2 chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w blockingWriter) Write(p []byte) (int, error) {
|
|
||||||
// Allow main to continue
|
|
||||||
close(w.c1)
|
|
||||||
// Wait for panic in main
|
|
||||||
<-w.c2
|
|
||||||
return len(p), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConcurrentWritePanic(t *testing.T) {
|
|
||||||
w := blockingWriter{make(chan struct{}), make(chan struct{})}
|
|
||||||
c := newConn(fakeNetConn{Reader: nil, Writer: w}, false, 1024, 1024)
|
|
||||||
go func() {
|
|
||||||
c.WriteMessage(TextMessage, []byte{})
|
|
||||||
}()
|
|
||||||
|
|
||||||
// wait for goroutine to block in write.
|
|
||||||
<-w.c1
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
close(w.c2)
|
|
||||||
if v := recover(); v != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
c.WriteMessage(TextMessage, []byte{})
|
|
||||||
t.Fatal("should not get here")
|
|
||||||
}
|
|
||||||
|
|
||||||
type failingReader struct{}
|
|
||||||
|
|
||||||
func (r failingReader) Read(p []byte) (int, error) {
|
|
||||||
return 0, io.EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFailedConnectionReadPanic(t *testing.T) {
|
|
||||||
c := newConn(fakeNetConn{Reader: failingReader{}, Writer: nil}, false, 1024, 1024)
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if v := recover(); v != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
for i := 0; i < 20000; i++ {
|
|
||||||
c.ReadMessage()
|
|
||||||
}
|
|
||||||
t.Fatal("should not get here")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBufioReuse(t *testing.T) {
|
|
||||||
brw := bufio.NewReadWriter(bufio.NewReader(nil), bufio.NewWriter(nil))
|
|
||||||
c := newConnBRW(nil, false, 0, 0, brw)
|
|
||||||
|
|
||||||
if c.br != brw.Reader {
|
|
||||||
t.Error("connection did not reuse bufio.Reader")
|
|
||||||
}
|
|
||||||
|
|
||||||
var wh writeHook
|
|
||||||
brw.Writer.Reset(&wh)
|
|
||||||
brw.WriteByte(0)
|
|
||||||
brw.Flush()
|
|
||||||
if &c.writeBuf[0] != &wh.p[0] {
|
|
||||||
t.Error("connection did not reuse bufio.Writer")
|
|
||||||
}
|
|
||||||
|
|
||||||
brw = bufio.NewReadWriter(bufio.NewReaderSize(nil, 0), bufio.NewWriterSize(nil, 0))
|
|
||||||
c = newConnBRW(nil, false, 0, 0, brw)
|
|
||||||
|
|
||||||
if c.br == brw.Reader {
|
|
||||||
t.Error("connection used bufio.Reader with small size")
|
|
||||||
}
|
|
||||||
|
|
||||||
brw.Writer.Reset(&wh)
|
|
||||||
brw.WriteByte(0)
|
|
||||||
brw.Flush()
|
|
||||||
if &c.writeBuf[0] != &wh.p[0] {
|
|
||||||
t.Error("connection used bufio.Writer with small size")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
46
vendor/github.com/gorilla/websocket/example_test.go
generated
vendored
46
vendor/github.com/gorilla/websocket/example_test.go
generated
vendored
@ -1,46 +0,0 @@
|
|||||||
// Copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package websocket_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
c *websocket.Conn
|
|
||||||
req *http.Request
|
|
||||||
)
|
|
||||||
|
|
||||||
// The websocket.IsUnexpectedCloseError function is useful for identifying
|
|
||||||
// application and protocol errors.
|
|
||||||
//
|
|
||||||
// This server application works with a client application running in the
|
|
||||||
// browser. The client application does not explicitly close the websocket. The
|
|
||||||
// only expected close message from the client has the code
|
|
||||||
// websocket.CloseGoingAway. All other other close messages are likely the
|
|
||||||
// result of an application or protocol error and are logged to aid debugging.
|
|
||||||
func ExampleIsUnexpectedCloseError() {
|
|
||||||
|
|
||||||
for {
|
|
||||||
messageType, p, err := c.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
|
|
||||||
log.Printf("error: %v, user-agent: %v", err, req.Header.Get("User-Agent"))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
processMesage(messageType, p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func processMesage(mt int, p []byte) {}
|
|
||||||
|
|
||||||
// TestX prevents godoc from showing this entire file in the example. Remove
|
|
||||||
// this function when a second example is added.
|
|
||||||
func TestX(t *testing.T) {}
|
|
13
vendor/github.com/gorilla/websocket/examples/autobahn/README.md
generated
vendored
13
vendor/github.com/gorilla/websocket/examples/autobahn/README.md
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
# Test Server
|
|
||||||
|
|
||||||
This package contains a server for the [Autobahn WebSockets Test Suite](http://autobahn.ws/testsuite).
|
|
||||||
|
|
||||||
To test the server, run
|
|
||||||
|
|
||||||
go run server.go
|
|
||||||
|
|
||||||
and start the client test driver
|
|
||||||
|
|
||||||
wstest -m fuzzingclient -s fuzzingclient.json
|
|
||||||
|
|
||||||
When the client completes, it writes a report to reports/clients/index.html.
|
|
15
vendor/github.com/gorilla/websocket/examples/autobahn/fuzzingclient.json
generated
vendored
15
vendor/github.com/gorilla/websocket/examples/autobahn/fuzzingclient.json
generated
vendored
@ -1,15 +0,0 @@
|
|||||||
|
|
||||||
{
|
|
||||||
"options": {"failByDrop": false},
|
|
||||||
"outdir": "./reports/clients",
|
|
||||||
"servers": [
|
|
||||||
{"agent": "ReadAllWriteMessage", "url": "ws://localhost:9000/m", "options": {"version": 18}},
|
|
||||||
{"agent": "ReadAllWritePreparedMessage", "url": "ws://localhost:9000/p", "options": {"version": 18}},
|
|
||||||
{"agent": "ReadAllWrite", "url": "ws://localhost:9000/r", "options": {"version": 18}},
|
|
||||||
{"agent": "CopyFull", "url": "ws://localhost:9000/f", "options": {"version": 18}},
|
|
||||||
{"agent": "CopyWriterOnly", "url": "ws://localhost:9000/c", "options": {"version": 18}}
|
|
||||||
],
|
|
||||||
"cases": ["*"],
|
|
||||||
"exclude-cases": [],
|
|
||||||
"exclude-agent-cases": {}
|
|
||||||
}
|
|
265
vendor/github.com/gorilla/websocket/examples/autobahn/server.go
generated
vendored
265
vendor/github.com/gorilla/websocket/examples/autobahn/server.go
generated
vendored
@ -1,265 +0,0 @@
|
|||||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Command server is a test server for the Autobahn WebSockets Test Suite.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"flag"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
)
|
|
||||||
|
|
||||||
var upgrader = websocket.Upgrader{
|
|
||||||
ReadBufferSize: 4096,
|
|
||||||
WriteBufferSize: 4096,
|
|
||||||
EnableCompression: true,
|
|
||||||
CheckOrigin: func(r *http.Request) bool {
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// echoCopy echoes messages from the client using io.Copy.
|
|
||||||
func echoCopy(w http.ResponseWriter, r *http.Request, writerOnly bool) {
|
|
||||||
conn, err := upgrader.Upgrade(w, r, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Upgrade:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
for {
|
|
||||||
mt, r, err := conn.NextReader()
|
|
||||||
if err != nil {
|
|
||||||
if err != io.EOF {
|
|
||||||
log.Println("NextReader:", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if mt == websocket.TextMessage {
|
|
||||||
r = &validator{r: r}
|
|
||||||
}
|
|
||||||
w, err := conn.NextWriter(mt)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("NextWriter:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if mt == websocket.TextMessage {
|
|
||||||
r = &validator{r: r}
|
|
||||||
}
|
|
||||||
if writerOnly {
|
|
||||||
_, err = io.Copy(struct{ io.Writer }{w}, r)
|
|
||||||
} else {
|
|
||||||
_, err = io.Copy(w, r)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
if err == errInvalidUTF8 {
|
|
||||||
conn.WriteControl(websocket.CloseMessage,
|
|
||||||
websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
|
|
||||||
time.Time{})
|
|
||||||
}
|
|
||||||
log.Println("Copy:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = w.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Close:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func echoCopyWriterOnly(w http.ResponseWriter, r *http.Request) {
|
|
||||||
echoCopy(w, r, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func echoCopyFull(w http.ResponseWriter, r *http.Request) {
|
|
||||||
echoCopy(w, r, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// echoReadAll echoes messages from the client by reading the entire message
|
|
||||||
// with ioutil.ReadAll.
|
|
||||||
func echoReadAll(w http.ResponseWriter, r *http.Request, writeMessage, writePrepared bool) {
|
|
||||||
conn, err := upgrader.Upgrade(w, r, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Upgrade:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
for {
|
|
||||||
mt, b, err := conn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
if err != io.EOF {
|
|
||||||
log.Println("NextReader:", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if mt == websocket.TextMessage {
|
|
||||||
if !utf8.Valid(b) {
|
|
||||||
conn.WriteControl(websocket.CloseMessage,
|
|
||||||
websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
|
|
||||||
time.Time{})
|
|
||||||
log.Println("ReadAll: invalid utf8")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if writeMessage {
|
|
||||||
if !writePrepared {
|
|
||||||
err = conn.WriteMessage(mt, b)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("WriteMessage:", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pm, err := websocket.NewPreparedMessage(mt, b)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("NewPreparedMessage:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = conn.WritePreparedMessage(pm)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("WritePreparedMessage:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
w, err := conn.NextWriter(mt)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("NextWriter:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, err := w.Write(b); err != nil {
|
|
||||||
log.Println("Writer:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := w.Close(); err != nil {
|
|
||||||
log.Println("Close:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func echoReadAllWriter(w http.ResponseWriter, r *http.Request) {
|
|
||||||
echoReadAll(w, r, false, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func echoReadAllWriteMessage(w http.ResponseWriter, r *http.Request) {
|
|
||||||
echoReadAll(w, r, true, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func echoReadAllWritePreparedMessage(w http.ResponseWriter, r *http.Request) {
|
|
||||||
echoReadAll(w, r, true, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func serveHome(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.URL.Path != "/" {
|
|
||||||
http.Error(w, "Not found.", 404)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.Method != "GET" {
|
|
||||||
http.Error(w, "Method not allowed", 405)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
||||||
io.WriteString(w, "<html><body>Echo Server</body></html>")
|
|
||||||
}
|
|
||||||
|
|
||||||
var addr = flag.String("addr", ":9000", "http service address")
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Parse()
|
|
||||||
http.HandleFunc("/", serveHome)
|
|
||||||
http.HandleFunc("/c", echoCopyWriterOnly)
|
|
||||||
http.HandleFunc("/f", echoCopyFull)
|
|
||||||
http.HandleFunc("/r", echoReadAllWriter)
|
|
||||||
http.HandleFunc("/m", echoReadAllWriteMessage)
|
|
||||||
http.HandleFunc("/p", echoReadAllWritePreparedMessage)
|
|
||||||
err := http.ListenAndServe(*addr, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("ListenAndServe: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type validator struct {
|
|
||||||
state int
|
|
||||||
x rune
|
|
||||||
r io.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
var errInvalidUTF8 = errors.New("invalid utf8")
|
|
||||||
|
|
||||||
func (r *validator) Read(p []byte) (int, error) {
|
|
||||||
n, err := r.r.Read(p)
|
|
||||||
state := r.state
|
|
||||||
x := r.x
|
|
||||||
for _, b := range p[:n] {
|
|
||||||
state, x = decode(state, x, b)
|
|
||||||
if state == utf8Reject {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.state = state
|
|
||||||
r.x = x
|
|
||||||
if state == utf8Reject || (err == io.EOF && state != utf8Accept) {
|
|
||||||
return n, errInvalidUTF8
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// UTF-8 decoder from http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
|
||||||
//
|
|
||||||
// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to
|
|
||||||
// deal in the Software without restriction, including without limitation the
|
|
||||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
// sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
// IN THE SOFTWARE.
|
|
||||||
var utf8d = [...]byte{
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1f
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3f
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5f
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7f
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9f
|
|
||||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // a0..bf
|
|
||||||
8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c0..df
|
|
||||||
0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef
|
|
||||||
0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff
|
|
||||||
0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
|
|
||||||
1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
|
|
||||||
1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
|
|
||||||
1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // s7..s8
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
utf8Accept = 0
|
|
||||||
utf8Reject = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
func decode(state int, x rune, b byte) (int, rune) {
|
|
||||||
t := utf8d[b]
|
|
||||||
if state != utf8Accept {
|
|
||||||
x = rune(b&0x3f) | (x << 6)
|
|
||||||
} else {
|
|
||||||
x = rune((0xff >> t) & b)
|
|
||||||
}
|
|
||||||
state = int(utf8d[256+state*16+int(t)])
|
|
||||||
return state, x
|
|
||||||
}
|
|
102
vendor/github.com/gorilla/websocket/examples/chat/README.md
generated
vendored
102
vendor/github.com/gorilla/websocket/examples/chat/README.md
generated
vendored
@ -1,102 +0,0 @@
|
|||||||
# Chat Example
|
|
||||||
|
|
||||||
This application shows how to use use the
|
|
||||||
[websocket](https://github.com/gorilla/websocket) package to implement a simple
|
|
||||||
web chat application.
|
|
||||||
|
|
||||||
## Running the example
|
|
||||||
|
|
||||||
The example requires a working Go development environment. The [Getting
|
|
||||||
Started](http://golang.org/doc/install) page describes how to install the
|
|
||||||
development environment.
|
|
||||||
|
|
||||||
Once you have Go up and running, you can download, build and run the example
|
|
||||||
using the following commands.
|
|
||||||
|
|
||||||
$ go get github.com/gorilla/websocket
|
|
||||||
$ cd `go list -f '{{.Dir}}' github.com/gorilla/websocket/examples/chat`
|
|
||||||
$ go run *.go
|
|
||||||
|
|
||||||
To use the chat example, open http://localhost:8080/ in your browser.
|
|
||||||
|
|
||||||
## Server
|
|
||||||
|
|
||||||
The server application defines two types, `Client` and `Hub`. The server
|
|
||||||
creates an instance of the `Client` type for each websocket connection. A
|
|
||||||
`Client` acts as an intermediary between the websocket connection and a single
|
|
||||||
instance of the `Hub` type. The `Hub` maintains a set of registered clients and
|
|
||||||
broadcasts messages to the clients.
|
|
||||||
|
|
||||||
The application runs one goroutine for the `Hub` and two goroutines for each
|
|
||||||
`Client`. The goroutines communicate with each other using channels. The `Hub`
|
|
||||||
has channels for registering clients, unregistering clients and broadcasting
|
|
||||||
messages. A `Client` has a buffered channel of outbound messages. One of the
|
|
||||||
client's goroutines reads messages from this channel and writes the messages to
|
|
||||||
the websocket. The other client goroutine reads messages from the websocket and
|
|
||||||
sends them to the hub.
|
|
||||||
|
|
||||||
### Hub
|
|
||||||
|
|
||||||
The code for the `Hub` type is in
|
|
||||||
[hub.go](https://github.com/gorilla/websocket/blob/master/examples/chat/hub.go).
|
|
||||||
The application's `main` function starts the hub's `run` method as a goroutine.
|
|
||||||
Clients send requests to the hub using the `register`, `unregister` and
|
|
||||||
`broadcast` channels.
|
|
||||||
|
|
||||||
The hub registers clients by adding the client pointer as a key in the
|
|
||||||
`clients` map. The map value is always true.
|
|
||||||
|
|
||||||
The unregister code is a little more complicated. In addition to deleting the
|
|
||||||
client pointer from the `clients` map, the hub closes the clients's `send`
|
|
||||||
channel to signal the client that no more messages will be sent to the client.
|
|
||||||
|
|
||||||
The hub handles messages by looping over the registered clients and sending the
|
|
||||||
message to the client's `send` channel. If the client's `send` buffer is full,
|
|
||||||
then the hub assumes that the client is dead or stuck. In this case, the hub
|
|
||||||
unregisters the client and closes the websocket.
|
|
||||||
|
|
||||||
### Client
|
|
||||||
|
|
||||||
The code for the `Client` type is in [client.go](https://github.com/gorilla/websocket/blob/master/examples/chat/client.go).
|
|
||||||
|
|
||||||
The `serveWs` function is registered by the application's `main` function as
|
|
||||||
an HTTP handler. The handler upgrades the HTTP connection to the WebSocket
|
|
||||||
protocol, creates a client, registers the client with the hub and schedules the
|
|
||||||
client to be unregistered using a defer statement.
|
|
||||||
|
|
||||||
Next, the HTTP handler starts the client's `writePump` method as a goroutine.
|
|
||||||
This method transfers messages from the client's send channel to the websocket
|
|
||||||
connection. The writer method exits when the channel is closed by the hub or
|
|
||||||
there's an error writing to the websocket connection.
|
|
||||||
|
|
||||||
Finally, the HTTP handler calls the client's `readPump` method. This method
|
|
||||||
transfers inbound messages from the websocket to the hub.
|
|
||||||
|
|
||||||
WebSocket connections [support one concurrent reader and one concurrent
|
|
||||||
writer](https://godoc.org/github.com/gorilla/websocket#hdr-Concurrency). The
|
|
||||||
application ensures that these concurrency requirements are met by executing
|
|
||||||
all reads from the `readPump` goroutine and all writes from the `writePump`
|
|
||||||
goroutine.
|
|
||||||
|
|
||||||
To improve efficiency under high load, the `writePump` function coalesces
|
|
||||||
pending chat messages in the `send` channel to a single WebSocket message. This
|
|
||||||
reduces the number of system calls and the amount of data sent over the
|
|
||||||
network.
|
|
||||||
|
|
||||||
## Frontend
|
|
||||||
|
|
||||||
The frontend code is in [home.html](https://github.com/gorilla/websocket/blob/master/examples/chat/home.html).
|
|
||||||
|
|
||||||
On document load, the script checks for websocket functionality in the browser.
|
|
||||||
If websocket functionality is available, then the script opens a connection to
|
|
||||||
the server and registers a callback to handle messages from the server. The
|
|
||||||
callback appends the message to the chat log using the appendLog function.
|
|
||||||
|
|
||||||
To allow the user to manually scroll through the chat log without interruption
|
|
||||||
from new messages, the `appendLog` function checks the scroll position before
|
|
||||||
adding new content. If the chat log is scrolled to the bottom, then the
|
|
||||||
function scrolls new content into view after adding the content. Otherwise, the
|
|
||||||
scroll position is not changed.
|
|
||||||
|
|
||||||
The form handler writes the user input to the websocket and clears the input
|
|
||||||
field.
|
|
137
vendor/github.com/gorilla/websocket/examples/chat/client.go
generated
vendored
137
vendor/github.com/gorilla/websocket/examples/chat/client.go
generated
vendored
@ -1,137 +0,0 @@
|
|||||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Time allowed to write a message to the peer.
|
|
||||||
writeWait = 10 * time.Second
|
|
||||||
|
|
||||||
// Time allowed to read the next pong message from the peer.
|
|
||||||
pongWait = 60 * time.Second
|
|
||||||
|
|
||||||
// Send pings to peer with this period. Must be less than pongWait.
|
|
||||||
pingPeriod = (pongWait * 9) / 10
|
|
||||||
|
|
||||||
// Maximum message size allowed from peer.
|
|
||||||
maxMessageSize = 512
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
newline = []byte{'\n'}
|
|
||||||
space = []byte{' '}
|
|
||||||
)
|
|
||||||
|
|
||||||
var upgrader = websocket.Upgrader{
|
|
||||||
ReadBufferSize: 1024,
|
|
||||||
WriteBufferSize: 1024,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client is a middleman between the websocket connection and the hub.
|
|
||||||
type Client struct {
|
|
||||||
hub *Hub
|
|
||||||
|
|
||||||
// The websocket connection.
|
|
||||||
conn *websocket.Conn
|
|
||||||
|
|
||||||
// Buffered channel of outbound messages.
|
|
||||||
send chan []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// readPump pumps messages from the websocket connection to the hub.
|
|
||||||
//
|
|
||||||
// The application runs readPump in a per-connection goroutine. The application
|
|
||||||
// ensures that there is at most one reader on a connection by executing all
|
|
||||||
// reads from this goroutine.
|
|
||||||
func (c *Client) readPump() {
|
|
||||||
defer func() {
|
|
||||||
c.hub.unregister <- c
|
|
||||||
c.conn.Close()
|
|
||||||
}()
|
|
||||||
c.conn.SetReadLimit(maxMessageSize)
|
|
||||||
c.conn.SetReadDeadline(time.Now().Add(pongWait))
|
|
||||||
c.conn.SetPongHandler(func(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
|
||||||
for {
|
|
||||||
_, message, err := c.conn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
|
|
||||||
log.Printf("error: %v", err)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))
|
|
||||||
c.hub.broadcast <- message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// writePump pumps messages from the hub to the websocket connection.
|
|
||||||
//
|
|
||||||
// A goroutine running writePump is started for each connection. The
|
|
||||||
// application ensures that there is at most one writer to a connection by
|
|
||||||
// executing all writes from this goroutine.
|
|
||||||
func (c *Client) writePump() {
|
|
||||||
ticker := time.NewTicker(pingPeriod)
|
|
||||||
defer func() {
|
|
||||||
ticker.Stop()
|
|
||||||
c.conn.Close()
|
|
||||||
}()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case message, ok := <-c.send:
|
|
||||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
|
||||||
if !ok {
|
|
||||||
// The hub closed the channel.
|
|
||||||
c.conn.WriteMessage(websocket.CloseMessage, []byte{})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w, err := c.conn.NextWriter(websocket.TextMessage)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Write(message)
|
|
||||||
|
|
||||||
// Add queued chat messages to the current websocket message.
|
|
||||||
n := len(c.send)
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
w.Write(newline)
|
|
||||||
w.Write(<-c.send)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := w.Close(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case <-ticker.C:
|
|
||||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
|
||||||
if err := c.conn.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// serveWs handles websocket requests from the peer.
|
|
||||||
func serveWs(hub *Hub, w http.ResponseWriter, r *http.Request) {
|
|
||||||
conn, err := upgrader.Upgrade(w, r, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
client := &Client{hub: hub, conn: conn, send: make(chan []byte, 256)}
|
|
||||||
client.hub.register <- client
|
|
||||||
|
|
||||||
// Allow collection of memory referenced by the caller by doing all work in
|
|
||||||
// new goroutines.
|
|
||||||
go client.writePump()
|
|
||||||
go client.readPump()
|
|
||||||
}
|
|
98
vendor/github.com/gorilla/websocket/examples/chat/home.html
generated
vendored
98
vendor/github.com/gorilla/websocket/examples/chat/home.html
generated
vendored
@ -1,98 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>Chat Example</title>
|
|
||||||
<script type="text/javascript">
|
|
||||||
window.onload = function () {
|
|
||||||
var conn;
|
|
||||||
var msg = document.getElementById("msg");
|
|
||||||
var log = document.getElementById("log");
|
|
||||||
|
|
||||||
function appendLog(item) {
|
|
||||||
var doScroll = log.scrollTop > log.scrollHeight - log.clientHeight - 1;
|
|
||||||
log.appendChild(item);
|
|
||||||
if (doScroll) {
|
|
||||||
log.scrollTop = log.scrollHeight - log.clientHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById("form").onsubmit = function () {
|
|
||||||
if (!conn) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!msg.value) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
conn.send(msg.value);
|
|
||||||
msg.value = "";
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (window["WebSocket"]) {
|
|
||||||
conn = new WebSocket("ws://" + document.location.host + "/ws");
|
|
||||||
conn.onclose = function (evt) {
|
|
||||||
var item = document.createElement("div");
|
|
||||||
item.innerHTML = "<b>Connection closed.</b>";
|
|
||||||
appendLog(item);
|
|
||||||
};
|
|
||||||
conn.onmessage = function (evt) {
|
|
||||||
var messages = evt.data.split('\n');
|
|
||||||
for (var i = 0; i < messages.length; i++) {
|
|
||||||
var item = document.createElement("div");
|
|
||||||
item.innerText = messages[i];
|
|
||||||
appendLog(item);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
var item = document.createElement("div");
|
|
||||||
item.innerHTML = "<b>Your browser does not support WebSockets.</b>";
|
|
||||||
appendLog(item);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style type="text/css">
|
|
||||||
html {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
overflow: hidden;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
#log {
|
|
||||||
background: white;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.5em 0.5em 0.5em 0.5em;
|
|
||||||
position: absolute;
|
|
||||||
top: 0.5em;
|
|
||||||
left: 0.5em;
|
|
||||||
right: 0.5em;
|
|
||||||
bottom: 3em;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#form {
|
|
||||||
padding: 0 0.5em 0 0.5em;
|
|
||||||
margin: 0;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 1em;
|
|
||||||
left: 0px;
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="log"></div>
|
|
||||||
<form id="form">
|
|
||||||
<input type="submit" value="Send" />
|
|
||||||
<input type="text" id="msg" size="64"/>
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
53
vendor/github.com/gorilla/websocket/examples/chat/hub.go
generated
vendored
53
vendor/github.com/gorilla/websocket/examples/chat/hub.go
generated
vendored
@ -1,53 +0,0 @@
|
|||||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
// hub maintains the set of active clients and broadcasts messages to the
|
|
||||||
// clients.
|
|
||||||
type Hub struct {
|
|
||||||
// Registered clients.
|
|
||||||
clients map[*Client]bool
|
|
||||||
|
|
||||||
// Inbound messages from the clients.
|
|
||||||
broadcast chan []byte
|
|
||||||
|
|
||||||
// Register requests from the clients.
|
|
||||||
register chan *Client
|
|
||||||
|
|
||||||
// Unregister requests from clients.
|
|
||||||
unregister chan *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func newHub() *Hub {
|
|
||||||
return &Hub{
|
|
||||||
broadcast: make(chan []byte),
|
|
||||||
register: make(chan *Client),
|
|
||||||
unregister: make(chan *Client),
|
|
||||||
clients: make(map[*Client]bool),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Hub) run() {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case client := <-h.register:
|
|
||||||
h.clients[client] = true
|
|
||||||
case client := <-h.unregister:
|
|
||||||
if _, ok := h.clients[client]; ok {
|
|
||||||
delete(h.clients, client)
|
|
||||||
close(client.send)
|
|
||||||
}
|
|
||||||
case message := <-h.broadcast:
|
|
||||||
for client := range h.clients {
|
|
||||||
select {
|
|
||||||
case client.send <- message:
|
|
||||||
default:
|
|
||||||
close(client.send)
|
|
||||||
delete(h.clients, client)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
40
vendor/github.com/gorilla/websocket/examples/chat/main.go
generated
vendored
40
vendor/github.com/gorilla/websocket/examples/chat/main.go
generated
vendored
@ -1,40 +0,0 @@
|
|||||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
var addr = flag.String("addr", ":8080", "http service address")
|
|
||||||
|
|
||||||
func serveHome(w http.ResponseWriter, r *http.Request) {
|
|
||||||
log.Println(r.URL)
|
|
||||||
if r.URL.Path != "/" {
|
|
||||||
http.Error(w, "Not found", 404)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.Method != "GET" {
|
|
||||||
http.Error(w, "Method not allowed", 405)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
http.ServeFile(w, r, "home.html")
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Parse()
|
|
||||||
hub := newHub()
|
|
||||||
go hub.run()
|
|
||||||
http.HandleFunc("/", serveHome)
|
|
||||||
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
serveWs(hub, w, r)
|
|
||||||
})
|
|
||||||
err := http.ListenAndServe(*addr, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("ListenAndServe: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
19
vendor/github.com/gorilla/websocket/examples/command/README.md
generated
vendored
19
vendor/github.com/gorilla/websocket/examples/command/README.md
generated
vendored
@ -1,19 +0,0 @@
|
|||||||
# Command example
|
|
||||||
|
|
||||||
This example connects a websocket connection to stdin and stdout of a command.
|
|
||||||
Received messages are written to stdin followed by a `\n`. Each line read from
|
|
||||||
standard out is sent as a message to the client.
|
|
||||||
|
|
||||||
$ go get github.com/gorilla/websocket
|
|
||||||
$ cd `go list -f '{{.Dir}}' github.com/gorilla/websocket/examples/command`
|
|
||||||
$ go run main.go <command and arguments to run>
|
|
||||||
# Open http://localhost:8080/ .
|
|
||||||
|
|
||||||
Try the following commands.
|
|
||||||
|
|
||||||
# Echo sent messages to the output area.
|
|
||||||
$ go run main.go cat
|
|
||||||
|
|
||||||
# Run a shell.Try sending "ls" and "cat main.go".
|
|
||||||
$ go run main.go sh
|
|
||||||
|
|
102
vendor/github.com/gorilla/websocket/examples/command/home.html
generated
vendored
102
vendor/github.com/gorilla/websocket/examples/command/home.html
generated
vendored
@ -1,102 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>Command Example</title>
|
|
||||||
<script type="text/javascript">
|
|
||||||
window.onload = function () {
|
|
||||||
var conn;
|
|
||||||
var msg = document.getElementById("msg");
|
|
||||||
var log = document.getElementById("log");
|
|
||||||
|
|
||||||
function appendLog(item) {
|
|
||||||
var doScroll = log.scrollTop > log.scrollHeight - log.clientHeight - 1;
|
|
||||||
log.appendChild(item);
|
|
||||||
if (doScroll) {
|
|
||||||
log.scrollTop = log.scrollHeight - log.clientHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById("form").onsubmit = function () {
|
|
||||||
if (!conn) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!msg.value) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
conn.send(msg.value);
|
|
||||||
msg.value = "";
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (window["WebSocket"]) {
|
|
||||||
conn = new WebSocket("ws://" + document.location.host + "/ws");
|
|
||||||
conn.onclose = function (evt) {
|
|
||||||
var item = document.createElement("div");
|
|
||||||
item.innerHTML = "<b>Connection closed.</b>";
|
|
||||||
appendLog(item);
|
|
||||||
};
|
|
||||||
conn.onmessage = function (evt) {
|
|
||||||
var messages = evt.data.split('\n');
|
|
||||||
for (var i = 0; i < messages.length; i++) {
|
|
||||||
var item = document.createElement("div");
|
|
||||||
item.innerText = messages[i];
|
|
||||||
appendLog(item);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
var item = document.createElement("div");
|
|
||||||
item.innerHTML = "<b>Your browser does not support WebSockets.</b>";
|
|
||||||
appendLog(item);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style type="text/css">
|
|
||||||
html {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
overflow: hidden;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
#log {
|
|
||||||
background: white;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.5em 0.5em 0.5em 0.5em;
|
|
||||||
position: absolute;
|
|
||||||
top: 0.5em;
|
|
||||||
left: 0.5em;
|
|
||||||
right: 0.5em;
|
|
||||||
bottom: 3em;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#log pre {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#form {
|
|
||||||
padding: 0 0.5em 0 0.5em;
|
|
||||||
margin: 0;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 1em;
|
|
||||||
left: 0px;
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="log"></div>
|
|
||||||
<form id="form">
|
|
||||||
<input type="submit" value="Send" />
|
|
||||||
<input type="text" id="msg" size="64"/>
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
193
vendor/github.com/gorilla/websocket/examples/command/main.go
generated
vendored
193
vendor/github.com/gorilla/websocket/examples/command/main.go
generated
vendored
@ -1,193 +0,0 @@
|
|||||||
// Copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"flag"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
addr = flag.String("addr", "127.0.0.1:8080", "http service address")
|
|
||||||
cmdPath string
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Time allowed to write a message to the peer.
|
|
||||||
writeWait = 10 * time.Second
|
|
||||||
|
|
||||||
// Maximum message size allowed from peer.
|
|
||||||
maxMessageSize = 8192
|
|
||||||
|
|
||||||
// Time allowed to read the next pong message from the peer.
|
|
||||||
pongWait = 60 * time.Second
|
|
||||||
|
|
||||||
// Send pings to peer with this period. Must be less than pongWait.
|
|
||||||
pingPeriod = (pongWait * 9) / 10
|
|
||||||
|
|
||||||
// Time to wait before force close on connection.
|
|
||||||
closeGracePeriod = 10 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
func pumpStdin(ws *websocket.Conn, w io.Writer) {
|
|
||||||
defer ws.Close()
|
|
||||||
ws.SetReadLimit(maxMessageSize)
|
|
||||||
ws.SetReadDeadline(time.Now().Add(pongWait))
|
|
||||||
ws.SetPongHandler(func(string) error { ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
|
||||||
for {
|
|
||||||
_, message, err := ws.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
message = append(message, '\n')
|
|
||||||
if _, err := w.Write(message); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func pumpStdout(ws *websocket.Conn, r io.Reader, done chan struct{}) {
|
|
||||||
defer func() {
|
|
||||||
}()
|
|
||||||
s := bufio.NewScanner(r)
|
|
||||||
for s.Scan() {
|
|
||||||
ws.SetWriteDeadline(time.Now().Add(writeWait))
|
|
||||||
if err := ws.WriteMessage(websocket.TextMessage, s.Bytes()); err != nil {
|
|
||||||
ws.Close()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if s.Err() != nil {
|
|
||||||
log.Println("scan:", s.Err())
|
|
||||||
}
|
|
||||||
close(done)
|
|
||||||
|
|
||||||
ws.SetWriteDeadline(time.Now().Add(writeWait))
|
|
||||||
ws.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
|
||||||
time.Sleep(closeGracePeriod)
|
|
||||||
ws.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func ping(ws *websocket.Conn, done chan struct{}) {
|
|
||||||
ticker := time.NewTicker(pingPeriod)
|
|
||||||
defer ticker.Stop()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ticker.C:
|
|
||||||
if err := ws.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(writeWait)); err != nil {
|
|
||||||
log.Println("ping:", err)
|
|
||||||
}
|
|
||||||
case <-done:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func internalError(ws *websocket.Conn, msg string, err error) {
|
|
||||||
log.Println(msg, err)
|
|
||||||
ws.WriteMessage(websocket.TextMessage, []byte("Internal server error."))
|
|
||||||
}
|
|
||||||
|
|
||||||
var upgrader = websocket.Upgrader{}
|
|
||||||
|
|
||||||
func serveWs(w http.ResponseWriter, r *http.Request) {
|
|
||||||
ws, err := upgrader.Upgrade(w, r, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("upgrade:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer ws.Close()
|
|
||||||
|
|
||||||
outr, outw, err := os.Pipe()
|
|
||||||
if err != nil {
|
|
||||||
internalError(ws, "stdout:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer outr.Close()
|
|
||||||
defer outw.Close()
|
|
||||||
|
|
||||||
inr, inw, err := os.Pipe()
|
|
||||||
if err != nil {
|
|
||||||
internalError(ws, "stdin:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer inr.Close()
|
|
||||||
defer inw.Close()
|
|
||||||
|
|
||||||
proc, err := os.StartProcess(cmdPath, flag.Args(), &os.ProcAttr{
|
|
||||||
Files: []*os.File{inr, outw, outw},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
internalError(ws, "start:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
inr.Close()
|
|
||||||
outw.Close()
|
|
||||||
|
|
||||||
stdoutDone := make(chan struct{})
|
|
||||||
go pumpStdout(ws, outr, stdoutDone)
|
|
||||||
go ping(ws, stdoutDone)
|
|
||||||
|
|
||||||
pumpStdin(ws, inw)
|
|
||||||
|
|
||||||
// Some commands will exit when stdin is closed.
|
|
||||||
inw.Close()
|
|
||||||
|
|
||||||
// Other commands need a bonk on the head.
|
|
||||||
if err := proc.Signal(os.Interrupt); err != nil {
|
|
||||||
log.Println("inter:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-stdoutDone:
|
|
||||||
case <-time.After(time.Second):
|
|
||||||
// A bigger bonk on the head.
|
|
||||||
if err := proc.Signal(os.Kill); err != nil {
|
|
||||||
log.Println("term:", err)
|
|
||||||
}
|
|
||||||
<-stdoutDone
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := proc.Wait(); err != nil {
|
|
||||||
log.Println("wait:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func serveHome(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.URL.Path != "/" {
|
|
||||||
http.Error(w, "Not found", 404)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.Method != "GET" {
|
|
||||||
http.Error(w, "Method not allowed", 405)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
http.ServeFile(w, r, "home.html")
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Parse()
|
|
||||||
if len(flag.Args()) < 1 {
|
|
||||||
log.Fatal("must specify at least one argument")
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
cmdPath, err = exec.LookPath(flag.Args()[0])
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
http.HandleFunc("/", serveHome)
|
|
||||||
http.HandleFunc("/ws", serveWs)
|
|
||||||
log.Fatal(http.ListenAndServe(*addr, nil))
|
|
||||||
}
|
|
17
vendor/github.com/gorilla/websocket/examples/echo/README.md
generated
vendored
17
vendor/github.com/gorilla/websocket/examples/echo/README.md
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
# Client and server example
|
|
||||||
|
|
||||||
This example shows a simple client and server.
|
|
||||||
|
|
||||||
The server echoes messages sent to it. The client sends a message every second
|
|
||||||
and prints all messages received.
|
|
||||||
|
|
||||||
To run the example, start the server:
|
|
||||||
|
|
||||||
$ go run server.go
|
|
||||||
|
|
||||||
Next, start the client:
|
|
||||||
|
|
||||||
$ go run client.go
|
|
||||||
|
|
||||||
The server includes a simple web client. To use the client, open
|
|
||||||
http://127.0.0.1:8080 in the browser and follow the instructions on the page.
|
|
81
vendor/github.com/gorilla/websocket/examples/echo/client.go
generated
vendored
81
vendor/github.com/gorilla/websocket/examples/echo/client.go
generated
vendored
@ -1,81 +0,0 @@
|
|||||||
// Copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"log"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
)
|
|
||||||
|
|
||||||
var addr = flag.String("addr", "localhost:8080", "http service address")
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Parse()
|
|
||||||
log.SetFlags(0)
|
|
||||||
|
|
||||||
interrupt := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(interrupt, os.Interrupt)
|
|
||||||
|
|
||||||
u := url.URL{Scheme: "ws", Host: *addr, Path: "/echo"}
|
|
||||||
log.Printf("connecting to %s", u.String())
|
|
||||||
|
|
||||||
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("dial:", err)
|
|
||||||
}
|
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
done := make(chan struct{})
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
defer c.Close()
|
|
||||||
defer close(done)
|
|
||||||
for {
|
|
||||||
_, message, err := c.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("read:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Printf("recv: %s", message)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
ticker := time.NewTicker(time.Second)
|
|
||||||
defer ticker.Stop()
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case t := <-ticker.C:
|
|
||||||
err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
|
|
||||||
if err != nil {
|
|
||||||
log.Println("write:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case <-interrupt:
|
|
||||||
log.Println("interrupt")
|
|
||||||
// To cleanly close a connection, a client should send a close
|
|
||||||
// frame and wait for the server to close the connection.
|
|
||||||
err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
|
||||||
if err != nil {
|
|
||||||
log.Println("write close:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-done:
|
|
||||||
case <-time.After(time.Second):
|
|
||||||
}
|
|
||||||
c.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
132
vendor/github.com/gorilla/websocket/examples/echo/server.go
generated
vendored
132
vendor/github.com/gorilla/websocket/examples/echo/server.go
generated
vendored
@ -1,132 +0,0 @@
|
|||||||
// Copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"html/template"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
)
|
|
||||||
|
|
||||||
var addr = flag.String("addr", "localhost:8080", "http service address")
|
|
||||||
|
|
||||||
var upgrader = websocket.Upgrader{} // use default options
|
|
||||||
|
|
||||||
func echo(w http.ResponseWriter, r *http.Request) {
|
|
||||||
c, err := upgrader.Upgrade(w, r, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Print("upgrade:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer c.Close()
|
|
||||||
for {
|
|
||||||
mt, message, err := c.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("read:", err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
log.Printf("recv: %s", message)
|
|
||||||
err = c.WriteMessage(mt, message)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("write:", err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func home(w http.ResponseWriter, r *http.Request) {
|
|
||||||
homeTemplate.Execute(w, "ws://"+r.Host+"/echo")
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Parse()
|
|
||||||
log.SetFlags(0)
|
|
||||||
http.HandleFunc("/echo", echo)
|
|
||||||
http.HandleFunc("/", home)
|
|
||||||
log.Fatal(http.ListenAndServe(*addr, nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
var homeTemplate = template.Must(template.New("").Parse(`
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
window.addEventListener("load", function(evt) {
|
|
||||||
|
|
||||||
var output = document.getElementById("output");
|
|
||||||
var input = document.getElementById("input");
|
|
||||||
var ws;
|
|
||||||
|
|
||||||
var print = function(message) {
|
|
||||||
var d = document.createElement("div");
|
|
||||||
d.innerHTML = message;
|
|
||||||
output.appendChild(d);
|
|
||||||
};
|
|
||||||
|
|
||||||
document.getElementById("open").onclick = function(evt) {
|
|
||||||
if (ws) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ws = new WebSocket("{{.}}");
|
|
||||||
ws.onopen = function(evt) {
|
|
||||||
print("OPEN");
|
|
||||||
}
|
|
||||||
ws.onclose = function(evt) {
|
|
||||||
print("CLOSE");
|
|
||||||
ws = null;
|
|
||||||
}
|
|
||||||
ws.onmessage = function(evt) {
|
|
||||||
print("RESPONSE: " + evt.data);
|
|
||||||
}
|
|
||||||
ws.onerror = function(evt) {
|
|
||||||
print("ERROR: " + evt.data);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
document.getElementById("send").onclick = function(evt) {
|
|
||||||
if (!ws) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
print("SEND: " + input.value);
|
|
||||||
ws.send(input.value);
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
document.getElementById("close").onclick = function(evt) {
|
|
||||||
if (!ws) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ws.close();
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<table>
|
|
||||||
<tr><td valign="top" width="50%">
|
|
||||||
<p>Click "Open" to create a connection to the server,
|
|
||||||
"Send" to send a message to the server and "Close" to close the connection.
|
|
||||||
You can change the message and send multiple times.
|
|
||||||
<p>
|
|
||||||
<form>
|
|
||||||
<button id="open">Open</button>
|
|
||||||
<button id="close">Close</button>
|
|
||||||
<p><input id="input" type="text" value="Hello world!">
|
|
||||||
<button id="send">Send</button>
|
|
||||||
</form>
|
|
||||||
</td><td valign="top" width="50%">
|
|
||||||
<div id="output"></div>
|
|
||||||
</td></tr></table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`))
|
|
9
vendor/github.com/gorilla/websocket/examples/filewatch/README.md
generated
vendored
9
vendor/github.com/gorilla/websocket/examples/filewatch/README.md
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
# File Watch example.
|
|
||||||
|
|
||||||
This example sends a file to the browser client for display whenever the file is modified.
|
|
||||||
|
|
||||||
$ go get github.com/gorilla/websocket
|
|
||||||
$ cd `go list -f '{{.Dir}}' github.com/gorilla/websocket/examples/filewatch`
|
|
||||||
$ go run main.go <name of file to watch>
|
|
||||||
# Open http://localhost:8080/ .
|
|
||||||
# Modify the file to see it update in the browser.
|
|
193
vendor/github.com/gorilla/websocket/examples/filewatch/main.go
generated
vendored
193
vendor/github.com/gorilla/websocket/examples/filewatch/main.go
generated
vendored
@ -1,193 +0,0 @@
|
|||||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"html/template"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Time allowed to write the file to the client.
|
|
||||||
writeWait = 10 * time.Second
|
|
||||||
|
|
||||||
// Time allowed to read the next pong message from the client.
|
|
||||||
pongWait = 60 * time.Second
|
|
||||||
|
|
||||||
// Send pings to client with this period. Must be less than pongWait.
|
|
||||||
pingPeriod = (pongWait * 9) / 10
|
|
||||||
|
|
||||||
// Poll file for changes with this period.
|
|
||||||
filePeriod = 10 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
addr = flag.String("addr", ":8080", "http service address")
|
|
||||||
homeTempl = template.Must(template.New("").Parse(homeHTML))
|
|
||||||
filename string
|
|
||||||
upgrader = websocket.Upgrader{
|
|
||||||
ReadBufferSize: 1024,
|
|
||||||
WriteBufferSize: 1024,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func readFileIfModified(lastMod time.Time) ([]byte, time.Time, error) {
|
|
||||||
fi, err := os.Stat(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, lastMod, err
|
|
||||||
}
|
|
||||||
if !fi.ModTime().After(lastMod) {
|
|
||||||
return nil, lastMod, nil
|
|
||||||
}
|
|
||||||
p, err := ioutil.ReadFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fi.ModTime(), err
|
|
||||||
}
|
|
||||||
return p, fi.ModTime(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func reader(ws *websocket.Conn) {
|
|
||||||
defer ws.Close()
|
|
||||||
ws.SetReadLimit(512)
|
|
||||||
ws.SetReadDeadline(time.Now().Add(pongWait))
|
|
||||||
ws.SetPongHandler(func(string) error { ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
|
||||||
for {
|
|
||||||
_, _, err := ws.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func writer(ws *websocket.Conn, lastMod time.Time) {
|
|
||||||
lastError := ""
|
|
||||||
pingTicker := time.NewTicker(pingPeriod)
|
|
||||||
fileTicker := time.NewTicker(filePeriod)
|
|
||||||
defer func() {
|
|
||||||
pingTicker.Stop()
|
|
||||||
fileTicker.Stop()
|
|
||||||
ws.Close()
|
|
||||||
}()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-fileTicker.C:
|
|
||||||
var p []byte
|
|
||||||
var err error
|
|
||||||
|
|
||||||
p, lastMod, err = readFileIfModified(lastMod)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if s := err.Error(); s != lastError {
|
|
||||||
lastError = s
|
|
||||||
p = []byte(lastError)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lastError = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if p != nil {
|
|
||||||
ws.SetWriteDeadline(time.Now().Add(writeWait))
|
|
||||||
if err := ws.WriteMessage(websocket.TextMessage, p); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case <-pingTicker.C:
|
|
||||||
ws.SetWriteDeadline(time.Now().Add(writeWait))
|
|
||||||
if err := ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func serveWs(w http.ResponseWriter, r *http.Request) {
|
|
||||||
ws, err := upgrader.Upgrade(w, r, nil)
|
|
||||||
if err != nil {
|
|
||||||
if _, ok := err.(websocket.HandshakeError); !ok {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastMod time.Time
|
|
||||||
if n, err := strconv.ParseInt(r.FormValue("lastMod"), 16, 64); err == nil {
|
|
||||||
lastMod = time.Unix(0, n)
|
|
||||||
}
|
|
||||||
|
|
||||||
go writer(ws, lastMod)
|
|
||||||
reader(ws)
|
|
||||||
}
|
|
||||||
|
|
||||||
func serveHome(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.URL.Path != "/" {
|
|
||||||
http.Error(w, "Not found", 404)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.Method != "GET" {
|
|
||||||
http.Error(w, "Method not allowed", 405)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
||||||
p, lastMod, err := readFileIfModified(time.Time{})
|
|
||||||
if err != nil {
|
|
||||||
p = []byte(err.Error())
|
|
||||||
lastMod = time.Unix(0, 0)
|
|
||||||
}
|
|
||||||
var v = struct {
|
|
||||||
Host string
|
|
||||||
Data string
|
|
||||||
LastMod string
|
|
||||||
}{
|
|
||||||
r.Host,
|
|
||||||
string(p),
|
|
||||||
strconv.FormatInt(lastMod.UnixNano(), 16),
|
|
||||||
}
|
|
||||||
homeTempl.Execute(w, &v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Parse()
|
|
||||||
if flag.NArg() != 1 {
|
|
||||||
log.Fatal("filename not specified")
|
|
||||||
}
|
|
||||||
filename = flag.Args()[0]
|
|
||||||
http.HandleFunc("/", serveHome)
|
|
||||||
http.HandleFunc("/ws", serveWs)
|
|
||||||
if err := http.ListenAndServe(*addr, nil); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const homeHTML = `<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>WebSocket Example</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<pre id="fileData">{{.Data}}</pre>
|
|
||||||
<script type="text/javascript">
|
|
||||||
(function() {
|
|
||||||
var data = document.getElementById("fileData");
|
|
||||||
var conn = new WebSocket("ws://{{.Host}}/ws?lastMod={{.LastMod}}");
|
|
||||||
conn.onclose = function(evt) {
|
|
||||||
data.textContent = 'Connection closed';
|
|
||||||
}
|
|
||||||
conn.onmessage = function(evt) {
|
|
||||||
console.log('file updated');
|
|
||||||
data.textContent = evt.data;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`
|
|
119
vendor/github.com/gorilla/websocket/json_test.go
generated
vendored
119
vendor/github.com/gorilla/websocket/json_test.go
generated
vendored
@ -1,119 +0,0 @@
|
|||||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package websocket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"io"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestJSON(t *testing.T) {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
c := fakeNetConn{&buf, &buf}
|
|
||||||
wc := newConn(c, true, 1024, 1024)
|
|
||||||
rc := newConn(c, false, 1024, 1024)
|
|
||||||
|
|
||||||
var actual, expect struct {
|
|
||||||
A int
|
|
||||||
B string
|
|
||||||
}
|
|
||||||
expect.A = 1
|
|
||||||
expect.B = "hello"
|
|
||||||
|
|
||||||
if err := wc.WriteJSON(&expect); err != nil {
|
|
||||||
t.Fatal("write", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := rc.ReadJSON(&actual); err != nil {
|
|
||||||
t.Fatal("read", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(&actual, &expect) {
|
|
||||||
t.Fatal("equal", actual, expect)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPartialJSONRead(t *testing.T) {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
c := fakeNetConn{&buf, &buf}
|
|
||||||
wc := newConn(c, true, 1024, 1024)
|
|
||||||
rc := newConn(c, false, 1024, 1024)
|
|
||||||
|
|
||||||
var v struct {
|
|
||||||
A int
|
|
||||||
B string
|
|
||||||
}
|
|
||||||
v.A = 1
|
|
||||||
v.B = "hello"
|
|
||||||
|
|
||||||
messageCount := 0
|
|
||||||
|
|
||||||
// Partial JSON values.
|
|
||||||
|
|
||||||
data, err := json.Marshal(v)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
for i := len(data) - 1; i >= 0; i-- {
|
|
||||||
if err := wc.WriteMessage(TextMessage, data[:i]); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
messageCount++
|
|
||||||
}
|
|
||||||
|
|
||||||
// Whitespace.
|
|
||||||
|
|
||||||
if err := wc.WriteMessage(TextMessage, []byte(" ")); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
messageCount++
|
|
||||||
|
|
||||||
// Close.
|
|
||||||
|
|
||||||
if err := wc.WriteMessage(CloseMessage, FormatCloseMessage(CloseNormalClosure, "")); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < messageCount; i++ {
|
|
||||||
err := rc.ReadJSON(&v)
|
|
||||||
if err != io.ErrUnexpectedEOF {
|
|
||||||
t.Error("read", i, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = rc.ReadJSON(&v)
|
|
||||||
if _, ok := err.(*CloseError); !ok {
|
|
||||||
t.Error("final", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeprecatedJSON(t *testing.T) {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
c := fakeNetConn{&buf, &buf}
|
|
||||||
wc := newConn(c, true, 1024, 1024)
|
|
||||||
rc := newConn(c, false, 1024, 1024)
|
|
||||||
|
|
||||||
var actual, expect struct {
|
|
||||||
A int
|
|
||||||
B string
|
|
||||||
}
|
|
||||||
expect.A = 1
|
|
||||||
expect.B = "hello"
|
|
||||||
|
|
||||||
if err := WriteJSON(wc, &expect); err != nil {
|
|
||||||
t.Fatal("write", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ReadJSON(rc, &actual); err != nil {
|
|
||||||
t.Fatal("read", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(&actual, &expect) {
|
|
||||||
t.Fatal("equal", actual, expect)
|
|
||||||
}
|
|
||||||
}
|
|
73
vendor/github.com/gorilla/websocket/mask_test.go
generated
vendored
73
vendor/github.com/gorilla/websocket/mask_test.go
generated
vendored
@ -1,73 +0,0 @@
|
|||||||
// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of
|
|
||||||
// this source code is governed by a BSD-style license that can be found in the
|
|
||||||
// LICENSE file.
|
|
||||||
|
|
||||||
// Require 1.7 for sub-bencmarks
|
|
||||||
// +build go1.7,!appengine
|
|
||||||
|
|
||||||
package websocket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func maskBytesByByte(key [4]byte, pos int, b []byte) int {
|
|
||||||
for i := range b {
|
|
||||||
b[i] ^= key[pos&3]
|
|
||||||
pos++
|
|
||||||
}
|
|
||||||
return pos & 3
|
|
||||||
}
|
|
||||||
|
|
||||||
func notzero(b []byte) int {
|
|
||||||
for i := range b {
|
|
||||||
if b[i] != 0 {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMaskBytes(t *testing.T) {
|
|
||||||
key := [4]byte{1, 2, 3, 4}
|
|
||||||
for size := 1; size <= 1024; size++ {
|
|
||||||
for align := 0; align < wordSize; align++ {
|
|
||||||
for pos := 0; pos < 4; pos++ {
|
|
||||||
b := make([]byte, size+align)[align:]
|
|
||||||
maskBytes(key, pos, b)
|
|
||||||
maskBytesByByte(key, pos, b)
|
|
||||||
if i := notzero(b); i >= 0 {
|
|
||||||
t.Errorf("size:%d, align:%d, pos:%d, offset:%d", size, align, pos, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkMaskBytes(b *testing.B) {
|
|
||||||
for _, size := range []int{2, 4, 8, 16, 32, 512, 1024} {
|
|
||||||
b.Run(fmt.Sprintf("size-%d", size), func(b *testing.B) {
|
|
||||||
for _, align := range []int{wordSize / 2} {
|
|
||||||
b.Run(fmt.Sprintf("align-%d", align), func(b *testing.B) {
|
|
||||||
for _, fn := range []struct {
|
|
||||||
name string
|
|
||||||
fn func(key [4]byte, pos int, b []byte) int
|
|
||||||
}{
|
|
||||||
{"byte", maskBytesByByte},
|
|
||||||
{"word", maskBytes},
|
|
||||||
} {
|
|
||||||
b.Run(fn.name, func(b *testing.B) {
|
|
||||||
key := newMaskKey()
|
|
||||||
data := make([]byte, size+align)[align:]
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
fn.fn(key, 0, data)
|
|
||||||
}
|
|
||||||
b.SetBytes(int64(len(data)))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
74
vendor/github.com/gorilla/websocket/prepared_test.go
generated
vendored
74
vendor/github.com/gorilla/websocket/prepared_test.go
generated
vendored
@ -1,74 +0,0 @@
|
|||||||
// Copyright 2017 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package websocket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"compress/flate"
|
|
||||||
"math/rand"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var preparedMessageTests = []struct {
|
|
||||||
messageType int
|
|
||||||
isServer bool
|
|
||||||
enableWriteCompression bool
|
|
||||||
compressionLevel int
|
|
||||||
}{
|
|
||||||
// Server
|
|
||||||
{TextMessage, true, false, flate.BestSpeed},
|
|
||||||
{TextMessage, true, true, flate.BestSpeed},
|
|
||||||
{TextMessage, true, true, flate.BestCompression},
|
|
||||||
{PingMessage, true, false, flate.BestSpeed},
|
|
||||||
{PingMessage, true, true, flate.BestSpeed},
|
|
||||||
|
|
||||||
// Client
|
|
||||||
{TextMessage, false, false, flate.BestSpeed},
|
|
||||||
{TextMessage, false, true, flate.BestSpeed},
|
|
||||||
{TextMessage, false, true, flate.BestCompression},
|
|
||||||
{PingMessage, false, false, flate.BestSpeed},
|
|
||||||
{PingMessage, false, true, flate.BestSpeed},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPreparedMessage(t *testing.T) {
|
|
||||||
for _, tt := range preparedMessageTests {
|
|
||||||
var data = []byte("this is a test")
|
|
||||||
var buf bytes.Buffer
|
|
||||||
c := newConn(fakeNetConn{Reader: nil, Writer: &buf}, tt.isServer, 1024, 1024)
|
|
||||||
if tt.enableWriteCompression {
|
|
||||||
c.newCompressionWriter = compressNoContextTakeover
|
|
||||||
}
|
|
||||||
c.SetCompressionLevel(tt.compressionLevel)
|
|
||||||
|
|
||||||
// Seed random number generator for consistent frame mask.
|
|
||||||
rand.Seed(1234)
|
|
||||||
|
|
||||||
if err := c.WriteMessage(tt.messageType, data); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
want := buf.String()
|
|
||||||
|
|
||||||
pm, err := NewPreparedMessage(tt.messageType, data)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scribble on data to ensure that NewPreparedMessage takes a snapshot.
|
|
||||||
copy(data, "hello world")
|
|
||||||
|
|
||||||
// Seed random number generator for consistent frame mask.
|
|
||||||
rand.Seed(1234)
|
|
||||||
|
|
||||||
buf.Reset()
|
|
||||||
if err := c.WritePreparedMessage(pm); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
got := buf.String()
|
|
||||||
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("write message != prepared message for %+v", tt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
51
vendor/github.com/gorilla/websocket/server_test.go
generated
vendored
51
vendor/github.com/gorilla/websocket/server_test.go
generated
vendored
@ -1,51 +0,0 @@
|
|||||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package websocket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var subprotocolTests = []struct {
|
|
||||||
h string
|
|
||||||
protocols []string
|
|
||||||
}{
|
|
||||||
{"", nil},
|
|
||||||
{"foo", []string{"foo"}},
|
|
||||||
{"foo,bar", []string{"foo", "bar"}},
|
|
||||||
{"foo, bar", []string{"foo", "bar"}},
|
|
||||||
{" foo, bar", []string{"foo", "bar"}},
|
|
||||||
{" foo, bar ", []string{"foo", "bar"}},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSubprotocols(t *testing.T) {
|
|
||||||
for _, st := range subprotocolTests {
|
|
||||||
r := http.Request{Header: http.Header{"Sec-Websocket-Protocol": {st.h}}}
|
|
||||||
protocols := Subprotocols(&r)
|
|
||||||
if !reflect.DeepEqual(st.protocols, protocols) {
|
|
||||||
t.Errorf("SubProtocols(%q) returned %#v, want %#v", st.h, protocols, st.protocols)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var isWebSocketUpgradeTests = []struct {
|
|
||||||
ok bool
|
|
||||||
h http.Header
|
|
||||||
}{
|
|
||||||
{false, http.Header{"Upgrade": {"websocket"}}},
|
|
||||||
{false, http.Header{"Connection": {"upgrade"}}},
|
|
||||||
{true, http.Header{"Connection": {"upgRade"}, "Upgrade": {"WebSocket"}}},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsWebSocketUpgrade(t *testing.T) {
|
|
||||||
for _, tt := range isWebSocketUpgradeTests {
|
|
||||||
ok := IsWebSocketUpgrade(&http.Request{Header: tt.h})
|
|
||||||
if tt.ok != ok {
|
|
||||||
t.Errorf("IsWebSocketUpgrade(%v) returned %v, want %v", tt.h, ok, tt.ok)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
74
vendor/github.com/gorilla/websocket/util_test.go
generated
vendored
74
vendor/github.com/gorilla/websocket/util_test.go
generated
vendored
@ -1,74 +0,0 @@
|
|||||||
// Copyright 2014 The Gorilla WebSocket Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package websocket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var tokenListContainsValueTests = []struct {
|
|
||||||
value string
|
|
||||||
ok bool
|
|
||||||
}{
|
|
||||||
{"WebSocket", true},
|
|
||||||
{"WEBSOCKET", true},
|
|
||||||
{"websocket", true},
|
|
||||||
{"websockets", false},
|
|
||||||
{"x websocket", false},
|
|
||||||
{"websocket x", false},
|
|
||||||
{"other,websocket,more", true},
|
|
||||||
{"other, websocket, more", true},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTokenListContainsValue(t *testing.T) {
|
|
||||||
for _, tt := range tokenListContainsValueTests {
|
|
||||||
h := http.Header{"Upgrade": {tt.value}}
|
|
||||||
ok := tokenListContainsValue(h, "Upgrade", "websocket")
|
|
||||||
if ok != tt.ok {
|
|
||||||
t.Errorf("tokenListContainsValue(h, n, %q) = %v, want %v", tt.value, ok, tt.ok)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var parseExtensionTests = []struct {
|
|
||||||
value string
|
|
||||||
extensions []map[string]string
|
|
||||||
}{
|
|
||||||
{`foo`, []map[string]string{map[string]string{"": "foo"}}},
|
|
||||||
{`foo, bar; baz=2`, []map[string]string{
|
|
||||||
map[string]string{"": "foo"},
|
|
||||||
map[string]string{"": "bar", "baz": "2"}}},
|
|
||||||
{`foo; bar="b,a;z"`, []map[string]string{
|
|
||||||
map[string]string{"": "foo", "bar": "b,a;z"}}},
|
|
||||||
{`foo , bar; baz = 2`, []map[string]string{
|
|
||||||
map[string]string{"": "foo"},
|
|
||||||
map[string]string{"": "bar", "baz": "2"}}},
|
|
||||||
{`foo, bar; baz=2 junk`, []map[string]string{
|
|
||||||
map[string]string{"": "foo"}}},
|
|
||||||
{`foo junk, bar; baz=2 junk`, nil},
|
|
||||||
{`mux; max-channels=4; flow-control, deflate-stream`, []map[string]string{
|
|
||||||
map[string]string{"": "mux", "max-channels": "4", "flow-control": ""},
|
|
||||||
map[string]string{"": "deflate-stream"}}},
|
|
||||||
{`permessage-foo; x="10"`, []map[string]string{
|
|
||||||
map[string]string{"": "permessage-foo", "x": "10"}}},
|
|
||||||
{`permessage-foo; use_y, permessage-foo`, []map[string]string{
|
|
||||||
map[string]string{"": "permessage-foo", "use_y": ""},
|
|
||||||
map[string]string{"": "permessage-foo"}}},
|
|
||||||
{`permessage-deflate; client_max_window_bits; server_max_window_bits=10 , permessage-deflate; client_max_window_bits`, []map[string]string{
|
|
||||||
map[string]string{"": "permessage-deflate", "client_max_window_bits": "", "server_max_window_bits": "10"},
|
|
||||||
map[string]string{"": "permessage-deflate", "client_max_window_bits": ""}}},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseExtensions(t *testing.T) {
|
|
||||||
for _, tt := range parseExtensionTests {
|
|
||||||
h := http.Header{http.CanonicalHeaderKey("Sec-WebSocket-Extensions"): {tt.value}}
|
|
||||||
extensions := parseExtensions(h)
|
|
||||||
if !reflect.DeepEqual(extensions, tt.extensions) {
|
|
||||||
t.Errorf("parseExtensions(%q)\n = %v,\nwant %v", tt.value, extensions, tt.extensions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
15
vendor/modules.txt
vendored
Normal file
15
vendor/modules.txt
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# code.ivysaur.me/libnmdc v0.16.0
|
||||||
|
code.ivysaur.me/libnmdc
|
||||||
|
# github.com/cxmcc/tiger v0.0.0-20170524142333-bde35e2713d7
|
||||||
|
github.com/cxmcc/tiger
|
||||||
|
# github.com/googollee/go-engine.io v0.0.0-20170224222511-80ae0e43aca1
|
||||||
|
github.com/googollee/go-engine.io
|
||||||
|
github.com/googollee/go-engine.io/message
|
||||||
|
github.com/googollee/go-engine.io/parser
|
||||||
|
github.com/googollee/go-engine.io/polling
|
||||||
|
github.com/googollee/go-engine.io/transport
|
||||||
|
github.com/googollee/go-engine.io/websocket
|
||||||
|
# github.com/googollee/go-socket.io v0.0.0-20170525141029-5447e71f36d3
|
||||||
|
github.com/googollee/go-socket.io
|
||||||
|
# github.com/gorilla/websocket v1.2.0
|
||||||
|
github.com/gorilla/websocket
|
Loading…
Reference in New Issue
Block a user