health_test.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. package health
  2. import (
  3. "net/http"
  4. "os"
  5. "strings"
  6. "sync"
  7. "testing"
  8. "time"
  9. "github.com/fatedier/frp/tests/config"
  10. "github.com/fatedier/frp/tests/consts"
  11. "github.com/fatedier/frp/tests/mock"
  12. "github.com/fatedier/frp/tests/util"
  13. "github.com/stretchr/testify/assert"
  14. )
  15. const FRPS_CONF = `
  16. [common]
  17. bind_addr = 0.0.0.0
  18. bind_port = 14000
  19. vhost_http_port = 14000
  20. log_file = console
  21. log_level = debug
  22. token = 123456
  23. `
  24. const FRPC_CONF = `
  25. [common]
  26. server_addr = 127.0.0.1
  27. server_port = 14000
  28. log_file = console
  29. log_level = debug
  30. token = 123456
  31. [tcp1]
  32. type = tcp
  33. local_port = 15001
  34. remote_port = 15000
  35. group = test
  36. group_key = 123
  37. health_check_type = tcp
  38. health_check_interval_s = 1
  39. [tcp2]
  40. type = tcp
  41. local_port = 15002
  42. remote_port = 15000
  43. group = test
  44. group_key = 123
  45. health_check_type = tcp
  46. health_check_interval_s = 1
  47. [http1]
  48. type = http
  49. local_port = 15003
  50. custom_domains = test1.com
  51. health_check_type = http
  52. health_check_interval_s = 1
  53. health_check_url = /health
  54. [http2]
  55. type = http
  56. local_port = 15004
  57. custom_domains = test2.com
  58. health_check_type = http
  59. health_check_interval_s = 1
  60. health_check_url = /health
  61. [http3]
  62. type = http
  63. local_port = 15005
  64. custom_domains = test.balancing.com
  65. group = test-balancing
  66. group_key = 123
  67. [http4]
  68. type = http
  69. local_port = 15006
  70. custom_domains = test.balancing.com
  71. group = test-balancing
  72. group_key = 123
  73. `
  74. func TestHealthCheck(t *testing.T) {
  75. assert := assert.New(t)
  76. // ****** start background services ******
  77. echoSvc1 := mock.NewEchoServer(15001, 1, "echo1")
  78. err := echoSvc1.Start()
  79. if assert.NoError(err) {
  80. defer echoSvc1.Stop()
  81. }
  82. echoSvc2 := mock.NewEchoServer(15002, 1, "echo2")
  83. err = echoSvc2.Start()
  84. if assert.NoError(err) {
  85. defer echoSvc2.Stop()
  86. }
  87. var healthMu sync.RWMutex
  88. svc1Health := true
  89. svc2Health := true
  90. httpSvc1 := mock.NewHttpServer(15003, func(w http.ResponseWriter, r *http.Request) {
  91. if strings.Contains(r.URL.Path, "health") {
  92. healthMu.RLock()
  93. defer healthMu.RUnlock()
  94. if svc1Health {
  95. w.WriteHeader(200)
  96. } else {
  97. w.WriteHeader(500)
  98. }
  99. } else {
  100. w.Write([]byte("http1"))
  101. }
  102. })
  103. err = httpSvc1.Start()
  104. if assert.NoError(err) {
  105. defer httpSvc1.Stop()
  106. }
  107. httpSvc2 := mock.NewHttpServer(15004, func(w http.ResponseWriter, r *http.Request) {
  108. if strings.Contains(r.URL.Path, "health") {
  109. healthMu.RLock()
  110. defer healthMu.RUnlock()
  111. if svc2Health {
  112. w.WriteHeader(200)
  113. } else {
  114. w.WriteHeader(500)
  115. }
  116. } else {
  117. w.Write([]byte("http2"))
  118. }
  119. })
  120. err = httpSvc2.Start()
  121. if assert.NoError(err) {
  122. defer httpSvc2.Stop()
  123. }
  124. httpSvc3 := mock.NewHttpServer(15005, func(w http.ResponseWriter, r *http.Request) {
  125. w.Write([]byte("http3"))
  126. })
  127. err = httpSvc3.Start()
  128. if assert.NoError(err) {
  129. defer httpSvc3.Stop()
  130. }
  131. httpSvc4 := mock.NewHttpServer(15006, func(w http.ResponseWriter, r *http.Request) {
  132. w.Write([]byte("http4"))
  133. })
  134. err = httpSvc4.Start()
  135. if assert.NoError(err) {
  136. defer httpSvc4.Stop()
  137. }
  138. time.Sleep(200 * time.Millisecond)
  139. // ****** start frps and frpc ******
  140. frpsCfgPath, err := config.GenerateConfigFile(consts.FRPS_NORMAL_CONFIG, FRPS_CONF)
  141. if assert.NoError(err) {
  142. defer os.Remove(frpsCfgPath)
  143. }
  144. frpcCfgPath, err := config.GenerateConfigFile(consts.FRPC_NORMAL_CONFIG, FRPC_CONF)
  145. if assert.NoError(err) {
  146. defer os.Remove(frpcCfgPath)
  147. }
  148. frpsProcess := util.NewProcess(consts.FRPS_SUB_BIN_PATH, []string{"-c", frpsCfgPath})
  149. err = frpsProcess.Start()
  150. if assert.NoError(err) {
  151. defer frpsProcess.Stop()
  152. }
  153. time.Sleep(100 * time.Millisecond)
  154. frpcProcess := util.NewProcess(consts.FRPC_SUB_BIN_PATH, []string{"-c", frpcCfgPath})
  155. err = frpcProcess.Start()
  156. if assert.NoError(err) {
  157. defer frpcProcess.Stop()
  158. }
  159. time.Sleep(1000 * time.Millisecond)
  160. // ****** healcheck type tcp ******
  161. // echo1 and echo2 is ok
  162. result := make([]string, 0)
  163. res, err := util.SendTcpMsg("127.0.0.1:15000", "echo")
  164. assert.NoError(err)
  165. result = append(result, res)
  166. res, err = util.SendTcpMsg("127.0.0.1:15000", "echo")
  167. assert.NoError(err)
  168. result = append(result, res)
  169. assert.Contains(result, "echo1")
  170. assert.Contains(result, "echo2")
  171. // close echo2 server, echo1 is work
  172. echoSvc2.Stop()
  173. time.Sleep(1200 * time.Millisecond)
  174. result = make([]string, 0)
  175. res, err = util.SendTcpMsg("127.0.0.1:15000", "echo")
  176. assert.NoError(err)
  177. result = append(result, res)
  178. res, err = util.SendTcpMsg("127.0.0.1:15000", "echo")
  179. assert.NoError(err)
  180. result = append(result, res)
  181. assert.NotContains(result, "echo2")
  182. // resume echo2 server, all services are ok
  183. echoSvc2 = mock.NewEchoServer(15002, 1, "echo2")
  184. err = echoSvc2.Start()
  185. if assert.NoError(err) {
  186. defer echoSvc2.Stop()
  187. }
  188. time.Sleep(1200 * time.Millisecond)
  189. result = make([]string, 0)
  190. res, err = util.SendTcpMsg("127.0.0.1:15000", "echo")
  191. assert.NoError(err)
  192. result = append(result, res)
  193. res, err = util.SendTcpMsg("127.0.0.1:15000", "echo")
  194. assert.NoError(err)
  195. result = append(result, res)
  196. assert.Contains(result, "echo1")
  197. assert.Contains(result, "echo2")
  198. // ****** healcheck type http ******
  199. // http1 and http2 is ok
  200. code, body, _, err := util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test1.com", nil, "")
  201. assert.NoError(err)
  202. assert.Equal(200, code)
  203. assert.Equal("http1", body)
  204. code, body, _, err = util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test2.com", nil, "")
  205. assert.NoError(err)
  206. assert.Equal(200, code)
  207. assert.Equal("http2", body)
  208. // http2 health check error
  209. healthMu.Lock()
  210. svc2Health = false
  211. healthMu.Unlock()
  212. time.Sleep(1200 * time.Millisecond)
  213. code, body, _, err = util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test1.com", nil, "")
  214. assert.NoError(err)
  215. assert.Equal(200, code)
  216. assert.Equal("http1", body)
  217. code, _, _, err = util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test2.com", nil, "")
  218. assert.NoError(err)
  219. assert.Equal(404, code)
  220. // resume http2 service, http1 and http2 are ok
  221. healthMu.Lock()
  222. svc2Health = true
  223. healthMu.Unlock()
  224. time.Sleep(1200 * time.Millisecond)
  225. code, body, _, err = util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test1.com", nil, "")
  226. assert.NoError(err)
  227. assert.Equal(200, code)
  228. assert.Equal("http1", body)
  229. code, body, _, err = util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test2.com", nil, "")
  230. assert.NoError(err)
  231. assert.Equal(200, code)
  232. assert.Equal("http2", body)
  233. // ****** load balancing type http ******
  234. result = make([]string, 0)
  235. code, body, _, err = util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test.balancing.com", nil, "")
  236. assert.NoError(err)
  237. assert.Equal(200, code)
  238. result = append(result, body)
  239. code, body, _, err = util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test.balancing.com", nil, "")
  240. assert.NoError(err)
  241. assert.Equal(200, code)
  242. result = append(result, body)
  243. assert.Contains(result, "http3")
  244. assert.Contains(result, "http4")
  245. }