diff --git a/.github/workflows/ufm_log_analyzer_ci_workflow.yml b/.github/workflows/ufm_log_analyzer_ci_workflow.yml index 8a73689b..d487d96b 100644 --- a/.github/workflows/ufm_log_analyzer_ci_workflow.yml +++ b/.github/workflows/ufm_log_analyzer_ci_workflow.yml @@ -1,14 +1,14 @@ name: Ufm log analyzer CI Workflow on: - push: + pull_request: paths: - 'plugins/ufm_log_analyzer_plugin/**' - '.github/workflows/ufm_log_analyzer_ci_workflow.yml' jobs: pylint: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout code @@ -34,7 +34,7 @@ jobs: pylint --rcfile=src/loganalyze/.pylintrc src/loganalyze ruff: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout code @@ -53,3 +53,29 @@ jobs: pip install ruff==0.7.3 ruff format --diff --check src/loganalyze + + pytest: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.9 + + - name: Run Pytest + run: | + SCRIPT_DIR="plugins/ufm_log_analyzer_plugin" + # Set PYTHONPATH to include src directory and two levels up for utils + PYTHONPATH="$(realpath $SCRIPT_DIR/src):$(realpath $SCRIPT_DIR/../../)" + export PYTHONPATH + + cd $SCRIPT_DIR + + pip install -r src/loganalyze/requirements.txt + pip install pytest==8.3.4 + + pytest unit_tests \ No newline at end of file diff --git a/plugins/ufm_log_analyzer_plugin/README.md b/plugins/ufm_log_analyzer_plugin/README.md index 05694bae..dead48d5 100644 --- a/plugins/ufm_log_analyzer_plugin/README.md +++ b/plugins/ufm_log_analyzer_plugin/README.md @@ -75,4 +75,17 @@ This logic will show links that: ![Tool flow](img/loganalzer.png) +## Testing +There is a folder named `unit_tests`, this folder contains some unit tests, to run the tests follow these steps: + +1. Inside the project virtual environment, make sure you have `pytest` installed. + If not, you can install it using `pip`: + ```bash + python3 -m pip install pytest +2. Navigate to the root directory of the log analyzer project: + ```bash + cd plugins/ufm_log_analyzer_plugin +3. Run `pytest` to execute the tests: + ```bash + pytest unit_tests \ No newline at end of file diff --git a/plugins/ufm_log_analyzer_plugin/src/loganalyze/.pylintrc b/plugins/ufm_log_analyzer_plugin/src/loganalyze/.pylintrc index 1f8ebad5..fe4d56ae 100644 --- a/plugins/ufm_log_analyzer_plugin/src/loganalyze/.pylintrc +++ b/plugins/ufm_log_analyzer_plugin/src/loganalyze/.pylintrc @@ -8,4 +8,7 @@ disable=missing-function-docstring, [DESIGN] max-locals=20 -max-args=8 \ No newline at end of file +max-args=8 + +[unit_tests/*] +disable=protected-access \ No newline at end of file diff --git a/plugins/ufm_log_analyzer_plugin/src/loganalyze/log_analyzers/base_analyzer.py b/plugins/ufm_log_analyzer_plugin/src/loganalyze/log_analyzers/base_analyzer.py index a95ca640..82ef67c8 100644 --- a/plugins/ufm_log_analyzer_plugin/src/loganalyze/log_analyzers/base_analyzer.py +++ b/plugins/ufm_log_analyzer_plugin/src/loganalyze/log_analyzers/base_analyzer.py @@ -185,7 +185,11 @@ def __init__( ): super().__init__(dest_image_path) dataframes = [pd.read_csv(ufm_log) for ufm_log in logs_csvs] - df = pd.concat(dataframes, ignore_index=True) + if dataframes: + df = pd.concat(dataframes, ignore_index=True) + else: + df = pd.DataFrame() # Return an empty DataFrame if dataframes is empty + if sort_timestamp: df[DataConstants.TIMESTAMP] = pd.to_datetime(df[DataConstants.TIMESTAMP]) max_timestamp = df[DataConstants.TIMESTAMP].max() diff --git a/plugins/ufm_log_analyzer_plugin/unit_tests/__init__.py b/plugins/ufm_log_analyzer_plugin/unit_tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/plugins/ufm_log_analyzer_plugin/unit_tests/conftest.py b/plugins/ufm_log_analyzer_plugin/unit_tests/conftest.py new file mode 100644 index 00000000..cef7aee0 --- /dev/null +++ b/plugins/ufm_log_analyzer_plugin/unit_tests/conftest.py @@ -0,0 +1,19 @@ +# @copyright: +# Copyright © 2013-2024 NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. + +# This software product is a proprietary product of Nvidia Corporation and its affiliates +# (the "Company") and all right, title, and interest in and to the +# software product, including all associated intellectual property rights, +# are and shall remain exclusively with the Company. + +# This software product is governed by the End User License Agreement +# provided with the software product. + +# @author: Miryam Schwartz +# @date: Dec 08, 2024 + +import sys +import os + +sys.path.append(os.getcwd() + "/src") # Add the src directory containing loganalyze +sys.path.append("/".join(os.getcwd().split("/")[:-2])) # Add the root project directory diff --git a/plugins/ufm_log_analyzer_plugin/unit_tests/test_ibdiagnet_log_analyzer.py b/plugins/ufm_log_analyzer_plugin/unit_tests/test_ibdiagnet_log_analyzer.py new file mode 100644 index 00000000..ac4f3ee4 --- /dev/null +++ b/plugins/ufm_log_analyzer_plugin/unit_tests/test_ibdiagnet_log_analyzer.py @@ -0,0 +1,36 @@ +# @copyright: +# Copyright © 2013-2024 NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. + +# This software product is a proprietary product of Nvidia Corporation and its affiliates +# (the "Company") and all right, title, and interest in and to the +# software product, including all associated intellectual property rights, +# are and shall remain exclusively with the Company. + +# This software product is governed by the End User License Agreement +# provided with the software product. + +# @author: Miryam Schwartz +# @date: Dec 08, 2024 + +import pytest + +from loganalyze.log_analyzers.ibdiagnet_log_analyzer import IBDIAGNETLogAnalyzer + +# Define a test-specific subclass +class TestIBDIAGNETLogAnalyzer(IBDIAGNETLogAnalyzer): + def __init__(self, fabric_size_data): + # Do not call the parent constructor, set up only what's needed for the test + self._log_data_sorted = fabric_size_data + +@pytest.fixture +def fabric_size_data(): + # Shared mock data + return {"switch_count": 10, "link_count": 50} + +@pytest.fixture +def analyzer(fabric_size_data): + return TestIBDIAGNETLogAnalyzer(fabric_size_data) + +def test_get_fabric_size(analyzer, fabric_size_data): + result = analyzer.get_fabric_size() + assert result == fabric_size_data, "get_fabric_size should return _log_data_sorted" diff --git a/plugins/ufm_log_analyzer_plugin/unit_tests/test_ufm_top_analyzer.py b/plugins/ufm_log_analyzer_plugin/unit_tests/test_ufm_top_analyzer.py new file mode 100644 index 00000000..3ce677da --- /dev/null +++ b/plugins/ufm_log_analyzer_plugin/unit_tests/test_ufm_top_analyzer.py @@ -0,0 +1,39 @@ +# @copyright: +# Copyright © 2013-2024 NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. + +# This software product is a proprietary product of Nvidia Corporation and its affiliates +# (the "Company") and all right, title, and interest in and to the +# software product, including all associated intellectual property rights, +# are and shall remain exclusively with the Company. + +# This software product is governed by the End User License Agreement +# provided with the software product. + +# @author: Miryam Schwartz +# @date: Dec 08, 2024 + +import pytest + +from loganalyze.log_analyzers.ufm_top_analyzer import UFMTopAnalyzer + +@pytest.fixture +def analyzer(): + # Fixture to initialize the analyzer object + return UFMTopAnalyzer() + +def test_add_analyzer(analyzer): + mock_analyzer_1 = "Analyzer1" + mock_analyzer_2 = "Analyzer2" + + # Initially, the list should be empty + assert len(analyzer._analyzers) == 0 + + # Add first analyzer and check the length + analyzer.add_analyzer(mock_analyzer_1) + assert len(analyzer._analyzers) == 1 + assert mock_analyzer_1 in analyzer._analyzers + + # Add second analyzer and check the updated length + analyzer.add_analyzer(mock_analyzer_2) + assert len(analyzer._analyzers) == 2 + assert mock_analyzer_2 in analyzer._analyzers