github.com/netdata/go.d.plugin@v0.58.1/modules/logstash/logstash_test.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package logstash
     4  
     5  import (
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"os"
     9  	"testing"
    10  
    11  	"github.com/netdata/go.d.plugin/pkg/web"
    12  
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  var (
    18  	nodeStataData, _ = os.ReadFile("testdata/stats.json")
    19  )
    20  
    21  func Test_testDataIsValid(t *testing.T) {
    22  	for name, data := range map[string][]byte{
    23  		"nodeStataData": nodeStataData,
    24  	} {
    25  		require.NotNilf(t, data, name)
    26  
    27  	}
    28  }
    29  
    30  func TestLogstash_Init(t *testing.T) {
    31  	tests := map[string]struct {
    32  		wantFail bool
    33  		config   Config
    34  	}{
    35  		"success with default": {
    36  			wantFail: false,
    37  			config:   New().Config,
    38  		},
    39  		"fail when URL not set": {
    40  			wantFail: true,
    41  			config: Config{
    42  				HTTP: web.HTTP{
    43  					Request: web.Request{URL: ""},
    44  				},
    45  			},
    46  		},
    47  	}
    48  
    49  	for name, test := range tests {
    50  		t.Run(name, func(t *testing.T) {
    51  			ls := New()
    52  			ls.Config = test.config
    53  
    54  			if test.wantFail {
    55  				assert.False(t, ls.Init())
    56  			} else {
    57  				assert.True(t, ls.Init())
    58  			}
    59  		})
    60  	}
    61  }
    62  
    63  func TestLogstash_Charts(t *testing.T) {
    64  	assert.NotNil(t, New().Charts())
    65  }
    66  
    67  func TestLogstash_Cleanup(t *testing.T) {
    68  	assert.NotPanics(t, New().Cleanup)
    69  }
    70  
    71  func TestLogstash_Check(t *testing.T) {
    72  	tests := map[string]struct {
    73  		wantFail bool
    74  		prepare  func(t *testing.T) (ls *Logstash, cleanup func())
    75  	}{
    76  		"success on valid response": {
    77  			wantFail: false,
    78  			prepare:  caseValidResponse,
    79  		},
    80  		"fail on invalid data response": {
    81  			wantFail: true,
    82  			prepare:  caseInvalidDataResponse,
    83  		},
    84  		"fail on connection refused": {
    85  			wantFail: true,
    86  			prepare:  caseConnectionRefused,
    87  		},
    88  		"fail on 404 response": {
    89  			wantFail: true,
    90  			prepare:  case404,
    91  		},
    92  	}
    93  
    94  	for name, test := range tests {
    95  		t.Run(name, func(t *testing.T) {
    96  			ls, cleanup := test.prepare(t)
    97  			defer cleanup()
    98  
    99  			if test.wantFail {
   100  				assert.False(t, ls.Check())
   101  			} else {
   102  				assert.True(t, ls.Check())
   103  			}
   104  		})
   105  	}
   106  }
   107  
   108  func TestLogstash_Collect(t *testing.T) {
   109  	tests := map[string]struct {
   110  		prepare         func(t *testing.T) (ls *Logstash, cleanup func())
   111  		wantNumOfCharts int
   112  		wantMetrics     map[string]int64
   113  	}{
   114  		"success on valid response": {
   115  			prepare:         caseValidResponse,
   116  			wantNumOfCharts: len(charts) + len(pipelineChartsTmpl),
   117  			wantMetrics: map[string]int64{
   118  				"event_duration_in_millis":                                 0,
   119  				"event_filtered":                                           0,
   120  				"event_in":                                                 0,
   121  				"event_out":                                                0,
   122  				"event_queue_push_duration_in_millis":                      0,
   123  				"jvm_gc_collectors_eden_collection_count":                  5796,
   124  				"jvm_gc_collectors_eden_collection_time_in_millis":         45008,
   125  				"jvm_gc_collectors_old_collection_count":                   7,
   126  				"jvm_gc_collectors_old_collection_time_in_millis":          3263,
   127  				"jvm_mem_heap_committed_in_bytes":                          528154624,
   128  				"jvm_mem_heap_used_in_bytes":                               189973480,
   129  				"jvm_mem_heap_used_percent":                                35,
   130  				"jvm_mem_pools_eden_committed_in_bytes":                    69795840,
   131  				"jvm_mem_pools_eden_used_in_bytes":                         2600120,
   132  				"jvm_mem_pools_old_committed_in_bytes":                     449642496,
   133  				"jvm_mem_pools_old_used_in_bytes":                          185944824,
   134  				"jvm_mem_pools_survivor_committed_in_bytes":                8716288,
   135  				"jvm_mem_pools_survivor_used_in_bytes":                     1428536,
   136  				"jvm_threads_count":                                        28,
   137  				"jvm_uptime_in_millis":                                     699809475,
   138  				"pipelines_pipeline-1_event_duration_in_millis":            5027018,
   139  				"pipelines_pipeline-1_event_filtered":                      567639,
   140  				"pipelines_pipeline-1_event_in":                            567639,
   141  				"pipelines_pipeline-1_event_out":                           567639,
   142  				"pipelines_pipeline-1_event_queue_push_duration_in_millis": 84241,
   143  				"process_open_file_descriptors":                            101,
   144  			},
   145  		},
   146  		"fail on invalid data response": {
   147  			prepare:         caseInvalidDataResponse,
   148  			wantNumOfCharts: 0,
   149  			wantMetrics:     nil,
   150  		},
   151  		"fail on connection refused": {
   152  			prepare:         caseConnectionRefused,
   153  			wantNumOfCharts: 0,
   154  			wantMetrics:     nil,
   155  		},
   156  		"fail on 404 response": {
   157  			prepare:         case404,
   158  			wantNumOfCharts: 0,
   159  			wantMetrics:     nil,
   160  		},
   161  	}
   162  
   163  	for name, test := range tests {
   164  		t.Run(name, func(t *testing.T) {
   165  			ls, cleanup := test.prepare(t)
   166  			defer cleanup()
   167  
   168  			mx := ls.Collect()
   169  
   170  			require.Equal(t, test.wantMetrics, mx)
   171  			if len(test.wantMetrics) > 0 {
   172  				assert.Equal(t, test.wantNumOfCharts, len(*ls.Charts()))
   173  				ensureCollectedHasAllChartsDimsVarsIDs(t, ls, mx)
   174  			}
   175  		})
   176  	}
   177  }
   178  
   179  func ensureCollectedHasAllChartsDimsVarsIDs(t *testing.T, ls *Logstash, mx map[string]int64) {
   180  	for _, chart := range *ls.Charts() {
   181  		for _, dim := range chart.Dims {
   182  			_, ok := mx[dim.ID]
   183  			assert.Truef(t, ok, "collected metrics has no data for dim '%s' chart '%s'", dim.ID, chart.ID)
   184  		}
   185  		for _, v := range chart.Vars {
   186  			_, ok := mx[v.ID]
   187  			assert.Truef(t, ok, "collected metrics has no data for var '%s' chart '%s'", v.ID, chart.ID)
   188  		}
   189  	}
   190  }
   191  
   192  func caseValidResponse(t *testing.T) (*Logstash, func()) {
   193  	t.Helper()
   194  	srv := httptest.NewServer(http.HandlerFunc(
   195  		func(w http.ResponseWriter, r *http.Request) {
   196  			switch r.URL.Path {
   197  			case urlPathNodeStatsAPI:
   198  				_, _ = w.Write(nodeStataData)
   199  			default:
   200  				w.WriteHeader(http.StatusNotFound)
   201  			}
   202  		}))
   203  	ls := New()
   204  	ls.URL = srv.URL
   205  	require.True(t, ls.Init())
   206  
   207  	return ls, srv.Close
   208  }
   209  
   210  func caseInvalidDataResponse(t *testing.T) (*Logstash, func()) {
   211  	t.Helper()
   212  	srv := httptest.NewServer(http.HandlerFunc(
   213  		func(w http.ResponseWriter, r *http.Request) {
   214  			_, _ = w.Write([]byte("hello and\n goodbye"))
   215  		}))
   216  	ls := New()
   217  	ls.URL = srv.URL
   218  	require.True(t, ls.Init())
   219  
   220  	return ls, srv.Close
   221  }
   222  
   223  func caseConnectionRefused(t *testing.T) (*Logstash, func()) {
   224  	t.Helper()
   225  	ls := New()
   226  	ls.URL = "http://127.0.0.1:65001"
   227  	require.True(t, ls.Init())
   228  
   229  	return ls, func() {}
   230  }
   231  
   232  func case404(t *testing.T) (*Logstash, func()) {
   233  	t.Helper()
   234  	srv := httptest.NewServer(http.HandlerFunc(
   235  		func(w http.ResponseWriter, r *http.Request) {
   236  			w.WriteHeader(http.StatusNotFound)
   237  		}))
   238  	ls := New()
   239  	ls.URL = srv.URL
   240  	require.True(t, ls.Init())
   241  
   242  	return ls, srv.Close
   243  }