location_resolver_test.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. package endpoints
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io/ioutil"
  6. "net/http"
  7. "strconv"
  8. "sync"
  9. "testing"
  10. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
  11. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
  12. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
  13. "github.com/stretchr/testify/assert"
  14. )
  15. func TestLocationResolver_GetName(t *testing.T) {
  16. resolver := &LocationResolver{}
  17. assert.Equal(t, "location resolver", resolver.GetName())
  18. }
  19. // cases from later commit
  20. func TestLocationResolver_TryResolve_EmptyLocationProduct(t *testing.T) {
  21. resolver := &LocationResolver{}
  22. resolveParam := &ResolveParam{}
  23. endpoint, support, err := resolver.TryResolve(resolveParam)
  24. assert.Nil(t, err)
  25. assert.Equal(t, "", endpoint)
  26. assert.Equal(t, false, support)
  27. }
  28. func TestLocationResolver_TryResolve_LocationWithError(t *testing.T) {
  29. resolver := &LocationResolver{}
  30. resolveParam := &ResolveParam{
  31. LocationProduct: "ecs",
  32. RegionId: "cn-hangzhou",
  33. Product: "ecs",
  34. CommonApi: func(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
  35. err = errors.NewClientError("SDK.MockError", "Mock error", nil)
  36. return
  37. },
  38. }
  39. endpoint, support, err := resolver.TryResolve(resolveParam)
  40. assert.Equal(t, "", endpoint)
  41. assert.Equal(t, false, support)
  42. assert.Equal(t, "[SDK.MockError] Mock error", err.Error())
  43. }
  44. func makeHTTPResponse(statusCode int, content string) (res *http.Response) {
  45. header := make(http.Header)
  46. status := strconv.Itoa(statusCode)
  47. res = &http.Response{
  48. Proto: "HTTP/1.1",
  49. ProtoMajor: 1,
  50. Header: header,
  51. StatusCode: statusCode,
  52. Status: status + " " + http.StatusText(statusCode),
  53. }
  54. res.Header = make(http.Header)
  55. res.Body = ioutil.NopCloser(bytes.NewReader([]byte(content)))
  56. return
  57. }
  58. func TestLocationResolver_TryResolve_Location_With_Endpoint2(t *testing.T) {
  59. resolver := &LocationResolver{}
  60. resolveParam := &ResolveParam{
  61. LocationProduct: "ecs3",
  62. RegionId: "cn-hangzhou",
  63. Product: "ecs3",
  64. CommonApi: func(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
  65. response = responses.NewCommonResponse()
  66. responses.Unmarshal(response, makeHTTPResponse(200, `{
  67. "Endpoints":{
  68. "Endpoint":[
  69. {
  70. "Protocols":{
  71. "Protocols":["HTTP","HTTPS"]
  72. },
  73. "Type":"openAPI",
  74. "Namespace":"26842",
  75. "Id":"cn-beijing",
  76. "SerivceCode":"ecs",
  77. "Endpoint":"ecs-cn-hangzhou.aliyuncs.com"
  78. }
  79. ]
  80. },
  81. "RequestId":"B3B36D8E-5029-42E3-B1FB-9B687F7591DA",
  82. "Success":true
  83. }`), "JSON")
  84. return
  85. },
  86. }
  87. endpoint, support, err := resolver.TryResolve(resolveParam)
  88. assert.Equal(t, "ecs-cn-hangzhou.aliyuncs.com", endpoint)
  89. assert.Equal(t, true, support)
  90. assert.Nil(t, err)
  91. // hit the cache
  92. endpoint, support, err = resolver.TryResolve(resolveParam)
  93. assert.Equal(t, "ecs-cn-hangzhou.aliyuncs.com", endpoint)
  94. assert.Equal(t, true, support)
  95. assert.Nil(t, err)
  96. }
  97. func TestLocationResolver_TryResolve_Location_With_EmptyEndpoint(t *testing.T) {
  98. resolver := &LocationResolver{}
  99. resolveParam := &ResolveParam{
  100. LocationProduct: "ecs2",
  101. RegionId: "cn-hangzhou",
  102. Product: "ecs2",
  103. CommonApi: func(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
  104. response = responses.NewCommonResponse()
  105. responses.Unmarshal(response, makeHTTPResponse(200, `{"Success":true,"RequestId":"request id","Endpoints":{"Endpoint":[{"Endpoint":""}]}}`), "JSON")
  106. return
  107. },
  108. }
  109. endpoint, support, err := resolver.TryResolve(resolveParam)
  110. assert.Equal(t, "", endpoint)
  111. assert.Equal(t, false, support)
  112. assert.Nil(t, err)
  113. }
  114. func TestLocationResolver_TryResolve_LocationWith404(t *testing.T) {
  115. resolver := &LocationResolver{}
  116. resolveParam := &ResolveParam{
  117. LocationProduct: "ecs",
  118. RegionId: "cn-hangzhou",
  119. Product: "ecs",
  120. CommonApi: func(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
  121. response = responses.NewCommonResponse()
  122. responses.Unmarshal(response, makeHTTPResponse(404, "content"), "JSON")
  123. return
  124. },
  125. }
  126. endpoint, support, err := resolver.TryResolve(resolveParam)
  127. assert.Equal(t, "", endpoint)
  128. assert.Equal(t, false, support)
  129. assert.Nil(t, err)
  130. }
  131. func TestLocationResolver_TryResolve_LocationWith200InvalidJSON(t *testing.T) {
  132. resolver := &LocationResolver{}
  133. resolveParam := &ResolveParam{
  134. LocationProduct: "ecs",
  135. RegionId: "cn-hangzhou",
  136. Product: "ecs",
  137. CommonApi: func(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
  138. response = responses.NewCommonResponse()
  139. responses.Unmarshal(response, makeHTTPResponse(200, "content"), "JSON")
  140. return
  141. },
  142. }
  143. endpoint, support, err := resolver.TryResolve(resolveParam)
  144. assert.Equal(t, "", endpoint)
  145. assert.Equal(t, false, support)
  146. assert.Equal(t, "invalid character 'c' looking for beginning of value", err.Error())
  147. }
  148. func TestLocationResolver_TryResolve_LocationWith200ValidJSON(t *testing.T) {
  149. resolver := &LocationResolver{}
  150. resolveParam := &ResolveParam{
  151. LocationProduct: "ecs",
  152. RegionId: "cn-hangzhou",
  153. Product: "ecs",
  154. CommonApi: func(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
  155. response = responses.NewCommonResponse()
  156. responses.Unmarshal(response, makeHTTPResponse(200, `{"Code":"Success","RequestId":"request id"}`), "JSON")
  157. return
  158. },
  159. }
  160. endpoint, support, err := resolver.TryResolve(resolveParam)
  161. assert.Equal(t, "", endpoint)
  162. assert.Equal(t, false, support)
  163. assert.Nil(t, err)
  164. // assert.Equal(t, "json: cannot unmarshal array into Go struct field GetEndpointResponse.Endpoints of type endpoints.EndpointsObj", err.Error())
  165. }
  166. func TestLocationResolver_TryResolve_LocationWith200(t *testing.T) {
  167. resolver := &LocationResolver{}
  168. resolveParam := &ResolveParam{
  169. LocationProduct: "ecs",
  170. RegionId: "cn-hangzhou",
  171. Product: "ecs",
  172. CommonApi: func(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
  173. response = responses.NewCommonResponse()
  174. responses.Unmarshal(response, makeHTTPResponse(200, `{"Success":true,"RequestId":"request id","Endpoints":{"Endpoint":[]}}`), "JSON")
  175. return
  176. },
  177. }
  178. endpoint, support, err := resolver.TryResolve(resolveParam)
  179. assert.Equal(t, "", endpoint)
  180. assert.Equal(t, false, support)
  181. assert.Nil(t, err)
  182. }
  183. func resovleSucc(i int) (ep string, isSupport bool, err error) {
  184. resolver := &LocationResolver{}
  185. resolveParam := &ResolveParam{
  186. LocationProduct: "ecs",
  187. RegionId: fmt.Sprintf("cn-hangzhou%d", i),
  188. Product: "ecs",
  189. CommonApi: func(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
  190. response = responses.NewCommonResponse()
  191. responses.Unmarshal(response, makeHTTPResponse(200, `{"Success":true,"RequestId":"request id","Endpoints":{"Endpoint":[{"Endpoint":"domain.com"}]}}`), "JSON")
  192. return
  193. },
  194. }
  195. endpoint, support, err := resolver.TryResolve(resolveParam)
  196. return endpoint, support, err
  197. }
  198. // concurrent cases
  199. func TestResolveConcurrent(t *testing.T) {
  200. current := len(endpointCache.cache)
  201. cnt := 50
  202. var wg sync.WaitGroup
  203. for i := 0; i < cnt; i++ {
  204. wg.Add(1)
  205. go func(k int) {
  206. defer wg.Done()
  207. cachedKey := fmt.Sprintf("ecs#cn-hangzhou%d", k)
  208. for j := 0; j < 50; j++ {
  209. endpoint, support, err := resovleSucc(k)
  210. assert.Equal(t, "domain.com", endpointCache.Get(cachedKey))
  211. assert.Equal(t, "domain.com", endpoint)
  212. assert.Equal(t, true, support)
  213. assert.Nil(t, err)
  214. }
  215. }(i)
  216. }
  217. wg.Wait()
  218. assert.Equal(t, (current + cnt), len(endpointCache.cache))
  219. // hit cache and concurrent get
  220. for i := 0; i < cnt; i++ {
  221. wg.Add(1)
  222. go func(k int) {
  223. defer wg.Done()
  224. cachedKey := fmt.Sprintf("ecs#cn-hangzhou%d", k)
  225. for j := 0; j < cnt; j++ {
  226. assert.Equal(t, "domain.com", endpointCache.Get(cachedKey))
  227. endpoint, support, err := resovleSucc(k)
  228. assert.Equal(t, "domain.com", endpoint)
  229. assert.Equal(t, true, support)
  230. assert.Nil(t, err)
  231. }
  232. }(i)
  233. wg.Wait()
  234. }
  235. assert.Equal(t, (current + cnt), len(endpointCache.cache))
  236. }