Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue:3897880:PDR exclusion list tests #217

Merged
merged 8 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .github/workflows/pdr_plugin_ci_workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: PDR Plugin CI Workflow

on:
push:
paths:
- 'plugins/pdr_deterministic_plugin/**'
jobs:
build:
runs-on: ubuntu-latest

env:
PYTHONPATH: '.:plugins/pdr_deterministic_plugin/ufm_sim_web_service'
PDRPATH: 'plugins/pdr_deterministic_plugin'

steps:
- name: Checkout code
uses: actions/checkout@main

- name: Set up Python
uses: actions/setup-python@main
with:
python-version: 3.9

- name: Install dependencies
run: |
pip install -r $PDRPATH/requirements.txt
pip install pylint
pip install pytest pytest-cov
vg12345 marked this conversation as resolved.
Show resolved Hide resolved

- name: Run PyLint
run: pylint --rcfile=$PDRPATH/.pylintrc $PDRPATH

- name: Run exclusion list class test
timeout-minutes: 5
run: pytest -s $PDRPATH/tests/exclude_list_class_tests.py --cov=$PDRPATH

- name: Test exclusion list REST API
timeout-minutes: 5
run: |
sudo bash $PDRPATH/.pytest/run_pdr_standalone_pytest.sh
echo "Test exclusion list REST API methods"
sleep 10
pytest -s $PDRPATH/tests/exclude_list_rest_api_tests.py --cov=$PDRPATH
echo "Terminating standalone PDR process"
pkill -9 -f isolation_algo.py 2>/dev/null || true

- name: Run full simulation test
timeout-minutes: 10
run: |
sudo bash $PDRPATH/.pytest/run_pdr_standalone_pytest.sh
echo "Starting simulated test"
python $PDRPATH/tests/simulation_telemetry.py
echo "Terminating standalone PDR process"
pkill -9 -f isolation_algo.py 2>/dev/null || true
vg12345 marked this conversation as resolved.
Show resolved Hide resolved
17 changes: 17 additions & 0 deletions plugins/pdr_deterministic_plugin/.pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[MASTER]
init-hook="import os, sys; sys.path.append(os.path.join(os.getcwd(), 'plugins', 'pdr_deterministic_plugin', 'src')); sys.path.append(os.path.join(os.getcwd(), 'utils'))"

[MAIN]
max-public-methods=100

[DESIGN]
max-attributes=10

[MESSAGES CONTROL]
disable=missing-module-docstring,missing-function-docstring,fixme

[FORMAT]
max-line-length=140

[BASIC]
min-public-methods=0
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash -x

PLUGIN_DIR="plugins/pdr_deterministic_plugin"
pip install -r $PLUGIN_DIR/requirements.txt >/dev/null 2>&1
vg12345 marked this conversation as resolved.
Show resolved Hide resolved

cp -r utils $PLUGIN_DIR/ufm_sim_web_service
cp -r utils $PLUGIN_DIR/tests

echo "Init PDR configuration file"
CONFIG_FILE="/config/pdr_deterministic.conf"
mkdir -p /config
cp -f $PLUGIN_DIR/build/config/pdr_deterministic.conf "$CONFIG_FILE"
sed -i -e 's/\nTEST_MODE=True\n//g' "$CONFIG_FILE"
echo -e '\n[Common]\nTEST_MODE=True\n' >> "$CONFIG_FILE"
vg12345 marked this conversation as resolved.
Show resolved Hide resolved
sed -i -e 's/DRY_RUN=False/DRY_RUN=True/g' "$CONFIG_FILE"
sed -i -e 's/INTERVAL=300/INTERVAL=10/g' "$CONFIG_FILE"
sed -i -e 's/CONFIGURED_TEMP_CHECK=False/CONFIGURED_TEMP_CHECK=True/g' "$CONFIG_FILE"
vg12345 marked this conversation as resolved.
Show resolved Hide resolved
sed -i -e 's/DEISOLATE_CONSIDER_TIME=5/DEISOLATE_CONSIDER_TIME=1/g' "$CONFIG_FILE"

"Terminating standalone PDR process"
pkill -9 -f isolation_algo.py 2>/dev/null || true
vg12345 marked this conversation as resolved.
Show resolved Hide resolved
sleep 10

echo "Starting standalone PDR process"
python $PLUGIN_DIR/ufm_sim_web_service/isolation_algo.py >/dev/null 2>&1 &
11 changes: 11 additions & 0 deletions plugins/pdr_deterministic_plugin/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#
# 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.
#
9 changes: 9 additions & 0 deletions plugins/pdr_deterministic_plugin/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
flask<=3.0.3
vg12345 marked this conversation as resolved.
Show resolved Hide resolved
numpy<=1.26.4
pandas<=2.2.2
pytest<=8.2.0
requests<=2.31.0
twisted<=22.1.0
flask_restful<=0.3.10
tzlocal<=4.2
jsonschema<=4.5.1
102 changes: 102 additions & 0 deletions plugins/pdr_deterministic_plugin/tests/exclude_list_class_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#
# 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.
#

import os
import tempfile
import time
from constants import PDRConstants as Constants
from exclude_list import ExcludeList, ExcludeListItem
from isolation_algo import create_logger


def get_logger():
"""
Return logger associated with log file in temporary directory
"""
log_name = os.path.basename(Constants.LOG_FILE)
log_path = os.path.join(tempfile.gettempdir(), log_name)
return create_logger(log_path)


def test_exclude_list_class_methods():
"""
Test exclude list class methods by direct calls
"""
print("\n") # Start tests output from new line

excluded_ports = [
ExcludeListItem("0123456789aaabbb_1", 0), # Add forever
ExcludeListItem("9876543210cccddd_2", 30), # Add for 30 seconds
ExcludeListItem("3456789012eeefff_3", 0) # Add forever
]

# Create exclusion list and ensure it's empty
exclude_list = ExcludeList(get_logger())
items = exclude_list.items()
assert not items
print(" - test: create exclusion list and ensure it's empty -- PASS")

# Add ports to excluded list
for port in excluded_ports:
exclude_list.add(port.port_name, port.ttl_seconds)

# Test exclusion list size
items = exclude_list.items()
assert items and len(items) == len(excluded_ports)
print(" - test: add ports to exclusion list -- PASS")

# Test 'contains' method
for port in excluded_ports:
assert exclude_list.contains(port.port_name)
print(" - test: exclusion list 'contains' method -- PASS")

# Test exclusion list content
for (index, item) in enumerate(items):
assert item.port_name == excluded_ports[index].port_name
assert item.ttl_seconds == excluded_ports[index].ttl_seconds
print(" - test: exclusion list content -- PASS")

# Test auto-remove of second port after TTL is expired
auto_remove_port = excluded_ports[1]
time.sleep(auto_remove_port.ttl_seconds + 1)
assert not exclude_list.contains(auto_remove_port.port_name)
print(" - test: auto-remove of port from exclusion list after TTL is expired -- PASS")

# Test excluded list size
items = exclude_list.items()
assert items and len(items) == (len(excluded_ports) - 1)

# Test excluded list content
for port in excluded_ports:
if port.port_name != auto_remove_port.port_name:
assert exclude_list.contains(port.port_name)
print(" - test: exclusion list content -- PASS")

# Test forced remove of third port
remove_port = excluded_ports[2]
exclude_list.remove(port.port_name)
assert not exclude_list.contains(remove_port.port_name)
print(" - test: forced remove of port from exclusion list -- PASS")

# Test excluded list size
items = exclude_list.items()
assert items and len(items) == (len(excluded_ports) - 2)

# Test excluded list content
for port in excluded_ports:
if port.port_name != remove_port.port_name and port.port_name != auto_remove_port.port_name:
assert exclude_list.contains(port.port_name)
print(" - test: exclusion list content -- PASS")


if __name__ == '__main__':
test_exclude_list_class_methods()
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#
# 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.
#

import http
import json
import random
import time
import requests


def generate_port_name():
"""
Generate port name
"""
port_guid = f'{random.randrange(16**16):016x}'
port_num = random.randint(10, 99)
vg12345 marked this conversation as resolved.
Show resolved Hide resolved
return f'{port_guid}_{port_num}'


def test_exclude_list_rest_api():
"""
Test exclude list via plugin REST API
"""
print("\n") # Start tests output from new line

url = "http://127.0.0.1:8977/excluded"

excluded_ports = [
(generate_port_name(), 0), # Add forever
(generate_port_name(), 30), # Add for 30 seconds
(generate_port_name(), 0) # Add forever
]

# Get (empty) list content
response = requests.get(url, timeout=5)
assert response.status_code == http.client.OK
assert all(char.isspace() for char in response.text)
print(" - test: get exclusion list and ensure it's empty -- PASS")

# Add ports to excluded list
response = requests.put(url, data=json.dumps(excluded_ports), timeout=5)
assert response.status_code == http.client.OK
for pair in excluded_ports:
port_name = pair[0]
assert port_name in response.text
print(" - test: add ports to exclusion list -- PASS")

# Test exclusion list content
response = requests.get(url, timeout=5)
assert response.status_code == http.client.OK
for pair in excluded_ports:
port_name = pair[0]
assert port_name in response.text
print(" - test: get added ports from exclusion list -- PASS")

# Wait until second port TTL is expired
ttl_seconds = excluded_ports[1][1]
time.sleep(ttl_seconds + 1)

# Test auto-remove of second port after TTL is expired
response = requests.get(url, timeout=5)
assert response.status_code == http.client.OK
for (index, pair) in enumerate(excluded_ports):
port_name = pair[0]
if index == 1:
assert port_name not in response.text
else:
assert port_name in response.text
print(" - test: auto-remove of port from exclusion list after TTL is expired -- PASS")

# Test forced remove of third port
port_name = excluded_ports[2][0]
response = requests.delete(url, data=json.dumps([port_name]), timeout=5)
assert response.status_code == http.client.OK
assert f'{port_name} removed' in response.text
print(" - test: forced remove of port from exclusion list -- PASS")

# Test exclusion list content
response = requests.get(url, timeout=5)
for (index, pair) in enumerate(excluded_ports):
port_name = excluded_ports[index][0]
if index == 1 or index == 2:
assert port_name not in response.text
else:
assert port_name in response.text
print(" - test: exclusion list content -- PASS")


if __name__ == '__main__':
test_exclude_list_rest_api()
Loading