Skip to content

cm: mx4_ctx reshape prev[0]>>3 + prev[1]>>4 (drop bp, widen prev[0]) … #663

cm: mx4_ctx reshape prev[0]>>3 + prev[1]>>4 (drop bp, widen prev[0]) …

cm: mx4_ctx reshape prev[0]>>3 + prev[1]>>4 (drop bp, widen prev[0]) … #663

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
build-linux:
runs-on: ubuntu-latest
strategy:
matrix:
compiler: [gcc, clang]
build_type: [Release, Debug]
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y cmake build-essential libomp-dev
- name: Configure
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_C_COMPILER=${{ matrix.compiler }}
- name: Build
run: cmake --build build --config ${{ matrix.build_type }} -j$(nproc)
- name: Run tests
run: cd build && ctest --output-on-failure --timeout 300
build-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Configure
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
- name: Build
run: cmake --build build --config Release -j$(sysctl -n hw.ncpu)
- name: Run tests
run: cd build && ctest --output-on-failure --timeout 300
build-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Configure
run: cmake -S . -B build
- name: Build
run: cmake --build build --config Release
- name: Run tests
run: cd build && ctest -C Release --output-on-failure --timeout 300
roundtrip-test:
runs-on: ubuntu-latest
needs: build-linux
steps:
- uses: actions/checkout@v4
- name: Build
run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
- name: Download Canterbury Corpus
run: |
mkdir -p /tmp/cantrbry
cd /tmp/cantrbry
wget -q https://corpus.canterbury.ac.nz/resources/cantrbry.tar.gz
tar xzf cantrbry.tar.gz 2>/dev/null || true
- name: Roundtrip test (all levels)
run: |
for f in /tmp/cantrbry/*; do
[ -f "$f" ] || continue
name=$(basename "$f")
for level in 1 3 6 9 12 20 26; do
./build/bin/mcx compress -l $level "$f" -o "/tmp/${name}.mcx"
./build/bin/mcx decompress "/tmp/${name}.mcx" -o "/tmp/${name}.dec"
if diff "$f" "/tmp/${name}.dec" > /dev/null 2>&1; then
echo "OK: $name L$level"
else
echo "FAIL: $name L$level"
exit 1
fi
rm -f "/tmp/${name}.mcx" "/tmp/${name}.dec"
done
done
coverage:
runs-on: ubuntu-latest
needs: build-linux
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y cmake build-essential libomp-dev lcov
- name: Configure with coverage
run: |
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_COMPILER=gcc \
-DMCX_CODE_COVERAGE=ON \
-DMCX_BUILD_BENCHMARKS=OFF
- name: Build
run: cmake --build build -j$(nproc)
- name: Run tests
run: cd build && ctest --output-on-failure --timeout 300
- name: Generate coverage report
run: |
lcov --capture --directory build --output-file coverage.info \
--rc branch_coverage=1 --ignore-errors unused
# Remove external/test/system files from report
lcov --remove coverage.info \
'/usr/*' \
'*/tests/*' \
'*/external/*' \
--output-file coverage.info \
--rc branch_coverage=1 --ignore-errors unused
lcov --list coverage.info --rc branch_coverage=1 --ignore-errors unused
- name: Upload coverage to Codecov
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v4
with:
files: coverage.info
flags: unittests
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- name: Upload coverage artifact
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: lcov-report
path: coverage.info
retention-days: 30
pkg-config-test:
runs-on: ubuntu-latest
needs: build-linux
steps:
- uses: actions/checkout@v4
- name: Build and install
run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
sudo cmake --install build --prefix /usr/local
- name: Test pkg-config discovery
run: |
pkg-config --exists maxcomp
echo "CFLAGS: $(pkg-config --cflags maxcomp)"
echo "LIBS: $(pkg-config --libs maxcomp)"
- name: Build minimal program via pkg-config
run: |
cat > /tmp/test_pkgconfig.c << 'EOF'
#include <maxcomp/maxcomp.h>
#include <stdio.h>
#include <string.h>
int main(void) {
const char* data = "Hello MaxCompression pkg-config test!";
size_t src_size = strlen(data);
size_t cap = mcx_compress_bound(src_size);
unsigned char comp[1024], decomp[1024];
size_t comp_size = mcx_compress(comp, cap, data, src_size, 3);
if (mcx_is_error(comp_size)) { fprintf(stderr, "compress failed\n"); return 1; }
size_t dec_size = mcx_decompress(decomp, sizeof(decomp), comp, comp_size);
if (mcx_is_error(dec_size)) { fprintf(stderr, "decompress failed\n"); return 1; }
if (dec_size != src_size || memcmp(data, decomp, src_size) != 0) {
fprintf(stderr, "roundtrip mismatch\n"); return 1;
}
printf("pkg-config integration OK: %s v%s\n", "maxcomp", mcx_version_string());
return 0;
}
EOF
gcc /tmp/test_pkgconfig.c -o /tmp/test_pkgconfig \
$(pkg-config --cflags --libs maxcomp) -lm
LD_LIBRARY_PATH=/usr/local/lib /tmp/test_pkgconfig
# TODO: Add find_package(MaxCompression) test once CMake config export is implemented
python-bindings:
runs-on: ubuntu-latest
needs: build-linux
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Build shared library
run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON
cmake --build build -j$(nproc)
- name: Test Python bindings
run: |
cp build/lib/libmaxcomp.so bindings/python/ 2>/dev/null || cp build/bin/libmaxcomp.so bindings/python/
cd bindings/python
python3 -c "
import maxcomp
data = b'Hello World! ' * 1000
compressed = maxcomp.compress(data, level=6)
restored = maxcomp.decompress(compressed)
assert restored == data, 'Roundtrip failed'
ratio = len(data) / len(compressed)
print(f'Python bindings OK: {len(data)} -> {len(compressed)} ({ratio:.1f}x)')
print(f'Version: {maxcomp.version()}')
print(f'Bound(1MB): {maxcomp.compress_bound(1048576)}')
"
valgrind:
runs-on: ubuntu-latest
needs: build-linux
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y cmake build-essential libomp-dev valgrind
- name: Build (Debug, without OpenMP for cleaner valgrind output)
run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_FLAGS="-g -O1"
cmake --build build -j$(nproc)
- name: Run tests under valgrind memcheck
run: |
cd build
ctest --output-on-failure --timeout 600 \
--overwrite MemoryCheckCommand=/usr/bin/valgrind \
--overwrite "MemoryCheckCommandOptions=--leak-check=full --error-exitcode=1 --track-origins=yes --suppressions=${{ github.workspace }}/valgrind.supp" \
-T MemCheck || true
# Show memcheck results
cat Testing/Temporary/MemoryChecker.*.log 2>/dev/null || true
- name: Valgrind roundtrip on sample data
run: |
echo "The quick brown fox jumps over the lazy dog. Pack my box with five dozen liquor jugs." > /tmp/vg_test.txt
for level in 1 3 6 9 12; do
echo "=== Level $level ==="
valgrind --leak-check=full --error-exitcode=1 --track-origins=yes --suppressions=${{ github.workspace }}/valgrind.supp \
./build/bin/mcx compress -l $level -q /tmp/vg_test.txt -o /tmp/vg_test.mcx -f
valgrind --leak-check=full --error-exitcode=1 --track-origins=yes --suppressions=${{ github.workspace }}/valgrind.supp \
./build/bin/mcx decompress -q /tmp/vg_test.mcx -o /tmp/vg_test.dec -f
diff /tmp/vg_test.txt /tmp/vg_test.dec
echo "Level $level: OK (no leaks)"
rm -f /tmp/vg_test.mcx /tmp/vg_test.dec
done
rm -f /tmp/vg_test.txt
doxygen:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Doxygen
run: sudo apt-get update && sudo apt-get install -y doxygen
- name: Generate API docs
run: doxygen Doxyfile
- name: Check for undocumented public functions
run: |
# Extract public function declarations from header
grep -oP 'MCXAPI\s+\S+\s+\K(mcx_\w+)' include/maxcomp/maxcomp.h | sort > /tmp/public_funcs.txt
echo "Public functions:"
cat /tmp/public_funcs.txt
# Check Doxygen warnings for undocumented members
if doxygen Doxyfile 2>&1 | grep -i "not documented"; then
echo "WARNING: Some public symbols are undocumented"
else
echo "All public symbols documented"
fi
- name: Upload docs artifact
uses: actions/upload-artifact@v4
with:
name: api-docs
path: docs/api/html
retention-days: 30