[PATCH weston v2] Refactored simple unit/integration test framework and corresponding test program.

Jon A. Cruz jonc at osg.samsung.com
Tue May 5 15:50:22 PDT 2015


Refactored to a simple C-based test framework and an example program
that uses it to run through some simple wayland client checks.

Signed-off-by: Jon A. Cruz <jonc at osg.samsung.com>
---
 .gitignore                            |   3 +
 Makefile.am                           |  34 +++
 tools/Doxyfile                        | 318 +++++++++++++++++++++
 tools/devdocs.doxyfile                | 315 +++++++++++++++++++++
 tools/devtools.dox                    |  52 ++++
 tools/tools.dox                       |  29 ++
 tools/tools_arch_new.gv               |  60 ++++
 tools/tools_arch_old.gv               |  28 ++
 tools/waycheck/rough_draw.c           | 176 ++++++++++++
 tools/waycheck/rough_draw.h           |  42 +++
 tools/waycheck/waycheck.c             | 505 ++++++++++++++++++++++++++++++++++
 tools/waycheck/waycheck.dox           |  29 ++
 tools/waycheck/wtst_fixtures.c        | 289 +++++++++++++++++++
 tools/waycheck/wtst_fixtures.h        | 144 ++++++++++
 tools/zunitc/doc/zunitc.dox           |  67 +++++
 tools/zunitc/inc/zunitc/zunitc.h      | 300 ++++++++++++++++++++
 tools/zunitc/inc/zunitc/zunitc_impl.h |  76 +++++
 tools/zunitc/src/zunitc_impl.c        | 496 +++++++++++++++++++++++++++++++++
 tools/zunitc/test/zunitc_test.c       | 106 +++++++
 19 files changed, 3069 insertions(+)
 create mode 100644 tools/Doxyfile
 create mode 100644 tools/devdocs.doxyfile
 create mode 100644 tools/devtools.dox
 create mode 100644 tools/tools.dox
 create mode 100644 tools/tools_arch_new.gv
 create mode 100644 tools/tools_arch_old.gv
 create mode 100644 tools/waycheck/rough_draw.c
 create mode 100644 tools/waycheck/rough_draw.h
 create mode 100644 tools/waycheck/waycheck.c
 create mode 100644 tools/waycheck/waycheck.dox
 create mode 100644 tools/waycheck/wtst_fixtures.c
 create mode 100644 tools/waycheck/wtst_fixtures.h
 create mode 100644 tools/zunitc/doc/zunitc.dox
 create mode 100644 tools/zunitc/inc/zunitc/zunitc.h
 create mode 100644 tools/zunitc/inc/zunitc/zunitc_impl.h
 create mode 100644 tools/zunitc/src/zunitc_impl.c
 create mode 100644 tools/zunitc/test/zunitc_test.c

diff --git a/.gitignore b/.gitignore
index 047c386..2690bde 100644
--- a/.gitignore
+++ b/.gitignore
@@ -98,3 +98,6 @@ weston-drm.7
 weston.ini.5
 
 /tests/weston-ivi.ini
+
+waycheck
+zuctest
diff --git a/Makefile.am b/Makefile.am
index 2f16fac..073733f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1155,6 +1155,40 @@ setbacklight_CFLAGS = $(AM_CFLAGS) $(SETBACKLIGHT_CFLAGS)
 setbacklight_LDADD = $(SETBACKLIGHT_LIBS)
 endif
 
+# --------------------------------------------------------------------------
+
+all-local: waycheck$(EXEEXT) zuctest$(EXEEXT)
+
+noinst_PROGRAMS += zuctest$(EXEEXT)
+
+zuctest_CPPFLAGS =			\
+	-I$(top_builddir)/tools/zunitc/inc
+
+zuctest_SOURCES = \
+	tools/zunitc/src/zunitc_impl.c \
+	tools/zunitc/test/zunitc_test.c
+
+#
+
+noinst_PROGRAMS += waycheck$(EXEEXT)
+
+waycheck_LDADD =			\
+	$(WAYLAND_COMPOSITOR_LIBS)
+
+waycheck_CPPFLAGS =			\
+	-I$(top_builddir)/tools/zunitc/inc	\
+	-I$(top_builddir)/clients		\
+	-I$(top_srcdir)/shared
+
+waycheck_SOURCES = \
+	tools/zunitc/src/zunitc_impl.c \
+	shared/os-compatibility.c \
+	tools/waycheck/waycheck.c \
+	tools/waycheck/rough_draw.c \
+	tools/waycheck/wtst_fixtures.c
+
+# --------------------------------------------------------------------------
+
 EXTRA_DIST += tests/weston-tests-env
 
 BUILT_SOURCES +=				\
diff --git a/tools/Doxyfile b/tools/Doxyfile
new file mode 100644
index 0000000..e42cdbb
--- /dev/null
+++ b/tools/Doxyfile
@@ -0,0 +1,318 @@
+# Doxyfile 1.8.8
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING      = UTF-8
+PROJECT_NAME           = "Tools"
+PROJECT_NUMBER         =
+PROJECT_BRIEF          =
+PROJECT_LOGO           =
+OUTPUT_DIRECTORY       = docs
+CREATE_SUBDIRS         = NO
+ALLOW_UNICODE_NAMES    = NO
+OUTPUT_LANGUAGE        = English
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       =
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = YES
+STRIP_FROM_PATH        =
+STRIP_FROM_INC_PATH    =
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = YES
+QT_AUTOBRIEF           = NO
+MULTILINE_CPP_IS_BRIEF = NO
+INHERIT_DOCS           = YES
+SEPARATE_MEMBER_PAGES  = NO
+TAB_SIZE               = 4
+ALIASES                =
+TCL_SUBST              =
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+OPTIMIZE_FOR_FORTRAN   = NO
+OPTIMIZE_OUTPUT_VHDL   = NO
+EXTENSION_MAPPING      =
+MARKDOWN_SUPPORT       = YES
+AUTOLINK_SUPPORT       = YES
+BUILTIN_STL_SUPPORT    = NO
+CPP_CLI_SUPPORT        = NO
+SIP_SUPPORT            = NO
+IDL_PROPERTY_SUPPORT   = YES
+DISTRIBUTE_GROUP_DOC   = NO
+SUBGROUPING            = YES
+INLINE_GROUPED_CLASSES = NO
+INLINE_SIMPLE_STRUCTS  = NO
+TYPEDEF_HIDES_STRUCT   = NO
+LOOKUP_CACHE_SIZE      = 0
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_PACKAGE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = YES
+EXTRACT_LOCAL_METHODS  = NO
+EXTRACT_ANON_NSPACES   = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = NO
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+SHOW_GROUPED_MEMB_INC  = NO
+FORCE_LOCAL_INCLUDES   = NO
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = NO
+SORT_MEMBERS_CTORS_1ST = NO
+SORT_GROUP_NAMES       = NO
+SORT_BY_SCOPE_NAME     = NO
+STRICT_PROTO_MATCHING  = NO
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       =
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = YES
+SHOW_FILES             = YES
+SHOW_NAMESPACES        = YES
+FILE_VERSION_FILTER    =
+LAYOUT_FILE            =
+CITE_BIB_FILES         =
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           =
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = \
+		       tools.dox \
+		       zunitc/doc/zunitc.dox \
+		       zunitc/inc/zunitc/zunitc.h \
+		       waycheck/waycheck.dox \
+		       waycheck/wtst_fixtures.h \
+		       waycheck/rough_draw.h
+INPUT_ENCODING         = UTF-8
+FILE_PATTERNS          =
+RECURSIVE              = NO
+EXCLUDE                =
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       =
+EXCLUDE_SYMBOLS        =
+EXAMPLE_PATH           =
+EXAMPLE_PATTERNS       =
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             =
+INPUT_FILTER           =
+FILTER_PATTERNS        =
+FILTER_SOURCE_FILES    = NO
+FILTER_SOURCE_PATTERNS =
+USE_MDFILE_AS_MAINPAGE =
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION    = NO
+REFERENCES_LINK_SOURCE = YES
+SOURCE_TOOLTIPS        = YES
+USE_HTAGS              = NO
+VERBATIM_HEADERS       = YES
+CLANG_ASSISTED_PARSING = NO
+CLANG_OPTIONS          =
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = YES
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          =
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            =
+HTML_FOOTER            =
+HTML_STYLESHEET        =
+HTML_EXTRA_STYLESHEET  =
+HTML_EXTRA_FILES       =
+HTML_COLORSTYLE_HUE    = 220
+HTML_COLORSTYLE_SAT    = 100
+HTML_COLORSTYLE_GAMMA  = 80
+HTML_TIMESTAMP         = YES
+HTML_DYNAMIC_SECTIONS  = NO
+HTML_INDEX_NUM_ENTRIES = 100
+GENERATE_DOCSET        = NO
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+DOCSET_PUBLISHER_NAME  = Publisher
+GENERATE_HTMLHELP      = NO
+CHM_FILE               =
+HHC_LOCATION           =
+GENERATE_CHI           = NO
+CHM_INDEX_ENCODING     =
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+GENERATE_QHP           = NO
+QCH_FILE               =
+QHP_NAMESPACE          = org.doxygen.Project
+QHP_VIRTUAL_FOLDER     = doc
+QHP_CUST_FILTER_NAME   =
+QHP_CUST_FILTER_ATTRS  =
+QHP_SECT_FILTER_ATTRS  =
+QHG_LOCATION           =
+GENERATE_ECLIPSEHELP   = NO
+ECLIPSE_DOC_ID         = org.doxygen.Project
+DISABLE_INDEX          = NO
+GENERATE_TREEVIEW      = NO
+ENUM_VALUES_PER_LINE   = 4
+TREEVIEW_WIDTH         = 250
+EXT_LINKS_IN_WINDOW    = NO
+FORMULA_FONTSIZE       = 10
+FORMULA_TRANSPARENT    = YES
+USE_MATHJAX            = NO
+MATHJAX_FORMAT         = HTML-CSS
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+MATHJAX_EXTENSIONS     =
+MATHJAX_CODEFILE       =
+SEARCHENGINE           = YES
+SERVER_BASED_SEARCH    = NO
+EXTERNAL_SEARCH        = NO
+SEARCHENGINE_URL       =
+SEARCHDATA_FILE        = searchdata.xml
+EXTERNAL_SEARCH_ID     =
+EXTRA_SEARCH_MAPPINGS  =
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = YES
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4
+EXTRA_PACKAGES         =
+LATEX_HEADER           =
+LATEX_FOOTER           =
+LATEX_EXTRA_FILES      =
+PDF_HYPERLINKS         = YES
+USE_PDFLATEX           = YES
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+LATEX_SOURCE_CODE      = NO
+LATEX_BIB_STYLE        = plain
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    =
+RTF_EXTENSIONS_FILE    =
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_SUBDIR             =
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+GENERATE_DOCBOOK       = NO
+DOCBOOK_OUTPUT         = docbook
+DOCBOOK_PROGRAMLISTING = NO
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           =
+INCLUDE_FILE_PATTERNS  =
+PREDEFINED             =
+EXPAND_AS_DEFINED      =
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+TAGFILES               =
+GENERATE_TAGFILE       =
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+EXTERNAL_PAGES         = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+MSCGEN_PATH            =
+DIA_PATH               =
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = YES
+DOT_NUM_THREADS        = 0
+DOT_FONTNAME           = Helvetica
+DOT_FONTSIZE           = 10
+DOT_FONTPATH           =
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+UML_LIMIT_NUM_FIELDS   = 10
+TEMPLATE_RELATIONS     = NO
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = NO
+CALLER_GRAPH           = NO
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+INTERACTIVE_SVG        = NO
+DOT_PATH               =
+DOTFILE_DIRS           =
+MSCFILE_DIRS           =
+DIAFILE_DIRS           =
+PLANTUML_JAR_PATH      =
+DOT_GRAPH_MAX_NODES    = 50
+MAX_DOT_GRAPH_DEPTH    = 0
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
diff --git a/tools/devdocs.doxyfile b/tools/devdocs.doxyfile
new file mode 100644
index 0000000..41aa836
--- /dev/null
+++ b/tools/devdocs.doxyfile
@@ -0,0 +1,315 @@
+# Doxyfile 1.8.8
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING      = UTF-8
+PROJECT_NAME           = "Tool Internals"
+PROJECT_NUMBER         =
+PROJECT_BRIEF          =
+PROJECT_LOGO           =
+OUTPUT_DIRECTORY       = devdocs
+CREATE_SUBDIRS         = NO
+ALLOW_UNICODE_NAMES    = NO
+OUTPUT_LANGUAGE        = English
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       =
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = YES
+STRIP_FROM_PATH        =
+STRIP_FROM_INC_PATH    =
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = YES
+QT_AUTOBRIEF           = NO
+MULTILINE_CPP_IS_BRIEF = NO
+INHERIT_DOCS           = YES
+SEPARATE_MEMBER_PAGES  = NO
+TAB_SIZE               = 4
+ALIASES                =
+TCL_SUBST              =
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+OPTIMIZE_FOR_FORTRAN   = NO
+OPTIMIZE_OUTPUT_VHDL   = NO
+EXTENSION_MAPPING      =
+MARKDOWN_SUPPORT       = YES
+AUTOLINK_SUPPORT       = YES
+BUILTIN_STL_SUPPORT    = NO
+CPP_CLI_SUPPORT        = NO
+SIP_SUPPORT            = NO
+IDL_PROPERTY_SUPPORT   = YES
+DISTRIBUTE_GROUP_DOC   = NO
+SUBGROUPING            = YES
+INLINE_GROUPED_CLASSES = NO
+INLINE_SIMPLE_STRUCTS  = NO
+TYPEDEF_HIDES_STRUCT   = NO
+LOOKUP_CACHE_SIZE      = 0
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = NO
+EXTRACT_PACKAGE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = YES
+EXTRACT_LOCAL_METHODS  = NO
+EXTRACT_ANON_NSPACES   = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = NO
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+SHOW_GROUPED_MEMB_INC  = NO
+FORCE_LOCAL_INCLUDES   = NO
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = NO
+SORT_MEMBERS_CTORS_1ST = NO
+SORT_GROUP_NAMES       = NO
+SORT_BY_SCOPE_NAME     = NO
+STRICT_PROTO_MATCHING  = NO
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       =
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = YES
+SHOW_FILES             = YES
+SHOW_NAMESPACES        = YES
+FILE_VERSION_FILTER    =
+LAYOUT_FILE            =
+CITE_BIB_FILES         =
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           =
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = \
+		       devtools.dox \
+		       zunitc \
+		       waycheck
+INPUT_ENCODING         = UTF-8
+FILE_PATTERNS          =
+RECURSIVE              = YES
+EXCLUDE                =
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       =
+EXCLUDE_SYMBOLS        =
+EXAMPLE_PATH           =
+EXAMPLE_PATTERNS       =
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             =
+INPUT_FILTER           =
+FILTER_PATTERNS        =
+FILTER_SOURCE_FILES    = NO
+FILTER_SOURCE_PATTERNS =
+USE_MDFILE_AS_MAINPAGE =
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION    = NO
+REFERENCES_LINK_SOURCE = YES
+SOURCE_TOOLTIPS        = YES
+USE_HTAGS              = NO
+VERBATIM_HEADERS       = YES
+CLANG_ASSISTED_PARSING = NO
+CLANG_OPTIONS          =
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = YES
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          =
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            =
+HTML_FOOTER            =
+HTML_STYLESHEET        =
+HTML_EXTRA_STYLESHEET  =
+HTML_EXTRA_FILES       =
+HTML_COLORSTYLE_HUE    = 220
+HTML_COLORSTYLE_SAT    = 100
+HTML_COLORSTYLE_GAMMA  = 80
+HTML_TIMESTAMP         = YES
+HTML_DYNAMIC_SECTIONS  = NO
+HTML_INDEX_NUM_ENTRIES = 100
+GENERATE_DOCSET        = NO
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+DOCSET_PUBLISHER_NAME  = Publisher
+GENERATE_HTMLHELP      = NO
+CHM_FILE               =
+HHC_LOCATION           =
+GENERATE_CHI           = NO
+CHM_INDEX_ENCODING     =
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+GENERATE_QHP           = NO
+QCH_FILE               =
+QHP_NAMESPACE          = org.doxygen.Project
+QHP_VIRTUAL_FOLDER     = doc
+QHP_CUST_FILTER_NAME   =
+QHP_CUST_FILTER_ATTRS  =
+QHP_SECT_FILTER_ATTRS  =
+QHG_LOCATION           =
+GENERATE_ECLIPSEHELP   = NO
+ECLIPSE_DOC_ID         = org.doxygen.Project
+DISABLE_INDEX          = NO
+GENERATE_TREEVIEW      = NO
+ENUM_VALUES_PER_LINE   = 4
+TREEVIEW_WIDTH         = 250
+EXT_LINKS_IN_WINDOW    = NO
+FORMULA_FONTSIZE       = 10
+FORMULA_TRANSPARENT    = YES
+USE_MATHJAX            = NO
+MATHJAX_FORMAT         = HTML-CSS
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+MATHJAX_EXTENSIONS     =
+MATHJAX_CODEFILE       =
+SEARCHENGINE           = YES
+SERVER_BASED_SEARCH    = NO
+EXTERNAL_SEARCH        = NO
+SEARCHENGINE_URL       =
+SEARCHDATA_FILE        = searchdata.xml
+EXTERNAL_SEARCH_ID     =
+EXTRA_SEARCH_MAPPINGS  =
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = YES
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4
+EXTRA_PACKAGES         =
+LATEX_HEADER           =
+LATEX_FOOTER           =
+LATEX_EXTRA_FILES      =
+PDF_HYPERLINKS         = YES
+USE_PDFLATEX           = YES
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+LATEX_SOURCE_CODE      = NO
+LATEX_BIB_STYLE        = plain
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    =
+RTF_EXTENSIONS_FILE    =
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_SUBDIR             =
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+GENERATE_DOCBOOK       = NO
+DOCBOOK_OUTPUT         = docbook
+DOCBOOK_PROGRAMLISTING = NO
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           =
+INCLUDE_FILE_PATTERNS  =
+PREDEFINED             =
+EXPAND_AS_DEFINED      =
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+TAGFILES               =
+GENERATE_TAGFILE       =
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+EXTERNAL_PAGES         = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+MSCGEN_PATH            =
+DIA_PATH               =
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = YES
+DOT_NUM_THREADS        = 0
+DOT_FONTNAME           = Helvetica
+DOT_FONTSIZE           = 10
+DOT_FONTPATH           =
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+UML_LIMIT_NUM_FIELDS   = 10
+TEMPLATE_RELATIONS     = NO
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = NO
+CALLER_GRAPH           = NO
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+INTERACTIVE_SVG        = NO
+DOT_PATH               =
+DOTFILE_DIRS           = .
+MSCFILE_DIRS           =
+DIAFILE_DIRS           =
+PLANTUML_JAR_PATH      =
+DOT_GRAPH_MAX_NODES    = 50
+MAX_DOT_GRAPH_DEPTH    = 0
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
diff --git a/tools/devtools.dox b/tools/devtools.dox
new file mode 100644
index 0000000..c1ec9fb
--- /dev/null
+++ b/tools/devtools.dox
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ at mainpage
+
+- @ref zunitc - Simple test framework
+
+- @ref waycheck - Simple integration/acceptance test tool
+
+ at section tools_overview Overview
+
+The tools area currently consists of two sub-projects (@ref zunitc and
+ at ref waycheck) that are refined from the prior single weston/tests source
+folder.
+
+ at subsection tools_overview_old Old Code Organization
+
+The original 'tests' folder contained basic weston testing with an
+integrated test runner framework. Over time things progressed to the
+stage where splitting apart into discrete layers was warranted.
+
+ at dotfile tools_arch_old.gv "Original test code organization"
+
+ at subsection tools_overview_new New Code Organization
+
+The test code that is not weston-specific gets split out to a separate
+folder and/or folders. Then an additional testing tool 'waycheck' that is
+compositor-agnostic is added.
+
+ at dotfile tools_arch_new.gv "Refactored test code organization"
+
+*/
diff --git a/tools/tools.dox b/tools/tools.dox
new file mode 100644
index 0000000..e4f5524
--- /dev/null
+++ b/tools/tools.dox
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ at mainpage
+
+- @ref zunitc - Simple test framework
+
+- @ref waycheck - Simple integration/acceptance test tool
+*/
diff --git a/tools/tools_arch_new.gv b/tools/tools_arch_new.gv
new file mode 100644
index 0000000..fe8b6c7
--- /dev/null
+++ b/tools/tools_arch_new.gv
@@ -0,0 +1,60 @@
+digraph toolarch_new {
+    rankdir = "TB";
+
+    node[shape=record]
+
+    subgraph cluster_0 {
+        label = "./tests";
+
+        keyboard_test_c [label = "{keyboard-test.c|tests\l}"]
+        text_test_c [label = "{text-test.c|tests\l}"]
+        vertex_clip_test_c [label = "{vertex-clip-test.c|tests\l}"]
+
+	spacer [shape = point, style = invis]
+
+        weston_test_client_helper [label = "{weston-test-client-helper.h/.c|Weston test protocol\l}"]
+
+        weston_test_c [label = "{weston-test.c|Extension protocol\nimplementation}"]
+    }
+
+    subgraph cluster_1 {
+        label = "./tools/waycheck";
+
+	waycheck [label = "{waycheck.c| \n \n }"]
+    }
+
+    subgraph cluster_2 {
+        label = "./tools/wayland_fixtures";
+
+	wtst_fixtures [label = "{wtst_fixtures.h/c|Wayland tracking structs\lWayland callbacks\l}"]
+    }
+
+    subgraph cluster_3 {
+        label = "./tools/zunitc";
+
+	zunitc [label = "{zunitc|Test definition macros\lTest running functions\lTest reporting functions\lTest run lifecycle\l}"]
+    }
+
+    keyboard_test_c -> weston_test_client_helper
+    keyboard_test_c -> wtst_fixtures
+    keyboard_test_c -> zunitc
+    vertex_clip_test_c -> zunitc
+    text_test_c -> weston_test_client_helper
+    text_test_c -> wtst_fixtures
+    text_test_c -> zunitc
+
+    waycheck -> wtst_fixtures
+    waycheck -> zunitc
+
+    wtst_fixtures -> zunitc
+
+    edge [style = dashed, arrowhead = open]
+    weston_test_client_helper -> weston_test_c
+
+    edge [style = invis]
+    weston_test_client_helper -> zunitc
+
+    text_test_c -> spacer
+    keyboard_test_c -> spacer
+    spacer -> weston_test_client_helper
+}
diff --git a/tools/tools_arch_old.gv b/tools/tools_arch_old.gv
new file mode 100644
index 0000000..b746121
--- /dev/null
+++ b/tools/tools_arch_old.gv
@@ -0,0 +1,28 @@
+digraph toolarch_old {
+    rankdir = "TB";
+
+    node[shape = record]
+
+    subgraph cluster_0 {
+        label = "./tests";
+
+        keyboard_test_c [label = "{keyboard-test.c|tests\l}"]
+        text_test_c [label = "{text-test.c|tests\l}"]
+        vertex_clip_test_c [label = "{vertex-clip-test.c|tests\l}"]
+
+        weston_test_client_helper [label = "{weston-test-client-helper.h/.c|Wayland tracking structs\lWeston test protocol\lWayland callbacks\lTest run lifecycle\l}"]
+
+        weston_test_c [label = "{weston-test.c|Extension protocol\nimplementation}"]
+        weston_test_runner [label = "{weston-test-runner.h/.c|Test definition macros\lTest running functions\lTest reporting functions\lTest run lifecycle\l}"]
+    }
+
+    weston_test_client_helper -> weston_test_runner
+    keyboard_test_c -> weston_test_client_helper
+    keyboard_test_c -> weston_test_runner
+    vertex_clip_test_c -> weston_test_runner
+    text_test_c -> weston_test_client_helper
+    text_test_c -> weston_test_runner
+
+    edge [style = dashed, arrowhead = open]
+    weston_test_client_helper -> weston_test_c
+}
diff --git a/tools/waycheck/rough_draw.c b/tools/waycheck/rough_draw.c
new file mode 100644
index 0000000..9506d68
--- /dev/null
+++ b/tools/waycheck/rough_draw.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stddef.h>
+
+#include "rough_draw.h"
+
+static void fillRect(pixel *raw, pixel val, int width, int height, int stride)
+{
+	int x = 0;
+	int y = 0;
+
+	for (y = 0; y < height; ++y) {
+		pixel *ptr = raw + (y * stride);
+		for (x = 0; x < width; ++x) {
+			*(ptr++) = val;
+		}
+	}
+}
+
+static pixel meld(pixel val1, pixel val2, double factor)
+{
+	pixel result = val1;
+	unsigned char *p0 = (unsigned char *)&result;
+	unsigned char *p1 = (unsigned char *)&val2;
+	size_t i;
+	for (i = 0; i < sizeof(pixel); ++i) {
+		p0[i] = ((int)(((p0[i] << 8) * (1.0 - factor))
+			 + ((p1[i] << 8) * factor))) >> 8;
+	}
+	return result;
+}
+
+static void gradRect(pixel *raw, pixel val1, pixel val2,
+		     int width, int height, int stride)
+{
+	int x = 0;
+	int y = 0;
+
+	double dwidth = (double)width;
+	for (x = 0; x < width; ++x) {
+		pixel melded = meld(val1, val2, x / dwidth);
+		for (y = 0; y < height; ++y) {
+			pixel *ptr = raw + (y * stride) + x;
+			*ptr = melded;
+		}
+	}
+}
+
+void draw_bars(pixel *raw, int width, int height)
+{
+	pixel bars[] = {0xffb4b4b4, 0xffb4b410, 0xff10b4b4, 0xff10b410,
+			0xffb410b4, 0xffb41010, 0xff1010b4};
+	if (raw) {
+		int y0 = ((height * 1.75) / 3);
+		int y1 = ((height * 2) / 3);
+		int y2 = ((height * 3) / 4);
+		int h1 = y1 - y0;
+		int h2 = height - y2;
+		int w1 = width / 8;
+		int w2 = (width * 0.75) / 7;
+		int xr = (width * 7) / 8;
+
+		fillRect(raw, 0x7f1f1f1f, width, height, width);
+
+		// left gray:
+		fillRect(raw, 0xff686868, w1, y0, width);
+		fillRect(raw + (y0 * width), 0xff10ebeb, w1, h1, width);
+		fillRect(raw + (y1 * width), 0xffebeb10, w1, h1, width);
+		fillRect(raw + (y2 * width), 0xff313131, w1, h2, width);
+
+		// right gray:
+		fillRect(raw + xr, 0xff686868, w1, y0, width);
+		fillRect(raw + xr + (y0 * width), 0xff1010eb, w1, h1, width);
+		fillRect(raw + xr + (y1 * width), 0xffeb1010, w1, h1, width);
+		fillRect(raw + xr + (y2 * width), 0xff313131, w1, h2, width);
+
+		int xoff = w1;
+		fillRect(raw + xoff + (y0 * width), 0xffebebeb, w2, h1, width);
+		fillRect(raw + xoff + (y1 * width), 0xff101010, w2, h1, width);
+
+		double barSpan = (width * 0.75);
+		size_t barCount = sizeof(bars) / sizeof(bars[0]);
+		size_t i = 0;
+		for (i = 0; i < barCount; ++i)
+		{
+			xoff = (barSpan * i) / barCount;
+			int ww = (barSpan * (i + 1)) / barCount;
+			ww -= xoff;
+			xoff += w1;
+			fillRect(raw + xoff, bars[i], ww, y0, width);
+		}
+
+		int hw = width - (w1 + w1 + w2);
+		// Gray horiz:
+		xoff = w1 + w2;
+		fillRect(raw + xoff + (y0 * width), 0xffb4b4b4, hw, h1, width);
+		gradRect(raw + xoff + (y1 * width), 0xff101010, 0xffebebeb,
+			 hw, h1, width);
+
+
+		xoff = (width * 0.85625) / 3;
+		int w3 = (width * 0.64375) / 3;
+		fillRect(raw + w1 + (y2 * width), 0xff101010, width - (w1 * 2),
+			 h2, width);
+		fillRect(raw + xoff + (y2 * width), 0xffebebeb, w3, h2, width);
+
+		int w4 = (width * 0.10625) / 3;
+		xoff = (width * 1.765625) / 3;
+		fillRect(raw + xoff + (y2 * width), 0xff0c0c0c, w4, h2, width);
+
+		xoff = (width * 1.98125) / 3;
+		fillRect(raw + xoff + (y2 * width), 0xff141414, w4, h2, width);
+
+		xoff = (width * 2.196875) / 3;
+		fillRect(raw + xoff + (y2 * width), 0xff191919, w4, h2, width);
+	}
+}
+
+void draw_crosshairs(pixel *raw, int width, int height)
+{
+	if (raw) {
+		pixel fg = 0x7f000000;
+		pixel bg = 0x7f7f7f7f;
+		int x = (width + 1) / 2;
+		int y = (height + 1) / 2;
+
+		fillRect(raw + ((y - 1) * width), bg,
+			 width, 3, width);
+		fillRect(raw + (y * width), fg, width, 1, width);
+
+		fillRect(raw + ((y - 2) * width), bg,
+			 width / 3, 5, width);
+		fillRect(raw + ((y - 1) * width), fg,
+			 width / 3, 3, width);
+		fillRect(raw + ((y - 2) * width + (width * 2 / 3)), bg,
+			 width / 3, 5, width);
+		fillRect(raw + ((y - 1) * width + (width * 2 / 3)), fg,
+			 width / 3, 3, width);
+
+//
+
+		fillRect(raw + x - 1, bg,
+			 3, height, width);
+		fillRect(raw + x, fg,
+			 1, height, width);
+
+		fillRect(raw + x - 2, bg,
+			 5, height / 3, width);
+		fillRect(raw + x - 1, fg,
+			 3, height / 3, width);
+		fillRect(raw + x - 2 + ((height * 2 / 3) * width), bg,
+			 5, height / 3, width);
+		fillRect(raw + x - 1 + ((height * 2 / 3) * width), fg,
+			 3, height / 3, width);
+	}
+}
diff --git a/tools/waycheck/rough_draw.h b/tools/waycheck/rough_draw.h
new file mode 100644
index 0000000..e8317aa
--- /dev/null
+++ b/tools/waycheck/rough_draw.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ROUGH_DRAW_H_SEEN_
+#define ROUGH_DRAW_H_SEEN_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+typedef uint32_t pixel;
+
+void draw_bars(pixel *raw, int width, int height);
+
+void draw_crosshairs(pixel *raw, int width, int height);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // ROUGH_DRAW_H_SEEN_
diff --git a/tools/waycheck/waycheck.c b/tools/waycheck/waycheck.c
new file mode 100644
index 0000000..b990dde
--- /dev/null
+++ b/tools/waycheck/waycheck.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <sys/mman.h>
+
+#include <linux/input.h>
+#include <wayland-client.h>
+
+
+#include "os-compatibility.h"
+#include "rough_draw.h"
+#include "wtst_fixtures.h"
+#include "zunitc/zunitc.h"
+
+// - - - - - - - - - -
+
+/**
+ * Baseline test to see if a connection can be made to the Wayland server.
+ */
+ZUC_TEST(BaseTest, CanConnectDisplay)
+{
+	struct wl_display *display = wl_display_connect(NULL);
+
+	ZUC_EXPECT_TRUE(display != NULL);
+
+	if (display) {
+		wl_display_disconnect(display);
+		display = NULL;
+	}
+}
+
+// A very simple case that only exercises the test fixture.
+ZUC_TEST(BaseTest, HelloWayland)
+{
+	wtst_ctx *ctx = wtst_ctx_create();
+
+	ZUC_EXPECT_TRUE(ctx != NULL);
+
+	wtst_ctx_destroy(ctx);
+}
+
+ZUC_TEST(BaseTest, AdvertisesRequired)
+{
+	char const *required[] = {
+		"wl_compositor",
+		"wl_data_device_manager",
+		//wl_drm
+		//wl_input_method
+		//wl_input_panel
+		"wl_output",
+		//wl_scaler
+		"wl_seat",
+		"wl_shell",
+		"wl_shm",
+		"wl_subcompositor",
+		//wl_text_input_manager
+	};
+
+	wtst_ctx *ctx = wtst_ctx_create();
+
+	int num_required = sizeof(required) / sizeof(required[0]);
+	int i;
+	for (i = 0; i < num_required; i++) {
+		printf("Check %s\n", required[i]);
+		ZUC_EXPECT_TRUE(wtst_is_global_advertised(ctx, required[i]));
+	}
+
+	wtst_ctx_destroy(ctx);
+}
+
+
+// Forward declaration of internal testing structs:
+typedef struct _wtst_shm_pool wtst_shm_pool;
+typedef struct _wtst_pointer wtst_pointer;
+typedef struct _wtst_shell_surface wtst_shell_surface;
+typedef struct _wtst_surface wtst_surface;
+
+typedef void (*button_cb)(uint32_t serial, uint32_t time,
+			  uint32_t button, uint32_t state);
+
+// Simple testing helpers:
+static pixel *wtst_shm_pool_get_membuf(wtst_shm_pool *pool);
+static struct wl_shm_pool *wtst_shm_pool_get_pool(wtst_shm_pool *pool);
+static void wtst_shm_pool_consume(wtst_shm_pool *pool, size_t mem_used);
+static struct wl_surface *wtst_shell_surface_get_surface(wtst_shell_surface *);
+
+static wtst_shm_pool *wtst_create_mempool(struct wl_shm *shm,
+					  int fd, size_t flen);
+
+static wtst_shell_surface *wtst_create_shell_surface(struct wl_compositor *
+						     compositor,
+						     struct wl_shell *shell);
+
+static wtst_pointer *set_pointer_with_cursor(wtst_shm_pool *pool,
+					     unsigned int width,
+					     unsigned int height,
+					     int32_t hit_x, int32_t hit_y,
+					     struct wl_compositor *compositor,
+					     struct wl_pointer *pointer);
+
+static void set_button_cb(wtst_shell_surface *shell_surface,
+			  button_cb callback);
+
+//
+
+static const struct wl_pointer_listener pointer_listener;
+
+static bool keep_alive = true;
+
+static void handle_button(uint32_t serial, uint32_t time,
+			  uint32_t button, uint32_t state)
+{
+	keep_alive = false;
+}
+
+static const uint32_t PIXEL_FORMAT = WL_SHM_FORMAT_ARGB8888;
+
+
+ZUC_TEST(BaseTest, DoTheWork)
+{
+	wtst_ctx *ctx = wtst_ctx_create();
+
+	keep_alive = false; // Don't run the main loop for normal testing
+
+	// 320x200 == 4:3
+
+	// 320x180
+	// 355x200~
+	// 480x270
+	// 640x360
+	const int surf_width = 355;
+	const int surf_height = 200;
+
+	const int cursor_size = 45;
+
+	size_t needed = sizeof(pixel) * surf_width * surf_height;
+	needed += sizeof(pixel) * cursor_size * cursor_size;
+
+	int anon = os_create_anonymous_file(needed);
+	wtst_shm_pool *pool = wtst_create_mempool(ctx->shm, anon, needed);
+	struct wl_buffer *buffer = NULL;
+	if (pool) {
+		pixel *mem = wtst_shm_pool_get_membuf(pool);
+		draw_bars(mem, surf_width, surf_height);
+
+		struct wl_shm_pool *shpool =
+			wtst_shm_pool_get_pool(pool);
+		buffer = wl_shm_pool_create_buffer(shpool,
+						 0,
+						 surf_width,
+						 surf_height,
+						 surf_width * sizeof(pixel),
+						 PIXEL_FORMAT);
+		wtst_shm_pool_consume(pool,
+				      surf_width * surf_height * sizeof(pixel));
+	}
+
+	wtst_shell_surface *sh_surface =
+		wtst_create_shell_surface(ctx->compositor, ctx->shell);
+
+	if (buffer) {
+		struct wl_surface *surface =
+			wtst_shell_surface_get_surface(sh_surface);
+
+		wl_surface_attach(surface, buffer, 0, 0);
+		wl_surface_commit(surface);
+	}
+
+	int mid_hit = cursor_size / 2;
+	wtst_pointer *pointer = set_pointer_with_cursor(pool,
+							cursor_size,
+							cursor_size,
+							mid_hit, mid_hit,
+							ctx->compositor,
+							ctx->pointer);
+
+	set_button_cb(sh_surface, handle_button);
+	wl_pointer_add_listener(ctx->pointer, &pointer_listener, pointer);
+
+	while (keep_alive) {
+		if (wl_display_dispatch(ctx->display) < 0)
+			keep_alive = false;
+	}
+
+	//hello_free_buffer(buffer);
+	wl_buffer_destroy(buffer);
+	//hello_cleanup_wayland();
+
+	wtst_ctx_destroy(ctx);
+}
+
+int main( int argc, const char* argv[] )
+{
+	ZUC_ADD_TEST(BaseTest, CanConnectDisplay);
+	ZUC_ADD_TEST(BaseTest, HelloWayland);
+	ZUC_ADD_TEST(BaseTest, AdvertisesRequired);
+	ZUC_ADD_TEST(BaseTest, DoTheWork);
+
+	ZUC_RUN_TESTS();
+
+	return 0;
+}
+
+// ========================================================================
+// ========================================================================
+// ========================================================================
+// ========================================================================
+
+struct _wtst_shm_pool {
+	struct wl_shm_pool *pool;
+	//
+	int fd;
+	pixel *membuf;
+	size_t flen;
+	size_t used;
+};
+
+struct _wtst_pointer {
+	struct wl_pointer *pointer;
+	//
+	pixel *membuf;
+	struct wl_buffer *buffer;
+	struct wl_surface *surface; /**< Surface containing the image. */
+	struct wl_surface *current_surface;
+	int32_t hit_x;
+	int32_t hit_y;
+};
+
+struct _wtst_shell_surface {
+	struct wl_shell_surface *shell_surface;
+	//
+	struct wl_surface *surface; /**< surface that this is wrapping. */
+	struct wl_shell_surface_listener listener;
+};
+
+struct _wtst_surface {
+	struct wl_surface *surface;
+	//
+	button_cb button;
+};
+
+pixel *wtst_shm_pool_get_membuf(wtst_shm_pool *pool)
+{
+	return (pool) ? pool->membuf : NULL;
+}
+
+struct wl_shm_pool *wtst_shm_pool_get_pool(wtst_shm_pool *pool)
+{
+	return (pool) ? pool->pool : NULL;
+}
+
+static void wtst_shm_pool_consume(wtst_shm_pool *pool, size_t mem_used)
+{
+	if (pool)
+		pool->used += mem_used;
+}
+
+wtst_shm_pool *wtst_create_mempool(struct wl_shm *shm, int fd, size_t flen)
+{
+	wtst_shm_pool *wtst_pool = malloc(sizeof(wtst_shm_pool));
+	if (wtst_pool) {
+		memset(wtst_pool, 0, sizeof(*wtst_pool));
+		wtst_pool->fd = fd;
+		wtst_pool->flen = flen;
+		wtst_pool->membuf = mmap(NULL, flen, PROT_READ | PROT_WRITE,
+					 MAP_SHARED, fd, 0);
+		if (wtst_pool->membuf == MAP_FAILED) {
+			perror("ERROR: unable to memmap");
+		} else {
+			wtst_pool->pool = wl_shm_create_pool(shm, fd, flen);
+			if (!wtst_pool->pool) {
+				perror("ERROR: Unable to create pool");
+				munmap(wtst_pool->membuf, flen);
+			}
+		}
+
+		if (!wtst_pool->pool) {
+			free(wtst_pool);
+			wtst_pool = NULL;
+		}
+	}
+
+	return wtst_pool;
+}
+
+static void shell_surface_ping(void *data,
+			       struct wl_shell_surface *shell_surface,
+			       uint32_t serial)
+{
+    wl_shell_surface_pong(shell_surface, serial);
+}
+
+static void shell_surface_configure(void *data,
+    struct wl_shell_surface *shell_surface,
+    uint32_t edges, int32_t width, int32_t height)
+{
+}
+
+static const struct wl_shell_surface_listener
+shell_surface_listener = {
+	.ping = shell_surface_ping,
+	.configure = shell_surface_configure,
+};
+
+wtst_shell_surface *wtst_create_shell_surface(struct wl_compositor *compositor,
+					      struct wl_shell *shell)
+{
+	wtst_shell_surface *wss = malloc(sizeof(wtst_shell_surface));
+	if (wss) {
+		memset(wss, 0, sizeof(*wss));
+		wss->listener.ping = shell_surface_ping;
+		wss->listener.configure = shell_surface_configure;
+
+		wss->surface = wl_compositor_create_surface(compositor);
+	}
+
+	if (wss && wss->surface) {
+		wss->shell_surface = wl_shell_get_shell_surface(shell,
+								wss->surface);
+		if (wss->shell_surface) {
+			wl_shell_surface_add_listener(wss->shell_surface,
+						      &wss->listener,
+						      wss);
+			wl_shell_surface_set_toplevel(wss->shell_surface);
+			wl_shell_surface_set_user_data(wss->shell_surface, wss);
+			wl_surface_set_user_data(wss->surface, NULL);
+		}
+	}
+
+	if (wss && (!wss->surface || !wss->shell_surface)) {
+		if (wss->surface)
+			wl_surface_destroy(wss->surface);
+		free(wss);
+		wss = NULL;
+	}
+
+	return wss;
+}
+
+struct wl_surface *
+wtst_shell_surface_get_surface(wtst_shell_surface *sh_surface)
+{
+	return (sh_surface) ? sh_surface->surface : NULL;
+}
+
+
+void set_button_cb(wtst_shell_surface *shell_surface, button_cb callback)
+{
+	if (shell_surface && shell_surface->surface) {
+		wtst_surface *wsurf =
+			wl_surface_get_user_data(shell_surface->surface);
+		if (!wsurf) {
+			wsurf = malloc(sizeof(wtst_surface));
+			if (wsurf) {
+				memset(wsurf, 0, sizeof(*wsurf));
+				wsurf->surface = shell_surface->surface;
+				wl_surface_set_user_data(wsurf->surface,
+							 wsurf);
+			}
+		}
+
+		if (wsurf)
+			wsurf->button = callback;
+	}
+}
+
+wtst_pointer *set_pointer_with_cursor(wtst_shm_pool *pool,
+				      unsigned int width, unsigned int height,
+				      int32_t hit_x, int32_t hit_y,
+				      struct wl_compositor *compositor,
+				      struct wl_pointer *pointer)
+{
+	wtst_pointer *wtptr = malloc(sizeof(wtst_pointer));
+	if (wtptr) {
+		memset(wtptr, 0, sizeof(*wtptr));
+		wtptr->pointer = pointer;
+		wtptr->hit_x = hit_x;
+		wtptr->hit_y = hit_y;
+
+		wtptr->surface = wl_compositor_create_surface(compositor);
+		if (wtptr->surface) {
+			int32_t stride = width * sizeof(pixel);
+
+			wtptr->membuf = pool->membuf;
+			wtptr->membuf += pool->used / sizeof(*wtptr->membuf);
+			draw_crosshairs(wtptr->membuf, width, height);
+			//wtptr->membuf[0] = 0xfffc0000;
+
+			wtptr->buffer = wl_shm_pool_create_buffer(pool->pool,
+								  pool->used,
+								  width,
+								  height,
+								  stride,
+								  PIXEL_FORMAT);
+			pool->used += width * height * sizeof(pixel);
+		}
+	}
+
+	if (wtptr && wtptr->buffer) {
+		draw_crosshairs(wtptr->membuf, width, height);
+		//wtptr->membuf[0] = 0xffc00000;
+	}
+
+	if (wtptr && !wtptr->buffer) {
+		if (wtptr->surface)
+			wl_surface_destroy(wtptr->surface);
+		free(wtptr);
+		wtptr = NULL;
+	}
+
+	wl_pointer_set_user_data(pointer, wtptr);
+
+	return wtptr;
+}
+
+
+static void foo_enter(void *data,
+		      struct wl_pointer *wl_pointer,
+		      uint32_t serial, struct wl_surface *surface,
+		      wl_fixed_t surface_x, wl_fixed_t surface_y)
+{
+	wtst_pointer *pointer = (wtst_pointer *)data;
+	if (pointer) {
+		pointer->current_surface = surface;
+
+		wl_surface_attach(pointer->surface, pointer->buffer, 0, 0);
+		wl_surface_commit(pointer->surface);
+		wl_pointer_set_cursor(pointer->pointer, serial,
+				      pointer->surface,
+				      pointer->hit_x, pointer->hit_y);
+	}
+}
+
+static void foo_leave(void *data,
+		      struct wl_pointer *wl_pointer, uint32_t serial,
+		      struct wl_surface *wl_surface)
+{
+	wtst_pointer *pointer = (wtst_pointer *)data;
+	if (pointer)
+		pointer->current_surface = NULL;
+}
+
+static void foo_motion(void *data,
+			   struct wl_pointer *wl_pointer, uint32_t time,
+			   wl_fixed_t surface_x, wl_fixed_t surface_y)
+{
+}
+
+static void foo_button(void *data,
+			   struct wl_pointer *wl_pointer, uint32_t serial,
+			   uint32_t time, uint32_t button, uint32_t state)
+{
+	wtst_pointer *pointer = (wtst_pointer *)data;
+	if (pointer && pointer->current_surface) {
+		wtst_surface *wsurf =
+			wl_surface_get_user_data(pointer->current_surface);
+		if (wsurf && wsurf->button)
+			wsurf->button(serial, time, button, state);
+	}
+}
+
+static void foo_axis(void *data,
+			 struct wl_pointer *wl_pointer, uint32_t time,
+			 uint32_t axis, wl_fixed_t value)
+{
+}
+
+static const struct wl_pointer_listener pointer_listener = {
+	.enter = foo_enter,
+	.leave = foo_leave,
+	.motion = foo_motion,
+	.button = foo_button,
+	.axis = foo_axis
+};
diff --git a/tools/waycheck/waycheck.dox b/tools/waycheck/waycheck.dox
new file mode 100644
index 0000000..66ae65b
--- /dev/null
+++ b/tools/waycheck/waycheck.dox
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ at page waycheck
+
+A simple integration/acceptance tool to exercise Wayland compositors.
+
+Tests use @ref zunitc for their infrastructure, and most include use of a common wtst_ctx test fixture.
+*/
\ No newline at end of file
diff --git a/tools/waycheck/wtst_fixtures.c b/tools/waycheck/wtst_fixtures.c
new file mode 100644
index 0000000..832818b
--- /dev/null
+++ b/tools/waycheck/wtst_fixtures.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "wtst_fixtures.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wayland-client.h>
+
+typedef struct wtst_advertised {
+	uint32_t name;
+	char *interface;
+	uint32_t version;
+	//
+	struct wtst_advertised *next;
+} wtst_advertised;
+
+struct wtst_ctx_private {
+	int val;
+	wtst_advertised *adverts;
+};
+
+static void reg_global(void *data,
+		       struct wl_registry *registry,
+		       uint32_t name,
+		       const char *interface,
+		       uint32_t version);
+
+static void reg_global_remove(void *data,
+			      struct wl_registry *registry,
+			      uint32_t name);
+
+static void add_global_advert(wtst_ctx *ctx,
+			      uint32_t name,
+			      const char *interface,
+			      uint32_t version);
+
+static wtst_ctx_private *wtst_ctx_private_create(void);
+
+static void wtst_ctx_private_destroy(wtst_ctx_private *private);
+
+static int logle = 0;
+
+
+wtst_ctx *wtst_ctx_create(void)
+{
+	wtst_ctx *ctx = malloc(sizeof(*ctx));
+	if (!ctx) {
+		perror("Unable to allocate context.");
+	} else {
+		memset(ctx, 0, sizeof(*ctx));
+		ctx->reg_listener = malloc(sizeof(*(ctx->reg_listener)));
+		memset(ctx->reg_listener, 0, sizeof(*(ctx->reg_listener)));
+
+		ctx->display = wl_display_connect(NULL);
+		if (!ctx->display) {
+			perror("Unable to connect to display");
+			free(ctx);
+			ctx = NULL;
+		} else {
+			ctx->private = wtst_ctx_private_create();
+
+			ctx->registry = wl_display_get_registry(ctx->display);
+
+			ctx->reg_listener->global = reg_global;
+			ctx->reg_listener->global_remove = reg_global_remove;
+
+			wl_registry_add_listener(ctx->registry,
+						 ctx->reg_listener,
+						 ctx);
+			wl_display_sync(ctx->display);
+			wl_display_roundtrip(ctx->display);
+		}
+	}
+
+	return ctx;
+}
+
+void wtst_ctx_destroy(wtst_ctx *ctx)
+{
+	if (ctx) {
+		if (ctx->registry)
+			wl_registry_destroy(ctx->registry);
+		if (ctx->reg_listener)
+			free(ctx->reg_listener);
+//
+
+		if (ctx->compositor)
+			wl_compositor_destroy(ctx->compositor);
+		if (ctx->display)
+			wl_display_disconnect(ctx->display);
+		if (ctx->shm)
+			wl_shm_destroy(ctx->shm);
+		if (ctx->shell)
+			wl_shell_destroy(ctx->shell);
+		if (ctx->seat)
+			wl_seat_destroy(ctx->seat);
+		if (ctx->pointer)
+			wl_pointer_destroy(ctx->pointer);
+
+		wtst_ctx_private_destroy(ctx->private);
+
+		free(ctx);
+	}
+}
+
+wtst_ctx_private *wtst_ctx_private_create(void)
+{
+	wtst_ctx_private *private = malloc(sizeof(wtst_ctx_private));
+	if (private) {
+		memset(private, 0, sizeof(*private));
+
+		// fill in simple marker
+		private->val = 0x59;
+	}
+
+	return private;
+}
+
+void wtst_ctx_private_destroy(wtst_ctx_private *private)
+{
+	if (private) {
+		if (private->adverts) {
+			// TODO
+		}
+		free(private);
+	}
+}
+
+
+void reg_global(void *data,
+		struct wl_registry *registry,
+		uint32_t name,
+		const char *interface,
+		uint32_t version)
+{
+	struct wtst_ctx *ctx = (struct wtst_ctx *)data;
+	if (logle > 1) {
+		printf("reg_global ++: %2d   %s  v%d\n",
+		       name, interface, version);
+	}
+
+	add_global_advert(ctx, name, interface, version);
+
+	if (strcmp(interface, wl_seat_interface.name) == 0) {
+		if (ctx->seat)
+			wl_seat_destroy(ctx->seat);
+		ctx->seat = wl_registry_bind(registry,
+					    name,
+					    &wl_seat_interface,
+					    version);
+		ctx->seat_name = name;
+
+		ctx->pointer = wl_seat_get_pointer(ctx->seat);
+
+	} else if (strcmp(interface, wl_compositor_interface.name) == 0) {
+		if (ctx->compositor)
+			wl_compositor_destroy(ctx->compositor);
+		ctx->compositor = wl_registry_bind(registry,
+						   name,
+						   &wl_compositor_interface,
+						   version);
+		ctx->compositor_name = name;
+	} else if (strcmp(interface, wl_shm_interface.name) == 0) {
+		if (ctx->shm)
+			wl_shm_destroy(ctx->shm);
+		ctx->shm = wl_registry_bind(registry,
+					    name,
+					    &wl_shm_interface,
+					    version);
+		ctx->shm_name = name;
+	} else if (strcmp(interface, wl_shell_interface.name) == 0) {
+		if (ctx->shell)
+			wl_shell_destroy(ctx->shell);
+		ctx->shell = wl_registry_bind(registry,
+					      name,
+					      &wl_shell_interface,
+					      version);
+		ctx->shell_name = name;
+	}
+}
+
+void reg_global_remove(void *data,
+		       struct wl_registry *registry,
+		       uint32_t name)
+{
+	struct wtst_ctx *ctx = (struct wtst_ctx *)data;
+	if (logle > 1)
+		printf("reg_global --: %2d\n", name);
+	// TODO remove item from ctx list
+	if (name == ctx->seat_name) {
+		if (ctx->seat)
+			wl_seat_destroy(ctx->seat);
+		ctx->seat = NULL;
+		ctx->seat_name = 0;
+
+		wl_pointer_destroy(ctx->pointer);
+		ctx->pointer = 0;
+	} else if (name == ctx->compositor_name) {
+		if (ctx->compositor)
+			wl_compositor_destroy(ctx->compositor);
+		ctx->compositor = NULL;
+		ctx->compositor_name = 0;
+	} else if (name == ctx->shm_name) {
+		if (ctx->shm)
+			wl_shm_destroy(ctx->shm);
+		ctx->shm = NULL;
+		ctx->shm_name = 0;
+	} else if (name == ctx->shell_name) {
+		if (ctx->shell)
+			wl_shell_destroy(ctx->shell);
+		ctx->shell = NULL;
+		ctx->shell_name = 0;
+	}
+}
+
+// --
+
+void add_global_advert(wtst_ctx *ctx,
+		       uint32_t name,
+		       const char *interface,
+		       uint32_t version)
+{
+	if (ctx && ctx->private) {
+		// See if we've got this interface already
+		wtst_advertised *curr;
+		for (curr = ctx->private->adverts; curr; curr = curr->next) {
+			if (strcmp(curr->interface, interface) == 0)
+				break;
+		}
+
+		if (curr) {
+			// Update these in case they have changed.
+			curr->name = name;
+			curr->version = version;
+		} else {
+			// create a new one
+			wtst_advertised *advert =
+				malloc(sizeof(wtst_advertised));
+			memset(advert, 0, sizeof(*advert));
+			advert->name = name;
+			advert->interface = strdup(interface);
+			advert->version = version;
+			curr = ctx->private->adverts;
+			while (curr && curr->next) {
+				curr = curr->next;
+			}
+			if (curr)
+				curr->next = advert;
+			else
+				ctx->private->adverts = advert;
+		}
+	}
+}
+
+int wtst_is_global_advertised(wtst_ctx *ctx, char const *interface)
+{
+	int found = 0;
+	if (ctx && ctx->private && interface) {
+		wtst_advertised *curr = ctx->private->adverts;
+		while (curr && strcmp(interface, curr->interface)) {
+			curr = curr->next;
+		}
+		found = curr != NULL;
+	}
+	return found;
+}
diff --git a/tools/waycheck/wtst_fixtures.h b/tools/waycheck/wtst_fixtures.h
new file mode 100644
index 0000000..bfffb9d
--- /dev/null
+++ b/tools/waycheck/wtst_fixtures.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef WTST_FIXTURES_H
+#define WTST_FIXTURES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file
+ * Common helpers for Wayland tests.
+ */
+
+#include <stdint.h>
+
+/**
+ * Mapping of the public fixture struct.
+ */
+typedef struct wtst_ctx wtst_ctx;
+
+/**
+ * Mapping of the private fixture struct.
+ */
+typedef struct wtst_ctx_private wtst_ctx_private;
+
+//
+
+/**
+ * Test fixture that holds the basics for simple Wayland client testing.
+ *
+ * @see wtst_ctx_create()
+ * @see wtst_ctx_destroy()
+ */
+struct wtst_ctx
+{
+	/** The display the client is connected to. */
+	struct wl_display *display;
+
+	//
+	/** The registry the client is connected to. */
+	struct wl_registry *registry;
+
+	//
+
+	/** Main compositor as advertised and updated by the registry. */
+	struct wl_compositor *compositor;
+
+	/** Current main compositor name advertised by the registry. */
+	uint32_t compositor_name;
+
+	/**
+	 * Main shared memory object as advertised and updated by the
+	 * registry.
+	 */
+	struct wl_shm *shm;
+
+	/** Current shared memory object name advertised by the registry. */
+	uint32_t shm_name;
+
+	/** Main shell as advertised and updated by the registry. */
+	struct wl_shell *shell;
+
+	/** Current shell name advertised by the registry. */
+	uint32_t shell_name;
+
+	/** Main seat as advertised and updated by the registry. */
+	struct wl_seat *seat;
+
+	/** Current seat name advertised by the registry. */
+	uint32_t seat_name;
+
+	//
+
+	/** Pointer from the current seat. @see seat */
+	struct wl_pointer *pointer;
+
+	//
+
+	/** Listener registered with the registry. */
+	struct wl_registry_listener *reg_listener;
+
+	//
+
+	/** Context for internal implementation details. */
+	wtst_ctx_private *private;
+};
+
+//
+
+/**
+ * Creates an instance of the test fixture.
+ *
+ * @return a pointer to a test fixture upon success, NULL otherwise.
+ * @see wtst_ctx_destroy()
+ */
+wtst_ctx *wtst_ctx_create(void);
+
+/**
+ * Destroys a test fixture.
+ *
+ * @param ctx pointer to a test fixture to destroy.
+ * It should have previously been created via wtst_ctx_create().
+ * @see wtst_ctx_create()
+ */
+void wtst_ctx_destroy(wtst_ctx *ctx);
+
+/**
+ * Determines of an interface has been advertized by the Wayland registry
+ * as being present.
+ *
+ * @param ctx the test fixture in use.
+ * @param interface the name of the interface to query.
+ * @return true if the interface is supported, false otherwise.
+ */
+int wtst_is_global_advertised(wtst_ctx *ctx, char const *interface);
+
+//
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // WTST_FIXTURES_H
diff --git a/tools/zunitc/doc/zunitc.dox b/tools/zunitc/doc/zunitc.dox
new file mode 100644
index 0000000..dab03b6
--- /dev/null
+++ b/tools/zunitc/doc/zunitc.dox
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ at page zunitc zunitc
+
+A simple test framework in plain C suitable for basic unit and integration testing.
+
+The main rationale for creating this framework was to have a simple to use testing
+framework with tests implemented in C using common patterns and under a
+compatible license. The structure of the test code and macro use is intended to
+follow common patterns established by frameworks such as Boost Test and Google Test.
+
+
+To get started, one or more tests should be defined via ZUC_TEST(), which sets up
+automatic test registration via gcc extensions. To actually execute tests,
+ZUC_RUN_TESTS() should be called.
+
+
+Tests can use several ZUC_EXPECT_* or ZUC_ASSERT_* checks to validate
+conditions. The ZUC_EXPECT_* ones upon failure will mark the current test
+as failing, but allow execution to continue. On the other hand, the
+ZUC_ASSERT_* tests will mark the current test as failed and then immediately
+terminate the test.
+
+The set of non-fatal test checks are
+
+- ZUC_EXPECT_TRUE()
+- ZUC_EXPECT_FALSE()
+- ZUC_EXPECT_EQ()
+- ZUC_EXPECT_NE()
+- ZUC_EXPECT_LT()
+- ZUC_EXPECT_LE()
+- ZUC_EXPECT_GT()
+- ZUC_EXPECT_GE()
+
+The set of fatal test checks are
+
+- ZUC_ASSERT_TRUE()
+- ZUC_ASSERT_FALSE()
+- ZUC_ASSERT_EQ()
+- ZUC_ASSERT_NE()
+- ZUC_ASSERT_LT()
+- ZUC_ASSERT_LE()
+- ZUC_ASSERT_GT()
+- ZUC_ASSERT_GE()
+
+*/
diff --git a/tools/zunitc/inc/zunitc/zunitc.h b/tools/zunitc/inc/zunitc/zunitc.h
new file mode 100644
index 0000000..9d033cd
--- /dev/null
+++ b/tools/zunitc/inc/zunitc/zunitc.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef Z_UNIT_C_H_SEEN_
+#define Z_UNIT_C_H_SEEN_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file
+ * Simple unit test framework declarations.
+ */
+
+#include "zunitc/zunitc_impl.h"
+
+/**
+ * Adds a test to the list of those to be run.
+ * @param tcase the name for the test case to group this test under.
+ * @param test the name of this specific test.
+ */
+#define ZUC_ADD_TEST(tcase, test) \
+	zucimpl_add_test(zuctest_##tcase##_##test, #tcase, #test)
+
+/**
+ * Runs all tests that have been registered.
+ */
+#define ZUC_RUN_TESTS() \
+	zucimpl_run_tests()
+
+/**
+ * Defines a test case that can be registered to run.
+ */
+#define ZUC_TEST(tcase, test) \
+	static void zuctest_##tcase##_##test(void)
+
+//#define ZUC_TEST_F(tcase, test) static void zuctest_##tcase##_##test(void)
+
+
+/**
+ * Verfies that the specified expression is true and marks the test as failed
+ * if it is not.
+ *
+ * @param condition the expression that is expected to be true.
+ * @note it is far better to use a more specific check when possible
+ * (e.g. ZUC_EXPECT_EQ(), ZUC_EXPECT_NE(), etc.)
+ */
+#define ZUC_EXPECT_TRUE(condition) \
+	zucimpl_expect_true(condition, __FILE__, __LINE__, #condition)
+
+/**
+ * Verfies that the specified expression is false and marks the test as failed
+ * if it is not.
+ *
+ * @param condition the expression that is expected to be false.
+ * @note it is far better to use a more specific check when possible
+ * (e.g. ZUC_EXPECT_EQ(), ZUC_EXPECT_NE(), etc.)
+ */
+#define ZUC_EXPECT_FALSE(condition) \
+	zucimpl_expect_false(condition, __FILE__, __LINE__, #condition)
+
+/**
+ * Verfies that the values of the specified expressions match and marks
+ * the test as failed if they do not.
+ *
+ * @param expected the value the result should hold.
+ * @param actual the actual value seen in testing.
+ */
+#define ZUC_EXPECT_EQ(expected, actual) \
+	zucimpl_expect_eq((expected), (actual), __FILE__, __LINE__, #actual)
+
+/**
+ * Verfies that the values of the specified expressions differ and marks
+ * the test as failed if they do not.
+ *
+ * @param expected the value the result should not hold.
+ * @param actual the actual value seen in testing.
+ */
+#define ZUC_EXPECT_NE(expected, actual) \
+	zucimpl_expect_ne((expected), (actual), __FILE__, __LINE__, #actual)
+
+/**
+ * Verifies that the value of the first expression is less than the value
+ * of the second expression and marks the test as failed if it is not.
+ *
+ * @param lhs the expression whose value should be lesser than the other.
+ * @param rhs the expression whose value should be greater than the other.
+ */
+#define ZUC_EXPECT_LT(lhs, rhs) \
+	zucimpl_expect_lt((lhs), (rhs), __FILE__, __LINE__, #lhs, #rhs)
+
+/**
+ * Verifies that the value of the first expression is less than or equal
+ * to the value of the second expression and marks the test as failed if
+ * it is not.
+ *
+ * @param lhs the expression whose value should be lesser than or equal to
+ * the other.
+ * @param rhs the expression whose value should be greater than or equal to
+ * the other.
+ */
+#define ZUC_EXPECT_LE(lhs, rhs) \
+	zucimpl_expect_le((lhs), (rhs), __FILE__, __LINE__, #lhs, #rhs)
+
+/**
+ * Verifies that the value of the first expression is greater than the
+ * value of the second expression and marks the test as failed if it is not.
+ *
+ * @param lhs the expression whose value should be greater than the other.
+ * @param rhs the expression whose value should be lesser than the other.
+ */
+#define ZUC_EXPECT_GT(lhs, rhs) \
+	zucimpl_expect_gt((lhs), (rhs), __FILE__, __LINE__, #lhs, #rhs)
+
+/**
+ * Verifies that the value of the first expression is greater than or equal
+ * to the value of the second expression and marks the test as failed if
+ * it is not.
+ *
+ * @param lhs the expression whose value should be greater than or equal to
+ * the other.
+ * @param rhs the expression whose value should be lesser than or equal to
+ * the other.
+ */
+#define ZUC_EXPECT_GE(lhs, rhs) \
+	zucimpl_expect_ge((lhs), (rhs), __FILE__, __LINE__, #lhs, #rhs)
+
+
+
+/**
+ * Verfies that the specified expression is true, marks the test as failed
+ * and terminates the test if it is not.
+ *
+ * @param condition the expression that is expected to be true.
+ * @note it is far better to use a more specific check when possible
+ * (e.g. ZUC_EXPECT_EQ(), ZUC_EXPECT_NE(), etc.)
+ */
+#define ZUC_ASSERT_TRUE(condition) \
+	do { \
+		if (zucimpl_expect_true(condition, \
+					__FILE__, __LINE__, \
+					#condition)) { \
+			return; \
+		} \
+	} \
+	while (0)
+
+/**
+ * Verfies that the specified expression is false, marks the test as
+ * failed and terminates the test if it is not.
+ *
+ * @param condition the expression that is expected to be false.
+ * @note it is far better to use a more specific check when possible
+ * (e.g. ZUC_EXPECT_EQ(), ZUC_EXPECT_NE(), etc.)
+ */
+#define ZUC_ASSERT_FALSE(condition) \
+	do { \
+		if (zucimpl_expect_false(condition, \
+					 __FILE__, __LINE__, \
+					 #condition)) { \
+			return; \
+		} \
+	} \
+	while (0)
+
+/**
+ * Verfies that the values of the specified expressions match, marks the
+ * test as failed and terminates the test if they do not.
+ *
+ * @param expected the value the result should hold.
+ * @param actual the actual value seen in testing.
+ */
+#define ZUC_ASSERT_EQ(expected, actual) \
+	do { \
+		if (zucimpl_expect_eq((expected), (actual), \
+				      __FILE__, __LINE__, \
+				      #actual)) { \
+			return; \
+		} \
+	} \
+	while (0)
+
+/**
+ * Verfies that the values of the specified expressions differ, marks the
+ * test as failed and terminates the test if they do not.
+ *
+ * @param expected the value the result should not hold.
+ * @param actual the actual value seen in testing.
+ */
+#define ZUC_ASSERT_NE(expected, actual) \
+	do { \
+		if (zucimpl_expect_ne((expected), (actual), \
+				      __FILE__, __LINE__, \
+				      #actual)) { \
+			return; \
+		} \
+	} \
+	while (0)
+
+/**
+ * Verifies that the value of the first expression is less than the value
+ * of the second expression, marks the test as failed and terminates the
+ * test if it is not.
+ *
+ * @param lhs the expression whose value should be lesser than the other.
+ * @param rhs the expression whose value should be greater than the other.
+ */
+#define ZUC_ASSERT_LT(lhs, rhs) \
+	do { \
+		if (zucimpl_expect_lt((lhs), (rhs), \
+				      __FILE__, __LINE__, \
+				      #lhs, #rhs)) { \
+			return; \
+		} \
+	} \
+	while (0)
+
+/**
+ * Verifies that the value of the first expression is less than or equal
+ * to the value of the second expression, marks the test as failed and
+ * terminates the test if it is not.
+ *
+ * @param lhs the expression whose value should be lesser than or equal to
+ * the other.
+ * @param rhs the expression whose value should be greater than or equal to
+ * the other.
+ */
+#define ZUC_ASSERT_LE(lhs, rhs) \
+	do { \
+		if (zucimpl_expect_le((lhs), (rhs), \
+				      __FILE__, __LINE__, \
+				      #lhs, #rhs)) { \
+			return; \
+		} \
+	} \
+	while (0)
+
+/**
+ * Verifies that the value of the first expression is greater than the
+ * value of the second expression, marks the test as failed and terminates
+ * the test if it is not.
+ *
+ * @param lhs the expression whose value should be greater than the other.
+ * @param rhs the expression whose value should be lesser than the other.
+ */
+#define ZUC_ASSERT_GT(lhs, rhs) \
+	do { \
+		if (zucimpl_expect_gt((lhs), (rhs), \
+				      __FILE__, __LINE__, \
+				      #lhs, #rhs)) { \
+			return; \
+		} \
+	} \
+	while (0)
+
+/**
+ * Verifies that the value of the first expression is greater than or equal
+ * to the value of the second expression, marks the test as failed and
+ * terminates the test if it is not.
+ *
+ * @param lhs the expression whose value should be greater than or equal to
+ * the other.
+ * @param rhs the expression whose value should be lesser than or equal to
+ * the other.
+ */
+#define ZUC_ASSERT_GE(lhs, rhs) \
+	do { \
+		if (zucimpl_expect_ge((lhs), (rhs), \
+				      __FILE__, __LINE__, \
+				      #lhs, #rhs)) { \
+			return; \
+		} \
+	} \
+	while (0)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // Z_UNIT_C_H_SEEN_
diff --git a/tools/zunitc/inc/zunitc/zunitc_impl.h b/tools/zunitc/inc/zunitc/zunitc_impl.h
new file mode 100644
index 0000000..8e95f24
--- /dev/null
+++ b/tools/zunitc/inc/zunitc/zunitc_impl.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef Z_UNIT_C_IMPL_H_SEEN_
+#define Z_UNIT_C_IMPL_H_SEEN_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*zucimpl_test_fn)(void);
+
+void zucimpl_add_test(zucimpl_test_fn testFn,
+		      char const *caseName, char const *testName);
+
+void zucimpl_run_tests(void);
+
+int zucimpl_testFailed(void);
+
+int zucimpl_expect_true(int condition,
+			char const *file, int line,
+			const char *valueStr);
+
+int zucimpl_expect_false(int condition,
+			 char const *file, int line,
+			 const char *valueStr);
+
+int zucimpl_expect_eq(int expected, int actual,
+		      char const *file, int line,
+		      const char *valueStr);
+
+int zucimpl_expect_ne(int expected, int actual,
+		      char const *file, int line,
+		      const char *valueStr);
+
+int zucimpl_expect_lt(int lhs, int rhs,
+		      char const *file, int line,
+		      const char *lhsStr, const char* rhsStr);
+
+int zucimpl_expect_le(int lhs, int rhs,
+		      char const *file, int line,
+		      const char *lhsStr, const char* rhsStr);
+
+int zucimpl_expect_gt(int lhs, int rhs,
+		      char const *file, int line,
+		      const char *lhsStr, const char* rhsStr);
+
+int zucimpl_expect_ge(int lhs, int rhs,
+		      char const *file, int line,
+		      const char *lhsStr, const char* rhsStr);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // Z_UNIT_C_IMPL_H_SEEN_
diff --git a/tools/zunitc/src/zunitc_impl.c b/tools/zunitc/src/zunitc_impl.c
new file mode 100644
index 0000000..2b4c8ea
--- /dev/null
+++ b/tools/zunitc/src/zunitc_impl.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+// Required #define to get clock_gettime() & strdup
+#define _POSIX_C_SOURCE 200809L
+#include <time.h>
+#include <string.h>
+
+#include <unistd.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "zunitc/zunitc_impl.h"
+#include "zunitc/zunitc.h"
+
+
+#if _POSIX_MONOTONIC_CLOCK
+static const clockid_t TARGET_TIMER = CLOCK_MONOTONIC;
+#else
+static const clockid_t TARGET_TIMER = CLOCK_REALTIME;
+#endif
+
+typedef struct ZucTest
+{
+	zucimpl_test_fn fn;
+	char *caseName;
+	char *testName;
+	int failed;
+	int disabled;
+	long elapsed;
+
+	struct ZucTest *next;
+} ZucTest;
+
+typedef struct ZucCase
+{
+	char *caseName;
+	long elapsed;
+	int testCount;
+	ZucTest *firstTest;
+
+	struct ZucCase *next;
+} ZucCase;
+
+
+static char const DISABLED_PREFIX[] = "DISABLED_";
+
+// Data structure simple, but should suffice for smaller numbers of tests.
+static int caseListCount = 0;
+static ZucCase *caseListHead = NULL;
+
+static int gBad = 0;
+
+static ZucCase *gCurrCase = NULL;
+static ZucTest *gCurrTest = NULL;
+
+
+static ZucCase *getCase(char const *caseName);
+
+static void attachTest(ZucTest *test);
+
+static void countLiveTests(int *caseCount, int *testCount, int *disabledCount);
+
+static void countLiveTestsForCase(ZucCase const *testCase,
+				  int *testCount, int *disabledCount);
+
+
+ZucCase *getCase(char const *caseName)
+{
+	ZucCase *foundCase = NULL;
+	if (caseName)
+	{
+		ZucCase *currCase;
+		for (currCase = caseListHead; currCase && !foundCase;
+		     currCase = currCase->next)
+		{
+			if (strcmp(currCase->caseName, caseName) == 0)
+			{
+				foundCase = currCase;
+			}
+		}
+	}
+	return foundCase;
+}
+
+void zucimpl_add_test(zucimpl_test_fn testFn,
+		      char const *caseName, char const *testName)
+{
+	ZucTest *test = (ZucTest *)malloc(sizeof(ZucTest));
+	if (test) {
+		memset(test, 0, sizeof(ZucTest));
+		test->fn = testFn;
+		test->caseName = strdup(caseName);
+		test->testName = strdup(testName);
+		if (!testFn ||
+		    (strncmp(DISABLED_PREFIX,
+			     testName, sizeof(DISABLED_PREFIX) - 1) == 0))
+		{
+			test->disabled = 1;
+		}
+
+		attachTest(test);
+	} else {
+		fprintf(stderr, "%s:%d: error unable to allocate memory.\n",
+			__FILE__, __LINE__);
+	}
+}
+
+void attachTest(ZucTest *test)
+{
+	if (test) {
+		ZucCase *testCase = getCase(test->caseName);
+		if (!testCase)
+		{
+			// Need to add a new case to hold the test
+			testCase = (ZucCase *)malloc(sizeof(ZucCase));
+			memset(testCase, 0, sizeof(ZucCase));
+			testCase->caseName = strdup(test->caseName);
+
+			if (caseListHead) {
+				ZucCase *curr = caseListHead;
+				while (curr && curr->next) {
+					curr = curr->next;
+				}
+				curr->next = testCase;
+			} else {
+				caseListHead = testCase;
+			}
+			caseListCount++;
+		}
+
+		if (testCase->firstTest) {
+			ZucTest *curr = testCase->firstTest;
+			while (curr && curr->next) {
+				curr = curr->next;
+			}
+			curr->next = test;
+		} else {
+			testCase->firstTest = test;
+		}
+		testCase->testCount++;
+	}
+}
+
+void zucimpl_run_tests(void)
+{
+	printf("Running tests...\n");
+
+	int liveCaseCount = 0;
+	int liveTestCount = 0;
+	int disabledCount = 0;
+	countLiveTests(&liveCaseCount, &liveTestCount, &disabledCount);
+
+	printf("[==========] Running %d %s from %d test %s.\n",
+	       liveTestCount,
+	       (liveTestCount == 1) ? "test" : "tests",
+	       liveCaseCount,
+	       (liveCaseCount == 1) ? "case" : "cases");
+
+	long totalElapsed = 0;
+	int totalPassed = 0;
+	int totalFailed = 0;
+	gBad = 0;
+	ZucCase *currCase;
+	for (currCase = caseListHead; currCase; currCase = currCase->next)
+	{
+		gCurrCase = currCase;
+
+		int countXX = 0;
+		countLiveTestsForCase(currCase, &countXX, NULL);
+		if (countXX)
+		{
+			printf("[----------] %d %s from %s.\n",
+			       countXX,
+			       (countXX == 1) ? "test" : "tests",
+			       currCase->caseName);
+
+			ZucTest *curr;
+			for (curr = currCase->firstTest; curr;
+			     curr = curr->next)
+			{
+				if (!curr->disabled)
+				{
+					gCurrTest = curr;
+					printf("[ RUN      ] %s:%s\n",
+					       curr->caseName, curr->testName);
+					struct timespec begin;
+					memset(&begin, 0, sizeof(begin));
+					clock_gettime(TARGET_TIMER, &begin);
+
+					curr->fn();
+
+					if (curr->failed)
+					{
+						totalFailed++;
+					} else {
+						totalPassed++;
+					}
+
+					struct timespec end;
+					memset(&end, 0, sizeof(end));
+					clock_gettime(TARGET_TIMER, &end);
+					// tv_sec, tv_nsec
+
+					long elapsed =
+						(end.tv_sec - begin.tv_sec)
+						* 1000L;
+					if (end.tv_sec != begin.tv_sec) {
+						elapsed -= (begin.tv_nsec)
+							/ 1000000L;
+						elapsed += (end.tv_nsec)
+							/ 1000000L;
+					} else {
+						elapsed +=
+							(end.tv_nsec
+							 - begin.tv_nsec)
+							/ 1000000L;
+					}
+					curr->elapsed = elapsed;
+					currCase->elapsed += elapsed;
+
+					if (curr->failed)
+					{
+						printf("[  FAILED  ] %s:%s (%ld ms)\n",curr->caseName, curr->testName, curr->elapsed);
+					}
+					else
+					{
+						printf("[       OK ] %s:%s (%ld ms)\n", curr->caseName, curr->testName, curr->elapsed);
+					}
+
+					gCurrTest = NULL;
+				}
+			}
+
+			totalElapsed += currCase->elapsed;
+			printf("[----------] %d %s from %s (%ld ms)\n",
+			       currCase->testCount,
+			       (currCase->testCount == 1) ? "test" : "tests",
+			       currCase->caseName,
+			       currCase->elapsed);
+			printf("\n");
+		}
+		gCurrCase = NULL;
+	}
+	printf("[==========] %d %s from %d test %s ran. (%ld ms)\n",
+	       liveTestCount,
+	       (liveTestCount == 1) ? "test" : "tests",
+	       liveCaseCount,
+	       (liveCaseCount == 1) ? "case" : "cases",
+	       totalElapsed);
+	if (totalPassed) {
+		printf("[  PASSED  ] %d %s.\n", totalPassed, (totalPassed == 1) ? "test" : "tests");
+	}
+
+	if (totalFailed) {
+		printf("[  FAILED  ] %d %s, listed below:\n",
+		       totalFailed, (totalFailed == 1) ? "test" : "tests");
+
+		for (currCase = caseListHead; currCase; currCase = currCase->next)
+		{
+			ZucTest *curr;
+			for (curr = currCase->firstTest; curr; curr = curr->next)
+			{
+				if (curr->failed) {
+					printf("[  FAILED  ] %s.%s\n", currCase->caseName, curr->testName);
+				}
+			}
+		}
+	}
+
+	if (totalFailed || disabledCount)
+	{
+		printf("\n");
+	}
+
+	if (totalFailed)
+	{
+		printf(" %d FAILED %s\n",
+		       totalFailed,
+		       (totalFailed == 1) ? "TEST" : "TESTS");
+	}
+
+	if (disabledCount)
+	{
+		printf("  YOU HAVE %d DISABLED %s\n",
+		       disabledCount,
+		       (disabledCount == 1) ? "TEST" : "TESTS");
+	}
+}
+
+int zucimpl_testFailed()
+{
+	int failed = gBad;
+	if (gCurrTest) {
+		failed = gCurrTest->failed;
+	}
+	return failed;
+}
+
+static void markFailed(void)
+{
+	gBad = 1;
+	if (gCurrTest) {
+		gCurrTest->failed = 1;
+	}
+}
+
+int zucimpl_expect_true(int condition, char const *file, int line, const char *valueStr){
+	int failed = 0;
+	if (!condition)
+	{
+		printf("%s:%d: error: Value of: %s\n", file, line, valueStr);
+		printf("  Actual: %d\n", condition);
+		printf("Expected: TRUE\n");
+		failed = 1;
+		markFailed();
+	}
+	return failed;
+}
+
+int zucimpl_expect_false(int condition, char const *file, int line, const char *valueStr)
+{
+	int failed = 0;
+	if (condition)
+	{
+		printf("%s:%d: error: Value of: %s\n", file, line, valueStr);
+		printf("  Actual: %d\n", condition);
+		printf("Expected: FALSE\n");
+		failed = 1;
+		markFailed();
+	}
+	return failed;
+}
+
+int zucimpl_expect_eq(int expected, int actual, char const *file, int line, const char *valueStr)
+{
+	int failed = 0;
+	if (expected != actual)
+	{
+		printf("%s:%d: error: Value of: %s\n", file, line, valueStr);
+		printf("  Actual: %d\n", actual);
+		printf("Expected: %d\n", expected);
+		failed = 1;
+		markFailed();
+	}
+	return failed;
+}
+
+int zucimpl_expect_ne(int expected, int actual, char const *file, int line, const char *valueStr)
+{
+	int failed = 0;
+	if (expected == actual)
+	{
+		printf("%s:%d: error: ", file, line);
+		printf("Expected: (%d) != (%s), actual %d vs %d\n", expected, valueStr, expected, actual);
+		failed = 1;
+		markFailed();
+	}
+	return failed;
+}
+
+int zucimpl_expect_lt(int lhs, int rhs, char const *file, int line, const char *lhsStr, const char* rhsStr)
+{
+	int failed = 0;
+	if (lhs >= rhs)
+	{
+		printf("%s:%d: error: ", file, line);
+		printf("Expected: (%s) < (%s), actual %d vs %d\n", lhsStr, rhsStr, lhs, rhs);
+		failed = 1;
+		markFailed();
+	}
+	return failed;
+}
+
+int zucimpl_expect_le(int lhs, int rhs, char const *file, int line, const char *lhsStr, const char* rhsStr)
+{
+	int failed = 0;
+	if (lhs > rhs)
+	{
+		printf("%s:%d: error: ", file, line);
+		printf("Expected: (%s) <= (%s), actual %d vs %d\n", lhsStr, rhsStr, lhs, rhs);
+		failed = 1;
+		markFailed();
+	}
+	return failed;
+}
+
+int zucimpl_expect_gt(int lhs, int rhs, char const *file, int line, const char *lhsStr, const char* rhsStr)
+{
+	int failed = 0;
+	if (lhs <= rhs)
+	{
+		printf("%s:%d: error: ", file, line);
+		printf("Expected: (%s) > (%s), actual %d vs %d\n", lhsStr, rhsStr, lhs, rhs);
+		failed = 1;
+		markFailed();
+	}
+	return failed;
+}
+
+int zucimpl_expect_ge(int lhs, int rhs, char const *file, int line, const char *lhsStr, const char* rhsStr)
+{
+	int failed = 0;
+	if (lhs < rhs)
+	{
+		printf("%s:%d: error: ", file, line);
+		printf("Expected: (%s) >= (%s), actual %d vs %d\n", lhsStr, rhsStr, lhs, rhs);
+		failed = 1;
+		markFailed();
+	}
+	return failed;
+}
+
+void countLiveTestsForCase(ZucCase const *testCase, int *testCount, int *disabledCount)
+{
+	int localTestCount = 0;
+	int localSkippedCount = 0;
+	ZucTest *curr;
+	for (curr = testCase->firstTest; curr; curr = curr->next)
+	{
+		if (curr->disabled)
+		{
+			localSkippedCount++;
+		}
+		else
+		{
+			localTestCount++;
+		}
+	}
+
+	if (testCount)
+	{
+		*testCount = localTestCount;
+	}
+
+	if (disabledCount)
+	{
+		*disabledCount = localSkippedCount;
+	}
+}
+
+void countLiveTests(int *caseCount, int *testCount, int *disabledCount)
+{
+	int localCaseCount = 0;
+	int localTestCount = 0;
+	int localSkippedCount = 0;
+
+	ZucCase *currCase;
+	for (currCase = caseListHead; currCase; currCase = currCase->next)
+	{
+		int liveInCase = 0;
+		int skippedInCase = 0;
+		countLiveTestsForCase(currCase, &liveInCase, &skippedInCase);
+		localSkippedCount += skippedInCase;
+		localTestCount += liveInCase;
+		if (liveInCase)
+		{
+			localCaseCount++;
+		}
+	}
+
+	if (caseCount)
+	{
+		*caseCount = localCaseCount;
+	}
+
+	if (testCount)
+	{
+		*testCount = localTestCount;
+	}
+
+	if (disabledCount)
+	{
+		*disabledCount = localSkippedCount;
+	}
+}
diff --git a/tools/zunitc/test/zunitc_test.c b/tools/zunitc/test/zunitc_test.c
new file mode 100644
index 0000000..813b72f
--- /dev/null
+++ b/tools/zunitc/test/zunitc_test.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * A simple file to show tests being setup and run.
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdio.h>
+
+
+
+#include "zunitc/zunitc.h"
+
+ZUC_TEST(BaseTest, MathIsSane)
+{
+	ZUC_EXPECT_EQ(4, 2 + 2);
+}
+
+ZUC_TEST(BaseTest, MathIsHard)
+{
+#ifdef ENABLE_FAIL_TESTS
+	ZUC_EXPECT_EQ(5, 2 + 2);
+	ZUC_EXPECT_EQ(7, 9);
+#endif
+}
+
+ZUC_TEST(BaseTest, MathIsMoreHard)
+{
+#ifdef ENABLE_FAIL_TESTS
+	ZUC_ASSERT_EQ(5, 2 + 2);
+	ZUC_ASSERT_EQ(7, 9);
+#endif
+}
+
+ZUC_TEST(OtherTest, MathMonkey)
+{
+	ZUC_EXPECT_TRUE(1);
+	ZUC_EXPECT_TRUE(3);
+	ZUC_EXPECT_FALSE(0);
+
+	ZUC_ASSERT_TRUE(1);
+	ZUC_ASSERT_TRUE(3);
+	ZUC_ASSERT_FALSE(0);
+
+	ZUC_EXPECT_EQ(5, 2 + 3);
+	ZUC_ASSERT_EQ(5, 2 + 3);
+
+	int b = 9;
+	ZUC_EXPECT_NE(1, 2);
+	ZUC_EXPECT_NE(b, b + 2);
+
+	ZUC_ASSERT_NE(1, 2);
+	ZUC_ASSERT_NE(b, b + 1);
+
+	ZUC_EXPECT_LT(1, 2);
+	ZUC_ASSERT_LT(1, 3);
+
+	ZUC_EXPECT_LE(1, 2);
+	ZUC_ASSERT_LE(1, 3);
+
+	ZUC_EXPECT_LE(1, 1);
+	ZUC_ASSERT_LE(1, 1);
+
+	ZUC_EXPECT_GT(2, 1);
+	ZUC_ASSERT_GT(3, 1);
+
+	ZUC_EXPECT_GE(1, 1);
+	ZUC_ASSERT_GE(1, 1);
+
+	ZUC_EXPECT_GE(2, 1);
+	ZUC_ASSERT_GE(3, 1);
+}
+
+int main( int argc, const char* argv[] )
+{
+	ZUC_ADD_TEST(BaseTest, MathIsSane);
+	ZUC_ADD_TEST(BaseTest, MathIsHard);
+	ZUC_ADD_TEST(BaseTest, MathIsMoreHard);
+	ZUC_ADD_TEST(OtherTest, MathMonkey);
+
+	ZUC_RUN_TESTS();
+
+	return 0;
+}
-- 
2.1.0



More information about the wayland-devel mailing list