test_core   F
last analyzed

Complexity

Total Complexity 87

Size/Duplication

Total Lines 741
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 87
eloc 507
dl 0
loc 741
rs 2
c 0
b 0
f 0

39 Methods

Rating   Name   Duplication   Size   Complexity  
A TestGlances.test_017_programs() 0 9 2
A TestGlances.test_097_attribute() 0 23 1
A TestGlances.test_101_cpu_plugin_method() 0 4 1
A TestGlances.test_096_views() 0 8 2
A TestGlances.test_017_hddsmart() 0 22 4
A TestGlances.test_008_diskio() 0 6 1
A TestGlances.test_999_the_end() 0 5 1
B TestGlances.test_019_events() 0 50 1
A TestGlances.test_016_subsample() 0 13 2
A TestGlances.test_103_mem_plugin_method() 0 4 1
A TestGlances.test_003_cpu() 0 12 2
A TestGlances.setUp() 0 3 1
A TestGlances.test_010_processes() 0 11 1
A TestGlances.test_015_sorted_stats() 0 27 2
A TestGlances.test_005_mem() 0 12 2
A TestGlances.test_018_string_value_to_float() 0 9 1
A TestGlances.test_001_plugins() 0 7 2
A TestGlances.test_020_filter() 0 23 1
A TestGlances.test_006_memswap() 0 11 2
A TestGlances.test_107_fs_plugin_method() 0 4 1
F TestGlances._common_plugin_tests() 0 124 30
A TestGlances.test_012_ip() 0 6 1
A TestGlances.test_104_memswap_plugin_method() 0 4 1
A TestGlances.test_009_fs() 0 7 1
A TestGlances.test_099_output_bars() 0 31 1
A TestGlances.test_000_update() 0 19 3
A TestGlances.test_021_pretty_date() 0 14 1
A TestGlances.test_013_irq() 0 7 1
A TestGlances.test_094_thresholds() 0 16 1
A TestGlances.test_095_methods() 0 8 3
A TestGlances.test_004_load() 0 12 2
A TestGlances.test_200_views_hidden() 0 43 3
A TestGlances.test_105_network_plugin_method() 0 4 1
A TestGlances.test_007_network() 0 6 1
A TestGlances.test_011_folders() 0 7 1
A TestGlances.test_102_load_plugin_method() 0 5 1
A TestGlances.test_014_gpu() 0 7 1
A TestGlances.test_098_history() 0 18 1
A TestGlances.test_002_system() 0 9 2

How to fix   Complexity   

Complexity

Complex classes like test_core often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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
# Refactor by @ariel-anieli in 2024
10
11
"""Glances unitary tests suite."""
12
13
import json
14
import time
15
import unittest
16
from datetime import datetime
17
18
# Ugly hack waiting for Python 3.10 deprecation
19
try:
20
    from datetime import UTC
21
except ImportError:
22
    from datetime import timezone
23
24
    UTC = timezone.utc
25
26
from glances import __version__
27
from glances.events_list import GlancesEventsList
28
from glances.filter import GlancesFilter, GlancesFilterList
29
from glances.globals import LINUX, WINDOWS, pretty_date, string_value_to_float, subsample
30
from glances.main import GlancesMain
31
from glances.outputs.glances_bars import Bar
32
from glances.plugins.plugin.model import GlancesPluginModel
33
from glances.stats import GlancesStats
34
from glances.thresholds import (
35
    GlancesThresholdCareful,
36
    GlancesThresholdCritical,
37
    GlancesThresholdOk,
38
    GlancesThresholds,
39
    GlancesThresholdWarning,
40
)
41
42
# Global variables
43
# =================
44
45
# Init Glances core
46
core = GlancesMain(args_begin_at=2)
47
test_config = core.get_config()
48
test_args = core.get_args()
49
50
# Init Glances stats
51
stats = GlancesStats(config=test_config, args=test_args)
52
53
# Unitest class
54
# ==============
55
print(f'Unitary tests for Glances {__version__}')
56
57
58
class TestGlances(unittest.TestCase):
59
    """Test Glances class."""
60
61
    def setUp(self):
62
        """The function is called *every time* before test_*."""
63
        print('\n' + '=' * 78)
64
65
    def _common_plugin_tests(self, plugin):
66
        """Common method to test a Glances plugin
67
        This method is called multiple time by test 100 to 1xx"""
68
69
        # Reset all the stats, history and views
70
        plugin_instance = stats.get_plugin(plugin)
71
        plugin_instance.reset()  # reset stats
72
        plugin_instance.reset_views()  # reset views
73
        plugin_instance.reset_stats_history()  # reset history
74
75
        # Check before update
76
        self.assertEqual(plugin_instance.get_raw(), plugin_instance.stats_init_value)
77
        self.assertEqual(plugin_instance.is_enabled(), True)
78
        self.assertEqual(plugin_instance.is_disabled(), False)
79
        self.assertEqual(plugin_instance.get_views(), {})
80
        self.assertIsInstance(plugin_instance.get_raw(), (dict, list))
81
        if plugin_instance.history_enable() and isinstance(plugin_instance.get_raw(), dict):
82
            self.assertEqual(plugin_instance.get_key(), None)
83
            self.assertTrue(
84
                all(
85
                    f in [h['name'] for h in plugin_instance.items_history_list]
86
                    for f in plugin_instance.get_raw_history()
87
                )
88
            )
89
        elif plugin_instance.history_enable() and isinstance(plugin_instance.get_raw(), list):
90
            self.assertNotEqual(plugin_instance.get_key(), None)
91
92
        # Update stats (add first element)
93
        plugin_instance.update()
94
        plugin_instance.update_stats_history()
95
        plugin_instance.update_views()
96
97
        # Check stats
98
        self.assertIsInstance(plugin_instance.get_raw(), (dict, list))
99
        if isinstance(plugin_instance.get_raw(), dict) and plugin_instance.get_raw() != {}:
100
            res = False
101
            for f in plugin_instance.fields_description:
102
                if f not in plugin_instance.get_raw():
103
                    print(f"WARNING: {f} field not found in {plugin} plugin stats")
104
                else:
105
                    res = True
106
            self.assertTrue(res)
107
        elif isinstance(plugin_instance.get_raw(), list) and len(plugin_instance.get_raw()) > 0:
108
            res = False
109
            for i in plugin_instance.get_raw():
110
                for f in i:
111
                    if f in plugin_instance.fields_description:
112
                        res = True
113
            self.assertTrue(res)
114
115
        self.assertEqual(plugin_instance.get_raw(), plugin_instance.get_export())
116
        self.assertEqual(plugin_instance.get_stats(), plugin_instance.get_json())
117
        self.assertEqual(json.loads(plugin_instance.get_stats()), plugin_instance.get_raw())
118
        if len(plugin_instance.fields_description) > 0:
119
            # Get first item of the fields_description
120
            first_field = list(plugin_instance.fields_description.keys())[0]
121
            self.assertIsInstance(plugin_instance.get_raw_stats_item(first_field), dict)
122
            self.assertIsInstance(json.loads(plugin_instance.get_stats_item(first_field)), dict)
123
            self.assertIsInstance(plugin_instance.get_item_info(first_field, 'description'), str)
124
        # Filter stats
125
        current_stats = plugin_instance.get_raw()
126
        if isinstance(plugin_instance.get_raw(), dict):
127
            current_stats['foo'] = 'bar'
128
            current_stats = plugin_instance.filter_stats(current_stats)
129
            self.assertTrue('foo' not in current_stats)
130
        elif isinstance(plugin_instance.get_raw(), list) and len(plugin_instance.get_raw()) > 0:
131
            current_stats[0]['foo'] = 'bar'
132
            current_stats = plugin_instance.filter_stats(current_stats)
133
            self.assertTrue('foo' not in current_stats[0])
134
135
        # Update stats (add second element)
136
        plugin_instance.update()
137
        plugin_instance.update_stats_history()
138
        plugin_instance.update_views()
139
140
        # Check stats history
141
        # Not working on WINDOWS
142
        if plugin_instance.history_enable() and not WINDOWS:
143
            if isinstance(plugin_instance.get_raw(), dict):
144
                first_history_field = plugin_instance.get_items_history_list()[0]['name']
145
            elif isinstance(plugin_instance.get_raw(), list) and len(plugin_instance.get_raw()) > 0:
146
                first_history_field = '_'.join(
147
                    [
148
                        plugin_instance.get_raw()[0][plugin_instance.get_key()],
149
                        plugin_instance.get_items_history_list()[0]['name'],
150
                    ]
151
                )
152
            if len(plugin_instance.get_raw()) > 0:
153
                self.assertEqual(len(plugin_instance.get_raw_history(first_history_field)), 2)
0 ignored issues
show
introduced by
The variable first_history_field does not seem to be defined for all execution paths.
Loading history...
154
                self.assertGreater(
155
                    plugin_instance.get_raw_history(first_history_field)[1][0],
156
                    plugin_instance.get_raw_history(first_history_field)[0][0],
157
                )
158
                # Check time
159
                self.assertEqual(
160
                    plugin_instance.get_raw_history(first_history_field)[1][0].tzinfo,
161
                    UTC,
162
                )
163
164
            # Update stats (add third element)
165
            plugin_instance.update()
166
            plugin_instance.update_stats_history()
167
            plugin_instance.update_views()
168
169
            if len(plugin_instance.get_raw()) > 0:
170
                self.assertEqual(len(plugin_instance.get_raw_history(first_history_field)), 3)
171
                self.assertEqual(len(plugin_instance.get_raw_history(first_history_field, 2)), 2)
172
                self.assertIsInstance(json.loads(plugin_instance.get_stats_history()), dict)
173
174
        # Check views
175
        self.assertIsInstance(plugin_instance.get_views(), dict)
176
        self.assertIsInstance(json.loads(plugin_instance.get_json_views()), dict)
177
        self.assertEqual(json.loads(plugin_instance.get_json_views()), plugin_instance.get_views())
178
        # Check views history
179
        # Not working on WINDOWS
180
        if plugin_instance.history_enable() and not WINDOWS:
181
            if isinstance(plugin_instance.get_raw(), dict):
182
                self.assertIsInstance(plugin_instance.get_views(first_history_field), dict)
183
                self.assertTrue('decoration' in plugin_instance.get_views(first_history_field))
184
            elif isinstance(plugin_instance.get_raw(), list) and len(plugin_instance.get_raw()) > 0:
185
                first_history_field = plugin_instance.get_items_history_list()[0]['name']
186
                first_item = plugin_instance.get_raw()[0][plugin_instance.get_key()]
187
                self.assertIsInstance(plugin_instance.get_views(item=first_item, key=first_history_field), dict)
188
                self.assertTrue('decoration' in plugin_instance.get_views(item=first_item, key=first_history_field))
189
190
    def test_000_update(self):
191
        """Update stats (mandatory step for all the stats).
192
193
        The update is made twice (for rate computation).
194
        """
195
        print('INFO: [TEST_000] Test the stats update function')
196
        try:
197
            stats.update()
198
        except Exception as e:
199
            print(f'ERROR: Stats update failed: {e}')
200
            self.assertTrue(False)
201
        time.sleep(1)
202
        try:
203
            stats.update()
204
        except Exception as e:
205
            print(f'ERROR: Stats update failed: {e}')
206
            self.assertTrue(False)
207
208
        self.assertTrue(True)
209
210
    def test_001_plugins(self):
211
        """Check mandatory plugins."""
212
        plugins_to_check = ['system', 'cpu', 'load', 'mem', 'memswap', 'network', 'diskio', 'fs']
213
        print('INFO: [TEST_001] Check the mandatory plugins list: {}'.format(', '.join(plugins_to_check)))
214
        plugins_list = stats.getPluginsList()
215
        for plugin in plugins_to_check:
216
            self.assertTrue(plugin in plugins_list)
217
218
    def test_002_system(self):
219
        """Check SYSTEM plugin."""
220
        stats_to_check = ['hostname', 'os_name']
221
        print('INFO: [TEST_002] Check SYSTEM stats: {}'.format(', '.join(stats_to_check)))
222
        stats_grab = stats.get_plugin('system').get_raw()
223
        for stat in stats_to_check:
224
            # Check that the key exist
225
            self.assertTrue(stat in stats_grab, msg=f'Cannot find key: {stat}')
226
        print(f'INFO: SYSTEM stats: {stats_grab}')
227
228
    def test_003_cpu(self):
229
        """Check CPU plugin."""
230
        stats_to_check = ['system', 'user', 'idle']
231
        print('INFO: [TEST_003] Check mandatory CPU stats: {}'.format(', '.join(stats_to_check)))
232
        stats_grab = stats.get_plugin('cpu').get_raw()
233
        for stat in stats_to_check:
234
            # Check that the key exist
235
            self.assertTrue(stat in stats_grab, msg=f'Cannot find key: {stat}')
236
            # Check that % is > 0 and < 100
237
            self.assertGreaterEqual(stats_grab[stat], 0)
238
            self.assertLessEqual(stats_grab[stat], 100)
239
        print(f'INFO: CPU stats: {stats_grab}')
240
241
    @unittest.skipIf(WINDOWS, "Load average not available on Windows")
242
    def test_004_load(self):
243
        """Check LOAD plugin."""
244
        stats_to_check = ['cpucore', 'min1', 'min5', 'min15']
245
        print('INFO: [TEST_004] Check LOAD stats: {}'.format(', '.join(stats_to_check)))
246
        stats_grab = stats.get_plugin('load').get_raw()
247
        for stat in stats_to_check:
248
            # Check that the key exist
249
            self.assertTrue(stat in stats_grab, msg=f'Cannot find key: {stat}')
250
            # Check that % is > 0
251
            self.assertGreaterEqual(stats_grab[stat], 0)
252
        print(f'INFO: LOAD stats: {stats_grab}')
253
254
    def test_005_mem(self):
255
        """Check MEM plugin."""
256
        plugin_name = 'mem'
257
        stats_to_check = ['available', 'used', 'free', 'total']
258
        print('INFO: [TEST_005] Check {} stats: {}'.format(plugin_name, ', '.join(stats_to_check)))
259
        stats_grab = stats.get_plugin('mem').get_raw()
260
        for stat in stats_to_check:
261
            # Check that the key exist
262
            self.assertTrue(stat in stats_grab, msg=f'Cannot find key: {stat}')
263
            # Check that % is > 0
264
            self.assertGreaterEqual(stats_grab[stat], 0)
265
        print(f'INFO: MEM stats: {stats_grab}')
266
267
    def test_006_memswap(self):
268
        """Check MEMSWAP plugin."""
269
        stats_to_check = ['used', 'free', 'total']
270
        print('INFO: [TEST_006] Check MEMSWAP stats: {}'.format(', '.join(stats_to_check)))
271
        stats_grab = stats.get_plugin('memswap').get_raw()
272
        for stat in stats_to_check:
273
            # Check that the key exist
274
            self.assertTrue(stat in stats_grab, msg=f'Cannot find key: {stat}')
275
            # Check that % is > 0
276
            self.assertGreaterEqual(stats_grab[stat], 0)
277
        print(f'INFO: MEMSWAP stats: {stats_grab}')
278
279
    def test_007_network(self):
280
        """Check NETWORK plugin."""
281
        print('INFO: [TEST_007] Check NETWORK stats')
282
        stats_grab = stats.get_plugin('network').get_raw()
283
        self.assertTrue(isinstance(stats_grab, list), msg='Network stats is not a list')
284
        print(f'INFO: NETWORK stats: {stats_grab}')
285
286
    def test_008_diskio(self):
287
        """Check DISKIO plugin."""
288
        print('INFO: [TEST_008] Check DISKIO stats')
289
        stats_grab = stats.get_plugin('diskio').get_raw()
290
        self.assertTrue(isinstance(stats_grab, list), msg='DiskIO stats is not a list')
291
        print(f'INFO: diskio stats: {stats_grab}')
292
293
    def test_009_fs(self):
294
        """Check File System plugin."""
295
        # stats_to_check = [ ]
296
        print('INFO: [TEST_009] Check FS stats')
297
        stats_grab = stats.get_plugin('fs').get_raw()
298
        self.assertTrue(isinstance(stats_grab, list), msg='FileSystem stats is not a list')
299
        print(f'INFO: FS stats: {stats_grab}')
300
301
    def test_010_processes(self):
302
        """Check Process plugin."""
303
        # stats_to_check = [ ]
304
        print('INFO: [TEST_010] Check PROCESS stats')
305
        stats_grab = stats.get_plugin('processcount').get_raw()
306
        # total = stats_grab['total']
307
        self.assertTrue(isinstance(stats_grab, dict), msg='Process count stats is not a dict')
308
        print(f'INFO: PROCESS count stats: {stats_grab}')
309
        stats_grab = stats.get_plugin('processlist').get_raw()
310
        self.assertTrue(isinstance(stats_grab, list), msg='Process count stats is not a list')
311
        print(f'INFO: PROCESS list stats: {len(stats_grab)} items in the list')
312
        # Check if number of processes in the list equal counter
313
        # self.assertEqual(total, len(stats_grab))
314
315
    def test_011_folders(self):
316
        """Check File System plugin."""
317
        # stats_to_check = [ ]
318
        print('INFO: [TEST_011] Check FOLDER stats')
319
        stats_grab = stats.get_plugin('folders').get_raw()
320
        self.assertTrue(isinstance(stats_grab, list), msg='Folders stats is not a list')
321
        print(f'INFO: Folders stats: {stats_grab}')
322
323
    def test_012_ip(self):
324
        """Check IP plugin."""
325
        print('INFO: [TEST_012] Check IP stats')
326
        stats_grab = stats.get_plugin('ip').get_raw()
327
        self.assertTrue(isinstance(stats_grab, dict), msg='IP stats is not a dict')
328
        print(f'INFO: IP stats: {stats_grab}')
329
330
    @unittest.skipIf(not LINUX, "IRQs available only on Linux")
331
    def test_013_irq(self):
332
        """Check IRQ plugin."""
333
        print('INFO: [TEST_013] Check IRQ stats')
334
        stats_grab = stats.get_plugin('irq').get_raw()
335
        self.assertTrue(isinstance(stats_grab, list), msg='IRQ stats is not a list')
336
        print(f'INFO: IRQ stats: {stats_grab}')
337
338
    @unittest.skipIf(not LINUX, "GPU available only on Linux")
339
    def test_014_gpu(self):
340
        """Check GPU plugin."""
341
        print('INFO: [TEST_014] Check GPU stats')
342
        stats_grab = stats.get_plugin('gpu').get_raw()
343
        self.assertTrue(isinstance(stats_grab, list), msg='GPU stats is not a list')
344
        print(f'INFO: GPU stats: {stats_grab}')
345
346
    def test_015_sorted_stats(self):
347
        """Check sorted stats method."""
348
        print('INFO: [TEST_015] Check sorted stats method')
349
        aliases = {
350
            "key2": "alias11",
351
            "key5": "alias2",
352
        }
353
        unsorted_stats = [
354
            {"key": "key4"},
355
            {"key": "key2"},
356
            {"key": "key5"},
357
            {"key": "key21"},
358
            {"key": "key3"},
359
        ]
360
361
        gp = GlancesPluginModel()
362
        gp.get_key = lambda: "key"
363
        gp.has_alias = aliases.get
364
        gp.stats = unsorted_stats
365
366
        sorted_stats = gp.sorted_stats()
367
        self.assertEqual(len(sorted_stats), 5)
368
        self.assertEqual(sorted_stats[0]["key"], "key5")
369
        self.assertEqual(sorted_stats[1]["key"], "key2")
370
        self.assertEqual(sorted_stats[2]["key"], "key3")
371
        self.assertEqual(sorted_stats[3]["key"], "key4")
372
        self.assertEqual(sorted_stats[4]["key"], "key21")
373
374
    def test_016_subsample(self):
375
        """Test subsampling function."""
376
        print('INFO: [TEST_016] Subsampling')
377
        for l_test in [
378
            ([1, 2, 3], 4),
379
            ([1, 2, 3, 4], 4),
380
            ([1, 2, 3, 4, 5, 6, 7], 4),
381
            ([1, 2, 3, 4, 5, 6, 7, 8], 4),
382
            (list(range(1, 800)), 4),
383
            (list(range(1, 8000)), 800),
384
        ]:
385
            l_subsample = subsample(l_test[0], l_test[1])
386
            self.assertLessEqual(len(l_subsample), l_test[1])
387
388
    def test_017_hddsmart(self):
389
        """Check hard disk SMART data plugin."""
390
        try:
391
            from glances.globals import is_admin
392
        except ImportError:
393
            print("INFO: [TEST_017] pySMART not found, not running SMART plugin test")
394
            return
395
396
        stat = 'DeviceName'
397
        print(f'INFO: [TEST_017] Check SMART stats: {stat}')
398
        stats_grab = stats.get_plugin('smart').get_raw()
399
        if not is_admin():
400
            print("INFO: Not admin, SMART list should be empty")
401
            assert len(stats_grab) == 0
402
        elif stats_grab == {}:
403
            print("INFO: Admin but SMART list is empty")
404
            assert len(stats_grab) == 0
405
        else:
406
            print(stats_grab)
407
            self.assertTrue(stat in stats_grab[0].keys(), msg=f'Cannot find key: {stat}')
408
409
        print(f'INFO: SMART stats: {stats_grab}')
410
411
    def test_017_programs(self):
412
        """Check Programs plugin."""
413
        # stats_to_check = [ ]
414
        print('INFO: [TEST_022] Check PROGRAMS stats')
415
        stats_grab = stats.get_plugin('programlist').get_raw()
416
        self.assertTrue(isinstance(stats_grab, list), msg='Programs stats is not a list')
417
        if stats_grab:
418
            self.assertTrue(isinstance(stats_grab[0], dict), msg='Programs stats is not a list of dict')
419
            self.assertTrue('nprocs' in stats_grab[0], msg='No nprocs')
420
421
    def test_018_string_value_to_float(self):
422
        """Check string_value_to_float function"""
423
        print('INFO: [TEST_018] Check string_value_to_float function')
424
        self.assertEqual(string_value_to_float('32kB'), 32000.0)
425
        self.assertEqual(string_value_to_float('32 KB'), 32000.0)
426
        self.assertEqual(string_value_to_float('15.5MB'), 15500000.0)
427
        self.assertEqual(string_value_to_float('25.9'), 25.9)
428
        self.assertEqual(string_value_to_float('12'), 12)
429
        self.assertEqual(string_value_to_float('--'), None)
430
431
    def test_019_events(self):
432
        """Test events class"""
433
        print('INFO: [TEST_019] Test events')
434
        # Init events
435
        events = GlancesEventsList(max_events=5, min_duration=1, min_interval=3)
436
        # Minimal event duration not reached
437
        events.add('WARNING', 'LOAD', 4)
438
        events.add('CRITICAL', 'LOAD', 5)
439
        events.add('OK', 'LOAD', 1)
440
        self.assertEqual(len(events.get()), 0)
441
        # Minimal event duration LOAD reached
442
        events.add('WARNING', 'LOAD', 4)
443
        time.sleep(1)
444
        events.add('CRITICAL', 'LOAD', 5)
445
        time.sleep(1)
446
        events.add('OK', 'LOAD', 1)
447
        self.assertEqual(len(events.get()), 1)
448
        self.assertEqual(events.get()[0]['type'], 'LOAD')
449
        self.assertEqual(events.get()[0]['state'], 'CRITICAL')
450
        self.assertEqual(events.get()[0]['max'], 5)
451
        # Minimal event duration CPU reached
452
        events.add('WARNING', 'CPU', 60)
453
        time.sleep(1)
454
        events.add('WARNING', 'CPU', 70)
455
        time.sleep(1)
456
        events.add('OK', 'CPU', 10)
457
        self.assertEqual(len(events.get()), 2)
458
        self.assertEqual(events.get()[0]['type'], 'CPU')
459
        self.assertEqual(events.get()[0]['state'], 'WARNING')
460
        self.assertEqual(events.get()[0]['min'], 60)
461
        self.assertEqual(events.get()[0]['max'], 70)
462
        self.assertEqual(events.get()[0]['count'], 2)
463
        # Minimal event duration CPU reached (again)
464
        # but time between two events (min_interval) is too short
465
        # a merge will be done
466
        time.sleep(0.5)
467
        events.add('WARNING', 'CPU', 60)
468
        time.sleep(1)
469
        events.add('WARNING', 'CPU', 80)
470
        time.sleep(1)
471
        events.add('OK', 'CPU', 10)
472
        self.assertEqual(len(events.get()), 2)
473
        self.assertEqual(events.get()[0]['type'], 'CPU')
474
        self.assertEqual(events.get()[0]['state'], 'WARNING')
475
        self.assertEqual(events.get()[0]['min'], 60)
476
        self.assertEqual(events.get()[0]['max'], 80)
477
        self.assertEqual(events.get()[0]['count'], 4)
478
        # Clean WARNING events
479
        events.clean()
480
        self.assertEqual(len(events.get()), 1)
481
482
    def test_020_filter(self):
483
        """Test filter classes"""
484
        print('INFO: [TEST_020] Test filter')
485
        gf = GlancesFilter()
486
        gf.filter = '.*python.*'
487
        self.assertEqual(gf.filter, '.*python.*')
488
        self.assertEqual(gf.filter_key, None)
489
        self.assertTrue(gf.is_filtered({'name': 'python'}))
490
        self.assertTrue(gf.is_filtered({'name': '/usr/bin/python -m glances'}))
491
        self.assertFalse(gf.is_filtered({'noname': 'python'}))
492
        self.assertFalse(gf.is_filtered({'name': 'snake'}))
493
        gf.filter = 'username:nicolargo'
494
        self.assertEqual(gf.filter, 'nicolargo')
495
        self.assertEqual(gf.filter_key, 'username')
496
        self.assertTrue(gf.is_filtered({'username': 'nicolargo'}))
497
        self.assertFalse(gf.is_filtered({'username': 'notme'}))
498
        self.assertFalse(gf.is_filtered({'notuser': 'nicolargo'}))
499
        gfl = GlancesFilterList()
500
        gfl.filter = '.*python.*,username:nicolargo'
501
        self.assertTrue(gfl.is_filtered({'name': 'python is in the place'}))
502
        self.assertFalse(gfl.is_filtered({'name': 'snake is in the place'}))
503
        self.assertTrue(gfl.is_filtered({'name': 'snake is in the place', 'username': 'nicolargo'}))
504
        self.assertFalse(gfl.is_filtered({'name': 'snake is in the place', 'username': 'notme'}))
505
506
    def test_021_pretty_date(self):
507
        """Test pretty_date"""
508
        print('INFO: [TEST_021] pretty_date')
509
        self.assertEqual(pretty_date(datetime(2024, 1, 1, 12, 0), datetime(2024, 1, 1, 12, 0)), 'just now')
510
        self.assertEqual(pretty_date(datetime(2024, 1, 1, 11, 59), datetime(2024, 1, 1, 12, 0)), 'a min')
511
        self.assertEqual(pretty_date(datetime(2024, 1, 1, 11, 55), datetime(2024, 1, 1, 12, 0)), '5 mins')
512
        self.assertEqual(pretty_date(datetime(2024, 1, 1, 11, 0), datetime(2024, 1, 1, 12, 0)), 'an hour')
513
        self.assertEqual(pretty_date(datetime(2024, 1, 1, 0, 0), datetime(2024, 1, 1, 12, 0)), '12 hours')
514
        self.assertEqual(pretty_date(datetime(2023, 12, 20, 0, 0), datetime(2024, 1, 1, 12, 0)), 'a week')
515
        self.assertEqual(pretty_date(datetime(2023, 12, 5, 0, 0), datetime(2024, 1, 1, 12, 0)), '3 weeks')
516
        self.assertEqual(pretty_date(datetime(2023, 12, 1, 0, 0), datetime(2024, 1, 1, 12, 0)), 'a month')
517
        self.assertEqual(pretty_date(datetime(2023, 6, 1, 0, 0), datetime(2024, 1, 1, 12, 0)), '7 months')
518
        self.assertEqual(pretty_date(datetime(2023, 1, 1, 0, 0), datetime(2024, 1, 1, 12, 0)), 'an year')
519
        self.assertEqual(pretty_date(datetime(2020, 1, 1, 0, 0), datetime(2024, 1, 1, 12, 0)), '4 years')
520
521
    def test_094_thresholds(self):
522
        """Test thresholds classes"""
523
        print('INFO: [TEST_094] Thresholds')
524
        ok = GlancesThresholdOk()
525
        careful = GlancesThresholdCareful()
526
        warning = GlancesThresholdWarning()
527
        critical = GlancesThresholdCritical()
528
        self.assertTrue(ok < careful)
529
        self.assertTrue(careful < warning)
530
        self.assertTrue(warning < critical)
531
        self.assertFalse(ok > careful)
532
        self.assertEqual(ok, ok)
533
        self.assertEqual(str(ok), 'OK')
534
        thresholds = GlancesThresholds()
535
        thresholds.add('cpu_percent', 'OK')
536
        self.assertEqual(thresholds.get(stat_name='cpu_percent').description(), 'OK')
537
538
    def test_095_methods(self):
539
        """Test mandatories methods"""
540
        print('INFO: [TEST_095] Mandatories methods')
541
        mandatories_methods = ['reset', 'update']
542
        plugins_list = stats.getPluginsList()
543
        for plugin in plugins_list:
544
            for method in mandatories_methods:
545
                self.assertTrue(hasattr(stats.get_plugin(plugin), method), msg=f'{plugin} has no method {method}()')
546
547
    def test_096_views(self):
548
        """Test get_views method"""
549
        print('INFO: [TEST_096] Test views')
550
        plugins_list = stats.getPluginsList()
551
        for plugin in plugins_list:
552
            stats.get_plugin(plugin).get_raw()
553
            views_grab = stats.get_plugin(plugin).get_views()
554
            self.assertTrue(isinstance(views_grab, dict), msg=f'{plugin} view is not a dict')
555
556
    def test_097_attribute(self):
557
        """Test GlancesAttribute classes"""
558
        print('INFO: [TEST_097] Test attribute')
559
        # GlancesAttribute
560
        from glances.attribute import GlancesAttribute
561
562
        a = GlancesAttribute('a', description='ad', history_max_size=3)
563
        self.assertEqual(a.name, 'a')
564
        self.assertEqual(a.description, 'ad')
565
        a.description = 'adn'
566
        self.assertEqual(a.description, 'adn')
567
        a.value = 1
568
        a.value = 2
569
        self.assertEqual(len(a.history), 2)
570
        a.value = 3
571
        self.assertEqual(len(a.history), 3)
572
        a.value = 4
573
        # Check if history_max_size=3 is OK
574
        self.assertEqual(len(a.history), 3)
575
        self.assertEqual(a.history_size(), 3)
576
        self.assertEqual(a.history_len(), 3)
577
        self.assertEqual(a.history_value()[1], 4)
578
        self.assertEqual(a.history_mean(nb=3), 4.5)
579
580
    def test_098_history(self):
581
        """Test GlancesHistory classes"""
582
        print('INFO: [TEST_098] Test history')
583
        # GlancesHistory
584
        from glances.history import GlancesHistory
585
586
        h = GlancesHistory()
587
        h.add('a', 1, history_max_size=100)
588
        h.add('a', 2, history_max_size=100)
589
        h.add('a', 3, history_max_size=100)
590
        h.add('b', 10, history_max_size=100)
591
        h.add('b', 20, history_max_size=100)
592
        h.add('b', 30, history_max_size=100)
593
        self.assertEqual(len(h.get()), 2)
594
        self.assertEqual(len(h.get()['a']), 3)
595
        h.reset()
596
        self.assertEqual(len(h.get()), 2)
597
        self.assertEqual(len(h.get()['a']), 0)
598
599
    def test_099_output_bars(self):
600
        """Test quick look plugin.
601
602
        > bar.min_value
603
        0
604
        > bar.max_value
605
        100
606
        > bar.percent = -1
607
        > bar.percent
608
        0
609
        """
610
        print('INFO: [TEST_099] Test progress bar')
611
612
        bar = Bar(size=1)
613
        # Percent value can not be lower than min_value
614
        bar.percent = -1
615
        self.assertLessEqual(bar.percent, bar.min_value)
616
        # but... percent value can be higher than max_value
617
        bar.percent = 101
618
        self.assertLessEqual(bar.percent, 101)
619
620
        # Test display
621
        bar = Bar(size=50)
622
        bar.percent = 0
623
        self.assertEqual(bar.get(), '                                              0.0%')
624
        bar.percent = 70
625
        self.assertEqual(bar.get(), '|||||||||||||||||||||||||||||||              70.0%')
626
        bar.percent = 100
627
        self.assertEqual(bar.get(), '||||||||||||||||||||||||||||||||||||||||||||  100%')
628
        bar.percent = 110
629
        self.assertEqual(bar.get(), '|||||||||||||||||||||||||||||||||||||||||||| >100%')
630
631
    # Error in Github Action. Do not remove the comment.
632
    # def test_100_system_plugin_method(self):
633
    #     """Test system plugin methods"""
634
    #     print('INFO: [TEST_100] Test system plugin methods')
635
    #     self._common_plugin_tests('system')
636
637
    def test_101_cpu_plugin_method(self):
638
        """Test cpu plugin methods"""
639
        print('INFO: [TEST_100] Test cpu plugin methods')
640
        self._common_plugin_tests('cpu')
641
642
    @unittest.skipIf(WINDOWS, "Load average not available on Windows")
643
    def test_102_load_plugin_method(self):
644
        """Test load plugin methods"""
645
        print('INFO: [TEST_102] Test load plugin methods')
646
        self._common_plugin_tests('load')
647
648
    def test_103_mem_plugin_method(self):
649
        """Test mem plugin methods"""
650
        print('INFO: [TEST_103] Test mem plugin methods')
651
        self._common_plugin_tests('mem')
652
653
    def test_104_memswap_plugin_method(self):
654
        """Test memswap plugin methods"""
655
        print('INFO: [TEST_104] Test memswap plugin methods')
656
        self._common_plugin_tests('memswap')
657
658
    def test_105_network_plugin_method(self):
659
        """Test network plugin methods"""
660
        print('INFO: [TEST_105] Test network plugin methods')
661
        self._common_plugin_tests('network')
662
663
    # Error in Github Action. Do not remove the comment.
664
    # def test_106_diskio_plugin_method(self):
665
    #     """Test diskio plugin methods"""
666
    #     print('INFO: [TEST_106] Test diskio plugin methods')
667
    #     self._common_plugin_tests('diskio')
668
669
    def test_107_fs_plugin_method(self):
670
        """Test fs plugin methods"""
671
        print('INFO: [TEST_107] Test fs plugin methods')
672
        self._common_plugin_tests('fs')
673
674
    def test_200_views_hidden(self):
675
        """Test hide feature"""
676
        print('INFO: [TEST_200] Test views hidden feature')
677
        # Test will be done with the diskio plugin, first available interface (read_bytes fields)
678
        plugin = 'diskio'
679
        field = 'read_bytes_rate_per_sec'
680
        plugin_instance = stats.get_plugin(plugin)
681
        if len(plugin_instance.get_views()) == 0 or not test_config.get_bool_value(plugin, 'hide_zero', False):
682
            # No diskIO interface, test can not be done
683
            return
684
        # Get first disk interface
685
        key = list(plugin_instance.get_views().keys())[0]
686
        # Test
687
        ######
688
        # Init the stats
689
        plugin_instance.update()
690
        raw_stats = plugin_instance.get_raw()
691
        # Reset the views
692
        plugin_instance.set_views({})
693
        # Set field to 0 (should be hidden)
694
        raw_stats[0][field] = 0
695
        plugin_instance.set_stats(raw_stats)
696
        self.assertEqual(plugin_instance.get_raw()[0][field], 0)
697
        plugin_instance.update_views()
698
        self.assertTrue(plugin_instance.get_views()[key][field]['hidden'])
699
        # Set field to 0 (should be hidden)
700
        raw_stats[0][field] = 0
701
        plugin_instance.set_stats(raw_stats)
702
        self.assertEqual(plugin_instance.get_raw()[0][field], 0)
703
        plugin_instance.update_views()
704
        self.assertTrue(plugin_instance.get_views()[key][field]['hidden'])
705
        # Set field to 1 (should not be hidden)
706
        raw_stats[0][field] = 1
707
        plugin_instance.set_stats(raw_stats)
708
        self.assertEqual(plugin_instance.get_raw()[0][field], 1)
709
        plugin_instance.update_views()
710
        self.assertFalse(plugin_instance.get_views()[key][field]['hidden'])
711
        # Set field back to 0 (should not be hidden)
712
        raw_stats[0][field] = 0
713
        plugin_instance.set_stats(raw_stats)
714
        self.assertEqual(plugin_instance.get_raw()[0][field], 0)
715
        plugin_instance.update_views()
716
        self.assertFalse(plugin_instance.get_views()[key][field]['hidden'])
717
718
    # def test_700_secure(self):
719
    #     """Test secure functions"""
720
    #     print('INFO: [TEST_700] Secure functions')
721
722
    #     if WINDOWS:
723
    #         self.assertIn(secure_popen('echo TEST'), ['TEST\n', 'TEST\r\n'])
724
    #         self.assertIn(secure_popen('echo TEST1 && echo TEST2'), ['TEST1\nTEST2\n', 'TEST1\r\nTEST2\r\n'])
725
    #     else:
726
    #         self.assertEqual(secure_popen('echo -n TEST'), 'TEST')
727
    #         self.assertEqual(secure_popen('echo -n TEST1 && echo -n TEST2'), 'TEST1TEST2')
728
    #         # Make the test failed on Github (AssertionError: '' != 'FOO\n')
729
    #         # but not on my localLinux computer...
730
    #         # self.assertEqual(secure_popen('echo FOO | grep FOO'), 'FOO\n')
731
732
    def test_999_the_end(self):
733
        """Free all the stats"""
734
        print('INFO: [TEST_999] Free the stats')
735
        stats.end()
736
        self.assertTrue(True)
737
738
739
if __name__ == '__main__':
740
    unittest.main()
741