]> sigrok.org Git - libsigrok.git/commitdiff
Add a testsuite for libsigrok.
authorUwe Hermann <redacted>
Thu, 7 Mar 2013 08:37:42 +0000 (09:37 +0100)
committerUwe Hermann <redacted>
Sat, 9 Mar 2013 10:55:43 +0000 (11:55 +0100)
This adds a suite of unit tests for libsigrok. It uses the 'Check'
tool/library (apt-get install check) to run the tests.

The configure tool tries to find libcheck. If it succeeds, a
"make check" will run all tests. Otherwise, none of the tests will
be built and "make check" will not run any tests.

This also means that users who don't have 'check' installed will still
be able to build and install libsigrok just fine.

HACKING
Makefile.am
README
configure.ac
tests/Makefile.am [new file with mode: 0644]
tests/check_core.c [new file with mode: 0644]
tests/check_driver_all.c [new file with mode: 0644]
tests/check_main.c [new file with mode: 0644]
tests/check_strutil.c [new file with mode: 0644]
tests/lib.c [new file with mode: 0644]
tests/lib.h [new file with mode: 0644]

diff --git a/HACKING b/HACKING
index a502a2008742e935dd33fd4191317c40fe04da5d..faac0a8c0da22a4bcf900efa8ccddb87f2703a20 100644 (file)
--- a/HACKING
+++ b/HACKING
@@ -144,6 +144,14 @@ Doxygen
    Variables that are "static" don't need to be marked like this.
 
 
+Testsuite
+---------
+
+You can run the libsigrok testsuite using:
+
+ $ make check
+
+
 Release engineering
 -------------------
 
index 4e2da389aa635846d988618a27f443bb9ec84bd4..d220857f2ac5ea99f2f327475ef8497ebffdd760 100644 (file)
@@ -22,7 +22,7 @@ ACLOCAL_AMFLAGS = -I autostuff
 
 AM_CPPFLAGS = -I$(top_srcdir)
 
-SUBDIRS = contrib hardware input output
+SUBDIRS = contrib hardware input output tests
 
 lib_LTLIBRARIES = libsigrok.la
 
diff --git a/README b/README
index 73ee69d694892c7c8f6bc678cddea45ee0542caf..f4e8472013ec9ee939b434a77d29c346bf9bc7de 100644 (file)
--- a/README
+++ b/README
@@ -40,6 +40,7 @@ Requirements
  - libftdi >= 0.16 (optional, used by some drivers)
  - libudev >= 151 (optional, used by some drivers)
  - libasound / alsa-lib >= 1.0 (optional, only used by the alsa driver)
+ - check >= 0.9.4 (optional, only needed to run unit tests)
 
 
 Building and installing
index 9c0e7ec6a3e802a5f2fdba39681d846c3f5c58a6..7621f6e586559e8b3a0a6519b4a5ecebc387807c 100644 (file)
@@ -337,6 +337,12 @@ if test "x$HW_ALSA" != xno; then
                SR_PKGLIBS="$SR_PKGLIBS alsa"])
 fi
 
+# The Check unit testing framework is optional.
+PKG_CHECK_MODULES([check], [check >= 0.9.4],
+       [have_check="yes"; CFLAGS="$CFLAGS $check_CFLAGS";
+       LIBS="$LIBS $check_LIBS"], [have_check="no"])
+AM_CONDITIONAL(HAVE_CHECK, test x"$have_check" = "xyes")
+
 # EZUSB FX2 firmware helper code is only needed for some hardware drivers.
 AM_CONDITIONAL(NEED_EZUSB, \
        test "x$LA_FX2LAFW" != xno \
@@ -418,6 +424,7 @@ AC_CONFIG_FILES([Makefile version.h hardware/Makefile
                 output/text/Makefile
                 libsigrok.pc
                 contrib/Makefile
+                tests/Makefile
                ])
 
 AC_OUTPUT
@@ -433,7 +440,7 @@ echo "Detected libraries:"
 echo
 
 # Note: This only works for libs with pkg-config integration.
-for lib in "glib-2.0" "libusb-1.0" "libzip" "libftdi" "libudev" "alsa"; do
+for lib in "glib-2.0" "libusb-1.0" "libzip" "libftdi" "libudev" "alsa" "check"; do
        if `$PKG_CONFIG --exists $lib`; then
                ver=`$PKG_CONFIG --modversion $lib`
                answer="yes ($ver)"
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644 (file)
index 0000000..6c8a860
--- /dev/null
@@ -0,0 +1,40 @@
+##
+## This file is part of the libsigrok project.
+##
+## Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
+##
+## 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 2 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+##
+
+if HAVE_CHECK
+
+TESTS = check_main
+
+check_PROGRAMS = ${TESTS}
+
+check_main_SOURCES = \
+       $(top_builddir)/libsigrok.h \
+       lib.c \
+       lib.h \
+       check_main.c \
+       check_core.c \
+       check_strutil.c \
+       check_driver_all.c
+
+check_main_CFLAGS = @check_CFLAGS@
+
+check_main_LDADD = $(top_builddir)/libsigrok.la @check_LIBS@
+
+endif
diff --git a/tests/check_core.c b/tests/check_core.c
new file mode 100644 (file)
index 0000000..8bc1d5a
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * 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 2 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <check.h>
+#include "../libsigrok.h"
+
+/*
+ * Check various basic init related things.
+ *
+ *  - Check whether an sr_init() call with a proper sr_ctx works.
+ *    If it returns != SR_OK (or segfaults) this test will fail.
+ *    The sr_init() call (among other things) also runs sanity checks on
+ *    all libsigrok hardware drivers and errors out upon issues.
+ *
+ *  - Check whether a subsequent sr_exit() with that sr_ctx works.
+ *    If it returns != SR_OK (or segfaults) this test will fail.
+ */
+START_TEST(test_init_exit)
+{
+       int ret;
+       struct sr_context *sr_ctx;
+
+       ret = sr_init(&sr_ctx);
+       fail_unless(ret == SR_OK, "sr_init() failed: %d.", ret);
+       ret = sr_exit(sr_ctx);
+       fail_unless(ret == SR_OK, "sr_exit() failed: %d.", ret);
+}
+END_TEST
+
+/*
+ * Check whether two nested sr_init() and sr_exit() calls work.
+ * The two functions have two different contexts.
+ * If any function returns != SR_OK (or segfaults) this test will fail.
+ */
+START_TEST(test_init_exit_2)
+{
+       int ret;
+       struct sr_context *sr_ctx1, *sr_ctx2;
+
+       ret = sr_init(&sr_ctx1);
+       fail_unless(ret == SR_OK, "sr_init() 1 failed: %d.", ret);
+       ret = sr_init(&sr_ctx2);
+       fail_unless(ret == SR_OK, "sr_init() 2 failed: %d.", ret);
+       ret = sr_exit(sr_ctx2);
+       fail_unless(ret == SR_OK, "sr_exit() 2 failed: %d.", ret);
+       ret = sr_exit(sr_ctx1);
+       fail_unless(ret == SR_OK, "sr_exit() 1 failed: %d.", ret);
+}
+END_TEST
+
+/*
+ * Same as above, but sr_exit() in the "wrong" order.
+ * This should work fine, it's not a bug to do this.
+ */
+START_TEST(test_init_exit_2_reverse)
+{
+       int ret;
+       struct sr_context *sr_ctx1, *sr_ctx2;
+
+       ret = sr_init(&sr_ctx1);
+       fail_unless(ret == SR_OK, "sr_init() 1 failed: %d.", ret);
+       ret = sr_init(&sr_ctx2);
+       fail_unless(ret == SR_OK, "sr_init() 2 failed: %d.", ret);
+       ret = sr_exit(sr_ctx1);
+       fail_unless(ret == SR_OK, "sr_exit() 1 failed: %d.", ret);
+       ret = sr_exit(sr_ctx2);
+       fail_unless(ret == SR_OK, "sr_exit() 2 failed: %d.", ret);
+}
+END_TEST
+
+/*
+ * Check whether three nested sr_init() and sr_exit() calls work.
+ * The three functions have three different contexts.
+ * If any function returns != SR_OK (or segfaults) this test will fail.
+ */
+START_TEST(test_init_exit_3)
+{
+       int ret;
+       struct sr_context *sr_ctx1, *sr_ctx2, *sr_ctx3;
+
+       ret = sr_init(&sr_ctx1);
+       fail_unless(ret == SR_OK, "sr_init() 1 failed: %d.", ret);
+       ret = sr_init(&sr_ctx2);
+       fail_unless(ret == SR_OK, "sr_init() 2 failed: %d.", ret);
+       ret = sr_init(&sr_ctx3);
+       fail_unless(ret == SR_OK, "sr_init() 3 failed: %d.", ret);
+       ret = sr_exit(sr_ctx3);
+       fail_unless(ret == SR_OK, "sr_exit() 3 failed: %d.", ret);
+       ret = sr_exit(sr_ctx2);
+       fail_unless(ret == SR_OK, "sr_exit() 2 failed: %d.", ret);
+       ret = sr_exit(sr_ctx1);
+       fail_unless(ret == SR_OK, "sr_exit() 1 failed: %d.", ret);
+}
+END_TEST
+
+/*
+ * Same as above, but sr_exit() in the "wrong" order.
+ * This should work fine, it's not a bug to do this.
+ */
+START_TEST(test_init_exit_3_reverse)
+{
+       int ret;
+       struct sr_context *sr_ctx1, *sr_ctx2, *sr_ctx3;
+
+       ret = sr_init(&sr_ctx1);
+       fail_unless(ret == SR_OK, "sr_init() 1 failed: %d.", ret);
+       ret = sr_init(&sr_ctx2);
+       fail_unless(ret == SR_OK, "sr_init() 2 failed: %d.", ret);
+       ret = sr_init(&sr_ctx3);
+       fail_unless(ret == SR_OK, "sr_init() 3 failed: %d.", ret);
+       ret = sr_exit(sr_ctx1);
+       fail_unless(ret == SR_OK, "sr_exit() 1 failed: %d.", ret);
+       ret = sr_exit(sr_ctx2);
+       fail_unless(ret == SR_OK, "sr_exit() 2 failed: %d.", ret);
+       ret = sr_exit(sr_ctx3);
+       fail_unless(ret == SR_OK, "sr_exit() 3 failed: %d.", ret);
+}
+END_TEST
+
+/* Check whether sr_init(NULL) fails as it should. */
+START_TEST(test_init_null)
+{
+       int ret;
+
+        ret = sr_log_loglevel_set(SR_LOG_NONE);
+        fail_unless(ret == SR_OK, "sr_log_loglevel_set() failed: %d.", ret);
+
+       ret = sr_init(NULL);
+       fail_unless(ret != SR_OK, "sr_init(NULL) should have failed.");
+}
+END_TEST
+
+/* Check whether sr_exit(NULL) fails as it should. */
+START_TEST(test_exit_null)
+{
+       int ret;
+
+        ret = sr_log_loglevel_set(SR_LOG_NONE);
+        fail_unless(ret == SR_OK, "sr_log_loglevel_set() failed: %d.", ret);
+
+       ret = sr_exit(NULL);
+       fail_unless(ret != SR_OK, "sr_exit(NULL) should have failed.");
+}
+END_TEST
+
+Suite *suite_core(void)
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("core");
+
+       tc = tcase_create("init_exit");
+       tcase_add_test(tc, test_init_exit);
+       tcase_add_test(tc, test_init_exit_2);
+       tcase_add_test(tc, test_init_exit_2_reverse);
+       tcase_add_test(tc, test_init_exit_3);
+       tcase_add_test(tc, test_init_exit_3_reverse);
+       tcase_add_test(tc, test_init_null);
+       tcase_add_test(tc, test_exit_null);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/tests/check_driver_all.c b/tests/check_driver_all.c
new file mode 100644 (file)
index 0000000..5da3545
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * 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 2 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <check.h>
+#include "../libsigrok.h"
+#include "lib.h"
+
+struct sr_context *sr_ctx;
+
+static void setup(void)
+{
+       int ret;
+
+       ret = sr_init(&sr_ctx);
+       fail_unless(ret == SR_OK, "sr_init() failed: %d.", ret);
+}
+
+static void teardown(void)
+{
+       int ret;
+
+       ret = sr_exit(sr_ctx);
+       fail_unless(ret == SR_OK, "sr_exit() failed: %d.", ret);
+}
+
+/* Check whether at least one driver is available. */
+START_TEST(test_driver_available)
+{
+       struct sr_dev_driver **drivers;
+
+       drivers = sr_driver_list();
+       fail_unless(drivers != NULL, "No drivers found.");
+}
+END_TEST
+
+/* Check whether initializing all drivers works. */
+START_TEST(test_driver_init_all)
+{
+       srtest_driver_init_all(sr_ctx);
+}
+END_TEST
+
+/*
+ * Check whether setting a samplerate works.
+ *
+ * Additionally, this also checks whether SR_CONF_SAMPLERATE can be both
+ * set and read back properly.
+ */
+START_TEST(test_config_get_set_samplerate)
+{
+       /*
+        * Note: This currently only works for the demo driver.
+        *       For other drivers, a scan is needed and the respective
+        *       hardware must be attached to the host running the testsuite.
+        */
+       srtest_check_samplerate(sr_ctx, "demo", SR_KHZ(19));
+}
+END_TEST
+
+Suite *suite_driver_all(void)
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("driver-all");
+
+       tc = tcase_create("config");
+       tcase_add_checked_fixture(tc, setup, teardown);
+       tcase_add_test(tc, test_driver_available);
+       tcase_add_test(tc, test_driver_init_all);
+       tcase_add_test(tc, test_config_get_set_samplerate);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/tests/check_main.c b/tests/check_main.c
new file mode 100644 (file)
index 0000000..e07a6b8
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * 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 2 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <check.h>
+#include "../libsigrok.h"
+
+Suite *suite_core(void);
+Suite *suite_strutil(void);
+Suite *suite_driver_all(void);
+
+int main(void)
+{
+       int ret;
+       Suite *s;
+       SRunner *srunner;
+
+       s = suite_create("mastersuite");
+       srunner = srunner_create(s);
+
+       /* Add all testsuites to the master suite. */
+       srunner_add_suite(srunner, suite_core());
+       srunner_add_suite(srunner, suite_strutil());
+       srunner_add_suite(srunner, suite_driver_all());
+
+       srunner_run_all(srunner, CK_VERBOSE);
+       ret = srunner_ntests_failed(srunner);
+       srunner_free(srunner);
+
+       return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/tests/check_strutil.c b/tests/check_strutil.c
new file mode 100644 (file)
index 0000000..a439d6e
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * 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 2 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <check.h>
+#include "../libsigrok.h"
+
+struct sr_context *sr_ctx;
+
+static void setup(void)
+{
+       int ret;
+
+       ret = sr_init(&sr_ctx);
+       fail_unless(ret == SR_OK, "sr_init() failed: %d.", ret);
+}
+
+static void teardown(void)
+{
+       int ret;
+
+       ret = sr_exit(sr_ctx);
+       fail_unless(ret == SR_OK, "sr_exit() failed: %d.", ret);
+}
+
+static void test_samplerate(uint64_t samplerate, const char *expected)
+{
+       char *s;
+
+       s = sr_samplerate_string(samplerate);
+       fail_unless(s != NULL);
+       fail_unless(!strcmp(s, expected),
+                   "Invalid result for '%s': %s.", expected, s);
+       g_free(s);
+}
+
+/*
+ * Check various inputs for sr_samplerate_string():
+ *
+ *  - One, two, or three digit results (e.g. 5/55/555 MHz).
+ *  - Results which contain commas (e.g. 1.234 / 12.34 / 123.4 kHz).
+ *  - Results with zeroes right after the comma (e.g. 1.034 Hz).
+ *    See also: http://sigrok.org/bugzilla/show_bug.cgi?id=73
+ *  - Results with trailing zeroes (e.g. 1.230 kHz).
+ *    (This is currently allowed, but might be changed later)
+ *  - Results with zeroes in the middle (e.g. 1.204 kHz).
+ *  - All of the above, but using SR_MHZ() and friends.
+ *    See also: http://sigrok.org/bugzilla/show_bug.cgi?id=72
+ *
+ * All of the above tests are done for the Hz/kHz/MHz/GHz ranges.
+ */
+
+START_TEST(test_hz)
+{
+       test_samplerate(0, "0 Hz");
+       test_samplerate(1, "1 Hz");
+       test_samplerate(23, "23 Hz");
+       test_samplerate(644, "644 Hz");
+       test_samplerate(604, "604 Hz");
+       test_samplerate(550, "550 Hz");
+
+       /* Again, but now using SR_HZ(). */
+       test_samplerate(SR_HZ(0), "0 Hz");
+       test_samplerate(SR_HZ(1), "1 Hz");
+       test_samplerate(SR_HZ(23), "23 Hz");
+       test_samplerate(SR_HZ(644), "644 Hz");
+       test_samplerate(SR_HZ(604), "604 Hz");
+       test_samplerate(SR_HZ(550), "550 Hz");
+}
+END_TEST
+
+START_TEST(test_khz)
+{
+       test_samplerate(1000, "1 kHz");
+       test_samplerate(99000, "99 kHz");
+       test_samplerate(225000, "225 kHz");
+       test_samplerate(1234, "1.234 kHz");
+       test_samplerate(12345, "12.345 kHz");
+       test_samplerate(123456, "123.456 kHz");
+       test_samplerate(1034, "1.034 kHz");
+       test_samplerate(1004, "1.004 kHz");
+       test_samplerate(1230, "1.230 kHz");
+
+       /* Again, but now using SR_KHZ(). */
+       test_samplerate(SR_KHZ(1), "1 kHz");
+       test_samplerate(SR_KHZ(99), "99 kHz");
+       test_samplerate(SR_KHZ(225), "225 kHz");
+       test_samplerate(SR_KHZ(1.234), "1.234 kHz");
+       test_samplerate(SR_KHZ(12.345), "12.345 kHz");
+       test_samplerate(SR_KHZ(123.456), "123.456 kHz");
+       test_samplerate(SR_KHZ(1.204), "1.204 kHz");
+       test_samplerate(SR_KHZ(1.034), "1.034 kHz");
+       test_samplerate(SR_KHZ(1.004), "1.004 kHz");
+       test_samplerate(SR_KHZ(1.230), "1.230 kHz");
+}
+END_TEST
+
+START_TEST(test_mhz)
+{
+       test_samplerate(1000000, "1 MHz");
+       test_samplerate(28000000, "28 MHz");
+       test_samplerate(775000000, "775 MHz");
+       test_samplerate(1234567, "1.234567 MHz");
+       test_samplerate(12345678, "12.345678 MHz");
+       test_samplerate(123456789, "123.456789 MHz");
+       test_samplerate(1230007, "1.230007 MHz");
+       test_samplerate(1034567, "1.034567 MHz");
+       test_samplerate(1000007, "1.000007 MHz");
+       test_samplerate(1234000, "1.234000 MHz");
+
+       /* Again, but now using SR_MHZ(). */
+       test_samplerate(SR_MHZ(1), "1 MHz");
+       test_samplerate(SR_MHZ(28), "28 MHz");
+       test_samplerate(SR_MHZ(775), "775 MHz");
+       test_samplerate(SR_MHZ(1.234567), "1.234567 MHz");
+       test_samplerate(SR_MHZ(12.345678), "12.345678 MHz");
+       test_samplerate(SR_MHZ(123.456789), "123.456789 MHz");
+       test_samplerate(SR_MHZ(1.230007), "1.230007 MHz");
+       test_samplerate(SR_MHZ(1.034567), "1.034567 MHz");
+       test_samplerate(SR_MHZ(1.000007), "1.000007 MHz");
+       test_samplerate(SR_MHZ(1.234000), "1.234000 MHz");
+}
+END_TEST
+
+START_TEST(test_ghz)
+{
+       /* Note: Numbers > 2^32 need a ULL suffix. */
+
+       test_samplerate(1000000000, "1 GHz");
+       test_samplerate(5000000000ULL, "5 GHz");
+       test_samplerate(72000000000ULL, "72 GHz");
+       test_samplerate(388000000000ULL, "388 GHz");
+       test_samplerate(4417594444ULL, "4.417594444 GHz");
+       test_samplerate(44175944444ULL, "44.175944444 GHz");
+       test_samplerate(441759444441ULL, "441.759444441 GHz");
+       test_samplerate(441759000001ULL, "441.759000001 GHz");
+       test_samplerate(441050000000ULL, "441.05 GHz");
+       test_samplerate(441000000005ULL, "441.000000005 GHz");
+       test_samplerate(441500000000ULL, "441.500000000 GHz");
+
+       /* Again, but now using SR_GHZ(). */
+       test_samplerate(SR_GHZ(1), "1 GHz");
+       test_samplerate(SR_GHZ(5), "5 GHz");
+       test_samplerate(SR_GHZ(72), "72 GHz");
+       test_samplerate(SR_GHZ(388), "388 GHz");
+       test_samplerate(SR_GHZ(4.417594444), "4.417594444 GHz");
+       test_samplerate(SR_GHZ(44.175944444), "44.175944444 GHz");
+       test_samplerate(SR_GHZ(441.759444441), "441.759444441 GHz");
+       test_samplerate(SR_GHZ(441.759000001), "441.759000001 GHz");
+       test_samplerate(SR_GHZ(441.050000000), "441.05 GHz");
+       test_samplerate(SR_GHZ(441.000000005), "441.000000005 GHz");
+       test_samplerate(SR_GHZ(441.500000000), "441.500000000 GHz");
+
+       /* Now check the biggest-possible samplerate (2^64 Hz). */
+       test_samplerate(18446744073709551615ULL, "18446744073.709551615 GHz");
+       test_samplerate(SR_GHZ(18446744073ULL), "18446744073 GHz");
+}
+END_TEST
+
+Suite *suite_strutil(void)
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("strutil");
+
+       tc = tcase_create("sr_samplerate_string");
+       tcase_add_checked_fixture(tc, setup, teardown);
+       tcase_add_test(tc, test_hz);
+       tcase_add_test(tc, test_khz);
+       tcase_add_test(tc, test_mhz);
+       tcase_add_test(tc, test_ghz);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/tests/lib.c b/tests/lib.c
new file mode 100644 (file)
index 0000000..44777bb
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * 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 2 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <check.h>
+#include "../libsigrok.h"
+
+/* Get a libsigrok driver by name. */
+struct sr_dev_driver *srtest_driver_get(const char *drivername)
+{
+       struct sr_dev_driver **drivers, *driver = NULL;
+       int i;
+
+       drivers = sr_driver_list();
+       fail_unless(drivers != NULL, "No drivers found.");
+
+       for (i = 0; drivers[i]; i++) {
+               if (strcmp(drivers[i]->name, drivername))
+                       continue;
+               driver = drivers[i];
+       }
+       fail_unless(driver != NULL, "Driver '%s' not found.", drivername);
+
+       return driver;
+}
+
+/* Initialize a libsigrok driver. */
+void srtest_driver_init(struct sr_context *sr_ctx, struct sr_dev_driver *driver)
+{
+       int ret;
+
+       ret = sr_driver_init(sr_ctx, driver);
+       fail_unless(ret == SR_OK, "Failed to init '%s' driver: %d.",
+                   driver->name, ret);
+}
+
+/* Initialize all libsigrok drivers. */
+void srtest_driver_init_all(struct sr_context *sr_ctx)
+{
+       struct sr_dev_driver **drivers, *driver;
+       int i, ret;
+
+       drivers = sr_driver_list();
+       fail_unless(drivers != NULL, "No drivers found.");
+
+       for (i = 0; drivers[i]; i++) {
+               driver = drivers[i];
+               ret = sr_driver_init(sr_ctx, driver);
+               fail_unless(ret == SR_OK, "Failed to init '%s' driver: %d.",
+                           driver->name, ret);
+       }
+}
+
+/* Set the samplerate for the respective driver to the specified value. */
+void srtest_set_samplerate(struct sr_dev_driver *driver, uint64_t samplerate)
+{
+       int ret;
+       struct sr_dev_inst *sdi;
+
+       sdi = g_slist_nth_data(driver->priv, 0);
+
+       ret = driver->config_set(SR_CONF_SAMPLERATE, &samplerate, sdi);
+       fail_unless(ret == SR_OK, "%s: Failed to set SR_CONF_SAMPLERATE: %d.",
+                   driver->name, ret);
+}
+
+/* Get the respective driver's current samplerate. */
+uint64_t srtest_get_samplerate(struct sr_dev_driver *driver)
+{
+       int ret;
+       uint64_t *samplerate;
+       struct sr_dev_inst *sdi;
+
+       sdi = g_slist_nth_data(driver->priv, 0);
+
+       ret = driver->config_get(SR_CONF_SAMPLERATE,
+                                (const void **)&samplerate, sdi);
+       fail_unless(ret == SR_OK, "%s: Failed to get SR_CONF_SAMPLERATE: %d.",
+                   driver->name, ret);
+       fail_unless(samplerate != NULL);
+
+       return *samplerate;
+}
+
+/* Check whether the respective driver can set/get the correct samplerate. */
+void srtest_check_samplerate(struct sr_context *sr_ctx, const char *drivername,
+                            uint64_t samplerate)
+{
+       struct sr_dev_driver *driver;
+       uint64_t s;
+
+       driver = srtest_driver_get(drivername);
+       srtest_driver_init(sr_ctx, driver);;
+       srtest_set_samplerate(driver, samplerate);
+       s = srtest_get_samplerate(driver);
+       fail_unless(s == samplerate, "%s: Incorrect samplerate: %" PRIu64 ".",
+                   drivername, s);
+}
diff --git a/tests/lib.h b/tests/lib.h
new file mode 100644 (file)
index 0000000..beaa0f5
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * 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 2 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#ifndef LIBSIGROK_TESTS_LIB_H
+#define LIBSIGROK_TESTS_LIB_H
+
+#include "../libsigrok.h"
+
+struct sr_dev_driver *srtest_driver_get(const char *drivername);
+void srtest_driver_init(struct sr_context *sr_ctx, struct sr_dev_driver *driver);
+void srtest_driver_init_all(struct sr_context *sr_ctx);
+void srtest_set_samplerate(struct sr_dev_driver *driver, uint64_t samplerate);
+uint64_t srtest_get_samplerate(struct sr_dev_driver *driver);
+void srtest_check_samplerate(struct sr_context *sr_ctx, const char *drivername,
+                            uint64_t samplerate);
+
+#endif