diff options
author | xebd <xeb@mail.ru> | 2022-09-12 10:56:47 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-12 10:56:47 +0300 |
commit | 28fe4de9441aa9d0c42c010e8eef5b1a19122c9d (patch) | |
tree | ecefcafbeb9c9610ed3cf8c30a238b9168bba3bb | |
parent | 25c72614bf8106b0e4f71e2bce70514b03858463 (diff) | |
parent | 127b1de95923fccdfdc892c20f931d364e099f4b (diff) | |
download | accel-ppp-28fe4de9441aa9d0c42c010e8eef5b1a19122c9d.tar.gz accel-ppp-28fe4de9441aa9d0c42c010e8eef5b1a19122c9d.zip |
Merge pull request #61 from svlobanov/tests2
add tests and ci workflow for running tests
27 files changed, 1470 insertions, 0 deletions
diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml new file mode 100644 index 00000000..f9cf1b84 --- /dev/null +++ b/.github/workflows/run-tests.yml @@ -0,0 +1,305 @@ +name: Run tests + +on: + workflow_dispatch: + pull_request: + push: + branches: + - master + +jobs: + Test-in-Qemu: + #if: ${{ false }} # disable for now + runs-on: ubuntu-latest + name: Test in Qemu (${{ matrix.distro }}) + strategy: + fail-fast: false + matrix: + include: + - distro: Ubuntu-22.04 + image: https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img + untar: false + format: qcow2 + + - distro: Ubuntu-20.04 + image: https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img + untar: false + format: qcow2 + + - distro: Ubuntu-18.04 + image: https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img + untar: false + format: qcow2 + + - distro: Debian12 + image: https://cloud.debian.org/images/cloud/bookworm/daily/latest/debian-12-generic-amd64-daily.tar.xz + untar: true + format: raw + + - distro: Debian11 + image: https://cdimage.debian.org/images/cloud/bullseye/latest/debian-11-generic-amd64.tar.xz + untar: true + format: raw + + - distro: Debian10 + image: https://cloud.debian.org/images/cloud/buster/latest/debian-10-generic-amd64.tar.xz + untar: true + format: raw + + steps: + - name: Check out repository code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + path: "accel-ppp" + - name: Install qemu and required tools + run: > + sudo apt update && + sudo apt -y install qemu-system-x86 qemu-utils cloud-image-utils cpu-checker cloud-image-utils wget openssh-client screen + - name: Check kvm support (fail is ok) + run: sudo kvm-ok || exit 0 + - name: Prepare cloud-init image disk + run: | + ssh-keygen -t ed25519 -q -N "" -f ssh-key + echo "instance-id: $(uuidgen || echo i-abcdefg)" > init-meta + echo "#cloud-config" > init-data + echo "package_update: true" >> init-data + echo "package_upgrade: true" >> init-data + echo "package_reboot_if_required: false" >> init-data + echo "users:" >> init-data + echo " - default" >> init-data + echo " - name: user" >> init-data + echo " shell: /bin/bash" >> init-data + echo " sudo: ALL=(ALL) NOPASSWD:ALL" >> init-data + echo " ssh_authorized_keys:" >> init-data + echo " - "`cat ssh-key.pub` >> init-data + echo "power_state:">> init-data + echo " mode: poweroff">> init-data + cat init-data + cloud-localds init.img init-data init-meta + - name: Download, unpack and resize target OS cloud image + if: ${{ matrix.untar }} + run: | + wget -nv ${{ matrix.image }} + mkdir img + tar -xf *.tar.xz -C img + qemu-img resize -f ${{ matrix.format }} img/`ls -1 img` +2G + - name: Download and resize target OS cloud image + if: ${{ !matrix.untar }} + run: | + mkdir img + wget -nv ${{ matrix.image }} -O img/image + qemu-img resize -f ${{ matrix.format }} img/`ls -1 img` +2G + - name: Run target OS first time (for cloud-init actions) + run: sudo qemu-system-x86_64 -m 4096 -nographic -drive format=${{ matrix.format }},file=img/`ls -1 img` -drive format=raw,file=init.img + - name: Run target OS + run: sudo screen -dmS qemu qemu-system-x86_64 -net nic -net user,hostfwd=tcp::2222-:22 -m 4096 -nographic -drive format=${{ matrix.format }},file=img/`ls -1 img` + - name: Check that target OS is running + run: | + sleep 1 + sudo screen -ls + - name: Wait for ssh connection + timeout-minutes: 30 + run: > + while ! ssh -o StrictHostKeyChecking=accept-new -p2222 -o ConnectTimeout=5 -i ssh-key user@localhost "exit 0"; + do + echo "Trying to establish ssh connection"; + sleep 5; + done; + cat ~/.ssh/known_hosts + - name: Display free space, current dir, kernel version and test sudo + run: | + ssh -i ssh-key -p2222 user@localhost "df -h" + ssh -i ssh-key -p2222 user@localhost "pwd" + ssh -i ssh-key -p2222 user@localhost "uname -a" + ssh -i ssh-key -p2222 user@localhost "sudo cat /etc/passwd" + - name: Install build tools (on target OS) + run: > + ssh -i ssh-key -p2222 user@localhost "sudo apt -y install + git build-essential cmake gcc linux-headers-\`uname -r\` + libpcre3-dev libssl-dev liblua5.1-0-dev kmod python3-pip + iproute2 ppp pppoe isc-dhcp-client timelimit && + sudo pip3 install pytest pytest-dependency gcovr" + - name: Copy source code to target OS + run: | + tar -Jcf accel-ppp.tar.xz accel-ppp + scp -i ssh-key -P2222 accel-ppp.tar.xz user@localhost: + ssh -i ssh-key -p2222 user@localhost "tar -xf accel-ppp.tar.xz" + - name: Build accel-ppp + run: > + ssh -i ssh-key -p2222 user@localhost "cd accel-ppp && + mkdir build && cd build && + cmake -DBUILD_IPOE_DRIVER=TRUE -DBUILD_VLAN_MON_DRIVER=TRUE -DCMAKE_INSTALL_PREFIX=/usr + -DKDIR=/usr/src/linux-headers-\`uname -r\` + -DLUA=TRUE -DSHAPER=TRUE -DRADIUS=TRUE .. && + make && sudo make install" + + - name: Run tests (not related to ipoe and vlan_mon drivers) + timeout-minutes: 5 + run: > + ssh -i ssh-key -p2222 user@localhost "cd accel-ppp/tests && + sudo python3 -m pytest -Wall -v -m \"not ipoe_driver and not vlan_mon_driver\"" + - name: Display processes and dmesg after tests + if: ${{ always() }} + run: > + ssh -i ssh-key -p2222 user@localhost "ps aux | grep accel- && + sudo dmesg" + + - name: Insert ipoe kernel module + run: > + ssh -i ssh-key -p2222 user@localhost "cd accel-ppp && + sudo insmod build/drivers/ipoe/driver/ipoe.ko && + lsmod | grep ipoe " + + - name: Run tests (not related to vlan_mon drivers) + timeout-minutes: 5 + if: ${{ always() }} + run: > + ssh -i ssh-key -p2222 user@localhost "cd accel-ppp/tests && + sudo python3 -m pytest -Wall -v -m \"not vlan_mon_driver\"" + - name: Display processes and dmesg after tests + if: ${{ always() }} + run: > + ssh -i ssh-key -p2222 user@localhost "ps aux | grep accel- && + sudo dmesg" + + - name: Insert vlan_mon kernel module + run: > + ssh -i ssh-key -p2222 user@localhost "cd accel-ppp && + sudo insmod build/drivers/vlan_mon/driver/vlan_mon.ko && + lsmod | grep vlan_mon" + + - name: Run tests (all) + timeout-minutes: 5 + if: ${{ always() }} + run: > + ssh -i ssh-key -p2222 user@localhost "cd accel-ppp/tests && + sudo python3 -m pytest -Wall -v" + - name: Display processes and dmesg after tests + if: ${{ always() }} + run: > + ssh -i ssh-key -p2222 user@localhost "ps aux | grep accel- && + sudo dmesg" + + Test-in-GH: + #if: ${{ false }} # disable for now + strategy: + fail-fast: false + matrix: + distro: ["ubuntu-22.04", "ubuntu-20.04"] + + runs-on: ${{ matrix.distro }} + steps: + - name: Install build tools (using apt) + run: > + sudo apt update && + sudo apt -y install git build-essential cmake gcc linux-headers-`uname -r` + libpcre3-dev libssl-dev liblua5.1-0-dev kmod python3-pip + iproute2 ppp pppoe isc-dhcp-client + + - name: Install testing tools (using pip) + run: > + sudo pip3 install pytest pytest-dependency gcovr + + - name: Check out repository code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: mkdir build + run: mkdir build + + - name: cmake (with coverage) + working-directory: ./build + run: > + cmake -DBUILD_IPOE_DRIVER=TRUE -DBUILD_VLAN_MON_DRIVER=TRUE -DCMAKE_INSTALL_PREFIX=/usr + -DKDIR=/usr/src/linux-headers-`uname -r` + -DLUA=TRUE -DSHAPER=TRUE -DRADIUS=TRUE .. + + - name: make && make install + working-directory: ./build + run: make && sudo make install + + - name: Insert and check kernel modules (ipoe and vlan-mon) + # if: ${{ false }} + run: | + sudo insmod build/drivers/vlan_mon/driver/vlan_mon.ko + sudo insmod build/drivers/ipoe/driver/ipoe.ko + lsmod | grep ipoe + lsmod | grep vlan_mon + + - name: Run tests + timeout-minutes: 5 + working-directory: ./tests + run: sudo python3 -m pytest -Wall -v + + Test-in-GH-Coverage: + #if: ${{ false }} # disable for now + strategy: + fail-fast: false + matrix: + distro: ["ubuntu-22.04", "ubuntu-20.04"] + + runs-on: ${{ matrix.distro }} + steps: + - name: Install build tools (using apt) + run: > + sudo apt update && + sudo apt -y install git build-essential cmake gcc linux-headers-`uname -r` + libpcre3-dev libssl-dev liblua5.1-0-dev kmod python3-pip + iproute2 ppp pppoe isc-dhcp-client + + - name: Install testing tools (using pip) + run: > + sudo pip3 install pytest pytest-dependency gcovr + + - name: Check out repository code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: mkdir build + run: mkdir build + + - name: cmake (with coverage) + working-directory: ./build + run: > + cmake -DBUILD_IPOE_DRIVER=TRUE -DBUILD_VLAN_MON_DRIVER=TRUE -DCMAKE_INSTALL_PREFIX=/usr + -DKDIR=/usr/src/linux-headers-`uname -r` + -DLUA=TRUE -DSHAPER=TRUE -DRADIUS=TRUE + -DCMAKE_C_FLAGS="--coverage -O0" .. + + - name: make && make install + working-directory: ./build + run: make && sudo make install + + - name: Insert and check kernel modules (ipoe and vlan-mon) + # if: ${{ false }} + run: | + sudo insmod build/drivers/vlan_mon/driver/vlan_mon.ko + sudo insmod build/drivers/ipoe/driver/ipoe.ko + lsmod | grep ipoe + lsmod | grep vlan_mon + + - name: Run tests (for coverage report) (fail is ok) + timeout-minutes: 5 + working-directory: ./tests + run: sudo python3 -m pytest -Wall -v || exit 0 + + - name: Generate coverage reports (default(txt), csv, html) + run: | + mkdir -p tests/report + gcovr --config=tests/gcovr.conf --output=tests/report/accel-ppp.txt + gcovr --config=tests/gcovr.conf --csv --output=tests/report/accel-ppp.csv + gcovr --config=tests/gcovr.conf --html --html-details --output=tests/report/accel-ppp.html + + - name: Show default coverage report + run: cat tests/report/accel-ppp.txt + + - name: Upload coverage report + # if: ${{ false }} + uses: actions/upload-artifact@v3 + with: + name: coverage-report-on-${{ matrix.distro }} + path: tests/report/ + if-no-files-found: error diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 00000000..0e7ab4f2 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,17 @@ +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Byte-compiled +__pycache__/ + +# pytest +.pytest_cache + +# gcovr reports +report/ diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..d062ed46 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,103 @@ +# Requirements + +These tests are done for Ubuntu and Debian distros. Please use latest stable Debian or Ubuntu to run the tests. + +## Preparations + +Install pytest + +Using apt: `sudo apt install python3-pytest python3-pytest-dependency` or using pip: `sudo pip3 install pytest pytest-dependency`. + +pytest-dependency version must be >= 0.5 (with 'scope' support) + +--- +Note: tests will be run under sudo. If you prefer install python modules using pip, then do it under sudo as described above. + +--- + +Install additional tools required for tests: +```bash +sudo apt install iproute2 ppp pppoe isc-dhcp-client +``` + +Then build accel-ppp in 'build' directory (as usual) + +Install accel-pppd (make install or use distro package). Do not run accel-pppd using systemd or other supervisors +```bash +mkdir build && cd build +cmake -DBUILD_IPOE_DRIVER=TRUE -DBUILD_VLAN_MON_DRIVER=TRUE -DCMAKE_INSTALL_PREFIX=/usr -DKDIR=/usr/src/linux-headers-`uname -r` -DLUA=TRUE -DSHAPER=TRUE -DRADIUS=TRUE -DCPACK_TYPE=Ubuntu20 .. +make +sudo make install # or +# cpack -G DEB && dpkg -i accel-ppp.deb +``` + +If you prefer make install, then it is required to insert kernel modules: +```bash +# form root dir +sudo insmod build/drivers/vlan_mon/driver/vlan_mon.ko +sudo insmod build/drivers/ipoe/driver/ipoe.ko +``` + + +## Run tests (without coverage) + +```bash +# from this dir (tests) +sudo python3 -m pytest -Wall -v +``` + +To skip tests related to ipoe and vlan_mon kernel modules: +```bash +# from this dir (tests) +sudo python3 -m pytest -Wall -v -m "not ipoe_driver and not vlan_mon_driver" +``` + +## Preparations (for coverage report) + +Perform preparation steps for running tests without coverage + +Install gcovr + +Using apt: +```bash +sudo apt install gcovr +``` + +Using pip +```bash +sudo pip3 install gcovr +``` + +```bash +# from root dir +rm -rf build && mkdir build && cd build +cmake -DBUILD_IPOE_DRIVER=TRUE -DBUILD_VLAN_MON_DRIVER=TRUE -DCMAKE_INSTALL_PREFIX=/usr -DKDIR=/usr/src/linux-headers-`uname -r` -DLUA=TRUE -DSHAPER=TRUE -DRADIUS=TRUE -DCPACK_TYPE=Ubuntu20 -DCMAKE_C_FLAGS="--coverage -O0" .. +make +sudo make install # or +# cpack -G DEB && dpkg -i accel-ppp.deb +``` + +Then insert kernel modules (ipoe.ko and vlan-mon.ko) + +## Run tests and generate coverage report + +```bash +# from root dir (parent for this dir) +sudo python3 -m pytest -Wall tests -v # execute tests to collect coverage data +mkdir tests/report +gcovr --config=tests/gcovr.conf # default report +gcovr --config=tests/gcovr.conf --csv # csv report +gcovr --config=tests/gcovr.conf --html --html-details --output=tests/report/accel-ppp.html # html reports (most useful) +``` + +(If `gcovr` command does not exist, use `python3 -m gcovr` instead) + +## Remove coverage data + +If you want to re-run tests 'from scratch', you may want to remove coverage data. To do this: + +```bash +# from root dir (parent for this dir) +sudo gcovr -d # build report and delete +sudo gcovr -d # check that data is deleted (any coverage = 0%) +```
\ No newline at end of file diff --git a/tests/accel-cmd/test_cmd_basic.py b/tests/accel-cmd/test_cmd_basic.py new file mode 100644 index 00000000..c6cdc7ae --- /dev/null +++ b/tests/accel-cmd/test_cmd_basic.py @@ -0,0 +1,26 @@ +import pytest +from common import process + + +def test_accel_cmd_version(accel_cmd): + (exit, out, err) = process.run([accel_cmd, "--version"]) + + # test that accel-cmd --version exits with code 0, prints + # nothing to stdout and prints to stdout + assert exit == 0 and err == "" and "accel-cmd " in out and len(out.split(" ")) == 2 + + +def test_accel_cmd_non_existent_host(accel_cmd): + (exit, out, err) = process.run([accel_cmd, "-Hnon-existent-host", "--verbose"]) + + # test that accel-cmd (tried to connecto to non-existent host) exits with code != 0, + # prints nothing to stdout and prints an error to stderr + assert exit != 0 and out == "" and err != "" + + +def test_accel_cmd_mcast_host(accel_cmd): + (exit, out, err) = process.run([accel_cmd, "-H225.0.0.1"]) + + # test that accel-cmd (tried to connecto to mcast host) exits with code != 0, + # prints nothing to stdout and prints an error to stderr + assert exit != 0 and out == "" and err != "" diff --git a/tests/accel-cmd/test_real_commands.py b/tests/accel-cmd/test_real_commands.py new file mode 100644 index 00000000..1758b4e5 --- /dev/null +++ b/tests/accel-cmd/test_real_commands.py @@ -0,0 +1,53 @@ +import pytest +from common import process + + +@pytest.fixture() +def accel_pppd_config(): + return """ + [modules] + + [log] + log-debug=/dev/stdout + level=5 + + [cli] + tcp=127.0.0.1:2001 + """ + + +# test accel-cmd command with started accel-pppd +def test_accel_cmd_commands(accel_pppd_instance, accel_cmd): + + # test that accel-pppd started successfully + assert accel_pppd_instance + + (exit_sh_stat, out_sh_stat, err_sh_stat) = process.run([accel_cmd, "show stat"]) + + # test that 'show stat' has no errors and contains 'uptime' + assert ( + exit_sh_stat == 0 + and len(out_sh_stat) > 0 + and err_sh_stat == "" + and "uptime" in out_sh_stat + ) + + (exit_sh_ses, out_sh_ses, err_sh_ses) = process.run( + [accel_cmd, "show sessions sid,uptime"] + ) + # test that 'show sessions' has no errors and contains 'sid' + assert ( + exit_sh_ses == 0 + and len(out_sh_ses) > 0 + and err_sh_ses == "" + and "sid" in out_sh_ses + ) + + (exit_help, out_help, err_help) = process.run([accel_cmd, "help"]) + # test that 'help' has no errors and contains 'show stat' + assert ( + exit_help == 0 + and len(out_help) > 0 + and err_help == "" + and "show stat" in out_help + ) diff --git a/tests/accel-pppd/ipoe/conftest.py b/tests/accel-pppd/ipoe/conftest.py new file mode 100644 index 00000000..3db8dd60 --- /dev/null +++ b/tests/accel-pppd/ipoe/conftest.py @@ -0,0 +1,46 @@ +import pytest +from common import dhclient_process +import tempfile, os + +# dhclient executable file name +@pytest.fixture() +def dhclient(pytestconfig): + return pytestconfig.getoption("dhclient") + + +# pppd configuration as command line args (might be redefined by specific test) +# "-d" (do not daemonize) must be a part of the args +@pytest.fixture() +def dhclient_args(): + # test setup: + #lease_file = tempfile.NamedTemporaryFile(delete=True) + #lease_file_name = lease_file.name + #lease_file.close() # just create, close and delete + + # test execution: + yield ["-d", "-4", "--no-pid", "-lf", "/dev/null"] + + # test teardown: + #os.unlink(lease_file_name) + + +# setup and teardown for tests that required running dhclient (after accel-pppd) +@pytest.fixture() +def dhclient_instance(accel_pppd_instance, veth_pair_netns, dhclient, dhclient_args): + # test setup: + print("dhclient_instance: accel_pppd_instance = " + str(accel_pppd_instance)) + is_started, dhclient_thread, dhclient_control = dhclient_process.start( + veth_pair_netns["netns"], + dhclient, + dhclient_args, + ) + + # test execution: + yield { + "is_started": is_started, + "dhclient_thread": dhclient_thread, + "dhclient_control": dhclient_control, + } + + # test teardown: + dhclient_process.end(dhclient_thread, dhclient_control) diff --git a/tests/accel-pppd/ipoe/dhcpv4/test_ipoe_shared_session_wo_auth.py b/tests/accel-pppd/ipoe/dhcpv4/test_ipoe_shared_session_wo_auth.py new file mode 100644 index 00000000..104e4e9b --- /dev/null +++ b/tests/accel-pppd/ipoe/dhcpv4/test_ipoe_shared_session_wo_auth.py @@ -0,0 +1,70 @@ +import pytest +from common import process +import time + + +@pytest.fixture() +def accel_pppd_config(veth_pair_netns): + print("accel_pppd_config veth_pair_netns: " + str(veth_pair_netns)) + return ( + """ + [modules] + pppoe + ipoe + ippool + + [ip-pool] + gw-ip-address=192.0.2.1 + 192.0.2.2-255 + + [cli] + tcp=127.0.0.1:2001 + + [log] + log-debug=/dev/stdout + level=5 + + [ipoe] + noauth=1 + shared=1 + gw-ip-address=192.0.2.1/24 + interface=""" + + veth_pair_netns["veth_a"] + ) + + +# test dhcpv4 shared session without auth check +@pytest.mark.dependency(depends=["ipoe_driver_loaded"], scope = 'session') +@pytest.mark.ipoe_driver +def test_ipoe_shared_session_wo_auth(dhclient_instance, accel_cmd, veth_pair_netns): + + # test that dhclient (with accel-pppd) started successfully + assert dhclient_instance["is_started"] + + # wait until session is started + max_wait_time = 10.0 + sleep_time = 0.0 + is_started = False # is session started + while sleep_time < max_wait_time: + (exit, out, err) = process.run( + [ + accel_cmd, + "show sessions called-sid,ip,state", + ] + ) + assert exit == 0 # accel-cmd fails + # print(out) + if veth_pair_netns["veth_a"] in out and "192.0.2." in out and "active" in out: + # session is found + print( + "test_pppoe_session_wo_auth: session found in (sec): " + str(sleep_time) + ) + is_started = True + break + time.sleep(0.1) + sleep_time += 0.1 + + print("test_ipoe_shared_session_wo_auth: last accel-cmd out: " + out) + + # test that session is started + assert is_started == True diff --git a/tests/accel-pppd/ipoe/test_ipoe_driver.py b/tests/accel-pppd/ipoe/test_ipoe_driver.py new file mode 100644 index 00000000..d21e9ba7 --- /dev/null +++ b/tests/accel-pppd/ipoe/test_ipoe_driver.py @@ -0,0 +1,8 @@ +import pytest +import os + +# test that ipoe kernel module is loaded +@pytest.mark.dependency(name = 'ipoe_driver_loaded', scope = 'session') +@pytest.mark.ipoe_driver +def test_ipoe_kernel_module_loaded(): + assert os.path.isdir("/sys/module/ipoe")
\ No newline at end of file diff --git a/tests/accel-pppd/pppoe/conftest.py b/tests/accel-pppd/pppoe/conftest.py new file mode 100644 index 00000000..8ebaaed3 --- /dev/null +++ b/tests/accel-pppd/pppoe/conftest.py @@ -0,0 +1,42 @@ +import pytest +from common import pppd_process + +# pppd executable file name +@pytest.fixture() +def pppd(pytestconfig): + return pytestconfig.getoption("pppd") + + +# pppd configuration as string (should be redefined by specific test) +# all configs should contain "nodetach" option +@pytest.fixture() +def pppd_config(): + return "" + + +# pppd configuration as command line args +@pytest.fixture() +def pppd_args(pppd_config): + return pppd_config.split() + + +# setup and teardown for tests that required running pppd (after accel-pppd) +@pytest.fixture() +def pppd_instance(accel_pppd_instance, veth_pair_netns, pppd, pppd_args): + # test setup: + print("pppd_instance: accel_pppd_instance = " + str(accel_pppd_instance)) + is_started, pppd_thread, pppd_control = pppd_process.start( + veth_pair_netns["netns"], + pppd, + pppd_args, + ) + + # test execution: + yield { + "is_started": is_started, + "pppd_thread": pppd_thread, + "pppd_control": pppd_control, + } + + # test teardown: + pppd_process.end(pppd_thread, pppd_control) diff --git a/tests/accel-pppd/pppoe/test_pppoe_disc.py b/tests/accel-pppd/pppoe/test_pppoe_disc.py new file mode 100644 index 00000000..eb069c42 --- /dev/null +++ b/tests/accel-pppd/pppoe/test_pppoe_disc.py @@ -0,0 +1,42 @@ +import pytest +from common import netns + + +@pytest.fixture() +def accel_pppd_config(veth_pair_netns): + print(veth_pair_netns) + return ( + """ + [modules] + pppoe + + [log] + log-debug=/dev/stdout + level=5 + + [cli] + tcp=127.0.0.1:2001 + + [pppoe] + ac-name=test-accel + interface=""" + + veth_pair_netns["veth_a"] + ) + + +# test pppoe discovery +def test_pppoe_discovery(accel_pppd_instance, veth_pair_netns): + + # test that accel-pppd started successfully + assert accel_pppd_instance + + (exit_sh_stat, out_sh_stat, err_sh_stat) = netns.exec( + veth_pair_netns["netns"], ["pppoe-discovery", "-I", veth_pair_netns["veth_b"]] + ) + + # test that ac-name=test-accel is in pppoe-discovery reply (PADO) + assert ( + exit_sh_stat == 0 + and err_sh_stat == "" + and "test-accel" in out_sh_stat + ) diff --git a/tests/accel-pppd/pppoe/test_pppoe_pado_delay.py b/tests/accel-pppd/pppoe/test_pppoe_pado_delay.py new file mode 100644 index 00000000..96c73bf8 --- /dev/null +++ b/tests/accel-pppd/pppoe/test_pppoe_pado_delay.py @@ -0,0 +1,83 @@ +import pytest +from common import netns, process +import time + +# This test module requires pppoe-discovery with -a and -t options +# Ubuntu 20.04 has not this option, Ubuntu 22.04 is ok + +# Check that pppoe-discover supports -a and -t (to disable some tests required these features) +def support_pppoe_discovery_a_t(): + try: + (_, out, err) = process.run(["pppoe-discovery", "-h"]) + except: # can't run pppoe-discovery + return False + + if "-t " in out + err and "-a " in out + err: # found -t and -a options + return True + else: + return False + + +# skip tests in this module if pppoe-discovery doesn't support '-a' and '-t' options +pytestmark = pytest.mark.skipif( + not support_pppoe_discovery_a_t(), reason="bad pppoe-discovery" +) + + +@pytest.fixture() +def accel_pppd_config(veth_pair_netns): + print(veth_pair_netns) + return ( + """ + [modules] + pppoe + + [log] + log-debug=/dev/stdout + level=5 + + [cli] + tcp=127.0.0.1:2001 + + [pppoe] + ac-name=test-accel + pado-delay=1500 + interface=""" + + veth_pair_netns["veth_a"] + ) + + +# test pado delay. accel-pppd is configured for 1.5s delay +# first step: test that pppoe-discovery fails if wait timeout=1<1.5 +# second step: test that pppoe-discovery gets pado if wait timeout=2>1.5 +def test_pppoe_pado_delay(accel_pppd_instance, veth_pair_netns): + + # test that accel-pppd started successfully + assert accel_pppd_instance + + # send two times with wait timeout = 1 + (exit_sh_stat, out_sh_stat, err_sh_stat) = netns.exec( + veth_pair_netns["netns"], + ["pppoe-discovery", "-a1", "-t1", "-I", veth_pair_netns["veth_b"]], + ) + time.sleep(1) # sleep for one second (because accel-pppd replies in this timeslot) + (exit_sh_stat2, out_sh_stat2, err_sh_stat2) = netns.exec( + veth_pair_netns["netns"], + ["pppoe-discovery", "-a1", "-t1", "-I", veth_pair_netns["veth_b"]], + ) + time.sleep(1) # sleep for one second (because accel-pppd replies in this timeslot) + + # print(out_sh_stat + err_sh_stat) + # print(out_sh_stat2 + err_sh_stat2) + + # test that pppoe-discovery (wait timeout 1s) fails (as expected) (two times) + assert exit_sh_stat != 0 and "test-accel" not in out_sh_stat + assert exit_sh_stat2 != 0 and "test-accel" not in out_sh_stat2 + + (exit_sh_stat3, out_sh_stat3, err_sh_stat3) = netns.exec( + veth_pair_netns["netns"], + ["pppoe-discovery", "-a1", "-t2", "-I", veth_pair_netns["veth_b"]], + ) + + # test that pppoe-discovery (wait timeout 2s) gets pado + assert exit_sh_stat3 == 0 and "test-accel" in out_sh_stat3 diff --git a/tests/accel-pppd/pppoe/test_pppoe_session_wo_auth.py b/tests/accel-pppd/pppoe/test_pppoe_session_wo_auth.py new file mode 100644 index 00000000..0c8aa2c0 --- /dev/null +++ b/tests/accel-pppd/pppoe/test_pppoe_session_wo_auth.py @@ -0,0 +1,90 @@ +import pytest +from common import process +import time + + +@pytest.fixture() +def accel_pppd_config(veth_pair_netns): + print("accel_pppd_config veth_pair_netns: " + str(veth_pair_netns)) + return ( + """ + [modules] + pppoe + auth_pap + ippool + + [log] + log-debug=/dev/stdout + level=5 + + [auth] + any-login=1 + + [ip-pool] + gw-ip-address=192.0.2.1 + 192.0.2.2-255 + + [cli] + tcp=127.0.0.1:2001 + + [pppoe] + interface=""" + + veth_pair_netns["veth_a"] + ) + + +@pytest.fixture() +def pppd_config(veth_pair_netns): + print("pppd_config veth_pair_netns: " + str(veth_pair_netns)) + return ( + """ + nodetach + noipdefault + defaultroute + connect /bin/true + noauth + persist + mtu 1492 + noaccomp + default-asyncmap + plugin rp-pppoe.so + user loginAB + password pass123 + nic-""" + + veth_pair_netns["veth_b"] + ) + + +# test pppoe session without auth check +def test_pppoe_session_wo_auth(pppd_instance, accel_cmd): + + # test that pppd (with accel-pppd) started successfully + assert pppd_instance["is_started"] + + # wait until session is started + max_wait_time = 10.0 + sleep_time = 0.0 + is_started = False # is session started + while sleep_time < max_wait_time: + (exit, out, err) = process.run( + [ + accel_cmd, + "show sessions match username loginAB username,ip,state", + ] + ) + assert exit == 0 # accel-cmd fails + # print(out) + if "loginAB" in out and "192.0.2." in out and "active" in out: + # session is found + print( + "test_pppoe_session_wo_auth: session found in (sec): " + str(sleep_time) + ) + is_started = True + break + time.sleep(0.1) + sleep_time += 0.1 + + print("test_pppoe_session_wo_auth: last accel-cmd out: " + out) + + # test that session is started + assert is_started == True diff --git a/tests/accel-pppd/pppoe/test_pppoe_vlan_mon.py b/tests/accel-pppd/pppoe/test_pppoe_vlan_mon.py new file mode 100644 index 00000000..670abc33 --- /dev/null +++ b/tests/accel-pppd/pppoe/test_pppoe_vlan_mon.py @@ -0,0 +1,49 @@ +import pytest +from common import netns + + +# create vlan 15 only in netns (invisble to accel-pppd) +@pytest.fixture() +def veth_pair_vlans_config(): + return {"vlans_a": [], "vlans_b": [15]} + + +@pytest.fixture() +def accel_pppd_config(veth_pair_netns): + print(veth_pair_netns) + return """ + [modules] + pppoe + + [log] + log-debug=/dev/stdout + level=5 + + [cli] + tcp=127.0.0.1:2001 + + [pppoe] + ac-name=test-accel + vlan-mon=%s,10-20 + interface=re:%s.\\d+ + """ % ( + veth_pair_netns["veth_a"], + veth_pair_netns["veth_a"], + ) + + +# test pppoe discovery in vlan created by vlan_mon +@pytest.mark.dependency(depends=["vlan_mon_driver_loaded"], scope="session") +@pytest.mark.vlan_mon_driver +def test_pppoe_vlan_mon(accel_pppd_instance, veth_pair_netns): + + # test that accel-pppd started successfully + assert accel_pppd_instance + + (exit_sh_stat, out_sh_stat, err_sh_stat) = netns.exec( + veth_pair_netns["netns"], + ["pppoe-discovery", "-I", veth_pair_netns["veth_b"] + ".15"], + ) + + # test that ac-name=test-accel is in pppoe-discovery reply (PADO) + assert exit_sh_stat == 0 and err_sh_stat == "" and "test-accel" in out_sh_stat diff --git a/tests/accel-pppd/test_basic.py b/tests/accel-pppd/test_basic.py new file mode 100644 index 00000000..2b2c6f71 --- /dev/null +++ b/tests/accel-pppd/test_basic.py @@ -0,0 +1,83 @@ +import pytest +from common import process + + +def test_accel_pppd_version(accel_pppd): + (exit, out, err) = process.run([accel_pppd, "--version"]) + + # test that accel-pppd --version exits with code 0, prints + # nothing to stdout and prints to stdout + assert exit == 0 and err == "" and "accel-ppp " in out and len(out.split(" ")) == 2 + + +@pytest.fixture() +def accel_pppd_config(): + return """ + [modules] + log_file + log_syslog + log_tcp + #log_pgsql + + pptp + l2tp + sstp + pppoe + ipoe + + auth_mschap_v2 + auth_mschap_v1 + auth_chap_md5 + auth_pap + + radius + chap-secrets + + ippool + + pppd_compat + shaper + #net-snmp + logwtmp + connlimit + + ipv6_nd + ipv6_dhcp + ipv6pool + + [core] + log-error=/dev/stderr + + [log] + log-debug=/dev/stdout + log-file=/dev/stdout + log-emerg=/dev/stderr + level=5 + + [cli] + tcp=127.0.0.1:2001 + + [pppoe] + + [client-ip-range] + 10.0.0.0/8 + + [radius] + """ + + +# load all modules and check that accel-pppd replies to 'show stat' command +def test_load_all_modules(accel_pppd_instance, accel_cmd): + + # test that accel-pppd started successfully + assert accel_pppd_instance + + (exit_sh_stat, out_sh_stat, err_sh_stat) = process.run([accel_cmd, "show stat"]) + + # test that 'show stat' has no errors and contains 'uptime' + assert ( + exit_sh_stat == 0 + and len(out_sh_stat) > 1 + and err_sh_stat == "" + and "uptime" in out_sh_stat + ) diff --git a/tests/accel-pppd/test_vlan_mon_driver.py b/tests/accel-pppd/test_vlan_mon_driver.py new file mode 100644 index 00000000..a230c7c8 --- /dev/null +++ b/tests/accel-pppd/test_vlan_mon_driver.py @@ -0,0 +1,8 @@ +import pytest +import os + +# test that vlan_mon kernel module is loaded +@pytest.mark.dependency(name = 'vlan_mon_driver_loaded', scope = 'session') +@pytest.mark.vlan_mon_driver +def test_vlan_mon_kernel_module_loaded(): + assert os.path.isdir("/sys/module/vlan_mon")
\ No newline at end of file diff --git a/tests/common/__init__.py b/tests/common/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/common/__init__.py diff --git a/tests/common/accel_pppd_process.py b/tests/common/accel_pppd_process.py new file mode 100644 index 00000000..c2ee451e --- /dev/null +++ b/tests/common/accel_pppd_process.py @@ -0,0 +1,86 @@ +from subprocess import Popen, PIPE +from common import process +from threading import Thread +import time + + +def accel_pppd_thread_func(accel_pppd_control): + process = accel_pppd_control["process"] + print("accel_pppd_thread_func: before communicate") + (out, err) = process.communicate() + print( + "accel_pppd_thread_func: after communicate out=" + str(out) + " err=" + str(err) + ) + process.wait() + print("accel_pppd_thread_func: after wait") + + +def start(accel_pppd, args, accel_cmd, max_wait_time): + print("accel_pppd_start: begin") + accel_pppd_process = Popen([accel_pppd] + args, stdout=PIPE, stderr=PIPE) + accel_pppd_control = {"process": accel_pppd_process} + accel_pppd_thread = Thread( + target=accel_pppd_thread_func, + args=[accel_pppd_control], + ) + accel_pppd_thread.start() + + # wait until accel-pppd replies to 'show version' + # accel-pppd needs some time to be accessible + sleep_time = 0.0 + is_started = False + while sleep_time < max_wait_time: + if accel_pppd_process.poll() is not None: # process is terminated + print( + "accel_pppd_start: terminated during 'show version' polling in (sec): " + + str(sleep_time) + ) + is_started = False + break + (exit, out, err) = process.run([accel_cmd, "show version"]) + if exit != 0: # does not reply + time.sleep(0.1) + sleep_time += 0.1 + else: # replied + print("accel_pppd_start: 'show version' replied") + is_started = True + break + + return (is_started, accel_pppd_thread, accel_pppd_control) + + +def end(accel_pppd_thread, accel_pppd_control, accel_cmd, max_wait_time): + print("accel_pppd_end: begin") + if accel_pppd_control["process"].poll() is not None: # terminated + print("accel_pppd_end: already terminated. nothing to do") + accel_pppd_thread.join() + return + + process.run( + [accel_cmd, "shutdown hard"] + ) # send shutdown hard command (in coverage mode it helps saving coverage data) + print("accel_pppd_end: after shutdown hard") + + # wait until accel-pppd is finished + sleep_time = 0.0 + is_finished = False + while sleep_time < max_wait_time: + if accel_pppd_control["process"].poll() is None: # not terminated yet + time.sleep(0.01) + sleep_time += 0.01 + # print("accel_pppd_end: sleep 0.01") + else: + is_finished = True + print( + "accel_pppd_end: finished via shutdown hard in (sec): " + + str(sleep_time) + ) + break + + # accel-pppd is still alive. kill it + if not is_finished: + print("accel_pppd_end: kill process: " + str(accel_pppd_control["process"])) + accel_pppd_control["process"].kill() # kill -9 if 'shutdown hard' didn't help + + accel_pppd_thread.join() # wait until thread is finished + print("accel_pppd_end: end") diff --git a/tests/common/config.py b/tests/common/config.py new file mode 100644 index 00000000..94ddcd8c --- /dev/null +++ b/tests/common/config.py @@ -0,0 +1,15 @@ +import tempfile +import os + + +def make_tmp(content): + f = tempfile.NamedTemporaryFile(delete=False) + print("make_tmp filename: " + f.name) + f.write(bytes(content, "utf-8")) + f.close() + return f.name + + +def delete_tmp(filename): + print("delete_tmp filename: " + filename) + os.unlink(filename) diff --git a/tests/common/dhclient_process.py b/tests/common/dhclient_process.py new file mode 100644 index 00000000..aaea4860 --- /dev/null +++ b/tests/common/dhclient_process.py @@ -0,0 +1,45 @@ +from subprocess import Popen, PIPE +from threading import Thread + + +def dhclient_thread_func(dhclient_control): + process = dhclient_control["process"] + print("dhclient_thread_func: before communicate") + (out, err) = process.communicate() + print( + "dhclient_thread_func: after communicate out=" + str(out) + " err=" + str(err) + ) + process.wait() + print("dhclient_thread_func: after wait") + + +def start(netns, dhclient, args): + print("dhclient_start: begin") + print("dhclient_start: args=" + str(args)) + dhclient_process = Popen( + ["ip", "netns", "exec", netns] + [dhclient] + args, stdout=PIPE, stderr=PIPE + ) + print("dhclient_start: dhclient_process=" + str(dhclient_process)) + dhclient_control = {"process": dhclient_process} + dhclient_thread = Thread( + target=dhclient_thread_func, + args=[dhclient_control], + ) + dhclient_thread.start() + + is_started = True if dhclient_process.poll() is None else False + + return (is_started, dhclient_thread, dhclient_control) + + +def end(dhclient_thread, dhclient_control): + print("dhclient_end: begin") + if dhclient_control["process"].poll() is not None: # already terminated + print("dhclient_end: already terminated. nothing to do") + dhclient_thread.join() + return + + print("dhclient_end: kill process: " + str(dhclient_control["process"])) + dhclient_control["process"].kill() # kill -9 + dhclient_thread.join() # wait until thread is finished + print("dhclient_end: end") diff --git a/tests/common/iface.py b/tests/common/iface.py new file mode 100644 index 00000000..dbd052ab --- /dev/null +++ b/tests/common/iface.py @@ -0,0 +1,23 @@ +from common import netns + +# up interface. if netns is None, then up in global rt. if ok returns 0 +def up(iface, netns_name): + command = ["ip", "link", "set", iface, "up"] + exit, out, err = netns.exec(netns_name, command) + print( + "iface.up: iface=%s netns=%s exit=%d out=%s err=%s" + % (iface, netns_name, exit, out, err) + ) + + return exit + + +# delete interface. if netns is None, then up in global rt. if ok returns 0 +def delete(iface, netns_name): + exit, out, err = netns.exec(netns_name, ["ip", "link", "delete", iface]) + print( + "iface.delete: iface=%s netns=%s exit=%d out=%s err=%s" + % (iface, netns_name, exit, out, err) + ) + + return exit diff --git a/tests/common/netns.py b/tests/common/netns.py new file mode 100644 index 00000000..9b0d729b --- /dev/null +++ b/tests/common/netns.py @@ -0,0 +1,29 @@ +from common import process + +# creates netns and returns netns name. if ok return 0 +def create(netns_name): + netns, out, err = process.run(["ip", "netns", "add", netns_name]) + print("netns.create: exit=%d out=%s err=%s" % (netns, out, err)) + + return netns + + +# deletes netns. if ok return 0 +def delete(netns_name): + netns, out, err = process.run(["ip", "netns", "delete", netns_name]) + print("netns.delete: exit=%d out=%s err=%s" % (netns, out, err)) + + return netns + + +# execute command in netns using process.run +# if netns_name is None, then execute in global rt +def exec(netns_name, command): + if netns_name is None: + exit, out, err = process.run(command) + else: + exit, out, err = process.run(["ip", "netns", "exec", netns_name] + command) + + print("netns.exec: netns=%s command=%s :: exit=%d out=%s err=%s" % (netns_name, str(command), exit, out, err)) + + return (exit, out, err) diff --git a/tests/common/pppd_process.py b/tests/common/pppd_process.py new file mode 100644 index 00000000..45844400 --- /dev/null +++ b/tests/common/pppd_process.py @@ -0,0 +1,43 @@ +from subprocess import Popen, PIPE +from threading import Thread + + +def pppd_thread_func(pppd_control): + process = pppd_control["process"] + print("pppd_thread_func: before communicate") + (out, err) = process.communicate() + print("pppd_thread_func: after communicate out=" + str(out) + " err=" + str(err)) + process.wait() + print("pppd_thread_func: after wait") + + +def start(netns, pppd, args): + print("pppd_start: begin") + print("pppd_start: args=" + str(args)) + pppd_process = Popen( + ["ip", "netns", "exec", netns] + [pppd] + args, stdout=PIPE, stderr=PIPE + ) + print("pppd_start: pppd_process=" + str(pppd_process)) + pppd_control = {"process": pppd_process} + pppd_thread = Thread( + target=pppd_thread_func, + args=[pppd_control], + ) + pppd_thread.start() + + is_started = True if pppd_process.poll() is None else False + + return (is_started, pppd_thread, pppd_control) + + +def end(pppd_thread, pppd_control): + print("pppd_end: begin") + if pppd_control["process"].poll() is not None: # already terminated + print("pppd_end: already terminated. nothing to do") + pppd_thread.join() + return + + print("pppd_end: kill process: " + str(pppd_control["process"])) + pppd_control["process"].kill() # kill -9 + pppd_thread.join() # wait until thread is finished + print("pppd_end: end") diff --git a/tests/common/process.py b/tests/common/process.py new file mode 100644 index 00000000..e0c61363 --- /dev/null +++ b/tests/common/process.py @@ -0,0 +1,7 @@ +from subprocess import Popen, PIPE + +def run(command): + process = Popen(command, stdout=PIPE, stderr=PIPE) + (out, err) = process.communicate() + exit_code = process.wait() + return (exit_code, out.decode("utf-8"), err.decode("utf-8"))
\ No newline at end of file diff --git a/tests/common/veth.py b/tests/common/veth.py new file mode 100644 index 00000000..c9d3006c --- /dev/null +++ b/tests/common/veth.py @@ -0,0 +1,83 @@ +from common import process, netns, vlan, iface +import time +import math + +# creates veth pair. if ok returns 0 +def create_pair(name_a, name_b): + veth, out, err = process.run( + ["ip", "link", "add", name_a, "type", "veth", "peer", "name", name_b] + ) + print("veth.create: exit=%d out=%s err=%s" % (veth, out, err)) + + return veth + + +# put veth to netns. if ok returns 0 +def assign_netns(veth, netns): + veth, out, err = process.run(["ip", "link", "set", veth, "netns", netns]) + print("veth.assign_netns: exit=%d out=%s err=%s" % (veth, out, err)) + + return veth + + +# creates netns, creates veth pair and place second link to netns +# creates vlans over veth interfaces according to veth_pair_vlans_config +# return dict with 'netns', 'veth_a', 'veth_b' +def create_veth_pair_netns(veth_pair_vlans_config): + + name = str(math.floor(time.time() * 1000) % 1000000) + netns_name = "N" + name + netns_status = netns.create(netns_name) + print("create_veth_pair_netns: netns_status=%d" % netns_status) + + veth_a = "A" + name + veth_b = "B" + name + pair_status = create_pair(veth_a, veth_b) + print("create_veth_pair_netns: pair_status=%d" % pair_status) + + iface.up(veth_a, None) + + assign_status = assign_netns(veth_b, netns_name) + print("create_veth_pair_netns: assign_status=%d" % assign_status) + + iface.up(veth_b, netns_name) + + vlans_a = veth_pair_vlans_config["vlans_a"] + for vlan_num in vlans_a: + vlan.create(veth_a, vlan_num, None) + iface.up(veth_a + "." + str(vlan_num), None) + + vlans_b = veth_pair_vlans_config["vlans_b"] + for vlan_num in vlans_b: + vlan.create(veth_b, vlan_num, netns_name) + iface.up(veth_b + "." + str(vlan_num), netns_name) + + return { + "netns": netns_name, + "veth_a": veth_a, + "veth_b": veth_b, + "vlans_a": vlans_a, + "vlans_b": vlans_b, + } + + +# deletes veth pair and netns created by create_veth_pair_netns +def delete_veth_pair_netns(veth_pair_netns): + + vlans_a = veth_pair_netns["vlans_a"] + veth_a = veth_pair_netns["veth_a"] + vlans_b = veth_pair_netns["vlans_b"] + veth_b = veth_pair_netns["veth_b"] + netns_name = veth_pair_netns["netns"] + + # remove vlans on top of veth interface + for vlan_num in vlans_a: + iface.delete(veth_a + "." + str(vlan_num), None) + for vlan_num in vlans_b: + iface.delete(veth_b + "." + str(vlan_num), netns_name) + + veth_status = iface.delete(veth_a, None) + print("delete_veth_pair_netns: veth_status=%d" % veth_status) + + netns_status = netns.delete(netns_name) + print("delete_veth_pair_netns: netns_status=%d" % netns_status) diff --git a/tests/common/vlan.py b/tests/common/vlan.py new file mode 100644 index 00000000..459efb18 --- /dev/null +++ b/tests/common/vlan.py @@ -0,0 +1,13 @@ +from common import netns + +# up interface. if netns is None, then up in global rt. if ok returns 0 +def create(parent_if, vlan, netns_name): + command = ( + "ip link add link %s name %s.%d type vlan id %d" + % (parent_if, parent_if, vlan, vlan) + ).split() + + vlan, out, err = netns.exec(netns_name, command) + print("vlan.create: exit=%d out=%s err=%s" % (vlan, out, err)) + + return vlan diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..d3733409 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,99 @@ +import pytest +from common import accel_pppd_process, config, veth + + +def pytest_addoption(parser): + parser.addoption("--accel_cmd", action="store", default="accel-cmd") + parser.addoption("--accel_pppd", action="store", default="accel-pppd") + parser.addoption("--pppd", action="store", default="pppd") # pppd client + parser.addoption( + "--dhclient", action="store", default="dhclient" + ) # isc-dhcp-client + parser.addoption( + "--accel_pppd_max_wait_time", action="store", default=5.0 + ) # start timeout + parser.addoption( + "--accel_pppd_max_finish_time", action="store", default=10.0 + ) # fininsh timeout (before kill) + + +def pytest_configure(config): + config.addinivalue_line( + "markers", + "ipoe_driver: marks tests as related to ipoe kernel module (deselect with '-m \"not ipoe_driver\"')", + ) + config.addinivalue_line( + "markers", + "vlan_mon_driver: marks tests as related to ipoe kernel module (deselect with '-m \"not vlan_mon_driver\"')", + ) + + +# accel-pppd executable file name +@pytest.fixture() +def accel_pppd(pytestconfig): + return pytestconfig.getoption("accel_pppd") + + +# accel-cmd executable file name +@pytest.fixture() +def accel_cmd(pytestconfig): + return pytestconfig.getoption("accel_cmd") + + +# accel-pppd configuration as string (should be redefined by specific test) +@pytest.fixture() +def accel_pppd_config(): + return "" + + +# accel-pppd configuration file name +@pytest.fixture() +def accel_pppd_config_file(accel_pppd_config): + # test setup: + filename = config.make_tmp(accel_pppd_config) + + # test execution + yield filename + + # test teardown: + config.delete_tmp(filename) + + +# setup and teardown for tests that required running accel-pppd +@pytest.fixture() +def accel_pppd_instance(accel_pppd, accel_pppd_config_file, accel_cmd, pytestconfig): + # test setup: + is_started, accel_pppd_thread, accel_pppd_control = accel_pppd_process.start( + accel_pppd, + ["-c" + accel_pppd_config_file], + accel_cmd, + pytestconfig.getoption("accel_pppd_max_wait_time"), + ) + + # test execution: + yield is_started + + # test teardown: + accel_pppd_process.end( + accel_pppd_thread, + accel_pppd_control, + accel_cmd, + pytestconfig.getoption("accel_pppd_max_finish_time"), + ) + +# defines vlans that will be created over veth pair (might be redefined by specific test) +@pytest.fixture() +def veth_pair_vlans_config(): + return {"vlans_a": [], "vlans_b": []} + +# setup and teardown for netns and veth pair +@pytest.fixture() +def veth_pair_netns(veth_pair_vlans_config): + # test setup: + veth_pair_netns_instance = veth.create_veth_pair_netns(veth_pair_vlans_config) + + # test execution: + yield veth_pair_netns_instance + + # test teardown: + veth.delete_veth_pair_netns(veth_pair_netns_instance) diff --git a/tests/gcovr.conf b/tests/gcovr.conf new file mode 100644 index 00000000..144b3188 --- /dev/null +++ b/tests/gcovr.conf @@ -0,0 +1,2 @@ +#exclude = * +exclude = ../build/CMakeFiles |