Skip to content

Commit

Permalink
Add Tests and Automate Testing with GitHub Actions (#37)
Browse files Browse the repository at this point in the history
* Add Python 3.11 metadata classifier

* Add basic tox config

* separate testing dependencies

dev extras includes testing deps

* blacken code

* initial tox config

* remove tox parallel

* test github actions tox

* fix typo

* fix yaml format

* Remove python 3.11 support

Ray will not support until 2.3: https://github.com/ray-project/ray/milestone/104

* add github actions tests badge

* rename tests action

* remove outdated dockerized test environment

* test check for docker image updates

* test run on push (temp)

* fix parent action name

* fix ghcr link

* temp hardcode image version

* test get image version

* fix updatecheck output name

* test fix URL

* fix jq typo

* test env var

* attempt fix auth

* test -H auth

* test auth with step

* Revert "test auth with step"

This reverts commit 99c6de4.

* move auth to first step

* consolidate steps

* Revert "consolidate steps"

This reverts commit cc81755.

* add permissions key

* testing gh secrets

* add gh auth to increment version

* testing

* test use secret directly

* try write-all perms

* try cli login

* try new token

* try defaults

* attempt container auto-update

* attempt fix docker build context

* use environment variables

* lowercase package URL

* only update secret on success

* env increment fix

* rename actions

* temp disable package publishing

* try other fork update checker

* Update mock RSA

* temp disable workflow on push

* improve mock RSA handling

* fix string formatting when passing integer values

* replace generic exception with ValueError

* raise ValueError for invalid attenuation settings

* move RSA-universal constants to file

* update mock RSA

* improve mock analyzer handling

* update iqstream mocks

* update scos_actions for testing

* revert actions version

* fix mock IQ stream failure

* force num_samples integer input

* write tests for sigan interface

* disable scheduled image auto-update

* disable automatic image updates

* Add more checks to calibration loading

* remove unused import

* update isort to fix pre-commit CI

* switch ubuntu testing version to 20.04

* add concurrency to reduce duplicate testing

* modify pytest command

* fix CI test badge link

* test bandit security CI

* adjust runs-on for bandit CI

and add concurrency handling

* Add CodeQL action config

* remove dead code

* rename tox action

* remove tox testing on ubuntu-latest

* fix workflow triggering on branches

* update tox job naming

* try custom bandit action

* remove bandit config from pyproject.toml

* only run bandit on src directory

* add assertion to make bandit warn

* remove bandit matrix strategy

* remove CodeQL action

* remove pyproject bandit requirement

* bandit ci optional deps

* remove bandit testing code

should resolve open bot comment on PR

* test building docker image on dockerfile modified

* fix typo

* Only run tox on src/tests changes

* Only build docker image on dockerfile modified

* also build image on PR editing dockerfile

* Bandit and Tox on PR only when python modified

* Update README.md

* remove unused dependency

* Remove Bandit CI

* Delete auto-update-parent-image.yaml

* update unit tests for upstream changes

* add Python 3.11 to testing suite

* update test and dev dependencies

* Sync minimum tox versions for local testing and CI testing

* Rewrite unit test for IQ capture retry
  • Loading branch information
aromanielloNTIA authored May 12, 2023
1 parent 68233dd commit 9666495
Show file tree
Hide file tree
Showing 12 changed files with 543 additions and 153 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/build-docker-image.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Build Docker Image

# Run when Dockerfile is edited
on:
push:
paths:
- docker/Dockerfile
pull_request:
paths:
- docker/Dockerfile

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true

jobs:
build-docker-image:
name: Build tekrsa_usb Docker image
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build tekrsa_usb Docker image
uses: docker/build-push-action@v4
with:
push: false
tags: tekrsa_usb
file: ./docker/Dockerfile
54 changes: 54 additions & 0 deletions .github/workflows/tox.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Tox

on:
workflow_dispatch:
push:
branches:
- main
paths:
- src
- tests
- pyproject.toml
- tox.ini
pull_request:
branches:
- main
paths:
- src
- tests
- pyproject.toml
- tox.ini

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true

jobs:
run-all-tests:
name: Py${{ matrix.py }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-20.04
py:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
steps:
- name: Set up Python ${{ matrix.py }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.py }}
- name: Checkout scos-tekrsa
uses: actions/checkout@v3
- name: Install tox-gh
run: python -m pip install tox-gh
- name: Set up test suite
run: tox r -vv --notest
- name: Run test suite
run: tox r --skip-pkg-install
env:
PYTEST_ADDOPTS: "-vv --durations=0"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ docker/libcyusb_shared.so
*.egg-info
dist
.coverage
.tox
43 changes: 24 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
# NTIA/ITS SCOS Tektronix® RSA Plugin

![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/NTIA/scos-tekrsa?display_name=tag&sort=semver)
![GitHub all releases](https://img.shields.io/github/downloads/NTIA/scos-tekrsa/total)
![GitHub issues](https://img.shields.io/github/issues/NTIA/scos-tekrsa)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![GitHub release (latest SemVer)][latest-release-semver-badge]][github-releases]
[![GitHub Actions Test Status][github-actions-test-badge]][github-actions-tox-link]
[![GitHub all releases][github-download-count-badge]][github-releases]
[![GitHub issues][github-issue-count-badge]][github-issues]
[![Code style: black][code-style-badge]][code-style-repo]

[NTIA/ITS]: https://its.ntia.gov/
[github-actions-tox-link]: https://github.com/NTIA/scos-tekrsa/actions/workflows/tox.yaml
[github-actions-test-badge]: https://github.com/NTIA/scos-tekrsa/actions/workflows/tox.yaml/badge.svg
[code-style-badge]: https://img.shields.io/badge/code%20style-black-000000.svg
[code-style-repo]: https://github.com/psf/black
[latest-release-semver-badge]: https://img.shields.io/github/v/release/NTIA/scos-tekrsa?display_name=tag&sort=semver
[github-releases]: https://github.com/NTIA/scos-tekrsa/releases
[github-download-count-badge]: https://img.shields.io/github/downloads/NTIA/scos-tekrsa/total
[github-issue-count-badge]: https://img.shields.io/github/issues/NTIA/scos-tekrsa
[github-issues]: https://github.com/NTIA/scos-tekrsa/issues

This repository is a plugin to add support for the Tektronix RSA306, RSA306B, RSA503A,
RSA507A, RSA513A, RSA518A, RSA603A, and RSA607A real-time spectrum analyzers to
SCOS Sensor. See the
SCOS Sensor, developed by [NTIA/ITS]. See the
[SCOS Sensor documentation](https://github.com/NTIA/scos-sensor/blob/master/README.md)
for more information about SCOS Sensor, especially the section about
[Actions and Hardware Support](https://github.com/NTIA/scos-sensor/blob/master/README.md#actions-and-hardware-support).
Expand Down Expand Up @@ -77,7 +89,7 @@ file:
1. In the newly-created `env` file, set the `BASE_IMAGE`:

```text
BASE_IMAGE=ghcr.io/ntia/scos-tekrsa/tekrsa_usb:0.2.1
BASE_IMAGE=ghcr.io/ntia/scos-tekrsa/tekrsa_usb:latest
```

1. Get environment variables:
Expand All @@ -90,7 +102,7 @@ file:
(such as `scos_usrp`), then add the `scos_tekrsa` dependency:

```text
scos_tekrsa @ git+https://github.com/NTIA/scos-tekrsa@1.0.1
scos_tekrsa @ git+https://github.com/NTIA/scos-tekrsa@3.0.1
```

1. Compile requirements by running:
Expand Down Expand Up @@ -183,20 +195,13 @@ docker push ghcr.io/ntia/scos-tekrsa/tekrsa_usb:X.X.X

### Running Tests

A Docker container is used for testing the `tekrsa_usb` base image provided in this
repository. [Install Docker](https://docs.docker.com/get-docker/) in order to run tests.
The `scos_tekrsa` plugin is tested using [`tox`](https://tox.wiki/en/latest/) and the [`pytest`](https://docs.pytest.org/en/7.1.x/)
framework. The following commands can be used to run tests and show coverage reports.

```bash
docker build -f docker/Dockerfile-test -t rsa_test .
docker run rsa_test
```

The `scos_tekrsa` plugin is tested using the [`pytest`](https://docs.pytest.org/en/7.1.x/)
framework. Run tests, and view test coverage, by running the following command from the
top-level directory of this repository.

```bash
pytest --cov
pytest # faster, but less thorough
tox # test code in virtual environments for multiple versions of Python
tox --recreate # To recreate the virtual environments used for testing
```

## License
Expand Down
19 changes: 0 additions & 19 deletions docker/Dockerfile-test

This file was deleted.

15 changes: 10 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ classifiers = [
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]

dependencies = [
Expand All @@ -44,12 +45,16 @@ dependencies = [
]

[project.optional-dependencies]
tests = [
"pytest>=7.3.1,<8.0",
"pytest-cov>=4.0.0,<5.0",
"tox>=4.5.1,<5.0", # Should keep in sync with tox.ini minimum_version
]

dev = [
"hatchling>=1.6.0,<2.0",
"pre-commit>=2.20.0",
"pytest>=7.1.2",
"pytest-cov>=3.0.0",
"twine>=4.0.1,<5.0"
"hatchling>=1.14.2,<2.0",
"pre-commit>=3.3.1,<4.0",
"scos-tekrsa[tests]",
]

[project.urls]
Expand Down
101 changes: 81 additions & 20 deletions src/scos_tekrsa/hardware/mocks/rsa_block.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,84 @@
""" Mock functions from RSA API that are used in RadioInterface. """
""" Mock functions from RSA API that are used in SignalAnalyzerInterface. """
import numpy as np

from scos_tekrsa.hardware.tekrsa_constants import IQSTREAM_BW_SR_MAP

rng = np.random.default_rng()

# For testing IQ capture retry on failure, this parameter controls the
# number of times that the mocked IQSTREAM_Tempfile_NoConfig() will fail
# when run consecutively, before working.
TIMES_TO_FAIL = 3

# Mock Signal Analyzer Constants
DEVICE_NOMENCLATURE = "MOCK RSA507A"
MIN_CENTER_FREQ = 9e3
MAX_CENTER_FREQ = 6.2e9
MIN_IQ_BW = 9e3
MAX_IQ_BW = 40e6

# Default values
IQSTREAM_BW = 40e6
IQSTREAM_SR = 56e6
CENTER_FREQ = 1e9
REFERENCE_LEVEL = -30
ATTENUATION = 10
PREAMP_ENABLE = True


class MockRSA:
def __init__(self, randomize_values=False):
# Simulate returning less than requested num samples
self.times_to_fail = 0
self.times_to_fail = TIMES_TO_FAIL
self.times_failed = 0
self.randomize_values = randomize_values

# Initialize parameters
self._frequency = CENTER_FREQ
self._reference_level = REFERENCE_LEVEL
self._iq_bandwidth = IQSTREAM_BW
self._sample_rate = IQSTREAM_SR
self._attenuation = ATTENUATION
self._preamp_enable = PREAMP_ENABLE

def CONFIG_GetMinCenterFreq(self):
return 9.0e3
return MIN_CENTER_FREQ

def CONFIG_GetMaxCenterFreq(self):
return 6.2e9
return MAX_CENTER_FREQ

def CONFIG_GetCenterFreq(self):
return 1.0e9
return self._frequency

def CONFIG_SetCenterFreq(self, val):
return None
self._frequency = val

def CONFIG_GetReferenceLevel(self):
return 0.0
return self._reference_level

def CONFIG_SetReferenceLevel(self, val):
return None
self._reference_level = val

def CONFIG_GetRFAttenuator(self):
return self._attenuation

def CONFIG_SetRFAttenuator(self, val):
self._attenuation = val

def CONFIG_SetAutoAttenuationEnable(self, en):
return

def CONFIG_GetRFPreampEnable(self):
return self._preamp_enable

def CONFIG_SetRFPreampEnable(self, en):
self._preamp_enable = en

def DEVICE_SearchAndConnect(self, verbose=False):
return None

def DEVICE_GetNomenclature(self):
return "MOCK RSA507A"
return DEVICE_NOMENCLATURE

def ALIGN_GetWarmupStatus(self):
return True
Expand All @@ -43,27 +90,41 @@ def ALIGN_RunAlignment(self):
return None

def IQSTREAM_GetAcqParameters(self):
return 40.0e6, 56.0e6
return self._iq_bandwidth, self._sample_rate

def IQSTREAM_GetMinAcqBandwidth(self):
return MIN_IQ_BW

def IQSTREAM_GetMaxAcqBandwidth(self):
return MAX_IQ_BW

def IQSTREAM_SetAcqBandwidth(self, bw):
return None
self._iq_bandwidth = bw
self._sample_rate = IQSTREAM_BW_SR_MAP[self._iq_bandwidth]

def IQSTREAM_Tempfile_NoConfig(self, dur_msec):
# Get n_samp from dur_msec (assuming 56e6 SR)
n_samp = int((dur_msec / 1000) * 56e6)
def IQSTREAM_Tempfile_NoConfig(self, dur_msec, return_status):
# Get n_samp from dur_msec
n_samp = int((dur_msec / 1000) * self.IQSTREAM_GetAcqParameters()[1])

if self.times_failed < self.times_to_fail:
self.times_failed += 1
return np.ones(0, dtype=np.complex64)
if self.randomize_values:
i = np.random.normal(0.5, 0.5, n_samp)
q = np.random.normal(0.5, 0.5, n_samp)
iq = np.ones(0, dtype=np.complex64)
elif self.randomize_values:
i = rng.normal(0.5, 0.5, n_samp)
q = rng.normal(0.5, 0.5, n_samp)
rand_iq = np.empty(n_samp, dtype=np.complex64)
rand_iq.real = i
rand_iq.imag = q
return rand_iq
iq = rand_iq
else:
return np.ones(n_samp, dtype=np.complex64)
iq = np.ones(n_samp, dtype=np.complex64)
if return_status:
return iq, "No error."
else:
return iq

def IQSTREAM_Acquire(self, dur_msec, return_status):
return self.IQSTREAM_Tempfile_NoConfig(dur_msec, return_status)

def set_times_to_fail(self, n):
self.times_to_fail = n
Expand Down
Loading

0 comments on commit 9666495

Please sign in to comment.