websocket 增加多分组 fork https://github.com/olahol/melody
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

643 lines
12 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
  1. package melody
  2. import (
  3. "bytes"
  4. "github.com/gorilla/websocket"
  5. "math/rand"
  6. "net/http"
  7. "net/http/httptest"
  8. "strconv"
  9. "strings"
  10. "testing"
  11. "testing/quick"
  12. "time"
  13. )
  14. type TestServer struct {
  15. m *Melody
  16. }
  17. func NewTestServerHandler(handler handleMessageFunc) *TestServer {
  18. m := New()
  19. m.HandleMessage(handler)
  20. return &TestServer{
  21. m: m,
  22. }
  23. }
  24. func NewTestServer() *TestServer {
  25. m := New()
  26. return &TestServer{
  27. m: m,
  28. }
  29. }
  30. func (s *TestServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  31. s.m.HandleRequest(w, r)
  32. }
  33. func NewDialer(url string) (*websocket.Conn, error) {
  34. dialer := &websocket.Dialer{}
  35. conn, _, err := dialer.Dial(strings.Replace(url, "http", "ws", 1), nil)
  36. return conn, err
  37. }
  38. func TestEcho(t *testing.T) {
  39. echo := NewTestServerHandler(func(session *Session, msg []byte) {
  40. session.Write(msg)
  41. })
  42. server := httptest.NewServer(echo)
  43. defer server.Close()
  44. fn := func(msg string) bool {
  45. conn, err := NewDialer(server.URL)
  46. defer conn.Close()
  47. if err != nil {
  48. t.Error(err)
  49. return false
  50. }
  51. conn.WriteMessage(websocket.TextMessage, []byte(msg))
  52. _, ret, err := conn.ReadMessage()
  53. if err != nil {
  54. t.Error(err)
  55. return false
  56. }
  57. if msg != string(ret) {
  58. t.Errorf("%s should equal %s", msg, string(ret))
  59. return false
  60. }
  61. return true
  62. }
  63. if err := quick.Check(fn, nil); err != nil {
  64. t.Error(err)
  65. }
  66. }
  67. func TestLen(t *testing.T) {
  68. rand.Seed(time.Now().UnixNano())
  69. connect := int(rand.Int31n(1000))
  70. disconnect := rand.Float32()
  71. conns := make([]*websocket.Conn, connect)
  72. defer func() {
  73. for _, conn := range conns {
  74. if conn != nil {
  75. conn.Close()
  76. }
  77. }
  78. }()
  79. echo := NewTestServerHandler(func(session *Session, msg []byte) {})
  80. server := httptest.NewServer(echo)
  81. defer server.Close()
  82. disconnected := 0
  83. for i := 0; i < connect; i++ {
  84. conn, err := NewDialer(server.URL)
  85. if err != nil {
  86. t.Error(err)
  87. }
  88. if rand.Float32() < disconnect {
  89. conns[i] = nil
  90. disconnected += 1
  91. conn.Close()
  92. continue
  93. }
  94. conns[i] = conn
  95. }
  96. time.Sleep(time.Millisecond)
  97. connected := connect - disconnected
  98. if echo.m.Len() != connected {
  99. t.Errorf("melody len %d should equal %d", echo.m.Len(), connected)
  100. }
  101. }
  102. func TestEchoBinary(t *testing.T) {
  103. echo := NewTestServer()
  104. echo.m.HandleMessageBinary(func(session *Session, msg []byte) {
  105. session.WriteBinary(msg)
  106. })
  107. server := httptest.NewServer(echo)
  108. defer server.Close()
  109. fn := func(msg string) bool {
  110. conn, err := NewDialer(server.URL)
  111. defer conn.Close()
  112. if err != nil {
  113. t.Error(err)
  114. return false
  115. }
  116. conn.WriteMessage(websocket.BinaryMessage, []byte(msg))
  117. _, ret, err := conn.ReadMessage()
  118. if err != nil {
  119. t.Error(err)
  120. return false
  121. }
  122. if msg != string(ret) {
  123. t.Errorf("%s should equal %s", msg, string(ret))
  124. return false
  125. }
  126. return true
  127. }
  128. if err := quick.Check(fn, nil); err != nil {
  129. t.Error(err)
  130. }
  131. }
  132. func TestHandlers(t *testing.T) {
  133. echo := NewTestServer()
  134. echo.m.HandleMessage(func(session *Session, msg []byte) {
  135. session.Write(msg)
  136. })
  137. server := httptest.NewServer(echo)
  138. defer server.Close()
  139. var q *Session
  140. echo.m.HandleConnect(func(session *Session) {
  141. q = session
  142. session.Close()
  143. })
  144. echo.m.HandleDisconnect(func(session *Session) {
  145. if q != session {
  146. t.Error("disconnecting session should be the same as connecting")
  147. }
  148. })
  149. NewDialer(server.URL)
  150. }
  151. func TestMetadata(t *testing.T) {
  152. echo := NewTestServer()
  153. echo.m.HandleConnect(func(session *Session) {
  154. session.Set("stamp", time.Now().UnixNano())
  155. })
  156. echo.m.HandleMessage(func(session *Session, msg []byte) {
  157. stamp := session.MustGet("stamp").(int64)
  158. session.Write([]byte(strconv.Itoa(int(stamp))))
  159. })
  160. server := httptest.NewServer(echo)
  161. defer server.Close()
  162. fn := func(msg string) bool {
  163. conn, err := NewDialer(server.URL)
  164. defer conn.Close()
  165. if err != nil {
  166. t.Error(err)
  167. return false
  168. }
  169. conn.WriteMessage(websocket.TextMessage, []byte(msg))
  170. _, ret, err := conn.ReadMessage()
  171. if err != nil {
  172. t.Error(err)
  173. return false
  174. }
  175. stamp, err := strconv.Atoi(string(ret))
  176. if err != nil {
  177. t.Error(err)
  178. return false
  179. }
  180. diff := int(time.Now().UnixNano()) - stamp
  181. if diff <= 0 {
  182. t.Errorf("diff should be above 0 %d", diff)
  183. return false
  184. }
  185. return true
  186. }
  187. if err := quick.Check(fn, nil); err != nil {
  188. t.Error(err)
  189. }
  190. }
  191. func TestUpgrader(t *testing.T) {
  192. broadcast := NewTestServer()
  193. broadcast.m.HandleMessage(func(session *Session, msg []byte) {
  194. session.Write(msg)
  195. })
  196. server := httptest.NewServer(broadcast)
  197. defer server.Close()
  198. broadcast.m.Upgrader = &websocket.Upgrader{
  199. ReadBufferSize: 1024,
  200. WriteBufferSize: 1024,
  201. CheckOrigin: func(r *http.Request) bool { return false },
  202. }
  203. broadcast.m.HandleError(func(session *Session, err error) {
  204. if err == nil || err.Error() != "websocket: origin not allowed" {
  205. t.Error("there should be a origin error")
  206. }
  207. })
  208. _, err := NewDialer(server.URL)
  209. if err == nil || err.Error() != "websocket: bad handshake" {
  210. t.Error("there should be a badhandshake error")
  211. }
  212. }
  213. func TestBroadcast(t *testing.T) {
  214. broadcast := NewTestServer()
  215. broadcast.m.HandleMessage(func(session *Session, msg []byte) {
  216. broadcast.m.Broadcast(msg)
  217. })
  218. server := httptest.NewServer(broadcast)
  219. defer server.Close()
  220. n := 10
  221. fn := func(msg string) bool {
  222. conn, _ := NewDialer(server.URL)
  223. defer conn.Close()
  224. listeners := make([]*websocket.Conn, n)
  225. for i := 0; i < n; i++ {
  226. listener, _ := NewDialer(server.URL)
  227. listeners[i] = listener
  228. defer listeners[i].Close()
  229. }
  230. conn.WriteMessage(websocket.TextMessage, []byte(msg))
  231. for i := 0; i < n; i++ {
  232. _, ret, err := listeners[i].ReadMessage()
  233. if err != nil {
  234. t.Error(err)
  235. return false
  236. }
  237. if msg != string(ret) {
  238. t.Errorf("%s should equal %s", msg, string(ret))
  239. return false
  240. }
  241. }
  242. return true
  243. }
  244. if !fn("test") {
  245. t.Errorf("should not be false")
  246. }
  247. }
  248. func TestBroadcastBinary(t *testing.T) {
  249. broadcast := NewTestServer()
  250. broadcast.m.HandleMessageBinary(func(session *Session, msg []byte) {
  251. broadcast.m.BroadcastBinary(msg)
  252. })
  253. server := httptest.NewServer(broadcast)
  254. defer server.Close()
  255. n := 10
  256. fn := func(msg []byte) bool {
  257. conn, _ := NewDialer(server.URL)
  258. defer conn.Close()
  259. listeners := make([]*websocket.Conn, n)
  260. for i := 0; i < n; i++ {
  261. listener, _ := NewDialer(server.URL)
  262. listeners[i] = listener
  263. defer listeners[i].Close()
  264. }
  265. conn.WriteMessage(websocket.BinaryMessage, []byte(msg))
  266. for i := 0; i < n; i++ {
  267. messageType, ret, err := listeners[i].ReadMessage()
  268. if err != nil {
  269. t.Error(err)
  270. return false
  271. }
  272. if messageType != websocket.BinaryMessage {
  273. t.Errorf("message type should be BinaryMessage")
  274. return false
  275. }
  276. if !bytes.Equal(msg, ret) {
  277. t.Errorf("%v should equal %v", msg, ret)
  278. return false
  279. }
  280. }
  281. return true
  282. }
  283. if !fn([]byte{2, 3, 5, 7, 11}) {
  284. t.Errorf("should not be false")
  285. }
  286. }
  287. func TestBroadcastOthers(t *testing.T) {
  288. broadcast := NewTestServer()
  289. broadcast.m.HandleMessage(func(session *Session, msg []byte) {
  290. broadcast.m.BroadcastOthers(msg, session)
  291. })
  292. broadcast.m.Config.PongWait = time.Second
  293. broadcast.m.Config.PingPeriod = time.Second * 9 / 10
  294. server := httptest.NewServer(broadcast)
  295. defer server.Close()
  296. n := 10
  297. fn := func(msg string) bool {
  298. conn, _ := NewDialer(server.URL)
  299. defer conn.Close()
  300. listeners := make([]*websocket.Conn, n)
  301. for i := 0; i < n; i++ {
  302. listener, _ := NewDialer(server.URL)
  303. listeners[i] = listener
  304. defer listeners[i].Close()
  305. }
  306. conn.WriteMessage(websocket.TextMessage, []byte(msg))
  307. for i := 0; i < n; i++ {
  308. _, ret, err := listeners[i].ReadMessage()
  309. if err != nil {
  310. t.Error(err)
  311. return false
  312. }
  313. if msg != string(ret) {
  314. t.Errorf("%s should equal %s", msg, string(ret))
  315. return false
  316. }
  317. }
  318. return true
  319. }
  320. if !fn("test") {
  321. t.Errorf("should not be false")
  322. }
  323. }
  324. func TestBroadcastBinaryOthers(t *testing.T) {
  325. broadcast := NewTestServer()
  326. broadcast.m.HandleMessageBinary(func(session *Session, msg []byte) {
  327. broadcast.m.BroadcastBinaryOthers(msg, session)
  328. })
  329. broadcast.m.Config.PongWait = time.Second
  330. broadcast.m.Config.PingPeriod = time.Second * 9 / 10
  331. server := httptest.NewServer(broadcast)
  332. defer server.Close()
  333. n := 10
  334. fn := func(msg []byte) bool {
  335. conn, _ := NewDialer(server.URL)
  336. defer conn.Close()
  337. listeners := make([]*websocket.Conn, n)
  338. for i := 0; i < n; i++ {
  339. listener, _ := NewDialer(server.URL)
  340. listeners[i] = listener
  341. defer listeners[i].Close()
  342. }
  343. conn.WriteMessage(websocket.BinaryMessage, []byte(msg))
  344. for i := 0; i < n; i++ {
  345. messageType, ret, err := listeners[i].ReadMessage()
  346. if err != nil {
  347. t.Error(err)
  348. return false
  349. }
  350. if messageType != websocket.BinaryMessage {
  351. t.Errorf("message type should be BinaryMessage")
  352. return false
  353. }
  354. if !bytes.Equal(msg, ret) {
  355. t.Errorf("%v should equal %v", msg, ret)
  356. return false
  357. }
  358. }
  359. return true
  360. }
  361. if !fn([]byte{2, 3, 5, 7, 11}) {
  362. t.Errorf("should not be false")
  363. }
  364. }
  365. func TestPingPong(t *testing.T) {
  366. noecho := NewTestServer()
  367. noecho.m.Config.PongWait = time.Second
  368. noecho.m.Config.PingPeriod = time.Second * 9 / 10
  369. server := httptest.NewServer(noecho)
  370. defer server.Close()
  371. conn, err := NewDialer(server.URL)
  372. conn.SetPingHandler(func(string) error {
  373. return nil
  374. })
  375. defer conn.Close()
  376. if err != nil {
  377. t.Error(err)
  378. }
  379. conn.WriteMessage(websocket.TextMessage, []byte("test"))
  380. _, _, err = conn.ReadMessage()
  381. if err == nil {
  382. t.Error("there should be an error")
  383. }
  384. }
  385. func TestBroadcastFilter(t *testing.T) {
  386. broadcast := NewTestServer()
  387. broadcast.m.HandleMessage(func(session *Session, msg []byte) {
  388. broadcast.m.BroadcastFilter(msg, func(q *Session) bool {
  389. return session == q
  390. })
  391. })
  392. server := httptest.NewServer(broadcast)
  393. defer server.Close()
  394. fn := func(msg string) bool {
  395. conn, err := NewDialer(server.URL)
  396. defer conn.Close()
  397. if err != nil {
  398. t.Error(err)
  399. return false
  400. }
  401. conn.WriteMessage(websocket.TextMessage, []byte(msg))
  402. _, ret, err := conn.ReadMessage()
  403. if err != nil {
  404. t.Error(err)
  405. return false
  406. }
  407. if msg != string(ret) {
  408. t.Errorf("%s should equal %s", msg, string(ret))
  409. return false
  410. }
  411. return true
  412. }
  413. if !fn("test") {
  414. t.Errorf("should not be false")
  415. }
  416. }
  417. func TestBroadcastBinaryFilter(t *testing.T) {
  418. broadcast := NewTestServer()
  419. broadcast.m.HandleMessageBinary(func(session *Session, msg []byte) {
  420. broadcast.m.BroadcastBinaryFilter(msg, func(q *Session) bool {
  421. return session == q
  422. })
  423. })
  424. server := httptest.NewServer(broadcast)
  425. defer server.Close()
  426. fn := func(msg []byte) bool {
  427. conn, err := NewDialer(server.URL)
  428. defer conn.Close()
  429. if err != nil {
  430. t.Error(err)
  431. return false
  432. }
  433. conn.WriteMessage(websocket.BinaryMessage, []byte(msg))
  434. messageType, ret, err := conn.ReadMessage()
  435. if err != nil {
  436. t.Error(err)
  437. return false
  438. }
  439. if messageType != websocket.BinaryMessage {
  440. t.Errorf("message type should be BinaryMessage")
  441. return false
  442. }
  443. if !bytes.Equal(msg, ret) {
  444. t.Errorf("%v should equal %v", msg, ret)
  445. return false
  446. }
  447. return true
  448. }
  449. if !fn([]byte{2, 3, 5, 7, 11}) {
  450. t.Errorf("should not be false")
  451. }
  452. }
  453. func TestStop(t *testing.T) {
  454. noecho := NewTestServer()
  455. server := httptest.NewServer(noecho)
  456. defer server.Close()
  457. conn, err := NewDialer(server.URL)
  458. defer conn.Close()
  459. if err != nil {
  460. t.Error(err)
  461. }
  462. noecho.m.Close()
  463. }
  464. func TestSmallMessageBuffer(t *testing.T) {
  465. echo := NewTestServerHandler(func(session *Session, msg []byte) {
  466. session.Write(msg)
  467. })
  468. echo.m.Config.MessageBufferSize = 0
  469. echo.m.HandleError(func(s *Session, err error) {
  470. if err == nil {
  471. t.Error("there should be a buffer full error here")
  472. }
  473. })
  474. server := httptest.NewServer(echo)
  475. defer server.Close()
  476. conn, err := NewDialer(server.URL)
  477. defer conn.Close()
  478. if err != nil {
  479. t.Error(err)
  480. }
  481. conn.WriteMessage(websocket.TextMessage, []byte("12345"))
  482. }
  483. func TestPong(t *testing.T) {
  484. echo := NewTestServerHandler(func(session *Session, msg []byte) {
  485. session.Write(msg)
  486. })
  487. echo.m.Config.PongWait = time.Second
  488. echo.m.Config.PingPeriod = time.Second * 9 / 10
  489. server := httptest.NewServer(echo)
  490. defer server.Close()
  491. conn, err := NewDialer(server.URL)
  492. defer conn.Close()
  493. if err != nil {
  494. t.Error(err)
  495. }
  496. fired := false
  497. echo.m.HandlePong(func(s *Session) {
  498. fired = true
  499. })
  500. conn.WriteMessage(websocket.PongMessage, nil)
  501. time.Sleep(time.Millisecond)
  502. if !fired {
  503. t.Error("should have fired pong handler")
  504. }
  505. }