unit_router_test.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * Copyright (c) 2013 IBM Corp.
  3. *
  4. * All rights reserved. This program and the accompanying materials
  5. * are made available under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution, and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * Seth Hoenig
  11. * Allan Stockdill-Mander
  12. * Mike Robertson
  13. */
  14. package mqtt
  15. import (
  16. "testing"
  17. "github.com/eclipse/paho.mqtt.golang/packets"
  18. )
  19. func Test_newRouter(t *testing.T) {
  20. router, stop := newRouter()
  21. if router == nil {
  22. t.Fatalf("router is nil")
  23. }
  24. if stop == nil {
  25. t.Fatalf("stop is nil")
  26. }
  27. if router.routes.Len() != 0 {
  28. t.Fatalf("router.routes was not empty")
  29. }
  30. }
  31. func Test_AddRoute(t *testing.T) {
  32. router, _ := newRouter()
  33. cb := func(client Client, msg Message) {
  34. }
  35. router.addRoute("/alpha", cb)
  36. if router.routes.Len() != 1 {
  37. t.Fatalf("router.routes was wrong")
  38. }
  39. }
  40. func Test_Match(t *testing.T) {
  41. router, _ := newRouter()
  42. router.addRoute("/alpha", nil)
  43. if !router.routes.Front().Value.(*route).match("/alpha") {
  44. t.Fatalf("match function is bad")
  45. }
  46. if router.routes.Front().Value.(*route).match("alpha") {
  47. t.Fatalf("match function is bad")
  48. }
  49. }
  50. func Test_match(t *testing.T) {
  51. check := func(route, topic string, exp bool) {
  52. result := routeIncludesTopic(route, topic)
  53. if exp != result {
  54. t.Errorf("match was bad R: %v, T: %v, EXP: %v", route, topic, exp)
  55. }
  56. }
  57. // ** Basic **
  58. R := ""
  59. T := ""
  60. check(R, T, true)
  61. R = "x"
  62. T = ""
  63. check(R, T, false)
  64. R = ""
  65. T = "x"
  66. check(R, T, false)
  67. R = "x"
  68. T = "x"
  69. check(R, T, true)
  70. R = "x"
  71. T = "X"
  72. check(R, T, false)
  73. R = "alpha"
  74. T = "alpha"
  75. check(R, T, true)
  76. R = "alpha"
  77. T = "beta"
  78. check(R, T, false)
  79. // ** / **
  80. R = "/"
  81. T = "/"
  82. check(R, T, true)
  83. R = "/one"
  84. T = "/one"
  85. check(R, T, true)
  86. R = "/"
  87. T = "/two"
  88. check(R, T, false)
  89. R = "/two"
  90. T = "/"
  91. check(R, T, false)
  92. R = "/two"
  93. T = "two"
  94. check(R, T, false) // a leading "/" creates a different topic
  95. R = "/a/"
  96. T = "/a"
  97. check(R, T, false)
  98. R = "/a/"
  99. T = "/a/b"
  100. check(R, T, false)
  101. R = "/a/b"
  102. T = "/a/b"
  103. check(R, T, true)
  104. R = "/a/b/"
  105. T = "/a/b"
  106. check(R, T, false)
  107. R = "/a/b"
  108. T = "/R/b"
  109. check(R, T, false)
  110. // ** + **
  111. R = "/a/+/c"
  112. T = "/a/b/c"
  113. check(R, T, true)
  114. R = "/+/b/c"
  115. T = "/a/b/c"
  116. check(R, T, true)
  117. R = "/a/b/+"
  118. T = "/a/b/c"
  119. check(R, T, true)
  120. R = "/a/+/+"
  121. T = "/a/b/c"
  122. check(R, T, true)
  123. R = "/+/+/+"
  124. T = "/a/b/c"
  125. check(R, T, true)
  126. R = "/+/+/c"
  127. T = "/a/b/c"
  128. check(R, T, true)
  129. R = "/a/b/c/+" // different number of levels
  130. T = "/a/b/c"
  131. check(R, T, false)
  132. R = "+"
  133. T = "a"
  134. check(R, T, true)
  135. R = "/+"
  136. T = "a"
  137. check(R, T, false)
  138. R = "+/+"
  139. T = "/a"
  140. check(R, T, true)
  141. R = "+/+"
  142. T = "a"
  143. check(R, T, false)
  144. // ** # **
  145. R = "#"
  146. T = "/a/b/c"
  147. check(R, T, true)
  148. R = "/#"
  149. T = "/a/b/c"
  150. check(R, T, true)
  151. // R = "/#/" // not valid
  152. // T = "/a/b/c"
  153. // check(R, T, true)
  154. R = "/#"
  155. T = "/a/b/c"
  156. check(R, T, true)
  157. R = "/a/#"
  158. T = "/a/b/c"
  159. check(R, T, true)
  160. R = "/a/#"
  161. T = "/a/b/c"
  162. check(R, T, true)
  163. R = "/a/b/#"
  164. T = "/a/b/c"
  165. check(R, T, true)
  166. // ** unicode **
  167. R = "☃"
  168. T = "☃"
  169. check(R, T, true)
  170. R = "✈"
  171. T = "☃"
  172. check(R, T, false)
  173. R = "/☃/✈"
  174. T = "/☃/ッ"
  175. check(R, T, false)
  176. R = "#"
  177. T = "/☃/ッ"
  178. check(R, T, true)
  179. R = "/☃/+"
  180. T = "/☃/ッ/♫/ø/☹☹☹"
  181. check(R, T, false)
  182. R = "/☃/#"
  183. T = "/☃/ッ/♫/ø/☹☹☹"
  184. check(R, T, true)
  185. R = "/☃/ッ/♫/ø/+"
  186. T = "/☃/ッ/♫/ø/☹☹☹"
  187. check(R, T, true)
  188. R = "/☃/ッ/+/ø/☹☹☹"
  189. T = "/☃/ッ/♫/ø/☹☹☹"
  190. check(R, T, true)
  191. R = "/+/a/ッ/+/ø/☹☹☹"
  192. T = "/b/♫/ッ/♫/ø/☹☹☹"
  193. check(R, T, false)
  194. R = "/+/♫/ッ/+/ø/☹☹☹"
  195. T = "/b/♫/ッ/♫/ø/☹☹☹"
  196. check(R, T, true)
  197. }
  198. func Test_MatchAndDispatch(t *testing.T) {
  199. calledback := make(chan bool)
  200. cb := func(c Client, m Message) {
  201. calledback <- true
  202. }
  203. pub := packets.NewControlPacket(packets.Publish).(*packets.PublishPacket)
  204. pub.Qos = 2
  205. pub.TopicName = "a"
  206. pub.Payload = []byte("foo")
  207. msgs := make(chan *packets.PublishPacket)
  208. router, stopper := newRouter()
  209. router.addRoute("a", cb)
  210. router.matchAndDispatch(msgs, true, &client{oboundP: make(chan *PacketAndToken, 100)})
  211. msgs <- pub
  212. <-calledback
  213. stopper <- true
  214. select {
  215. case msgs <- pub:
  216. t.Errorf("msgs should not have a listener")
  217. default:
  218. }
  219. }
  220. func Test_SharedSubscription_MatchAndDispatch(t *testing.T) {
  221. calledback := make(chan bool)
  222. cb := func(c Client, m Message) {
  223. calledback <- true
  224. }
  225. pub := packets.NewControlPacket(packets.Publish).(*packets.PublishPacket)
  226. pub.Qos = 2
  227. pub.TopicName = "a"
  228. pub.Payload = []byte("foo")
  229. msgs := make(chan *packets.PublishPacket)
  230. router, stopper := newRouter()
  231. router.addRoute("$share/az1/a", cb)
  232. router.matchAndDispatch(msgs, true, &client{oboundP: make(chan *PacketAndToken, 100)})
  233. msgs <- pub
  234. <-calledback
  235. stopper <- true
  236. select {
  237. case msgs <- pub:
  238. t.Errorf("msgs should not have a listener")
  239. default:
  240. }
  241. }