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 }