diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3ad0c9c9..88814b18 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -51,7 +51,6 @@ jobs: - name: Install dependencies run: | - python -m pip install --upgrade pip if [ -f dev-requirements.txt ]; then python -m pip install -r dev-requirements.txt; fi if [ -f requirements.txt ]; then python -m pip install -r requirements.txt; fi @@ -64,33 +63,32 @@ jobs: # Installed c:\hostedtoolcache\windows\python\3.9.13\x64\lib\site-packages\exceptiongroup-1.2.1-py3.9.egg # error: h11 0.14.0 is installed but h11<0.13,>=0.11 is required by {'httpcore'} # Error: Process completed with exit code 1. - # test-windows: + test-windows: - # # https://github.com/actions/runner-images?tab=readme-ov-file#available-images - # runs-on: windows-2022 - # strategy: - # matrix: - # python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] - # steps: + # https://github.com/actions/runner-images?tab=readme-ov-file#available-images + runs-on: windows-2022 + strategy: + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + steps: - # - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - # - name: Set up Python ${{ matrix.python-version }} - # uses: actions/setup-python@v5 - # with: - # python-version: ${{ matrix.python-version }} - # cache: 'pip' + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' - # - name: Install dependencies - # run: | - # python -m pip install --upgrade pip - # if (Test-Path -PathType Leaf "dev-requirements.txt") { python -m pip install -r dev-requirements.txt } - # if (Test-Path -PathType Leaf "requirements.txt") { python -m pip install -r requirements.txt } - # pip install . + - name: Install dependencies + run: | + if (Test-Path -PathType Leaf "dev-requirements.txt") { python -m pip install -r dev-requirements.txt } + if (Test-Path -PathType Leaf "requirements.txt") { python -m pip install -r requirements.txt } + pip install . - # - name: Unitary tests - # run: | - # python -m pytest ./tests/test_core.py + - name: Unitary tests + run: | + python -m pytest ./tests/test_core.py test-macos: @@ -114,7 +112,6 @@ jobs: - name: Install dependencies run: | - python -m pip install --upgrade pip if [ -f dev-requirements.txt ]; then python -m pip install -r dev-requirements.txt; fi if [ -f requirements.txt ]; then python -m pip install -r requirements.txt; fi @@ -137,7 +134,7 @@ jobs: # with: # usesh: true # prepare: | - # pkg install -y python3 py-pip + # pkg install -y python3 # run: | # set -e -x # python3 -m pip install pytest diff --git a/Makefile b/Makefile index e1ea6a12..959c03c2 100644 --- a/Makefile +++ b/Makefile @@ -91,6 +91,9 @@ test: ## Run All unit tests test-core: ## Run Core unit tests $(PYTEST) tests/test_core.py +test-memoryleak: ## Run Memory-leak unit tests + $(PYTEST) tests/test_memoryleak.py + test-perf: ## Run Perf unit tests $(PYTEST) tests/test_perf.py diff --git a/glances/plugins/gpu/cards/nvidia.py b/glances/plugins/gpu/cards/nvidia.py index 52d2e53b..1e4bee68 100644 --- a/glances/plugins/gpu/cards/nvidia.py +++ b/glances/plugins/gpu/cards/nvidia.py @@ -31,11 +31,11 @@ try: except OSError: nvidia_gpu_enable = False # NNVML_LIB lib not found (NVidia driver not installed) - logger.warning(f"NVML Shared Library ({NVML_LIB}) not Found, Nvidia GPU plugin is disabled") + logger.debug(f"NVML Shared Library ({NVML_LIB}) not Found, Nvidia GPU plugin is disabled") except Exception as e: nvidia_gpu_enable = False # Display warning message if import KeyError - logger.warning(f"Missing Python Lib ({e}), Nvidia GPU plugin is disabled") + logger.debug(f"Missing Python Lib ({e}), Nvidia GPU plugin is disabled") else: nvidia_gpu_enable = True diff --git a/pyproject.toml b/pyproject.toml index 7ebd2fc4..cceca831 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -236,3 +236,9 @@ max-complexity = 21 [build-system] build-backend = "setuptools.build_meta" requires = ["setuptools>=68"] + +[tool.pytest.ini_options] +log_cli = true +log_level = "INFO" +#log_cli_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)" +#log_cli_date_format = "%Y-%m-%d %H:%M:%S" diff --git a/tests/conftest.py b/tests/conftest.py index c3fdd630..644852db 100755 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -15,6 +15,7 @@ $ sudo apt install chromium-chromedriver The chromedriver command line should be in your path (/usr/bin) """ +import logging import os import shlex import subprocess @@ -32,6 +33,11 @@ SERVER_PORT = 61234 URL = f"http://localhost:{SERVER_PORT}" +@pytest.fixture(scope="session") +def logger(): + return logging.getLogger(__name__) + + @pytest.fixture(scope="session") def glances_stats(): core = GlancesMain(args_begin_at=2) @@ -40,6 +46,18 @@ def glances_stats(): stats.end() +@pytest.fixture(scope="session") +def glances_stats_no_history(): + core = GlancesMain(args_begin_at=2) + args = core.get_args() + args.time = 1 + args.cached_time = 1 + args.disable_history = True + stats = GlancesStats(config=core.get_config(), args=args) + yield stats + stats.end() + + @pytest.fixture(scope="session") def glances_webserver(): if os.path.isfile('./venv/bin/python'): diff --git a/tests/test_core.py b/tests/test_core.py index 69776352..1a429251 100755 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -712,47 +712,6 @@ class TestGlances(unittest.TestCase): # # but not on my localLinux computer... # # self.assertEqual(secure_popen('echo FOO | grep FOO'), 'FOO\n') - # def test_800_memory_leak(self): - # """Memory leak check""" - # import tracemalloc - - # print('INFO: [TEST_800] Memory leak check') - # tracemalloc.start() - # # 3 iterations just to init the stats and fill the memory - # for _ in range(3): - # stats.update() - - # # Start the memory leak check - # snapshot_begin = tracemalloc.take_snapshot() - # for _ in range(3): - # stats.update() - # snapshot_end = tracemalloc.take_snapshot() - # snapshot_diff = snapshot_end.compare_to(snapshot_begin, 'filename') - # memory_leak = sum([s.size_diff for s in snapshot_diff]) - # print(f'INFO: Memory leak: {memory_leak} bytes') - - # # snapshot_begin = tracemalloc.take_snapshot() - # for _ in range(30): - # stats.update() - # snapshot_end = tracemalloc.take_snapshot() - # snapshot_diff = snapshot_end.compare_to(snapshot_begin, 'filename') - # memory_leak = sum([s.size_diff for s in snapshot_diff]) - # print(f'INFO: Memory leak: {memory_leak} bytes') - - # # snapshot_begin = tracemalloc.take_snapshot() - # for _ in range(300): - # stats.update() - # snapshot_end = tracemalloc.take_snapshot() - # snapshot_diff = snapshot_end.compare_to(snapshot_begin, 'filename') - # memory_leak = sum([s.size_diff for s in snapshot_diff]) - # print(f'INFO: Memory leak: {memory_leak} bytes') - # snapshot_top = snapshot_end.compare_to(snapshot_begin, 'traceback') - # print("Memory consumption (top 5):") - # for stat in snapshot_top[:5]: - # print(stat) - # for line in stat.traceback.format(): - # print(line) - def test_999_the_end(self): """Free all the stats""" print('INFO: [TEST_999] Free the stats') diff --git a/tests/test_memoryleak.py b/tests/test_memoryleak.py new file mode 100755 index 00000000..f4d53e67 --- /dev/null +++ b/tests/test_memoryleak.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# +# Glances - An eye on your system +# +# SPDX-FileCopyrightText: 2024 Nicolas Hennion +# +# SPDX-License-Identifier: LGPL-3.0-only +# + +"""Glances unitary tests suite for Glances memory leak.""" + +import tracemalloc + + +def test_memoryleak(glances_stats_no_history, logger): + """ + Test Glances memory leak. + """ + tracemalloc.start() + # First iterations just to init the stats and fill the memory + logger.info('Please wait test is filling memory with stats') + iteration = 100 + for _ in range(iteration): + glances_stats_no_history.update() + + # Then iteration to measure memory leak + logger.info('Please wait test if a memory leak is detected') + iteration = 20 + snapshot_begin = tracemalloc.take_snapshot() + for _ in range(iteration): + glances_stats_no_history.update() + snapshot_end = tracemalloc.take_snapshot() + snapshot_diff = snapshot_end.compare_to(snapshot_begin, 'filename') + memory_leak = sum([s.size_diff for s in snapshot_diff]) // iteration + assert memory_leak < 1000, f'Memory leak: {memory_leak} bytes' diff --git a/tests/test_perf.py b/tests/test_perf.py index 6b0caa81..d9dfb656 100755 --- a/tests/test_perf.py +++ b/tests/test_perf.py @@ -14,7 +14,7 @@ from glances.timer import Timer def test_perf_update(glances_stats): """ - Test Glances home page title. + Test Glances perf. """ perf_timer = Timer(3) counter = 0