diff options
author | chebizarro@gmail.com <chebizarro@gmail.com> | 2016-07-15 22:03:12 -0700 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2017-11-19 12:35:04 +0100 |
commit | 89a9daeef192194da890d41f2fd724fbca6f41ee (patch) | |
tree | 936e20e4d07083aaaf1ecc90905306fdc16e873a | |
parent | 0a6aeafc9a95d02ae7de7f10cc0c43c1c3f97074 (diff) | |
download | vala-89a9daeef192194da890d41f2fd724fbca6f41ee.tar.gz |
major revision of valadate
-rwxr-xr-x | build-aux/tap-test | 2 | ||||
-rw-r--r-- | tests/Makefile.am | 57 | ||||
-rw-r--r-- | tests/asynchronous/testcase.test | 11 | ||||
-rw-r--r-- | tests/genie/genie.gs | 18 | ||||
-rw-r--r-- | tests/valadatetests.vala | 29 | ||||
-rw-r--r-- | tests/valatests.vala | 108 | ||||
-rw-r--r-- | valadate/.gitignore | 18 | ||||
-rw-r--r-- | valadate/Makefile.am | 7 | ||||
-rw-r--r-- | valadate/assembly.vala | 2 | ||||
-rw-r--r-- | valadate/compositetest.vala | 39 | ||||
-rw-r--r-- | valadate/module.vala | 65 | ||||
-rw-r--r-- | valadate/tap.vala | 379 | ||||
-rw-r--r-- | valadate/tapresult.vala | 39 | ||||
-rw-r--r-- | valadate/test.vala | 27 | ||||
-rw-r--r-- | valadate/testcase.vala | 319 | ||||
-rw-r--r-- | valadate/testconfig.vala | 191 | ||||
-rw-r--r-- | valadate/testexplorer.vala | 76 | ||||
-rw-r--r-- | valadate/testfixture.vala | 11 | ||||
-rw-r--r-- | valadate/testresult.vala | 20 | ||||
-rw-r--r-- | valadate/testresultfactory.vala | 59 | ||||
-rw-r--r-- | valadate/testrunner.vala | 134 | ||||
-rw-r--r-- | valadate/testsuite.vala | 30 |
22 files changed, 1273 insertions, 368 deletions
diff --git a/build-aux/tap-test b/build-aux/tap-test index 481e333ec..b582791ef 100755 --- a/build-aux/tap-test +++ b/build-aux/tap-test @@ -2,4 +2,4 @@ # run a GTest in tap mode. The test binary is passed as $1 -$1 -k --tap +$1 -f tap diff --git a/tests/Makefile.am b/tests/Makefile.am index 1e8de9c7a..0bb18905d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,22 +1,61 @@ include $(top_srcdir)/Makefile.common include $(top_srcdir)/build-aux/glib-tap.mk -test_programs = valactests-0 +test_programs = valadatetests valactests@PACKAGE_SUFFIX@ -valactests_0_VALAFLAGS = \ +# Valadate tests +valadatetests_VALAFLAGS = \ --vapidir $(top_srcdir)/valadate \ --vapidir $(top_srcdir)/vapi \ --pkg valadate \ --pkg gio-2.0 \ --pkg config \ - --library valactests-0 \ + --library valadatetests \ -g \ $(NULL) -valactests_0_SOURCES = \ - valatests.vala +valadatetests_SOURCES = \ + valadatetests.vala \ + $(NULL) + +valadatetests_LDADD = \ + $(GLIB_LIBS) \ + $(GMODULE_LIBS) \ + -lgio-2.0 \ + -lm \ + $(top_srcdir)/valadate/libvaladate.la \ + $(NULL) + +valadatetests_CPPFLAGS = \ + -I$(top_srcdir)/valadate \ + $(GLIB_CPPFLAGS) \ + $(GMODULE_CPPFLAGS) \ + -fPIE \ + $(NULL) + +valadatetests_CFLAGS = \ + -I$(top_srcdir)/valadate \ + $(GLIB_CFLAGS) \ + $(GMODULE_CFLAGS) \ + -pie \ + -g \ + $(NULL) + +valactests@PACKAGE_SUFFIX@_VALAFLAGS = \ + --vapidir $(top_srcdir)/valadate \ + --vapidir $(top_srcdir)/vapi \ + --pkg valadate \ + --pkg gio-2.0 \ + --pkg config \ + --library valactests@PACKAGE_SUFFIX@ \ + -g \ + $(NULL) + +valactests@PACKAGE_SUFFIX@_SOURCES = \ + valatests.vala \ + $(NULL) -valactests_0_LDADD = \ +valactests@PACKAGE_SUFFIX@_LDADD = \ $(GLIB_LIBS) \ $(GMODULE_LIBS) \ -lgio-2.0 \ @@ -24,14 +63,14 @@ valactests_0_LDADD = \ $(top_srcdir)/valadate/libvaladate.la \ $(NULL) -valactests_0_CPPFLAGS = \ +valactests@PACKAGE_SUFFIX@_CPPFLAGS = \ -I$(top_srcdir)/valadate \ $(GLIB_CPPFLAGS) \ $(GMODULE_CPPFLAGS) \ -fPIE \ $(NULL) -valactests_0_CFLAGS = \ +valactests@PACKAGE_SUFFIX@_CFLAGS = \ -I$(top_srcdir)/valadate \ $(GLIB_CFLAGS) \ $(GMODULE_CFLAGS) \ @@ -42,7 +81,7 @@ valactests_0_CFLAGS = \ CLEANFILES += \ *.gir \ *.stamp \ - $(valactests_0_SOURCES:.vala=.c) \ + $(valactests@PACKAGE_SUFFIX@_SOURCES:.vala=.c) \ *.vapi \ rm -R .tests \ $(NULL) diff --git a/tests/asynchronous/testcase.test b/tests/asynchronous/testcase.test new file mode 100644 index 000000000..3b724869e --- /dev/null +++ b/tests/asynchronous/testcase.test @@ -0,0 +1,11 @@ +Packages: gio-2.0 +TestCase + +class TestCase : Valadate.TestCase { + + public void test_test() { + + + } + +} diff --git a/tests/genie/genie.gs b/tests/genie/genie.gs new file mode 100644 index 000000000..5ffcde27c --- /dev/null +++ b/tests/genie/genie.gs @@ -0,0 +1,18 @@ +[indent=4] +class Test : Object + delegate DelegateType (a : int) + data : int = 5 + d : DelegateType + + construct() + self.d = method + + def method (b:int) + print "%d %d", b, data + + def run (c:int) + d(c) + +init + var t = new Test() + t.run(1) diff --git a/tests/valadatetests.vala b/tests/valadatetests.vala new file mode 100644 index 000000000..693c54ec6 --- /dev/null +++ b/tests/valadatetests.vala @@ -0,0 +1,29 @@ +/* + * Valadate - Unit testing library for GObject-based libraries. + * Copyright (C) 2016 Chris Daley <chebizarro@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Chris Daley <chebizarro@gmail.com> + */ + +public class Valadate.Tests.TestFixture : Valadate.TestCase { + + public void test_testcase() { + + } + +} diff --git a/tests/valatests.vala b/tests/valatests.vala index 1e9cbae08..47edc2790 100644 --- a/tests/valatests.vala +++ b/tests/valatests.vala @@ -1,7 +1,7 @@ namespace Vala.Tests { /** - * Vala.TestFixture + * Vala.Tests.Fixture * * Searchs all of the sub directories in the current directory for * *.vala or *.test files, compiles and runs them. @@ -30,17 +30,20 @@ namespace Vala.Tests { private SubprocessLauncher launcher = new SubprocessLauncher(GLib.SubprocessFlags.STDOUT_PIPE | GLib.SubprocessFlags.STDERR_PIPE); - private const string VALAFLAGS = """--pkg gio-2.0 --pkg valadate - --main main --save-temps --disable-warnings - -X -pie -X -fPIE -X -g -X -O0 -X -pipe -X -lm + private const string VALA_FLAGS = + """--main main --save-temps --disable-warnings --pkg gio-2.0 + -X -lm -X -g -X -O0 -X -pipe -X -Wno-discarded-qualifiers -X -Wno-incompatible-pointer-types -X -Wno-deprecated-declarations -X -Werror=return-type -X -Werror=init-self -X -Werror=implicit -X -Werror=sequence-point -X -Werror=return-type -X -Werror=uninitialized -X -Werror=pointer-arith -X -Werror=int-to-pointer-cast -X -Werror=pointer-to-int-cast"""; - private const string GIRHEADER =""" - <?xml version="1.0"?> + private const string TESTCASE_FLAGS = + "--pkg valadate -X -pie -X -fPIE"; + + private const string GIRHEADER = + """<?xml version="1.0"?> <repository version="1.2" xmlns="http://www.gtk.org/introspection/core/1.0" xmlns:c="http://www.gtk.org/introspection/c/1.0" @@ -54,8 +57,9 @@ namespace Vala.Tests { c:symbol-prefixes="test"> %s </namespace> - </repository> - """; + </repository>"""; + + private const string BUGZILLA_URL = "http://bugzilla.gnome.org/"; private File testdir; private File buildir; @@ -67,7 +71,6 @@ namespace Vala.Tests { private string vapidirs; - public Fixture() { load_tests(); } @@ -88,7 +91,7 @@ namespace Vala.Tests { delete_tempdir(); tempdir.make_directory(); - vapidirs = "--vapidir %s --vapidir %s".printf(vapidir.get_path(), valadatedir.get_path()); + vapidirs = "--vapidir %s".printf(vapidir.get_path()); launcher.set_cwd(tempdir.get_path()); @@ -132,15 +135,23 @@ namespace Vala.Tests { } File testfile = directory.get_child(fname); - string testname = testfile.get_basename().substring(0,testfile.get_basename().last_index_of(".")); + string testname = testfile.get_basename().substring( + 0,testfile.get_basename().last_index_of(".")); - if(fname.has_suffix(".vala")) { - string command = "%s %s %s %s".printf(valac.get_path(), vapidirs, VALAFLAGS, testfile.get_path()); - string binary = testfile.get_basename().substring(0,testfile.get_basename().last_index_of(".")); + if(fname.has_suffix(".vala") || fname.has_suffix(".gs")) { + string binary = testfile.get_basename().substring( + 0,testfile.get_basename().last_index_of(".")); + string command = "%s %s %s --library %s -o %s %s".printf( + valac.get_path(), vapidirs, VALA_FLAGS, binary, + binary, testfile.get_path()); add_test(testname, ()=> { try { + if(binary.has_prefix("bug")) { + Test.bug_base (BUGZILLA_URL); + Test.bug(binary.substring(3)); + } run_command(command); if(tempdir.get_child(binary).query_exists()) run_command("./%s".printf(binary)); @@ -157,6 +168,10 @@ namespace Vala.Tests { add_test(testname, ()=> { try { + if(fname.has_prefix("bug")) { + Test.bug_base (BUGZILLA_URL); + Test.bug(fname.substring(3,fname.length-8)); + } parse_test(testfile); } catch (Error e) { Test.fail(); @@ -168,8 +183,9 @@ namespace Vala.Tests { private void default_callback(Subprocess process, size_t err, string buffer) { if (err > 0) { - Test.fail(); + //Test.skip(buffer); stdout.printf ("%s", buffer); + Test.fail(); process.force_exit(); } } @@ -191,7 +207,8 @@ namespace Vala.Tests { private void parse_test(File testfile) throws Error { var stream = new DataInputStream(testfile.read()); - string testname = testfile.get_basename().substring(0,testfile.get_basename().last_index_of(".")); + string testname = testfile.get_basename().substring( + 0,testfile.get_basename().last_index_of(".")); string line = stream.read_line(null); @@ -212,7 +229,7 @@ namespace Vala.Tests { var server = serverfile.create(FileCreateFlags.NONE); var server_stream = new DataOutputStream (server); - while ((line = stream.read_line (null)) != "Program: client") { } + do {} while ((line = stream.read_line (null)) != "Program: client"); while ((line = stream.read_line (null)) != "Program: server") { client_stream.put_string(line + "\n"); @@ -222,15 +239,20 @@ namespace Vala.Tests { server_stream.put_string(line + "\n"); } - string command = "%s %s %s %s %s".printf(valac.get_path(), vapidirs, packages, VALAFLAGS, clientfile.get_path()); + string command = "%s %s %s %s %s".printf( + valac.get_path(), vapidirs, packages, VALA_FLAGS, + clientfile.get_path()); run_command(command); - command = "%s %s %s %s %s".printf(valac.get_path(), vapidirs, packages, VALAFLAGS, serverfile.get_path()); + command = "%s %s %s %s %s".printf( + valac.get_path(), vapidirs, packages, VALA_FLAGS, + serverfile.get_path()); run_command(command); - string binary = serverfile.get_basename().substring(0,serverfile.get_basename().last_index_of(".")); + string binary = serverfile.get_basename().substring( + 0,serverfile.get_basename().last_index_of(".")); command = "./" + binary; @@ -270,7 +292,12 @@ namespace Vala.Tests { var girstream = girfile.create(FileCreateFlags.NONE); girstream.write(GIRHEADER.printf(gir).data); - string command = "%s %s %s --library %s %s".printf(vapigen.get_path(), vapidirs, girdirs, testname, girfile.get_path()); + string command = "%s %s %s --library %s %s".printf( + vapigen.get_path(), + vapidirs, + girdirs, + testname, + girfile.get_path()); run_command(command); @@ -292,7 +319,11 @@ namespace Vala.Tests { invalid_stream.put_string(line + "\n"); } - string command = "%s %s %s %s %s".printf(valac.get_path(), vapidirs, packages, VALAFLAGS, invalidfile.get_path()); + string command = "%s %s %s %s %s".printf( + valac.get_path(), + vapidirs, packages, + VALA_FLAGS, + invalidfile.get_path()); run_command(command, (p,e,b) => { if (e <= 0) @@ -300,9 +331,42 @@ namespace Vala.Tests { }); break; + case "TestCase": + + var testcasefile = tempdir.get_child(testname + ".vala"); + var testcase = testcasefile.create(FileCreateFlags.NONE); + var testcase_stream = new DataOutputStream (testcase); + + testcase_stream.put_string("namespace Vala.Tests {\n"); + + while ((line = stream.read_line (null)) != null) { + testcase_stream.put_string(line + "\n"); + } + + testcase_stream.put_string("\n}"); + + string command = "%s %s %s %s %s".printf( + valac.get_path(), + vapidirs, + packages, + VALA_FLAGS, + testcasefile.get_path()); + + run_command(command); + + string binary = testcasefile.get_basename().substring( + 0,testcasefile.get_basename().last_index_of(".")); + + command = "./" + binary; + + run_command(command); + + break; + default : break; } } } + } diff --git a/valadate/.gitignore b/valadate/.gitignore new file mode 100644 index 000000000..cf84fea03 --- /dev/null +++ b/valadate/.gitignore @@ -0,0 +1,18 @@ +Makefile.in +Makefile +*.o +*.lo +*.la +*.c +*.h +*.stamp +*.gir +*.vapi +.deps +.libs +*.pc +*.gcda +*.gcno +coverage +lcov.info +*~ diff --git a/valadate/Makefile.am b/valadate/Makefile.am index 829e268fb..900b64847 100644 --- a/valadate/Makefile.am +++ b/valadate/Makefile.am @@ -7,13 +7,19 @@ lib_LTLIBRARIES = \ libvaladate_la_SOURCES = \ assembly.vala \ + compositetest.vala \ module.vala \ + tap.vala \ + tapresult.vala \ test.vala \ testcase.vala \ + testconfig.vala \ testexplorer.vala \ testfixture.vala \ testresult.vala \ + testresultfactory.vala \ testrunner.vala \ + testsuite.vala \ $(NULL) libvaladate_la_VALAFLAGS = \ @@ -24,6 +30,7 @@ libvaladate_la_VALAFLAGS = \ --pkg gmodule-2.0 \ --pkg vala \ --pkg gee \ + --pkg config \ --library valadate \ --vapi valadate.vapi \ -H valadate.h \ diff --git a/valadate/assembly.vala b/valadate/assembly.vala index e68e6075f..b7f0c3dd8 100644 --- a/valadate/assembly.vala +++ b/valadate/assembly.vala @@ -1,6 +1,6 @@ /* * Valadate - Unit testing library for GObject-based libraries. - * Copyright (C) 20016 Chris Daley <chebizarro@gmail.com> + * Copyright (C) 2016 Chris Daley <chebizarro@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/valadate/compositetest.vala b/valadate/compositetest.vala new file mode 100644 index 000000000..46ada0f94 --- /dev/null +++ b/valadate/compositetest.vala @@ -0,0 +1,39 @@ +/* + * Valadate - Unit testing library for GObject-based libraries. + * Copyright (C) 2016 Chris Daley <chebizarro@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Chris Daley <chebizarro@gmail.com> + */ + +public abstract class Valadate.CompositeTest : Object, Test { + + public string name {get;set;} + + public abstract int size {get;} + + public virtual TestResult? run(TestResult? result = null) { } + + public abstract Test get(string testname); + + public abstract void set(string testname, Test test); + + public abstract bool contains(string testname); + + public virtual TestResult? run_test(string testname, TestResult? result = null) throws TestError {} + +} diff --git a/valadate/module.vala b/valadate/module.vala index a4e942197..c364c2f4f 100644 --- a/valadate/module.vala +++ b/valadate/module.vala @@ -1,6 +1,6 @@ /* * Valadate - Unit testing library for GObject-based libraries. - * Copyright (C) 20016 Chris Daley <chebizarro@gmail.com> + * Copyright (C) 2016 Chris Daley <chebizarro@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,39 +20,42 @@ * Chris Daley <chebizarro@gmail.com> */ -namespace Valadate { +public errordomain Valadate.ModuleError { + NOT_FOUND, + LOAD, + METHOD +} - public class Module : Object { - - private string lib_path; - private GLib.Module module; +/** + * Represents a loadable module containing {@link Valadate.Test}s + */ +public class Valadate.Module : Object { + + private string lib_path; + private GLib.Module module; - public Module (string libpath) { - lib_path = libpath; - } - - public void load_module() throws Error - requires(lib_path != null) - { - //if (!File.new_for_path(lib_path).query_exists()) - //throw new Error.MODULE("Module: %s does not exist", lib_path); - - module = GLib.Module.open (lib_path, ModuleFlags.BIND_LOCAL); - //if (module == null) - //throw new Error.MODULE(GLib.Module.error()); - module.make_resident(); - } - - internal void* get_method(string method_name) throws Error { - void* function; - if(module.symbol (method_name, out function)) - if (function != null) - return function; - //throw new Error.METHOD(GLib.Module.error()); - return null; - } + public Module (string libpath) { + lib_path = libpath; + } + + public void load_module() throws ModuleError + requires(lib_path != null) + { + if (!File.new_for_path(lib_path).query_exists()) + throw new ModuleError.NOT_FOUND("Module: %s does not exist", lib_path); + module = GLib.Module.open (lib_path, ModuleFlags.BIND_LOCAL); + if (module == null) + throw new ModuleError.LOAD(GLib.Module.error()); + module.make_resident(); + } + + internal void* get_method(string method_name) throws ModuleError { + void* function; + if(module.symbol (method_name, out function)) + if (function != null) + return function; + throw new ModuleError.METHOD(GLib.Module.error()); } - } diff --git a/valadate/tap.vala b/valadate/tap.vala new file mode 100644 index 000000000..30745bed5 --- /dev/null +++ b/valadate/tap.vala @@ -0,0 +1,379 @@ +/* + * Valadate - Unit testing library for GObject-based libraries. + * Ported from JTap - http://svn.solucorp.qc.ca/repos/solucorp/JTap/trunk/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +public class Valadate.Tap : Object { + + private const string version = "1.0"; + + private bool plan_set = false; + private bool no_plan = false; + private bool skip_all = false; + private bool test_died = false; + private int expected_tests = 0; + private int executed_tests = 0; + private int failed_tests = 0; + private bool _exit = true; + private string? todo = null; + + + public Tap(bool really_exit = true) { + _exit = really_exit; + GLib.set_printerr_handler (printerr_func_stack_trace); + Log.set_default_handler (log_func_stack_trace); + } + + private static void printerr_func_stack_trace (string? text) { + if (text == null || str_equal (text, "")) + return; + + stderr.printf (text); + + /* Print a stack trace since we've hit some major issue */ + GLib.on_error_stack_trace ("libtool --mode=execute gdb"); + } + + private void log_func_stack_trace ( + string? log_domain, + LogLevelFlags log_levels, + string message) { + Log.default_handler (log_domain, log_levels, message); + + /* Print a stack trace for any message at the warning level or above */ + if ((log_levels & ( + LogLevelFlags.LEVEL_WARNING | + LogLevelFlags.LEVEL_ERROR | + LogLevelFlags.LEVEL_CRITICAL)) != 0) { + GLib.on_error_stack_trace ("libtool --mode=execute gdb"); + } + } + + public int plan_no_plan() { + if (plan_set) + die("You tried to plan twice!"); + + plan_set = true; + no_plan = true; + return 1; + } + + + public int plan_skip_all(string reason) { + if (plan_set) + die("You tried to plan twice!"); + + print_plan(0, "Skip " + reason); + + skip_all = true; + plan_set = true; + + exit(0); + return 0; + } + + + public int plan_tests(int tests) { + if (plan_set) + die("You tried to plan twice!"); + + if (tests == 0) + die("You said to run 0 tests! You've got to run something."); + + print_plan(tests); + expected_tests = tests; + + plan_set = true; + + return tests; + } + + + private void print_plan(int expected_tests, string? directive = null) { + stdout.puts("1.." + expected_tests.to_string()); + if (directive != null) + stdout.puts(" # " + directive); + + stdout.puts("\n"); + stdout.flush(); + } + + public bool pass(string name) { + return ok(true, name); + } + + public bool fail(string name) { + return ok(false, name); + } + + /* + This is the workhorse method that actually + prints the tests result. + */ + public bool ok(bool result, string? name= null) { + if (!plan_set) + die("You tried to run a test without a plan! Gotta have a plan."); + + executed_tests++; + + if (!result) { + stdout.puts("not "); + failed_tests++; + } + stdout.puts("ok " + executed_tests.to_string()); + + if (name != null) { + stdout.puts(" - "); + stdout.puts(name.replace("#", "\\\\#")); + } + + if (todo != null) { + stdout.puts(" # TODO " + todo); + if (!result) + failed_tests--; + } + + stdout.puts("\n"); + stdout.flush(); + + if (!result) { + /* + string file = null; + string clas = null; + string func = null; + int line = 0; + + try { + for (int i = 0 ; i < stack.length ; i++) { + Class c = Class.forName(stack[i].getClassName()); + if (! Tap.class.isAssignableFrom(c)) { + // We are outside a Tap object, so this is probably the callpoint + file = stack[i].getFileName(); + clas = c.getName(); + func = stack[i].getMethodName(); + line = stack[i].getLineNumber(); + break; + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + + if (name != null) { + diag(" Failed " + (todo == null ? "" : "(TODO) ") + "test '" + name + "'"); + diag(" in " + file + ":" + func + "() at line " + line + "."); + } + else { + diag(" Failed " + (todo == null ? "" : "(TODO) ") + "test in " + file + ":" + func + "() at line " + line + "."); + }*/ + } + + return result; + } + + private bool equals(Value result, Value expected) { + bool r; + + if ((result.peek_pointer() == null)&&(expected.peek_pointer() == null)) + r = true; + else if ((result.peek_pointer() == null)||(expected.peek_pointer() == null)) + r = false; + else + r = (result == expected); + + return r; + } + + + private bool matches(Value result, string? pattern) { + bool r; + + if ((result.peek_pointer() == null)||(pattern == null)) + r = false; + else + r = (result.get_string() == pattern); + + return r; + } + + + private void is_diag(Value result, Value expected) { + diag(" got: '" + result.get_string() + "'"); + diag(" expected: '" + expected.get_string() + "'"); + } + + + public bool is(Value result, Value expected, string? name = null) { + bool r = ok(equals(result, expected), name); + if (!r) + is_diag(result, expected); + return r; + } + + + public bool isnt(Value result, Value expected, string? name = null) { + bool r = ok(!equals(result, expected), name); + if (! r) + is_diag(result, expected); + return r; + } + + public bool like(Value result, string pattern, string? name = null) { + bool r = ok(matches(result, pattern), name); + if (!r) + diag(" " + result.get_string() + " doesn't match '" + pattern + "'"); + return r; + } + + public bool unlike(Value result, string pattern, string? name = null) { + bool r = ok(! matches(result, pattern), name); + if (! r) + diag(" " + result.get_string() + " matches '" + pattern + "'"); + return r; + } + + public bool isa_ok(Value o, Type c, string? name = null) { + + bool r = false; + if ((o.peek_pointer() == null)||(c == Type.INVALID)) + r = false ; + else + r = ok(c.is_a(o.type()), name); + + if (!r) + diag(" Value isn't a '" + c.name() + "' it's a '" + o.type().name() + "'"); + + return r; + } + + + public void skip(string reason, int n = 1) throws TapError { + for (int i = 0 ; i < n ; i++) { + executed_tests++; + stdout.puts("ok " + executed_tests.to_string() + " # skip " + reason + "\n"); + stdout.flush(); + } + throw new TapError.SKIP(reason); + } + + + public void todo_start(string reason) { + if (reason == "") + reason = null; + todo = reason; + } + + + public void todo_end() { + todo = null; + } + + + public bool diag(string msg) { + if (msg != null) { + string[] lines = msg.split("\n"); + StringBuilder buf = new StringBuilder() ; + for (int i = 0 ; i < lines.length ; i++) + buf.append("# " + lines[i] + "\n"); + stdout.puts(buf.str); + stdout.flush(); + } + return false; + } + + + + private void die(string reason) { + stderr.puts(reason + "\n"); + test_died = true; + exit(255); + } + + + public void BAIL_OUT(string reason) { + stdout.puts("Bail out! " + reason + "\n"); + stdout.flush(); + exit(255); + } + + + private int cleanup() { + int rc = 0; + + if (! plan_set) { + diag("Looks like your test died before it could output anything."); + return rc; + } + + if (test_died) { + diag("Looks like your test died just after " + executed_tests.to_string() + "."); + return rc; + } + + if ((! skip_all)&&(no_plan)) { + print_plan(executed_tests); + } + + if ((! no_plan)&&(expected_tests < executed_tests)) { + diag("Looks like you planned " + expected_tests.to_string() + " test" + (expected_tests > 1 ? "s" : "") + " but ran " + + (executed_tests - expected_tests).to_string() + " extra."); + rc = -1; + } + + if ((! no_plan)&&(expected_tests > executed_tests)) { + diag("Looks like you planned " + expected_tests.to_string() + " test" + (expected_tests > 1 ? "s" : "") + " but only ran " + + executed_tests.to_string() + "."); + } + + if (failed_tests > 0) { + diag("Looks like you failed " + failed_tests.to_string() + " test" + (failed_tests > 1 ? "s" : "") + " of " + executed_tests.to_string() + "."); + } + + return rc; + } + + + public int exit_status() { + if ((no_plan)||(! plan_set)) + return failed_tests; + + if (expected_tests < executed_tests) + return executed_tests - expected_tests; + + return failed_tests + (expected_tests - executed_tests); + } + + + private void exit(int rc = 0) { + int alt_rc = cleanup(); + + if (alt_rc != 0) + rc = alt_rc; + + //if (_exit) + //System.exit(rc); + //else + //throw new TapError.EXIT(rc.to_string()); + } +} + +public errordomain Valadate.TapError { + EXIT, + SKIP +} diff --git a/valadate/tapresult.vala b/valadate/tapresult.vala new file mode 100644 index 000000000..6f176e431 --- /dev/null +++ b/valadate/tapresult.vala @@ -0,0 +1,39 @@ +/* + * Valadate - Unit testing library for GObject-based libraries. + * Copyright (C) 2016 Chris Daley <chebizarro@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Chris Daley <chebizarro@gmail.com> + */ + +public class Valadate.TAPResult : Object, TestResult { + + + public int error_count {get;internal set;} + public int failure_count {get;internal set;} + public int run_count {get;internal set;} + + public void add_test(Test test) {} + + public void add_error(Test test) {} + + public void add_failure(Test test) {} + + public void report() {} + + +} diff --git a/valadate/test.vala b/valadate/test.vala index e76973791..be5882aa1 100644 --- a/valadate/test.vala +++ b/valadate/test.vala @@ -1,6 +1,6 @@ /* * Valadate - Unit testing library for GObject-based libraries. - * Copyright (C) 20016 Chris Daley <chebizarro@gmail.com> + * Copyright (C) 2016 Chris Daley <chebizarro@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,23 +19,20 @@ * Authors: * Chris Daley <chebizarro@gmail.com> */ -namespace Valadate { - +/** + * The Test interface is implemented by TestCase and TestSuite. + * It is the base interface for all runnable Tests. + */ +public interface Valadate.Test : Object { /** - * The Test interface is implemented by TestCase and TestSuite. - * It is the base interface for all runnable Tests. + * Runs the Tests and collects the results in a TestResult + * + * @param result the TestResult object used to store the results of the Test */ - public interface Test : Object { - /** - * Runs the Tests and collects the results in a TestResult - * - * @param result the TestResult object used to store the results of the Test - */ - public abstract TestResult run (TestResult? result = null); - - public delegate void TestMethod (); + public abstract TestResult? run (TestResult? result = null); + public abstract string name {get;set;} - } + public delegate void TestMethod (); } diff --git a/valadate/testcase.vala b/valadate/testcase.vala index 5a8f51779..76a295dc7 100644 --- a/valadate/testcase.vala +++ b/valadate/testcase.vala @@ -24,181 +24,224 @@ * Julien Peeters <contact@julienpeeters.fr> */ -namespace Valadate { - - public delegate void AsyncBegin(AsyncReadyCallback callback); - public delegate void AsyncFinish(AsyncResult result) throws GLib.Error; +public errordomain Valadate.TestError { + NOT_FOUND +} - - public abstract class TestCase : Object, Test, TestFixture { +public abstract class Valadate.TestCase : CompositeTest, TestFixture { - public GLib.TestSuite _suite; + private HashTable<string, TestAdaptor> _tests = + new HashTable<string, TestAdaptor> (str_hash, str_equal); - public GLib.TestSuite suite { - get { - if (_suite == null) - _suite = new GLib.TestSuite (this.name); - return _suite; - } - } + public virtual void set_up() {} - public string name {get;set;} + public virtual void tear_down() {} - private Adaptor[] adaptors = new Adaptor[0]; + private class TestAdaptor : Object, Test { - private HashTable<string, Adaptor> tests = - new HashTable<string, Adaptor> (str_hash, str_equal); + public string name { get; set; } + private Test.TestMethod test; - construct { - name = this.get_type().name(); + public TestAdaptor(string name, owned Test.TestMethod test) { + this.name = name; + this.test = (owned)test; } - public void add_test (string name, owned Test.TestMethod test) - requires (name.contains("/") != true) - { - var adaptor = new Adaptor (name, (owned)test, this); - this.adaptors += adaptor; + public TestResult? run(TestResult? result = null) { + this.test(); + return result; + } - this.tests.insert(name, adaptor); + } - this.suite.add (new GLib.TestCase (adaptor.name, - adaptor.set_up, - adaptor.run, - adaptor.tear_down )); - } + public void add_test (string name, owned Test.TestMethod test) + requires (name.contains("/") != true) + { + var adaptor = new TestAdaptor (name, (owned)test); + _tests.insert(name, adaptor); + } - public void add_async_test ( - string name, - owned AsyncBegin async_begin, - owned AsyncFinish async_finish, - int timeout = 200) - { - var adaptor = new Adaptor (name, () => { }, this); - adaptor.is_async = true; - adaptor.async_begin = (owned)async_begin; - adaptor.async_finish = (owned)async_finish; - adaptor.async_timeout = timeout; - this.adaptors += adaptor; - - this.tests.insert(name, adaptor); - - this.suite.add (new GLib.TestCase ( - adaptor.name, - adaptor.set_up, - adaptor.run, - adaptor.tear_down, - sizeof(Adaptor))); - } + public virtual TestResult? run_test(string testname, TestResult? result = null) throws TestError { + if(!_tests.contains(testname)) + throw new TestError.NOT_FOUND("The Test %s was not found", testname); + + var test = _tests.get(testname); + + test.run(result); + + return result; + } - /** - * Runs the Tests and collects the results in a TestResult - * - * @param result the TestResult object used to store the results of the Test - */ - public virtual TestResult run(TestResult? result = null) { - return result; - } - public virtual TestResult run_test(Test test, TestResult? result = null) { - return result; + + + + + + + + + + + + + + public delegate void AsyncBegin(AsyncReadyCallback callback); + public delegate void AsyncFinish(AsyncResult result) throws GLib.Error; + + public GLib.TestSuite _suite; + + public GLib.TestSuite suite { + get { + if (_suite == null) + _suite = new GLib.TestSuite (this.name); + return _suite; } + } - public virtual void set_up () {} - public virtual void tear_down () {} + private Adaptor[] adaptors = new Adaptor[0]; - private class Adaptor { - [CCode (notify = false)] - public string name { get; private set; } - public int async_timeout { get; set; } - private Test.TestMethod test; - private TestCase test_case; + + construct { + name = this.get_type().name(); + } + + public void add_testb (string name, owned Test.TestMethod test) + requires (name.contains("/") != true) + { + var adaptor = new Adaptor (name, (owned)test, this); + this.adaptors += adaptor; + + //this._tests.insert(name, adaptor); + + this.suite.add (new GLib.TestCase (adaptor.name, + adaptor.set_up, + adaptor.run, + adaptor.tear_down )); + } + + + public void add_async_test ( + string name, + owned AsyncBegin async_begin, + owned AsyncFinish async_finish, + int timeout = 200) + { + var adaptor = new Adaptor (name, () => { }, this); + adaptor.is_async = true; + adaptor.async_begin = (owned)async_begin; + adaptor.async_finish = (owned)async_finish; + adaptor.async_timeout = timeout; + this.adaptors += adaptor; + + //this._tests.insert(name, adaptor); + + this.suite.add (new GLib.TestCase ( + adaptor.name, + adaptor.set_up, + adaptor.run, + adaptor.tear_down, + sizeof(Adaptor))); + + } + - public bool is_async = false; - public AsyncBegin async_begin; - public AsyncFinish async_finish; - public Adaptor (string name, - owned Test.TestMethod test, - TestCase test_case) { - this.name = name; - this.test = (owned)test; - this.test_case = test_case; - } - public void set_up (void* fixture) { - GLib.set_printerr_handler (printerr_func_stack_trace); - Log.set_default_handler (log_func_stack_trace); - this.test_case.set_up (); - } - private static void printerr_func_stack_trace (string? text) { - if (text == null || str_equal (text, "")) - return; + private class Adaptor { + [CCode (notify = false)] + public string name { get; private set; } + public int async_timeout { get; set; } - stderr.printf (text); + private Test.TestMethod test; + private TestCase test_case; - /* Print a stack trace since we've hit some major issue */ + public bool is_async = false; + public AsyncBegin async_begin; + public AsyncFinish async_finish; + + public Adaptor (string name, + owned Test.TestMethod test, + TestCase test_case) { + this.name = name; + this.test = (owned)test; + this.test_case = test_case; + } + + public void set_up (void* fixture) { + GLib.set_printerr_handler (printerr_func_stack_trace); + Log.set_default_handler (log_func_stack_trace); + this.test_case.set_up (); + } + + private static void printerr_func_stack_trace (string? text) { + if (text == null || str_equal (text, "")) + return; + + stderr.printf (text); + + /* Print a stack trace since we've hit some major issue */ + GLib.on_error_stack_trace ("libtool --mode=execute gdb"); + } + + private void log_func_stack_trace ( + string? log_domain, + LogLevelFlags log_levels, + string message) { + Log.default_handler (log_domain, log_levels, message); + + /* Print a stack trace for any message at the warning level or above */ + if ((log_levels & ( + LogLevelFlags.LEVEL_WARNING | + LogLevelFlags.LEVEL_ERROR | + LogLevelFlags.LEVEL_CRITICAL)) != 0) { GLib.on_error_stack_trace ("libtool --mode=execute gdb"); } + } - private void log_func_stack_trace ( - string? log_domain, - LogLevelFlags log_levels, - string message) { - Log.default_handler (log_domain, log_levels, message); - - /* Print a stack trace for any message at the warning level or above */ - if ((log_levels & ( - LogLevelFlags.LEVEL_WARNING | - LogLevelFlags.LEVEL_ERROR | - LogLevelFlags.LEVEL_CRITICAL)) != 0) { - GLib.on_error_stack_trace ("libtool --mode=execute gdb"); + public void run (void* fixture) { + if (this.is_async) { + try { + assert( wait_for_async (async_timeout, this.async_begin, this.async_finish) ); } - } - - public void run (void* fixture) { - if (this.is_async) { - try { - assert( wait_for_async (async_timeout, this.async_begin, this.async_finish) ); - } - catch (GLib.Error err) { - message(@"Got exception while excuting asynchronous test: $(err.message)"); - GLib.Test.fail(); - } - } else { - this.test(); + catch (GLib.Error err) { + message(@"Got exception while excuting asynchronous test: $(err.message)"); + GLib.Test.fail(); } + } else { + this.test(); } + } - public void tear_down (void* fixture) { - this.test_case.tear_down (); - } - - public bool wait_for_async(int timeout, AsyncBegin async_function, AsyncFinish async_finish) throws GLib.Error { - var loop = new MainLoop(MainContext.default(), true); - AsyncResult? result = null; - // Plan the async function - async_function((o, r) => { result = r; loop.quit(); }); - // Plan timeout - var t1 = Timeout.add(timeout, () => { loop.quit(); return false; }); - // Run the loop if it was not quit yet. - if(loop.is_running()) - loop.run(); - // Cancel timer - Source.remove(t1); - // Check the outcome - if(result == null) - return false; - async_finish(result); - return true; - } + public void tear_down (void* fixture) { + this.test_case.tear_down (); + } + + public bool wait_for_async(int timeout, AsyncBegin async_function, AsyncFinish async_finish) throws GLib.Error { + var loop = new MainLoop(MainContext.default(), true); + AsyncResult? result = null; + // Plan the async function + async_function((o, r) => { result = r; loop.quit(); }); + // Plan timeout + var t1 = Timeout.add(timeout, () => { loop.quit(); return false; }); + // Run the loop if it was not quit yet. + if(loop.is_running()) + loop.run(); + // Cancel timer + Source.remove(t1); + // Check the outcome + if(result == null) + return false; + async_finish(result); + return true; } } } diff --git a/valadate/testconfig.vala b/valadate/testconfig.vala new file mode 100644 index 000000000..ed66d3ded --- /dev/null +++ b/valadate/testconfig.vala @@ -0,0 +1,191 @@ +/* + * Valadate - Unit testing library for GObject-based libraries. + * Copyright (C) 2016 Chris Daley <chebizarro@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Chris Daley <chebizarro@gmail.com> + */ + +public class Valadate.TestConfig : Object { + + public virtual signal void set_up() {} + public virtual signal void tear_up() {} + + public static string seed; + public static string testplan; + public static string format = "tap"; + public static bool fatal_warnings; + public static bool list; + public static bool quiet; + public static bool timed; + public static bool verbose; + public static bool version; + public static bool vala_version; + + [CCode (array_length = false, array_null_terminated = true)] + public static string[] paths; + [CCode (array_length = false, array_null_terminated = true)] + public static string[] skip; + [CCode (array_length = false, array_null_terminated = true)] + public static string[] testplans; + + public string binary {get;set;} + + public TestResult result {get;set;} + + public OptionContext opt_context; + + private Vala.CodeContext context; + private Module module; + + + public const OptionEntry[] options = { + { "seed", 0, 0, OptionArg.STRING, ref seed, "Start tests with random seed", "SEEDSTRING" }, + { "format", 'f', 0, OptionArg.STRING, ref format, "Output test results using format", "FORMAT" }, + { "g-fatal-warnings", 0, 0, OptionArg.NONE, ref fatal_warnings, "Make all warnings fatal", null }, + { "list", 'l', 0, OptionArg.NONE, ref list, "List test cases available in a test executable", null }, + { "skip", 's', 0, OptionArg.STRING_ARRAY, ref skip, "Skip all tests matching", "TESTPATH..." }, + { "quiet", 'q', 0, OptionArg.NONE, ref quiet, "Run tests quietly", null }, + { "timed", 't', 0, OptionArg.NONE, ref timed, "Run timed tests", null }, + { "testplan", 0, 0, OptionArg.STRING, ref testplan, "Run the specified TestPlan", "FILE" }, + { "verbose", 0, 0, OptionArg.NONE, ref verbose, "Run tests verbosely", null }, + { "version", 0, 0, OptionArg.NONE, ref version, "Display version number", null }, + { "vala-version", 0, 0, OptionArg.NONE, ref vala_version, "Display Vala version number", null }, + { "", 0, 0, OptionArg.STRING_ARRAY, ref paths, "Only start test cases matching", "TESTPATH..." }, + { null } + }; + + + public TestConfig() { + opt_context = new OptionContext ("- Valadate Testing Framework"); + opt_context.set_help_enabled (true); + opt_context.add_main_entries (options, null); + setup_context(); + } + + private void setup_context() { + File currdir = File.new_for_path(GLib.Environment.get_current_dir()); + File valadatedir = currdir.get_parent().get_child("valadate"); + File vapidir = currdir.get_parent().get_child("vapi"); + + + context = new Vala.CodeContext (); + Vala.CodeContext.push (context); + context.report.enable_warnings = false; + context.report.set_verbose_errors (false); + context.verbose_mode = false; + + context.vapi_directories = {valadatedir.get_path(), vapidir.get_path()}; + + context.add_external_package ("glib-2.0"); + context.add_external_package ("gobject-2.0"); + context.add_external_package ("gio-2.0"); + context.add_external_package ("gmodule-2.0"); + context.add_external_package ("valadate"); + + } + + public int parse(string[] args) { + binary = args[0]; + GLib.Environment.set_prgname(binary); + + try { + opt_context.parse (ref args); + } catch (OptionError e) { + stdout.printf ("%s\n", e.message); + stdout.printf ("Run '%s --help' to see a full list of available command line options.\n", args[0]); + return 1; + } + + if (version) { + stdout.printf ("Valadate %s\n", "1.0"); + return 0; + } else if (vala_version) { + stdout.printf ("Vala %s\n", Config.PACKAGE_SUFFIX.substring (1)); + return 0; + } + + if(seed == null) + seed = "R02S%08x%08x%08x%08x".printf( + GLib.Random.next_int(), + GLib.Random.next_int(), + GLib.Random.next_int(), + GLib.Random.next_int()); + + result = TestResultFactory.get_instance().new_for_type(format); + + try { + load(); + } catch (ConfigError e) { + stdout.printf ("%s\n", e.message); + return 1; + } + + // We are just listing the tests in the binary + if(paths == null && TestConfig.list) { + result.report(); + return 0; + } + + return -1; + } + + private void load() throws ConfigError { + string testdir = Path.get_dirname(binary).replace(".libs", ""); + + string testplan = Path.get_basename(binary); + if(testplan.has_prefix("lt-")) + testplan = testplan.substring(3); + + string testplanfile = testdir + GLib.Path.DIR_SEPARATOR_S + testplan + ".vapi"; + + if (!FileUtils.test (testplanfile, FileTest.EXISTS)) + throw new ConfigError.TESTPLAN("Test Plan %s Not Found!", testplanfile); + + try { + module = new Module(binary); + module.load_module(); + load_test_plan(testplanfile); + } catch (ModuleError e) { + throw new ConfigError.MODULE(e.message); + } + } + + + internal void load_test_plan(string path) throws ConfigError { + + context.add_source_file (new Vala.SourceFile (context, Vala.SourceFileType.PACKAGE, path)); + + var parser = new Vala.Parser (); + parser.parse (context); + + context.check (); + + if (context.report.get_errors () > 0) + throw new ConfigError.TESTPLAN("Error parsing testplan %s", path); + + var testexplorer = new TestExplorer(module, result); + context.accept(testexplorer); + //_tests = testexplorer.get_tests(); + } + +} + +public errordomain Valadate.ConfigError { + MODULE, + TESTPLAN +} diff --git a/valadate/testexplorer.vala b/valadate/testexplorer.vala index 97e76a981..bb9bedd35 100644 --- a/valadate/testexplorer.vala +++ b/valadate/testexplorer.vala @@ -1,6 +1,6 @@ /* * Valadate - Unit testing library for GObject-based libraries. - * Copyright (C) 20016 Chris Daley <chebizarro@gmail.com> + * Copyright (C) 2016 Chris Daley <chebizarro@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,40 +20,49 @@ * Chris Daley <chebizarro@gmail.com> */ -namespace Valadate { - - internal class TestExplorer : Vala.CodeVisitor { +internal class Valadate.TestExplorer : Vala.CodeVisitor { - private Vala.Class testcase; - private Test[] tests; - private TestCase current_test; - private weak Module module; + private Vala.Class testcase; + private Vala.Class testsuite; + + + private Test[] tests; + private TestCase current_test; + private weak Module module; + private weak TestResult result; - internal delegate void* Constructor(); - internal delegate void TestMethod(TestCase self); + internal delegate void* Constructor(); + internal delegate void TestMethod(TestCase self); + + public TestExplorer(Module module, TestResult result) { + this.module = module; + this.result = result; + } + + public Test[] get_tests() { + return tests; + } + + public override void visit_class(Vala.Class class) { - public TestExplorer(Module module) { - this.module = module; + if (class.get_full_name() == "Valadate.TestCase") { + testcase = class; + return; } - - public Test[] get_tests() { - return tests; + + if (class.get_full_name() == "Valadate.TestSuite") { + testsuite = class; + return; } - - public override void visit_class(Vala.Class class) { - - if (class.get_full_name() == "Valadate.TestCase") { - testcase = class; - return; - } - if (testcase != null && - class.is_subtype_of(testcase) && - class.is_abstract != true ) { + if (testcase != null && + class.is_subtype_of(testcase) && + class.is_abstract != true ) { - string cname = Vala.Symbol.camel_case_to_lower_case( - class.default_construction_method.get_full_name().replace(".","_")); + string cname = Vala.Symbol.camel_case_to_lower_case( + class.default_construction_method.get_full_name().replace(".","_")); + try { unowned Constructor meth = (Constructor)module.get_method(cname); current_test = meth() as TestCase; current_test.name = class.get_full_name().replace("."," "); @@ -77,19 +86,18 @@ namespace Valadate { } } - tests += current_test; class.accept_children(this); - + } catch (ModuleError e) { + stderr.puts(e.message); } } + } - public override void visit_namespace(Vala.Namespace ns) { - ns.accept_children(this); - } - - + public override void visit_namespace(Vala.Namespace ns) { + ns.accept_children(this); } + } diff --git a/valadate/testfixture.vala b/valadate/testfixture.vala index 6bcebd144..29b75ae41 100644 --- a/valadate/testfixture.vala +++ b/valadate/testfixture.vala @@ -1,6 +1,6 @@ /* * Valadate - Unit testing library for GObject-based libraries. - * Copyright (C) 20016 Chris Daley <chebizarro@gmail.com> + * Copyright (C) 2016 Chris Daley <chebizarro@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,14 +19,11 @@ * Authors: * Chris Daley <chebizarro@gmail.com> */ -namespace Valadate { - public interface TestFixture : Object { +public interface Valadate.TestFixture : Object { - public abstract void set_up (); + public abstract void set_up (); - public abstract void tear_down (); - - } + public abstract void tear_down (); } diff --git a/valadate/testresult.vala b/valadate/testresult.vala index e43c9fc86..af377b2e1 100644 --- a/valadate/testresult.vala +++ b/valadate/testresult.vala @@ -1,6 +1,6 @@ /* * Valadate - Unit testing library for GObject-based libraries. - * Copyright (C) 20016 Chris Daley <chebizarro@gmail.com> + * Copyright (C) 2016 Chris Daley <chebizarro@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,20 +19,18 @@ * Authors: * Chris Daley <chebizarro@gmail.com> */ -namespace Valadate { +public interface Valadate.TestResult : Object { - public interface TestResult : Object { + public abstract int error_count {get;internal set;} + public abstract int failure_count {get;internal set;} + public abstract int run_count {get;internal set;} - public abstract int error_count {get;internal set;} - public abstract int failure_count {get;internal set;} - public abstract int run_count {get;internal set;} + public abstract void add_test(Test test); - public abstract void add_error(Test test); + public abstract void add_error(Test test); - public abstract void add_failure(Test test); + public abstract void add_failure(Test test); - public abstract void report(); - - } + public abstract void report(); } diff --git a/valadate/testresultfactory.vala b/valadate/testresultfactory.vala new file mode 100644 index 000000000..9eaed5258 --- /dev/null +++ b/valadate/testresultfactory.vala @@ -0,0 +1,59 @@ +/* + * Valadate - Unit testing library for GObject-based libraries. + * Copyright (C) 2016 Chris Daley <chebizarro@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Chris Daley <chebizarro@gmail.com> + */ + +/** + * The TestResultFactory is a singleton Factory class + * for registered TestResult classes + */ +public class Valadate.TestResultFactory : Object { + + private static TestResultFactory instance; + + private HashTable<string, Type> result_types = + new HashTable<string, Type> (str_hash, str_equal); + + + private TestResultFactory() { + result_types.set("tap",typeof(TAPResult)); + } + + public static TestResultFactory get_instance() { + if(instance == null) + instance = new TestResultFactory(); + return instance; + } + + public void add_result_type(string type, Type class) + requires(class.is_a(typeof(TestResult))) + { + result_types.set(type, class); + } + + public TestResult? new_for_type(string type) { + if(result_types.contains(type)) { + Type t = result_types.get(type); + return Object.new(t) as TestResult; + } + return null; + } + +} diff --git a/valadate/testrunner.vala b/valadate/testrunner.vala index 53f064ccf..63b1accc9 100644 --- a/valadate/testrunner.vala +++ b/valadate/testrunner.vala @@ -1,6 +1,6 @@ /* * Valadate - Unit testing library for GObject-based libraries. - * Copyright (C) 20016 Chris Daley <chebizarro@gmail.com> + * Copyright (C) 2016 Chris Daley <chebizarro@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,117 +20,53 @@ * Chris Daley <chebizarro@gmail.com> */ -namespace Valadate { - - public errordomain RunError { - MODULE, - GIR, - TESTS, - METHOD - } +public class Valadate.TestRunner : Object { + private TestConfig config; - public class TestRunner : Object { - - private Vala.CodeContext context; - private Module module; - private string path; - private Test[] _tests; - - public Test[] tests { - get { - return _tests; - } - } - - public TestRunner(string path) { - this.path = path; - } - - public void load() throws RunError { - string girdir = Path.get_dirname(path).replace(".libs", ""); - - string girname = Path.get_basename(path); - if(girname.has_prefix("lt-")) - girname = girname.substring(3); - - string girfile = girdir + GLib.Path.DIR_SEPARATOR_S + girname + ".vapi"; - - try { - module = new Module(path); - module.load_module(); - load_test_plan(girfile); - - } catch (Error e) { - throw new RunError.MODULE(e.message); - } + private string path; + private Test[] _tests; + + private TestResult result; + + public Test[] tests { + get { + return _tests; } + } - internal void load_test_plan(string girpath) { - if (!FileUtils.test (girpath, FileTest.EXISTS)) - return; - - context = new Vala.CodeContext (); - Vala.CodeContext.push (context); + public TestRunner(TestConfig config) { + this.config = config; + this.path = config.binary; + } - context.report.enable_warnings = false; - context.report.set_verbose_errors (false); - context.verbose_mode = false; - - File currdir = File.new_for_path(GLib.Environment.get_current_dir()); - File valadatedir = currdir.get_parent().get_child("valadate"); - File vapidir = currdir.get_parent().get_child("vapi"); - - context.vapi_directories = {valadatedir.get_path(), vapidir.get_path()}; - - context.add_external_package ("glib-2.0"); - context.add_external_package ("gobject-2.0"); - context.add_external_package ("gio-2.0"); - context.add_external_package ("gmodule-2.0"); - context.add_external_package ("valadate"); - - context.add_source_file (new Vala.SourceFile (context, Vala.SourceFileType.PACKAGE, girpath)); - - var parser = new Vala.Parser (); - parser.parse (context); - - context.check (); + public TestResult? run(TestResult? result = null) throws ConfigError { - var testexplorer = new TestExplorer(module); - context.accept(testexplorer); - _tests = testexplorer.get_tests(); - - } - - - - public static int main (string[] args) { - - var runner = new TestRunner(args[0]); + + return result; + } - GLib.Test.init(ref args); - try { - runner.load(); - } catch (RunError err) { - message(err.message); - return -1; - } + public static int main (string[] args) { - foreach (Test test in runner.tests) - GLib.TestSuite.get_root().add_suite(((TestCase)test).suite); + var config = new TestConfig(); + + int result = config.parse(args); + if(result >= 0) + return result; - GLib.Test.run (); - - runner = null; - - return 0; - + var runner = new TestRunner(config); + + try { + runner.run(); + } catch (ConfigError err) { + stderr.puts(err.message); + return 1; } + - + return 0; } - } diff --git a/valadate/testsuite.vala b/valadate/testsuite.vala new file mode 100644 index 000000000..ed4c684bd --- /dev/null +++ b/valadate/testsuite.vala @@ -0,0 +1,30 @@ +/* + * Valadate - Unit testing library for GObject-based libraries. + * Copyright (C) 2016 Chris Daley <chebizarro@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Chris Daley <chebizarro@gmail.com> + */ + +public abstract class Valadate.TestSuite : CompositeTest { + + public abstract void add_test (Test test); + + public virtual Test[] tests {get;set;} + + +} |