Skip to content

Commit a542680

Browse files
author
FEO\preus
committed
add test to workflow
1 parent 74b0bbb commit a542680

File tree

3 files changed

+182
-8
lines changed

3 files changed

+182
-8
lines changed

.github/workflows/build-package.yml

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ jobs:
77
download_releases:
88
runs-on: ubuntu-latest
99
steps:
10-
- name: checkout repo
11-
uses: actions/checkout@v4
12-
1310
- name: download release asset from deterministicGaussianSampling
1411
uses: robinraju/release-downloader@v1
1512
with:
@@ -18,6 +15,92 @@ jobs:
1815
fileName: '*.zip'
1916
out-file-path: 'deterministicGaussianSamplingLibs'
2017
token: ${{ secrets.GITHUB_TOKEN }}
18+
19+
- name: ppload downloaded libs as artifact
20+
uses: actions/upload-artifact@v4
21+
with:
22+
name: deterministicGaussianSampling-libs
23+
path: deterministicGaussianSamplingLibs
24+
25+
test:
26+
needs: download_releases
27+
strategy:
28+
matrix:
29+
os: [ubuntu-latest, windows-latest] #, macos-latest]
30+
python-version: [3.9, 3.11]
31+
runs-on: ${{ matrix.os }}
32+
33+
steps:
34+
- name: checkout repo
35+
uses: actions/checkout@v4
36+
37+
- name: set up Python ${{ matrix.python-version }}
38+
uses: actions/setup-python@v5
39+
with:
40+
python-version: ${{ matrix.python-version }}
41+
42+
- name: get deterministicGaussianSampling libs
43+
uses: actions/download-artifact@v4
44+
with:
45+
name: deterministicGaussianSampling-libs
46+
path: external_libs
47+
48+
- name: extract ZIP on Unix
49+
if: ${{ runner.os == 'Linux' }}
50+
run: |
51+
unzip external_libs/linux.zip -d external_libs_unpacked
52+
mkdir -p src/deterministic_gaussian_sampling/lib/linux/bin
53+
cp -r external_libs_unpacked/lib/* src/deterministic_gaussian_sampling/lib/linux/bin
54+
55+
- name: extract ZIP on Windows
56+
if: ${{ runner.os == 'Windows' }}
57+
shell: pwsh
58+
run: |
59+
Expand-Archive -Path external_libs/windows.zip -DestinationPath external_libs_unpacked -Force
60+
New-Item -ItemType Directory -Path src\deterministic_gaussian_sampling\lib\windows\bin -Force
61+
Copy-Item external_libs_unpacked\bin\* src\deterministic_gaussian_sampling\lib\windows\bin -Recurse -Force
62+
63+
- name: install package
64+
run: pip install -e .
65+
66+
- name: run tests
67+
run: pytest -v
68+
69+
70+
71+
name: Download OS‑specific release and test
72+
73+
on:
74+
push:
75+
workflow_dispatch:
76+
77+
jobs:
78+
test:
79+
strategy:
80+
matrix:
81+
os: [ubuntu-latest, windows-latest]
82+
runs-on: ${{ matrix.os }}
83+
84+
steps:
85+
- uses: actions/checkout@v4
86+
87+
- name: Download release asset
88+
uses: robinraju/release-downloader@v1
89+
with:
90+
repository: 'OWNER/REPO' # replace with actual
91+
latest: true
92+
fileName: ${{ matrix.os == 'windows-latest' && 'windows.zip' || 'linux.zip' }}
93+
out-file-path: external_libs
94+
token: ${{ secrets.GITHUB_TOKEN }}
95+
96+
- name: Extract archive
97+
if: runner.os != 'Windows'
98+
run: unzip external_libs/linux.zip -d external_libs_unpacked
99+
100+
- name: Extract archive on Windows
101+
if: runner.os == 'Windows'
102+
shell: pwsh
103+
run: Expand-Archive -Path external_libs/windows.zip -DestinationPath external_libs_unpacked -Force
104+
105+
# ... then run your tests etc.
21106

22-
- name: list extracted files
23-
run: ls -R deterministicGaussianSamplingLibs

src/deterministic_gaussian_sampling/dll_handling/dynamic_dll_loading.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
from pathlib import Path
21
import ctypes
2+
import platform
3+
from pathlib import Path
34

45
import deterministic_gaussian_sampling.type_wrapper.ctypes_wrapper as ctypes_wrapper
56

@@ -113,6 +114,17 @@ def _setup_ctypes_dll(cdll: ctypes.CDLL) -> ctypes.CDLL:
113114

114115
def load_dll() -> ctypes.CDLL:
115116
package_root = Path(__file__).resolve().parent.parent
116-
dll_path = package_root / "lib" / "windows" / "bin" / "libapproxLCD.dll"
117117

118-
return _setup_ctypes_dll(ctypes.CDLL(dll_path))
118+
system = platform.system()
119+
if system == "Windows":
120+
dll_rel = Path("lib") / "windows" / "bin" / "libapproxLCD.dll"
121+
elif system == "Linux":
122+
dll_rel = Path("lib") / "linux" / "bin" / "libapproxLCD.so"
123+
elif system == "Darwin":
124+
dll_rel = Path("lib") / "macos" / "bin" / "libapproxLCD.dylib"
125+
else:
126+
raise RuntimeError(f"Unsupported OS: {system}")
127+
128+
dll_path = package_root / dll_rel
129+
130+
return _setup_ctypes_dll(ctypes.CDLL(dll_path))

tests/test_dirac_to_dirac.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import deterministic_gaussian_sampling
2+
import numpy as np
3+
from scipy import stats
4+
import pytest
5+
6+
def compare_stats(full: np.ndarray, reduced: np.ndarray, rtol=1e-1, atol=1e-2):
7+
"""
8+
Compare the statistics of two datasets.
9+
Raises AssertionError if they differ more than allowed tolerances.
10+
"""
11+
assert full.ndim == 2 and reduced.ndim == 2
12+
assert full.shape[1] == reduced.shape[1] # same dimensionality
13+
14+
# Compute mean, variance, std
15+
stats_full = {
16+
'mean': full.mean(axis=0),
17+
'var': full.var(axis=0, ddof=1),
18+
'std': full.std(axis=0, ddof=1)
19+
}
20+
stats_red = {
21+
'mean': reduced.mean(axis=0),
22+
'var': reduced.var(axis=0, ddof=1),
23+
'std': reduced.std(axis=0, ddof=1)
24+
}
25+
26+
# Assert that means and stds are approximately equal
27+
np.testing.assert_allclose(stats_full['mean'], stats_red['mean'], rtol=rtol, atol=atol)
28+
np.testing.assert_allclose(stats_full['std'], stats_red['std'], rtol=rtol, atol=atol)
29+
30+
# Optionally: per-dimension Welch's t-test
31+
for dim in range(full.shape[1]):
32+
t_stat, p_val = stats.ttest_ind(full[:, dim], reduced[:, dim], equal_var=False)
33+
# Expect p-value > 0.05 (no significant difference)
34+
assert p_val > 0.05, f"Significant difference in dimension {dim}: p={p_val:.3f}"
35+
36+
37+
@pytest.mark.parametrize("M,L,N", [
38+
(100, 3, 2),
39+
(100, 5, 8),
40+
(250, 5, 3),
41+
(250, 20, 9),
42+
(500, 5, 3),
43+
# (500, 75, 20),
44+
# (750, 5, 3),
45+
# (750, 50, 12),
46+
# (1000, 100, 3),
47+
# (1000, 100, 15),
48+
])
49+
def test_dirac_approximation_simple(M, L, N, seed=42):
50+
np.random.seed(seed)
51+
x = np.random.rand(L, N)
52+
y = np.random.rand(M, N)
53+
d2dApprox = deterministic_gaussian_sampling.DiracToDiracApproximation()
54+
result = d2dApprox.approximate_double(y, M, L, N, x)
55+
56+
# Compare statistics between original and reduced sets
57+
compare_stats(x, result.x)
58+
59+
@pytest.mark.parametrize("M,L,N", [
60+
(100, 3, 2),
61+
(100, 5, 8),
62+
(250, 5, 3),
63+
(250, 20, 9),
64+
(500, 5, 3),
65+
# (500, 75, 20),
66+
# (750, 5, 3),
67+
# (750, 50, 12),
68+
# (1000, 100, 3),
69+
# (1000, 100, 15),
70+
])
71+
def test_dirac_approximation_threaded(M, L, N, seed=42):
72+
np.random.seed(seed)
73+
x = np.random.rand(L, N)
74+
y = np.random.rand(M, N)
75+
d2dApprox = deterministic_gaussian_sampling.DiracToDiracApproximation()
76+
result = d2dApprox.approximate_thread_double(y, M, L, N, x)
77+
78+
# Compare statistics between original and reduced sets
79+
compare_stats(x, result.x)

0 commit comments

Comments
 (0)