client_test.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. // Copyright 2020-2021 InfluxData, Inc. All rights reserved.
  2. // Use of this source code is governed by MIT
  3. // license that can be found in the LICENSE file.
  4. package influxdb2
  5. import (
  6. "context"
  7. "fmt"
  8. ilog "github.com/influxdata/influxdb-client-go/v2/log"
  9. "log"
  10. "net/http"
  11. "net/http/httptest"
  12. "runtime"
  13. "strings"
  14. "testing"
  15. "time"
  16. ihttp "github.com/influxdata/influxdb-client-go/v2/api/http"
  17. "github.com/influxdata/influxdb-client-go/v2/domain"
  18. http2 "github.com/influxdata/influxdb-client-go/v2/internal/http"
  19. iwrite "github.com/influxdata/influxdb-client-go/v2/internal/write"
  20. "github.com/stretchr/testify/assert"
  21. "github.com/stretchr/testify/require"
  22. )
  23. func TestUrls(t *testing.T) {
  24. urls := []struct {
  25. serverURL string
  26. serverAPIURL string
  27. writeURLPrefix string
  28. }{
  29. {"http://host:8086", "http://host:8086/api/v2/", "http://host:8086/api/v2/write"},
  30. {"http://host:8086/", "http://host:8086/api/v2/", "http://host:8086/api/v2/write"},
  31. {"http://host:8086/path", "http://host:8086/path/api/v2/", "http://host:8086/path/api/v2/write"},
  32. {"http://host:8086/path/", "http://host:8086/path/api/v2/", "http://host:8086/path/api/v2/write"},
  33. {"http://host:8086/path1/path2/path3", "http://host:8086/path1/path2/path3/api/v2/", "http://host:8086/path1/path2/path3/api/v2/write"},
  34. {"http://host:8086/path1/path2/path3/", "http://host:8086/path1/path2/path3/api/v2/", "http://host:8086/path1/path2/path3/api/v2/write"},
  35. }
  36. for _, url := range urls {
  37. t.Run(url.serverURL, func(t *testing.T) {
  38. c := NewClient(url.serverURL, "x")
  39. ci := c.(*clientImpl)
  40. assert.Equal(t, url.serverURL, ci.serverURL)
  41. assert.Equal(t, url.serverAPIURL, ci.httpService.ServerAPIURL())
  42. ws := iwrite.NewService("org", "bucket", ci.httpService, c.Options().WriteOptions())
  43. wu := ws.WriteURL()
  44. assert.Equal(t, url.writeURLPrefix+"?bucket=bucket&org=org&precision=ns", wu)
  45. })
  46. }
  47. }
  48. func TestWriteAPIManagement(t *testing.T) {
  49. data := []struct {
  50. org string
  51. bucket string
  52. expectedCout int
  53. }{
  54. {"o1", "b1", 1},
  55. {"o1", "b2", 2},
  56. {"o1", "b1", 2},
  57. {"o2", "b1", 3},
  58. {"o2", "b2", 4},
  59. {"o1", "b2", 4},
  60. {"o1", "b3", 5},
  61. {"o2", "b2", 5},
  62. }
  63. c := NewClient("http://localhost", "x").(*clientImpl)
  64. for i, d := range data {
  65. t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
  66. w := c.WriteAPI(d.org, d.bucket)
  67. assert.NotNil(t, w)
  68. assert.Len(t, c.writeAPIs, d.expectedCout)
  69. wb := c.WriteAPIBlocking(d.org, d.bucket)
  70. assert.NotNil(t, wb)
  71. assert.Len(t, c.syncWriteAPIs, d.expectedCout)
  72. })
  73. }
  74. c.Close()
  75. assert.Len(t, c.writeAPIs, 0)
  76. assert.Len(t, c.syncWriteAPIs, 0)
  77. }
  78. func TestUserAgentBase(t *testing.T) {
  79. ua := fmt.Sprintf("influxdb-client-go/%s (%s; %s)", Version, runtime.GOOS, runtime.GOARCH)
  80. assert.Equal(t, ua, http2.UserAgentBase)
  81. }
  82. type doer struct {
  83. userAgent string
  84. doer ihttp.Doer
  85. }
  86. func (d *doer) Do(req *http.Request) (*http.Response, error) {
  87. req.Header.Set("User-Agent", d.userAgent)
  88. return d.doer.Do(req)
  89. }
  90. func TestUserAgent(t *testing.T) {
  91. ua := http2.UserAgentBase
  92. server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  93. <-time.After(100 * time.Millisecond)
  94. if r.Header.Get("User-Agent") == ua {
  95. w.WriteHeader(http.StatusNoContent)
  96. } else {
  97. w.WriteHeader(http.StatusNotFound)
  98. }
  99. }))
  100. defer server.Close()
  101. var sb strings.Builder
  102. log.SetOutput(&sb)
  103. log.SetFlags(0)
  104. c := NewClientWithOptions(server.URL, "x", DefaultOptions().SetLogLevel(ilog.WarningLevel))
  105. assert.True(t, strings.Contains(sb.String(), "Application name is not set"))
  106. up, err := c.Ping(context.Background())
  107. require.NoError(t, err)
  108. assert.True(t, up)
  109. err = c.WriteAPIBlocking("o", "b").WriteRecord(context.Background(), "a,a=a a=1i")
  110. assert.NoError(t, err)
  111. c.Close()
  112. sb.Reset()
  113. // Test setting application name
  114. c = NewClientWithOptions(server.URL, "x", DefaultOptions().SetApplicationName("Monitor/1.1"))
  115. ua = fmt.Sprintf("influxdb-client-go/%s (%s; %s) Monitor/1.1", Version, runtime.GOOS, runtime.GOARCH)
  116. assert.False(t, strings.Contains(sb.String(), "Application name is not set"))
  117. up, err = c.Ping(context.Background())
  118. require.NoError(t, err)
  119. assert.True(t, up)
  120. err = c.WriteAPIBlocking("o", "b").WriteRecord(context.Background(), "a,a=a a=1i")
  121. assert.NoError(t, err)
  122. c.Close()
  123. ua = "Monitor/1.1"
  124. opts := DefaultOptions()
  125. opts.HTTPOptions().SetHTTPDoer(&doer{
  126. userAgent: ua,
  127. doer: http.DefaultClient,
  128. })
  129. //Create client with custom user agent setter
  130. c = NewClientWithOptions(server.URL, "x", opts)
  131. up, err = c.Ping(context.Background())
  132. require.NoError(t, err)
  133. assert.True(t, up)
  134. err = c.WriteAPIBlocking("o", "b").WriteRecord(context.Background(), "a,a=a a=1i")
  135. assert.NoError(t, err)
  136. c.Close()
  137. }
  138. func TestServerError429(t *testing.T) {
  139. server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  140. <-time.After(100 * time.Millisecond)
  141. w.Header().Set("Retry-After", "1")
  142. w.Header().Set("Content-Type", "application/json")
  143. w.WriteHeader(http.StatusTooManyRequests)
  144. _, _ = w.Write([]byte(`{"code":"too many requests", "message":"exceeded rate limit"}`))
  145. }))
  146. defer server.Close()
  147. c := NewClient(server.URL, "x")
  148. err := c.WriteAPIBlocking("o", "b").WriteRecord(context.Background(), "a,a=a a=1i")
  149. require.Error(t, err)
  150. assert.Equal(t, "too many requests: exceeded rate limit", err.Error())
  151. }
  152. func TestServerOnPath(t *testing.T) {
  153. server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  154. if r.URL.Path == "/proxy/0:0/influx/api/v2/write" {
  155. w.WriteHeader(http.StatusNoContent)
  156. } else {
  157. w.WriteHeader(http.StatusInternalServerError)
  158. _, _ = w.Write([]byte(fmt.Sprintf(`{"code":"internal server error", "message":"%s"}`, r.URL.Path)))
  159. }
  160. }))
  161. defer server.Close()
  162. c := NewClient(server.URL+"/proxy/0:0/influx/", "x")
  163. err := c.WriteAPIBlocking("o", "b").WriteRecord(context.Background(), "a,a=a a=1i")
  164. require.NoError(t, err)
  165. }
  166. func TestServerErrorNonJSON(t *testing.T) {
  167. server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  168. <-time.After(100 * time.Millisecond)
  169. w.WriteHeader(http.StatusInternalServerError)
  170. _, _ = w.Write([]byte(`internal server error`))
  171. }))
  172. defer server.Close()
  173. c := NewClient(server.URL, "x")
  174. //Test non JSON error in custom code
  175. err := c.WriteAPIBlocking("o", "b").WriteRecord(context.Background(), "a,a=a a=1i")
  176. require.Error(t, err)
  177. assert.Equal(t, "500 Internal Server Error: internal server error", err.Error())
  178. // Test non JSON error from generated code
  179. params := &domain.GetBucketsParams{}
  180. b, err := c.APIClient().GetBuckets(context.Background(), params)
  181. assert.Nil(t, b)
  182. require.Error(t, err)
  183. assert.Equal(t, "500 Internal Server Error: internal server error", err.Error())
  184. }
  185. func TestServerErrorInflux1_8(t *testing.T) {
  186. server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  187. w.Header().Set("X-Influxdb-Error", "bruh moment")
  188. w.Header().Set("Content-Type", "application/json")
  189. w.WriteHeader(404)
  190. _, _ = w.Write([]byte(`{"error": "bruh moment"}`))
  191. }))
  192. defer server.Close()
  193. c := NewClient(server.URL, "x")
  194. err := c.WriteAPIBlocking("o", "b").WriteRecord(context.Background(), "a,a=a a=1i")
  195. require.Error(t, err)
  196. assert.Equal(t, "404 Not Found: bruh moment", err.Error())
  197. }
  198. func TestServerErrorEmptyBody(t *testing.T) {
  199. server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  200. w.WriteHeader(404)
  201. }))
  202. defer server.Close()
  203. c := NewClient(server.URL, "x")
  204. err := c.WriteAPIBlocking("o", "b").WriteRecord(context.Background(), "a,a=a a=1i")
  205. require.Error(t, err)
  206. assert.Equal(t, "Unexpected status code 404", err.Error())
  207. }
  208. func TestReadyFail(t *testing.T) {
  209. server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  210. w.WriteHeader(200)
  211. w.Write([]byte(`<html></html>`))
  212. }))
  213. defer server.Close()
  214. c := NewClient(server.URL, "x")
  215. r, err := c.Ready(context.Background())
  216. assert.Error(t, err)
  217. assert.Nil(t, r)
  218. }
  219. func TestHealthFail(t *testing.T) {
  220. server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  221. w.WriteHeader(200)
  222. w.Write([]byte(`<html></html>`))
  223. }))
  224. defer server.Close()
  225. c := NewClient(server.URL, "x")
  226. h, err := c.Health(context.Background())
  227. assert.Error(t, err)
  228. assert.Nil(t, h)
  229. }