test_restful.TestGlances.test_999_stop_server()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
#!/usr/bin/env python
2
#
3
# Glances - An eye on your system
4
#
5
# SPDX-FileCopyrightText: 2022 Nicolas Hennion <[email protected]>
6
#
7
# SPDX-License-Identifier: LGPL-3.0-only
8
#
9
10
"""Glances unitary tests suite for the RESTful API."""
11
12
import numbers
13
import os
14
import shlex
15
import subprocess
16
import time
17
import types
18
import unittest
19
20
import requests
21
22
from glances import __version__
23
from glances.globals import text_type
24
from glances.outputs.glances_restful_api import GlancesRestfulApi
25
from glances.timer import Counter
26
27
SERVER_PORT = 61234
28
API_VERSION = GlancesRestfulApi.API_VERSION
29
URL = f"http://localhost:{SERVER_PORT}/api/{API_VERSION}"
30
pid = None
31
32
# Unitest class
33
# ==============
34
print(f'RESTful API unitary tests for Glances {__version__}')
35
36
37
class TestGlances(unittest.TestCase):
38
    """Test Glances class."""
39
40
    def setUp(self):
41
        """The function is called *every time* before test_*."""
42
        print('\n' + '=' * 78)
43
44
    def http_get(self, url, gzip=False):
45
        """Make the request"""
46
        if gzip:
47
            ret = requests.get(url, stream=True, headers={'Accept-encoding': 'gzip'})
48
        else:
49
            ret = requests.get(url, headers={'Accept-encoding': 'identity'})
50
        return ret
51
52 View Code Duplication
    def test_000_start_server(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
53
        """Start the Glances Web Server."""
54
        global pid
55
56
        print('INFO: [TEST_000] Start the Glances Web Server API')
57
        if os.path.isfile('./venv/bin/python'):
58
            cmdline = "./venv/bin/python"
59
        else:
60
            cmdline = "python"
61
        cmdline += f" -m glances -B 0.0.0.0 -w --browser -p {SERVER_PORT} --disable-webui -C ./conf/glances.conf"
62
        print(f"Run the Glances Web Server on port {SERVER_PORT}")
63
        args = shlex.split(cmdline)
64
        pid = subprocess.Popen(args)
65
        print("Please wait 5 seconds...")
66
        time.sleep(5)
67
68
        self.assertTrue(pid is not None)
69
70
    def test_001_all(self):
71
        """All."""
72
        method = "all"
73
        print('INFO: [TEST_001] Get all stats')
74
        print(f"HTTP RESTful request: {URL}/{method}")
75
        # First call is not cached
76
        counter_first_call = Counter()
77
        first_req = self.http_get(f"{URL}/{method}")
78
        self.assertTrue(first_req.ok)
79
        self.assertTrue(first_req.json(), dict)
80
        counter_first_call_result = counter_first_call.get()
81
        # Second call (if it is in the same second) is cached
82
        counter_second_call = Counter()
83
        second_req = self.http_get(f"{URL}/{method}")
84
        self.assertTrue(second_req.ok)
85
        self.assertTrue(second_req.json(), dict)
86
        counter_second_call_result = counter_second_call.get()
87
        # Check if result of first call is equal to second call
88
        self.assertEqual(first_req.json(), second_req.json(), "The result of the first and second call should be equal")
89
        # Check cache result
90
        print(
91
            f"First API call took {counter_first_call_result:.2f} seconds"
92
            f" and second API call (cached) took {counter_second_call_result:.2f} seconds"
93
        )
94
        self.assertTrue(
95
            counter_second_call_result < counter_first_call_result,
96
            "The second call should be cached (faster than the first one)",
97
        )
98
99
    def test_002_pluginslist(self):
100
        """Plugins list."""
101
        method = "pluginslist"
102
        print('INFO: [TEST_002] Plugins list')
103
        print(f"HTTP RESTful request: {URL}/{method}")
104
        req = self.http_get(f"{URL}/{method}")
105
106
        self.assertTrue(req.ok)
107
        self.assertIsInstance(req.json(), list)
108
        self.assertIn('cpu', req.json())
109
110
    def test_003_plugins(self):
111
        """Plugins."""
112
        method = "pluginslist"
113
        print('INFO: [TEST_003] Plugins')
114
        plist = self.http_get(f"{URL}/{method}")
115
116
        for p in plist.json():
117
            print(f"HTTP RESTful request: {URL}/{p}")
118
            req = self.http_get(f"{URL}/{p}")
119
            self.assertTrue(req.ok)
120
            if p in ('uptime', 'version', 'psutilversion'):
121
                self.assertIsInstance(req.json(), text_type)
122
            elif p in (
123
                'fs',
124
                'percpu',
125
                'sensors',
126
                'alert',
127
                'processlist',
128
                'programlist',
129
                'diskio',
130
                'hddtemp',
131
                'batpercent',
132
                'network',
133
                'folders',
134
                'amps',
135
                'ports',
136
                'irq',
137
                'wifi',
138
                'gpu',
139
                'containers',
140
                'vms',
141
            ):
142
                self.assertIsInstance(req.json(), list)
143
                if len(req.json()) > 0:
144
                    self.assertIsInstance(req.json()[0], dict)
145
            else:
146
                self.assertIsInstance(req.json(), dict)
147
148
    def test_004_items(self):
149
        """Items."""
150
        method = "cpu"
151
        print('INFO: [TEST_004] Items for the CPU method')
152
        ilist = self.http_get(f"{URL}/{method}")
153
154
        for i in ilist.json():
155
            print(f"HTTP RESTful request: {URL}/{method}/{i}")
156
            req = self.http_get(f"{URL}/{method}/{i}")
157
            self.assertTrue(req.ok)
158
            self.assertIsInstance(req.json(), dict)
159
            print(req.json()[i])
160
            # Value can be a number or None (for _rate in first loop)
161
            self.assertIsInstance(req.json()[i], (numbers.Number, types.NoneType))
162
163
    def test_005_values(self):
164
        """Values."""
165
        method = "processlist"
166
        print('INFO: [TEST_005] Item=Value for the PROCESSLIST method')
167
        req = self.http_get(f"{URL}/{method}/pid/value/0")
168
169
        self.assertTrue(req.ok)
170
        self.assertIsInstance(req.json(), dict)
171
172
    def test_006_all_limits(self):
173
        """All limits."""
174
        method = "all/limits"
175
        print('INFO: [TEST_006] Get all limits')
176
        print(f"HTTP RESTful request: {URL}/{method}")
177
        req = self.http_get(f"{URL}/{method}")
178
179
        self.assertTrue(req.ok)
180
        self.assertIsInstance(req.json(), dict)
181
182
    def test_007_all_views(self):
183
        """All views."""
184
        method = "all/views"
185
        print('INFO: [TEST_007] Get all views')
186
        print(f"HTTP RESTful request: {URL}/{method}")
187
        req = self.http_get(f"{URL}/{method}")
188
189
        self.assertTrue(req.ok)
190
        self.assertIsInstance(req.json(), dict)
191
192
    def test_008_plugins_limits(self):
193
        """Plugins limits."""
194
        method = "pluginslist"
195
        print('INFO: [TEST_008] Plugins limits')
196
        plist = self.http_get(f"{URL}/{method}")
197
198
        for p in plist.json():
199
            print(f"HTTP RESTful request: {URL}/{p}/limits")
200
            req = self.http_get(f"{URL}/{p}/limits")
201
            self.assertTrue(req.ok)
202
            self.assertIsInstance(req.json(), dict)
203
204
    def test_009_plugins_views(self):
205
        """Plugins views."""
206
        method = "pluginslist"
207
        print('INFO: [TEST_009] Plugins views')
208
        plist = self.http_get(f"{URL}/{method}")
209
210
        for p in plist.json():
211
            print(f"HTTP RESTful request: {URL}/{p}/views")
212
            req = self.http_get(f"{URL}/{p}/views")
213
            self.assertTrue(req.ok)
214
            self.assertIsInstance(req.json(), dict)
215
216
    def test_010_history(self):
217
        """History."""
218
        method = "history"
219
        print('INFO: [TEST_010] History')
220
        print(f"HTTP RESTful request: {URL}/cpu/{method}")
221
        req = self.http_get(f"{URL}/cpu/{method}")
222
        self.assertIsInstance(req.json(), dict)
223
        self.assertIsInstance(req.json()['user'], list)
224
        self.assertTrue(len(req.json()['user']) > 0)
225
        print(f"HTTP RESTful request: {URL}/cpu/{method}/3")
226
        req = self.http_get(f"{URL}/cpu/{method}/3")
227
        self.assertIsInstance(req.json(), dict)
228
        self.assertIsInstance(req.json()['user'], list)
229
        self.assertTrue(len(req.json()['user']) > 1)
230
        print(f"HTTP RESTful request: {URL}/cpu/system/{method}")
231
        req = self.http_get(f"{URL}/cpu/system/{method}")
232
        self.assertIsInstance(req.json(), list)
233
        self.assertIsInstance(req.json()[0], list)
234
        print(f"HTTP RESTful request: {URL}/cpu/system/{method}/3")
235
        req = self.http_get(f"{URL}/cpu/system/{method}/3")
236
        self.assertIsInstance(req.json(), list)
237
        self.assertIsInstance(req.json()[0], list)
238
239
    def test_011_issue1401(self):
240
        """Check issue #1401."""
241
        method = "network/interface_name"
242
        print('INFO: [TEST_011] Issue #1401')
243
        req = self.http_get(f"{URL}/{method}")
244
        self.assertTrue(req.ok)
245
        self.assertIsInstance(req.json(), dict)
246
        self.assertIsInstance(req.json()['interface_name'], list)
247
248
    def test_012_status(self):
249
        """Check status endpoint."""
250
        method = "status"
251
        print('INFO: [TEST_012] Status')
252
        print(f"HTTP RESTful request: {URL}/{method}")
253
        req = self.http_get(f"{URL}/{method}")
254
255
        self.assertTrue(req.ok)
256
        self.assertEqual(req.json()['version'], __version__)
257
258
    def test_013_top(self):
259
        """Values."""
260
        method = "processlist"
261
        request = f"{URL}/{method}/top/2"
262
        print('INFO: [TEST_013] Top nb item of PROCESSLIST')
263
        print(request)
264
        req = self.http_get(request)
265
266
        self.assertTrue(req.ok)
267
        self.assertIsInstance(req.json(), list)
268
        self.assertEqual(len(req.json()), 2)
269
270
    def test_014_config(self):
271
        """Test API request to get Glances configuration."""
272
        method = "config"
273
        print('INFO: [TEST_014] Get config')
274
275
        req = self.http_get(f"{URL}/{method}")
276
        self.assertTrue(req.ok)
277
        self.assertIsInstance(req.json(), dict)
278
279
        req = self.http_get(f"{URL}/{method}/global/refresh")
280
        self.assertTrue(req.ok)
281
        self.assertEqual(req.json(), "2")
282
283
    def test_015_all_gzip(self):
284
        """All with Gzip."""
285
        method = "all"
286
        print('INFO: [TEST_015] Get all stats (with GZip compression)')
287
        print(f"HTTP RESTful request: {URL}/{method}")
288
        req = self.http_get(f"{URL}/{method}", gzip=True)
289
290
        self.assertTrue(req.ok)
291
        self.assertTrue(req.headers['Content-Encoding'] == 'gzip')
292
        self.assertTrue(req.json(), dict)
293
294
    def test_016_fields_description(self):
295
        """Fields description."""
296
        print('INFO: [TEST_016] Get fields description and unit')
297
298
        print(f"HTTP RESTful request: {URL}/cpu/total/description")
299
        req = self.http_get(f"{URL}/cpu/total/description")
300
        self.assertTrue(req.ok)
301
        self.assertTrue(req.json(), str)
302
303
        print(f"HTTP RESTful request: {URL}/cpu/total/unit")
304
        req = self.http_get(f"{URL}/cpu/total/unit")
305
        self.assertTrue(req.ok)
306
        self.assertTrue(req.json(), str)
307
308
    def test_017_item_key(self):
309
        """Get /plugin/item/key value."""
310
        print('INFO: [TEST_017] Get /plugin/item/key value')
311
        plugin = "network"
312
        item = "interface_name"
313
        req = self.http_get(f"{URL}/{plugin}/{item}")
314
        self.assertTrue(req.ok)
315
        self.assertIsInstance(req.json(), dict)
316
        self.assertIsInstance(req.json()[item], list)
317
        if len(req.json()[item]) > 0:
318
            key = req.json()[item][0]
319
            item = "bytes_all"
320
            req = self.http_get(f"{URL}/{plugin}/{item}/{key}")
321
            self.assertTrue(req.ok)
322
            self.assertIsInstance(req.json(), dict)
323
            self.assertIsInstance(req.json()[item], int)
324
325
    def test_100_browser(self):
326
        """Get /serverslist (for Glances Central Browser)."""
327
        print('INFO: [TEST_100] Get /serverslist (for Glances Central Browser)')
328
        req = self.http_get(f"{URL}/serverslist")
329
        self.assertTrue(req.ok)
330
        self.assertIsInstance(req.json(), list)
331
        if len(req.json()) > 0:
332
            self.assertIsInstance(req.json()[0], dict)
333
334
    def test_999_stop_server(self):
335
        """Stop the Glances Web Server."""
336
        print('INFO: [TEST_999] Stop the Glances Web Server')
337
338
        print("Stop the Glances Web Server")
339
        pid.terminate()
340
        time.sleep(1)
341
342
        self.assertTrue(True)
343
344
345
if __name__ == '__main__':
346
    unittest.main()
347