summaryrefslogtreecommitdiff
path: root/test.sh
diff options
context:
space:
mode:
Diffstat (limited to 'test.sh')
-rwxr-xr-xtest.sh1835
1 files changed, 1835 insertions, 0 deletions
diff --git a/test.sh b/test.sh
new file mode 100755
index 0000000..85f1baa
--- /dev/null
+++ b/test.sh
@@ -0,0 +1,1835 @@
+#!/bin/sh
+#
+# A simple test suite for ccache.
+#
+# Copyright (C) 2002-2007 Andrew Tridgell
+# Copyright (C) 2009-2011 Joel Rosdahl
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+unset CCACHE_BASEDIR
+unset CCACHE_CC
+unset CCACHE_COMPILERCHECK
+unset CCACHE_COMPRESS
+unset CCACHE_CPP2
+unset CCACHE_DIR
+unset CCACHE_DISABLE
+unset CCACHE_EXTENSION
+unset CCACHE_EXTRAFILES
+unset CCACHE_HARDLINK
+unset CCACHE_HASHDIR
+unset CCACHE_LOGFILE
+unset CCACHE_NLEVELS
+unset CCACHE_NODIRECT
+unset CCACHE_NOSTATS
+unset CCACHE_PATH
+unset CCACHE_PREFIX
+unset CCACHE_READONLY
+unset CCACHE_RECACHE
+unset CCACHE_SLOPPINESS
+unset CCACHE_TEMPDIR
+unset CCACHE_UMASK
+unset CCACHE_UNIFY
+
+test_failed() {
+ echo "SUITE: \"$testsuite\", TEST: \"$testname\" - $1"
+ $CCACHE -s
+ cd ..
+ echo TEST FAILED
+ echo "Test data and log file have been left in $TESTDIR"
+ exit 1
+}
+
+randcode() {
+ outfile="$1"
+ nlines=$2
+ i=0
+ (
+ while [ $i -lt $nlines ]; do
+ echo "int foo$nlines$i(int x) { return x; }"
+ i=`expr $i + 1`
+ done
+ ) >> "$outfile"
+}
+
+
+getstat() {
+ stat="$1"
+ value=`$CCACHE -s | grep "$stat" | cut -c34-40`
+ echo $value
+}
+
+checkstat() {
+ stat="$1"
+ expected_value="$2"
+ value=`getstat "$stat"`
+ if [ "$expected_value" != "$value" ]; then
+ test_failed "Expected \"$stat\" to be $expected_value, got $value"
+ fi
+}
+
+checkfile() {
+ if [ ! -f $1 ]; then
+ test_failed "$1 not found"
+ fi
+ if [ "`cat $1`" != "$2" ]; then
+ test_failed "Bad content of $1.\nExpected: $2\nActual: `cat $1`"
+ fi
+}
+
+checkfilecount() {
+ expected=$1
+ pattern=$2
+ dir=$3
+ actual=`find $dir -name "$pattern" | wc -l`
+ if [ $actual -ne $expected ]; then
+ test_failed "Found $actual (expected $expected) $pattern files in $dir"
+ fi
+}
+
+sed_in_place() {
+ expr=$1
+ shift
+ for file in $*; do
+ sed "$expr" > ${file}.sed < $file
+ mv ${file}.sed $file
+ done
+}
+
+backdate() {
+ touch -t 199901010000 "$@"
+}
+
+run_suite() {
+ rm -rf $CCACHE_DIR
+ CCACHE_NODIRECT=1
+ export CCACHE_NODIRECT
+
+ echo "starting testsuite $1"
+ testsuite=$1
+
+ ${1}_suite
+
+ testname="the tmp directory should be empty"
+ if [ -d $CCACHE_DIR/tmp ] && [ "`find $CCACHE_DIR/tmp -type f | wc -l`" -gt 0 ]; then
+ test_failed "$CCACHE_DIR/tmp is not empty"
+ fi
+}
+
+base_tests() {
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 0
+ checkstat 'files in cache' 0
+
+ j=1
+ rm -f *.c
+ while [ $j -lt 32 ]; do
+ randcode test$j.c $j
+ j=`expr $j + 1`
+ done
+
+ testname="BASIC"
+ $CCACHE_COMPILE -c test1.c
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ checkstat 'files in cache' 1
+
+ testname="BASIC2"
+ $CCACHE_COMPILE -c test1.c
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+ checkstat 'files in cache' 1
+
+ testname="debug"
+ $CCACHE_COMPILE -c test1.c -g
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 2
+ checkstat 'files in cache' 2
+
+ testname="debug2"
+ $CCACHE_COMPILE -c test1.c -g
+ checkstat 'cache hit (preprocessed)' 2
+ checkstat 'cache miss' 2
+
+ testname="output"
+ $CCACHE_COMPILE -c test1.c -o foo.o
+ checkstat 'cache hit (preprocessed)' 3
+ checkstat 'cache miss' 2
+
+ testname="link"
+ $CCACHE_COMPILE test1.c -o test 2> /dev/null
+ checkstat 'called for link' 1
+
+ testname="linkobj"
+ $CCACHE_COMPILE foo.o -o test 2> /dev/null
+ checkstat 'called for link' 2
+
+ testname="preprocessing"
+ $CCACHE_COMPILE -E -c test1.c > /dev/null 2>&1
+ checkstat 'called for preprocessing' 1
+
+ testname="multiple"
+ $CCACHE_COMPILE -c test1.c test2.c
+ checkstat 'multiple source files' 1
+
+ testname="find"
+ $CCACHE blahblah -c test1.c 2> /dev/null
+ checkstat "couldn't find the compiler" 1
+
+ testname="bad"
+ $CCACHE_COMPILE -c test1.c -I 2> /dev/null
+ checkstat 'bad compiler arguments' 1
+
+ testname="unsupported source language"
+ ln -f test1.c test1.ccc
+ $CCACHE_COMPILE -c test1.ccc 2> /dev/null
+ checkstat 'unsupported source language' 1
+
+ testname="unsupported"
+ $CCACHE_COMPILE -M foo -c test1.c > /dev/null 2>&1
+ checkstat 'unsupported compiler option' 1
+
+ testname="stdout"
+ $CCACHE echo foo -c test1.c > /dev/null
+ checkstat 'compiler produced stdout' 1
+
+ testname="non-regular"
+ mkdir testd
+ $CCACHE_COMPILE -o testd -c test1.c > /dev/null 2>&1
+ rmdir testd
+ checkstat 'output to a non-regular file' 1
+
+ testname="no-input"
+ $CCACHE_COMPILE -c -O2 2> /dev/null
+ checkstat 'no input file' 1
+
+ testname="CCACHE_DISABLE"
+ CCACHE_DISABLE=1 $CCACHE_COMPILE -c test1.c 2> /dev/null
+ checkstat 'cache hit (preprocessed)' 3
+ $CCACHE_COMPILE -c test1.c
+ checkstat 'cache hit (preprocessed)' 4
+
+ testname="CCACHE_CPP2"
+ CCACHE_CPP2=1 $CCACHE_COMPILE -c test1.c -O -O
+ checkstat 'cache hit (preprocessed)' 4
+ checkstat 'cache miss' 3
+
+ CCACHE_CPP2=1 $CCACHE_COMPILE -c test1.c -O -O
+ checkstat 'cache hit (preprocessed)' 5
+ checkstat 'cache miss' 3
+
+ testname="CCACHE_NOSTATS"
+ CCACHE_NOSTATS=1 $CCACHE_COMPILE -c test1.c -O -O
+ checkstat 'cache hit (preprocessed)' 5
+ checkstat 'cache miss' 3
+
+ testname="CCACHE_RECACHE"
+ CCACHE_RECACHE=1 $CCACHE_COMPILE -c test1.c -O -O
+ checkstat 'cache hit (preprocessed)' 5
+ checkstat 'cache miss' 4
+
+ # strictly speaking should be 3 - RECACHE causes a double counting!
+ checkstat 'files in cache' 4
+ $CCACHE -c > /dev/null
+ checkstat 'files in cache' 3
+
+ testname="CCACHE_HASHDIR"
+ CCACHE_HASHDIR=1 $CCACHE_COMPILE -c test1.c -O -O
+ checkstat 'cache hit (preprocessed)' 5
+ checkstat 'cache miss' 5
+
+ CCACHE_HASHDIR=1 $CCACHE_COMPILE -c test1.c -O -O
+ checkstat 'cache hit (preprocessed)' 6
+ checkstat 'cache miss' 5
+ checkstat 'files in cache' 4
+
+ testname="comments"
+ echo '/* a silly comment */' > test1-comment.c
+ cat test1.c >> test1-comment.c
+ $CCACHE_COMPILE -c test1-comment.c
+ rm -f test1-comment*
+ checkstat 'cache hit (preprocessed)' 6
+ checkstat 'cache miss' 6
+
+ testname="CCACHE_UNIFY"
+ CCACHE_UNIFY=1 $CCACHE_COMPILE -c test1.c
+ checkstat 'cache hit (preprocessed)' 6
+ checkstat 'cache miss' 7
+ mv test1.c test1-saved.c
+ echo '/* another comment */' > test1.c
+ cat test1-saved.c >> test1.c
+ CCACHE_UNIFY=1 $CCACHE_COMPILE -c test1.c
+ mv test1-saved.c test1.c
+ checkstat 'cache hit (preprocessed)' 7
+ checkstat 'cache miss' 7
+
+ testname="cache-size"
+ for f in *.c; do
+ $CCACHE_COMPILE -c $f
+ done
+ checkstat 'cache hit (preprocessed)' 8
+ checkstat 'cache miss' 37
+ checkstat 'files in cache' 36
+
+ $CCACHE -C >/dev/null
+
+ testname="cpp call"
+ $CCACHE_COMPILE -c test1.c -E > test1.i
+ checkstat 'cache hit (preprocessed)' 8
+ checkstat 'cache miss' 37
+
+ testname="direct .i compile"
+ $CCACHE_COMPILE -c test1.c
+ checkstat 'cache hit (preprocessed)' 8
+ checkstat 'cache miss' 38
+
+ $CCACHE_COMPILE -c test1.i
+ checkstat 'cache hit (preprocessed)' 9
+ checkstat 'cache miss' 38
+
+ $CCACHE_COMPILE -c test1.i
+ checkstat 'cache hit (preprocessed)' 10
+ checkstat 'cache miss' 38
+
+ testname="-x c"
+ $CCACHE_COMPILE -x c -c test1.ccc
+ checkstat 'cache hit (preprocessed)' 10
+ checkstat 'cache miss' 39
+ $CCACHE_COMPILE -x c -c test1.ccc
+ checkstat 'cache hit (preprocessed)' 11
+ checkstat 'cache miss' 39
+
+ testname="-xc"
+ $CCACHE_COMPILE -xc -c test1.ccc
+ checkstat 'cache hit (preprocessed)' 12
+ checkstat 'cache miss' 39
+
+ testname="-x none"
+ $CCACHE_COMPILE -x assembler -x none -c test1.c
+ checkstat 'cache hit (preprocessed)' 13
+ checkstat 'cache miss' 39
+
+ testname="-x unknown"
+ $CCACHE_COMPILE -x unknown -c test1.c 2>/dev/null
+ checkstat 'cache hit (preprocessed)' 13
+ checkstat 'cache miss' 39
+ checkstat 'unsupported source language' 2
+
+ testname="-D not hashed"
+ $CCACHE_COMPILE -DNOT_AFFECTING=1 -c test1.c 2>/dev/null
+ checkstat 'cache hit (preprocessed)' 14
+ checkstat 'cache miss' 39
+
+ if [ -x /usr/bin/printf ]; then
+ /usr/bin/printf '#include <wchar.h>\nwchar_t foo[] = L"\xbf";\n' >latin1.c
+ if CCACHE_DISABLE=1 $COMPILER -c -finput-charset=latin1 latin1.c >/dev/null 2>&1; then
+ testname="-finput-charset"
+ CCACHE_CPP2=1 $CCACHE_COMPILE -c -finput-charset=latin1 latin1.c
+ checkstat 'cache hit (preprocessed)' 14
+ checkstat 'cache miss' 40
+ $CCACHE_COMPILE -c -finput-charset=latin1 latin1.c
+ checkstat 'cache hit (preprocessed)' 15
+ checkstat 'cache miss' 40
+ fi
+ fi
+
+ testname="compilercheck=mtime"
+ $CCACHE -Cz >/dev/null
+ cat >compiler.sh <<EOF
+#!/bin/sh
+CCACHE_DISABLE=1 # If $COMPILER happens to be a ccache symlink...
+export CCACHE_DISABLE
+exec $COMPILER "\$@"
+# A comment
+EOF
+ chmod +x compiler.sh
+ backdate compiler.sh
+ CCACHE_COMPILERCHECK=mtime $CCACHE ./compiler.sh -c test1.c
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ sed_in_place 's/comment/yoghurt/' compiler.sh # Don't change the size
+ chmod +x compiler.sh
+ backdate compiler.sh
+ CCACHE_COMPILERCHECK=mtime $CCACHE ./compiler.sh -c test1.c
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+ touch compiler.sh
+ CCACHE_COMPILERCHECK=mtime $CCACHE ./compiler.sh -c test1.c
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 2
+
+ testname="compilercheck=content"
+ $CCACHE -z >/dev/null
+ CCACHE_COMPILERCHECK=content $CCACHE ./compiler.sh -c test1.c
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ backdate compiler.sh
+ CCACHE_COMPILERCHECK=content $CCACHE ./compiler.sh -c test1.c
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+ echo "# Compiler upgrade" >>compiler.sh
+ backdate compiler.sh
+ CCACHE_COMPILERCHECK=content $CCACHE ./compiler.sh -c test1.c
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 2
+
+ testname="compilercheck=none"
+ $CCACHE -z >/dev/null
+ backdate compiler.sh
+ CCACHE_COMPILERCHECK=none $CCACHE ./compiler.sh -c test1.c
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ CCACHE_COMPILERCHECK=none $CCACHE ./compiler.sh -c test1.c
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+ echo "# Compiler upgrade" >>compiler.sh
+ CCACHE_COMPILERCHECK=none $CCACHE ./compiler.sh -c test1.c
+ checkstat 'cache hit (preprocessed)' 2
+ checkstat 'cache miss' 1
+
+ testname="compilercheck=command"
+ $CCACHE -z >/dev/null
+ backdate compiler.sh
+ CCACHE_COMPILERCHECK='echo %compiler%' $CCACHE ./compiler.sh -c test1.c
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ echo "# Compiler upgrade" >>compiler.sh
+ CCACHE_COMPILERCHECK="echo ./compiler.sh" $CCACHE ./compiler.sh -c test1.c
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+ cat <<EOF >foobar.sh
+#!/bin/sh
+echo foo
+echo bar
+EOF
+ chmod +x foobar.sh
+ CCACHE_COMPILERCHECK='./foobar.sh' $CCACHE ./compiler.sh -c test1.c
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 2
+ CCACHE_COMPILERCHECK='echo foo; echo bar' $CCACHE ./compiler.sh -c test1.c
+ checkstat 'cache hit (preprocessed)' 2
+ checkstat 'cache miss' 2
+
+ testname="compilercheck=unknown_command"
+ $CCACHE -z >/dev/null
+ backdate compiler.sh
+ CCACHE_COMPILERCHECK="unknown_command" $CCACHE ./compiler.sh -c test1.c 2>/dev/null
+ if [ "$?" -eq 0 ]; then
+ test_failed "Expected failure running unknown_command to verify compiler but was success"
+ fi
+ checkstat 'compiler check failed' 1
+
+ testname="no object file"
+ cat <<'EOF' >test_no_obj.c
+int test_no_obj;
+EOF
+ cat <<'EOF' >prefix-remove.sh
+#!/bin/sh
+"$@"
+[ x$3 = x-o ] && rm $4
+EOF
+ chmod +x prefix-remove.sh
+ CCACHE_PREFIX=`pwd`/prefix-remove.sh $CCACHE_COMPILE -c test_no_obj.c
+ checkstat 'compiler produced no output' 1
+
+ testname="empty object file"
+ cat <<'EOF' >test_empty_obj.c
+int test_empty_obj;
+EOF
+ cat <<'EOF' >prefix-empty.sh
+#!/bin/sh
+"$@"
+[ x$3 = x-o ] && cp /dev/null $4
+EOF
+ chmod +x prefix-empty.sh
+ CCACHE_PREFIX=`pwd`/prefix-empty.sh $CCACHE_COMPILE -c test_empty_obj.c
+ checkstat 'compiler produced empty output' 1
+
+ testname="stderr-files"
+ $CCACHE -Cz >/dev/null
+ num=`find $CCACHE_DIR -name '*.stderr' | wc -l`
+ if [ $num -ne 0 ]; then
+ test_failed "$num stderr files found, expected 0"
+ fi
+ cat <<EOF >stderr.c
+int stderr(void)
+{
+ /* Trigger warning by having no return statement. */
+}
+EOF
+ checkstat 'files in cache' 0
+ $CCACHE_COMPILE -Wall -W -c stderr.c 2>/dev/null
+ num=`find $CCACHE_DIR -name '*.stderr' | wc -l`
+ if [ $num -ne 1 ]; then
+ test_failed "$num stderr files found, expected 1"
+ fi
+ checkstat 'files in cache' 2
+
+ testname="zero-stats"
+ $CCACHE -z > /dev/null
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 0
+ checkstat 'files in cache' 2
+
+ testname="clear"
+ $CCACHE -C > /dev/null
+ checkstat 'files in cache' 0
+
+ rm -f test1.c
+}
+
+base_suite() {
+ CCACHE_COMPILE="$CCACHE $COMPILER"
+ base_tests
+}
+
+link_suite() {
+ if [ `dirname $COMPILER` = . ]; then
+ ln -s ../ccache $COMPILER
+ CCACHE_COMPILE="./$COMPILER"
+ base_tests
+ else
+ echo "Compiler ($COMPILER) not taken from PATH -- not running link test"
+ fi
+}
+
+hardlink_suite() {
+ CCACHE_COMPILE="$CCACHE $COMPILER"
+ CCACHE_HARDLINK=1
+ export CCACHE_HARDLINK
+ CCACHE_NOCOMPRESS=1
+ export CCACHE_NOCOMPRESS
+ base_tests
+ unset CCACHE_HARDLINK
+ unset CCACHE_NOCOMPRESS
+}
+
+cpp2_suite() {
+ CCACHE_COMPILE="$CCACHE $COMPILER"
+ CCACHE_CPP2=1
+ export CCACHE_CPP2
+ base_tests
+ unset CCACHE_CPP2
+}
+
+nlevels4_suite() {
+ CCACHE_COMPILE="$CCACHE $COMPILER"
+ CCACHE_NLEVELS=4
+ export CCACHE_NLEVELS
+ base_tests
+ unset CCACHE_NLEVELS
+}
+
+nlevels1_suite() {
+ CCACHE_COMPILE="$CCACHE $COMPILER"
+ CCACHE_NLEVELS=1
+ export CCACHE_NLEVELS
+ base_tests
+ unset CCACHE_NLEVELS
+}
+
+direct_suite() {
+ unset CCACHE_NODIRECT
+
+ ##################################################################
+ # Create some code to compile.
+ cat <<EOF >test.c
+/* test.c */
+#include "test1.h"
+#include "test2.h"
+EOF
+ cat <<EOF >test1.h
+#include "test3.h"
+int test1;
+EOF
+ cat <<EOF >test2.h
+int test2;
+EOF
+ cat <<EOF >test3.h
+int test3;
+EOF
+ backdate test1.h test2.h test3.h
+
+ ##################################################################
+ # First compilation is a miss.
+ testname="first compilation"
+ $CCACHE -z >/dev/null
+ $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ ##################################################################
+ # Another compilation should now generate a direct hit.
+ testname="direct hit"
+ $CCACHE -z >/dev/null
+ $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 0
+
+ ##################################################################
+ # Check that corrupt manifest files are handled and rewritten.
+ testname="corrupt manifest file"
+ $CCACHE -z >/dev/null
+ manifest_file=`find $CCACHE_DIR -name '*.manifest'`
+ rm $manifest_file
+ touch $manifest_file
+ $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 0
+ $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 0
+
+ ##################################################################
+ # Compiling with CCACHE_NODIRECT set should generate a preprocessed hit.
+ testname="preprocessed hit"
+ $CCACHE -z >/dev/null
+ CCACHE_NODIRECT=1 $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 0
+
+ ##################################################################
+ # Test compilation of a modified include file.
+ testname="modified include file"
+ $CCACHE -z >/dev/null
+ echo "int test3_2;" >>test3.h
+ backdate test3.h
+ $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ ##################################################################
+ # A removed but previously compiled header file should be handled
+ # gracefully.
+ testname="missing header file"
+ $CCACHE -z >/dev/null
+
+ mv test1.h test1.h.saved
+ mv test3.h test3.h.saved
+ cat <<EOF >test1.h
+/* No more include of test3.h */
+int test1;
+EOF
+ backdate test1.h
+
+ $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ # Restore
+ mv test1.h.saved test1.h
+ mv test3.h.saved test3.h
+
+ rm -f other.d
+
+ ##################################################################
+ # Check calculation of dependency file names.
+ $CCACHE -Cz >/dev/null
+ checkstat 'files in cache' 0
+ mkdir test.dir
+ for ext in .obj "" . .foo.bar; do
+ testname="dependency file calculation from object file 'test$ext'"
+ dep_file=test.dir/`echo test$ext | sed 's/\.[^.]*\$//'`.d
+ $CCACHE $COMPILER -MD -c test.c -o test.dir/test$ext
+ rm -f $dep_file
+ $CCACHE $COMPILER -MD -c test.c -o test.dir/test$ext
+ if [ ! -f $dep_file ]; then
+ test_failed "$dep_file missing"
+ fi
+ done
+ rm -rf test.dir
+ checkstat 'files in cache' 12
+
+ ##################################################################
+ # Check that -Wp,-MD,file.d works.
+ testname="-Wp,-MD"
+ $CCACHE -z >/dev/null
+ $CCACHE $COMPILER -c -Wp,-MD,other.d test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ checkfile other.d "test.o: test.c test1.h test3.h test2.h"
+
+ rm -f other.d
+
+ $CCACHE $COMPILER -c -Wp,-MD,other.d test.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ checkfile other.d "test.o: test.c test1.h test3.h test2.h"
+
+ rm -f other.d
+
+ ##################################################################
+ # Check that -Wp,-MMD,file.d works.
+ testname="-Wp,-MMD"
+ $CCACHE -C >/dev/null
+ $CCACHE -z >/dev/null
+ $CCACHE $COMPILER -c -Wp,-MMD,other.d test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ checkfile other.d "test.o: test.c test1.h test3.h test2.h"
+
+ rm -f other.d
+
+ $CCACHE $COMPILER -c -Wp,-MMD,other.d test.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ checkfile other.d "test.o: test.c test1.h test3.h test2.h"
+
+ rm -f other.d
+
+ ##################################################################
+ # Check that -Wp,-MD,file.d,-P disables direct mode.
+ testname="-Wp,-MD,file.d,-P"
+ $CCACHE -z >/dev/null
+ $CCACHE $COMPILER -c -Wp,-MD,$DEVNULL,-P test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ $CCACHE $COMPILER -c -Wp,-MD,$DEVNULL,-P test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+
+ ##################################################################
+ # Check that -Wp,-MMD,file.d,-P disables direct mode.
+ testname="-Wp,-MDD,file.d,-P"
+ $CCACHE -z >/dev/null
+ $CCACHE $COMPILER -c -Wp,-MMD,$DEVNULL,-P test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ $CCACHE $COMPILER -c -Wp,-MMD,$DEVNULL,-P test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+
+ ##################################################################
+ # Test some header modifications to get multiple objects in the manifest.
+ testname="several objects"
+ $CCACHE -z >/dev/null
+ for i in 0 1 2 3 4; do
+ echo "int test1_$i;" >>test1.h
+ backdate test1.h
+ $CCACHE $COMPILER -c test.c
+ $CCACHE $COMPILER -c test.c
+ done
+ checkstat 'cache hit (direct)' 5
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 5
+
+ ##################################################################
+ # Check that -MD works.
+ testname="-MD"
+ $CCACHE -z >/dev/null
+ $CCACHE $COMPILER -c -MD test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ checkfile test.d "test.o: test.c test1.h test3.h test2.h"
+
+ rm -f test.d
+
+ $CCACHE $COMPILER -c -MD test.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ checkfile test.d "test.o: test.c test1.h test3.h test2.h"
+
+ ##################################################################
+ # Check the scenario of running a ccache with direct mode on a cache
+ # built up by a ccache without direct mode support.
+ testname="direct mode on old cache"
+ $CCACHE -z >/dev/null
+ $CCACHE -C >/dev/null
+ CCACHE_NODIRECT=1 $CCACHE $COMPILER -c -MD test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ checkfile test.d "test.o: test.c test1.h test3.h test2.h"
+
+ rm -f test.d
+
+ CCACHE_NODIRECT=1 $CCACHE $COMPILER -c -MD test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+ checkfile test.d "test.o: test.c test1.h test3.h test2.h"
+
+ rm -f test.d
+
+ $CCACHE $COMPILER -c -MD test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 2
+ checkstat 'cache miss' 1
+ checkfile test.d "test.o: test.c test1.h test3.h test2.h"
+
+ rm -f test.d
+
+ $CCACHE $COMPILER -c -MD test.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 2
+ checkstat 'cache miss' 1
+ checkfile test.d "test.o: test.c test1.h test3.h test2.h"
+
+ ##################################################################
+ # Check that -MF works.
+ testname="-MF"
+ $CCACHE -C >/dev/null
+ $CCACHE -z >/dev/null
+ $CCACHE $COMPILER -c -MD -MF other.d test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ checkfile other.d "test.o: test.c test1.h test3.h test2.h"
+
+ rm -f other.d
+
+ $CCACHE $COMPILER -c -MD -MF other.d test.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ checkfile other.d "test.o: test.c test1.h test3.h test2.h"
+
+ ##################################################################
+ # Check that a missing .d file in the cache is handled correctly.
+ testname="missing dependency file"
+ $CCACHE -z >/dev/null
+ $CCACHE -C >/dev/null
+
+ $CCACHE $COMPILER -c -MD test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ checkfile other.d "test.o: test.c test1.h test3.h test2.h"
+
+ $CCACHE $COMPILER -c -MD test.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ checkfile other.d "test.o: test.c test1.h test3.h test2.h"
+
+ find $CCACHE_DIR -name '*.d' -exec rm -f '{}' \;
+
+ $CCACHE $COMPILER -c -MD test.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+ checkfile other.d "test.o: test.c test1.h test3.h test2.h"
+
+ ##################################################################
+ # Check that stderr from both the preprocessor and the compiler is emitted
+ # in direct mode too.
+ testname="cpp stderr"
+ $CCACHE -z >/dev/null
+ $CCACHE -C >/dev/null
+cat <<EOF >cpp-warning.c
+#if FOO
+/* Trigger preprocessor warning about extra token after #endif. */
+#endif FOO
+int stderr(void)
+{
+ /* Trigger compiler warning by having no return statement. */
+}
+EOF
+ $CCACHE $COMPILER -Wall -W -c cpp-warning.c 2>stderr-orig.txt
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ CCACHE_NODIRECT=1
+ export CCACHE_NODIRECT
+ $CCACHE $COMPILER -Wall -W -c cpp-warning.c 2>stderr-cpp.txt
+ unset CCACHE_NODIRECT
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+ checkfile stderr-cpp.txt "`cat stderr-orig.txt`"
+
+ $CCACHE $COMPILER -Wall -W -c cpp-warning.c 2>stderr-mf.txt
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+ checkfile stderr-mf.txt "`cat stderr-orig.txt`"
+
+ ##################################################################
+ # Check that changes in comments are ignored when hashing.
+ testname="changes in comments"
+ $CCACHE -C >/dev/null
+ $CCACHE -z >/dev/null
+ cat <<EOF >comments.h
+/*
+ * /* foo comment
+ */
+EOF
+ backdate comments.h
+ cat <<'EOF' >comments.c
+#include "comments.h"
+char test[] = "\
+/* apple */ // banana"; // foo comment
+EOF
+
+ $CCACHE $COMPILER -c comments.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ sed_in_place 's/foo/ignored/' comments.h comments.c
+ backdate comments.h
+
+ $CCACHE $COMPILER -c comments.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ # Check that comment-like string contents are hashed.
+ sed_in_place 's/apple/orange/' comments.c
+ backdate comments.h
+
+ $CCACHE $COMPILER -c comments.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 2
+
+ ##################################################################
+ # Check that it's possible to compile and cache an empty source code file.
+ testname="empty source file"
+ $CCACHE -Cz >/dev/null
+ cp /dev/null empty.c
+ $CCACHE $COMPILER -c empty.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ $CCACHE $COMPILER -c empty.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ ##################################################################
+ # Check that empty include files are handled as well.
+ testname="empty include file"
+ $CCACHE -Cz >/dev/null
+ cp /dev/null empty.h
+ cat <<EOF >include_empty.c
+#include "empty.h"
+EOF
+ backdate empty.h
+ $CCACHE $COMPILER -c include_empty.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ $CCACHE $COMPILER -c include_empty.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ ##################################################################
+ # Check that direct mode correctly detects file name/path changes.
+ testname="__FILE__ in source file"
+ $CCACHE -Cz >/dev/null
+ cat <<EOF >file.c
+#define file __FILE__
+int test;
+EOF
+ $CCACHE $COMPILER -c file.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ $CCACHE $COMPILER -c file.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ $CCACHE $COMPILER -c `pwd`/file.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 2
+
+ testname="__FILE__ in include file"
+ $CCACHE -Cz >/dev/null
+ cat <<EOF >file.h
+#define file __FILE__
+int test;
+EOF
+ backdate file.h
+ cat <<EOF >file_h.c
+#include "file.h"
+EOF
+ $CCACHE $COMPILER -c file_h.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ $CCACHE $COMPILER -c file_h.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ mv file_h.c file2_h.c
+ $CCACHE $COMPILER -c `pwd`/file2_h.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 2
+
+ ##################################################################
+ # Check that direct mode ignores __FILE__ if sloppiness is specified.
+ testname="__FILE__ in source file, sloppy"
+ $CCACHE -Cz >/dev/null
+ cat <<EOF >file.c
+#define file __FILE__
+int test;
+EOF
+ CCACHE_SLOPPINESS=file_macro $CCACHE $COMPILER -c file.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ CCACHE_SLOPPINESS=file_macro $CCACHE $COMPILER -c file.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ CCACHE_SLOPPINESS=file_macro $CCACHE $COMPILER -c `pwd`/file.c
+ checkstat 'cache hit (direct)' 2
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ testname="__FILE__ in include file, sloppy"
+ $CCACHE -Cz >/dev/null
+ cat <<EOF >file.h
+#define file __FILE__
+int test;
+EOF
+ backdate file.h
+ cat <<EOF >file_h.c
+#include "file.h"
+EOF
+ CCACHE_SLOPPINESS=file_macro $CCACHE $COMPILER -c file_h.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ CCACHE_SLOPPINESS=file_macro $CCACHE $COMPILER -c file_h.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ mv file_h.c file2_h.c
+ CCACHE_SLOPPINESS=file_macro $CCACHE $COMPILER -c `pwd`/file2_h.c
+ checkstat 'cache hit (direct)' 2
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ ##################################################################
+ # Check that we never get direct hits when __TIME__ is used.
+ testname="__TIME__ in source file"
+ $CCACHE -Cz >/dev/null
+ cat <<EOF >time.c
+#define time __TIME__
+int test;
+EOF
+ $CCACHE $COMPILER -c time.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ $CCACHE $COMPILER -c time.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+
+ testname="__TIME__ in include time"
+ $CCACHE -Cz >/dev/null
+ cat <<EOF >time.h
+#define time __TIME__
+int test;
+EOF
+ backdate time.h
+ cat <<EOF >time_h.c
+#include "time.h"
+EOF
+ $CCACHE $COMPILER -c time_h.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ $CCACHE $COMPILER -c time_h.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+
+ ##################################################################
+ # Check that direct mode ignores __TIME__ when sloppiness is specified.
+ testname="__TIME__ in source file, sloppy"
+ $CCACHE -Cz >/dev/null
+ cat <<EOF >time.c
+#define time __TIME__
+int test;
+EOF
+ CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c time.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c time.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ testname="__TIME__ in include time, sloppy"
+ $CCACHE -Cz >/dev/null
+ cat <<EOF >time.h
+#define time __TIME__
+int test;
+EOF
+ backdate time.h
+ cat <<EOF >time_h.c
+#include "time.h"
+EOF
+ CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c time_h.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c time_h.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ ##################################################################
+ # Check that a too new include file turns off direct mode.
+ testname="too new include file"
+ $CCACHE -Cz >/dev/null
+ cat <<EOF >new.c
+#include "new.h"
+EOF
+ cat <<EOF >new.h
+int test;
+EOF
+ touch -t 203801010000 new.h
+ $CCACHE $COMPILER -c new.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ $CCACHE $COMPILER -c new.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+
+ ##################################################################
+ # Check that include file mtime is ignored when sloppiness is specified.
+ testname="too new include file, sloppy"
+ $CCACHE -Cz >/dev/null
+ cat <<EOF >new.c
+#include "new.h"
+EOF
+ cat <<EOF >new.h
+int test;
+EOF
+ touch -t 203801010000 new.h
+ CCACHE_SLOPPINESS=include_file_mtime $CCACHE $COMPILER -c new.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ CCACHE_SLOPPINESS=include_file_mtime $CCACHE $COMPILER -c new.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+}
+
+basedir_suite() {
+ ##################################################################
+ # Create some code to compile.
+ mkdir -p dir1/src dir1/include
+ cat <<EOF >dir1/src/test.c
+#include <test.h>
+EOF
+ cat <<EOF >dir1/include/test.h
+int test;
+EOF
+ cp -r dir1 dir2
+ backdate dir1/include/test.h dir2/include/test.h
+
+ cat <<EOF >stderr.h
+int stderr(void)
+{
+ /* Trigger warning by having no return statement. */
+}
+EOF
+ cat <<EOF >stderr.c
+#include <stderr.h>
+EOF
+ backdate stderr.h
+
+ ##################################################################
+ # CCACHE_BASEDIR="" and using absolute include path will result in a cache
+ # miss.
+ testname="empty CCACHE_BASEDIR"
+ $CCACHE -z >/dev/null
+
+ cd dir1
+ CCACHE_BASEDIR="" $CCACHE $COMPILER -I`pwd`/include -c src/test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ cd ..
+
+ cd dir2
+ CCACHE_BASEDIR="" $CCACHE $COMPILER -I`pwd`/include -c src/test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 2
+ cd ..
+
+ ##################################################################
+ # Setting CCACHE_BASEDIR will result in a cache hit because include paths
+ # in the preprocessed output are rewritten.
+ testname="set CCACHE_BASEDIR"
+ $CCACHE -z >/dev/null
+ $CCACHE -C >/dev/null
+
+ cd dir1
+ CCACHE_BASEDIR="`pwd`" $CCACHE $COMPILER -I`pwd`/include -c src/test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ cd ..
+
+ cd dir2
+ # The space after -I is there to test an extra code path.
+ CCACHE_BASEDIR="`pwd`" $CCACHE $COMPILER -I `pwd`/include -c src/test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+ cd ..
+
+ ##################################################################
+ # Setting CCACHE_BASEDIR will result in a cache hit because -I arguments
+ # are rewritten, as are the paths stored in the manifest.
+ testname="set CCACHE_BASEDIR, direct lookup"
+ $CCACHE -z >/dev/null
+ $CCACHE -C >/dev/null
+ unset CCACHE_NODIRECT
+
+ cd dir1
+ CCACHE_BASEDIR="`pwd`" $CCACHE $COMPILER -I`pwd`/include -c src/test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ cd ..
+
+ cd dir2
+ CCACHE_BASEDIR="`pwd`" $CCACHE $COMPILER -I`pwd`/include -c src/test.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ cd ..
+
+ ##################################################################
+ # CCACHE_BASEDIR="" is the default.
+ testname="default CCACHE_BASEDIR"
+ cd dir1
+ $CCACHE -z >/dev/null
+ $CCACHE $COMPILER -I`pwd`/include -c src/test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ cd ..
+
+ ##################################################################
+ # Rewriting triggered by CCACHE_BASEDIR should handle paths with multiple
+ # slashes correctly.
+ testname="path normalization"
+ cd dir1
+ $CCACHE -z >/dev/null
+ CCACHE_BASEDIR=`pwd` $CCACHE $COMPILER -I`pwd`//include -c `pwd`//src/test.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 0
+ cd ..
+
+ ##################################################################
+ # Check that rewriting triggered by CCACHE_BASEDIR also affects stderr.
+ testname="stderr"
+ $CCACHE -z >/dev/null
+ CCACHE_BASEDIR=`pwd` $CCACHE $COMPILER -Wall -W -I`pwd` -c `pwd`/stderr.c -o `pwd`/stderr.o 2>stderr.txt
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ if grep `pwd` stderr.txt >/dev/null 2>&1; then
+ test_failed "Base dir (`pwd`) found in stderr:\n`cat stderr.txt`"
+ fi
+
+ CCACHE_BASEDIR=`pwd` $CCACHE $COMPILER -Wall -W -I`pwd` -c `pwd`/stderr.c -o `pwd`/stderr.o 2>stderr.txt
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ if grep `pwd` stderr.txt >/dev/null 2>&1; then
+ test_failed "Base dir (`pwd`) found in stderr:\n`cat stderr.txt`"
+ fi
+}
+
+compression_suite() {
+ ##################################################################
+ # Create some code to compile.
+ cat <<EOF >test.c
+int test;
+EOF
+
+ ##################################################################
+ # Check that compressed and uncompressed files get the same hash sum.
+ testname="compression hash sum"
+ CCACHE_COMPRESS=1 $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ CCACHE_COMPRESS=1 $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+
+ $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 2
+ checkstat 'cache miss' 1
+}
+
+readonly_suite() {
+ ##################################################################
+ # Create some code to compile.
+ echo "int test;" >test.c
+ echo "int test2;" >test2.c
+
+ # Cache a compilation.
+ $CCACHE $COMPILER -c test.c -o test.o
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ # Make the cache readonly
+ # Check that readonly mode finds the result.
+ testname="cache hit"
+ rm -f test.o
+ chmod -R a-w $CCACHE_DIR
+ CCACHE_READONLY=1 CCACHE_TEMPDIR=/tmp CCACHE_PREFIX=false $CCACHE $COMPILER -c test.c -o test.o
+ status=$?
+ chmod -R a+w $CCACHE_DIR
+ if [ $status -ne 0 ]; then
+ test_failed "failure when compiling test.c readonly"
+ fi
+ if [ ! -f test.o ]; then
+ test_failed "test.o missing"
+ fi
+
+ # Check that readonly mode doesn't try to store new results.
+ testname="cache miss"
+ files_before=`find $CCACHE_DIR -type f | wc -l`
+ CCACHE_READONLY=1 CCACHE_TEMPDIR=/tmp $CCACHE $COMPILER -c test2.c -o test2.o
+ if [ $? -ne 0 ]; then
+ test_failed "failure when compiling test2.c readonly"
+ fi
+ if [ ! -f test2.o ]; then
+ test_failed "test2.o missing"
+ fi
+ files_after=`find $CCACHE_DIR -type f | wc -l`
+ if [ $files_before -ne $files_after ]; then
+ test_failed "readonly mode stored files in the cache"
+ fi
+
+ # Check that readonly mode and direct mode works.
+ unset CCACHE_NODIRECT
+ files_before=`find $CCACHE_DIR -type f | wc -l`
+ CCACHE_READONLY=1 CCACHE_TEMPDIR=/tmp $CCACHE $COMPILER -c test.c -o test.o
+ CCACHE_NODIRECT=1
+ export CCACHE_NODIRECT
+ if [ $? -ne 0 ]; then
+ test_failed "failure when compiling test2.c readonly"
+ fi
+ files_after=`find $CCACHE_DIR -type f | wc -l`
+ if [ $files_before -ne $files_after ]; then
+ test_failed "readonly mode + direct mode stored files in the cache"
+ fi
+
+ ##################################################################
+}
+
+extrafiles_suite() {
+ ##################################################################
+ # Create some code to compile.
+ cat <<EOF >test.c
+int test;
+EOF
+ echo a >a
+ echo b >b
+
+ ##################################################################
+ # Test the CCACHE_EXTRAFILES feature.
+
+ testname="cache hit"
+ $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ testname="cache miss"
+ $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+
+ testname="cache miss a b"
+ CCACHE_EXTRAFILES="a${PATH_DELIM}b" $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 2
+
+ testname="cache hit a b"
+ CCACHE_EXTRAFILES="a${PATH_DELIM}b" $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (preprocessed)' 2
+ checkstat 'cache miss' 2
+
+ testname="cache miss a b2"
+ echo b2 >b
+ CCACHE_EXTRAFILES="a${PATH_DELIM}b" $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (preprocessed)' 2
+ checkstat 'cache miss' 3
+
+ testname="cache hit a b2"
+ CCACHE_EXTRAFILES="a${PATH_DELIM}b" $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (preprocessed)' 3
+ checkstat 'cache miss' 3
+
+ testname="cache miss doesntexist"
+ CCACHE_EXTRAFILES="doesntexist" $CCACHE $COMPILER -c test.c
+ checkstat 'cache hit (preprocessed)' 3
+ checkstat 'cache miss' 3
+ checkstat 'error hashing extra file' 1
+}
+
+prepare_cleanup_test() {
+ dir=$1
+ rm -rf $dir
+ mkdir -p $dir
+ i=0
+ while [ $i -lt 10 ]; do
+ perl -e 'print "A" x 4017' >$dir/result$i-4017.o
+ touch $dir/result$i-4017.stderr
+ touch $dir/result$i-4017.d
+ if [ $i -gt 5 ]; then
+ backdate $dir/result$i-4017.stderr
+ fi
+ i=`expr $i + 1`
+ done
+ # NUMFILES: 30, TOTALSIZE: 40 KiB, MAXFILES: 0, MAXSIZE: 0
+ echo "0 0 0 0 0 0 0 0 0 0 0 30 40 0 0" >$dir/stats
+}
+
+cleanup_suite() {
+ testname="clear"
+ prepare_cleanup_test $CCACHE_DIR/a
+ $CCACHE -C >/dev/null
+ checkfilecount 0 '*.o' $CCACHE_DIR
+ checkfilecount 0 '*.d' $CCACHE_DIR
+ checkfilecount 0 '*.stderr' $CCACHE_DIR
+ checkstat 'files in cache' 0
+
+ testname="forced cleanup, no limits"
+ $CCACHE -C >/dev/null
+ prepare_cleanup_test $CCACHE_DIR/a
+ $CCACHE -F 0 -M 0 >/dev/null
+ $CCACHE -c >/dev/null
+ checkfilecount 10 '*.o' $CCACHE_DIR
+ checkfilecount 10 '*.d' $CCACHE_DIR
+ checkfilecount 10 '*.stderr' $CCACHE_DIR
+ checkstat 'files in cache' 30
+
+ testname="forced cleanup, file limit"
+ $CCACHE -C >/dev/null
+ prepare_cleanup_test $CCACHE_DIR/a
+ # (9/10) * 30 * 16 = 432
+ $CCACHE -F 432 -M 0 >/dev/null
+ $CCACHE -c >/dev/null
+ # floor(0.8 * 9) = 7
+ checkfilecount 7 '*.o' $CCACHE_DIR
+ checkfilecount 7 '*.d' $CCACHE_DIR
+ checkfilecount 7 '*.stderr' $CCACHE_DIR
+ checkstat 'files in cache' 21
+ for i in 0 1 2 3 4 5 9; do
+ file=$CCACHE_DIR/a/result$i-4017.o
+ if [ ! -f $file ]; then
+ test_failed "File $file removed when it shouldn't"
+ fi
+ done
+ for i in 6 7 8; do
+ file=$CCACHE_DIR/a/result$i-4017.o
+ if [ -f $file ]; then
+ test_failed "File $file not removed when it should"
+ fi
+ done
+
+ testname="forced cleanup, size limit"
+ $CCACHE -C >/dev/null
+ prepare_cleanup_test $CCACHE_DIR/a
+ # (4/10) * 10 * 4 * 16 = 256
+ $CCACHE -F 0 -M 256K >/dev/null
+ $CCACHE -c >/dev/null
+ # floor(0.8 * 4) = 3
+ checkfilecount 3 '*.o' $CCACHE_DIR
+ checkfilecount 3 '*.d' $CCACHE_DIR
+ checkfilecount 3 '*.stderr' $CCACHE_DIR
+ checkstat 'files in cache' 9
+ for i in 3 4 5; do
+ file=$CCACHE_DIR/a/result$i-4017.o
+ if [ ! -f $file ]; then
+ test_failed "File $file removed when it shouldn't"
+ fi
+ done
+ for i in 0 1 2 6 7 8 9; do
+ file=$CCACHE_DIR/a/result$i-4017.o
+ if [ -f $file ]; then
+ test_failed "File $file not removed when it should"
+ fi
+ done
+
+ testname="autocleanup"
+ $CCACHE -C >/dev/null
+ for x in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
+ prepare_cleanup_test $CCACHE_DIR/$x
+ done
+ # (9/10) * 30 * 16 = 432
+ $CCACHE -F 432 -M 0 >/dev/null
+ touch empty.c
+ checkfilecount 160 '*.o' $CCACHE_DIR
+ checkfilecount 160 '*.d' $CCACHE_DIR
+ checkfilecount 160 '*.stderr' $CCACHE_DIR
+ checkstat 'files in cache' 480
+ $CCACHE $COMPILER -c empty.c -o empty.o
+ # floor(0.8 * 9) = 7
+ checkfilecount 157 '*.o' $CCACHE_DIR
+ checkfilecount 156 '*.d' $CCACHE_DIR
+ checkfilecount 156 '*.stderr' $CCACHE_DIR
+ checkstat 'files in cache' 469
+
+ testname="sibling cleanup"
+ $CCACHE -C >/dev/null
+ prepare_cleanup_test $CCACHE_DIR/a
+ # (9/10) * 30 * 16 = 432
+ $CCACHE -F 432 -M 0 >/dev/null
+ backdate $CCACHE_DIR/a/result2-4017.stderr
+ $CCACHE -c >/dev/null
+ # floor(0.8 * 9) = 7
+ checkfilecount 7 '*.o' $CCACHE_DIR
+ checkfilecount 7 '*.d' $CCACHE_DIR
+ checkfilecount 7 '*.stderr' $CCACHE_DIR
+ checkstat 'files in cache' 21
+ for i in 0 1 3 4 5 8 9; do
+ file=$CCACHE_DIR/a/result$i-4017.o
+ if [ ! -f $file ]; then
+ test_failed "File $file removed when it shouldn't"
+ fi
+ done
+ for i in 2 6 7; do
+ file=$CCACHE_DIR/a/result$i-4017.o
+ if [ -f $file ]; then
+ test_failed "File $file not removed when it should"
+ fi
+ done
+
+ testname="new unknown file"
+ $CCACHE -C >/dev/null
+ prepare_cleanup_test $CCACHE_DIR/a
+ touch $CCACHE_DIR/a/abcd.unknown
+ $CCACHE -c >/dev/null # update counters
+ checkstat 'files in cache' 31
+ # (9/10) * 30 * 16 = 432
+ $CCACHE -F 432 -M 0 >/dev/null
+ $CCACHE -c >/dev/null
+ if [ ! -f $CCACHE_DIR/a/abcd.unknown ]; then
+ test_failed "$CCACHE_DIR/a/abcd.unknown removed"
+ fi
+ checkstat 'files in cache' 19
+
+ testname="old unknown file"
+ $CCACHE -C >/dev/null
+ prepare_cleanup_test $CCACHE_DIR/a
+ # (9/10) * 30 * 16 = 432
+ $CCACHE -F 432 -M 0 >/dev/null
+ touch $CCACHE_DIR/a/abcd.unknown
+ backdate $CCACHE_DIR/a/abcd.unknown
+ $CCACHE -c >/dev/null
+ if [ -f $CCACHE_DIR/a/abcd.unknown ]; then
+ test_failed "$CCACHE_DIR/a/abcd.unknown not removed"
+ fi
+
+ testname="cleanup of tmp files"
+ $CCACHE -C >/dev/null
+ touch $CCACHE_DIR/a/abcd.tmp.efgh
+ $CCACHE -c >/dev/null # update counters
+ checkstat 'files in cache' 1
+ backdate $CCACHE_DIR/a/abcd.tmp.efgh
+ $CCACHE -c >/dev/null
+ if [ -f $CCACHE_DIR/a/abcd.tmp.efgh ]; then
+ test_failed "$CCACHE_DIR/a/abcd.tmp.unknown not removed"
+ fi
+ checkstat 'files in cache' 0
+
+ testname="ignore .nfs* files"
+ prepare_cleanup_test $CCACHE_DIR/a
+ touch $CCACHE_DIR/a/.nfs0123456789
+ $CCACHE -F 0 -M 0 >/dev/null
+ $CCACHE -c >/dev/null
+ checkfilecount 1 '.nfs*' $CCACHE_DIR
+ checkstat 'files in cache' 30
+}
+
+pch_suite() {
+ unset CCACHE_NODIRECT
+
+ cat <<EOF >pch.c
+#include "pch.h"
+int main()
+{
+ void *p = NULL;
+ return 0;
+}
+EOF
+ cat <<EOF >pch.h
+#include <stdlib.h>
+EOF
+ cat <<EOF >pch2.c
+int main()
+{
+ void *p = NULL;
+ return 0;
+}
+EOF
+
+ if $COMPILER -fpch-preprocess pch.h 2>/dev/null && [ -f pch.h.gch ] && $COMPILER pch.c -o pch; then
+ :
+ else
+ echo "Compiler (`$COMPILER --version | head -1`) doesn't support precompiled headers -- not running pch test"
+ return
+ fi
+
+ ##################################################################
+ # Tests for creating a .gch.
+
+ backdate pch.h
+
+ testname="create .gch, -c, no -o"
+ $CCACHE -zC >/dev/null
+ $CCACHE $COMPILER -c pch.h
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ rm -f pch.h.gch
+ $CCACHE $COMPILER -c pch.h
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ if [ ! -f pch.h.gch ]; then
+ test_failed "pch.h.gch missing"
+ fi
+
+ testname="create .gch, no -c, -o"
+ $CCACHE -z >/dev/null
+ $CCACHE $COMPILER pch.h -o pch.gch
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ $CCACHE $COMPILER pch.h -o pch.gch
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ if [ ! -f pch.gch ]; then
+ test_failed "pch.gch missing"
+ fi
+
+ ##################################################################
+ # Tests for using a .gch.
+
+ rm -f pch.h
+ backdate pch.h.gch
+
+ testname="no -fpch-preprocess, #include"
+ $CCACHE -Cz >/dev/null
+ $CCACHE $COMPILER -c pch.c 2>/dev/null
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 0
+ # Preprocessor error because GCC can't find the real include file when
+ # trying to preprocess:
+ checkstat 'preprocessor error' 1
+
+ testname="no -fpch-preprocess, -include, no sloppy time macros"
+ $CCACHE -Cz >/dev/null
+ $CCACHE $COMPILER -c -include pch.h pch2.c 2>/dev/null
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 0
+ # Must enable sloppy time macros:
+ checkstat "can't use precompiled header" 1
+
+ testname="no -fpch-preprocess, -include"
+ $CCACHE -Cz >/dev/null
+ CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -include pch.h pch2.c 2>/dev/null
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -include pch.h pch2.c 2>/dev/null
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ testname="-fpch-preprocess, #include, no sloppy time macros"
+ $CCACHE -Cz >/dev/null
+ $CCACHE $COMPILER -c -fpch-preprocess pch.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ # Must enable sloppy time macros:
+ checkstat "can't use precompiled header" 1
+
+ testname="-fpch-preprocess, #include, sloppy time macros"
+ $CCACHE -Cz >/dev/null
+ CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -fpch-preprocess pch.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -fpch-preprocess pch.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+
+ testname="-fpch-preprocess, #include, file changed"
+ echo "updated" >>pch.h.gch # GCC seems to cope with this...
+ backdate pch.h.gch
+ CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -fpch-preprocess pch.c
+ checkstat 'cache hit (direct)' 1
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 2
+
+ testname="preprocessor mode"
+ $CCACHE -Cz >/dev/null
+ CCACHE_NODIRECT=1 CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -fpch-preprocess pch.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 0
+ checkstat 'cache miss' 1
+ CCACHE_NODIRECT=1 CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -fpch-preprocess pch.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 1
+
+ testname="preprocessor mode, file changed"
+ echo "updated" >>pch.h.gch # GCC seems to cope with this...
+ backdate pch.h.gch
+ CCACHE_NODIRECT=1 CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -fpch-preprocess pch.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 1
+ checkstat 'cache miss' 2
+ CCACHE_NODIRECT=1 CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -fpch-preprocess pch.c
+ checkstat 'cache hit (direct)' 0
+ checkstat 'cache hit (preprocessed)' 2
+ checkstat 'cache miss' 2
+}
+
+######################################################################
+# main program
+
+suites="$*"
+if [ -n "$CC" ]; then
+ COMPILER="$CC"
+else
+ COMPILER=gcc
+fi
+if [ -z "$CCACHE" ]; then
+ CCACHE=`pwd`/ccache
+fi
+
+compiler_version="`$COMPILER --version 2>&1 | head -1`"
+case $compiler_version in
+ *gcc*|2.95*)
+ ;;
+ *)
+ echo "WARNING: Compiler $COMPILER not supported (version: $compiler_version) -- not running tests" >&2
+ exit 0
+ ;;
+esac
+
+TESTDIR=testdir.$$
+rm -rf $TESTDIR
+mkdir $TESTDIR
+cd $TESTDIR || exit 1
+
+CCACHE_DIR=`pwd`/.ccache
+export CCACHE_DIR
+CCACHE_LOGFILE=`pwd`/ccache.log
+export CCACHE_LOGFILE
+
+# ---------------------------------------
+
+all_suites="
+base
+link !win32
+hardlink
+cpp2
+nlevels4
+nlevels1
+basedir !win32
+direct
+compression
+readonly
+extrafiles
+cleanup
+pch
+"
+
+host_os="`uname -s`"
+case $host_os in
+ *MINGW*|*mingw*)
+ export CCACHE_DETECT_SHEBANG
+ CCACHE_DETECT_SHEBANG=1
+ DEVNULL=NUL
+ PATH_DELIM=";"
+ all_suites="`echo "$all_suites" | grep -v '!win32'`"
+ ;;
+ *)
+ DEVNULL=/dev/null
+ PATH_DELIM=":"
+ all_suites="`echo "$all_suites" | cut -d' ' -f1`"
+ ;;
+esac
+
+if [ -z "$suites" ]; then
+ suites="$all_suites"
+fi
+
+for suite in $suites; do
+ run_suite $suite
+done
+
+# ---------------------------------------
+
+cd ..
+rm -rf $TESTDIR
+echo test done - OK
+exit 0