test_core.TestGlances.test_022_plugin_dag()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 10
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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