github.com/opensearch-project/opensearch-go/v2@v2.3.0/opensearchapi/opensearchapi_benchmark_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // 3 // The OpenSearch Contributors require contributions made to 4 // this file be licensed under the Apache-2.0 license or a 5 // compatible open source license. 6 // 7 // Modifications Copyright OpenSearch Contributors. See 8 // GitHub history for details. 9 10 // Licensed to Elasticsearch B.V. under one or more contributor 11 // license agreements. See the NOTICE file distributed with 12 // this work for additional information regarding copyright 13 // ownership. Elasticsearch B.V. licenses this file to you under 14 // the Apache License, Version 2.0 (the "License"); you may 15 // not use this file except in compliance with the License. 16 // You may obtain a copy of the License at 17 // 18 // http://www.apache.org/licenses/LICENSE-2.0 19 // 20 // Unless required by applicable law or agreed to in writing, 21 // software distributed under the License is distributed on an 22 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 23 // KIND, either express or implied. See the License for the 24 // specific language governing permissions and limitations 25 // under the License. 26 27 package opensearchapi_test 28 29 import ( 30 "context" 31 "io/ioutil" 32 "net/http" 33 "strconv" 34 "strings" 35 "testing" 36 37 "github.com/opensearch-project/opensearch-go/v2" 38 "github.com/opensearch-project/opensearch-go/v2/opensearchapi" 39 ) 40 41 // TODO: Refactor into a shared mock/testing package 42 43 var ( 44 defaultResponse = &http.Response{ 45 StatusCode: 200, 46 Header: http.Header{}, 47 Body: ioutil.NopCloser(strings.NewReader("MOCK")), 48 } 49 defaultRoundTripFn = func(*http.Request) (*http.Response, error) { return defaultResponse, nil } 50 errorRoundTripFn = func(request *http.Request) (*http.Response, error) { 51 if request.URL.Path == "/" { 52 return &http.Response{ 53 StatusCode: 200, 54 Header: http.Header{}, 55 Body: ioutil.NopCloser(strings.NewReader("{}")), 56 }, nil 57 } 58 return &http.Response{ 59 Header: http.Header{}, 60 StatusCode: 400, 61 Body: ioutil.NopCloser(strings.NewReader(` 62 { "error" : { 63 "root_cause" : [ 64 { 65 "type" : "parsing_exception", 66 "reason" : "no [query] registered for [foo]", 67 "line" : 1, 68 "col" : 22 69 } 70 ], 71 "type" : "parsing_exception", 72 "reason" : "no [query] registered for [foo]", 73 "line" : 1, 74 "col" : 22 75 }, 76 "status" : 400 77 }`)), 78 }, nil 79 } 80 ) 81 82 type FakeTransport struct { 83 RoundTripFn func(*http.Request) (*http.Response, error) 84 } 85 86 func (t *FakeTransport) RoundTrip(req *http.Request) (*http.Response, error) { 87 return t.RoundTripFn(req) 88 } 89 90 func newFakeClient(b *testing.B) *opensearch.Client { 91 cfg := opensearch.Config{Transport: &FakeTransport{RoundTripFn: defaultRoundTripFn}} 92 client, err := opensearch.NewClient(cfg) 93 94 if err != nil { 95 b.Fatalf("Unexpected error when creating a client: %s", err) 96 } 97 98 return client 99 } 100 101 func newFakeClientWithError(b *testing.B) *opensearch.Client { 102 cfg := opensearch.Config{Transport: &FakeTransport{RoundTripFn: errorRoundTripFn}} 103 client, err := opensearch.NewClient(cfg) 104 105 if err != nil { 106 b.Fatalf("Unexpected error when creating a client: %s", err) 107 } 108 109 return client 110 } 111 112 func BenchmarkAPI(b *testing.B) { 113 var client = newFakeClient(b) 114 var fakeClientWithError = newFakeClientWithError(b) 115 116 b.Run("client.Info() ", func(b *testing.B) { 117 b.ResetTimer() 118 for i := 0; i < b.N; i++ { 119 if _, err := client.Info(); err != nil { 120 b.Errorf("Unexpected error when getting a response: %s", err) 121 } 122 } 123 }) 124 125 b.Run("client.Info() WithContext ", func(b *testing.B) { 126 b.ResetTimer() 127 for i := 0; i < b.N; i++ { 128 if _, err := client.Info(client.Info.WithContext(context.Background())); err != nil { 129 b.Errorf("Unexpected error when getting a response: %s", err) 130 } 131 } 132 }) 133 134 b.Run("InfoRequest{}.Do() ", func(b *testing.B) { 135 b.ResetTimer() 136 for i := 0; i < b.N; i++ { 137 req := opensearchapi.InfoRequest{} 138 if _, err := req.Do(context.Background(), client); err != nil { 139 b.Errorf("Unexpected error when getting a response: %s", err) 140 } 141 } 142 }) 143 144 b.Run("client.Cluster.Health() ", func(b *testing.B) { 145 b.ResetTimer() 146 for i := 0; i < b.N; i++ { 147 if _, err := client.Cluster.Health(); err != nil { 148 b.Errorf("Unexpected error when getting a response: %s", err) 149 } 150 } 151 }) 152 153 b.Run("client.Cluster.Health() With() ", func(b *testing.B) { 154 b.ResetTimer() 155 for i := 0; i < b.N; i++ { 156 _, err := client.Cluster.Health( 157 client.Cluster.Health.WithContext(context.Background()), 158 client.Cluster.Health.WithLevel("indices"), 159 client.Cluster.Health.WithPretty(), 160 ) 161 162 if err != nil { 163 b.Errorf("Unexpected error when getting a response: %s", err) 164 } 165 } 166 }) 167 168 b.Run("ClusterHealthRequest{}.Do() ", func(b *testing.B) { 169 b.ResetTimer() 170 for i := 0; i < b.N; i++ { 171 req := opensearchapi.ClusterHealthRequest{} 172 if _, err := req.Do(context.Background(), client); err != nil { 173 b.Errorf("Unexpected error when getting a response: %s", err) 174 } 175 } 176 }) 177 178 b.Run("ClusterHealthRequest{...}.Do() ", func(b *testing.B) { 179 b.ResetTimer() 180 for i := 0; i < b.N; i++ { 181 req := opensearchapi.ClusterHealthRequest{Level: "indices", Pretty: true} 182 if _, err := req.Do(context.Background(), client); err != nil { 183 b.Errorf("Unexpected error when getting a response: %s", err) 184 } 185 } 186 }) 187 188 b.Run("client.Index() With() ", func(b *testing.B) { 189 indx := "test" 190 body := strings.NewReader(`{"title" : "Test"}`) 191 b.ResetTimer() 192 for i := 0; i < b.N; i++ { 193 _, err := client.Index( 194 indx, 195 body, 196 client.Index.WithDocumentID("1"), 197 client.Index.WithRefresh("true"), 198 client.Index.WithContext(context.Background()), 199 client.Index.WithRefresh("true"), 200 client.Index.WithPretty(), 201 client.Index.WithTimeout(100), 202 ) 203 204 if err != nil { 205 b.Errorf("Unexpected error when getting a response: %s", err) 206 } 207 } 208 }) 209 210 b.Run("IndexRequest{...}.Do() ", func(b *testing.B) { 211 b.ResetTimer() 212 var body strings.Builder 213 for i := 0; i < b.N; i++ { 214 docID := strconv.FormatInt(int64(i), 10) 215 body.Reset() 216 body.WriteString(`{"foo" : "bar `) 217 body.WriteString(docID) 218 body.WriteString(` " }`) 219 220 req := opensearchapi.IndexRequest{ 221 Index: "test", 222 DocumentID: docID, 223 Body: strings.NewReader(body.String()), 224 Refresh: "true", 225 Pretty: true, 226 Timeout: 100, 227 } 228 229 if _, err := req.Do(context.Background(), client); err != nil { 230 b.Errorf("Unexpected error when getting a response: %s", err) 231 } 232 } 233 }) 234 235 b.Run("IndexRequest{...}.Do() reused ", func(b *testing.B) { 236 b.ResetTimer() 237 var body strings.Builder 238 239 req := opensearchapi.IndexRequest{} 240 req.Index = "test" 241 req.Refresh = "true" 242 req.Pretty = true 243 req.Timeout = 100 244 245 for i := 0; i < b.N; i++ { 246 docID := strconv.FormatInt(int64(i), 10) 247 body.Reset() 248 body.WriteString(`{"foo" : "bar `) 249 body.WriteString(docID) 250 body.WriteString(` " }`) 251 req.DocumentID = docID 252 req.Body = strings.NewReader(body.String()) 253 254 if _, err := req.Do(context.Background(), client); err != nil { 255 b.Errorf("Unexpected error when getting a response: %s", err) 256 } 257 } 258 }) 259 260 b.Run("client.Search() ", func(b *testing.B) { 261 body := strings.NewReader(`{"query" : { "match_all" : {} } }`) 262 b.ResetTimer() 263 for i := 0; i < b.N; i++ { 264 _, err := client.Search(client.Search.WithContext(context.Background()), client.Search.WithBody(body)) 265 266 if err != nil { 267 b.Errorf("Unexpected error when getting a response: %s", err) 268 } 269 } 270 }) 271 272 b.Run("client.Search() with error ", func(b *testing.B) { 273 body := strings.NewReader(`{}`) 274 275 b.ResetTimer() 276 for i := 0; i < b.N; i++ { 277 _, err := fakeClientWithError.Search(fakeClientWithError.Search.WithContext(context.Background()), fakeClientWithError.Search.WithBody(body)) 278 279 if err != nil { 280 b.Errorf("Unexpected error when getting a response: %s", err) 281 } 282 } 283 }) 284 285 b.Run("SearchRequest{...}.Do() ", func(b *testing.B) { 286 body := strings.NewReader(`{"query" : { "match_all" : {} } }`) 287 288 b.ResetTimer() 289 for i := 0; i < b.N; i++ { 290 req := opensearchapi.SearchRequest{Body: body} 291 if _, err := req.Do(context.Background(), client); err != nil { 292 b.Errorf("Unexpected error when getting a response: %s", err) 293 } 294 } 295 }) 296 297 b.Run("SearchRequest{...}.Do() with error ", func(b *testing.B) { 298 body := strings.NewReader(`{}`) 299 300 b.ResetTimer() 301 for i := 0; i < b.N; i++ { 302 req := opensearchapi.SearchRequest{Body: body} 303 if _, err := req.Do(context.Background(), fakeClientWithError); err != nil { 304 b.Errorf("Unexpected error when getting a response: %s", err) 305 } 306 } 307 }) 308 }