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

Bryce Harrington bryce at osg.samsung.com
Fri May 29 16:24:07 PDT 2015


On Fri, May 29, 2015 at 03:33:59PM -0700, Bryce Harrington wrote:
> On Tue, May 05, 2015 at 03:50:22PM -0700, Jon A. Cruz wrote:
> > 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>
> 
> This is a review I started last week (took me a while since this is such
> a huge patch), and you've since posted a v3 so don't know how relevant
> any of this commentary still is.

I do have a couple questions, that I didn't figure out from studying
your code:

First, is this intended to handle client-style tests?  E.g. is this
supposed to replace the weston-tests-env bash script?  If so, how do
weston test server instances get set up?

Second, the current autoconf-based test suite causes test output to be
logged in the root directory, so some test results will be there, the
rest under logs.  Will this enable us to keep all the test output files
together in one place?

Bryce

> > ---
> >  .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
> 
> Wayland puts documentation (and the doxygen config file) under
> wayland/doc/doxygen/ .  While we don't have a doc/ subdir for weston, I
> think for consistency we should, and this tool documentation should move
> there.
> 
> Wayland names the config file wayland.doxygen, so a similar file naming
> scheme would be sensible here (or else change Wayland's file name style
> to match, if people file this name more conventional.)
> 
> Wayland also takes the approach of using the stock config file generated
> by doxygen -g, IIRC, and then at run time cat it and concatenate
> project-specific non-default parameter settings.  See the Makefile.am
> for the doc stuff.  If possible I'd suggest following a similar approach
> to keep things consistent.  That approach also makes it relatively easy
> to see what non-default settings are in use.
> 
> If you roll another patchset, you could put the stock defaults Doxygen
> config file (and any other boilerplate-ish bits) in a separate patch, as
> they'll not need as close of review.
> 
> > @@ -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
> 
> Do these need copyright boilerplate?  (If the minimal dox files above
> need them, figure it's worth asking...)
> 
> > @@ -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";
> 
> The above have assumptions of where the tool is being run from.  Make
> sure to check this with parallel build and against distcheck.  Those
> have flagged path issues with stuff before.
> 
> > +	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 config.h?
> 
> > +#include <stddef.h>
> > +
> > +#include "rough_draw.h"
> > +
> > +static void fillRect(pixel *raw, pixel val, int width, int height, int stride)
> 
> Wayland/Weston code style puts the return type on a separate line ahead
> of the function name.
> 
> > +{
> > +	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;
> > +		}
> > +	}
> > +}
> 
> memset?
> 
> > +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)
> 
> Wayland style is not to use camel case.
> 
> > +{
> > +	int x = 0;
> > +	int y = 0;
> > +
> > +	double dwidth = (double)width;
> > +	for (x = 0; x < width; ++x) {
> 
> nitpick, but I'd put a linebreak before the for, and none before the
> dwidth decl.
> 
> > +		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)
> 
> doxygen comments for this function would be nice.
> 
> > +{
> > +	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:
> 
> No C++ comments.  (I know... but I got dinged for using them.)
> 
> I notice you use these throughout the patchset; they'll all need changed
> to C style comments.
> 
> > +		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;
> 
> I believe Wayland likes type definitions to be up at top.  If we're
> allowing it to be mid-function, then some of the rest of this patch
> would benefit from it (e.g. the iter vars of for loops).
> 
> > +		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)
> 
> i is set to 0 twice here.
> 
> > +		{
> > +			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);
> > +
> 
> Sorry for another useless nitpick, but I typically prefer to use
> #defines for the colors, so I can group the definitions in one place if
> I want to tweak the color palette later.
> 
> > +
> > +		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;
> > +	}
> > +}
> 
> Are these just example tests to go with the harness, or do they actually
> need to get run?  If the latter, maybe they should move to tests/?
> 
> > +// 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]);
> 
> I think there's an ARRAY_SIZE() macro to do this.
> 
> > +	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)
> 
> 'DoTheWork' seems not very descriptive...  CommunicateWithServer would
> be more descriptive but maybe there's something better.
> 
> > +{
> > +	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);
> 
> Check 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();
> 
> stray bits?
> 
> > +	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) {
> 
> Maybe just return early here if it's null?
> 
> 	if (wtst_pool == NULL)
> 		return NULL;
> 
> > +		memset(wtst_pool, 0, sizeof(*wtst_pool));
> 
> Since you're malloc'ing and memset'ing this to 0, it would be better to
> just use calloc instead of malloc.  That should simplify this logic, and
> in some circumstances calloc can run faster.
> 
> > +		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");
> 
> s/memmap/mmap/
> 
> Also, may as well free wtst_pool and return NULL at this point; all the
> following logic will be short circuited anyway.
> 
> > +		} 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));
> 
> Looks like if wss is NULL, none of the following logic is carried out,
> so why not just check it and return NULL directly here.  That would
> simplify the conditionals.
> 
> > +	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;
> > +}
> 
> There's a common C idiom (not sure what the proper name of it is; it's
> fills the role of a destructor), which uses a goto statement to jump to
> cleanup code.  E.g.
> 
> if (wss->surface == NULL)
> 	goto error;
> 
> /* ... */
> return wss;
> 
> error:
> 	if (wss->surface)
> 		wl_surface_destroy(wss->surface);
> 	free(wss);
> 	return NULL;
> 
> > +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));
> 
> Use calloc
> 
> > +		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
> > +};
> 
> s/foo/example_test/g
> 
> > 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 config.h
> 
> > +#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;
> 
> log_level ?
> 
> > +
> > +wtst_ctx *wtst_ctx_create(void)
> > +{
> > +	wtst_ctx *ctx = malloc(sizeof(*ctx));
> > +	if (!ctx) {
> > +		perror("Unable to allocate context.");
> 
> return NULL here, and avoid the indent for the else clause
> 
> > +	} else {
> > +		memset(ctx, 0, sizeof(*ctx));
> 
> calloc
> 
> > +		ctx->reg_listener = malloc(sizeof(*(ctx->reg_listener)));
> > +		memset(ctx->reg_listener, 0, sizeof(*(ctx->reg_listener)));
> 
> calloc
> 
> > +		ctx->display = wl_display_connect(NULL);
> > +		if (!ctx->display) {
> > +			perror("Unable to connect to display");
> > +			free(ctx);
> > +			ctx = NULL;
> 
> return NULL here, and avoid the indent for the else clause
> 
> > +		} 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) {
> 
> Just do:
> 
> if (!ctx)
> 	return;
> 
> > +		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));
> 
> calloc
> 
> > +		// 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));
> 
> calloc
> 
> > +			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;
> > +
> > +	//
> 
> There are empty C++ comments like the above scattered around; is that
> just stray leftovers, or are they intended as organizational separators?
> In either case, they need removed or changed.
> 
> > +	/** 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.
> 
> That'll be a handy feature.
> 
> > +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()
> 
> Since there are tests for explicit values true and false, would it make
> sense to have one for specific value NULL?
> 
> > +*/
> > 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)
> 
> stray?
> 
> > +
> > +/**
> > + * 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.
> > + */
> > +
> 
> include config.h
> 
> > +// 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));
> 
> calloc
> 
> > +		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));
> calloc
> 
> > +			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);
> > +					}
> 
> Since all the other args are the same in both cases, maybe just mush it together:
> 
> 					printf("[ %-8s] %s:%s (%ld ms)\n", (curr->failed)?"OK":"FAILED", 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);
> 
> You can probably condense the following code by eliminating brackets.
> 
> > +	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);
> > +				}
> > +			}
> > +		}
> > +	}
> 
> Brackets are unnecessary for the following three if statements:
> 
> > +	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;
> > +}
> 
> No need for failed var:
> 
> int zucimpl_testFailed()
> {
> 	if (gCurrTest)
> 		return gCurrTest->failed;
> 	return gBad;
> }
> 
> Similarly through the following routines; just return 0 or 1 when the
> failure status is determined.
> 
> If you don't like this approach, and want to retained a status variable
> returned at function end, that's fine but maybe call it 'has_failed' or
> even just 'status'.  I have to think a moment to realize "failed == 0"
> means non-failing.
> 
> > +
> > +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);
> 
> Your results output format differs for this and following functions
> compared with the above.
> 
> Also, makes me wonder if it's worth moving the printfs to a common
> helper function to better enforce consistency?
> 
> > +		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
> > 
> > _______________________________________________
> > wayland-devel mailing list
> > wayland-devel at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/wayland-devel
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list