Parallel agent work: bandwidth fix, CPU platforms, packaging
All checks were successful
CI / test (push) Successful in 2m8s

5 agents ran in parallel:

1. Fix bandwidth limit (-b): new advance_next_send() prevents drift
   bursts by resetting when >2x interval behind (bandwidth.rs, client.rs, server.rs)

2. Windows + FreeBSD CPU support (cpu.rs):
   - Windows: GetSystemTimes via raw FFI
   - FreeBSD: sysctl kern.cp_time parsing

3. Ubuntu .deb packaging (deploy/deb/):
   - build-deb.sh: creates .deb from pre-built binary
   - test-deb.sh: tests in Ubuntu Docker container

4. Fedora/RHEL RPM packaging (deploy/rpm/):
   - btest-rs.spec: full RPM spec with systemd unit
   - build-rpm.sh + test-rpm.sh

5. Alpine Linux apk packaging (deploy/alpine/):
   - APKBUILD with OpenRC init script
   - test-alpine.sh

58 tests pass, zero warnings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-04-01 14:04:00 +04:00
parent fe28c04c19
commit 8c853c3605
12 changed files with 816 additions and 15 deletions

73
deploy/rpm/btest-rs.spec Normal file
View File

@@ -0,0 +1,73 @@
Name: btest-rs
Version: 0.6.0
Release: 1%{?dist}
Summary: MikroTik Bandwidth Test (btest) server and client with EC-SRP5 auth
License: MIT AND Apache-2.0
URL: https://github.com/manawenuz/btest-rs
Source0: https://github.com/manawenuz/btest-rs/archive/refs/tags/v%{version}.tar.gz
BuildRequires: cargo
BuildRequires: rust
ExclusiveArch: x86_64 aarch64
%description
A Rust reimplementation of the MikroTik Bandwidth Test (btest) protocol,
providing both server and client functionality with EC-SRP5 authentication.
%prep
%autosetup -n %{name}-%{version}
%build
export CARGO_TARGET_DIR=target
cargo build --release
%install
install -Dm755 target/release/btest %{buildroot}%{_bindir}/btest
install -Dm644 docs/man/btest.1 %{buildroot}%{_mandir}/man1/btest.1
install -Dm644 LICENSE %{buildroot}%{_datadir}/licenses/%{name}/LICENSE
# systemd service unit
install -d %{buildroot}%{_unitdir}
cat > %{buildroot}%{_unitdir}/btest.service << 'EOF'
[Unit]
Description=MikroTik Bandwidth Test Server (btest-rs)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/btest -s
Restart=always
RestartSec=5
DynamicUser=yes
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
%files
%license LICENSE
%{_bindir}/btest
%{_mandir}/man1/btest.1*
%{_unitdir}/btest.service
%post
%systemd_post btest.service
%preun
%systemd_preun btest.service
%postun
%systemd_postun_with_restart btest.service
%changelog
* Mon Mar 30 2026 Siavash Sameni <manwe@manko.yoga> - 0.6.0-1
- Initial RPM package

30
deploy/rpm/build-rpm.sh Executable file
View File

@@ -0,0 +1,30 @@
#!/usr/bin/env bash
# build-rpm.sh — Build the btest-rs RPM package
set -euo pipefail
SPEC_DIR="$(cd "$(dirname "$0")" && pwd)"
SPEC_FILE="${SPEC_DIR}/btest-rs.spec"
VERSION="0.6.0"
TARBALL="v${VERSION}.tar.gz"
SOURCE_URL="https://github.com/manawenuz/btest-rs/archive/refs/tags/${TARBALL}"
echo "==> Setting up rpmbuild tree"
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
echo "==> Downloading source tarball"
if [ ! -f ~/rpmbuild/SOURCES/"${TARBALL}" ]; then
curl -fSL -o ~/rpmbuild/SOURCES/"${TARBALL}" "${SOURCE_URL}"
else
echo " (already present, skipping download)"
fi
echo "==> Copying spec file"
cp "${SPEC_FILE}" ~/rpmbuild/SPECS/btest-rs.spec
echo "==> Building RPM"
rpmbuild -ba ~/rpmbuild/SPECS/btest-rs.spec
echo ""
echo "==> Build complete. Packages:"
find ~/rpmbuild/RPMS -name '*.rpm' -print
find ~/rpmbuild/SRPMS -name '*.rpm' -print

75
deploy/rpm/test-rpm.sh Executable file
View File

@@ -0,0 +1,75 @@
#!/usr/bin/env bash
# test-rpm.sh — Test the btest-rs RPM build inside a Fedora container
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
IMAGE="fedora:latest"
echo "==> Testing RPM build in ${IMAGE}"
docker run --rm \
-v "${REPO_ROOT}:/workspace:ro" \
"${IMAGE}" \
bash -euxc '
# ── Install build dependencies ──
dnf install -y rpm-build rpmdevtools curl gcc make \
systemd-rpm-macros
# Install Rust toolchain
curl --proto "=https" --tlsv1.2 -sSf https://sh.rustup.rs \
| sh -s -- -y --profile minimal
source "$HOME/.cargo/env"
# ── Set up rpmbuild tree ──
rpmdev-setuptree
VERSION="0.6.0"
TARBALL="v${VERSION}.tar.gz"
# Copy spec
cp /workspace/deploy/rpm/btest-rs.spec ~/rpmbuild/SPECS/
# Create source tarball from workspace
# rpmbuild expects btest-rs-VERSION/ top-level directory
mkdir -p /tmp/btest-rs-${VERSION}
cp -a /workspace/. /tmp/btest-rs-${VERSION}/
tar czf ~/rpmbuild/SOURCES/${TARBALL} -C /tmp btest-rs-${VERSION}
# ── Build RPM ──
rpmbuild -ba ~/rpmbuild/SPECS/btest-rs.spec
# ── Install the RPM ──
RPM=$(find ~/rpmbuild/RPMS -name "btest-rs-*.rpm" | head -1)
echo "Installing: ${RPM}"
dnf install -y "${RPM}"
# ── Verify installation ──
echo "--- btest --version ---"
btest --version
echo "--- Checking systemd unit ---"
systemctl cat btest.service || true
echo "--- Checking man page ---"
test -f /usr/share/man/man1/btest.1* && echo "man page OK" || echo "man page MISSING"
echo "--- Checking license ---"
test -f /usr/share/licenses/btest-rs/LICENSE && echo "license OK" || echo "license MISSING"
# ── Loopback bandwidth test ──
echo "--- Starting loopback test ---"
btest -s &
SERVER_PID=$!
sleep 2
btest -c 127.0.0.1 --duration 3 && echo "Loopback test PASSED" \
|| echo "Loopback test FAILED (exit $?)"
kill "${SERVER_PID}" 2>/dev/null || true
wait "${SERVER_PID}" 2>/dev/null || true
echo "==> All RPM tests completed."
'
echo "==> Fedora container test finished."