test_core.TestGlances.test_011_folders()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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