diff --git a/.devcontainer/Dockerfile.ubuntu-20.04 b/.devcontainer/Dockerfile.ubuntu-20.04 index 20d5880..b466ed4 100644 --- a/.devcontainer/Dockerfile.ubuntu-20.04 +++ b/.devcontainer/Dockerfile.ubuntu-20.04 @@ -1,7 +1,7 @@ FROM ubuntu:20.04 RUN apt-get update && \ - apt-get install -y + apt-get upgrade -y RUN sed -i 's/^# \(.*export LS_OPTIONS.*$\)/\1/g' ~/.bashrc && \ sed -i 's/^# \(.*alias ll.*$\)/\1/g' ~/.bashrc diff --git a/.devcontainer/Dockerfile.ubuntu-latest b/.devcontainer/Dockerfile.ubuntu-latest index e9f5ebc..60bdd95 100644 --- a/.devcontainer/Dockerfile.ubuntu-latest +++ b/.devcontainer/Dockerfile.ubuntu-latest @@ -1,7 +1,7 @@ FROM ubuntu:latest RUN apt-get update && \ - apt-get install -y + apt-get upgrade -y RUN sed -i 's/^# \(.*export LS_OPTIONS.*$\)/\1/g' ~/.bashrc && \ sed -i 's/^# \(.*alias ll.*$\)/\1/g' ~/.bashrc diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 099ffa2..751106f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -21,7 +21,8 @@ "ms-vscode.cpptools-extension-pack", "twxs.cmake", "streetsidesoftware.code-spell-checker", - "ms-azuretools.vscode-docker" + "ms-azuretools.vscode-docker", + "github.vscode-github-actions" ] } }, diff --git a/.github/install_dependencies b/.github/install_dependencies index 31147d0..c179468 100755 --- a/.github/install_dependencies +++ b/.github/install_dependencies @@ -8,12 +8,12 @@ case "${unameOut}" in Linux*) echo "Installing Linux dependencies" sudo apt-get update -y - sudo apt-get install -y \ + sudo apt-get install -y --no-install-recommends \ build-essential \ cmake \ libmp3lame-dev \ libshout3-dev \ - libconfig++-dev \ + 'libconfig++-dev' \ libfftw3-dev \ librtlsdr-dev \ libsoapysdr-dev \ diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml new file mode 100644 index 0000000..942677f --- /dev/null +++ b/.github/workflows/integration_tests.yml @@ -0,0 +1,19 @@ +name: Integration Tests + +on: + push: + branches: [main, unstable] + pull_request: + schedule: + - cron: '39 13 * * *' # run daily + +jobs: + build: + runs-on: [rpi3b] + timeout-minutes: 10 + steps: + - name: Checkout repository + uses: actions/checkout@main + + - name: Integration Tests + run: integration_tests/run diff --git a/.gitignore b/.gitignore index 2f6658a..32a0aad 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ build*/ .cache compile_commands.json rtl_airband*.log +integration_tests/rpiv2 +integration_tests/native diff --git a/integration_tests/configs/noaa.conf b/integration_tests/configs/noaa.conf new file mode 100644 index 0000000..91fd527 --- /dev/null +++ b/integration_tests/configs/noaa.conf @@ -0,0 +1,222 @@ +fft_size = 512; +devices: +( + { + type = "rtlsdr"; + serial = "device1"; + gain = 16.6; + centerfreq = 162.00000; + correction = 0; + sample_rate = 2.40; + channels: + ( + { + freq = 162.40000; + label = "NOAA 162.400 (162.40000)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.400_rtlsdr"; + } + ); + }, + { + freq = 162.42500; + label = "NOAA 162.425 (162.42500)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.425_rtlsdr"; + } + ); + }, + { + freq = 162.45000; + label = "NOAA 162.450 (162.45000)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.450_rtlsdr"; + } + ); + }, + { + freq = 162.47500; + label = "NOAA 162.475 (162.47500)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.475_rtlsdr"; + } + ); + }, + { + freq = 162.50000; + label = "NOAA 162.500 (162.50000)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.500_rtlsdr"; + } + ); + }, + { + freq = 162.52500; + label = "NOAA 162.525 (162.52500)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.525_rtlsdr"; + } + ); + }, + { + freq = 162.55000; + label = "NOAA 162.550 (162.55000)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.550_rtlsdr"; + } + ); + } + ); + }, + { + type = "soapysdr"; + device_string = "driver=airspy,device_id=0"; + gain = 16.6; + centerfreq = 162.00000; + correction = 0; + sample_rate = 3.0; + channels: + ( + { + freq = 162.40000; + label = "NOAA 162.400 (162.40000)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.400_soapysdr"; + } + ); + }, + { + freq = 162.42500; + label = "NOAA 162.425 (162.42500)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.425_soapysdr"; + } + ); + }, + { + freq = 162.45000; + label = "NOAA 162.450 (162.45000)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.450_soapysdr"; + } + ); + }, + { + freq = 162.47500; + label = "NOAA 162.475 (162.47500)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.475_soapysdr"; + } + ); + }, + { + freq = 162.50000; + label = "NOAA 162.500 (162.50000)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.500_soapysdr"; + } + ); + }, + { + freq = 162.52500; + label = "NOAA 162.525 (162.52500)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.525_soapysdr"; + } + ); + }, + { + freq = 162.55000; + label = "NOAA 162.550 (162.55000)"; + modulation = "nfm"; + squelch_snr_threshold = 0.00; + outputs: + ( + { + type = "file"; + directory = "./"; + filename_template = "NOAA_162.550_soapysdr"; + } + ); + } + ); + } +); diff --git a/integration_tests/run b/integration_tests/run new file mode 100755 index 0000000..a4d92d9 --- /dev/null +++ b/integration_tests/run @@ -0,0 +1,81 @@ +#!/bin/bash + +set -x +set -e + +function run_rtl_airband { + BIN_PATH=$1 + CONFIG_PATH=$2 + OUTPUT_DIR=$3 + + mkdir -p ${OUTPUT_DIR} + pushd ${OUTPUT_DIR} + + # run for 30 seconds then send kill command + sudo ${BIN_PATH} -c ${CONFIG_PATH} -F -e & + PID=$! + sleep 30 + sudo kill -SIGINT $PID + + # wait 5 seconds for files to be closed and renamed + sleep 5 + + # make sure there is at least one NOAA channel that generated an MP3 longer + # than 10 seconds for each rtl and soapy (not 30 seconds because of startup time) + check_length '*_rtlsdr_*.mp3' + check_length '*_soapysdr_*.mp3' + + popd + +} + +function check_length { + + for i in $@ ; do + + seconds=$(ffmpeg -i $i -f null - 2>&1 | grep time | awk '{print $2}' | cut -d ':' -f 3) + echo "$i is $seconds sec long" + if (( $(echo "$seconds > 10.0" | bc -l) )); then + return 0 + fi + + done + + return -1 + +} + +REPO_DIR=$(readlink -f `dirname ${0}`/../) + +INTEGRATION_TESTS_DIR=${REPO_DIR}/integration_tests + +# make a work dir +WORK_DIR=${INTEGRATION_TESTS_DIR}/work +rm -rf ${WORK_DIR} || true + +cd ${REPO_DIR} + +# build a version that uses the Broadcom VideoCore GPU +GPU_BUILD_DIR=${WORK_DIR}/build_rpiv2 +cmake -B ${GPU_BUILD_DIR} -DNFM=TRUE -DPLATFORM=rpiv2 -DCMAKE_BUILD_TYPE=Release +VERBOSE=1 cmake --build ${GPU_BUILD_DIR} -j2 + +# make sure the binary is linking about the GPU library +ldd ${GPU_BUILD_DIR}/src/rtl_airband | grep libbcm_host + + +# build a version that uses FFTW +FFTW_BUILD_DIR=${WORK_DIR}/build_native +cmake -B ${FFTW_BUILD_DIR} -DNFM=TRUE -DPLATFORM=native -DCMAKE_BUILD_TYPE=Release +VERBOSE=1 cmake --build ${FFTW_BUILD_DIR} -j2 + +# make sure the binary is linking against the FFTW library +ldd ${FFTW_BUILD_DIR}/src/rtl_airband | grep libfftw3f + + +# run the noaa config twice, once for each binary +GPU_OUTPUT_DIR=${WORK_DIR}/output_rpiv2/ +FFTW_OUTPUT_DIR=${WORK_DIR}/output_native/ +run_rtl_airband ${GPU_BUILD_DIR}/src/rtl_airband ${INTEGRATION_TESTS_DIR}/configs/noaa.conf ${GPU_OUTPUT_DIR} +run_rtl_airband ${FFTW_BUILD_DIR}/src/rtl_airband ${INTEGRATION_TESTS_DIR}/configs/noaa.conf ${FFTW_OUTPUT_DIR} +