github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/cli/cmd/bench/bench_test.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package bench
    21  
    22  import (
    23  	"fmt"
    24  	"net/http"
    25  
    26  	. "github.com/onsi/ginkgo/v2"
    27  	. "github.com/onsi/gomega"
    28  
    29  	corev1 "k8s.io/api/core/v1"
    30  	"k8s.io/apimachinery/pkg/runtime"
    31  	"k8s.io/apimachinery/pkg/runtime/schema"
    32  	"k8s.io/cli-runtime/pkg/genericiooptions"
    33  	"k8s.io/cli-runtime/pkg/resource"
    34  	"k8s.io/client-go/kubernetes/scheme"
    35  	clientfake "k8s.io/client-go/rest/fake"
    36  	cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
    37  
    38  	"github.com/1aal/kubeblocks/pkg/cli/testing"
    39  	"github.com/1aal/kubeblocks/pkg/cli/types"
    40  )
    41  
    42  var _ = Describe("bench", func() {
    43  	const (
    44  		namespace   = "default"
    45  		clusterName = "test"
    46  	)
    47  
    48  	var (
    49  		tf      *cmdtesting.TestFactory
    50  		streams genericiooptions.IOStreams
    51  		cluster = testing.FakeCluster(clusterName, namespace)
    52  		pods    = testing.FakePods(3, namespace, clusterName)
    53  	)
    54  	BeforeEach(func() {
    55  		streams, _, _, _ = genericiooptions.NewTestIOStreams()
    56  		tf = cmdtesting.NewTestFactory().WithNamespace(namespace)
    57  		tf.Client = &clientfake.RESTClient{}
    58  		tf.FakeDynamicClient = testing.FakeDynamicClient()
    59  		codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
    60  		httpResp := func(obj runtime.Object) *http.Response {
    61  			return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, obj)}
    62  		}
    63  
    64  		tf.UnstructuredClient = &clientfake.RESTClient{
    65  			GroupVersion:         schema.GroupVersion{Group: types.AppsAPIGroup, Version: types.AppsAPIVersion},
    66  			NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
    67  			Client: clientfake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
    68  				urlPrefix := "/api/v1/namespaces/" + namespace
    69  				mapping := map[string]*http.Response{
    70  					"/api/v1/nodes/" + testing.NodeName:   httpResp(testing.FakeNode()),
    71  					urlPrefix + "/services":               httpResp(&corev1.ServiceList{}),
    72  					urlPrefix + "/events":                 httpResp(&corev1.EventList{}),
    73  					urlPrefix + "/persistentvolumeclaims": httpResp(&corev1.PersistentVolumeClaimList{}),
    74  					urlPrefix + "/pods":                   httpResp(pods),
    75  				}
    76  				return mapping[req.URL.Path], nil
    77  			}),
    78  		}
    79  
    80  		tf.Client = tf.UnstructuredClient
    81  		tf.FakeDynamicClient = testing.FakeDynamicClient(cluster, testing.FakeClusterDef(), testing.FakeClusterVersion())
    82  	})
    83  
    84  	AfterEach(func() {
    85  		tf.Cleanup()
    86  	})
    87  
    88  	It("bench command", func() {
    89  		cmd := NewBenchCmd(tf, streams)
    90  		Expect(cmd != nil).Should(BeTrue())
    91  		Expect(cmd.HasSubCommands()).Should(BeTrue())
    92  	})
    93  
    94  	It("sysbench command", func() {
    95  		cmd := NewSysBenchCmd(tf, streams)
    96  		Expect(cmd != nil).Should(BeTrue())
    97  	})
    98  
    99  	It("test sysbench run", func() {
   100  		o := &SysBenchOptions{
   101  			BenchBaseOptions: BenchBaseOptions{
   102  				Driver:    "mysql",
   103  				Database:  "test",
   104  				Host:      "svc-1",
   105  				Port:      3306,
   106  				User:      "test",
   107  				Password:  "test",
   108  				factory:   tf,
   109  				namespace: namespace,
   110  				IOStreams: streams,
   111  			},
   112  			Type:     []string{"oltp_read_only"},
   113  			Tables:   1,
   114  			Size:     100,
   115  			Duration: 60,
   116  		}
   117  		Expect(o.Complete([]string{})).Should(BeNil())
   118  		Expect(o.Validate()).ShouldNot(BeNil())
   119  		Expect(o.Run()).Should(BeNil())
   120  	})
   121  
   122  	It("pgbench command", func() {
   123  		cmd := NewPgBenchCmd(tf, streams)
   124  		Expect(cmd != nil).Should(BeTrue())
   125  	})
   126  
   127  	It("test pgbench run", func() {
   128  		o := &PgBenchOptions{
   129  			BenchBaseOptions: BenchBaseOptions{
   130  				Driver:    pgBenchDriver,
   131  				Database:  "test",
   132  				Host:      "svc-1",
   133  				Port:      3306,
   134  				User:      "test",
   135  				Password:  "test",
   136  				factory:   tf,
   137  				namespace: namespace,
   138  				IOStreams: streams,
   139  			},
   140  			Scale:   100,
   141  			Clients: []int{1},
   142  		}
   143  		Expect(o.Complete([]string{})).Should(BeNil())
   144  		Expect(o.Validate()).ShouldNot(BeNil())
   145  		Expect(o.Run()).Should(BeNil())
   146  	})
   147  
   148  	It("ycsb command", func() {
   149  		cmd := NewYcsbCmd(tf, streams)
   150  		Expect(cmd != nil).Should(BeTrue())
   151  	})
   152  
   153  	It("test ycsb run", func() {
   154  		o := &YcsbOptions{
   155  			BenchBaseOptions: BenchBaseOptions{
   156  				Driver:    "mysql",
   157  				Database:  "test",
   158  				Host:      "svc-1",
   159  				Port:      3306,
   160  				User:      "test",
   161  				Password:  "test",
   162  				factory:   tf,
   163  				namespace: namespace,
   164  				IOStreams: streams,
   165  			},
   166  			RecordCount:    1000,
   167  			OperationCount: 1000,
   168  			Threads:        []int{1},
   169  		}
   170  		Expect(o.Complete([]string{})).Should(BeNil())
   171  		Expect(o.Validate()).ShouldNot(BeNil())
   172  		Expect(o.Run()).Should(BeNil())
   173  	})
   174  
   175  	It("parse driver and endpoint", func() {
   176  		driver, host, port, err := getDriverAndHostAndPort(cluster, testing.FakeServices())
   177  		Expect(err).Should(BeNil())
   178  		Expect(driver).Should(Equal(testing.ComponentName))
   179  		Expect(host).Should(Equal(fmt.Sprintf("svc-1.%s.svc.cluster.local", testing.Namespace)))
   180  		Expect(port).Should(Equal(3306))
   181  	})
   182  
   183  	It("parse tolerations", func() {
   184  		o := &BenchBaseOptions{
   185  			TolerationsRaw: []string{"dev=true:NoSchedule,large:NoSchedule"},
   186  		}
   187  		err := o.BaseComplete()
   188  		Expect(err).Should(BeNil())
   189  		Expect(o.Tolerations).Should(Equal([]corev1.Toleration{
   190  			{Key: "dev", Operator: corev1.TolerationOpEqual, Value: "true", Effect: corev1.TaintEffectNoSchedule},
   191  			{Key: "large", Operator: corev1.TolerationOpExists, Effect: corev1.TaintEffectNoSchedule},
   192  		}))
   193  	})
   194  })