Implement storedevs, prepare to port littlefs
This commit is contained in:
907
kernel/fs/littlefs/.github/workflows/test.yml
vendored
Normal file
907
kernel/fs/littlefs/.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,907 @@
|
||||
name: test
|
||||
on: [push, pull_request]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash -euv -o pipefail {0}
|
||||
|
||||
env:
|
||||
CFLAGS: -Werror
|
||||
MAKEFLAGS: -j
|
||||
TESTFLAGS: -k
|
||||
BENCHFLAGS:
|
||||
|
||||
jobs:
|
||||
# run tests
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [x86_64, thumb, mips, powerpc]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq gcc python3 python3-pip
|
||||
pip3 install toml
|
||||
gcc --version
|
||||
python3 --version
|
||||
|
||||
# cross-compile with ARM Thumb (32-bit, little-endian)
|
||||
- name: install-thumb
|
||||
if: ${{matrix.arch == 'thumb'}}
|
||||
run: |
|
||||
sudo apt-get install -qq \
|
||||
gcc-arm-linux-gnueabi \
|
||||
libc6-dev-armel-cross \
|
||||
qemu-user
|
||||
echo "CC=arm-linux-gnueabi-gcc -mthumb --static" >> $GITHUB_ENV
|
||||
echo "EXEC=qemu-arm" >> $GITHUB_ENV
|
||||
arm-linux-gnueabi-gcc --version
|
||||
qemu-arm -version
|
||||
# cross-compile with MIPS (32-bit, big-endian)
|
||||
- name: install-mips
|
||||
if: ${{matrix.arch == 'mips'}}
|
||||
run: |
|
||||
sudo apt-get install -qq \
|
||||
gcc-mips-linux-gnu \
|
||||
libc6-dev-mips-cross \
|
||||
qemu-user
|
||||
echo "CC=mips-linux-gnu-gcc --static" >> $GITHUB_ENV
|
||||
echo "EXEC=qemu-mips" >> $GITHUB_ENV
|
||||
mips-linux-gnu-gcc --version
|
||||
qemu-mips -version
|
||||
# cross-compile with PowerPC (32-bit, big-endian)
|
||||
- name: install-powerpc
|
||||
if: ${{matrix.arch == 'powerpc'}}
|
||||
run: |
|
||||
sudo apt-get install -qq \
|
||||
gcc-powerpc-linux-gnu \
|
||||
libc6-dev-powerpc-cross \
|
||||
qemu-user
|
||||
echo "CC=powerpc-linux-gnu-gcc --static" >> $GITHUB_ENV
|
||||
echo "EXEC=qemu-ppc" >> $GITHUB_ENV
|
||||
powerpc-linux-gnu-gcc --version
|
||||
qemu-ppc -version
|
||||
|
||||
# does littlefs compile?
|
||||
- name: test-build
|
||||
run: |
|
||||
make clean
|
||||
make build
|
||||
|
||||
# make sure example can at least compile
|
||||
- name: test-example
|
||||
run: |
|
||||
make clean
|
||||
sed -n '/``` c/,/```/{/```/d; p}' README.md > test.c
|
||||
CFLAGS="$CFLAGS \
|
||||
-Duser_provided_block_device_read=NULL \
|
||||
-Duser_provided_block_device_prog=NULL \
|
||||
-Duser_provided_block_device_erase=NULL \
|
||||
-Duser_provided_block_device_sync=NULL \
|
||||
-include stdio.h" \
|
||||
make all
|
||||
rm test.c
|
||||
|
||||
# run the tests!
|
||||
- name: test
|
||||
run: |
|
||||
make clean
|
||||
make test
|
||||
|
||||
# collect coverage info
|
||||
#
|
||||
# Note the goal is to maximize coverage in the small, easy-to-run
|
||||
# tests, so we intentionally exclude more aggressive powerloss testing
|
||||
# from coverage results
|
||||
- name: cov
|
||||
if: ${{matrix.arch == 'x86_64'}}
|
||||
run: |
|
||||
make lfs.cov.csv
|
||||
./scripts/cov.py -u lfs.cov.csv
|
||||
mkdir -p cov
|
||||
cp lfs.cov.csv cov/cov.csv
|
||||
|
||||
# find compile-time measurements
|
||||
- name: sizes
|
||||
run: |
|
||||
make clean
|
||||
CFLAGS="$CFLAGS \
|
||||
-DLFS_NO_ASSERT \
|
||||
-DLFS_NO_DEBUG \
|
||||
-DLFS_NO_WARN \
|
||||
-DLFS_NO_ERROR" \
|
||||
make lfs.code.csv lfs.data.csv lfs.stack.csv lfs.structs.csv
|
||||
./scripts/structs.py -u lfs.structs.csv
|
||||
./scripts/summary.py lfs.code.csv lfs.data.csv lfs.stack.csv \
|
||||
-bfunction \
|
||||
-fcode=code_size \
|
||||
-fdata=data_size \
|
||||
-fstack=stack_limit --max=stack_limit
|
||||
mkdir -p sizes
|
||||
cp lfs.code.csv sizes/${{matrix.arch}}.code.csv
|
||||
cp lfs.data.csv sizes/${{matrix.arch}}.data.csv
|
||||
cp lfs.stack.csv sizes/${{matrix.arch}}.stack.csv
|
||||
cp lfs.structs.csv sizes/${{matrix.arch}}.structs.csv
|
||||
- name: sizes-readonly
|
||||
run: |
|
||||
make clean
|
||||
CFLAGS="$CFLAGS \
|
||||
-DLFS_NO_ASSERT \
|
||||
-DLFS_NO_DEBUG \
|
||||
-DLFS_NO_WARN \
|
||||
-DLFS_NO_ERROR \
|
||||
-DLFS_READONLY" \
|
||||
make lfs.code.csv lfs.data.csv lfs.stack.csv lfs.structs.csv
|
||||
./scripts/structs.py -u lfs.structs.csv
|
||||
./scripts/summary.py lfs.code.csv lfs.data.csv lfs.stack.csv \
|
||||
-bfunction \
|
||||
-fcode=code_size \
|
||||
-fdata=data_size \
|
||||
-fstack=stack_limit --max=stack_limit
|
||||
mkdir -p sizes
|
||||
cp lfs.code.csv sizes/${{matrix.arch}}-readonly.code.csv
|
||||
cp lfs.data.csv sizes/${{matrix.arch}}-readonly.data.csv
|
||||
cp lfs.stack.csv sizes/${{matrix.arch}}-readonly.stack.csv
|
||||
cp lfs.structs.csv sizes/${{matrix.arch}}-readonly.structs.csv
|
||||
- name: sizes-threadsafe
|
||||
run: |
|
||||
make clean
|
||||
CFLAGS="$CFLAGS \
|
||||
-DLFS_NO_ASSERT \
|
||||
-DLFS_NO_DEBUG \
|
||||
-DLFS_NO_WARN \
|
||||
-DLFS_NO_ERROR \
|
||||
-DLFS_THREADSAFE" \
|
||||
make lfs.code.csv lfs.data.csv lfs.stack.csv lfs.structs.csv
|
||||
./scripts/structs.py -u lfs.structs.csv
|
||||
./scripts/summary.py lfs.code.csv lfs.data.csv lfs.stack.csv \
|
||||
-bfunction \
|
||||
-fcode=code_size \
|
||||
-fdata=data_size \
|
||||
-fstack=stack_limit --max=stack_limit
|
||||
mkdir -p sizes
|
||||
cp lfs.code.csv sizes/${{matrix.arch}}-threadsafe.code.csv
|
||||
cp lfs.data.csv sizes/${{matrix.arch}}-threadsafe.data.csv
|
||||
cp lfs.stack.csv sizes/${{matrix.arch}}-threadsafe.stack.csv
|
||||
cp lfs.structs.csv sizes/${{matrix.arch}}-threadsafe.structs.csv
|
||||
- name: sizes-multiversion
|
||||
run: |
|
||||
make clean
|
||||
CFLAGS="$CFLAGS \
|
||||
-DLFS_NO_ASSERT \
|
||||
-DLFS_NO_DEBUG \
|
||||
-DLFS_NO_WARN \
|
||||
-DLFS_NO_ERROR \
|
||||
-DLFS_MULTIVERSION" \
|
||||
make lfs.code.csv lfs.data.csv lfs.stack.csv lfs.structs.csv
|
||||
./scripts/structs.py -u lfs.structs.csv
|
||||
./scripts/summary.py lfs.code.csv lfs.data.csv lfs.stack.csv \
|
||||
-bfunction \
|
||||
-fcode=code_size \
|
||||
-fdata=data_size \
|
||||
-fstack=stack_limit --max=stack_limit
|
||||
mkdir -p sizes
|
||||
cp lfs.code.csv sizes/${{matrix.arch}}-multiversion.code.csv
|
||||
cp lfs.data.csv sizes/${{matrix.arch}}-multiversion.data.csv
|
||||
cp lfs.stack.csv sizes/${{matrix.arch}}-multiversion.stack.csv
|
||||
cp lfs.structs.csv sizes/${{matrix.arch}}-multiversion.structs.csv
|
||||
- name: sizes-migrate
|
||||
run: |
|
||||
make clean
|
||||
CFLAGS="$CFLAGS \
|
||||
-DLFS_NO_ASSERT \
|
||||
-DLFS_NO_DEBUG \
|
||||
-DLFS_NO_WARN \
|
||||
-DLFS_NO_ERROR \
|
||||
-DLFS_MIGRATE" \
|
||||
make lfs.code.csv lfs.data.csv lfs.stack.csv lfs.structs.csv
|
||||
./scripts/structs.py -u lfs.structs.csv
|
||||
./scripts/summary.py lfs.code.csv lfs.data.csv lfs.stack.csv \
|
||||
-bfunction \
|
||||
-fcode=code_size \
|
||||
-fdata=data_size \
|
||||
-fstack=stack_limit --max=stack_limit
|
||||
mkdir -p sizes
|
||||
cp lfs.code.csv sizes/${{matrix.arch}}-migrate.code.csv
|
||||
cp lfs.data.csv sizes/${{matrix.arch}}-migrate.data.csv
|
||||
cp lfs.stack.csv sizes/${{matrix.arch}}-migrate.stack.csv
|
||||
cp lfs.structs.csv sizes/${{matrix.arch}}-migrate.structs.csv
|
||||
- name: sizes-error-asserts
|
||||
run: |
|
||||
make clean
|
||||
CFLAGS="$CFLAGS \
|
||||
-DLFS_NO_DEBUG \
|
||||
-DLFS_NO_WARN \
|
||||
-DLFS_NO_ERROR \
|
||||
-D'LFS_ASSERT(test)=do {if(!(test)) {return -1;}} while(0)'" \
|
||||
make lfs.code.csv lfs.data.csv lfs.stack.csv lfs.structs.csv
|
||||
./scripts/structs.py -u lfs.structs.csv
|
||||
./scripts/summary.py lfs.code.csv lfs.data.csv lfs.stack.csv \
|
||||
-bfunction \
|
||||
-fcode=code_size \
|
||||
-fdata=data_size \
|
||||
-fstack=stack_limit --max=stack_limit
|
||||
mkdir -p sizes
|
||||
cp lfs.code.csv sizes/${{matrix.arch}}-error-asserts.code.csv
|
||||
cp lfs.data.csv sizes/${{matrix.arch}}-error-asserts.data.csv
|
||||
cp lfs.stack.csv sizes/${{matrix.arch}}-error-asserts.stack.csv
|
||||
cp lfs.structs.csv sizes/${{matrix.arch}}-error-asserts.structs.csv
|
||||
|
||||
# create size statuses
|
||||
- name: upload-sizes
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sizes-${{matrix.arch}}
|
||||
path: sizes
|
||||
- name: status-sizes
|
||||
run: |
|
||||
mkdir -p status
|
||||
for f in $(shopt -s nullglob ; echo sizes/*.csv)
|
||||
do
|
||||
# skip .data.csv as it should always be zero
|
||||
[[ $f == *.data.csv ]] && continue
|
||||
export STEP="sizes$(echo $f \
|
||||
| sed -n 's/[^-.]*-\([^.]*\)\..*csv/-\1/p')"
|
||||
export CONTEXT="sizes (${{matrix.arch}}$(echo $f \
|
||||
| sed -n 's/[^-.]*-\([^.]*\)\..*csv/, \1/p')) / $(echo $f \
|
||||
| sed -n 's/[^.]*\.\(.*\)\.csv/\1/p')"
|
||||
export PREV="$(curl -sS \
|
||||
"$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/status/master`
|
||||
`?per_page=100" \
|
||||
| jq -re 'select(.sha != env.GITHUB_SHA) | .statuses[]
|
||||
| select(.context == env.CONTEXT).description
|
||||
| capture("(?<prev>[0-9∞]+)").prev' \
|
||||
|| echo 0)"
|
||||
export DESCRIPTION="$(./scripts/summary.py $f --max=stack_limit -Y \
|
||||
| awk '
|
||||
NR==2 {$1=0; printf "%s B",$NF}
|
||||
NR==2 && ENVIRON["PREV"]+0 != 0 {
|
||||
printf " (%+.1f%%)",100*($NF-ENVIRON["PREV"])/ENVIRON["PREV"]
|
||||
}')"
|
||||
jq -n '{
|
||||
state: "success",
|
||||
context: env.CONTEXT,
|
||||
description: env.DESCRIPTION,
|
||||
target_job: "${{github.job}} (${{matrix.arch}})",
|
||||
target_step: env.STEP,
|
||||
}' | tee status/$(basename $f .csv).json
|
||||
done
|
||||
- name: upload-status-sizes
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: status-sizes-${{matrix.arch}}
|
||||
path: status
|
||||
retention-days: 1
|
||||
|
||||
# create cov statuses
|
||||
- name: upload-cov
|
||||
if: ${{matrix.arch == 'x86_64'}}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cov
|
||||
path: cov
|
||||
- name: status-cov
|
||||
if: ${{matrix.arch == 'x86_64'}}
|
||||
run: |
|
||||
mkdir -p status
|
||||
f=cov/cov.csv
|
||||
for s in lines branches
|
||||
do
|
||||
export STEP="cov"
|
||||
export CONTEXT="cov / $s"
|
||||
export PREV="$(curl -sS \
|
||||
"$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/status/master`
|
||||
`?per_page=100" \
|
||||
| jq -re 'select(.sha != env.GITHUB_SHA) | .statuses[]
|
||||
| select(.context == env.CONTEXT).description
|
||||
| capture("(?<prev_a>[0-9]+)/(?<prev_b>[0-9]+)")
|
||||
| 100*((.prev_a|tonumber) / (.prev_b|tonumber))' \
|
||||
|| echo 0)"
|
||||
export DESCRIPTION="$(./scripts/cov.py -u $f -f$s -Y \
|
||||
| awk -F '[ /%]+' -v s=$s '
|
||||
NR==2 {$1=0; printf "%d/%d %s",$2,$3,s}
|
||||
NR==2 && ENVIRON["PREV"]+0 != 0 {
|
||||
printf " (%+.1f%%)",$4-ENVIRON["PREV"]
|
||||
}')"
|
||||
jq -n '{
|
||||
state: "success",
|
||||
context: env.CONTEXT,
|
||||
description: env.DESCRIPTION,
|
||||
target_job: "${{github.job}} (${{matrix.arch}})",
|
||||
target_step: env.STEP,
|
||||
}' | tee status/$(basename $f .csv)-$s.json
|
||||
done
|
||||
- name: upload-status-cov
|
||||
if: ${{matrix.arch == 'x86_64'}}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: status-cov
|
||||
path: status
|
||||
retention-days: 1
|
||||
|
||||
# run as many exhaustive tests as fits in GitHub's time limits
|
||||
#
|
||||
# this grows exponentially, so it doesn't turn out to be that many
|
||||
test-pls:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pls: [1, 2]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq gcc python3 python3-pip
|
||||
pip3 install toml
|
||||
gcc --version
|
||||
python3 --version
|
||||
- name: test-pls
|
||||
if: ${{matrix.pls <= 1}}
|
||||
run: |
|
||||
TESTFLAGS="$TESTFLAGS -P${{matrix.pls}}" make test
|
||||
# >=2pls takes multiple days to run fully, so we can only
|
||||
# run a subset of tests, these are the most important
|
||||
- name: test-limited-pls
|
||||
if: ${{matrix.pls > 1}}
|
||||
run: |
|
||||
TESTFLAGS="$TESTFLAGS -P${{matrix.pls}} test_dirs test_relocations" \
|
||||
make test
|
||||
|
||||
# run with LFS_NO_INTRINSICS to make sure that works
|
||||
test-no-intrinsics:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq gcc python3 python3-pip
|
||||
pip3 install toml
|
||||
gcc --version
|
||||
python3 --version
|
||||
- name: test-no-intrinsics
|
||||
run: |
|
||||
CFLAGS="$CFLAGS -DLFS_NO_INTRINSICS" make test
|
||||
|
||||
test-shrink:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq gcc python3 python3-pip
|
||||
pip3 install toml
|
||||
gcc --version
|
||||
python3 --version
|
||||
- name: test-no-intrinsics
|
||||
run: |
|
||||
CFLAGS="$CFLAGS -DLFS_SHRINKNONRELOCATING" make test
|
||||
|
||||
# run with all trace options enabled to at least make sure these
|
||||
# all compile
|
||||
test-yes-trace:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq gcc python3 python3-pip
|
||||
pip3 install toml
|
||||
gcc --version
|
||||
python3 --version
|
||||
- name: test-yes-trace
|
||||
run: |
|
||||
CFLAGS="$CFLAGS \
|
||||
-DLFS_YES_TRACE \
|
||||
-DLFS_RAMBD_YES_TRACE \
|
||||
-DLFS_FILEBD_YES_TRACE \
|
||||
-DLFS_RAMBD_YES_TRACE" \
|
||||
make test
|
||||
|
||||
# run LFS_MULTIVERSION tests
|
||||
test-multiversion:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq gcc python3 python3-pip
|
||||
pip3 install toml
|
||||
gcc --version
|
||||
python3 --version
|
||||
- name: test-multiversion
|
||||
run: |
|
||||
CFLAGS="$CFLAGS -DLFS_MULTIVERSION" make test
|
||||
|
||||
# run tests on the older version lfs2.0
|
||||
test-lfs2_0:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq gcc python3 python3-pip
|
||||
pip3 install toml
|
||||
gcc --version
|
||||
python3 --version
|
||||
- name: test-lfs2_0
|
||||
run: |
|
||||
CFLAGS="$CFLAGS -DLFS_MULTIVERSION" \
|
||||
TESTFLAGS="$TESTFLAGS -DDISK_VERSION=0x00020000" \
|
||||
make test
|
||||
|
||||
# run under Valgrind to check for memory errors
|
||||
test-valgrind:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq gcc python3 python3-pip valgrind
|
||||
pip3 install toml
|
||||
gcc --version
|
||||
python3 --version
|
||||
valgrind --version
|
||||
# Valgrind takes a while with diminishing value, so only test
|
||||
# on one geometry
|
||||
- name: test-valgrind
|
||||
run: |
|
||||
TESTFLAGS="$TESTFLAGS --valgrind --context=1024 -Gdefault -Pnone" \
|
||||
make test
|
||||
|
||||
# compile/run with Clang, mostly to check for Clang-specific warnings
|
||||
test-clang:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get install -qq clang python3 python3-pip
|
||||
pip3 install toml
|
||||
clang --version
|
||||
python3 --version
|
||||
- name: test-clang
|
||||
run: |
|
||||
CC=clang \
|
||||
make test
|
||||
|
||||
# run benchmarks
|
||||
#
|
||||
# note there's no real benefit to running these on multiple archs
|
||||
bench:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq gcc python3 python3-pip valgrind
|
||||
pip3 install toml
|
||||
gcc --version
|
||||
python3 --version
|
||||
valgrind --version
|
||||
- name: bench
|
||||
run: |
|
||||
make bench
|
||||
|
||||
# find bench results
|
||||
make lfs.bench.csv
|
||||
./scripts/summary.py lfs.bench.csv \
|
||||
-bsuite \
|
||||
-freaded=bench_readed \
|
||||
-fproged=bench_proged \
|
||||
-ferased=bench_erased
|
||||
mkdir -p bench
|
||||
cp lfs.bench.csv bench/bench.csv
|
||||
|
||||
# find perfbd results
|
||||
make lfs.perfbd.csv
|
||||
./scripts/perfbd.py -u lfs.perfbd.csv
|
||||
mkdir -p bench
|
||||
cp lfs.perfbd.csv bench/perfbd.csv
|
||||
|
||||
# create bench statuses
|
||||
- name: upload-bench
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bench
|
||||
path: bench
|
||||
- name: status-bench
|
||||
run: |
|
||||
mkdir -p status
|
||||
f=bench/bench.csv
|
||||
for s in readed proged erased
|
||||
do
|
||||
export STEP="bench"
|
||||
export CONTEXT="bench / $s"
|
||||
export PREV="$(curl -sS \
|
||||
"$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/status/master`
|
||||
`?per_page=100" \
|
||||
| jq -re 'select(.sha != env.GITHUB_SHA) | .statuses[]
|
||||
| select(.context == env.CONTEXT).description
|
||||
| capture("(?<prev>[0-9]+)").prev' \
|
||||
|| echo 0)"
|
||||
export DESCRIPTION="$(./scripts/summary.py $f -f$s=bench_$s -Y \
|
||||
| awk '
|
||||
NR==2 {$1=0; printf "%s B",$NF}
|
||||
NR==2 && ENVIRON["PREV"]+0 != 0 {
|
||||
printf " (%+.1f%%)",100*($NF-ENVIRON["PREV"])/ENVIRON["PREV"]
|
||||
}')"
|
||||
jq -n '{
|
||||
state: "success",
|
||||
context: env.CONTEXT,
|
||||
description: env.DESCRIPTION,
|
||||
target_job: "${{github.job}}",
|
||||
target_step: env.STEP,
|
||||
}' | tee status/$(basename $f .csv)-$s.json
|
||||
done
|
||||
- name: upload-status-bench
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: status-bench
|
||||
path: status
|
||||
retention-days: 1
|
||||
|
||||
# run compatibility tests using the current master as the previous version
|
||||
test-compat:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
# checkout the current pr target into lfsp
|
||||
- uses: actions/checkout@v4
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
with:
|
||||
ref: ${{github.event.pull_request.base.ref}}
|
||||
path: lfsp
|
||||
- name: install
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq gcc python3 python3-pip
|
||||
pip3 install toml
|
||||
gcc --version
|
||||
python3 --version
|
||||
# adjust prefix of lfsp
|
||||
- name: changeprefix
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
run: |
|
||||
./scripts/changeprefix.py lfs lfsp lfsp/*.h lfsp/*.c
|
||||
- name: test-compat
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
run: |
|
||||
TESTS=tests/test_compat.toml \
|
||||
SRC="$(find . lfsp -name '*.c' -maxdepth 1 \
|
||||
-and -not -name '*.t.*' \
|
||||
-and -not -name '*.b.*')" \
|
||||
CFLAGS="-DLFSP=lfsp/lfsp.h" \
|
||||
make test
|
||||
|
||||
# self-host with littlefs-fuse for a fuzz-like test
|
||||
fuse:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{!endsWith(github.ref, '-prefix')}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq gcc python3 python3-pip libfuse-dev
|
||||
sudo pip3 install toml
|
||||
gcc --version
|
||||
python3 --version
|
||||
fusermount -V
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: littlefs-project/littlefs-fuse
|
||||
ref: v2
|
||||
path: littlefs-fuse
|
||||
- name: setup
|
||||
run: |
|
||||
# copy our new version into littlefs-fuse
|
||||
rm -rf littlefs-fuse/littlefs/*
|
||||
cp -r $(git ls-tree --name-only HEAD) littlefs-fuse/littlefs
|
||||
|
||||
# setup disk for littlefs-fuse
|
||||
mkdir mount
|
||||
LOOP=$(sudo losetup -f)
|
||||
sudo chmod a+rw $LOOP
|
||||
dd if=/dev/zero bs=512 count=128K of=disk
|
||||
losetup $LOOP disk
|
||||
echo "LOOP=$LOOP" >> $GITHUB_ENV
|
||||
- name: test
|
||||
run: |
|
||||
# self-host test
|
||||
make -C littlefs-fuse
|
||||
|
||||
littlefs-fuse/lfs --format $LOOP
|
||||
littlefs-fuse/lfs $LOOP mount
|
||||
|
||||
ls mount
|
||||
mkdir mount/littlefs
|
||||
cp -r $(git ls-tree --name-only HEAD) mount/littlefs
|
||||
cd mount/littlefs
|
||||
stat .
|
||||
ls -flh
|
||||
make -B test-runner
|
||||
make -B test
|
||||
|
||||
# test migration using littlefs-fuse
|
||||
migrate:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{!endsWith(github.ref, '-prefix')}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq gcc python3 python3-pip libfuse-dev
|
||||
sudo pip3 install toml
|
||||
gcc --version
|
||||
python3 --version
|
||||
fusermount -V
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: littlefs-project/littlefs-fuse
|
||||
ref: v2
|
||||
path: v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: littlefs-project/littlefs-fuse
|
||||
ref: v1
|
||||
path: v1
|
||||
- name: setup
|
||||
run: |
|
||||
# copy our new version into littlefs-fuse
|
||||
rm -rf v2/littlefs/*
|
||||
cp -r $(git ls-tree --name-only HEAD) v2/littlefs
|
||||
|
||||
# setup disk for littlefs-fuse
|
||||
mkdir mount
|
||||
LOOP=$(sudo losetup -f)
|
||||
sudo chmod a+rw $LOOP
|
||||
dd if=/dev/zero bs=512 count=128K of=disk
|
||||
losetup $LOOP disk
|
||||
echo "LOOP=$LOOP" >> $GITHUB_ENV
|
||||
- name: test
|
||||
run: |
|
||||
# compile v1 and v2
|
||||
make -C v1
|
||||
make -C v2
|
||||
|
||||
# run self-host test with v1
|
||||
v1/lfs --format $LOOP
|
||||
v1/lfs $LOOP mount
|
||||
|
||||
ls mount
|
||||
mkdir mount/littlefs
|
||||
cp -r $(git ls-tree --name-only HEAD) mount/littlefs
|
||||
cd mount/littlefs
|
||||
stat .
|
||||
ls -flh
|
||||
make -B test-runner
|
||||
make -B test
|
||||
|
||||
# attempt to migrate
|
||||
cd ../..
|
||||
fusermount -u mount
|
||||
|
||||
v2/lfs --migrate $LOOP
|
||||
v2/lfs $LOOP mount
|
||||
|
||||
# run self-host test with v2 right where we left off
|
||||
ls mount
|
||||
cd mount/littlefs
|
||||
stat .
|
||||
ls -flh
|
||||
make -B test-runner
|
||||
make -B test
|
||||
|
||||
# status related tasks that run after tests
|
||||
status:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test, bench]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
- name: install
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
run: |
|
||||
# need a few things
|
||||
sudo apt-get install -qq gcc python3 python3-pip
|
||||
pip3 install toml
|
||||
gcc --version
|
||||
python3 --version
|
||||
- uses: actions/download-artifact@v4
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
continue-on-error: true
|
||||
with:
|
||||
pattern: '{sizes,sizes-*}'
|
||||
merge-multiple: true
|
||||
path: sizes
|
||||
- uses: actions/download-artifact@v4
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
continue-on-error: true
|
||||
with:
|
||||
pattern: '{cov,cov-*}'
|
||||
merge-multiple: true
|
||||
path: cov
|
||||
- uses: actions/download-artifact@v4
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
continue-on-error: true
|
||||
with:
|
||||
pattern: '{bench,bench-*}'
|
||||
merge-multiple: true
|
||||
path: bench
|
||||
|
||||
# try to find results from tests
|
||||
- name: create-table
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
run: |
|
||||
# compare against pull-request target
|
||||
curl -sS \
|
||||
"$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/status/`
|
||||
`${{github.event.pull_request.base.ref}}`
|
||||
`?per_page=100" \
|
||||
| jq -re 'select(.sha != env.GITHUB_SHA) | .statuses[]' \
|
||||
>> prev-status.json \
|
||||
|| true
|
||||
|
||||
# build table for GitHub
|
||||
declare -A table
|
||||
|
||||
# sizes table
|
||||
i=0
|
||||
j=0
|
||||
for c in "" readonly threadsafe multiversion migrate error-asserts
|
||||
do
|
||||
# per-config results
|
||||
c_or_default=${c:-default}
|
||||
c_camel=${c_or_default^}
|
||||
table[$i,$j]=$c_camel
|
||||
((j+=1))
|
||||
|
||||
for s in code stack structs
|
||||
do
|
||||
f=sizes/thumb${c:+-$c}.$s.csv
|
||||
[ -e $f ] && table[$i,$j]=$( \
|
||||
export PREV="$(jq -re '
|
||||
select(.context == "'"sizes (thumb${c:+, $c}) / $s"'").description
|
||||
| capture("(?<prev>[0-9∞]+)").prev' \
|
||||
prev-status.json || echo 0)"
|
||||
./scripts/summary.py $f --max=stack_limit -Y \
|
||||
| awk '
|
||||
NR==2 {$1=0; printf "%s B",$NF}
|
||||
NR==2 && ENVIRON["PREV"]+0 != 0 {
|
||||
printf " (%+.1f%%)",100*($NF-ENVIRON["PREV"])/ENVIRON["PREV"]
|
||||
}' \
|
||||
| sed -e 's/ /\ /g')
|
||||
((j+=1))
|
||||
done
|
||||
((j=0, i+=1))
|
||||
done
|
||||
|
||||
# coverage table
|
||||
i=0
|
||||
j=4
|
||||
for s in lines branches
|
||||
do
|
||||
table[$i,$j]=${s^}
|
||||
((j+=1))
|
||||
|
||||
f=cov/cov.csv
|
||||
[ -e $f ] && table[$i,$j]=$( \
|
||||
export PREV="$(jq -re '
|
||||
select(.context == "'"cov / $s"'").description
|
||||
| capture("(?<prev_a>[0-9]+)/(?<prev_b>[0-9]+)")
|
||||
| 100*((.prev_a|tonumber) / (.prev_b|tonumber))' \
|
||||
prev-status.json || echo 0)"
|
||||
./scripts/cov.py -u $f -f$s -Y \
|
||||
| awk -F '[ /%]+' -v s=$s '
|
||||
NR==2 {$1=0; printf "%d/%d %s",$2,$3,s}
|
||||
NR==2 && ENVIRON["PREV"]+0 != 0 {
|
||||
printf " (%+.1f%%)",$4-ENVIRON["PREV"]
|
||||
}' \
|
||||
| sed -e 's/ /\ /g')
|
||||
((j=4, i+=1))
|
||||
done
|
||||
|
||||
# benchmark table
|
||||
i=3
|
||||
j=4
|
||||
for s in readed proged erased
|
||||
do
|
||||
table[$i,$j]=${s^}
|
||||
((j+=1))
|
||||
|
||||
f=bench/bench.csv
|
||||
[ -e $f ] && table[$i,$j]=$( \
|
||||
export PREV="$(jq -re '
|
||||
select(.context == "'"bench / $s"'").description
|
||||
| capture("(?<prev>[0-9]+)").prev' \
|
||||
prev-status.json || echo 0)"
|
||||
./scripts/summary.py $f -f$s=bench_$s -Y \
|
||||
| awk '
|
||||
NR==2 {$1=0; printf "%s B",$NF}
|
||||
NR==2 && ENVIRON["PREV"]+0 != 0 {
|
||||
printf " (%+.1f%%)",100*($NF-ENVIRON["PREV"])/ENVIRON["PREV"]
|
||||
}' \
|
||||
| sed -e 's/ /\ /g')
|
||||
((j=4, i+=1))
|
||||
done
|
||||
|
||||
# build the actual table
|
||||
echo "| | Code | Stack | Structs | | Coverage |" >> table.txt
|
||||
echo "|:--|-----:|------:|--------:|:--|---------:|" >> table.txt
|
||||
for ((i=0; i<6; i++))
|
||||
do
|
||||
echo -n "|" >> table.txt
|
||||
for ((j=0; j<6; j++))
|
||||
do
|
||||
echo -n " " >> table.txt
|
||||
[[ i -eq 2 && j -eq 5 ]] && echo -n "**Benchmarks**" >> table.txt
|
||||
echo -n "${table[$i,$j]:-}" >> table.txt
|
||||
echo -n " |" >> table.txt
|
||||
done
|
||||
echo >> table.txt
|
||||
done
|
||||
|
||||
cat table.txt
|
||||
|
||||
# create a bot comment for successful runs on pull requests
|
||||
- name: create-comment
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
run: |
|
||||
touch comment.txt
|
||||
echo "<details>" >> comment.txt
|
||||
echo "<summary>" >> comment.txt
|
||||
echo "Tests passed ✓, `
|
||||
`Code: $(awk 'NR==3 {print $4}' table.txt || true), `
|
||||
`Stack: $(awk 'NR==3 {print $6}' table.txt || true), `
|
||||
`Structs: $(awk 'NR==3 {print $8}' table.txt || true)" \
|
||||
>> comment.txt
|
||||
echo "</summary>" >> comment.txt
|
||||
echo >> comment.txt
|
||||
[ -e table.txt ] && cat table.txt >> comment.txt
|
||||
echo >> comment.txt
|
||||
echo "</details>" >> comment.txt
|
||||
cat comment.txt
|
||||
|
||||
mkdir -p comment
|
||||
jq -n --rawfile comment comment.txt '{
|
||||
number: ${{github.event.number}},
|
||||
body: $comment,
|
||||
}' | tee comment/comment.json
|
||||
- name: upload-comment
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: comment
|
||||
path: comment
|
||||
retention-days: 1
|
||||
|
Reference in New Issue
Block a user