1#!/usr/bin/env sh 2 3# Builds and runs tests for a particular target passed as an argument to this 4# script. 5 6set -eux 7 8mirrors_url="https://ci-mirrors.rust-lang.org/libc" 9 10target="$1" 11 12export RUST_BACKTRACE="${RUST_BACKTRACE:-1}" 13 14# If we're going to run tests inside of a qemu image, then we don't need any of 15# the scripts below. Instead, download the image, prepare a filesystem which has 16# the current state of this repository, and then run the image. 17# 18# It's assume that all images, when run with two disks, will run the `run.sh` 19# script from the second which we place inside. 20if [ -n "${QEMU:-}" ]; then 21 tmpdir=/tmp/qemu-img-creation 22 mkdir -p "${tmpdir}" 23 24 if [ -z "${QEMU#*.gz}" ]; then 25 # image is .gz : download and uncompress it 26 base_file="${QEMU%.gz}" 27 pipe_cmd="gunzip -d" 28 elif [ -z "${QEMU#*.xz}" ]; then 29 # image is .xz : download and uncompress it 30 base_file="${QEMU%.xz}" 31 pipe_cmd="unxz" 32 else 33 # plain qcow2 image: just download it 34 base_file="$QEMU" 35 pipe_cmd="cat" # nop to forward the result 36 fi 37 38 qemufile="$(echo "$base_file" | sed 's/\//__/g')" 39 if [ ! -f "${tmpdir}/${qemufile}" ]; then 40 curl --retry 5 "${mirrors_url}/${QEMU}" | $pipe_cmd > "${tmpdir}/${qemufile}" 41 fi 42 43 # Create a mount a fresh new filesystem image that we'll later pass to QEMU. 44 # This will have a `run.sh` script will which use the artifacts inside to run 45 # on the host. 46 rm -f "${tmpdir}/libc-test.img" 47 mkdir "${tmpdir}/mount" 48 49 # Do the standard rigamarole of cross-compiling an executable and then the 50 # script to run just executes the binary. 51 cargo build \ 52 --manifest-path libc-test/Cargo.toml \ 53 --target "$target" \ 54 --test main ${LIBC_CI_ZBUILD_STD+"-Zbuild-std"} 55 rm "${CARGO_TARGET_DIR}/${target}"/debug/main-*.d 56 cp "${CARGO_TARGET_DIR}/${target}"/debug/main-* "${tmpdir}"/mount/libc-test 57 # shellcheck disable=SC2016 58 echo 'exec $1/libc-test' > "${tmpdir}/mount/run.sh" 59 60 du -sh "${tmpdir}/mount" 61 genext2fs \ 62 --root "${tmpdir}/mount" \ 63 --size-in-blocks 100000 \ 64 "${tmpdir}/libc-test.img" 65 66 # Pass -snapshot to prevent tampering with the disk images, this helps when 67 # running this script in development. The two drives are then passed next, 68 # first is the OS and second is the one we just made. Next the network is 69 # configured to work (I'm not entirely sure how), and then finally we turn off 70 # graphics and redirect the serial console output to out.log. 71 qemu-system-x86_64 \ 72 -m 1024 \ 73 -snapshot \ 74 -drive if=virtio,file="${tmpdir}/${qemufile}" \ 75 -drive if=virtio,file="${tmpdir}/libc-test.img" \ 76 -net nic,model=virtio \ 77 -net user \ 78 -nographic \ 79 -vga none 2>&1 | tee "${CARGO_TARGET_DIR}/out.log" 80 exec grep -E "^(PASSED)|(test result: ok)" "${CARGO_TARGET_DIR}/out.log" 81fi 82 83cmd="cargo test --target $target ${LIBC_CI_ZBUILD_STD+"-Zbuild-std"}" 84 85# Run tests in the `libc` crate 86case "$target" in 87 # FIXME(android): unit tests fail to start on Android 88 # FIXME(s390x): unit tests fail to locate glibc 89 *android*) ;; 90 *s390x*) ;; 91 *) $cmd 92esac 93 94# Everything else is in `libc-test` 95cmd="$cmd --manifest-path libc-test/Cargo.toml" 96 97if [ "$target" = "s390x-unknown-linux-gnu" ]; then 98 # FIXME: s390x-unknown-linux-gnu often fails to test due to timeout, 99 # so we retry this N times. 100 N=5 101 n=0 102 passed=0 103 until [ $n -ge $N ]; do 104 if [ "$passed" = "0" ]; then 105 if $cmd --no-default-features; then 106 passed=$((passed+1)) 107 continue 108 fi 109 elif [ "$passed" = "1" ]; then 110 if $cmd; then 111 passed=$((passed+1)) 112 continue 113 fi 114 elif [ "$passed" = "2" ]; then 115 if $cmd --features extra_traits; then 116 break 117 fi 118 fi 119 n=$((n+1)) 120 sleep 1 121 done 122else 123 $cmd --no-default-features 124 $cmd 125 $cmd --features extra_traits 126fi 127