github.com/netdata/go.d.plugin@v0.58.1/modules/couchbase/couchbase_test.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package couchbase
     4  
     5  import (
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"os"
     9  	"testing"
    10  
    11  	"github.com/netdata/go.d.plugin/agent/module"
    12  	"github.com/netdata/go.d.plugin/pkg/web"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  var (
    19  	v660BucketsBasicStats, _ = os.ReadFile("testdata/6.6.0/buckets_basic_stats.json")
    20  )
    21  
    22  func TestNew(t *testing.T) {
    23  	assert.Implements(t, (*module.Module)(nil), New())
    24  }
    25  
    26  func Test_testDataIsCorrectlyReadAndValid(t *testing.T) {
    27  	for name, data := range map[string][]byte{
    28  		"v660BucketsBasicStats": v660BucketsBasicStats,
    29  	} {
    30  		require.NotNilf(t, data, name)
    31  	}
    32  }
    33  
    34  func TestCouchbase_Init(t *testing.T) {
    35  	tests := map[string]struct {
    36  		config   Config
    37  		wantFail bool
    38  	}{
    39  		"success on default config": {
    40  			config: New().Config,
    41  		},
    42  		"fails on unset 'URL'": {
    43  			wantFail: true,
    44  			config: Config{
    45  				HTTP: web.HTTP{
    46  					Request: web.Request{
    47  						URL: "",
    48  					},
    49  				},
    50  			},
    51  		},
    52  		"fails on invalid URL": {
    53  			wantFail: true,
    54  			config: Config{
    55  				HTTP: web.HTTP{
    56  					Request: web.Request{
    57  						URL: "127.0.0.1:9090",
    58  					},
    59  				},
    60  			},
    61  		},
    62  	}
    63  
    64  	for name, test := range tests {
    65  		t.Run(name, func(t *testing.T) {
    66  			cb := New()
    67  			cb.Config = test.config
    68  
    69  			if test.wantFail {
    70  				assert.False(t, cb.Init())
    71  			} else {
    72  				assert.True(t, cb.Init())
    73  			}
    74  		})
    75  	}
    76  }
    77  
    78  func TestCouchbase_Check(t *testing.T) {
    79  	tests := map[string]struct {
    80  		prepare  func(*testing.T) (cb *Couchbase, cleanup func())
    81  		wantFail bool
    82  	}{
    83  		"success on valid response v6.6.0": {
    84  			prepare: prepareCouchbaseV660,
    85  		},
    86  		"fails on response with invalid data": {
    87  			wantFail: true,
    88  			prepare:  prepareCouchbaseInvalidData,
    89  		},
    90  		"fails on 404 response": {
    91  			wantFail: true,
    92  			prepare:  prepareCouchbase404,
    93  		},
    94  		"fails on connection refused": {
    95  			wantFail: true,
    96  			prepare:  prepareCouchbaseConnectionRefused,
    97  		},
    98  	}
    99  
   100  	for name, test := range tests {
   101  		t.Run(name, func(t *testing.T) {
   102  			cb, cleanup := test.prepare(t)
   103  			defer cleanup()
   104  
   105  			if test.wantFail {
   106  				assert.False(t, cb.Check())
   107  			} else {
   108  				assert.True(t, cb.Check())
   109  			}
   110  		})
   111  	}
   112  }
   113  
   114  func TestCouchbase_Collect(t *testing.T) {
   115  	tests := map[string]struct {
   116  		prepare       func(t *testing.T) (cb *Couchbase, cleanup func())
   117  		wantCollected map[string]int64
   118  	}{
   119  		"success on valid response v6.6.0": {
   120  			prepare: prepareCouchbaseV660,
   121  			wantCollected: map[string]int64{
   122  				"bucket_beer-sample_data_used":                     13990431,
   123  				"bucket_beer-sample_disk_fetches":                  1,
   124  				"bucket_beer-sample_disk_used":                     27690472,
   125  				"bucket_beer-sample_item_count":                    7303,
   126  				"bucket_beer-sample_mem_used":                      34294872,
   127  				"bucket_beer-sample_ops_per_sec":                   1100,
   128  				"bucket_beer-sample_quota_percent_used":            32706,
   129  				"bucket_beer-sample_vb_active_num_non_resident":    1,
   130  				"bucket_gamesim-sample_data_used":                  5371804,
   131  				"bucket_gamesim-sample_disk_fetches":               1,
   132  				"bucket_gamesim-sample_disk_used":                  13821793,
   133  				"bucket_gamesim-sample_item_count":                 586,
   134  				"bucket_gamesim-sample_mem_used":                   29586696,
   135  				"bucket_gamesim-sample_ops_per_sec":                1100,
   136  				"bucket_gamesim-sample_quota_percent_used":         28216,
   137  				"bucket_gamesim-sample_vb_active_num_non_resident": 1,
   138  				"bucket_travel-sample_data_used":                   53865472,
   139  				"bucket_travel-sample_disk_fetches":                1,
   140  				"bucket_travel-sample_disk_used":                   62244260,
   141  				"bucket_travel-sample_item_count":                  31591,
   142  				"bucket_travel-sample_mem_used":                    54318184,
   143  				"bucket_travel-sample_ops_per_sec":                 1100,
   144  				"bucket_travel-sample_quota_percent_used":          51801,
   145  				"bucket_travel-sample_vb_active_num_non_resident":  1,
   146  			},
   147  		},
   148  		"fails on response with invalid data": {
   149  			prepare: prepareCouchbaseInvalidData,
   150  		},
   151  		"fails on 404 response": {
   152  			prepare: prepareCouchbase404,
   153  		},
   154  		"fails on connection refused": {
   155  			prepare: prepareCouchbaseConnectionRefused,
   156  		},
   157  	}
   158  
   159  	for name, test := range tests {
   160  		t.Run(name, func(t *testing.T) {
   161  			cb, cleanup := test.prepare(t)
   162  			defer cleanup()
   163  
   164  			collected := cb.Collect()
   165  
   166  			assert.Equal(t, test.wantCollected, collected)
   167  			ensureCollectedHasAllChartsDimsVarsIDs(t, cb, collected)
   168  		})
   169  	}
   170  }
   171  
   172  func prepareCouchbaseV660(t *testing.T) (cb *Couchbase, cleanup func()) {
   173  	t.Helper()
   174  	srv := httptest.NewServer(http.HandlerFunc(
   175  		func(w http.ResponseWriter, r *http.Request) {
   176  			_, _ = w.Write(v660BucketsBasicStats)
   177  		}))
   178  
   179  	cb = New()
   180  	cb.URL = srv.URL
   181  	require.True(t, cb.Init())
   182  
   183  	return cb, srv.Close
   184  }
   185  
   186  func prepareCouchbaseInvalidData(t *testing.T) (*Couchbase, func()) {
   187  	t.Helper()
   188  	srv := httptest.NewServer(http.HandlerFunc(
   189  		func(w http.ResponseWriter, r *http.Request) {
   190  			_, _ = w.Write([]byte("hello and\n goodbye"))
   191  		}))
   192  	cb := New()
   193  	cb.URL = srv.URL
   194  	require.True(t, cb.Init())
   195  
   196  	return cb, srv.Close
   197  }
   198  
   199  func prepareCouchbase404(t *testing.T) (*Couchbase, func()) {
   200  	t.Helper()
   201  	srv := httptest.NewServer(http.HandlerFunc(
   202  		func(w http.ResponseWriter, r *http.Request) {
   203  			w.WriteHeader(http.StatusNotFound)
   204  		}))
   205  	cb := New()
   206  	cb.URL = srv.URL
   207  	require.True(t, cb.Init())
   208  
   209  	return cb, srv.Close
   210  }
   211  
   212  func prepareCouchbaseConnectionRefused(t *testing.T) (*Couchbase, func()) {
   213  	t.Helper()
   214  	cb := New()
   215  	cb.URL = "http://127.0.0.1:38001"
   216  	require.True(t, cb.Init())
   217  
   218  	return cb, func() {}
   219  }
   220  
   221  func ensureCollectedHasAllChartsDimsVarsIDs(t *testing.T, cb *Couchbase, collected map[string]int64) {
   222  	for _, chart := range *cb.Charts() {
   223  		if chart.Obsolete {
   224  			continue
   225  		}
   226  		for _, dim := range chart.Dims {
   227  			_, ok := collected[dim.ID]
   228  			assert.Truef(t, ok, "chart '%s' dim '%s': no dim in collected", dim.ID, chart.ID)
   229  		}
   230  		for _, v := range chart.Vars {
   231  			_, ok := collected[v.ID]
   232  			assert.Truef(t, ok, "chart '%s' dim '%s': no dim in collected", v.ID, chart.ID)
   233  		}
   234  	}
   235  }