Test Failed
Push — develop ( e8563a...4ddff4 )
by Nicolas
01:14 queued 35s
created

unittest-core.TestGlances.test_800_memory_leak()   B

Complexity

Conditions 7

Size

Total Lines 39
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

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