1
2
3
4
5
6
7
8
9
10
11
12
13
14 package api
15
16 import (
17 "bytes"
18 "context"
19 "fmt"
20 "net/http"
21 "net/http/httptest"
22 "net/url"
23 "testing"
24 )
25
26 func TestConfig(t *testing.T) {
27 c := Config{}
28 if c.roundTripper() != DefaultRoundTripper {
29 t.Fatalf("expected default roundtripper for nil RoundTripper field")
30 }
31 }
32
33 func TestClientURL(t *testing.T) {
34 tests := []struct {
35 address string
36 endpoint string
37 args map[string]string
38 expected string
39 }{
40 {
41 address: "http://localhost:9090",
42 endpoint: "/test",
43 expected: "http://localhost:9090/test",
44 },
45 {
46 address: "http://localhost",
47 endpoint: "/test",
48 expected: "http://localhost/test",
49 },
50 {
51 address: "http://localhost:9090",
52 endpoint: "test",
53 expected: "http://localhost:9090/test",
54 },
55 {
56 address: "http://localhost:9090/prefix",
57 endpoint: "/test",
58 expected: "http://localhost:9090/prefix/test",
59 },
60 {
61 address: "https://localhost:9090/",
62 endpoint: "/test/",
63 expected: "https://localhost:9090/test",
64 },
65 {
66 address: "http://localhost:9090",
67 endpoint: "/test/:param",
68 args: map[string]string{
69 "param": "content",
70 },
71 expected: "http://localhost:9090/test/content",
72 },
73 {
74 address: "http://localhost:9090",
75 endpoint: "/test/:param/more/:param",
76 args: map[string]string{
77 "param": "content",
78 },
79 expected: "http://localhost:9090/test/content/more/content",
80 },
81 {
82 address: "http://localhost:9090",
83 endpoint: "/test/:param/more/:foo",
84 args: map[string]string{
85 "param": "content",
86 "foo": "bar",
87 },
88 expected: "http://localhost:9090/test/content/more/bar",
89 },
90 {
91 address: "http://localhost:9090",
92 endpoint: "/test/:param",
93 args: map[string]string{
94 "nonexistent": "content",
95 },
96 expected: "http://localhost:9090/test/:param",
97 },
98 }
99
100 for _, test := range tests {
101 ep, err := url.Parse(test.address)
102 if err != nil {
103 t.Fatal(err)
104 }
105
106 hclient := &httpClient{
107 endpoint: ep,
108 client: http.Client{Transport: DefaultRoundTripper},
109 }
110
111 u := hclient.URL(test.endpoint, test.args)
112 if u.String() != test.expected {
113 t.Errorf("unexpected result: got %s, want %s", u, test.expected)
114 continue
115 }
116 }
117 }
118
119
120 type serveSpaces struct {
121 sizeKB int
122 }
123
124 func (t serveSpaces) ServeHTTP(w http.ResponseWriter, req *http.Request) {
125 kb := bytes.Repeat([]byte{' '}, 1024)
126 for i := 0; i < t.sizeKB; i++ {
127 w.Write(kb)
128 }
129 }
130
131 func BenchmarkClient(b *testing.B) {
132 b.ReportAllocs()
133 ctx := context.Background()
134
135 for _, sizeKB := range []int{4, 50, 1000, 2000} {
136 b.Run(fmt.Sprintf("%dKB", sizeKB), func(b *testing.B) {
137 testServer := httptest.NewServer(serveSpaces{sizeKB})
138 defer testServer.Close()
139
140 client, err := NewClient(Config{
141 Address: testServer.URL,
142 })
143 if err != nil {
144 b.Fatalf("Failed to initialize client: %v", err)
145 }
146 url, err := url.Parse(testServer.URL + "/prometheus/api/v1/query?query=up")
147 if err != nil {
148 b.Fatalf("Failed to parse url: %v", err)
149 }
150 req := &http.Request{
151 URL: url,
152 }
153 b.ResetTimer()
154 for i := 0; i < b.N; i++ {
155 _, _, err := client.Do(ctx, req)
156 if err != nil {
157 b.Fatalf("Query failed: %v", err)
158 }
159 }
160 b.StopTimer()
161 })
162 }
163 }
164
View as plain text