Browse Source

Merge branch 'travis' into bfgminer

Luke Dashjr 11 years ago
parent
commit
5685164f05
10 changed files with 219 additions and 0 deletions
  1. 24 0
      .travis.deps
  2. 11 0
      .travis.script
  3. 123 0
      .travis.yml
  4. 7 0
      Makefile.am
  5. 4 0
      driver-aan.c
  6. 22 0
      miner.c
  7. 1 0
      miner.h
  8. 3 0
      scrypt.c
  9. 3 0
      test-bfgminer.sh
  10. 21 0
      util.c

+ 24 - 0
.travis.deps

@@ -0,0 +1,24 @@
+test "x$1" = "xI-am-okay-with-destroying-my-system" || exit 1
+set -ex
+
+# Upgrading GCC triggers locale rebuild, so just do the one in use
+sudo rm /var/lib/locales/supported.d/*
+echo $LANG UTF-8 | sudo tee /var/lib/locales/supported.d/en
+
+echo -e 'deb http://ftp.us.debian.org/debian/ wheezy main\ndeb http://security.debian.org/ wheezy/updates main' | sudo tee '/etc/apt/sources.list'
+sudo rm -r /etc/apt/sources.list.d
+curl https://ftp-master.debian.org/keys/archive-key-7.0.asc | sudo apt-key add -
+sudo apt-get update -qq
+sudo apt-get install -y build-essential autoconf automake libtool libcurl4-gnutls-dev libjansson-dev uthash-dev $EXTRA_DEPS
+
+if [ -n "$UBUNTU_DEPS" ]; then
+	cat <<\EOF | sudo tee '/etc/apt/sources.list'
+deb http://gb.archive.ubuntu.com/ubuntu/ trusty main restricted universe
+deb http://gb.archive.ubuntu.com/ubuntu/ trusty-updates main restricted universe
+deb http://gb.archive.ubuntu.com/ubuntu/ trusty-backports main restricted universe
+deb http://security.ubuntu.com/ubuntu trusty-security main restricted universe
+EOF
+	sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 3B4FE6ACC0B21F32
+	sudo apt-get update -qq
+	sudo apt-get install -y $UBUNTU_DEPS
+fi

+ 11 - 0
.travis.script

@@ -0,0 +1,11 @@
+test "x$1" = "xI-am-okay-with-destroying-my-system" || exit 1
+set -ex
+
+export CC=$(which "$myCC")
+$CC --version
+
+./autogen.sh
+./configure $GLOBAL_CONFIGURE_ARGS $CONFIGURE_ARGS
+make CFLAGS="$GLOBAL_CFLAGS $BUILD_CFLAGS" $MAKEOPTS
+make check
+sudo make install

+ 123 - 0
.travis.yml

@@ -0,0 +1,123 @@
+os: linux
+language: c
+env:
+  global:
+    - MAKEOPTS=-j3
+    - GLOBAL_CFLAGS='-O2 -Wall'
+    - GLOBAL_CONFIGURE_ARGS='--prefix=/usr'
+matrix:
+  fast_finish: true
+  include:
+    - compiler: ": Full GCC"
+      # Upgrade GCC to avoid false warnings; build the full project with -Werror
+      env: myCC='gcc' UBUNTU_DEPS='gcc libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' BUILD_CFLAGS='-Werror' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-system-libbase58 --enable-tool'
+    - compiler: ": Full LLVM"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' BUILD_CFLAGS='-Werror' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-system-libbase58 --enable-tool'
+    - compiler: ": pkgconf"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev pkgconf' EXTRA_DEPS='libncursesw5-dev libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' BUILD_CFLAGS='-Werror' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-system-libbase58 --enable-tool'
+    - compiler: ": Std SHA2"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' CONFIGURE_ARGS=''
+    - compiler: ": Std scrypt"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' CONFIGURE_ARGS='--enable-scrypt'
+    - compiler: ": No hidapi"
+      env: myCC='clang' UBUNTU_DEPS='linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt'
+    - compiler: ": No VFIO"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-vfio'
+    - compiler: ": No UIO"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-uio'
+    - compiler: ": No VFIO/UIO"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-uio --without-vfio'
+    - compiler: ": Non-wide ncurses"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libncurses5-dev libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --with-curses=ncurses5'
+    - compiler: ": No curses"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-curses'
+    - compiler: ": No libudev"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-libudev'
+    - compiler: ": No libusb"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-libusb'
+    - compiler: ": No libevent"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libusb-1.0-0-dev libmicrohttpd-dev libi2c-dev yasm libsensors4-dev' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-libevent'
+    - compiler: ": No libmicrohttpd"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libusb-1.0-0-dev libevent-dev libi2c-dev yasm libsensors4-dev' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-libmicrohttpd'
+    - compiler: ": No libi2c-dev"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev yasm libsensors4-dev' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --disable-knc'
+    - compiler: ": No yasm"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev libsensors4-dev' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt'
+    - compiler: ": No libsensors"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev libudev-dev libusb-1.0-0-dev libevent-dev libmicrohttpd-dev libi2c-dev yasm' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-sensors'
+    - compiler: ": No opt deps"
+      env: myCC='clang' EXTRA_DEPS='pkg-config' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-uio --without-vfio --without-sensors --without-libmicrohttpd --without-libevent --without-libusb --without-curses --without-libudev --disable-knc'
+    - compiler: ": Only ncurses"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--enable-other-drivers --enable-scrypt --without-uio --without-vfio --without-sensors --without-libmicrohttpd --without-libevent --without-libusb --without-libudev --disable-knc'
+    - compiler: ": Only CPU"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev yasm' CONFIGURE_ARGS='--disable-other-drivers --enable-cpumining --enable-scrypt'
+    - compiler: ": Only OpenCL"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev libsensors4-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-opencl --enable-scrypt'
+    - compiler: ": OpenCL w/o ADL"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev libsensors4-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-opencl --enable-scrypt --disable-adl'
+    - compiler: ": OpenCL w/o sensors"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-opencl --enable-scrypt'
+    - compiler: ": OpenCL w/o ADL or sensors"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-opencl --enable-scrypt --disable-adl'
+    - compiler: ": Only bitforce"
+      env: myCC='clang' UBUNTU_DEPS='linux-libc-dev' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-bitforce'
+    - compiler: ": Only icarus"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-icarus'
+    - compiler: ": Only dualminer"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-icarus --enable-dualminer --enable-scrypt'
+    - compiler: ": Only zeusminer"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-icarus --enable-zeusminer --enable-scrypt'
+    - compiler: ": Only gridseed"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-gridseed --enable-scrypt'
+    - compiler: ": Only avalon"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-avalon'
+    - compiler: ": Only avalonmm"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-avalonmm'
+    - compiler: ": Only knc"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev libi2c-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-knc'
+    - compiler: ": Only modminer"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-modminer'
+    - compiler: ": Only cointerra"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev libusb-1.0-0-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-cointerra'
+    - compiler: ": Only klondike"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev libusb-1.0-0-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-klondike'
+    - compiler: ": Only x6500"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev libusb-1.0-0-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-x6500'
+    - compiler: ": Only ztex"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev libusb-1.0-0-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-ztex'
+    - compiler: ": Only bifury"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-bifury'
+    - compiler: ": Only bitfury"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-bitfury'
+    - compiler: ": Only bfsb"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-bitfury --enable-bfsb'
+    - compiler: ": Only bigpic"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-bitfury --enable-bigpic'
+    - compiler: ": Only bfx"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev libusb-1.0-0-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-bitfury --enable-bfx'
+    - compiler: ": Only drillbit"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-bitfury --enable-drillbit'
+    - compiler: ": Only twinfury"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-bitfury --enable-twinfury'
+    - compiler: ": Only littlefury"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-bitfury --enable-littlefury'
+    - compiler: ": Only nanofury"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-bitfury --enable-nanofury'
+    - compiler: ": Only hashbuster"
+      env: myCC='clang' UBUNTU_DEPS='libhidapi-dev' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-bitfury --enable-hashbuster'
+    - compiler: ": Only hashbusterusb"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev libusb-1.0-0-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-bitfury --enable-hashbusterusb'
+    - compiler: ": Only hashfast"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-hashfast'
+    - compiler: ": Only jingtian"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-jingtian'
+    - compiler: ": Only metabank"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-bitfury --enable-metabank'
+    - compiler: ": Only minergate"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-minergate'
+    - compiler: ": Only rockminer"
+      env: myCC='clang' EXTRA_DEPS='pkg-config libncursesw5-dev' CONFIGURE_ARGS='--disable-other-drivers --enable-rockminer'
+install:
+  - bash .travis.deps I-am-okay-with-destroying-my-system
+script:
+  - bash .travis.script I-am-okay-with-destroying-my-system

+ 7 - 0
Makefile.am

@@ -83,6 +83,13 @@ bfgminer_SOURCES += miner.h compat.h  \
 		   sha2.c sha2.h api.c
 EXTRA_bfgminer_DEPENDENCIES =
 
+TESTS = test-bfgminer.sh
+EXTRA_DIST += test-bfgminer.sh
+SH_LOG_COMPILER = /bin/sh
+AM_TESTS_ENVIRONMENT = PATH='$(srcdir)':"$$PATH"; export PATH;
+TESTS_ENVIRONMENT = $(AM_TESTS_ENVIRONMENT)
+TEST_EXTENSIONS = .sh
+
 .PHONY: update-version
 update-version:
 	./gen-version.sh >version.h.new

+ 4 - 0
driver-aan.c

@@ -88,7 +88,10 @@ void _test_aan_pll(const unsigned expect, const uint8_t postdiv, const uint8_t p
 	const uint16_t pll = (((postdiv << 5) | prediv) << 9) | fbdiv;
 	const unsigned got = aan_pll2freq(pll);
 	if (got != expect)
+	{
+		++unittest_failures;
 		applog(LOG_WARNING, "%s test failed for %4u(%x,%02x,%3d): got %4u", "aan_pll2freq", expect, postdiv, prediv, fbdiv, got);
+	}
 }
 
 static
@@ -98,6 +101,7 @@ void _test_aan_pll2(const unsigned freq)
 	const unsigned got = aan_pll2freq(pll);
 	if (got / 12 != freq / 12)
 	{
+		++unittest_failures;
 		const uint8_t postdiv = (pll >> 0xe);
 		const uint8_t prediv = (pll >> 9) & 0x1f;
 		const uint16_t fbdiv = pll & 0x1ff;

+ 22 - 0
miner.c

@@ -168,6 +168,7 @@ int opt_expiry = 120;
 int opt_expiry_lp = 3600;
 unsigned long long global_hashrate;
 static bool opt_unittest = false;
+unsigned unittest_failures;
 unsigned long global_quota_gcd = 1;
 time_t last_getwork;
 
@@ -760,11 +761,17 @@ invsyntax:
 
 #define TEST_CGPU_MATCH(pattern)  \
 	if (!cgpu_match(pattern, &cgpu))  \
+	{  \
+		++unittest_failures;  \
 		applog(LOG_ERR, "%s: Pattern \"%s\" should have matched!", __func__, pattern);  \
+	}  \
 // END TEST_CGPU_MATCH
 #define TEST_CGPU_NOMATCH(pattern)  \
 	if (cgpu_match(pattern, &cgpu))  \
+	{  \
+		++unittest_failures;  \
 		applog(LOG_ERR, "%s: Pattern \"%s\" should NOT have matched!", __func__, pattern);  \
+	}  \
 // END TEST_CGPU_MATCH
 static __maybe_unused
 void test_cgpu_match()
@@ -1362,10 +1369,16 @@ void _test_intrange(const char *s, const int v[2])
 {
 	int a[2];
 	if (!get_intrange(s, &a[0], &a[1]))
+	{
+		++unittest_failures;
 		applog(LOG_ERR, "Test \"%s\" failed: returned false", s);
+	}
 	for (int i = 0; i < 2; ++i)
 		if (unlikely(a[i] != v[i]))
+		{
+			++unittest_failures;
 			applog(LOG_ERR, "Test \"%s\" failed: value %d should be %d but got %d", s, i, v[i], a[i]);
+		}
 }
 #define _test_intrange(s, ...)  _test_intrange(s, (int[]){ __VA_ARGS__ })
 
@@ -1374,7 +1387,10 @@ void _test_intrange_fail(const char *s)
 {
 	int a[2];
 	if (get_intrange(s, &a[0], &a[1]))
+	{
+		++unittest_failures;
 		applog(LOG_ERR, "Test !\"%s\" failed: returned true with %d and %d", s, a[0], a[1]);
+	}
 }
 
 static
@@ -3702,6 +3718,7 @@ void test_decimal_width()
 		percentf3(testbuf2, sizeof(testbuf2), testn, 10.0);
 		width = snprintf(printbuf, sizeof(printbuf), "%10g %s %s |", testn, testbuf1, testbuf2);
 		if (unlikely((saved != -1) && (width != saved))) {
+			++unittest_failures;
 			applog(LOG_ERR, "Test width mismatch in percentf3! %d not %d at %10g", width, saved, testn);
 			applog(LOG_ERR, "%s", printbuf);
 		}
@@ -3717,6 +3734,7 @@ void test_decimal_width()
 		snprintf(printbuf, sizeof(printbuf), "%10g %s %s %s |", testn, testbuf1, testbuf2, testbuf3);
 		width = utf8_strlen(printbuf);
 		if (unlikely((saved != -1) && (width != saved))) {
+			++unittest_failures;
 			applog(LOG_ERR, "Test width mismatch in format_unit2! %d not %d at %10g", width, saved, testn);
 			applog(LOG_ERR, "%s", printbuf);
 		}
@@ -3733,6 +3751,7 @@ void test_decimal_width()
 		snprintf(printbuf, sizeof(printbuf), "%10g %s %s %s %s |", testn, testbuf1, testbuf2, testbuf3, testbuf4);
 		width = utf8_strlen(printbuf);
 		if (unlikely((saved != -1) && (width != saved))) {
+			++unittest_failures;
 			applog(LOG_ERR, "Test width mismatch in pick_unit! %d not %d at %10g", width, saved, testn);
 			applog(LOG_ERR, "%s", printbuf);
 		}
@@ -9489,6 +9508,7 @@ void _test_target(void * const funcp, const char * const funcname, const bool li
 	if (memcmp(&buf[off], &expect[off], 4))
 	{
 testfail: ;
+		++unittest_failures;
 		char hexbuf[65], expectbuf[65];
 		bin2hex(hexbuf, buf, 32);
 		bin2hex(expectbuf, expect, 32);
@@ -12706,6 +12726,8 @@ int main(int argc, char *argv[])
 #ifdef USE_JINGTIAN
 		test_aan_pll();
 #endif
+		if (unittest_failures)
+			quit(1, "Unit tests failed");
 	}
 
 #ifdef HAVE_CURSES

+ 1 - 0
miner.h

@@ -1165,6 +1165,7 @@ extern int opt_hysteresis;
 extern int opt_fail_pause;
 extern int opt_log_interval;
 extern unsigned long long global_hashrate;
+extern unsigned unittest_failures;
 extern char *current_fullhash;
 extern double current_diff;
 extern double best_diff;

+ 3 - 0
scrypt.c

@@ -436,6 +436,7 @@ void test_scrypt(void)
 		};
 		if (memcmp(expect_X, X, sizeof(expect_X)))
 		{
+			++unittest_failures;
 			bin2hex32(hex, X, 32);
 			applog(LOG_ERR, "%s: %s failed (got %s)", __func__, "PBKDF2_SHA256_80_128", hex);
 		}
@@ -452,6 +453,7 @@ void test_scrypt(void)
 		};
 		if (memcmp(expect_X, X, sizeof(expect_X)))
 		{
+			++unittest_failures;
 			bin2hex32(hex, X, 16);
 			applog(LOG_ERR, "%s; %s failed (got %s)", __func__, "salsa20_8", hex);
 		}
@@ -465,6 +467,7 @@ void test_scrypt(void)
 		};
 		if (memcmp(expect_X, X, sizeof(expect_X)))
 		{
+			++unittest_failures;
 			bin2hex32(hex, X, 8);
 			applog(LOG_ERR, "%s: %s failed (got %s)", __func__, "scrypt_1024_1_1_256_sp", hex);
 		}

+ 3 - 0
test-bfgminer.sh

@@ -0,0 +1,3 @@
+#!/bin/sh
+echo $PATH
+bfgminer --unittest --no-default-config --scan noauto -d?

+ 21 - 0
util.c

@@ -1521,16 +1521,25 @@ void _utf8_test(const char *s, const wchar_t expected, int expectedlen)
 	{
 		len = utf8_len(((uint8_t*)s)[0]);
 		if (len != expectedlen)
+		{
+			++unittest_failures;
 			applog(LOG_ERR, "UTF-8 test U+%06lX (len %d) failed: got utf8_len=>%d", (unsigned long)expected, expectedlen, len);
+		}
 		len = utf8_strlen(s);
 		if (len != (s[0] ? 1 : 0))
+		{
+			++unittest_failures;
 			applog(LOG_ERR, "UTF-8 test U+%06lX (len %d) failed: got utf8_strlen=>%d", (unsigned long)expected, expectedlen, len);
+		}
 		len = -1;
 	}
 	
 	r = utf8_decode(s, &len);
 	if (unlikely(r != expected || expectedlen != len))
+	{
+		++unittest_failures;
 		applog(LOG_ERR, "UTF-8 test U+%06lX (len %d) failed: got U+%06lX (len %d)", (unsigned long)expected, expectedlen, (unsigned long)r, len);
+	}
 }
 #define _test_intrange(s, ...)  _test_intrange(s, (int[]){ __VA_ARGS__ })
 
@@ -2127,8 +2136,11 @@ void _test_extract_domain(const char * const expect, const char * const uri)
 	size_t sz;
 	const char * const d = extract_domain(&sz, uri, strlen(uri));
 	if (sz != strlen(expect) || strncasecmp(d, expect, sz))
+	{
+		++unittest_failures;
 		applog(LOG_WARNING, "extract_domain \"%s\" test failed; got \"%.*s\" instead of \"%s\"",
 		       uri, (int)sz, d, expect);
+	}
 }
 
 static
@@ -2137,8 +2149,11 @@ void _test_get_regd_domain(const char * const expect, const char * const fqdn)
 	size_t sz;
 	const char * const d = get_registered_domain(&sz, fqdn, strlen(fqdn));
 	if (d == NULL || sz != strlen(expect) || strncasecmp(d, expect, sz))
+	{
+		++unittest_failures;
 		applog(LOG_WARNING, "get_registered_domain \"%s\" test failed; got \"%.*s\" instead of \"%s\"",
 		       fqdn, (int)sz, d, expect);
+	}
 }
 
 void test_domain_funcs()
@@ -2297,10 +2312,13 @@ void _test_uri_find_param(const char * const uri, const char * const param, cons
 		actual_offset = actual - uri;
 	int actual_invert = (expect_invert >= 0) ? (invert ? 1 : 0) : -1;
 	if (actual_offset != expect_offset || expect_invert != actual_invert)
+	{
+		++unittest_failures;
 		applog(LOG_WARNING, "%s(\"%s\", \"%s\", %s) test failed (offset: expect=%d actual=%d; invert: expect=%d actual=%d)",
 		       "uri_find_param", uri, param, (expect_invert >= 0) ? "(invert)" : "NULL",
 		       expect_offset, actual_offset,
 		       expect_invert, actual_invert);
+	}
 }
 
 static
@@ -2308,8 +2326,11 @@ void _test_uri_get_param(const char * const uri, const char * const param, const
 {
 	const bool actual = uri_get_param_bool(uri, param, defval);
 	if (actual != expect)
+	{
+		++unittest_failures;
 		applog(LOG_WARNING, "%s(\"%s\", \"%s\", %s) test failed",
 		       "uri_get_param_bool", uri, param, defval ? "true" : "false");
+	}
 }
 
 void test_uri_get_param()