github.com/netdata/go.d.plugin@v0.58.1/modules/vcsa/client/client_test.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package client
     4  
     5  import (
     6  	"encoding/json"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  const (
    16  	testUser        = "user"
    17  	testPass        = "pass"
    18  	testSessToken   = "sessToken"
    19  	testHealthValue = "green"
    20  )
    21  
    22  func newTestClient(srvURL string) *Client {
    23  	return New(nil, srvURL, testUser, testPass)
    24  }
    25  
    26  func TestClient_Login(t *testing.T) {
    27  	ts := newTestHTTPServer()
    28  	defer ts.Close()
    29  	cl := newTestClient(ts.URL)
    30  
    31  	assert.NoError(t, cl.Login())
    32  	assert.Equal(t, testSessToken, cl.token.get())
    33  }
    34  
    35  func TestClient_LoginWrongCredentials(t *testing.T) {
    36  	ts := newTestHTTPServer()
    37  	defer ts.Close()
    38  	cl := newTestClient(ts.URL)
    39  	cl.username += "!"
    40  
    41  	assert.Error(t, cl.Login())
    42  }
    43  
    44  func TestClient_Logout(t *testing.T) {
    45  	ts := newTestHTTPServer()
    46  	defer ts.Close()
    47  	cl := newTestClient(ts.URL)
    48  
    49  	assert.NoError(t, cl.Login())
    50  	assert.NoError(t, cl.Logout())
    51  	assert.Zero(t, cl.token.get())
    52  }
    53  
    54  func TestClient_Ping(t *testing.T) {
    55  	ts := newTestHTTPServer()
    56  	defer ts.Close()
    57  	cl := newTestClient(ts.URL)
    58  
    59  	require.NoError(t, cl.Login())
    60  	assert.NoError(t, cl.Ping())
    61  }
    62  
    63  func TestClient_PingWithReAuthentication(t *testing.T) {
    64  	ts := newTestHTTPServer()
    65  	defer ts.Close()
    66  	cl := newTestClient(ts.URL)
    67  
    68  	require.NoError(t, cl.Login())
    69  	cl.token.set("")
    70  	assert.NoError(t, cl.Ping())
    71  	assert.Equal(t, testSessToken, cl.token.get())
    72  }
    73  
    74  func TestClient_ApplMgmt(t *testing.T) {
    75  	ts := newTestHTTPServer()
    76  	defer ts.Close()
    77  	cl := newTestClient(ts.URL)
    78  
    79  	require.NoError(t, cl.Login())
    80  	v, err := cl.ApplMgmt()
    81  	assert.NoError(t, err)
    82  	assert.Equal(t, testHealthValue, v)
    83  }
    84  
    85  func TestClient_DatabaseStorage(t *testing.T) {
    86  	ts := newTestHTTPServer()
    87  	defer ts.Close()
    88  	cl := newTestClient(ts.URL)
    89  
    90  	require.NoError(t, cl.Login())
    91  	v, err := cl.DatabaseStorage()
    92  	assert.NoError(t, err)
    93  	assert.Equal(t, testHealthValue, v)
    94  }
    95  
    96  func TestClient_Load(t *testing.T) {
    97  	ts := newTestHTTPServer()
    98  	defer ts.Close()
    99  	cl := newTestClient(ts.URL)
   100  
   101  	require.NoError(t, cl.Login())
   102  	v, err := cl.Load()
   103  	assert.NoError(t, err)
   104  	assert.Equal(t, testHealthValue, v)
   105  }
   106  
   107  func TestClient_Mem(t *testing.T) {
   108  	ts := newTestHTTPServer()
   109  	defer ts.Close()
   110  	cl := newTestClient(ts.URL)
   111  
   112  	require.NoError(t, cl.Login())
   113  	v, err := cl.Mem()
   114  	assert.NoError(t, err)
   115  	assert.Equal(t, testHealthValue, v)
   116  }
   117  
   118  func TestClient_SoftwarePackages(t *testing.T) {
   119  	ts := newTestHTTPServer()
   120  	defer ts.Close()
   121  	cl := newTestClient(ts.URL)
   122  
   123  	require.NoError(t, cl.Login())
   124  	v, err := cl.SoftwarePackages()
   125  	assert.NoError(t, err)
   126  	assert.Equal(t, testHealthValue, v)
   127  }
   128  
   129  func TestClient_Storage(t *testing.T) {
   130  	ts := newTestHTTPServer()
   131  	defer ts.Close()
   132  	cl := newTestClient(ts.URL)
   133  
   134  	require.NoError(t, cl.Login())
   135  	v, err := cl.Storage()
   136  	assert.NoError(t, err)
   137  	assert.Equal(t, testHealthValue, v)
   138  }
   139  
   140  func TestClient_Swap(t *testing.T) {
   141  	ts := newTestHTTPServer()
   142  	defer ts.Close()
   143  	cl := newTestClient(ts.URL)
   144  
   145  	require.NoError(t, cl.Login())
   146  	v, err := cl.Swap()
   147  	assert.NoError(t, err)
   148  	assert.Equal(t, testHealthValue, v)
   149  }
   150  
   151  func TestClient_System(t *testing.T) {
   152  	ts := newTestHTTPServer()
   153  	defer ts.Close()
   154  	cl := newTestClient(ts.URL)
   155  
   156  	require.NoError(t, cl.Login())
   157  	v, err := cl.System()
   158  	assert.NoError(t, err)
   159  	assert.Equal(t, testHealthValue, v)
   160  }
   161  
   162  func TestClient_InvalidDataOnLogin(t *testing.T) {
   163  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   164  		_, _ = w.Write([]byte("hello\n and goodbye!"))
   165  	}))
   166  	defer ts.Close()
   167  	cl := newTestClient(ts.URL)
   168  
   169  	assert.Error(t, cl.Login())
   170  }
   171  
   172  func TestClient_404OnLogin(t *testing.T) {
   173  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   174  		w.WriteHeader(404)
   175  	}))
   176  	defer ts.Close()
   177  	cl := newTestClient(ts.URL)
   178  
   179  	assert.Error(t, cl.Login())
   180  }
   181  
   182  func newTestHTTPServer() *httptest.Server {
   183  	return httptest.NewServer(&mockVCSAServer{
   184  		username:  testUser,
   185  		password:  testPass,
   186  		sessionID: testSessToken,
   187  	})
   188  }
   189  
   190  type mockVCSAServer struct {
   191  	username  string
   192  	password  string
   193  	sessionID string
   194  }
   195  
   196  func (m mockVCSAServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   197  	switch r.URL.Path {
   198  	default:
   199  		w.WriteHeader(http.StatusNotFound)
   200  	case pathCISSession:
   201  		m.handleSession(w, r)
   202  	case
   203  		pathHealthApplMgmt,
   204  		pathHealthDatabaseStorage,
   205  		pathHealthLoad,
   206  		pathHealthMem,
   207  		pathHealthSoftwarePackager,
   208  		pathHealthStorage,
   209  		pathHealthSwap,
   210  		pathHealthSystem:
   211  		m.handleHealth(w, r)
   212  	}
   213  }
   214  
   215  func (m mockVCSAServer) handleHealth(w http.ResponseWriter, r *http.Request) {
   216  	if r.Method != http.MethodGet {
   217  		w.WriteHeader(http.StatusBadRequest)
   218  		return
   219  	}
   220  
   221  	if !m.isSessionAuthenticated(r) {
   222  		w.WriteHeader(http.StatusUnauthorized)
   223  		return
   224  	}
   225  
   226  	w.Header().Set("Content-Type", "application/json")
   227  	w.WriteHeader(http.StatusOK)
   228  
   229  	s := struct{ Value string }{Value: testHealthValue}
   230  	b, _ := json.Marshal(s)
   231  	_, _ = w.Write(b)
   232  }
   233  
   234  func (m mockVCSAServer) handleSession(w http.ResponseWriter, r *http.Request) {
   235  	switch r.Method {
   236  	default:
   237  		w.WriteHeader(http.StatusBadRequest)
   238  	case http.MethodDelete:
   239  		m.handleSessionDelete(w, r)
   240  	case http.MethodPost:
   241  		if r.URL.RawQuery == "" {
   242  			m.handleSessionCreate(w, r)
   243  		} else {
   244  			m.handleSessionGet(w, r)
   245  		}
   246  	}
   247  }
   248  
   249  func (m mockVCSAServer) handleSessionCreate(w http.ResponseWriter, r *http.Request) {
   250  	if !m.isReqAuthenticated(r) {
   251  		w.WriteHeader(http.StatusUnauthorized)
   252  		return
   253  	}
   254  
   255  	w.WriteHeader(http.StatusOK)
   256  	s := struct{ Value string }{Value: m.sessionID}
   257  	b, _ := json.Marshal(s)
   258  	_, _ = w.Write(b)
   259  }
   260  
   261  func (m mockVCSAServer) handleSessionGet(w http.ResponseWriter, r *http.Request) {
   262  	if !m.isSessionAuthenticated(r) {
   263  		w.WriteHeader(http.StatusUnauthorized)
   264  		return
   265  	}
   266  
   267  	w.WriteHeader(http.StatusOK)
   268  	s := struct{ Value struct{ User string } }{Value: struct{ User string }{User: m.username}}
   269  	b, _ := json.Marshal(s)
   270  	_, _ = w.Write(b)
   271  }
   272  
   273  func (m mockVCSAServer) handleSessionDelete(w http.ResponseWriter, r *http.Request) {
   274  	if !m.isSessionAuthenticated(r) {
   275  		w.WriteHeader(http.StatusUnauthorized)
   276  		return
   277  	}
   278  	w.WriteHeader(http.StatusOK)
   279  }
   280  
   281  func (m mockVCSAServer) isReqAuthenticated(r *http.Request) bool {
   282  	u, p, ok := r.BasicAuth()
   283  	return ok && m.username == u && p == m.password
   284  }
   285  
   286  func (m mockVCSAServer) isSessionAuthenticated(r *http.Request) bool {
   287  	return r.Header.Get(apiSessIDKey) == m.sessionID
   288  }