Skip to content

Add unit tests for encryption functionality and integration tests #22

Add unit tests for encryption functionality and integration tests

Add unit tests for encryption functionality and integration tests #22

Workflow file for this run

name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build-and-test:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
build_type: [Debug, Release]
include:
- os: ubuntu-latest
cc: clang
cxx: clang++
- os: macos-latest
cc: clang
cxx: clang++
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies (Ubuntu)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake clang-format clang-tidy libzstd-dev libsodium-dev
- name: Install dependencies (macOS)
if: matrix.os == 'macos-latest'
run: |
brew install clang-format zstd libsodium || true
# cmake is already available on macOS runners
- name: Set up environment
run: |
echo "CC=${{ matrix.cc }}" >> $GITHUB_ENV
echo "CXX=${{ matrix.cxx }}" >> $GITHUB_ENV
- name: Configure CMake
run: |
cmake -B build \
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-DCMAKE_C_COMPILER=${{ matrix.cc }} \
-DCMAKE_CXX_COMPILER=${{ matrix.cxx }} \
-DBFC_WITH_ZSTD=ON \
-DBFC_WITH_SODIUM=ON
- name: Build
run: cmake --build build --config ${{ matrix.build_type }} -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)
- name: Run tests
if: matrix.build_type == 'Debug'
run: |
cd build
ctest --output-on-failure --parallel $(nproc 2>/dev/null || sysctl -n hw.ncpu)
- name: Test CLI functionality
run: |
# Create test data
mkdir -p test_data
echo "Hello World" > test_data/hello.txt
echo "Goodbye" > test_data/bye.txt
mkdir -p test_data/subdir
echo "Nested file" > test_data/subdir/nested.txt
# Test CLI workflow
./build/bin/bfc create test.bfc test_data/
./build/bin/bfc list test.bfc
./build/bin/bfc info test.bfc
./build/bin/bfc verify test.bfc
./build/bin/bfc verify --deep test.bfc
# Test compression functionality
./build/bin/bfc create -c zstd test_compressed.bfc test_data/
./build/bin/bfc info test_compressed.bfc test_data/hello.txt
./build/bin/bfc verify test_compressed.bfc
# Test different compression levels
./build/bin/bfc create -c zstd -l 1 test_fast.bfc test_data/
./build/bin/bfc create -c zstd -l 6 test_balanced.bfc test_data/
./build/bin/bfc info test_balanced.bfc test_data/hello.txt
# Test extraction
mkdir -p extract_test
cd extract_test
../build/bin/bfc extract ../test.bfc
# Verify extracted files
[ -f hello.txt ] && echo "hello.txt extracted"
[ -f bye.txt ] && echo "bye.txt extracted"
[ -f subdir/nested.txt ] && echo "nested.txt extracted"
cd ..
rm -rf extract_test
# Test encryption functionality
echo "Testing encryption features..."
./build/bin/bfc create -e testpassword123 test_encrypted.bfc test_data/
./build/bin/bfc info test_encrypted.bfc
./build/bin/bfc info test_encrypted.bfc test_data/hello.txt | grep -i encrypt
# Test encrypted extraction
mkdir -p extract_encrypted
cd extract_encrypted
../build/bin/bfc extract -p testpassword123 ../test_encrypted.bfc
# Verify extracted files from encrypted container
[ -f hello.txt ] && echo "hello.txt extracted from encrypted container"
[ -f bye.txt ] && echo "bye.txt extracted from encrypted container"
[ -f subdir/nested.txt ] && echo "nested.txt extracted from encrypted container"
cd ..
rm -rf extract_encrypted
# Test wrong password failure
mkdir -p extract_fail_test
cd extract_fail_test
! ../build/bin/bfc extract -p wrongpassword ../test_encrypted.bfc && echo "Correctly failed with wrong password"
cd ..
rm -rf extract_fail_test
# Test key file encryption
echo -n "0123456789abcdef0123456789abcdef" > test.key
./build/bin/bfc create -k test.key test_keyfile.bfc test_data/
./build/bin/bfc info test_keyfile.bfc | grep -i encrypt
mkdir -p extract_keyfile
cd extract_keyfile
../build/bin/bfc extract -K ../test.key ../test_keyfile.bfc
[ -f hello.txt ] && echo "hello.txt extracted with key file"
cd ..
rm -rf extract_keyfile
# Test encryption with compression
echo "This is a larger test file with enough content to be compressed by zstd compression algorithm." > test_data/large.txt
./build/bin/bfc create -e testpass -c zstd test_enc_comp.bfc test_data/
./build/bin/bfc info test_enc_comp.bfc test_data/large.txt | grep -i encrypt
./build/bin/bfc info test_enc_comp.bfc test_data/large.txt | grep -i zstd
# Clean up
rm -rf test.bfc test_data test_compressed.bfc test_fast.bfc test_balanced.bfc
rm -rf test_encrypted.bfc test_keyfile.bfc test_enc_comp.bfc test.key
- name: Run benchmarks
run: |
cd build/benchmarks
./benchmark_crc32c
# Run compression benchmark (quick test)
timeout 60s ./benchmark_compress || gtimeout 60s ./benchmark_compress || echo "Compression benchmark completed or timed out"
# Run with timeout (different commands for Linux vs macOS)
if command -v timeout >/dev/null 2>&1; then
timeout 30s ./benchmark_writer || true
timeout 30s ./benchmark_reader || true
elif command -v gtimeout >/dev/null 2>&1; then
gtimeout 30s ./benchmark_writer || true
gtimeout 30s ./benchmark_reader || true
else
# macOS without coreutils - run without timeout
echo "Running benchmarks without timeout on macOS..."
./benchmark_writer &
WRITER_PID=$!
sleep 10 && kill $WRITER_PID 2>/dev/null || true
wait $WRITER_PID 2>/dev/null || true
./benchmark_reader &
READER_PID=$!
sleep 10 && kill $READER_PID 2>/dev/null || true
wait $READER_PID 2>/dev/null || true
fi
- name: Check code formatting (Ubuntu Debug only)
if: matrix.os == 'ubuntu-latest' && matrix.build_type == 'Debug'
run: |
find src include tests examples -name "*.c" -o -name "*.h" | xargs clang-format --dry-run --Werror
coverage:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake lcov bc libzstd-dev libsodium-dev
- name: Configure CMake with coverage
run: |
cmake -B build \
-DCMAKE_BUILD_TYPE=Debug \
-DBFC_COVERAGE=ON \
-DBFC_WITH_ZSTD=ON \
-DBFC_WITH_SODIUM=ON \
-DBFC_BUILD_BENCHMARKS=OFF \
-DCMAKE_C_FLAGS="--coverage -fprofile-arcs -ftest-coverage"
- name: Build
run: cmake --build build -j$(nproc)
- name: Run tests
run: |
cd build
ctest --output-on-failure
- name: Generate coverage report
run: |
cd build
lcov --capture --directory . --output-file coverage.info \
--rc branch_coverage=1 \
--ignore-errors deprecated,unsupported,unused
lcov --remove coverage.info \
'*/tests/*' \
--output-file coverage_filtered.info \
--rc branch_coverage=1 \
--ignore-errors deprecated,unsupported,unused
lcov --list coverage_filtered.info \
--rc branch_coverage=1 \
--ignore-errors deprecated,unsupported,unused
- name: Check coverage thresholds
run: |
cd build
# Generate summary and check thresholds
lcov --summary coverage_filtered.info \
--rc branch_coverage=1 \
--ignore-errors deprecated,unsupported,unused > coverage_summary.txt 2>&1
# Extract coverage percentages
LINE_COV=$(grep "lines" coverage_summary.txt | grep -o '[0-9]\+\.[0-9]\+%' | head -1 | sed 's/%//')
FUNC_COV=$(grep "functions" coverage_summary.txt | grep -o '[0-9]\+\.[0-9]\+%' | head -1 | sed 's/%//')
BRANCH_COV=$(grep "branches" coverage_summary.txt | grep -o '[0-9]\+\.[0-9]\+%' | head -1 | sed 's/%//')
echo "Coverage Summary:"
echo "Lines: ${LINE_COV}%"
echo "Functions: ${FUNC_COV}%"
echo "Branches: ${BRANCH_COV}%"
# Set coverage threshold based on current achievable coverage
THRESHOLD=72
# Check thresholds using bc for floating point comparison
if command -v bc >/dev/null 2>&1; then
LINE_FAIL=$(echo "${LINE_COV} < ${THRESHOLD}" | bc -l)
FUNC_FAIL=$(echo "${FUNC_COV} < 95" | bc -l) # High threshold for functions
if [ "${LINE_FAIL}" = "1" ]; then
echo "ERROR: Line coverage ${LINE_COV}% is below threshold ${THRESHOLD}%"
exit 1
fi
if [ "${FUNC_FAIL}" = "1" ]; then
echo "ERROR: Function coverage ${FUNC_COV}% is below threshold 95%"
exit 1
fi
echo "All coverage thresholds met!"
else
echo "bc not available, skipping threshold checks"
fi
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
file: build/coverage_filtered.info
fail_ci_if_error: false
static-analysis:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake clang-tidy cppcheck libzstd-dev libsodium-dev
- name: Configure CMake
run: cmake -B build -DCMAKE_BUILD_TYPE=Debug -DBFC_WITH_ZSTD=ON -DBFC_WITH_SODIUM=ON
- name: Run clang-tidy
run: |
cd build
run-clang-tidy -p . ../src/ || true
- name: Run cppcheck
run: |
cppcheck --enable=all --inconclusive --xml --xml-version=2 \
--suppress=missingIncludeSystem \
--suppress=unmatchedSuppression \
src/ include/ 2> cppcheck.xml || true
# Show results (non-blocking)
cat cppcheck.xml
security:
runs-on: ubuntu-latest
# Add permissions for security scanning
permissions:
contents: read
security-events: write
actions: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run CodeQL Analysis
uses: github/codeql-action/init@v3
with:
languages: cpp
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake libzstd-dev libsodium-dev
- name: Build for CodeQL
run: |
cmake -B build -DCMAKE_BUILD_TYPE=Release -DBFC_WITH_ZSTD=ON -DBFC_WITH_SODIUM=ON -DBFC_BUILD_BENCHMARKS=OFF
cmake --build build
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
documentation:
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
# Add permissions for GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Environment for GitHub Pages deployment
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y doxygen graphviz
- name: Generate documentation
run: |
# Create Doxygen config if it doesn't exist
if [ ! -f Doxyfile ]; then
doxygen -g
sed -i 's/PROJECT_NAME = "My Project"/PROJECT_NAME = "BFC"/' Doxyfile
sed -i 's/INPUT =/INPUT = include\/ src\/ README.md/' Doxyfile
sed -i 's/RECURSIVE = NO/RECURSIVE = YES/' Doxyfile
sed -i 's/GENERATE_HTML = YES/GENERATE_HTML = YES/' Doxyfile
sed -i 's/OUTPUT_DIRECTORY =/OUTPUT_DIRECTORY = docs/' Doxyfile
fi
doxygen Doxyfile
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/html
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4