Skip to content

Commit

Permalink
Add memory leak unitary test
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolargo committed Dec 29, 2024
1 parent 6124da2 commit 797b0d0
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 69 deletions.
47 changes: 22 additions & 25 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:

Expand All @@ -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
Expand All @@ -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
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions glances/plugins/gpu/cards/nvidia.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@
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

Expand Down
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
18 changes: 18 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
The chromedriver command line should be in your path (/usr/bin)
"""

import logging
import os
import shlex
import subprocess
Expand All @@ -32,6 +33,11 @@
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)
Expand All @@ -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'):
Expand Down
41 changes: 0 additions & 41 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,47 +712,6 @@ def test_200_views_hidden(self):
# # 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')
Expand Down
35 changes: 35 additions & 0 deletions tests/test_memoryleak.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env python
#
# Glances - An eye on your system
#
# SPDX-FileCopyrightText: 2024 Nicolas Hennion <[email protected]>
#
# 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'
2 changes: 1 addition & 1 deletion tests/test_perf.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

def test_perf_update(glances_stats):
"""
Test Glances home page title.
Test Glances perf.
"""
perf_timer = Timer(3)
counter = 0
Expand Down

0 comments on commit 797b0d0

Please sign in to comment.