Skip to content

Commit 9c8a0e1

Browse files
authored
Merge pull request #681 from medengineer/add-GHA-tests
Run unit and integration tests on PRs to development and testing
2 parents 2064ffc + 01cc224 commit 9c8a0e1

File tree

8 files changed

+194
-26
lines changed

8 files changed

+194
-26
lines changed

.github/workflows/tests.yml

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
name: Tests
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- 'JuceLibraryCode/**'
7+
- 'Plugins/**'
8+
- 'Resources/**'
9+
- 'Source/**'
10+
- 'CMakeLists.txt'
11+
- 'HelperFunctions.cmake'
12+
branches:
13+
- 'development'
14+
- 'testing'
15+
16+
jobs:
17+
unit-tests:
18+
name: Unit Tests
19+
runs-on: ubuntu-22.04
20+
21+
steps:
22+
- uses: actions/checkout@v4
23+
- name: build
24+
env:
25+
CC: gcc-10
26+
CXX: g++-10
27+
run: |
28+
sudo apt update
29+
sudo ./Resources/Scripts/install_linux_dependencies.sh
30+
git apply Resources/Scripts/gha_unit_tests.patch
31+
cd Build && cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON ..
32+
make -j8
33+
- name: run tests
34+
run: |
35+
chmod +x ./Resources/Scripts/run_unit_tests_linux.sh
36+
./Resources/Scripts/run_unit_tests_linux.sh Build/TestBin
37+
shell: bash
38+
39+
integration-tests:
40+
name: Integration Tests
41+
runs-on: windows-2022
42+
43+
steps:
44+
- uses: actions/checkout@v4
45+
with:
46+
fetch-depth: 0
47+
- name: Setup Python
48+
uses: actions/setup-python@v5
49+
with:
50+
python-version: '3.13'
51+
- name: Start Windows Audio Engine
52+
run: net start audiosrv
53+
- name: Install Scream
54+
shell: powershell
55+
run: |
56+
Start-Service audio*
57+
Invoke-WebRequest https://github.com/duncanthrax/scream/releases/download/3.6/Scream3.6.zip -OutFile C:\Scream3.6.zip
58+
Expand-7ZipArchive -Path C:\Scream3.6.zip -DestinationPath C:\Scream
59+
$cert = (Get-AuthenticodeSignature C:\Scream\Install\driver\Scream.sys).SignerCertificate
60+
$store = [System.Security.Cryptography.X509Certificates.X509Store]::new("TrustedPublisher", "LocalMachine")
61+
$store.Open("ReadWrite")
62+
$store.Add($cert)
63+
$store.Close()
64+
cd C:\Scream\Install\driver
65+
C:\Scream\Install\helpers\devcon install Scream.inf *Scream
66+
- name: Show audio device
67+
run: Get-CimInstance Win32_SoundDevice | fl *
68+
- name: configure
69+
run: |
70+
cd Build
71+
cmake -G "Visual Studio 17 2022" -A x64 ..
72+
- name: Add msbuild to PATH
73+
uses: microsoft/[email protected]
74+
- name: build
75+
run: |
76+
cd Build
77+
msbuild ALL_BUILD.vcxproj -p:Configuration=Release -p:Platform=x64 -m
78+
- name: Install open-ephys-data-format
79+
shell: powershell
80+
run: |
81+
New-Item -Path '..\OEPlugins' -ItemType Directory
82+
git clone --branch main https://github.com/open-ephys-plugins/open-ephys-data-format.git ..\OEPlugins\open-ephys-data-format
83+
cd ..\OEPlugins\open-ephys-data-format\Build
84+
cmake -G "Visual Studio 17 2022" -A x64 ..
85+
msbuild INSTALL.vcxproj -p:Configuration=Release -p:Platform=x64
86+
- name: Install OpenEphysHDF5Lib
87+
shell: powershell
88+
run: |
89+
git clone --branch main https://github.com/open-ephys-plugins/OpenEphysHDF5Lib.git ..\OEPlugins\OpenEphysHDF5Lib
90+
cd ..\OEPlugins\OpenEphysHDF5Lib\Build
91+
cmake -G "Visual Studio 17 2022" -A x64 ..
92+
msbuild INSTALL.vcxproj -p:Configuration=Release -p:Platform=x64
93+
- name: Install nwb-format
94+
shell: powershell
95+
run: |
96+
git clone --branch main https://github.com/open-ephys-plugins/nwb-format.git ..\OEPlugins\nwb-format
97+
cd ..\OEPlugins\nwb-format\Build
98+
cmake -G "Visual Studio 17 2022" -A x64 ..
99+
msbuild INSTALL.vcxproj -p:Configuration=Release -p:Platform=x64
100+
- name: Install test-suite
101+
shell: powershell
102+
run: |
103+
git clone --branch main https://github.com/open-ephys/open-ephys-python-tools.git C:\open-ephys-python-tools
104+
cd C:\open-ephys-python-tools
105+
pip install -e .
106+
pip install psutil
107+
- name: Run Tests
108+
shell: powershell
109+
run: |
110+
New-Item -Path 'C:\open-ephys\data' -ItemType Directory
111+
git clone --branch main https://github.com/open-ephys/open-ephys-test-suite.git C:\test-suite
112+
cd C:\test-suite
113+
$process = Start-Process -FilePath "Build\Release\open-ephys.exe" -ArgumentList "Build\Release\configs\file_reader_config.xml" -NoNewWindow -PassThru
114+
Write-Host "Started open-ephys process with ID: $($process.Id)"
115+
Start-Sleep -Seconds 10
116+
Write-Host "Starting Python script..."
117+
python run_all.py 2>&1 | Tee-Object -FilePath "python_output.log"
118+
Write-Host "Python script completed. Output saved to python_output.log"
119+
Stop-Process -Id $process.Id -Force
120+
env:
121+
OE_WINDOWS_GITHUB_RECORD_PATH: C:\open-ephys\data
122+
- name: Set timestamp
123+
shell: powershell
124+
id: timestamp
125+
run: |
126+
$timestamp = Get-Date -Format 'yyyy_MM_dd_HH_mm_ss'
127+
"timestamp=$timestamp" >> $env:GITHUB_OUTPUT
128+
- name: Upload test results
129+
uses: actions/upload-artifact@v4
130+
with:
131+
name: windows_${{ steps.timestamp.outputs.timestamp }}.log
132+
path: python_output.log
133+
retention-days: 7

Plugins/LfpViewer/Tests/LfpDisplayNodeTests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ TEST_F (LfpDisplayNodeTests, VisualIntegrityTest)
319319
Rectangle<int> canvasSnapshot (x, y, width, height);
320320
ExpectedImage expected (numChannels, sampleRate * 2); //2 seconds to match canvas timebase
321321

322-
tester->startAcquisition (false);
322+
processor->startAcquisition ();
323323
canvas->beginAnimation();
324324

325325
//Add 5 10Hz waves with +-125uV amplitude
@@ -367,16 +367,16 @@ TEST_F (LfpDisplayNodeTests, VisualIntegrityTest)
367367
missCount = getImageDifferencePixelCount (expectedImage, canvasImage);
368368
EXPECT_LE (float (missCount) / float (width * height), errorThreshold);
369369

370-
tester->stopAcquisition();
370+
processor->stopAcquisition();
371371
}
372372

373373
TEST_F (LfpDisplayNodeTests, DataIntegrityTest)
374374
{
375375
int numSamples = 100;
376-
tester->startAcquisition (false);
376+
processor->startAcquisition ();
377377

378378
auto inputBuffer = createBuffer (1000.0, 20.0, numChannels, numSamples);
379379
writeBlock (inputBuffer);
380380

381-
tester->stopAcquisition();
381+
processor->stopAcquisition();
382382
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
diff --git a/Tests/Processors/CMakeLists.txt b/Tests/Processors/CMakeLists.txt
2+
index a89fa4da4..ab53e8d89 100644
3+
--- a/Tests/Processors/CMakeLists.txt
4+
+++ b/Tests/Processors/CMakeLists.txt
5+
@@ -5,8 +5,8 @@ add_sources(${COMPONENT_NAME}_tests
6+
DataBufferTests.cpp
7+
PluginManagerTests.cpp
8+
SourceNodeTests.cpp
9+
- RecordNodeTests.cpp
10+
- ProcessorGraphTests.cpp
11+
+ #RecordNodeTests.cpp
12+
+ #ProcessorGraphTests.cpp
13+
EventTests.cpp
14+
DataThreadTests.cpp
15+
GenericProcessorTests.cpp
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
3+
# Use first argument as TEST_DIR if provided, otherwise use default
4+
TEST_DIR="${1:-../../Build/TestBin}"
5+
6+
# Track overall exit code
7+
EXIT_CODE=0
8+
9+
# Find all executable files that are not .so files
10+
for test_exec in $(find "$TEST_DIR" -type f -executable ! -name "*.so"); do
11+
echo "Running test: $test_exec"
12+
"$test_exec"
13+
TEST_RESULT=$?
14+
if [ $TEST_RESULT -ne 0 ]; then
15+
EXIT_CODE=1
16+
fi
17+
echo "----------------------------------------"
18+
done
19+
20+
exit $EXIT_CODE

Tests/Processors/DataThreadTests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,11 @@ class DataThreadTests : public testing::Test
115115

116116
TEST_F(DataThreadTests, DataIntegrity)
117117
{
118-
tester->startAcquisition(false);
118+
processor->startAcquisition();
119119

120120
int numSamples = 100;
121121
auto inputBuffer = createBuffer(1000.0, 20.0, 5, numSamples);
122122
writeBlock(inputBuffer);
123123

124-
tester->stopAcquisition();
124+
processor->stopAcquisition();
125125
}

Tests/Processors/RecordNodeTests.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,14 @@ class RecordNodeTests : public testing::Test {
220220

221221
TEST_F(RecordNodeTests, TestInputOutput_Continuous_Single) {
222222
int numSamples = 100;
223-
tester->startAcquisition(true);
223+
processor->startAcquisition();
224224

225225
auto inputBuffer = createBuffer(1000.0, 20.0, numChannels, numSamples);
226226
writeBlock(inputBuffer);
227227

228228
// The record node always flushes its pending writes when stopping acquisition, so we don't need to sleep before
229229
// stopping.
230-
tester->stopAcquisition();
230+
processor->stopAcquisition();
231231

232232
std::vector<int16_t> persistedData;
233233
loadContinuousDatFile(&persistedData);
@@ -245,7 +245,7 @@ TEST_F(RecordNodeTests, TestInputOutput_Continuous_Single) {
245245
}
246246

247247
TEST_F(RecordNodeTests, TestInputOutput_Continuous_Multiple) {
248-
tester->startAcquisition(true);
248+
processor->startAcquisition();
249249

250250
int numSamplesPerBlock = 100;
251251
int numBlocks = 8;
@@ -256,7 +256,7 @@ TEST_F(RecordNodeTests, TestInputOutput_Continuous_Multiple) {
256256
inputBuffers.push_back(inputBuffer);
257257
}
258258

259-
tester->stopAcquisition();
259+
processor->stopAcquisition();
260260

261261
std::vector<int16_t> persistedData;
262262
loadContinuousDatFile(&persistedData);
@@ -277,8 +277,8 @@ TEST_F(RecordNodeTests, TestInputOutput_Continuous_Multiple) {
277277
}
278278

279279
TEST_F(RecordNodeTests, TestEmpty) {
280-
tester->startAcquisition(true);
281-
tester->stopAcquisition();
280+
processor->startAcquisition();
281+
processor->stopAcquisition();
282282

283283
std::vector<int16_t> persistedData;
284284
loadContinuousDatFile(&persistedData);
@@ -287,7 +287,7 @@ TEST_F(RecordNodeTests, TestEmpty) {
287287

288288
TEST_F(RecordNodeTests, TestClipsProperly) {
289289
int numSamples = 100;
290-
tester->startAcquisition(true);
290+
processor->startAcquisition();
291291

292292
// The min value is actually -32767, not -32768 like the "true" min
293293
std::vector<AudioBuffer<float>> inputBuffers;
@@ -301,7 +301,7 @@ TEST_F(RecordNodeTests, TestClipsProperly) {
301301
writeBlock(inputBuffer);
302302
inputBuffers.push_back(inputBuffer);
303303

304-
tester->stopAcquisition();
304+
processor->stopAcquisition();
305305

306306
std::vector<int16_t> persistedData;
307307
loadContinuousDatFile(&persistedData);
@@ -341,10 +341,10 @@ class CustomBitVolts_RecordNodeTests : public RecordNodeTests {
341341

342342
TEST_F(CustomBitVolts_RecordNodeTests, Test_RespectsBitVolts) {
343343
int numSamples = 100;
344-
tester->startAcquisition(true);
344+
processor->startAcquisition();
345345
auto inputBuffer = createBuffer(1000.0, 20.0, numChannels, numSamples);
346346
writeBlock(inputBuffer);
347-
tester->stopAcquisition();
347+
processor->stopAcquisition();
348348

349349
std::vector<int16_t> persistedData;
350350
loadContinuousDatFile(&persistedData);
@@ -370,7 +370,7 @@ TEST_F(CustomBitVolts_RecordNodeTests, Test_RespectsBitVolts) {
370370
}
371371

372372
TEST_F(RecordNodeTests, Test_PersistsSampleNumbersAndTimestamps) {
373-
tester->startAcquisition(true);
373+
processor->startAcquisition();
374374

375375
int numSamples = 5;
376376
for (int i = 0; i < 3; i++) {
@@ -417,7 +417,7 @@ TEST_F(RecordNodeTests, Test_PersistsSampleNumbersAndTimestamps) {
417417
}
418418

419419
TEST_F(RecordNodeTests, Test_PersistsStructureOeBin) {
420-
tester->startAcquisition(true);
420+
processor->startAcquisition();
421421

422422
int numSamples = 5;
423423
for (int i = 0; i < 3; i++) {
@@ -479,7 +479,7 @@ TEST_F(RecordNodeTests, Test_PersistsEvents) {
479479
processor->setRecordEvents(true);
480480
processor->updateSettings();
481481

482-
tester->startAcquisition(true);
482+
processor->startAcquisition();
483483
int numSamples = 5;
484484

485485
auto streamId = processor->getDataStreams()[0]->getStreamId();
@@ -492,7 +492,7 @@ TEST_F(RecordNodeTests, Test_PersistsEvents) {
492492
true);
493493
auto inputBuffer = createBuffer(1000.0, 20.0, numChannels, numSamples);
494494
writeBlock(inputBuffer, eventPtr.get());
495-
tester->stopAcquisition();
495+
processor->stopAcquisition();
496496

497497
std::filesystem::path sampleNumbersPath;
498498
ASSERT_TRUE(eventsPathFor("sample_numbers.npy", &sampleNumbersPath));

Tests/Processors/SourceNodeTests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,11 @@ This test verifies that given a Data Thread, the Source Node will perform this w
127127
*/
128128
TEST_F(SourceNodeTests, DataAcquisition)
129129
{
130-
tester->startAcquisition(false);
130+
tester->getSourceNode()->startAcquisition();
131131

132132
int numSamples = 100;
133133
auto inputBuffer = createBuffer(1000.0, 20.0, 5, numSamples);
134134
writeBlock(inputBuffer);
135135

136-
tester->stopAcquisition();
136+
tester->getSourceNode()->stopAcquisition();
137137
}

Tests/TestHelpers/include/TestFixtures.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@ class ProcessorTester
7979
LookAndFeel::setDefaultLookAndFeel (customLookAndFeel.get());
8080

8181
// All of these sets the global state in AccessClass in their constructors
82-
audioComponent = std::make_unique<AudioComponent>();
82+
//audioComponent = std::make_unique<AudioComponent>();
8383
processorGraph = std::make_unique<ProcessorGraph> (true);
84-
controlPanel = std::make_unique<ControlPanel> (processorGraph.get(), audioComponent.get(), true);
84+
//controlPanel = std::make_unique<ControlPanel> (processorGraph.get(), audioComponent.get(), true);
8585

8686
SourceNode* snTemp = sourceNodeBuilder.buildSourceNode();
8787
sourceNodeId = nextProcessorId++;
@@ -97,12 +97,12 @@ class ProcessorTester
9797
sn->initialize (false);
9898
sn->setDestNode (nullptr);
9999

100-
controlPanel->updateRecordEngineList();
100+
//controlPanel->updateRecordEngineList();
101101

102102
// Refresh everything
103103
processorGraph->updateSettings (sn);
104104

105-
controlPanel->colourChanged();
105+
//controlPanel->colourChanged();
106106
}
107107

108108
virtual ~ProcessorTester()

0 commit comments

Comments
 (0)