Created SConscripts for the C and C++ unit tests.
authorDoug Hudson <douglas.hudson@intel.com>
Fri, 13 Feb 2015 23:19:57 +0000 (18:19 -0500)
committerSashi Penta <sashi.kumar.penta@intel.com>
Wed, 18 Feb 2015 16:11:36 +0000 (16:11 +0000)
This change included making mods to <src_dir>/resource/SConscript to:

-call the C and C++ unit test SConscripts

-ensure that the Google Unit Test library and Hippo Mocking
library were installed in <src_dir>/extlibs.

Also made a mod to ocstack.c/OCInit( ) to check for invalid mode parameter
and to stacktests.cpp to change OCDoResource signature for CA.

Change-Id: I290d04a876de8c99076e71827d91b5216ffaf29e
Signed-off-by: Doug Hudson <douglas.hudson@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/292
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Sudarshan Prasad <sudarshan.prasad@intel.com>
Reviewed-by: Sashi Penta <sashi.kumar.penta@intel.com>
13 files changed:
build_common/SConscript
build_common/external_libs.scons [new file with mode: 0644]
build_common/tools/UnpackAll.py [new file with mode: 0644]
extlibs/gtest/SConscript [new file with mode: 0644]
extlibs/hippomocks.scons [new file with mode: 0644]
resource/SConscript
resource/csdk/stack/src/ocstack.c
resource/csdk/stack/test/README
resource/csdk/stack/test/SConscript [new file with mode: 0644]
resource/csdk/stack/test/stacktests.cpp
resource/unit_tests.scons [new file with mode: 0644]
resource/unittests/README
resource/unittests/SConscript [new file with mode: 0644]

index 9443d47..a77869a 100644 (file)
@@ -235,6 +235,8 @@ else:
     else:
                env.SConscript(target_os + '/SConscript')
 
+env.SConscript('external_libs.scons')
+
 # Delete the temp files of configuration
 if env.GetOption('clean'):
        dir = env.get('SRC_DIR')
diff --git a/build_common/external_libs.scons b/build_common/external_libs.scons
new file mode 100644 (file)
index 0000000..44994d5
--- /dev/null
@@ -0,0 +1,128 @@
+##
+# This script manages external libraries
+#
+# Some methods are added to manage external packages:
+#    'PrepareLib': Checks the existence of an external library, if it
+# doesn't exist, calls the script user provided to download(if required)
+# and build the source code of the external library or notify user to
+# install the library.
+#   'Download': Download package from specify URL
+#   'UnpackAll': Unpack the package
+#   'Configure': Execute specify script(configure, bootstrap etc)
+#   'InstallHeadFile': Install head files
+#   'InstallLib': Install library binaries(.so, .a etc)
+#
+# By default, assume the script for an exteranl library is:
+#    <src_dir>/extlibs/<libname>/SConscript
+#
+# Note: After the external library is built:
+#   Head files should be installed to <src_dir>/deps/<target_os>/include
+#   lib(e.g .so, .a) should be installed to <src_dir>/deps/<target_os>/lib/<arch>
+#
+##
+import os, subprocess
+import urllib2, urlparse
+import SCons.Errors
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+target_arch = env.get('TARGET_ARCH')
+
+# for android, doesn't distinguish 'armeabi-v7a-hard' and 'armeabi-v7a' library
+if target_os == 'android':
+       if target_arch == 'armeabi-v7a-hard':
+               target_arch = 'armeabi-v7a'
+
+if target_os == 'darwin':
+       env.AppendUnique(CPPPATH = ['/usr/local/include'])
+       env.AppendUnique(LIBPATH = ['/usr/local/lib'])
+
+# External library include files are in <src_dir>/deps/<target_os>/include
+# the library binaries are in <src_dir>/deps/<target_os>/lib/<arch>
+env.AppendUnique(CPPPATH = [env.get('SRC_DIR') + '/deps/' + target_os + '/include'])
+env.AppendUnique(LIBPATH = [env.get('SRC_DIR') + '/deps/' + target_os + '/lib/' + target_arch])
+
+# Check whether a library exists, if not, notify user to install it or try to
+# download the source code and build it
+# @param libname - the name of the library try to prepare
+# @param lib - the lib(.so, .a etc) to check (a library may include more then
+#      one lib, e.g. boost, includes boost_thread, boost_system ...
+# @param path - the directory of the library building script, if it's not set,
+#                      by default, it's <src_dir>/extlibs/<libname>/
+# @param script - the building script, by default, it's 'SConscript'
+#
+def __prepare_lib(ienv, libname, lib = None, path = None, script = None):
+       p_env = ienv.Clone()
+       if p_env.GetOption('clean') or p_env.GetOption('help'):
+               return
+
+       conf = Configure(p_env)
+
+       if not lib:
+               lib = libname
+       if not conf.CheckLib(lib):
+               if path:
+                       dir = path
+               else:
+                       dir = env.get('SRC_DIR') + '/extlibs/' + libname
+
+               # Execute the script to download(if required) and build source code
+               if script:
+                       st = dir + '/' + script
+               else:
+                       st = dir + '/SConscript'
+
+               if os.path.exists(st):
+                       SConscript(st)
+               else:
+                       if target_os in ['linux', 'darwin', 'tizen']:
+                               print 'Don\'t find library(%s), please intall it, exit ...' % libname
+                       else:
+                               print 'Don\'t find library(%s) and don\'t find the process script (%s), exit ...' % (libname, st)
+                       Exit(1)
+
+       conf.Finish()
+
+# Run configure command (usually it's done before build a library)
+def __configure(env, cwd, cmd) :
+       print "Configuring using [%s/%s] ..." % (cwd, cmd)
+       # build it now (we need the shell, because some programs need it)
+       devnull = open(os.devnull, "wb")
+       handle  = subprocess.Popen(cmd, shell=True, cwd=cwd, stdout=devnull)
+
+       if handle.wait() <> 0 :
+               raise SCons.Errors.BuildError( "Run configuring script [%s]" % (cmd) )
+
+# Download from URL 'url', will save as 'target'
+def __download(ienv, target, url) :
+       if os.path.exists(target) :
+               return target
+
+       try :
+               print "Download %s from %s" % (target, url)
+               print "Downloading ..."
+               stream = urllib2.urlopen(url)
+               file = open(target, 'wb')
+               file.write(stream.read())
+               file.close()
+               print "Download %s from %s complete" % (target, url)
+               return target
+       except Exception, e :
+               raise SCons.Errors.StopError( '%s [%s]' % (e, url) )
+
+# Install header file(s) to <src_dir>/deps/<target_os>/include
+def __install_head_file(ienv, file):
+               return ienv.Install(env.get('SRC_DIR') + '/deps/' + target_os + '/include', file)
+
+# Install library binaries to <src_dir>/deps/<target_os>/lib/<arch>
+def __install_lib(ienv, lib):
+               return ienv.Install(env.get('SRC_DIR') + '/deps/' + target_os + '/lib/' + target_arch, lib)
+
+SConscript('tools/UnpackAll.py')
+
+env.AddMethod(__prepare_lib, "PrepareLib")
+env.AddMethod(__configure, "Configure")
+env.AddMethod(__download, "Download")
+env.AddMethod(__install_head_file, "InstallHeadFile")
+env.AddMethod(__install_lib, "InstallLib")
diff --git a/build_common/tools/UnpackAll.py b/build_common/tools/UnpackAll.py
new file mode 100644 (file)
index 0000000..4e24c58
--- /dev/null
@@ -0,0 +1,408 @@
+# -*- coding: utf-8 -*-
+
+############################################################################
+# GPL License                                                              #
+#                                                                          #
+# This file is a SCons (http://www.scons.org/) builder                     #
+# Copyright (c) 2012-14, Philipp Kraus, <philipp.kraus@flashpixx.de>       #
+# Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.     #
+# This program is free software: you can redistribute it and/or modify     #
+# it under the terms of the GNU General Public License as                  #
+# published by the Free Software Foundation, either version 3 of the       #
+# License, or (at your option) any later version.                          #
+#                                                                          #
+# This program is distributed in the hope that it will be useful,          #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of           #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            #
+# GNU General Public License for more details.                             #
+#                                                                          #
+# You should have received a copy of the GNU General Public License        #
+# along with this program. If not, see <http://www.gnu.org/licenses/>.     #
+############################################################################
+
+# This builder originated from work by Philipp Kraus and flashpixx project
+# (see https://github.com/flashpixx). Based on the Unpack.py, it only
+# contains changes to allow a complete unpacking of the archive.
+# It is assumed that the target represents a file in the archive after it
+# is unpacked.
+
+# The Unpack Builder can be used for unpacking archives (eg Zip, TGZ, BZ, ... ).
+# The emitter of the Builder reads the archive data and creates a returning
+# file list the builder extract the archive. The environment variable
+# stores a dictionary "UNPACK" for set different extractions (subdict "EXTRACTOR"):
+# {
+#   PRIORITY         => a value for setting the extractor order (lower numbers = extractor is used earlier)
+#   SUFFIX           => defines a list with file suffixes, which should be handled with this extractor
+#   EXTRACTSUFFIX    => suffix of the extract command
+#   EXTRACTFLAGS     => a string parameter for the RUN command for extracting the data
+#   EXTRACTCMD       => full extract command of the builder
+#   RUN              => the main program which will be started (if the parameter is empty, the extractor will be ignored)
+#   LISTCMD          => the listing command for the emitter
+#   LISTFLAGS        => the string options for the RUN command for showing a list of files
+#   LISTSUFFIX       => suffix of the list command
+#   LISTEXTRACTOR    => a optional Python function, that is called on each output line of the
+#                       LISTCMD for extracting file & dir names, the function need two parameters (first line number,
+#                       second line content) and must return a string with the file / dir path (other value types
+#                       will be ignored)
+# }
+# Other options in the UNPACK dictionary are:
+#   STOPONEMPTYFILE  => bool variable for stoping if the file has empty size (default True)
+#   VIWEXTRACTOUTPUT => shows the output messages of the extraction command (default False)
+#   EXTRACTDIR       => path in that the data will be extracted (default #)
+#
+# The file which is handled by the first suffix match of the extractor, the extractor list can be append for other files.
+# The order of the extractor dictionary creates the listing & extractor command eg file extension .tar.gz should be
+# before .gz, because the tar.gz is extract in one shoot.
+#
+# Under *nix system these tools are supported: tar, bzip2, gzip, unzip
+# Under Windows only 7-Zip (http://www.7-zip.org/) is supported
+
+
+import subprocess, os
+import SCons.Errors, SCons.Warnings, SCons.Util
+
+# enables Scons warning for this builder
+class UnpackWarning(SCons.Warnings.Warning) :
+    pass
+
+SCons.Warnings.enableWarningClass(UnpackWarning)
+
+# extractor function for Tar output
+# @param env environment object
+# @param count number of returning lines
+# @param no number of the output line
+# @param i line content
+def __fileextractor_nix_tar( env, count, no, i ) :
+    return i.split()[-1]
+
+# extractor function for GZip output,
+# ignore the first line
+# @param env environment object
+# @param count number of returning lines
+# @param no number of the output line
+# @param i line content
+def __fileextractor_nix_gzip( env, count, no, i ) :
+    if no == 0 :
+        return None
+    return i.split()[-1]
+
+# extractor function for Unzip output,
+# ignore the first & last two lines
+# @param env environment object
+# @param count number of returning lines
+# @param no number of the output line
+# @param i line content
+def __fileextractor_nix_unzip( env, count, no, i ) :
+    if no < 3 or no >= count - 2 :
+        return None
+    return i.split()[-1]
+
+# extractor function for 7-Zip
+# @param env environment object
+# @param count number of returning lines
+# @param no number of the output line
+# @param i line content
+def __fileextractor_win_7zip( env, count, no, i ) :
+    item = i.split()
+    if no > 8 and no < count - 2 :
+        return item[-1]
+    return None
+
+
+
+# returns the extractor item for handling the source file
+# @param source input source file
+# @param env environment object
+# @return extractor entry or None on non existing
+def __getExtractor( source, env ) :
+    # we check each unpacker and get the correct list command first, run the command and
+    # replace the target filelist with the list values, we sorte the extractors by their priority
+    for unpackername, extractor in sorted(env["UNPACK"]["EXTRACTOR"].iteritems(), key = lambda (k,v) : (v["PRIORITY"],k)):
+
+        if not SCons.Util.is_String(extractor["RUN"]) :
+            raise SCons.Errors.StopError("list command of the unpack builder for [%s] archives is not a string" % (unpackername))
+        if not len(extractor["RUN"]) :
+            raise SCons.Errors.StopError("run command of the unpack builder for [%s] archives is not set - can not extract files" % (unpackername))
+
+
+        if not SCons.Util.is_String(extractor["LISTFLAGS"]) :
+            raise SCons.Errors.StopError("list flags of the unpack builder for [%s] archives is not a string" % (unpackername))
+        if not SCons.Util.is_String(extractor["LISTCMD"]) :
+            raise SCons.Errors.StopError("list command of the unpack builder for [%s] archives is not a string" % (unpackername))
+
+        if not SCons.Util.is_String(extractor["EXTRACTFLAGS"]) :
+            raise SCons.Errors.StopError("extract flags of the unpack builder for [%s] archives is not a string" % (unpackername))
+        if not SCons.Util.is_String(extractor["EXTRACTCMD"]) :
+            raise SCons.Errors.StopError("extract command of the unpack builder for [%s] archives is not a string" % (unpackername))
+
+
+        # check the source file suffix and if the first is found, run the list command
+        if not SCons.Util.is_List(extractor["SUFFIX"]) :
+            raise SCons.Errors.StopError("suffix list of the unpack builder for [%s] archives is not a list" % (unpackername))
+
+        for suffix in extractor["SUFFIX"] :
+            if str(source[0]).lower()[-len(suffix):] == suffix.lower() :
+                return extractor
+
+    return None
+
+
+# creates the extracter output message
+# @param s original message
+# @param target target name
+# @param source source name
+# @param env environment object
+def __message( s, target, source, env ) :
+    print "extract [%s] ..." % (source[0])
+
+
+# action function for extracting of the data
+# @param target target packed file
+# @param source extracted files
+# @param env environment object
+def __action( target, source, env ) :
+    extractor = __getExtractor([File(source)], env)
+    if not extractor :
+        raise SCons.Errors.StopError( "can not find any extractor value for the source file [%s]" % (source) )
+
+    extractor_cmd = extractor["EXTRACTCMD"]
+
+    # if the extract command is empty, we create an error
+    if len(extractor_cmd) == 0 :
+        raise SCons.Errors.StopError( "the extractor command for the source file [%s] is empty" % (source) )
+
+    # build it now (we need the shell, because some programs need it)
+    handle = None
+
+    cmd = env.subst(extractor_cmd, source=source, target=target)
+    cwd = os.path.realpath('.')
+
+    if env["UNPACK"]["VIWEXTRACTOUTPUT"] :
+        handle  = subprocess.Popen( cmd, shell=True )
+    else :
+        devnull = open(os.devnull, "wb")
+        handle  = subprocess.Popen(cmd, shell=True, stdout=devnull, cwd = cwd)
+
+    if handle.wait() <> 0 :
+        print '''******************************* Error *****************************************
+*
+* Fail to unpack (%s). It should be due to it isn't downloaded completely.
+* Please download it manually or delete it and let the script auto
+* download again.
+*
+*******************************************************************************
+'''
+        raise SCons.Errors.BuildError( "error running extractor [%s] on the source [%s]" % (cmd, source) )
+
+# emitter function for getting the files
+# within the archive
+# @param target target packed file
+# @param source extracted files
+# @param env environment object
+def __emitter( target, source, env ) :
+    return target, source
+
+def __unpack_all(env, target, source) :
+       if os.path.exists(target):
+               return
+
+       print "Unpacking %s ..." % source
+       __action(target, source, env)
+
+# generate function, that adds the builder to the environment
+# @param env environment object
+def generate( env ) :
+    # setup environment variable
+    toolset = {
+        "STOPONEMPTYFILE"  : True,
+        "VIWEXTRACTOUTPUT" : False,
+        "EXTRACTDIR"       : os.curdir,
+        "EXTRACTOR" : {
+            "TARGZ" : {
+                "PRIORITY"       : 0,
+                "SUFFIX"         : [".tar.gz", ".tgz", ".tar.gzip"],
+                "EXTRACTSUFFIX"  : "",
+                "EXTRACTFLAGS"   : "",
+                "EXTRACTCMD"     : "${UNPACK['EXTRACTOR']['TARGZ']['RUN']} ${UNPACK['EXTRACTOR']['TARGZ']['EXTRACTFLAGS']} $SOURCE ${UNPACK['EXTRACTOR']['TARGZ']['EXTRACTSUFFIX']}",
+                "RUN"            : "",
+                "LISTCMD"        : "${UNPACK['EXTRACTOR']['TARGZ']['RUN']} ${UNPACK['EXTRACTOR']['TARGZ']['LISTFLAGS']} $SOURCE ${UNPACK['EXTRACTOR']['TARGZ']['LISTSUFFIX']}",
+                "LISTSUFFIX"     : "",
+                "LISTFLAGS"      : "",
+                "LISTEXTRACTOR"  : None
+            },
+
+            "TARBZ" : {
+                "PRIORITY"       : 0,
+                "SUFFIX"         : [".tar.bz", ".tbz", ".tar.bz2", ".tar.bzip2", ".tar.bzip"],
+                "EXTRACTSUFFIX"  : "",
+                "EXTRACTFLAGS"   : "",
+                "EXTRACTCMD"     : "${UNPACK['EXTRACTOR']['TARBZ']['RUN']} ${UNPACK['EXTRACTOR']['TARBZ']['EXTRACTFLAGS']} $SOURCE ${UNPACK['EXTRACTOR']['TARBZ']['EXTRACTSUFFIX']}",
+                "RUN"            : "",
+                "LISTCMD"        : "${UNPACK['EXTRACTOR']['TARBZ']['RUN']} ${UNPACK['EXTRACTOR']['TARBZ']['LISTFLAGS']} $SOURCE ${UNPACK['EXTRACTOR']['TARBZ']['LISTSUFFIX']}",
+                "LISTSUFFIX"     : "",
+                "LISTFLAGS"      : "",
+                "LISTEXTRACTOR"  : None
+            },
+
+            "BZIP" : {
+                "PRIORITY"       : 1,
+                "SUFFIX"         : [".bz", "bzip", ".bz2", ".bzip2"],
+                "EXTRACTSUFFIX"  : "",
+                "EXTRACTFLAGS"   : "",
+                "EXTRACTCMD"     : "${UNPACK['EXTRACTOR']['BZIP']['RUN']} ${UNPACK['EXTRACTOR']['BZIP']['EXTRACTFLAGS']} $SOURCE ${UNPACK['EXTRACTOR']['BZIP']['EXTRACTSUFFIX']}",
+                "RUN"            : "",
+                "LISTCMD"        : "${UNPACK['EXTRACTOR']['BZIP']['RUN']} ${UNPACK['EXTRACTOR']['BZIP']['LISTFLAGS']} $SOURCE ${UNPACK['EXTRACTOR']['BZIP']['LISTSUFFIX']}",
+                "LISTSUFFIX"     : "",
+                "LISTFLAGS"      : "",
+                "LISTEXTRACTOR"  : None
+            },
+
+            "GZIP" : {
+                "PRIORITY"       : 1,
+                "SUFFIX"         : [".gz", ".gzip"],
+                "EXTRACTSUFFIX"  : "",
+                "EXTRACTFLAGS"   : "",
+                "EXTRACTCMD"     : "${UNPACK['EXTRACTOR']['GZIP']['RUN']} ${UNPACK['EXTRACTOR']['GZIP']['EXTRACTFLAGS']} $SOURCE ${UNPACK['EXTRACTOR']['GZIP']['EXTRACTSUFFIX']}",
+                "RUN"            : "",
+                "LISTCMD"        : "${UNPACK['EXTRACTOR']['GZIP']['RUN']} ${UNPACK['EXTRACTOR']['GZIP']['LISTFLAGS']} $SOURCE ${UNPACK['EXTRACTOR']['GZIP']['LISTSUFFIX']}",
+                "LISTSUFFIX"     : "",
+                "LISTFLAGS"      : "",
+                "LISTEXTRACTOR"  : None
+            },
+
+            "TAR" : {
+                "PRIORITY"       : 1,
+                "SUFFIX"         : [".tar"],
+                "EXTRACTSUFFIX"  : "",
+                "EXTRACTFLAGS"   : "",
+                "EXTRACTCMD"     : "${UNPACK['EXTRACTOR']['TAR']['RUN']} ${UNPACK['EXTRACTOR']['TAR']['EXTRACTFLAGS']} $SOURCE ${UNPACK['EXTRACTOR']['TAR']['EXTRACTSUFFIX']}",
+                "RUN"            : "",
+                "LISTCMD"        : "${UNPACK['EXTRACTOR']['TAR']['RUN']} ${UNPACK['EXTRACTOR']['TAR']['LISTFLAGS']} $SOURCE ${UNPACK['EXTRACTOR']['TAR']['LISTSUFFIX']}",
+                "LISTSUFFIX"     : "",
+                "LISTFLAGS"      : "",
+                "LISTEXTRACTOR"  : None
+            },
+
+            "ZIP" : {
+                "PRIORITY"       : 1,
+                "SUFFIX"         : [".zip"],
+                "EXTRACTSUFFIX"  : "",
+                "EXTRACTFLAGS"   : "",
+                "EXTRACTCMD"     : "${UNPACK['EXTRACTOR']['ZIP']['RUN']} ${UNPACK['EXTRACTOR']['ZIP']['EXTRACTFLAGS']} $SOURCE ${UNPACK['EXTRACTOR']['ZIP']['EXTRACTSUFFIX']}",
+                "RUN"            : "",
+                "LISTCMD"        : "${UNPACK['EXTRACTOR']['ZIP']['RUN']} ${UNPACK['EXTRACTOR']['ZIP']['LISTFLAGS']} $SOURCE ${UNPACK['EXTRACTOR']['ZIP']['LISTSUFFIX']}",
+                "LISTSUFFIX"     : "",
+                "LISTFLAGS"      : "",
+                "LISTEXTRACTOR"  : None
+            }
+        }
+    }
+
+    # read tools for Windows system
+    if env["PLATFORM"] <> "darwin" and "win" in env["PLATFORM"] :
+
+        if env.WhereIs("7z") :
+            toolset["EXTRACTOR"]["TARGZ"]["RUN"]           = "7z"
+            toolset["EXTRACTOR"]["TARGZ"]["LISTEXTRACTOR"] = __fileextractor_win_7zip
+            toolset["EXTRACTOR"]["TARGZ"]["LISTFLAGS"]     = "x"
+            toolset["EXTRACTOR"]["TARGZ"]["LISTSUFFIX"]    = "-so -y | ${UNPACK['EXTRACTOR']['TARGZ']['RUN']} l -sii -ttar -y -so"
+            toolset["EXTRACTOR"]["TARGZ"]["EXTRACTFLAGS"]  = "x"
+            toolset["EXTRACTOR"]["TARGZ"]["EXTRACTSUFFIX"] = "-so -y | ${UNPACK['EXTRACTOR']['TARGZ']['RUN']} x -sii -ttar -y -oc:${UNPACK['EXTRACTDIR']}"
+
+            toolset["EXTRACTOR"]["TARBZ"]["RUN"]           = "7z"
+            toolset["EXTRACTOR"]["TARBZ"]["LISTEXTRACTOR"] = __fileextractor_win_7zip
+            toolset["EXTRACTOR"]["TARBZ"]["LISTFLAGS"]     = "x"
+            toolset["EXTRACTOR"]["TARBZ"]["LISTSUFFIX"]    = "-so -y | ${UNPACK['EXTRACTOR']['TARGZ']['RUN']} l -sii -ttar -y -so"
+            toolset["EXTRACTOR"]["TARBZ"]["EXTRACTFLAGS"]  = "x"
+            toolset["EXTRACTOR"]["TARBZ"]["EXTRACTSUFFIX"] = "-so -y | ${UNPACK['EXTRACTOR']['TARGZ']['RUN']} x -sii -ttar -y -oc:${UNPACK['EXTRACTDIR']}"
+
+            toolset["EXTRACTOR"]["BZIP"]["RUN"]            = "7z"
+            toolset["EXTRACTOR"]["BZIP"]["LISTEXTRACTOR"]  = __fileextractor_win_7zip
+            toolset["EXTRACTOR"]["BZIP"]["LISTFLAGS"]      = "l"
+            toolset["EXTRACTOR"]["BZIP"]["LISTSUFFIX"]     = "-y -so"
+            toolset["EXTRACTOR"]["BZIP"]["EXTRACTFLAGS"]   = "x"
+            toolset["EXTRACTOR"]["BZIP"]["EXTRACTSUFFIX"]  = "-y -oc:${UNPACK['EXTRACTDIR']}"
+
+            toolset["EXTRACTOR"]["GZIP"]["RUN"]            = "7z"
+            toolset["EXTRACTOR"]["GZIP"]["LISTEXTRACTOR"]  = __fileextractor_win_7zip
+            toolset["EXTRACTOR"]["GZIP"]["LISTFLAGS"]      = "l"
+            toolset["EXTRACTOR"]["GZIP"]["LISTSUFFIX"]     = "-y -so"
+            toolset["EXTRACTOR"]["GZIP"]["EXTRACTFLAGS"]   = "x"
+            toolset["EXTRACTOR"]["GZIP"]["EXTRACTSUFFIX"]  = "-y -oc:${UNPACK['EXTRACTDIR']}"
+
+            toolset["EXTRACTOR"]["ZIP"]["RUN"]             = "7z"
+            toolset["EXTRACTOR"]["ZIP"]["LISTEXTRACTOR"]   = __fileextractor_win_7zip
+            toolset["EXTRACTOR"]["ZIP"]["LISTFLAGS"]       = "l"
+            toolset["EXTRACTOR"]["ZIP"]["LISTSUFFIX"]      = "-y -so"
+            toolset["EXTRACTOR"]["ZIP"]["EXTRACTFLAGS"]    = "x"
+            toolset["EXTRACTOR"]["ZIP"]["EXTRACTSUFFIX"]   = "-y -oc:${UNPACK['EXTRACTDIR']}"
+
+            toolset["EXTRACTOR"]["TAR"]["RUN"]             = "7z"
+            toolset["EXTRACTOR"]["TAR"]["LISTEXTRACTOR"]   = __fileextractor_win_7zip
+            toolset["EXTRACTOR"]["TAR"]["LISTFLAGS"]       = "l"
+            toolset["EXTRACTOR"]["TAR"]["LISTSUFFIX"]      = "-y -ttar -so"
+            toolset["EXTRACTOR"]["TAR"]["EXTRACTFLAGS"]    = "x"
+            toolset["EXTRACTOR"]["TAR"]["EXTRACTSUFFIX"]   = "-y -ttar -oc:${UNPACK['EXTRACTDIR']}"
+
+        # here can add some other Windows tools, that can handle the archive files
+        # but I don't know which ones can handle all file types
+
+
+
+    # read the tools on *nix systems and sets the default parameters
+    elif env["PLATFORM"] in ["darwin", "linux", "posix"] :
+
+        if env.WhereIs("unzip") :
+            toolset["EXTRACTOR"]["ZIP"]["RUN"]             = "unzip"
+            toolset["EXTRACTOR"]["ZIP"]["LISTEXTRACTOR"]   = __fileextractor_nix_unzip
+            toolset["EXTRACTOR"]["ZIP"]["LISTFLAGS"]       = "-l"
+            toolset["EXTRACTOR"]["ZIP"]["EXTRACTFLAGS"]    = "-oqq"
+            toolset["EXTRACTOR"]["ZIP"]["EXTRACTSUFFIX"]   = "-d ${UNPACK['EXTRACTDIR']}"
+
+        if env.WhereIs("tar") :
+            toolset["EXTRACTOR"]["TAR"]["RUN"]             = "tar"
+            toolset["EXTRACTOR"]["TAR"]["LISTEXTRACTOR"]   = __fileextractor_nix_tar
+            toolset["EXTRACTOR"]["TAR"]["LISTFLAGS"]       = "tvf"
+            toolset["EXTRACTOR"]["TAR"]["EXTRACTFLAGS"]    = "xf"
+            toolset["EXTRACTOR"]["TAR"]["EXTRACTSUFFIX"]   = "-C ${UNPACK['EXTRACTDIR']}"
+
+            toolset["EXTRACTOR"]["TARGZ"]["RUN"]           = "tar"
+            toolset["EXTRACTOR"]["TARGZ"]["LISTEXTRACTOR"] = __fileextractor_nix_tar
+            toolset["EXTRACTOR"]["TARGZ"]["EXTRACTFLAGS"]  = "xfz"
+            toolset["EXTRACTOR"]["TARGZ"]["LISTFLAGS"]     = "tvfz"
+            toolset["EXTRACTOR"]["TARGZ"]["EXTRACTSUFFIX"] = "-C ${UNPACK['EXTRACTDIR']}"
+
+            toolset["EXTRACTOR"]["TARBZ"]["RUN"]           = "tar"
+            toolset["EXTRACTOR"]["TARBZ"]["LISTEXTRACTOR"] = __fileextractor_nix_tar
+            toolset["EXTRACTOR"]["TARBZ"]["EXTRACTFLAGS"]  = "xfj"
+            toolset["EXTRACTOR"]["TARBZ"]["LISTFLAGS"]     = "tvfj"
+            toolset["EXTRACTOR"]["TARBZ"]["EXTRACTSUFFIX"] = "-C ${UNPACK['EXTRACTDIR']}"
+
+        if env.WhereIs("bzip2") :
+            toolset["EXTRACTOR"]["BZIP"]["RUN"]            = "bzip2"
+            toolset["EXTRACTOR"]["BZIP"]["EXTRACTFLAGS"]   = "-df"
+
+        if env.WhereIs("gzip") :
+            toolset["EXTRACTOR"]["GZIP"]["RUN"]            = "gzip"
+            toolset["EXTRACTOR"]["GZIP"]["LISTEXTRACTOR"]  = __fileextractor_nix_gzip
+            toolset["EXTRACTOR"]["GZIP"]["LISTFLAGS"]      = "-l"
+            toolset["EXTRACTOR"]["GZIP"]["EXTRACTFLAGS"]   = "-df"
+
+    else :
+        raise SCons.Errors.StopError("Unpack tool detection on this platform [%s] unkown" % (env["PLATFORM"]))
+
+    # the target_factory must be a "Entry", because the target list can be files and dirs, so we can not specified the targetfactory explicite
+    env.Replace(UNPACK = toolset)
+    env.AddMethod(__unpack_all, 'UnpackAll')
+
+#    env["BUILDERS"]["UnpackAll"] = SCons.Builder.Builder( action = __action,  emitter = __emitter,  target_factory = SCons.Node.FS.Entry,  source_factory = SCons.Node.FS.File,  single_source = True,  PRINT_CMD_LINE_FUNC = __message )
+
+
+# existing function of the builder
+# @param env environment object
+# @return true
+def exists(env) :
+    return 1
+
+Import('env')
+generate(env)
diff --git a/extlibs/gtest/SConscript b/extlibs/gtest/SConscript
new file mode 100644 (file)
index 0000000..e9f1f23
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# 'googletest' script to check if Google Unit Test library is installed.  If not,
+# get it and install it
+#
+##
+
+import os
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+src_dir = env.get('SRC_DIR')
+
+
+if target_os == 'linux':
+       print '*** Checking for installation of google unit test 1.7.0 ***'     
+
+       gtest_dir      = src_dir + '/extlibs/gtest/gtest-1.7.0'
+       gtest_zip_file = src_dir + '/extlibs/gtest/gtest-1.7.0.zip'
+       gtest_url      = 'https://googletest.googlecode.com/files/gtest-1.7.0.zip'
+
+       if not os.path.exists(gtest_dir):
+               # If the gtest zip file is not already present, download it
+               if not os.path.exists(gtest_zip_file):
+                       gtest_zip = env.Download(gtest_zip_file, gtest_url)
+               else:
+                       gtest_zip = gtest_zip_file
+
+               # Unzip gtest
+               print 'Unzipping google unit test'
+               env.UnpackAll(gtest_dir, gtest_zip)
+
+               # Run configure on gtest
+               print 'Configuring google unit test'
+               env.Configure(gtest_dir, './configure')
+
+               # Run make on gtest
+               print 'Making google unit test'
+               env.Configure(gtest_dir, 'make')
+
+
diff --git a/extlibs/hippomocks.scons b/extlibs/hippomocks.scons
new file mode 100644 (file)
index 0000000..361225d
--- /dev/null
@@ -0,0 +1,33 @@
+##
+# 'hippomocks' script to check if Hippo Mocks Unit Test library is installed.
+# If not, get it and install it
+#
+##
+
+import os, sys
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+src_dir = env.get('SRC_DIR')
+
+# Only verify/install on linux
+if target_os == 'linux':
+       print '*** Checking for installation of hippomocks ***'
+
+       hippomocks_dir      = src_dir + '/extlibs/hippomocks-master'
+       hippomocks_zip_file = src_dir + '/extlibs/master.zip'
+       hippomocks_url      = 'https://github.com/dascandy/hippomocks/archive/master.zip'
+
+       if not os.path.exists(hippomocks_dir):
+               # If the hippomocks zip file is not already present, download it
+               if not os.path.exists(hippomocks_zip_file):
+                       hippomocks_zip = env.Download(hippomocks_zip_file, hippomocks_url)
+               else:
+                       hippomocks_zip = hippomocks_zip_file
+
+               # Unzip hippomocks
+               print 'Unzipping hippomocks'
+               env.UnpackAll(hippomocks_dir, hippomocks_zip)
+
+
index be5f341..d7adf7b 100644 (file)
@@ -3,9 +3,12 @@
 #
 ##
 
+import os
+
 Import('env')
 
 target_os = env.get('TARGET_OS')
+src_dir = env.get('SRC_DIR')
 
 # Build libcoap
 SConscript('csdk/connectivity/lib/libcoap-4.1.1/SConscript')
@@ -33,5 +36,8 @@ if target_os == 'linux':
        # Build secure samples
        SConscript('csdk/stack/samples/linux/secure/SConscript')
 
+       # Build C/C++ unit tests
+       SConscript('unit_tests.scons')
+
 elif target_os == 'arduino':
        SConscript('csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript')
index c91cac3..e2fca83 100644 (file)
@@ -105,9 +105,14 @@ static uint32_t GetTime(float afterSeconds)
     return now + (uint32_t)(afterSeconds * COAP_TICKS_PER_SECOND);
 }
 
-static OCStackResult FormOCResponse(OCResponse * * responseLoc,  ClientCB * cbNode, uint32_t maxAge,
-        unsigned char * fullUri, unsigned char * rcvdUri, CAToken_t * rcvdToken,
-        OCClientResponse * clientResponse, unsigned char * bufRes)
+static OCStackResult FormOCResponse(OCResponse * * responseLoc,
+                                    ClientCB * cbNode,
+                                    uint32_t maxAge,
+                                    unsigned char * fullUri,
+                                    unsigned char * rcvdUri,
+                                    CAToken_t * rcvdToken,
+                                    OCClientResponse * clientResponse,
+                                    unsigned char * bufRes)
 {
     OCResponse * response = (OCResponse *) OCMalloc(sizeof(OCResponse));
     if (!response)
@@ -1283,6 +1288,13 @@ OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
     OCStackResult result = OC_STACK_ERROR;
     OC_LOG(INFO, TAG, PCF("Entering OCInit"));
 
+    // Validate mode
+    if (!((mode == OC_CLIENT) || (mode == OC_SERVER) || (mode == OC_CLIENT_SERVER)))
+    {
+        OC_LOG(ERROR, TAG, PCF("Invalid mode"));
+        return OC_STACK_ERROR;
+    }
+
     if (ipAddr)
     {
         OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
@@ -1484,9 +1496,11 @@ OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
 }
 
 /**
- * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
+ * Discover or Perform requests on a specified resource
+ * (specified by that Resource's respective URI).
  *
- * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
+ * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of
+ *                             calling this API.
  * @param method             - @ref OCMethod to perform on the resource
  * @param requiredUri        - URI of the resource to interact with
  * @param referenceUri       - URI of the reference resource
@@ -1540,7 +1554,8 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
 
     uint16_t uriLen = strlen(requiredUri);
 
-    // ToDo: We should also check if the requiredUri has a mutlicast address, then qos has to be OC_Low_QOS
+    // ToDo: We should also check if the requiredUri has a mutlicast address,
+    // then qos has to be OC_Low_QOS
     switch (method)
     {
         case OC_REST_GET:
@@ -2119,13 +2134,15 @@ OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
 /**
  * Create a resource
  *
- * @param handle - pointer to handle to newly created resource.  Set by ocstack.  Used to refer to resource
+ * @param handle - pointer to handle to newly created resource.  Set by ocstack.
+ *                 Used to refer to resource
  * @param resourceTypeName - name of resource type.  Example: "core.led"
  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
  * @param uri - URI of the resource.  Example:  "/a/led"
  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
  *                        NULL for default entity handler
- * @param resourceProperties - properties supported by resource.  Example: OC_DISCOVERABLE|OC_OBSERVABLE
+ * @param resourceProperties - properties supported by resource.
+ *                             Example: OC_DISCOVERABLE|OC_OBSERVABLE
  *
  * @return
  *     OC_STACK_OK    - no errors
index 3ab5808..4db2ba0 100644 (file)
@@ -2,16 +2,19 @@
 //  NOTICE - Transition to SCONS
 //---------------------------------------------------------------------
 
-The IoTivity build system is transitioning to SCONS. Although the 
-makefiles are still available (until v1.0) and some developers are 
-still using them, they are currently no longer supported. To learn more 
-about building using SCONS see Readme.scons.txt in the repository root 
+The IoTivity build system is transitioning to SCONS. Although the
+makefiles are still available (until v1.0) and some developers are
+still using them, they are currently no longer supported. To learn more
+about building using SCONS see Readme.scons.txt in the repository root
 directory. The build steps used in continuous integration can be found
 in auto_build.sh which is also in the the repository root directory.
 
+To dynamically link with the Google Unit test library,
+add <src_dir>/extlibs/gtest/gtest-1.7.0/lib/.libs/ to LD_LIBRARY_PATH
+
 //---------------------------------------------------------------------
 
-stacktests.cpp is a unit test of the APIs in ocstack.c.  
+stacktests.cpp is a unit test of the APIs in ocstack.c.
 It uses Google Test for the unit tests.  Note that
 the unit tests are only to test the functionality of
 ocstack.c.  It is not a system or end-to-end test.
@@ -21,7 +24,7 @@ Unit Test Requirements:
 1. Install Google Test on a Linux build machine
 2. Create a file called "local.properties" in the 
    root/csdk/stack/test.  local.properties is used
-   by the makefile and specifies the path to the 
+   by the makefile and specifies the path to the
    Google Test directory on the build machine.
    Since local.properties is specific to each build
    system, do not add local.properties to the code repo.
diff --git a/resource/csdk/stack/test/SConscript b/resource/csdk/stack/test/SConscript
new file mode 100644 (file)
index 0000000..fb3cedc
--- /dev/null
@@ -0,0 +1,48 @@
+
+Import('env')
+
+stacktest_env = env.Clone()
+
+src_dir = stacktest_env.get('SRC_DIR')
+
+######################################################################
+# Build flags
+######################################################################
+stacktest_env.PrependUnique(CPPPATH = [
+               '../../ocsocket/include',
+               '../../logger/include',
+               '../../stack/include',
+               '../../ocmalloc/include',
+               '../../extlibs/cjson',
+               '../../../oc_logger/include',
+               '../../../../extlibs/gtest/gtest-1.7.0/include'
+               ])
+
+stacktest_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+stacktest_env.AppendUnique(LIBS = ['-lpthread'])
+stacktest_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+stacktest_env.AppendUnique(LIBPATH = [src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs'])
+stacktest_env.PrependUnique(LIBS = ['m',
+                                    'octbstack',
+                                    'oc_logger',
+                                    'connectivity_abstraction',
+                                    'coap',
+                                    'gtest',
+                                    'gtest_main'])
+
+if env.get('SECURED') == '1':
+    stacktest_env.AppendUnique(LIBS = ['tinydtls'])
+stacktest_env.ParseConfig('pkg-config --libs glib-2.0');
+
+if not env.get('RELEASE'):
+       stacktest_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+stacktests = stacktest_env.Program('stacktests', ['stacktests.cpp'])
+
+Alias("test", [stacktests])
+
+env.AppendTarget('test')
+
index 6e91b6e..a7165cf 100644 (file)
@@ -22,7 +22,6 @@
 extern "C"
 {
     #include "ocstack.h"
-    #include "ocstackinternal.h"
     #include "logger.h"
 }
 
@@ -83,7 +82,6 @@ OCEntityHandlerResult entityHandler(OCEntityHandlerFlag flag, OCEntityHandlerReq
 void InitStack(OCMode mode)
 {
     OC_LOG(INFO, TAG, "Entering InitStack");
-    OC_LOG_V(INFO, TAG, "InitStack on address %s",addr);
 
     EXPECT_EQ(OC_STACK_OK, OCInit(NULL, 0, mode));
     OC_LOG(INFO, TAG, "Leaving InitStack");
@@ -179,8 +177,16 @@ TEST(StackDiscovery, DoResourceDeviceDiscovery)
     cbData.cb = asyncDoResourcesCallback;
     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
-
-    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0));
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle,
+                                        OC_REST_GET,
+                                        szQueryUri,
+                                        0,
+                                        0,
+                                        OC_WIFI,
+                                        OC_LOW_QOS,
+                                        &cbData,
+                                        NULL,
+                                        0));
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
 
@@ -205,7 +211,16 @@ TEST(StackResource, UpdateResourceNullURI)
     cbData.cb = asyncDoResourcesCallback;
     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
-    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0));
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle,
+                                        OC_REST_GET,
+                                        szQueryUri,
+                                        0,
+                                        0,
+                                        OC_WIFI,
+                                        OC_LOW_QOS,
+                                        &cbData,
+                                        NULL,
+                                        0));
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
 
diff --git a/resource/unit_tests.scons b/resource/unit_tests.scons
new file mode 100644 (file)
index 0000000..eadcf91
--- /dev/null
@@ -0,0 +1,30 @@
+##
+# 'unit_test' script for building unit tests and libs
+#
+##
+
+import os
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+src_dir = env.get('SRC_DIR')
+build_dir = env.get('BUILD_DIR')
+
+
+if target_os == 'linux':
+       # Verify that 'google unit test' library is installed.  If not,
+       # get it and install it
+       SConscript(src_dir + '/extlibs/gtest/SConscript')
+
+       # Verify that 'hippomocks' mocking code is installed.  If not,
+       # get it and install it
+       SConscript(src_dir + '/extlibs/hippomocks.scons')
+
+       # Build C unit tests
+       SConscript('csdk/stack/test/SConscript')
+
+       # Build C++ unit tests
+       SConscript('unittests/SConscript')
+
+
index a13dcde..841eaa0 100644 (file)
@@ -2,17 +2,20 @@
 // NOTICE - Transition to SCONS
 //---------------------------------------------------------------------
 
-The IoTivity build system is transitioning to SCONS. Although the 
-makefiles are still available (until v1.0) and some developers are 
-still using them, they are currently no longer supported. To learn more 
-about building using SCONS see Readme.scons.txt in the repository root 
+The IoTivity build system is transitioning to SCONS. Although the
+makefiles are still available (until v1.0) and some developers are
+still using them, they are currently no longer supported. To learn more
+about building using SCONS see Readme.scons.txt in the repository root
 directory. The build steps used in continuous integration can be found
 in auto_build.sh which is also in the the repository root directory.
 
+To dynamically link with the Google Unit test library,
+add <src_dir>/extlibs/gtest/gtest-1.7.0/lib/.libs/ to LD_LIBRARY_PATH
+
 //---------------------------------------------------------------------
 
-The unittests folder contains unit tests for OCPlatfrom and OCResource APIs. 
-It uses Google Test for the unit tests. Please note that the unit tests are 
+The unittests folder contains unit tests for OCPlatfrom and OCResource APIs.
+It uses Google Test for the unit tests. Please note that the unit tests are
 only to test the functionality of public APIs.
 It is not a system or end-to-end test.
 
diff --git a/resource/unittests/SConscript b/resource/unittests/SConscript
new file mode 100644 (file)
index 0000000..f6a2b8e
--- /dev/null
@@ -0,0 +1,53 @@
+
+Import('env')
+
+unittests_env = env.Clone()
+
+src_dir = unittests_env.get('SRC_DIR')
+######################################################################
+# Build flags
+######################################################################
+unittests_env.PrependUnique(CPPPATH = [
+               '../include',
+               '../oc_logger/include',
+               '../csdk/stack/include',
+               '../csdk/ocsocket/include',
+               '../csdk/ocrandom/include',
+               '../csdk/logger/include',
+               '../../extlibs/gtest/gtest-1.7.0/include',
+               '../../extlibs/hippomocks-master/HippoMocks',
+               '../../extlibs/hippomocks-master/HippoMocksTest'
+               ])
+
+unittests_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+unittests_env.AppendUnique(LIBS = ['-lpthread'])
+unittests_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+unittests_env.AppendUnique(LIBPATH = [src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs'])
+unittests_env.PrependUnique(LIBS = [
+               'oc',
+               'octbstack',
+               'oc_logger',
+               'connectivity_abstraction',
+               'coap',
+               'gtest',
+               'gtest_main'
+               ])
+
+if env.get('SECURED') == '1':
+    stacktest_env.AppendUnique(LIBS = ['tinydtls'])
+unittests_env.ParseConfig('pkg-config --libs glib-2.0');
+
+if not env.get('RELEASE'):
+       unittests_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+unittests = unittests_env.Program('unittests', ['ConstructResourceTest.cpp',
+                                                'OCPlatformTest.cpp',
+                                                'OCResourceTest.cpp'])
+
+Alias("unittests", [unittests])
+
+env.AppendTarget('unittests')
+