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  }