[dfs] Update dfs v1 synchronously (#15) #16
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: test | |
on: [push, pull_request] | |
env: | |
CFLAGS: -Werror | |
MAKEFLAGS: -j | |
jobs: | |
# run tests | |
test: | |
runs-on: ubuntu-20.04 | |
strategy: | |
fail-fast: false | |
matrix: | |
arch: [x86_64, thumb, mips, powerpc] | |
steps: | |
- uses: actions/checkout@v2 | |
- name: install | |
run: | | |
# need a few additional tools | |
# | |
# note this includes gcc-10, which is required for -fcallgraph-info=su | |
sudo apt-get update -qq | |
sudo apt-get install -qq gcc-10 python3 python3-pip lcov | |
sudo pip3 install toml | |
echo "CC=gcc-10" >> $GITHUB_ENV | |
gcc-10 --version | |
lcov --version | |
python3 --version | |
# need newer lcov version for gcc-10 | |
#sudo apt-get remove lcov | |
#wget https://launchpad.net/ubuntu/+archive/primary/+files/lcov_1.15-1_all.deb | |
#sudo apt install ./lcov_1.15-1_all.deb | |
#lcov --version | |
#which lcov | |
#ls -lha /usr/bin/lcov | |
wget https://github.com/linux-test-project/lcov/releases/download/v1.15/lcov-1.15.tar.gz | |
tar xf lcov-1.15.tar.gz | |
sudo make -C lcov-1.15 install | |
# setup a ram-backed disk to speed up reentrant tests | |
mkdir disks | |
sudo mount -t tmpfs -o size=100m tmpfs disks | |
TESTFLAGS="$TESTFLAGS --disk=disks/disk" | |
# collect coverage | |
mkdir -p coverage | |
TESTFLAGS="$TESTFLAGS --coverage=` | |
`coverage/${{github.job}}-${{matrix.arch}}.info" | |
echo "TESTFLAGS=$TESTFLAGS" >> $GITHUB_ENV | |
# cross-compile with ARM Thumb (32-bit, little-endian) | |
- name: install-thumb | |
if: ${{matrix.arch == 'thumb'}} | |
run: | | |
sudo apt-get install -qq \ | |
gcc-10-arm-linux-gnueabi \ | |
libc6-dev-armel-cross \ | |
qemu-user | |
echo "CC=arm-linux-gnueabi-gcc-10 -mthumb --static" >> $GITHUB_ENV | |
echo "EXEC=qemu-arm" >> $GITHUB_ENV | |
arm-linux-gnueabi-gcc-10 --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-10-mips-linux-gnu \ | |
libc6-dev-mips-cross \ | |
qemu-user | |
echo "CC=mips-linux-gnu-gcc-10 --static" >> $GITHUB_ENV | |
echo "EXEC=qemu-mips" >> $GITHUB_ENV | |
mips-linux-gnu-gcc-10 --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-10-powerpc-linux-gnu \ | |
libc6-dev-powerpc-cross \ | |
qemu-user | |
echo "CC=powerpc-linux-gnu-gcc-10 --static" >> $GITHUB_ENV | |
echo "EXEC=qemu-ppc" >> $GITHUB_ENV | |
powerpc-linux-gnu-gcc-10 --version | |
qemu-ppc -version | |
# make sure example can at least compile | |
- name: test-example | |
run: | | |
sed -n '/``` c/,/```/{/```/d; p}' README.md > test.c | |
make all 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" | |
rm test.c | |
# test configurations | |
# normal+reentrant tests | |
- name: test-default | |
run: | | |
make clean | |
make test TESTFLAGS+="-nrk" | |
# NOR flash: read/prog = 1 block = 4KiB | |
- name: test-nor | |
run: | | |
make clean | |
make test TESTFLAGS+="-nrk \ | |
-DLFS_READ_SIZE=1 -DLFS_BLOCK_SIZE=4096" | |
# SD/eMMC: read/prog = 512 block = 512 | |
- name: test-emmc | |
run: | | |
make clean | |
make test TESTFLAGS+="-nrk \ | |
-DLFS_READ_SIZE=512 -DLFS_BLOCK_SIZE=512" | |
# NAND flash: read/prog = 4KiB block = 32KiB | |
- name: test-nand | |
run: | | |
make clean | |
make test TESTFLAGS+="-nrk \ | |
-DLFS_READ_SIZE=4096 -DLFS_BLOCK_SIZE=\(32*1024\)" | |
# other extreme geometries that are useful for various corner cases | |
- name: test-no-intrinsics | |
run: | | |
make clean | |
make test TESTFLAGS+="-nrk \ | |
-DLFS_NO_INTRINSICS" | |
- name: test-byte-writes | |
# it just takes too long to test byte-level writes when in qemu, | |
# should be plenty covered by the other configurations | |
if: ${{matrix.arch == 'x86_64'}} | |
run: | | |
make clean | |
make test TESTFLAGS+="-nrk \ | |
-DLFS_READ_SIZE=1 -DLFS_CACHE_SIZE=1" | |
- name: test-block-cycles | |
run: | | |
make clean | |
make test TESTFLAGS+="-nrk \ | |
-DLFS_BLOCK_CYCLES=1" | |
- name: test-odd-block-count | |
run: | | |
make clean | |
make test TESTFLAGS+="-nrk \ | |
-DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD_SIZE=256" | |
- name: test-odd-block-size | |
run: | | |
make clean | |
make test TESTFLAGS+="-nrk \ | |
-DLFS_READ_SIZE=11 -DLFS_BLOCK_SIZE=704" | |
# upload coverage for later coverage | |
- name: upload-coverage | |
uses: actions/upload-artifact@v2 | |
with: | |
name: coverage | |
path: coverage | |
retention-days: 1 | |
# update results | |
- name: results | |
run: | | |
mkdir -p results | |
make clean | |
make lfs.csv \ | |
CFLAGS+=" \ | |
-DLFS_NO_ASSERT \ | |
-DLFS_NO_DEBUG \ | |
-DLFS_NO_WARN \ | |
-DLFS_NO_ERROR" | |
cp lfs.csv results/${{matrix.arch}}.csv | |
./scripts/summary.py results/${{matrix.arch}}.csv | |
- name: results-readonly | |
run: | | |
mkdir -p results | |
make clean | |
make lfs.csv \ | |
CFLAGS+=" \ | |
-DLFS_NO_ASSERT \ | |
-DLFS_NO_DEBUG \ | |
-DLFS_NO_WARN \ | |
-DLFS_NO_ERROR \ | |
-DLFS_READONLY" | |
cp lfs.csv results/${{matrix.arch}}-readonly.csv | |
./scripts/summary.py results/${{matrix.arch}}-readonly.csv | |
- name: results-threadsafe | |
run: | | |
mkdir -p results | |
make clean | |
make lfs.csv \ | |
CFLAGS+=" \ | |
-DLFS_NO_ASSERT \ | |
-DLFS_NO_DEBUG \ | |
-DLFS_NO_WARN \ | |
-DLFS_NO_ERROR \ | |
-DLFS_THREADSAFE" | |
cp lfs.csv results/${{matrix.arch}}-threadsafe.csv | |
./scripts/summary.py results/${{matrix.arch}}-threadsafe.csv | |
- name: results-migrate | |
run: | | |
mkdir -p results | |
make clean | |
make lfs.csv \ | |
CFLAGS+=" \ | |
-DLFS_NO_ASSERT \ | |
-DLFS_NO_DEBUG \ | |
-DLFS_NO_WARN \ | |
-DLFS_NO_ERROR \ | |
-DLFS_MIGRATE" | |
cp lfs.csv results/${{matrix.arch}}-migrate.csv | |
./scripts/summary.py results/${{matrix.arch}}-migrate.csv | |
- name: results-error-asserts | |
run: | | |
mkdir -p results | |
make clean | |
make lfs.csv \ | |
CFLAGS+=" \ | |
-DLFS_NO_DEBUG \ | |
-DLFS_NO_WARN \ | |
-DLFS_NO_ERROR \ | |
-D'LFS_ASSERT(test)=do {if(!(test)) {return -1;}} while(0)'" | |
cp lfs.csv results/${{matrix.arch}}-error-asserts.csv | |
./scripts/summary.py results/${{matrix.arch}}-error-asserts.csv | |
- name: upload-results | |
uses: actions/upload-artifact@v2 | |
with: | |
name: results | |
path: results | |
# create statuses with results | |
- name: collect-status | |
run: | | |
mkdir -p status | |
for f in $(shopt -s nullglob ; echo results/*.csv) | |
do | |
export STEP="results$( | |
echo $f | sed -n 's/[^-]*-\(.*\).csv/-\1/p')" | |
for r in code stack structs | |
do | |
export CONTEXT="results (${{matrix.arch}}$( | |
echo $f | sed -n 's/[^-]*-\(.*\).csv/, \1/p')) / $r" | |
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("(?<result>[0-9∞]+)").result' \ | |
|| echo 0)" | |
export DESCRIPTION="$(./scripts/summary.py $f -f $r -Y | awk ' | |
NR==2 {printf "%s B",$2} | |
NR==2 && ENVIRON["PREV"]+0 != 0 { | |
printf " (%+.1f%%)",100*($2-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/$r-${{matrix.arch}}$( | |
echo $f | sed -n 's/[^-]*-\(.*\).csv/-\1/p').json | |
done | |
done | |
- name: upload-status | |
uses: actions/upload-artifact@v2 | |
with: | |
name: status | |
path: status | |
retention-days: 1 | |
# run under Valgrind to check for memory errors | |
valgrind: | |
runs-on: ubuntu-20.04 | |
steps: | |
- uses: actions/checkout@v2 | |
- name: install | |
run: | | |
# need toml, also pip3 isn't installed by default? | |
sudo apt-get update -qq | |
sudo apt-get install -qq python3 python3-pip | |
sudo pip3 install toml | |
- name: install-valgrind | |
run: | | |
sudo apt-get update -qq | |
sudo apt-get install -qq valgrind | |
valgrind --version | |
# normal tests, we don't need to test all geometries | |
- name: test-valgrind | |
run: make test TESTFLAGS+="-k --valgrind" | |
# self-host with littlefs-fuse for a fuzz-like test | |
fuse: | |
runs-on: ubuntu-20.04 | |
if: ${{!endsWith(github.ref, '-prefix')}} | |
steps: | |
- uses: actions/checkout@v2 | |
- name: install | |
run: | | |
# need toml, also pip3 isn't installed by default? | |
sudo apt-get update -qq | |
sudo apt-get install -qq python3 python3-pip libfuse-dev | |
sudo pip3 install toml | |
fusermount -V | |
gcc --version | |
- uses: actions/checkout@v2 | |
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 | |
# test migration using littlefs-fuse | |
migrate: | |
runs-on: ubuntu-20.04 | |
if: ${{!endsWith(github.ref, '-prefix')}} | |
steps: | |
- uses: actions/checkout@v2 | |
- name: install | |
run: | | |
# need toml, also pip3 isn't installed by default? | |
sudo apt-get update -qq | |
sudo apt-get install -qq python3 python3-pip libfuse-dev | |
sudo pip3 install toml | |
fusermount -V | |
gcc --version | |
- uses: actions/checkout@v2 | |
with: | |
repository: littlefs-project/littlefs-fuse | |
ref: v2 | |
path: v2 | |
- uses: actions/checkout@v2 | |
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 | |
# 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 | |
# collect coverage info | |
coverage: | |
runs-on: ubuntu-20.04 | |
needs: [test] | |
steps: | |
- uses: actions/checkout@v2 | |
- name: install | |
run: | | |
sudo apt-get update -qq | |
sudo apt-get install -qq python3 python3-pip lcov | |
sudo pip3 install toml | |
# yes we continue-on-error nearly every step, continue-on-error | |
# at job level apparently still marks a job as failed, which isn't | |
# what we want | |
- uses: actions/download-artifact@v2 | |
continue-on-error: true | |
with: | |
name: coverage | |
path: coverage | |
- name: results-coverage | |
continue-on-error: true | |
run: | | |
mkdir -p results | |
lcov $(for f in coverage/*.info ; do echo "-a $f" ; done) \ | |
-o results/coverage.info | |
./scripts/coverage.py results/coverage.info -o results/coverage.csv | |
- name: upload-results | |
uses: actions/upload-artifact@v2 | |
with: | |
name: results | |
path: results | |
- name: collect-status | |
run: | | |
mkdir -p status | |
[ -e results/coverage.csv ] || exit 0 | |
export STEP="results-coverage" | |
export CONTEXT="results / coverage" | |
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("(?<result>[0-9\\.]+)").result' \ | |
|| echo 0)" | |
export DESCRIPTION="$( | |
./scripts/coverage.py -u results/coverage.csv -Y | awk -F '[ /%]+' ' | |
NR==2 {printf "%.1f%% of %d lines",$4,$3} | |
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}}", | |
target_step: env.STEP}' \ | |
| tee status/coverage.json | |
- name: upload-status | |
uses: actions/upload-artifact@v2 | |
with: | |
name: status | |
path: status | |
retention-days: 1 |