health_test.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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. `
  62. func TestHealthCheck(t *testing.T) {
  63. assert := assert.New(t)
  64. // ****** start background services ******
  65. echoSvc1 := mock.NewEchoServer(15001, 1, "echo1")
  66. err := echoSvc1.Start()
  67. if assert.NoError(err) {
  68. defer echoSvc1.Stop()
  69. }
  70. echoSvc2 := mock.NewEchoServer(15002, 1, "echo2")
  71. err = echoSvc2.Start()
  72. if assert.NoError(err) {
  73. defer echoSvc2.Stop()
  74. }
  75. var healthMu sync.RWMutex
  76. svc1Health := true
  77. svc2Health := true
  78. httpSvc1 := mock.NewHttpServer(15003, func(w http.ResponseWriter, r *http.Request) {
  79. if strings.Contains(r.URL.Path, "health") {
  80. healthMu.RLock()
  81. defer healthMu.RUnlock()
  82. if svc1Health {
  83. w.WriteHeader(200)
  84. } else {
  85. w.WriteHeader(500)
  86. }
  87. } else {
  88. w.Write([]byte("http1"))
  89. }
  90. })
  91. err = httpSvc1.Start()
  92. if assert.NoError(err) {
  93. defer httpSvc1.Stop()
  94. }
  95. httpSvc2 := mock.NewHttpServer(15004, func(w http.ResponseWriter, r *http.Request) {
  96. if strings.Contains(r.URL.Path, "health") {
  97. healthMu.RLock()
  98. defer healthMu.RUnlock()
  99. if svc2Health {
  100. w.WriteHeader(200)
  101. } else {
  102. w.WriteHeader(500)
  103. }
  104. } else {
  105. w.Write([]byte("http2"))
  106. }
  107. })
  108. err = httpSvc2.Start()
  109. if assert.NoError(err) {
  110. defer httpSvc2.Stop()
  111. }
  112. time.Sleep(200 * time.Millisecond)
  113. // ****** start frps and frpc ******
  114. frpsCfgPath, err := config.GenerateConfigFile(consts.FRPS_NORMAL_CONFIG, FRPS_CONF)
  115. if assert.NoError(err) {
  116. defer os.Remove(frpsCfgPath)
  117. }
  118. frpcCfgPath, err := config.GenerateConfigFile(consts.FRPC_NORMAL_CONFIG, FRPC_CONF)
  119. if assert.NoError(err) {
  120. defer os.Remove(frpcCfgPath)
  121. }
  122. frpsProcess := util.NewProcess(consts.FRPS_SUB_BIN_PATH, []string{"-c", frpsCfgPath})
  123. err = frpsProcess.Start()
  124. if assert.NoError(err) {
  125. defer frpsProcess.Stop()
  126. }
  127. time.Sleep(100 * time.Millisecond)
  128. frpcProcess := util.NewProcess(consts.FRPC_SUB_BIN_PATH, []string{"-c", frpcCfgPath})
  129. err = frpcProcess.Start()
  130. if assert.NoError(err) {
  131. defer frpcProcess.Stop()
  132. }
  133. time.Sleep(1000 * time.Millisecond)
  134. // ****** healcheck type tcp ******
  135. // echo1 and echo2 is ok
  136. result := make([]string, 0)
  137. res, err := util.SendTcpMsg("127.0.0.1:15000", "echo")
  138. assert.NoError(err)
  139. result = append(result, res)
  140. res, err = util.SendTcpMsg("127.0.0.1:15000", "echo")
  141. assert.NoError(err)
  142. result = append(result, res)
  143. assert.Contains(result, "echo1")
  144. assert.Contains(result, "echo2")
  145. // close echo2 server, echo1 is work
  146. echoSvc2.Stop()
  147. time.Sleep(1200 * time.Millisecond)
  148. result = make([]string, 0)
  149. res, err = util.SendTcpMsg("127.0.0.1:15000", "echo")
  150. assert.NoError(err)
  151. result = append(result, res)
  152. res, err = util.SendTcpMsg("127.0.0.1:15000", "echo")
  153. assert.NoError(err)
  154. result = append(result, res)
  155. assert.NotContains(result, "echo2")
  156. // resume echo2 server, all services are ok
  157. echoSvc2 = mock.NewEchoServer(15002, 1, "echo2")
  158. err = echoSvc2.Start()
  159. if assert.NoError(err) {
  160. defer echoSvc2.Stop()
  161. }
  162. time.Sleep(1200 * time.Millisecond)
  163. result = make([]string, 0)
  164. res, err = util.SendTcpMsg("127.0.0.1:15000", "echo")
  165. assert.NoError(err)
  166. result = append(result, res)
  167. res, err = util.SendTcpMsg("127.0.0.1:15000", "echo")
  168. assert.NoError(err)
  169. result = append(result, res)
  170. assert.Contains(result, "echo1")
  171. assert.Contains(result, "echo2")
  172. // ****** healcheck type http ******
  173. // http1 and http2 is ok
  174. code, body, _, err := util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test1.com", nil, "")
  175. assert.NoError(err)
  176. assert.Equal(200, code)
  177. assert.Equal("http1", body)
  178. code, body, _, err = util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test2.com", nil, "")
  179. assert.NoError(err)
  180. assert.Equal(200, code)
  181. assert.Equal("http2", body)
  182. // http2 health check error
  183. healthMu.Lock()
  184. svc2Health = false
  185. healthMu.Unlock()
  186. time.Sleep(1200 * time.Millisecond)
  187. code, body, _, err = util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test1.com", nil, "")
  188. assert.NoError(err)
  189. assert.Equal(200, code)
  190. assert.Equal("http1", body)
  191. code, _, _, err = util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test2.com", nil, "")
  192. assert.NoError(err)
  193. assert.Equal(404, code)
  194. // resume http2 service, http1 and http2 are ok
  195. healthMu.Lock()
  196. svc2Health = true
  197. healthMu.Unlock()
  198. time.Sleep(1200 * time.Millisecond)
  199. code, body, _, err = util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test1.com", nil, "")
  200. assert.NoError(err)
  201. assert.Equal(200, code)
  202. assert.Equal("http1", body)
  203. code, body, _, err = util.SendHttpMsg("GET", "http://127.0.0.1:14000/xxx", "test2.com", nil, "")
  204. assert.NoError(err)
  205. assert.Equal(200, code)
  206. assert.Equal("http2", body)
  207. }