super-test.sh 15.9 KB
Newer Older
1
#! /usr/bin/env bash
2 3 4 5 6 7 8 9

set -euo pipefail

doit() {
  echo "@@@@ $@"
  "$@"
}

Kenton Varda's avatar
Kenton Varda committed
10 11
QUICK=

12 13
PARALLEL=$(nproc 2>/dev/null || echo 1)

Kenton Varda's avatar
Kenton Varda committed
14 15
while [ $# -gt 0 ]; do
  case "$1" in
16 17 18
    -j* )
      PARALLEL=${1#-j}
      ;;
Kenton Varda's avatar
Kenton Varda committed
19 20 21 22 23
    test )
      ;;  # nothing
    quick )
      QUICK=quick
      ;;
24 25 26
    caffeinate )
      # Re-run preventing sleep.
      shift
27
      exec caffeinate -ims $0 $@
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
      ;;
    tmpdir )
      # Clone to a temp directory.
      if [ "$#" -lt 2 ]; then
        echo "usage: $0 tmpdir NAME [COMMAND]" >&2
        exit 1
      fi
      DIR=/tmp/$2
      shift 2
      if [ -e $DIR ]; then
        if [ "${DIR/*..*}" = "" ]; then
          echo "NO DO NOT PUT .. IN THERE IT'S GOING TO GO IN /tmp AND I'M GONNA DELETE IT" >&2
          exit 1
        fi
        if [ ! -e "$DIR/super-test.sh" ]; then
          echo "$DIR exists and it doesn't look like one of mine." >&2
          exit 1
        fi
        # make distcheck leaves non-writable files when it fails, so we need to chmod to be safe.
        chmod -R +w $DIR
        rm -rf $DIR
      fi
      git clone . $DIR
      cd $DIR
52
      exec ./super-test.sh "$@"
53
      ;;
Kenton Varda's avatar
Kenton Varda committed
54 55 56 57 58 59 60 61 62 63
    remote )
      if [ "$#" -lt 2 ]; then
        echo "usage: $0 remote HOST [COMMAND]" >&2
        exit 1
      fi
      HOST=$2
      shift 2
      echo "========================================================================="
      echo "Pushing code to $HOST..."
      echo "========================================================================="
64
      BRANCH=$(git rev-parse --abbrev-ref HEAD)
Kenton Varda's avatar
Kenton Varda committed
65
      ssh $HOST '(chmod -fR +w tmp-test-capnp || true) && rm -rf tmp-test-capnp && mkdir tmp-test-capnp && git init tmp-test-capnp'
66
      git push ssh://$HOST/~/tmp-test-capnp "$BRANCH:test"
67 68
      ssh $HOST "cd tmp-test-capnp && git checkout test"
      exec ssh $HOST "cd tmp-test-capnp && ./super-test.sh $@ && cd .. && rm -rf tmp-test-capnp"
Kenton Varda's avatar
Kenton Varda committed
69
      ;;
Kenton Varda's avatar
Kenton Varda committed
70 71 72 73 74 75 76 77
    compiler )
      if [ "$#" -lt 2 ]; then
        echo "usage: $0 compiler CXX_NAME" >&2
        exit 1
      fi
      export CXX="$2"
      shift
      ;;
Kenton Varda's avatar
Kenton Varda committed
78 79 80
    clang )
      export CXX=clang++
      ;;
81 82 83
    gcc-4.9 )
      export CXX=g++-4.9
      ;;
Kenton Varda's avatar
Kenton Varda committed
84 85 86
    gcc-4.8 )
      export CXX=g++-4.8
      ;;
Kenton Varda's avatar
Kenton Varda committed
87 88 89
    gcc-4.7 )
      export CXX=g++-4.7
      ;;
90 91 92 93 94 95 96 97 98 99 100
    mingw )
      if [ "$#" -ne 2 ]; then
        echo "usage: $0 mingw CROSS_HOST" >&2
        exit 1
      fi
      CROSS_HOST=$2

      cd c++
      test -e configure || doit autoreconf -i
      test ! -e Makefile || (echo "ERROR: Directory unclean!" >&2 && false)

101
      export WINEPATH='Z:\usr\'"$CROSS_HOST"'\lib;Z:\usr\lib\gcc\'"$CROSS_HOST"'\6.3-win32;Z:'"$PWD"'\.libs'
102

103
      doit ./configure --host="$CROSS_HOST" --disable-shared CXXFLAGS='-static-libgcc -static-libstdc++'
104

105
      doit make -j$PARALLEL check
106 107 108 109 110
      doit make distclean
      rm -f *-mingw.exe
      exit 0
      ;;
    android )
Kenton Varda's avatar
Kenton Varda committed
111 112 113 114 115
      # To install Android SDK:
      # - Download command-line tools: https://developer.android.com/studio/index.html#command-tools
      # - Run $SDK_HOME/tools/bin/sdkmanager platform-tools 'platforms;android-25' 'system-images;android-25;google_apis;armeabi-v7a' emulator 'build-tools;25.0.2' ndk-bundle
      # - Run $SDK_HOME/tools/bin/avdmanager create avd -n capnp -k 'system-images;android-25;google_apis;armeabi-v7a' -b google_apis/armeabi-v7a
      # - Run $SDK_HOME/ndk-bundle/build/tools/make_standalone_toolchain.py --arch arm --api 24 --install-dir $TOOLCHAIN_HOME
116 117 118 119 120 121 122 123 124 125 126 127
      if [ "$#" -ne 4 ]; then
        echo "usage: $0 android SDK_HOME TOOLCHAIN_HOME CROSS_HOST" >&2
        exit 1
      fi
      SDK_HOME=$2
      TOOLCHAIN_HOME=$3
      CROSS_HOST=$4

      cd c++
      test -e configure || doit autoreconf -i
      test ! -e Makefile || (echo "ERROR: Directory unclean!" >&2 && false)
      doit ./configure --disable-shared
128
      doit make -j$PARALLEL capnp capnpc-c++
129 130 131 132 133 134 135 136

      cp capnp capnp-host
      cp capnpc-c++ capnpc-c++-host

      export PATH="$TOOLCHAIN_HOME/bin:$PATH"
      doit make distclean
      doit ./configure --host="$CROSS_HOST" --with-external-capnp --disable-shared CXXFLAGS='-pie -fPIE' CAPNP=./capnp-host CAPNPC_CXX=./capnpc-c++-host

137 138
      doit make -j$PARALLEL
      doit make -j$PARALLEL capnp-test
139 140 141

      echo "Starting emulator..."
      trap 'kill $(jobs -p)' EXIT
142
      # TODO(someday): Speed up with KVM? Then maybe we won't have to skip fuzz tests?
Kenton Varda's avatar
Kenton Varda committed
143 144
      $SDK_HOME/emulator/emulator -avd capnp -no-window &
      $SDK_HOME/platform-tools/adb 'wait-for-device'
145
      echo "Waiting for localhost to be resolvable..."
Kenton Varda's avatar
Kenton Varda committed
146 147 148 149 150
      doit $SDK_HOME/platform-tools/adb shell 'while ! ping -c 1 localhost > /dev/null 2>&1; do sleep 1; done'
      # TODO(cleanup): With 'adb shell' I find I cannot put files anywhere, so I'm using 'su' a
      #   lot here. There is probably a better way.
      doit $SDK_HOME/platform-tools/adb shell 'su 0 tee /data/capnp-test > /dev/null' < capnp-test
      doit $SDK_HOME/platform-tools/adb shell 'su 0 chmod a+rx /data/capnp-test'
151
      doit $SDK_HOME/platform-tools/adb shell 'cd /data && CAPNP_SKIP_FUZZ_TEST=1 su 0 /data/capnp-test && echo ANDROID_""TESTS_PASSED' | tee android-test.log
152 153 154 155
      grep -q ANDROID_TESTS_PASSED android-test.log

      doit make distclean
      rm -f capnp-host capnpc-c++-host
Kenton Varda's avatar
Kenton Varda committed
156 157
      exit 0
      ;;
158
    cmake )
159
      cd c++
160 161 162 163
      rm -rf cmake-build
      mkdir cmake-build
      cd cmake-build
      doit cmake -G "Unix Makefiles" ..
164
      doit make -j$PARALLEL check
165 166
      exit 0
      ;;
167 168 169 170 171 172 173 174 175 176 177 178
    exotic )
      echo "========================================================================="
      echo "MinGW 64-bit"
      echo "========================================================================="
      "$0" mingw x86_64-w64-mingw32
      echo "========================================================================="
      echo "MinGW 32-bit"
      echo "========================================================================="
      "$0" mingw i686-w64-mingw32
      echo "========================================================================="
      echo "Android"
      echo "========================================================================="
Kenton Varda's avatar
Kenton Varda committed
179
      "$0" android /home/kenton/android-sdk-linux /home/kenton/android-24 arm-linux-androideabi
180 181 182 183
      echo "========================================================================="
      echo "CMake"
      echo "========================================================================="
      "$0" cmake
184
      exit 0
185
      ;;
Kenton Varda's avatar
Kenton Varda committed
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
    clean )
      rm -rf tmp-staging
      cd c++
      if [ -e Makefile ]; then
        doit make maintainer-clean
      fi
      rm -f capnproto-*.tar.gz samples/addressbook samples/addressbook.capnp.c++ \
            samples/addressbook.capnp.h
      exit 0
      ;;
    help )
      echo "usage: $0 [COMMAND]"
      echo "commands:"
      echo "  test          Runs tests (the default)."
      echo "  clang         Runs tests using Clang compiler."
201
      echo "  gcc-4.7       Runs tests using gcc-4.7."
Kenton Varda's avatar
Kenton Varda committed
202
      echo "  gcc-4.8       Runs tests using gcc-4.8."
203
      echo "  gcc-4.9       Runs tests using gcc-4.9."
Kenton Varda's avatar
Kenton Varda committed
204
      echo "  remote HOST   Runs tests on HOST via SSH."
205 206
      echo "  mingw         Cross-compiles to MinGW and runs tests using WINE."
      echo "  android       Cross-compiles to Android and runs tests using emulator."
Kenton Varda's avatar
Kenton Varda committed
207 208 209 210 211 212 213 214 215 216 217 218
      echo "  clean         Delete temporary files that may be left after failure."
      echo "  help          Prints this help text."
      exit 0
      ;;
    * )
      echo "unknown command: $1" >&2
      echo "try: $0 help" >&2
      exit 1
      ;;
  esac
  shift
done
219

220
# Build optimized builds because they catch more problems, but also enable debugging macros.
221
# Enable lots of warnings and make sure the build breaks if they fire.  Disable strict-aliasing
222 223
# because GCC warns about code that I know is OK.  Disable sign-compare because I've fixed more
# sign-compare warnings than probably all other warnings combined and I've never seen it flag a
224
# real problem. Disable unused parameters because it's stupidly noisy and never a real problem.
225 226
# Enable expensive release-gating tests.
export CXXFLAGS="-O2 -DDEBUG -Wall -Wextra -Werror -Wno-strict-aliasing -Wno-sign-compare -Wno-unused-parameter -DCAPNP_EXPENSIVE_TESTS=1"
227

228 229
STAGING=$PWD/tmp-staging

230 231 232 233 234 235 236
rm -rf "$STAGING"
mkdir "$STAGING"
mkdir "$STAGING/bin"
mkdir "$STAGING/lib"
export PATH=$STAGING/bin:$PATH
export LD_LIBRARY_PATH=$STAGING/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
export PKG_CONFIG_PATH=$STAGING/lib/pkgconfig
Kenton Varda's avatar
Kenton Varda committed
237 238 239 240

if [ "$QUICK" = quick ]; then
  echo "************************** QUICK TEST ***********************************"
fi
241 242 243 244 245

echo "========================================================================="
echo "Building c++"
echo "========================================================================="

246 247 248
# Apple now aliases gcc to clang, so probe to find out what compiler we're really using.
if (${CXX:-g++} -dM -E -x c++ /dev/null 2>&1 | grep -q '__clang__'); then
  IS_CLANG=yes
249
  DISABLE_OPTIMIZATION_IF_GCC=
250
else
251
  IS_CLANG=no
252
  DISABLE_OPTIMIZATION_IF_GCC=-O0
253 254
fi

255
if [ $IS_CLANG = yes ]; then
256 257
  # Don't fail out on this ridiculous "argument unused during compilation" warning.
  export CXXFLAGS="$CXXFLAGS -Wno-error=unused-command-line-argument"
258
else
259
  # GCC emits uninitialized warnings all over and they seem bogus. We use valgrind to test for
260 261 262
  # uninitialized memory usage later on. GCC 4 also emits strange bogus warnings with
  # -Wstrict-overflow, so we disable it.
  CXXFLAGS="$CXXFLAGS -Wno-maybe-uninitialized -Wno-strict-overflow"
263
fi
264

265 266 267
cd c++
doit autoreconf -i
doit ./configure --prefix="$STAGING"
268
doit make -j$PARALLEL check
269

270 271 272 273 274
if [ $IS_CLANG = no ]; then
  # Verify that generated code compiles with pedantic warnings.  Make sure to treat capnp headers
  # as system headers so warnings in them are ignored.
  doit ${CXX:-g++} -isystem src -std=c++11 -fno-permissive -pedantic -Wall -Wextra -Werror \
      -c src/capnp/test.capnp.c++ -o /dev/null
Kenton Varda's avatar
Kenton Varda committed
275 276
fi

277 278 279 280 281 282
echo "========================================================================="
echo "Testing c++ install"
echo "========================================================================="

doit make install

Kenton Varda's avatar
Kenton Varda committed
283 284
test "x$(which capnp)" = "x$STAGING/bin/capnp"
test "x$(which capnpc-c++)" = "x$STAGING/bin/capnpc-c++"
285

286
cd samples
287

288
doit capnp compile -oc++ addressbook.capnp -I"$STAGING"/include --no-standard-import
289 290
doit ${CXX:-g++} -std=c++11 addressbook.c++ addressbook.capnp.c++ -o addressbook \
    $CXXFLAGS $(pkg-config --cflags --libs capnp)
291 292 293 294
echo "@@@@ ./addressbook (in various configurations)"
./addressbook write | ./addressbook read
./addressbook dwrite | ./addressbook dread
rm addressbook addressbook.capnp.c++ addressbook.capnp.h
295 296 297 298 299 300 301 302 303 304 305 306 307 308

doit capnp compile -oc++ calculator.capnp -I"$STAGING"/include --no-standard-import
doit ${CXX:-g++} -std=c++11 calculator-client.c++ calculator.capnp.c++ -o calculator-client \
    $CXXFLAGS $(pkg-config --cflags --libs capnp-rpc)
doit ${CXX:-g++} -std=c++11 calculator-server.c++ calculator.capnp.c++ -o calculator-server \
    $CXXFLAGS $(pkg-config --cflags --libs capnp-rpc)
rm -f /tmp/capnp-calculator-example-$$
./calculator-server unix:/tmp/capnp-calculator-example-$$ &
sleep 0.1
./calculator-client unix:/tmp/capnp-calculator-example-$$
kill %+
wait %+ || true
rm calculator-client calculator-server calculator.capnp.c++ calculator.capnp.h /tmp/capnp-calculator-example-$$

309 310
cd ..

311 312 313 314 315 316
if [ "$QUICK" = quick ]; then
  doit make maintainer-clean
  rm -rf "$STAGING"
  exit 0
fi

317 318 319 320 321
echo "========================================================================="
echo "Testing --with-external-capnp"
echo "========================================================================="

doit make distclean
322 323
doit ./configure --prefix="$STAGING" --disable-shared \
    --with-external-capnp CAPNP=$STAGING/bin/capnp
324
doit make -j$PARALLEL check
325 326 327 328 329 330 331 332

echo "========================================================================="
echo "Testing --disable-reflection"
echo "========================================================================="

doit make distclean
doit ./configure --prefix="$STAGING" --disable-shared --disable-reflection \
    --with-external-capnp CAPNP=$STAGING/bin/capnp
333
doit make -j$PARALLEL check
334 335 336 337 338 339 340 341 342 343 344 345 346 347
doit make distclean

# Test 32-bit build now while we have $STAGING available for cross-compiling.
if [ "x`uname -m`" = "xx86_64" ]; then
  echo "========================================================================="
  echo "Testing 32-bit build"
  echo "========================================================================="

  if [[ "`uname`" =~ CYGWIN ]]; then
    # It's just not possible to run cygwin32 binaries from within cygwin64.

    # Build as if we are cross-compiling, using the capnp we installed to $STAGING.
    doit ./configure --prefix="$STAGING" --disable-shared --host=i686-pc-cygwin \
        --with-external-capnp CAPNP=$STAGING/bin/capnp
348 349
    doit make -j$PARALLEL
    doit make -j$PARALLEL capnp-test.exe
350

351 352 353 354 355 356 357 358 359
    # Expect a cygwin32 sshd to be listening at localhost port 2222, and use it
    # to run the tests.
    doit scp -P 2222 capnp-test.exe localhost:~/tmp-capnp-test.exe
    doit ssh -p 2222 localhost './tmp-capnp-test.exe && rm tmp-capnp-test.exe'

    doit make distclean

  elif [ "x${CXX:-g++}" != "xg++-4.8" ]; then
    doit ./configure CXX="${CXX:-g++} -m32" --disable-shared
360
    doit make -j$PARALLEL check
361 362 363 364 365 366 367 368 369
    doit make distclean
  fi
fi

echo "========================================================================="
echo "Testing c++ uninstall"
echo "========================================================================="

doit ./configure --prefix="$STAGING"
370 371 372 373 374 375
doit make uninstall

echo "========================================================================="
echo "Testing c++ dist"
echo "========================================================================="

376
doit make -j$PARALLEL distcheck
377 378 379
doit make distclean
rm capnproto-*.tar.gz

380 381 382 383 384 385
if [ "x`uname`" = xLinux ]; then
  echo "========================================================================="
  echo "Testing generic Unix (no Linux-specific features)"
  echo "========================================================================="

  doit ./configure --disable-shared CXXFLAGS="$CXXFLAGS -DKJ_USE_FUTEX=0 -DKJ_USE_EPOLL=0"
386
  doit make -j$PARALLEL check
387 388 389
  doit make distclean
fi

390 391 392 393
echo "========================================================================="
echo "Testing with -fno-rtti and -fno-exceptions"
echo "========================================================================="

394 395 396 397 398
# GCC miscompiles capnpc-c++ when -fno-exceptions and -O2 are specified together. The
# miscompilation happens in one specific inlined call site of Array::dispose(), but this method
# is inlined in hundreds of other places without issue, so I have no idea how to narrow down the
# bug. Clang works fine. So, for now, we disable optimizations on GCC for -fno-exceptions tests.

399
doit ./configure --disable-shared CXXFLAGS="$CXXFLAGS -fno-rtti"
400
doit make -j$PARALLEL check
401
doit make distclean
402
doit ./configure --disable-shared CXXFLAGS="$CXXFLAGS -fno-exceptions $DISABLE_OPTIMIZATION_IF_GCC"
403
doit make -j$PARALLEL check
404
doit make distclean
405
doit ./configure --disable-shared CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions $DISABLE_OPTIMIZATION_IF_GCC"
406
doit make -j$PARALLEL check
407

408 409 410 411
# Valgrind is currently "experimental and mostly broken" on OSX and fails to run the full test
# suite, but I have it installed because it did manage to help me track down a bug or two.  Anyway,
# skip it on OSX for now.
if [ "x`uname`" != xDarwin ] && which valgrind > /dev/null; then
Kenton Varda's avatar
Kenton Varda committed
412 413
  doit make distclean

414 415 416 417 418
  echo "========================================================================="
  echo "Testing with valgrind"
  echo "========================================================================="

  doit ./configure --disable-shared CXXFLAGS="-g"
419 420
  doit make -j$PARALLEL
  doit make -j$PARALLEL capnp-test
421 422 423
  # Running the fuzz tests under Valgrind is a great thing to do -- but it takes
  # some 40 minutes. So, it needs to be done as a separate step of the release
  # process, perhaps along with the AFL tests.
Kenton Varda's avatar
Kenton Varda committed
424
  CAPNP_SKIP_FUZZ_TEST=1 doit valgrind --leak-check=full --track-fds=yes --error-exitcode=1 ./capnp-test
425 426
fi

427 428 429
doit make maintainer-clean

rm -rf "$STAGING"