These are unit tests of basic features of the rules compiler, such as evaluation of expressions and embedding C code. --- .gitignore | 4 ++ generator/main.ml | 6 ++- inspection/Makefile.am | 35 +++++++++++++- inspection/test-harness.c | 51 ++++++++++++++++++++ inspection/test1.rules | 80 ++++++++++++++++++++++++++++++++ inspection/test2.rules | 116 ++++++++++++++++++++++++++++++++++++++++++++++ po/POTFILES | 3 ++ 7 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 inspection/test-harness.c create mode 100644 inspection/test1.rules create mode 100644 inspection/test2.rules diff --git a/.gitignore b/.gitignore index b5e5a77..46b2964 100644 --- a/.gitignore +++ b/.gitignore @@ -252,6 +252,10 @@ Makefile.in /inspection/guestfs-inspection.8 /inspection/rules.c /inspection/stamp-guestfs-inspection.pod +/inspection/test1 +/inspection/test1.c +/inspection/test2 +/inspection/test2.c /inspector/actual-*.xml /inspector/stamp-virt-inspector.pod /inspector/test-xmllint.sh diff --git a/generator/main.ml b/generator/main.ml index 7473e89..6bf5486 100644 --- a/generator/main.ml +++ b/generator/main.ml @@ -212,7 +212,11 @@ Run it from the top source directory using the command output_to "customize/customize-synopsis.pod" generate_customize_synopsis_pod; output_to "customize/customize-options.pod" generate_customize_options_pod; - (* Run the rules compiler to generate inspection rules. *) + (* Run the rules compiler to generate test cases and inspection rules. *) + output_to "inspection/test1.c" + (Rules_compiler.compile "inspection/test1.rules"); + output_to "inspection/test2.c" + (Rules_compiler.compile "inspection/test2.rules"); output_to "inspection/rules.c" (Rules_compiler.compile "inspection/inspection.rules"); diff --git a/inspection/Makefile.am b/inspection/Makefile.am index 9227249..c1be08a 100644 --- a/inspection/Makefile.am +++ b/inspection/Makefile.am @@ -18,7 +18,9 @@ include $(top_srcdir)/subdir-rules.mk generator_built = \ - rules.c + rules.c \ + test1.c \ + test2.c BUILT_SOURCES = \ $(generator_built) @@ -90,3 +92,34 @@ stamp-guestfs-inspection.pod: guestfs-inspection.pod --license GPLv2+ \ $< touch $@ + +# Tests. + +TESTS = test1 test2 +check_PROGRAMS = $(TESTS) + +test1_SOURCES = \ + $(SHARED_SOURCE_FILES) \ + facts.c \ + inspection.h \ + stringsbuf.c \ + stringsbuf.h \ + test-harness.c \ + test1.c + +test1_LDADD = $(guestfs_inspection_LDADD) +test1_CPPFLAGS = $(guestfs_inspection_CPPFLAGS) +test1_CFLAGS = $(guestfs_inspection_CFLAGS) + +test2_SOURCES = \ + $(SHARED_SOURCE_FILES) \ + facts.c \ + inspection.h \ + stringsbuf.c \ + stringsbuf.h \ + test-harness.c \ + test2.c + +test2_LDADD = $(guestfs_inspection_LDADD) +test2_CPPFLAGS = $(guestfs_inspection_CPPFLAGS) +test2_CFLAGS = $(guestfs_inspection_CFLAGS) diff --git a/inspection/test-harness.c b/inspection/test-harness.c new file mode 100644 index 0000000..cfe39df --- /dev/null +++ b/inspection/test-harness.c @@ -0,0 +1,51 @@ +/* guestfs-inspection tests + * Copyright (C) 2009-2015 Red Hat Inc. + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "inspection.h" + +int verbose = 1; + +int +main (int argc, char *argv[]) +{ + /* Run the rules. */ + rules (); + + /* For debugging. */ + print_true_facts (); + + /* The tests should contain a TestOK rule which verifies that all + * true and false facts are what we expect. So we just need to + * check that TestOK is true and we're done. + */ + CLEANUP_FREE fact *f = create_fact ("TestOK", NULL); + if (!is_fact (true, f)) { + fprintf (stderr, "%s: test failed, see debugging information above\n", + argv[0]); + exit (EXIT_FAILURE); + } + + exit (EXIT_SUCCESS); +} diff --git a/inspection/test1.rules b/inspection/test1.rules new file mode 100644 index 0000000..416ccd2 --- /dev/null +++ b/inspection/test1.rules @@ -0,0 +1,80 @@ +/* Libguestfs inspection rules unit test -*- prolog -*- + * Copyright (C) 2009-2015 Red Hat Inc. + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +Filesystem(fs) :- + (fs)*={{ + const char *fses[] = { "/dev/sda1", "/dev/sda2", "/dev/sda3", NULL }; + size_t i; + for (i = 0; fses[i] != NULL; ++i) + set_fs (fses[i]); + return 0; + }}. + +File("/dev/sda1", "/etc/fstab"). +File("/dev/sda1", "/etc/debian_version"). +File("/dev/sda2", "/etc/fstab"). +File("/dev/sda2", "/etc/redhat-release"). +File("/dev/sda2", "/etc/fedora-release"). +File("/dev/sda3", "/etc/fstab"). +File("/dev/sda3", "/etc/fedora-release") :- false. +File("/dev/sda3", "/etc/redhat-release"). + +Symlink("/dev/sda1", "/bin"). + +Directory("/dev/sda1", "/lib"). +Directory("/dev/sda1", "/etc"). +Directory("/dev/sda2", "/bin"). +Directory("/dev/sda2", "/etc"). +Directory("/dev/sda2", "/lib"). +Directory("/dev/sda3", "/bin"). +Directory("/dev/sda3", "/etc"). +Directory("/dev/sda3", "/lib"). + +UnixRoot(fs) :- + Filesystem(fs), + (Directory(fs, "/bin"); Symlink(fs, "/bin")), + (File(fs, "/etc/fstab"); Symlink(fs, "/etc/fstab")), + (Directory(fs, "/lib"); Symlink(fs, "/lib")). + +Distro(rootfs, "RHEL") :- + UnixRoot(rootfs), + File(rootfs, "/etc/redhat-release"), + ! File(rootfs, "/etc/fedora-release"). + +Distro(rootfs, "Fedora") :- + UnixRoot(rootfs), + File(rootfs, "/etc/fedora-release"). + +Distro(rootfs, "Debian") :- + UnixRoot(rootfs), + File(rootfs, "/etc/debian_version"). + +ProductName(rootfs, "Fedora", product_name) :- + Filesystem(rootfs), + Distro(rootfs, "Fedora"), + (product_name)={{ + set_product_name ("Fedora release 23 (Twenty Three)"); + return 0; + }}. + +/* This rule is checked by the test harness. */ +TestOK :- + Distro("/dev/sda1", "Debian"), + Distro("/dev/sda2", "Fedora"), + Distro("/dev/sda3", "RHEL"), + ProductName("/dev/sda2", "Fedora", "Fedora release 23 (Twenty Three)"). diff --git a/inspection/test2.rules b/inspection/test2.rules new file mode 100644 index 0000000..09bc062 --- /dev/null +++ b/inspection/test2.rules @@ -0,0 +1,116 @@ +/* Libguestfs inspection rules unit test -*- prolog -*- + * Copyright (C) 2009-2015 Red Hat Inc. + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* Test false, true expressions. */ +TestTrue1. +TestTrue2 :- true. +TestFalse :- false. + +/* Basic boolean expressions. */ +TestAnd1 :- true, true. +TestAnd2 :- true, false. +TestAnd3 :- false, false. +TestAnd4 :- false, true. +TestOr1 :- true; true. +TestOr2 :- true; false. +TestOr3 :- false; false. +TestOr4 :- false; true. +TestNot1 :- !TestTrue1. +TestNot2 :- !TestFalse. + +/* Precedence of AND and OR operators. */ +TestPrec :- true; true, false. /* should be parsed as true; (true, false) */ + +/* Parentheses. */ +TestParen1 :- (true, true); false. +TestParen2 :- false; (true, true). +TestParen3 :- (true; false), true. +TestParen4 :- true, (true; false). + +/* Cartesian product. */ +TestCartesian(x,y) :- true. + +/* Boolean code. */ +TestCTrue :- {{ return 1; }}. +TestCFalse :- {{ return 0; }}. + +/* Assignment code. */ +TestCAssign1(x) :- (x)={{ set_x ("123"); return 0; }}. +TestCAssign2(x,y) :- (x,y)={{ set_x_y ("123", "456"); return 0; }}. +TestCAssign3(x,y,z) :- (x,y,z)={{ set_x_y_z ("123", "456", "789"); return 0; }}. + +/* Assignment code for lists. */ +TestCListAssign1(x) :- + (x)*={{ /* no assignments */ return 0; }}. +TestCListAssign2(x) :- + (x)*={{ set_x ("123"); return 0; }}. +TestCListAssign3(x) :- + (x)*={{ set_x ("123"); set_x ("456"); return 0; }}. +TestCListAssign4(x,y) :- + (x,y)*={{ /* no assignments */ return 0; }}. +TestCListAssign5(x,y) :- + (x,y)*={{ set_x_y ("123", "456"); return 0; }}. +TestCListAssign6(x,y) :- + (x,y)*={{ set_x_y ("123", "456"); set_x_y ("456", "789"); return 0; }}. + +/* These assignments only differ in a small amount of checking code. */ +TestCListAssign7(x,y) :- + (x,y)?={{ /* no assignments */ return 0; }}. +TestCListAssign8(x,y) :- + (x,y)?={{ set_x_y ("123", "456"); return 0; }}. +TestCListAssign9(x,y) :- + (x,y)+={{ set_x_y ("123", "456"); return 0; }}. +TestCListAssign10(x,y) :- + (x,y)+={{ set_x_y ("123", "456"); set_x_y ("456", "789"); return 0; }}. + +/* Check no clashes in generated code with commonly used variables. */ +TestCAssignClash(i,j,fact,verbose,args,env) :- + (i,j,fact,verbose,args,env)={{ + set_i_j_fact_verbose_args_env ("1", "2", "3", "4", "5", "6"); + return 0; + }}. + +/* This rule is checked by the test harness. */ +TestOK :- + TestTrue1, TestTrue2, !TestFalse, + TestAnd1, !TestAnd2, !TestAnd3, !TestAnd4, + TestOr1, TestOr2, !TestOr3, TestOr4, + !TestNot1, TestNot2, + TestPrec, + TestParen1, TestParen2, TestParen3, TestParen4, + TestCartesian("123", "123"), + TestCartesian("123", "456"), + TestCartesian("123", "789"), + TestCartesian("456", "123"), /* etc etc */ + TestCTrue, !TestCFalse, + TestCAssign1("123"), TestCAssign2("123", "456"), + TestCAssign3("123", "456", "789"), + /* no assignments to TestCListAssign1 */ + TestCListAssign2("123"), + TestCListAssign3("123"), + TestCListAssign3("456"), + /* no assignments to TestCListAssign4 */ + TestCListAssign5("123", "456"), + TestCListAssign6("123", "456"), + TestCListAssign6("456", "789"), + /* no assignments to TestCListAssign7 */ + TestCListAssign8("123", "456"), + TestCListAssign9("123", "456"), + TestCListAssign10("123", "456"), + TestCListAssign10("456", "789"), + TestCAssignClash("1", "2", "3", "4", "5", "6"). diff --git a/po/POTFILES b/po/POTFILES index b6332f6..afdc75f 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -263,6 +263,9 @@ inspection/facts.c inspection/inspection.c inspection/mount.c inspection/stringsbuf.c +inspection/test-harness.c +inspection/test1.c +inspection/test2.c inspector/inspector.c java/com_redhat_et_libguestfs_GuestFS.c lua/lua-guestfs.c -- 2.5.0