Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am	(revision 1bb2488f0c626690cd402a7004cd0df0db3e31d2)
+++ tests/Makefile.am	(revision 2b10f958db325dea85128cd85f1c1c9c8a596962)
@@ -48,6 +48,6 @@
 
 avl_test_SOURCES = avltree/avl_test.cfa avltree/avl0.cfa avltree/avl1.cfa avltree/avl2.cfa avltree/avl3.cfa avltree/avl4.cfa avltree/avl-private.cfa
-# automake doesn't know we still need C rules so pretend like we have a C program
-_dummy_hack_SOURCES = .dummy_hack.c
+# automake doesn't know we still need C/CPP rules so pretend like we have a C program
+_dummy_hack_SOURCES = .dummy_hack.c .dummy_hackxx.cpp
 
 #----------------------------------------------------------------------------------------------------------------
@@ -74,4 +74,7 @@
 	@echo "int main() { return 0; }" > ${@}
 
+.dummy_hackxx.cpp:
+	@echo "int bar() { return 0; }" > ${@}
+
 concurrency :
 	@+${TEST_PY} --debug=${debug}  --install=${installed} -Iconcurrent
@@ -82,4 +85,7 @@
 % : %.cfa $(CFACC)
 	$(PRETTY_PATH) $(CFACOMPILE) $(shell realpath --relative-to=${srcdir} ${<}) -o $(abspath ${@})
+
+% : %.cpp
+	$(PRETTY_PATH) $(CXXCOMPILE) $(shell realpath --relative-to=${srcdir} ${<}) -o $(abspath ${@})
 
 declarationSpecifier: declarationSpecifier.cfa $(CFACC)
Index: tests/Makefile.in
===================================================================
--- tests/Makefile.in	(revision 1bb2488f0c626690cd402a7004cd0df0db3e31d2)
+++ tests/Makefile.in	(revision 2b10f958db325dea85128cd85f1c1c9c8a596962)
@@ -107,5 +107,5 @@
 CONFIG_CLEAN_FILES = config.py
 CONFIG_CLEAN_VPATH_FILES = test.py
-am__dummy_hack_OBJECTS = .dummy_hack.$(OBJEXT)
+am__dummy_hack_OBJECTS = .dummy_hack.$(OBJEXT) .dummy_hackxx.$(OBJEXT)
 _dummy_hack_OBJECTS = $(am__dummy_hack_OBJECTS)
 _dummy_hack_LDADD = $(LDADD)
@@ -155,4 +155,22 @@
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo "  CXX     " $@;
+am__v_CXX_1 = 
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo "  CXXLD   " $@;
+am__v_CXXLD_1 = 
 SOURCES = $(_dummy_hack_SOURCES) $(avl_test_SOURCES)
 DIST_SOURCES = $(_dummy_hack_SOURCES) $(avl_test_SOURCES)
@@ -368,10 +386,10 @@
 PRETTY_PATH = cd ${srcdir} &&
 avl_test_SOURCES = avltree/avl_test.cfa avltree/avl0.cfa avltree/avl1.cfa avltree/avl2.cfa avltree/avl3.cfa avltree/avl4.cfa avltree/avl-private.cfa
-# automake doesn't know we still need C rules so pretend like we have a C program
-_dummy_hack_SOURCES = .dummy_hack.c
+# automake doesn't know we still need C/CPP rules so pretend like we have a C program
+_dummy_hack_SOURCES = .dummy_hack.c .dummy_hackxx.cpp
 all: all-am
 
 .SUFFIXES:
-.SUFFIXES: .c .cfa .dummy_hack .lo .o .obj .validate
+.SUFFIXES: .c .cfa .cpp .dummy_hack .dummy_hackxx .lo .o .obj .validate
 $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am $(top_srcdir)/src/cfa.make $(am__configure_deps)
 	@for dep in $?; do \
@@ -409,5 +427,5 @@
 .dummy_hack$(EXEEXT): $(_dummy_hack_OBJECTS) $(_dummy_hack_DEPENDENCIES) $(EXTRA__dummy_hack_DEPENDENCIES) 
 	@rm -f .dummy_hack$(EXEEXT)
-	$(AM_V_CCLD)$(LINK) $(_dummy_hack_OBJECTS) $(_dummy_hack_LDADD) $(LIBS)
+	$(AM_V_CXXLD)$(CXXLINK) $(_dummy_hack_OBJECTS) $(_dummy_hack_LDADD) $(LIBS)
 avltree/$(am__dirstamp):
 	@$(MKDIR_P) avltree
@@ -443,4 +461,5 @@
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/.dummy_hack.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/.dummy_hackxx.Po@am__quote@
 
 .c.o:
@@ -467,4 +486,28 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+.cpp.o:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCXX_TRUE@	$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
 
 mostlyclean-libtool:
@@ -717,4 +760,7 @@
 	@echo "int main() { return 0; }" > ${@}
 
+.dummy_hackxx.cpp:
+	@echo "int bar() { return 0; }" > ${@}
+
 concurrency :
 	@+${TEST_PY} --debug=${debug}  --install=${installed} -Iconcurrent
@@ -726,4 +772,7 @@
 	$(PRETTY_PATH) $(CFACOMPILE) $(shell realpath --relative-to=${srcdir} ${<}) -o $(abspath ${@})
 
+% : %.cpp
+	$(PRETTY_PATH) $(CXXCOMPILE) $(shell realpath --relative-to=${srcdir} ${<}) -o $(abspath ${@})
+
 declarationSpecifier: declarationSpecifier.cfa $(CFACC)
 	$(PRETTY_PATH) $(CFACOMPILE) -CFA -XCFA -p $(shell realpath --relative-to=${srcdir} ${<}) -o $(abspath ${@})
Index: tests/pybin/tools.py
===================================================================
--- tests/pybin/tools.py	(revision 1bb2488f0c626690cd402a7004cd0df0db3e31d2)
+++ tests/pybin/tools.py	(revision 2b10f958db325dea85128cd85f1c1c9c8a596962)
@@ -37,12 +37,15 @@
 	# otherwise create a pipe and run the desired command
 	else :
-		proc = subprocess.run(
-			cmd,
-			stdout=None if print2stdout else PIPE,
-			stderr=STDOUT,
-			shell=True,
-			timeout=settings.timeout.single if timeout else None
-		)
-		return proc.returncode, proc.stdout
+		try:
+			proc = subprocess.run(
+				cmd,
+				stdout=None if print2stdout else PIPE,
+				stderr=STDOUT,
+				shell=True,
+				timeout=settings.timeout.single if timeout else None
+			)
+			return proc.returncode, proc.stdout.decode("utf-8") if proc.stdout else None
+		except subprocess.TimeoutExpired:
+			return 124, str(None)
 
 def is_ascii(fname):
Index: tests/test.py
===================================================================
--- tests/test.py	(revision 1bb2488f0c626690cd402a7004cd0df0db3e31d2)
+++ tests/test.py	(revision 2b10f958db325dea85128cd85f1c1c9c8a596962)
@@ -174,5 +174,5 @@
 
 		ret, info = core_info(exe_file)
-		error = error + info
+		error = error + info if error else info
 
 
@@ -198,5 +198,5 @@
 		out = sys.stdout
 		if error :
-			text = text + "\n" + error
+			text = text + '\n' + error
 			out = sys.stderr
 
@@ -288,9 +288,10 @@
 		settings.update_make_cmd(forceJobs, options.jobs)
 
-		print('%s (%s:%s) on %i cores' % (
-			'Regenerate tests' if settings.generating else 'Running',
+		print('%s %i tests on %i cores (%s:%s)' % (
+			'Regenerating' if settings.generating else 'Running',
+			len(tests),
+			options.jobs,
 			settings.arch.string,
-			settings.debug.string,
-			options.jobs
+			settings.debug.string
 		))
 
