testit_android revision 92f1ee6990752f26aebdbbfb5a87c474d3edd1e0
1#!/bin/sh
2# //===--------------------------- testit ---------------------------------===//
3# //
4# //                     The LLVM Compiler Infrastructure
5# //
6# // This file is distributed under the University of Illinois Open Source
7# // License. See LICENSE.TXT for details.
8# //
9# //===--------------------------------------------------------------------===//
10
11currentpath=`pwd`
12origpath=$currentpath
13currentdir=`basename $currentpath`
14while [ $currentdir != "test" ]; do
15	if [ $currentdir = "/" ]
16	then
17		echo "current directory must be in or under \"test\"."
18		exit 1
19	fi
20	cd ..
21	currentpath=`pwd`
22	currentdir=`basename $currentpath`
23done
24
25cd ..
26LIBCXX_ROOT=`pwd`
27cd $origpath
28
29ANDROID_SUPPORT=$(cd "$LIBCXX_ROOT"/../../../android/support && pwd)
30
31VERBOSE=1
32
33run () {
34  if [ "$VERBOSE" -gt 1 ]; then
35    echo "COMMAND: $@"
36  fi
37  case $VERBOSE in
38    0|1)
39      # Hide command output and errors.
40      "$@" >/dev/null 2>&1
41      ;;
42    2)
43      # Only hide command output
44      "$@" >/dev/null
45      ;;
46    *)
47      # Show command output and errors.
48      "$@"
49      ;;
50  esac
51}
52
53run2 () {
54  if [ "$VERBOSE" -gt 2 ]; then
55    echo "COMMAND: $@"
56  fi
57  case $VERBOSE in
58    0|1)
59      # Hide command output and errors.
60      "$@" >/dev/null 2>&1
61      ;;
62    2)
63      # Only hide command output
64      "$@" >/dev/null
65      ;;
66    *)
67      # Show command output and errors.
68      "$@"
69      ;;
70  esac
71}
72
73# The list of valid target abis supported by this script.
74VALID_ABIS="armeabi armeabi-v7a x86 mips"
75
76DO_HELP=
77DO_STATIC=
78TARGET_ABI=
79TARGET_ARCH=
80TARGET_PATH=/data/local/tmp/libcxx
81CXX=
82for OPT; do
83  case $OPT in
84    --help|-?)
85      DO_HELP=true
86      ;;
87    --abi=*)
88      TARGET_ABI=${OPT##--abi=}
89      ;;
90    --static)
91      DO_STATIC=true
92      ;;
93    --cxx=*)
94      CXX=${OPT##--cxx=}
95      ;;
96    --verbose)
97      VERBOSE=$(( $VERBOSE + 1 ))
98      ;;
99    -*)
100      echo "Unknown option: $OPT. See --help."
101      exit 1
102      ;;
103    *)
104      echo "This script doesn't take parameters. See --help."
105      exit 1
106      ;;
107  esac
108done
109
110if [ "$DO_HELP" ]; then
111  echo \
112"Usage: $(basename $0) [options]
113
114This script is used to run the libc++ test suite for Android.
115You will need the following things:
116
117  - The prebuild libc++ libraries in your NDK install.
118  - A prebuilt Android toolchain in your path.
119  - The 'adb' tool in your path.
120  - An Android device connected to ADB.
121
122The toolchain and device must match your target ABI. For example, if
123you use --abi=armeabi-v7a, your device must run ARMv7-A Android binaries,
124and arm-linux-androideabi-g++ will be used to compile all tests, unless
125you use --cxx=<command> to override it.
126
127Valid options:
128  --help|-?        Display this message.
129  --abi=<name>     Specify target ABI. Use --abi=list for list.
130  --static         Link against static libc++ library.
131  --cxx=<program>  Override C++ compiler/linker.
132  --verbose        Increase verbosity.
133"
134  exit 0
135fi
136
137# Check target ABI.
138if [ "$TARGET_ABI" = "list" ]; then
139  echo "List of valid target ABIs:"
140  for ABI in $VALID_ABIS; do
141    printf " %s" $ABI
142  done
143  printf "\n"
144  exit 0
145fi
146
147if [ -z "$TARGET_ABI" ]; then
148  echo "ERROR: Please specify a target ABI (--abi=<name>)."
149  exit 1
150fi
151
152FOUND_ABI=
153for ABI in $VALID_ABIS; do
154  if [ "$ABI" = "$TARGET_ABI" ]; then
155    FOUND_ABI=true
156    break
157  fi
158done
159
160if [ -z "$FOUND_ABI" ]; then
161  echo "ERROR: Invalid abi '$TARGET_ABI'. Must be one of: $VALID_ABIS"
162  exit 1
163fi
164
165LIBCXX_LIBS=$(cd $LIBCXX_ROOT/.. && pwd)/libs/$TARGET_ABI
166for LIB in libc++_static.a libc++_shared.so; do
167  if [ ! -f "$LIBCXX_LIBS/$LIB" ]; then
168    echo "ERROR: Missing prebuilt library: $LIBCXX_LIBS/$LIB"
169    echo "Please run: build/tools/build-cxx-stl.sh --stl=libc++"
170    exit 1
171  fi
172done
173
174LIBCOMPILER_RT_LIBS=$(cd "$LIBCXX_ROOT"/../../../android/compiler-rt && pwd)/libs/$TARGET_ABI
175for LIB in libcompiler_rt_static.a libcompiler_rt_shared.so; do
176  if [ ! -f "$LIBCOMPILER_RT_LIBS/$LIB" ]; then
177    echo "ERROR: Missing prebuilt library: $LIBCOMPILER_RT_LIBS/$LIB"
178    echo "Please run: build/tools/build-compiler-rt.sh --ndk-dir=$NDK \
179--src-dir=/tmp/ndk-$USER/src/llvm-3.3/compiler-rt --llvm-version=3.3"
180    exit 1
181  fi
182done
183
184# Check or detect C++ toolchain.
185TOOLCHAIN_CFLAGS=
186TOOLCHAIN_LDFLAGS=
187if [ -z "$TOOLCHAIN_PREFIX" ]; then
188  # Compute 
189  case $TARGET_ABI in
190    armeabi)
191      TOOLCHAIN_PREFIX=arm-linux-androideabi
192      TOOLCHAIN_CFLAGS="-mthumb"
193      TOOLCHAIN_LDFLAGS="-mthumb"
194      ;;
195    armeabi-v7a)
196      TOOLCHAIN_PREFIX=arm-linux-androideabi
197      TOOLCHAIN_CFLAGS="-march=armv7-a -mthumb -mfpu=vfpv3-d16"
198      TOOLCHAIN_LDFLAGS="-march=armv7-a -mthumb -Wl,--fix-cortex-a8"
199      ;;
200    x86)
201      TOOLCHAIN_PREFIX=i686-linux-android
202      ;;
203    mips)
204      TOOLCHAIN_PREFIX=mipsel-linux-android
205      ;;
206    *)
207      echo "ERROR: Unknown ABI '$ABI'"
208      exit 1
209      ;;
210  esac
211  if [ -z "$CXX" ]; then
212      CXX=$TOOLCHAIN_PREFIX-g++
213  fi
214fi
215
216REAL_CXX=$(which "$CXX" 2>/dev/null)
217if [ -z "$REAL_CXX" ]; then
218  echo "ERROR: Missing C++ compiler: $CXX"
219  exit 1
220fi
221CC=$CXX
222
223if [ -z "$OPTIONS" ]
224then
225  OPTIONS="-std=c++11 -O0 -g"
226fi
227OPTIONS="$OPTIONS $TOOLCHAIN_CFLAGS $TOOLCHAIN_LDFLAGS"
228OPTIONS="$OPTIONS -I$LIBCXX_ROOT/test/support"
229# llvm-libc++/libcxx/test/lit.cfg line #294 defineds the following for testing on Linux
230OPTIONS="$OPTIONS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS"
231
232if [ -z "$HEADER_INCLUDE" ]
233then
234  HEADER_INCLUDE="-I$LIBCXX_ROOT/include -I$ANDROID_SUPPORT/include"
235fi
236
237if [ -z "$SOURCE_LIB" ]
238then
239  SOURCE_LIB="-L$LIBCXX_LIBS"
240fi
241SOURCE_LIB="$SOURCE_LIB -L$LIBCOMPILER_RT_LIBS"
242
243if [ -z "$ADB" ]
244then
245  ADB=adb
246fi
247
248# Run a shell command through ADB, return its status.
249adb_shell () {
250  # We need a temporary file to store the output of our command
251  local CMD_OUT RET OUTPUT
252  CMD_OUT=$(mktemp /tmp/testit_android-cmdout-XXXXXX)
253  # Run the command, while storing the standard output to CMD_OUT
254  # and appending the exit code as the last line.
255  if [ "$VERBOSE" -gt 2 ]; then
256    echo "COMMAND: $ADB shell $@"
257  fi
258  $ADB shell "$@ ; echo \$?" | sed -e 's![[:cntrl:]]!!g' > $CMD_OUT 2>&1
259  # Get last line in log, which contains the exit code from the command
260  RET=$(sed -e '$!d' $CMD_OUT)
261  # Get output, which corresponds to everything except the last line
262  OUT=$(sed -e '$d' $CMD_OUT)
263  rm -f $CMD_OUT
264  if [ "$VERBOSE" -gt 2 ]; then
265    printf "%s" "$OUT"
266  fi
267  return $RET
268}
269
270# Push a given file through ADB.
271# $1: File path
272adb_push () {
273  local FILE=$1
274  local FILE_BASENAME=$(basename "$FILE")
275  run2 $ADB push $FILE $TARGET_PATH/$FILE_BASENAME 2>/dev/null
276}
277
278# Run a given executable through ADB.
279# $1: Executable path
280adb_run () {
281  local EXECUTABLE=$1
282  local EXECUTABLE_BASENAME=$(basename "$EXECUTABLE")
283  run2 $ADB push $EXECUTABLE $TARGET_PATH/$EXECUTABLE_BASENAME 2>/dev/null &&
284  adb_shell "LD_LIBRARY_PATH=$TARGET_PATH; cd $TARGET_PATH; ./$EXECUTABLE_BASENAME"
285}
286
287adb_shell "rm -rf $TARGET_PATH"
288adb_shell "mkdir -p $TARGET_PATH"
289
290if [ "$DO_STATIC" ]; then
291  # Statically link to ensure the executable can be run easily through ADB
292  LIBS="-lc++_static -lcompiler_rt_static -latomic"
293else
294  run2 $ADB push $LIBCXX_LIBS/libc++_shared.so $TARGET_PATH 2>/dev/null
295  if [ $? != 0 ]; then
296    echo "ERROR: Can't push shared libc++ to target device!"
297    exit 1
298  fi
299  run2 $ADB push $LIBCOMPILER_RT_LIBS/libcompiler_rt_shared.so $TARGET_PATH 2>/dev/null
300  if [ $? != 0 ]; then
301    echo "ERROR: Can't push shared libcompiler_rt to target device!"
302    exit 1
303  fi
304  LIBS="-nodefaultlibs -lc++_shared -lcompiler_rt_shared -latomic -ldl -lc -lm"
305fi
306
307case $TRIPLE in
308  *-*-mingw* | *-*-cygwin* | *-*-win*)
309    TEST_EXE=test.exe
310    ;;
311  *)
312    TEST_EXE=a.out
313    ;;
314esac
315
316TEST_EXE=/tmp/testit_android-$USER-$$-$TEST_EXE
317
318FAIL=0
319PASS=0
320UNIMPLEMENTED=0
321IMPLEMENTED_FAIL=0
322IMPLEMENTED_PASS=0
323
324afunc() {
325	fail=0
326	pass=0
327	if (ls *.fail.cpp > /dev/null 2>&1)
328	then
329		for FILE in $(ls *.fail.cpp); do
330			if run $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS -o $TEST_EXE > /dev/null 2>&1
331			then
332				rm $TEST_EXE
333				echo "$FILE should not compile"
334				fail=$(($fail+1))
335			else
336				pass=$(($pass+1))
337			fi
338		done
339	fi
340
341	if (ls *.pass.cpp > /dev/null 2>&1)
342	then
343		if (ls *.dat > /dev/null 2>&1)
344		then
345			adb_shell "rm $TARGET_PATH/*.dat"
346			for FILE in $(ls *.dat); do
347	                      if [ "$VERBOSE" -gt 1 ]; then
348	                          echo "Pushing data: " $FILE
349			      fi
350			      adb_push $FILE
351			      if [ $? != 0 ]; then
352				  echo "Failed to push file $FILE"
353	                      fi
354			done
355		fi
356		for FILE in $(ls *.pass.cpp); do
357                      if [ "$VERBOSE" -gt 1 ]; then
358                          echo "Running test: " $FILE
359                      fi
360                        COMMAND="( cd $(pwd) && $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS )"
361			if run $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS -o $TEST_EXE
362			then
363				if adb_run $TEST_EXE
364				then
365					rm $TEST_EXE
366					pass=$(($pass+1))
367				else
368					echo "`pwd`/$FILE failed at run time"
369					echo "Compile line was: $COMMAND # run-time"
370					fail=$(($fail+1))
371					rm $TEST_EXE
372				fi
373			else
374				echo "`pwd`/$FILE failed to compile"
375				echo "Compile line was: $COMMAND # compile-time"
376				fail=$(($fail+1))
377			fi
378		done
379	fi
380
381	if [ $fail -gt 0 ]
382	then
383		echo "failed $fail tests in `pwd`"
384		IMPLEMENTED_FAIL=$(($IMPLEMENTED_FAIL+1))
385	fi
386	if [ $pass -gt 0 ]
387	then
388		echo "passed $pass tests in `pwd`"
389		if [ $fail -eq 0 ]
390		then
391			IMPLEMENTED_PASS=$((IMPLEMENTED_PASS+1))
392		fi
393	fi
394	if [ $fail -eq 0 -a $pass -eq 0 ]
395	then
396		echo "not implemented:  `pwd`"
397		UNIMPLEMENTED=$(($UNIMPLEMENTED+1))
398	fi
399
400	FAIL=$(($FAIL+$fail))
401	PASS=$(($PASS+$pass))
402
403	for FILE in *
404	do
405		if [ -d "$FILE" ];
406		then
407			cd $FILE
408			afunc
409			cd ..
410		fi
411	done
412}
413
414afunc
415
416echo "****************************************************"
417echo "Results for `pwd`:"
418echo "using `$CC --version`"
419echo "with $OPTIONS $HEADER_INCLUDE $SOURCE_LIB"
420echo "----------------------------------------------------"
421echo "sections without tests   : $UNIMPLEMENTED"
422echo "sections with failures   : $IMPLEMENTED_FAIL"
423echo "sections without failures: $IMPLEMENTED_PASS"
424echo "                       +   ----"
425echo "total number of sections : $(($UNIMPLEMENTED+$IMPLEMENTED_FAIL+$IMPLEMENTED_PASS))"
426echo "----------------------------------------------------"
427echo "number of tests failed   : $FAIL"
428echo "number of tests passed   : $PASS"
429echo "                       +   ----"
430echo "total number of tests    : $(($FAIL+$PASS))"
431echo "****************************************************"
432
433exit $FAIL
434