Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/phpt_runner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
// Minimal PHPT runner supporting --SKIPIF--, --FILE--, --EXPECT--
if ($argc < 2) {
fwrite(STDERR, "Usage: php phpt_runner.php <testfile.phpt>\n");
exit(1);
}
$testFile = $argv[1];
$contents = file_get_contents($testFile);
$sections = [];
$current = null;
foreach (preg_split('/\r?\n/', $contents) as $line) {
if (preg_match('/^--([A-Z]+)--$/', $line, $m)) {
$current = $m[1];
$sections[$current] = '';
} elseif ($current) {
$sections[$current] .= $line . "\n";
}
}
$php = escapeshellcmd(PHP_BINARY);
$extArg = getenv('PHPT_ADD_EXTENSION') ? ' -d extension=blake3 ' : ' ';
if (isset($sections['SKIPIF'])) {
$code = $sections['SKIPIF'];
$tmpSkip = tempnam(sys_get_temp_dir(), 'phpt_skip_') . '.php';
file_put_contents($tmpSkip, $code);
$cmd = $php . $extArg . escapeshellarg($tmpSkip);
$out = shell_exec($cmd);
unlink($tmpSkip);
if ($out !== null && preg_match('/^skip/i', trim($out))) {
echo basename($testFile) . ": SKIPPED\n";
exit(0);
}
}
if (!isset($sections['FILE']) || !isset($sections['EXPECT'])) {
fwrite(STDERR, "Missing required sections in $testFile\n");
exit(1);
}
$code = $sections['FILE'];
$tmpFile = tempnam(sys_get_temp_dir(), 'phpt_') . '.php';
file_put_contents($tmpFile, $code);
$cmd = $php . $extArg . escapeshellarg($tmpFile);
$actual = shell_exec($cmd);
unlink($tmpFile);
$expected = $sections['EXPECT'];
// Normalize trailing newlines
$actualNorm = rtrim($actual ?? '', "\r\n") . "\n";
$expectedNorm = rtrim($expected, "\r\n") . "\n";
if ($actualNorm === $expectedNorm) {
echo basename($testFile) . ": PASS\n";
exit(0);
} else {
echo basename($testFile) . ": FAIL\n";
echo "Expected:\n$expectedNorm\n";
echo "Got:\n$actualNorm\n";
exit(1);
}
44 changes: 44 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: CI

on:
pull_request:
branches: [ "main", "master" ]

jobs:
build-test:
runs-on: ubuntu-24.04
strategy:
matrix:
php: [ '8.3', '8.4', '8.5' ]
name: PHP ${{ matrix.php }} build & test
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: none
coverage: none
- name: Build extension
run: |
phpize
./configure --enable-blake3
make -j$(nproc)
sudo make install
- name: php -v
run: php -v
- name: Official PHPT tests
env:
TEST_PHP_ARGS: -d extension=blake3
NO_INTERACTION: 1
run: |
export TEST_PHP_EXECUTABLE="$(command -v php)"
RUN_TESTS="$(find /usr/lib/php -name run-tests.php | head -n1)"
echo "Using runner: ${RUN_TESTS}"
php "${RUN_TESTS}" -q --show-diff --show-slow 1000 --set-timeout 120 tests
- name: Custom runner smoke check
env:
CUSTOM_PHPT_RUNNER: 1
run: |
for f in tests/*.phpt; do php -d extension=blake3 .github/phpt_runner.php "$f" || exit 1; done

34 changes: 24 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,21 @@ permissions:

jobs:
build:
name: Build extension for PHP ${{ matrix.php }}
runs-on: ubuntu-24.04
name: Build extension for PHP ${{ matrix.php }} (${{ matrix.distro }}-${{ matrix.arch }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
php: [ '8.3', '8.4']
include:
- { php: '8.3', arch: amd64, distro: '24.04', os: ubuntu-24.04 }
- { php: '8.3', arch: arm64, distro: '24.04', os: ubuntu-24.04-arm }
- { php: '8.4', arch: amd64, distro: '24.04', os: ubuntu-24.04 }
- { php: '8.4', arch: arm64, distro: '24.04', os: ubuntu-24.04-arm }
- { php: '8.5', arch: amd64, distro: '24.04', os: ubuntu-24.04 }
- { php: '8.5', arch: arm64, distro: '24.04', os: ubuntu-24.04-arm }
# Stock Ubuntu 26.04 repos only ship PHP 8.5
- { php: '8.5', arch: amd64, distro: '26.04', os: ubuntu-26.04 }
- { php: '8.5', arch: arm64, distro: '26.04', os: ubuntu-26.04-arm }
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -37,13 +46,16 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y software-properties-common lsb-release ca-certificates curl git build-essential autoconf automake libtool pkg-config dpkg-dev
sudo add-apt-repository -y ppa:ondrej/php
# Stock Ubuntu 26.04 already ships PHP 8.5; the PPA is only needed on 24.04
if [ "${{ matrix.distro }}" = "24.04" ]; then sudo add-apt-repository -y ppa:ondrej/php; fi
sudo apt-get update
sudo apt-get install -y php${{ matrix.php }} php${{ matrix.php }}-dev

- name: Build extension (PHP ${{ matrix.php }})
env:
PHP_VER: ${{ matrix.php }}
ARCH: ${{ matrix.arch }}
DISTRO: ${{ matrix.distro }}
run: |
set -euo pipefail
PHP_BIN="php${PHP_VER}"
Expand All @@ -63,7 +75,7 @@ jobs:
if [ -f modules/blake3.so ]; then
DIST_ID=$(lsb_release -is | tr '[:upper:]' '[:lower:]')
DIST_CODENAME=$(lsb_release -cs)
cp modules/blake3.so blake3-${DIST_ID}-${DIST_CODENAME}-php${PHP_VER}-amd64.so
cp modules/blake3.so blake3-${DIST_ID}-${DIST_CODENAME}-php${PHP_VER}-${ARCH}.so
else
echo "Error: modules/blake3.so not found" >&2; exit 1
fi
Expand All @@ -81,21 +93,21 @@ jobs:
cp modules/blake3.so "${STAGING}${EXT_DIR}/blake3.so"

mkdir -p "${STAGING}/DEBIAN"
printf "Package: php-blake3\nVersion: %s-php%s\nSection: php\nPriority: optional\nArchitecture: amd64\nMaintainer: php-blake3 maintainers\nDescription: BLAKE3 hashing extension for PHP (built for PHP %s)\n" "${PKG_VERSION}" "${PHP_VER}" "${PHP_VER}" > "${STAGING}/DEBIAN/control"
printf "Package: php-blake3\nVersion: %s-php%s\nSection: php\nPriority: optional\nArchitecture: %s\nMaintainer: php-blake3 maintainers\nDescription: BLAKE3 hashing extension for PHP (built for PHP %s)\n" "${PKG_VERSION}" "${PHP_VER}" "${ARCH}" "${PHP_VER}" > "${STAGING}/DEBIAN/control"

# Build .deb
DIST_ID=$(lsb_release -is | tr '[:upper:]' '[:lower:]')
DIST_CODENAME=$(lsb_release -cs)
DEB_NAME="php-blake3_${PKG_VERSION}_${DIST_ID}-${DIST_CODENAME}_php${PHP_VER}_amd64.deb"
DEB_NAME="php-blake3_${PKG_VERSION}_${DIST_ID}-${DIST_CODENAME}_php${PHP_VER}_${ARCH}.deb"
dpkg-deb --build --root-owner-group "${STAGING}" "${DEB_NAME}"

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: php-blake3-php${{ matrix.php }}
name: php-blake3-php${{ matrix.php }}-${{ matrix.distro }}-${{ matrix.arch }}
path: |
blake3-*-php${{ matrix.php }}-amd64.so
php-blake3_*_php${{ matrix.php }}_amd64.deb
blake3-*-php${{ matrix.php }}-${{ matrix.arch }}.so
php-blake3_*_php${{ matrix.php }}_${{ matrix.arch }}.deb
if-no-files-found: error

release:
Expand All @@ -120,6 +132,8 @@ jobs:
prerelease: false
files: |
artifacts/**/blake3-*-php*-amd64.so
artifacts/**/blake3-*-php*-arm64.so
artifacts/**/php-blake3_*_php*_amd64.deb
artifacts/**/php-blake3_*_php*_arm64.deb
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
10 changes: 6 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
FROM ubuntu:24.04
ARG BASE_IMAGE=ubuntu:24.04
FROM ${BASE_IMAGE}
LABEL authors="cypherbits"
ENV LC_ALL=C.UTF-8
RUN apt-get update -y && apt-get dist-upgrade software-properties-common -y
RUN add-apt-repository ppa:ondrej/php
RUN apt-get update -y && apt-get install php8.3 php8.3-dev -y
# Stock Ubuntu 26.04 (resolute) already ships PHP 8.5; only older bases need the PPA
RUN if [ "$(. /etc/os-release && echo "${VERSION_ID%%.*}")" = "24" ]; then add-apt-repository ppa:ondrej/php; fi
RUN apt-get update -y && apt-get install php8.5 php8.5-dev -y
COPY . /making
RUN cd /making && phpize && ./configure --enable-blake3 && make && make install
CMD bash
CMD bash
30 changes: 26 additions & 4 deletions build.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
docker build --tag "blake3build:latest" .
docker create --name blake3build_container blake3build
#!/usr/bin/env bash
set -euo pipefail

PHP_VERSION="${PHP_VERSION:-8.5}"
DISTRO="${DISTRO:-24.04}"
ARCH="${ARCH:-$(docker version --format '{{.Client.Arch}}')}"
IMAGE_TAG="blake3build:php${PHP_VERSION}-${DISTRO}-${ARCH}"
CONTAINER_NAME="blake3build_container_php${PHP_VERSION}-${DISTRO}-${ARCH}"
ARTIFACT="blake3-php${PHP_VERSION}-${DISTRO}-${ARCH}.so"

BUILD_ARGS=()
if [ "${DISTRO}" != "24.04" ]; then
BUILD_ARGS+=(--build-arg BASE_IMAGE="ubuntu:${DISTRO}")
fi
if [ "${ARCH}" != "amd64" ]; then
BUILD_ARGS+=(--platform "linux/${ARCH}")
fi

docker build "${BUILD_ARGS[@]}" --tag "${IMAGE_TAG}" .
docker rm -f "${CONTAINER_NAME}" 2>/dev/null || true
docker create --name "${CONTAINER_NAME}" "${IMAGE_TAG}"
#/making/modules/blake3.so
docker cp blake3build_container:/making/modules/blake3.so ./compiled/blake3.so
docker rm blake3build_container
mkdir -p ./compiled
docker cp "${CONTAINER_NAME}:/making/modules/blake3.so" "./compiled/${ARTIFACT}"
docker rm "${CONTAINER_NAME}"

echo "Built ./compiled/${ARTIFACT}"
12 changes: 12 additions & 0 deletions tests/000_constants.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
BLAKE3_OUT_LEN constant is defined and equals 32
--SKIPIF--
<?php if (!extension_loaded('blake3')) die('skip blake3 extension required'); ?>
--FILE--
<?php
var_dump(defined('BLAKE3_OUT_LEN'));
var_dump(BLAKE3_OUT_LEN);
?>
--EXPECT--
bool(true)
int(32)
10 changes: 10 additions & 0 deletions tests/001_empty_string.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--TEST--
blake3('') returns expected hex (32 bytes)
--SKIPIF--
<?php if (!extension_loaded('blake3')) die('skip blake3 extension required'); ?>
--FILE--
<?php
var_dump(blake3(''));
?>
--EXPECT--
string(64) "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262"
10 changes: 10 additions & 0 deletions tests/002_output_size.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--TEST--
blake3('Hello world', 20) returns expected shortened hash
--SKIPIF--
<?php if (!extension_loaded('blake3')) die('skip blake3 extension required'); ?>
--FILE--
<?php
var_dump(blake3('Hello world', 20));
?>
--EXPECT--
string(40) "e7e6fb7d2869d109b62cdb1227208d4016cdaa0a"
10 changes: 10 additions & 0 deletions tests/003_keyed_hash.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--TEST--
blake3('Hello world', 32, key) returns expected hash
--SKIPIF--
<?php if (!extension_loaded('blake3')) die('skip blake3 extension required'); ?>
--FILE--
<?php
var_dump(blake3('Hello world', 32, 'cae8954e7b3415ea18303db548e15207'));
?>
--EXPECT--
string(64) "75672fafd13480d2325914f0665795eceecad4e668d9ea2a87c40e71232a7d3a"
16 changes: 16 additions & 0 deletions tests/004_raw_output.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
blake3 raw output returns 32 bytes and differs from hex output
--SKIPIF--
<?php if (!extension_loaded('blake3')) die('skip blake3 extension required'); ?>
--FILE--
<?php
$raw = blake3('', 32, '', true); // empty key
$hex = blake3('', 32); // default hex
var_dump(strlen($raw));
var_dump(strlen($hex));
var_dump($raw === $hex); // raw vs hex must differ
?>
--EXPECT--
int(32)
int(64)
bool(false)
11 changes: 11 additions & 0 deletions tests/005_extended_output.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--TEST--
Extended output length for 64-byte request
--SKIPIF--
<?php if (!extension_loaded('blake3')) die('skip blake3 extension required'); ?>
--FILE--
<?php
$hex = blake3('abc', 64);
var_dump(strlen($hex));
?>
--EXPECT--
int(128)
15 changes: 15 additions & 0 deletions tests/006_file_hash.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
blake3_file matches blake3() on file contents
--SKIPIF--
<?php if (!extension_loaded('blake3')) die('skip blake3 extension required'); ?>
--FILE--
<?php
$fn = __DIR__ . '/tmp.txt';
file_put_contents($fn, 'Hello world');
$hFile = blake3_file($fn);
$hMem = blake3('Hello world');
var_dump($hFile === $hMem);
unlink($fn);
?>
--EXPECT--
bool(true)
14 changes: 14 additions & 0 deletions tests/007_invalid_key_length.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
blake3 with invalid key length triggers fatal error
--SKIPIF--
<?php
if (getenv('CUSTOM_PHPT_RUNNER')) die('skip custom runner does not capture fatal');
if (!extension_loaded('blake3')) die('skip blake3 extension required');
?>
--FILE--
<?php
blake3('abc', 32, 'shortkey');
echo "unreached\n";
?>
--EXPECTF--
Fatal error: BLAKE3 key length MUST be 32 bytes in %s on line %d
14 changes: 14 additions & 0 deletions tests/008_invalid_output_length.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
blake3 with output length 0 triggers fatal error
--SKIPIF--
<?php
if (getenv('CUSTOM_PHPT_RUNNER')) die('skip custom runner does not capture fatal');
if (!extension_loaded('blake3')) die('skip blake3 extension required');
?>
--FILE--
<?php
blake3('abc', 0);
echo "unreached\n";
?>
--EXPECTF--
Fatal error: BLAKE3 output length cannot be zero in %s on line %d
Loading
Loading