diff options
49 files changed, 1299 insertions, 633 deletions
diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam index 8b17299..881b6ff 100644 --- a/project2/Jamfile.jam +++ b/project2/Jamfile.jam @@ -31,7 +31,7 @@ build-project daemon ; # Ensure tests are run (final targets don't reference projects, but specific libraries) build-project basics//unittests ; -build-project ice//tests ; +build-project ice//unittests ; explicit install installp2con installp2cgi installp2fcgi ; package.install install : : console//p2console cgi//p2cgi cgi//p2fcgi daemon//p2daemon ; diff --git a/project2/common/commonObjects.cpp b/project2/common/commonObjects.cpp index cb973cc..a25bb9f 100644 --- a/project2/common/commonObjects.cpp +++ b/project2/common/commonObjects.cpp @@ -1,6 +1,5 @@ #include <pch.hpp> #include "commonObjects.h" -#include "logger.h" #include "safeMapFind.h" #include "scriptLoader.h" diff --git a/project2/ice/.ycm_extra_conf.py b/project2/ice/.ycm_extra_conf.py new file mode 100644 index 0000000..ffb537b --- /dev/null +++ b/project2/ice/.ycm_extra_conf.py @@ -0,0 +1,119 @@ +import os +import ycm_core + +flags = [ +'-Wall', +'-Wextra', +'-Werror', +'-Wc++98-compat', +'-Wno-long-long', +'-Wno-variadic-macros', +'-fexceptions', +'-DNDEBUG', +'-std=c++11', +'-x', +'c++', +'-I', +'.', +'-I', +'../common', +'-I', +'../lib', +'-isystem', +'/usr/include/slicer', +'-isystem', +'/usr/include', +'-isystem', +'/usr/include/glibmm-2.4', +] + +# Set this to the absolute path to the folder (NOT the file!) containing the +# compile_commands.json file to use that instead of 'flags'. See here for +# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html +# +# Most projects will NOT need to set this to anything; you can just change the +# 'flags' list of compilation flags. Notice that YCM itself uses that approach. +compilation_database_folder = '' + +if os.path.exists( compilation_database_folder ): + database = ycm_core.CompilationDatabase( compilation_database_folder ) +else: + database = None + +SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ] + +def DirectoryOfThisScript(): + return os.path.dirname( os.path.abspath( __file__ ) ) + + +def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): + if not working_directory: + return list( flags ) + new_flags = [] + make_next_absolute = False + path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] + for flag in flags: + new_flag = flag + + if make_next_absolute: + make_next_absolute = False + if not flag.startswith( '/' ): + new_flag = os.path.join( working_directory, flag ) + + for path_flag in path_flags: + if flag == path_flag: + make_next_absolute = True + break + + if flag.startswith( path_flag ): + path = flag[ len( path_flag ): ] + new_flag = path_flag + os.path.join( working_directory, path ) + break + + if new_flag: + new_flags.append( new_flag ) + return new_flags + + +def IsHeaderFile( filename ): + extension = os.path.splitext( filename )[ 1 ] + return extension in [ '.h', '.hxx', '.hpp', '.hh' ] + + +def GetCompilationInfoForFile( filename ): + # The compilation_commands.json file generated by CMake does not have entries + # for header files. So we do our best by asking the db for flags for a + # corresponding source file, if any. If one exists, the flags for that file + # should be good enough. + if IsHeaderFile( filename ): + basename = os.path.splitext( filename )[ 0 ] + for extension in SOURCE_EXTENSIONS: + replacement_file = basename + extension + if os.path.exists( replacement_file ): + compilation_info = database.GetCompilationInfoForFile( + replacement_file ) + if compilation_info.compiler_flags_: + return compilation_info + return None + return database.GetCompilationInfoForFile( filename ) + + +def FlagsForFile( filename, **kwargs ): + if database: + # Bear in mind that compilation_info.compiler_flags_ does NOT return a + # python list, but a "list-like" StringVec object + compilation_info = GetCompilationInfoForFile( filename ) + if not compilation_info: + return None + + final_flags = MakeRelativePathsInFlagsAbsolute( + compilation_info.compiler_flags_, + compilation_info.compiler_working_dir_ ) + else: + relative_to = DirectoryOfThisScript() + final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) + + return { + 'flags': final_flags, + 'do_cache': True + } diff --git a/project2/ice/Jamfile.jam b/project2/ice/Jamfile.jam index 67e9eab..2a531cb 100644 --- a/project2/ice/Jamfile.jam +++ b/project2/ice/Jamfile.jam @@ -9,18 +9,20 @@ lib Ice ; lib IceUtil ; lib pthread ; lib boost_filesystem ; +lib slicer : : <name>slicer : : <include>/usr/include/slicer ; -build-project tests ; +build-project unittests ; cpp-pch pch : pch.hpp : <include>../../libmisc <library>../lib//p2lib <library>../common//p2common <library>glibmm + <library>slicer ; lib p2iceclient : - pch iceDataSource.cpp iceClient.cpp buildClient.cpp slice2Task.cpp slice2Rows.cpp + pch iceDataSource.cpp iceClient.cpp buildClient.cpp slice2Task.cpp slice2Rows.cpp iceRows.cpp : <include>../../libmisc <library>glibmm @@ -40,7 +42,7 @@ lib p2iceclient : ; lib p2icedaemon : - pch iceDaemon.cpp iceModule.cpp buildDaemon.cpp slice2Daemon.cpp slice2DaemonLoader.cpp slice2Presenter.cpp + pch iceDaemon.cpp iceModule.cpp buildDaemon.cpp slice2Daemon.cpp slice2DaemonLoader.cpp iceViewSerializer.cpp : <include>../../libmisc <library>glibmm @@ -57,10 +59,11 @@ lib p2icedaemon : : : <library>../daemon/lib//p2daemonlib <library>p2ice + <include>. ; lib p2ice : - pch iceConvert.cpp iceCompile.cpp sliceCompile.cpp buildComms.cpp buildShared.cpp slice2Type.cpp + pch iceConvert.cpp iceCompile.cpp sliceCompile.cpp buildComms.cpp slice2Common.cpp iceBase.cpp : <include>../../libmisc <library>glibmm @@ -69,6 +72,7 @@ lib p2ice : <library>dl <library>Ice <library>Slice + <library>slicer <library>IceUtil <library>boost_filesystem ; diff --git a/project2/ice/buildComms.cpp b/project2/ice/buildComms.cpp index 4add6c7..bdba5e9 100644 --- a/project2/ice/buildComms.cpp +++ b/project2/ice/buildComms.cpp @@ -2,9 +2,13 @@ #include "buildComms.h" #include <logger.h> #include <misc.h> +#include <boost/filesystem/operations.hpp> -BuildComms::BuildComms(const boost::filesystem::path & slice) : - IceCompile(slice) +namespace fs = boost::filesystem; + +BuildComms::BuildComms(const boost::filesystem::path & slice, bool ip) : + IceCompile(slice), + iceParts(ip) { } @@ -16,6 +20,16 @@ BuildComms::Build(const boost::filesystem::path & in, const boost::filesystem::p if (system(slicecmd.c_str())) { throw std::runtime_error("slice2cpp failed"); } + if (!iceParts) { + // We always need to the header, but we can truncate the cpp if we don't need the ice bits + boost::filesystem::resize_file(out, 0); + } + + const auto slicercmd = stringbf("%s %s %s", slicer, in, out); + Logger()->messagebf(LOG_DEBUG, "%s: slicer command: %s", __PRETTY_FUNCTION__, slicercmd); + if (system(slicercmd.c_str())) { + throw std::runtime_error("slicer failed"); + } } boost::filesystem::path diff --git a/project2/ice/buildComms.h b/project2/ice/buildComms.h index 31e7590..116051e 100644 --- a/project2/ice/buildComms.h +++ b/project2/ice/buildComms.h @@ -6,11 +6,13 @@ class BuildComms : public IceCompile { public: - BuildComms(const boost::filesystem::path & slice); + BuildComms(const boost::filesystem::path & slice, bool iceParts); void Build(const boost::filesystem::path & in, const boost::filesystem::path & out) const; boost::filesystem::path InputPath() const; boost::filesystem::path OutputName(const std::string & type) const; + + const bool iceParts; }; #endif diff --git a/project2/ice/buildDaemon.cpp b/project2/ice/buildDaemon.cpp index 83976b0..a6579c9 100644 --- a/project2/ice/buildDaemon.cpp +++ b/project2/ice/buildDaemon.cpp @@ -1,6 +1,5 @@ #include <pch.hpp> #include "buildDaemon.h" -#include "slice2Presenter.h" #include "slice2Daemon.h" #include "slice2DaemonLoader.h" @@ -18,9 +17,6 @@ BuildDaemon::Headers(FILE * out) const void BuildDaemon::Body(FILE * out, Slice::UnitPtr u) const { - Slice2Presenter presenterBuilder(out); - u->visit(&presenterBuilder, false); - Slice2Daemon daemonBuilder(out); u->visit(&daemonBuilder, false); diff --git a/project2/ice/buildShared.cpp b/project2/ice/buildShared.cpp deleted file mode 100644 index 61450c8..0000000 --- a/project2/ice/buildShared.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include <pch.hpp> -#include "buildShared.h" -#include "slice2Type.h" - -BuildShared::BuildShared(const boost::filesystem::path & slice, const IceCompile::Deps & dep) : - SliceCompile(slice, dep) -{ -} - -void -BuildShared::Headers(FILE * out) const -{ - fprintf(out, "#include <iceConvert.h>\n"); -} - -void -BuildShared::Body(FILE * out, Slice::UnitPtr u) const -{ - Slice2Type typeBuilder(out); - u->visit(&typeBuilder, false); -} - -boost::filesystem::path -BuildShared::OutputName(const std::string & type) const -{ - return slice.filename().replace_extension(".shared" + type); -} - - - diff --git a/project2/ice/buildShared.h b/project2/ice/buildShared.h deleted file mode 100644 index cf0e5d5..0000000 --- a/project2/ice/buildShared.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef BUILDSHARED_H -#define BUILDSHARED_H - -#include "sliceCompile.h" -#include <string> - -class BuildShared : public SliceCompile { - public: - BuildShared(const boost::filesystem::path & slice, const IceCompile::Deps & dep); - - virtual void Headers(FILE *) const; - virtual void Body(FILE *, Slice::UnitPtr) const; - - boost::filesystem::path OutputName(const std::string & type) const; -}; - -#endif - - - diff --git a/project2/ice/iceBase.cpp b/project2/ice/iceBase.cpp new file mode 100644 index 0000000..0171f1b --- /dev/null +++ b/project2/ice/iceBase.cpp @@ -0,0 +1,43 @@ +#include "iceBase.h" +#include "buildComms.h" + +void +IceBase::SetSlice(Libs & libs, const GetComponentCompiler & gcc, const VariableType & vslice, bool iceParts, bool slicerParts) +{ + auto slice = vslice.as<std::string>(); + IceCompile::CPtr bc(new BuildComms(slice, iceParts)); + bc->Update(IceCompile::UpdateBuild); + IceCompile::CPtr bcl(( !iceParts && !slicerParts ) ? + gcc(slice, { }) : + gcc(slice, { bc })); + libs.push_back(LibCompile(bcl, new std::thread(&IceCompile::Update, bcl.get(), + IceCompile::UpdateBuild | IceCompile::UpdateCompile | IceCompile::UpdateLink))); +} + +class WaitAndLoad : public boost::static_visitor<> { + public: + WaitAndLoad(IceBase::LibPromise & l) : lib(l) { } + + void operator()(IceBase::LibCompile & th) const + { + boost::get<1>(th)->join(); + delete boost::get<1>(th); + lib = boost::get<0>(th)->Open(); + } + + void operator()(IceCompile::LibHandle) const + { + } + + private: + IceBase::LibPromise & lib; +}; + +void +IceBase::FinaliseLoad(Libs & libs) +{ + BOOST_FOREACH(auto & lib, libs) { + boost::apply_visitor(WaitAndLoad(lib), lib); + } +} + diff --git a/project2/ice/iceBase.h b/project2/ice/iceBase.h new file mode 100644 index 0000000..06d8994 --- /dev/null +++ b/project2/ice/iceBase.h @@ -0,0 +1,23 @@ +#ifndef ICEBASE_H +#define ICEBASE_H + +#include <boost/tuple/tuple.hpp> +#include <thread> +#include "iceCompile.h" +#include <variableType.h> + +class IceBase { + public: + typedef boost::tuple<IceCompile::CPtr, std::thread *> LibCompile; + typedef boost::variant<LibCompile, IceCompile::LibHandle> LibPromise; + typedef std::vector<LibPromise> Libs; + typedef boost::function<IceCompile::CPtr(const std::string &, const IceCompile::Deps &)> GetComponentCompiler; + + static void FinaliseLoad(Libs & libs); + + protected: + static void SetSlice(Libs &, const GetComponentCompiler &, const VariableType &, bool iceParts, bool slicerParts); +}; + +#endif + diff --git a/project2/ice/iceCompile.cpp b/project2/ice/iceCompile.cpp index 3df8dbd..74b0b45 100644 --- a/project2/ice/iceCompile.cpp +++ b/project2/ice/iceCompile.cpp @@ -8,12 +8,14 @@ namespace fs = boost::filesystem; std::string IceCompile::slice2cpp; +std::string IceCompile::slicer; std::string IceCompile::cxx; std::string IceCompile::linker; std::string IceCompile::cxxopts; std::string IceCompile::linkeropts; fs::path IceCompile::tmpdir; fs::path IceCompile::headerdir; +fs::path IceCompile::slicerheaderdir; DECLARE_OPTIONS(IceCompile, "ICE Compile Options") ("ice.compile.cxx", Options::value(&cxx, "g++"), @@ -26,10 +28,14 @@ DECLARE_OPTIONS(IceCompile, "ICE Compile Options") "The extra arguments to pass to linker") ("ice.compile.slice2cpp", Options::value(&slice2cpp, "slice2cpp"), "The ICE Slice to CPP processor to use") +("ice.compile.slicer", Options::value(&slicer, "slicer"), + "The Slicer to CPP processor to use") ("ice.compile.tmpdir", Options::value(&tmpdir, "/tmp/project2.slice"), "The temporary directory used when compiling") ("ice.compile.headers", Options::value(&headerdir, "/usr/include/project2"), "The root folder where Project2 header files are found") +("ice.compile.slicerheaders", Options::value(&slicerheaderdir, "/usr/include/slicer"), + "The root folder where Slicer header files are found") END_OPTIONS(IceCompile); IceCompile::IceCompile(const boost::filesystem::path & s) : @@ -81,8 +87,10 @@ void IceCompile::Compile(const fs::path & in, const fs::path & out) const { const auto compile = stringbf( - "%s %s -o %s -x c++ -c -I %s -I %s -I ../libmisc/ -I %s -I %s -I %s `pkg-config --cflags glibmm-2.4` %s", + "%s %s -o %s -x c++ -c -I %s -I %s -I ../libmisc/ -I %s -I %s -I %s -I %s -I %s `pkg-config --cflags glibmm-2.4` %s", cxx, cxxopts, out, tmpdir, + slicerheaderdir, + headerdir.parent_path() / "libmisc", headerdir / "lib", headerdir / "common", headerdir / "ice", diff --git a/project2/ice/iceCompile.h b/project2/ice/iceCompile.h index d849ac6..5e6873a 100644 --- a/project2/ice/iceCompile.h +++ b/project2/ice/iceCompile.h @@ -15,12 +15,14 @@ class IceCompile { typedef std::vector<CPtr> Deps; static std::string slice2cpp; + static std::string slicer; static std::string cxx; static std::string linker; static std::string cxxopts; static std::string linkeropts; static boost::filesystem::path tmpdir; static boost::filesystem::path headerdir; + static boost::filesystem::path slicerheaderdir; IceCompile(const boost::filesystem::path & slice); IceCompile(const boost::filesystem::path & slice, const Deps & deps); diff --git a/project2/ice/iceDaemon.cpp b/project2/ice/iceDaemon.cpp index 04d6fdb..a8fb8c2 100644 --- a/project2/ice/iceDaemon.cpp +++ b/project2/ice/iceDaemon.cpp @@ -1,8 +1,8 @@ #include <pch.hpp> #include "iceDaemon.h" #include "buildComms.h" -#include "buildShared.h" #include "buildDaemon.h" +#include "iceViewSerializer.h" #include <scriptLoader.h> #include <options.h> #include <sys/stat.h> @@ -20,12 +20,18 @@ std::string IceDaemon::adapterName; std::string IceDaemon::adapterEndpoint; -std::string IceDaemon::interface; -std::string IceDaemon::slice; std::string IceDaemon::viewRoot; std::string IceDaemon::taskRoot; +IceBase::Libs IceDaemon::libs; -DECLARE_GENERIC_LOADER("ice", DaemonLoader, IceDaemon); +class IceDaemonLoader : public DaemonLoader::For<IceDaemon> { + public: + void onConfigLoad() override { + IceBase::FinaliseLoad(IceDaemon::libs); + } +}; + +DECLARE_CUSTOM_COMPONENT_LOADER("ice", IceDaemon, IceDaemonLoader, DaemonLoader); DECLARE_OPTIONS(IceDaemon, "ICE Daemon Options") ("ice.daemon.viewRoot", Options::value(&viewRoot, "views"), "The folder in which to find view scripts") @@ -35,10 +41,12 @@ DECLARE_OPTIONS(IceDaemon, "ICE Daemon Options") "The name of the ICE adapter created") ("ice.daemon.adapterEndpoint", Options::value(&adapterEndpoint), "The ICE endpoint string for the ICE adapter") -("ice.daemon.slice", Options::value(&slice), - "The ICE Slice file to compile") -("ice.daemon.interface", Options::value(&interface), - "The ICE interface to wrap") +("ice.daemon.slice", Options::functions(boost::bind(&IceBase::SetSlice, boost::ref(IceDaemon::libs), &IceDaemon::GetComponentCompiler, _1, true, true), boost::bind(&IceDaemon::ClearSlice)), + "The ICE Slice file(s) to compile") +("ice.daemon.slicedaemon", Options::functions(boost::bind(&IceDaemon::SetSlice, boost::ref(IceDaemon::libs), &IceDaemon::GetComponentCompiler, _1, false, true), boost::bind(&IceDaemon::ClearSlice)), + "The ICE Slice file(s) to compile (daemon only, assumes comms library referenced)") +("ice.daemon.slicerdaemon", Options::functions(boost::bind(&IceDaemon::SetSlice, boost::ref(IceDaemon::libs), &IceDaemon::GetComponentCompiler, _1, false, false), boost::bind(&IceDaemon::ClearSlice)), + "The ICE Slice file(s) to compile (daemon only, assumes comms library referenced and built with Slicer support)") END_OPTIONS(IceDaemon); IceDaemon::IceDaemon(int & argc, char ** argv) : @@ -60,31 +68,28 @@ IceDaemon::shutdown() const void IceDaemon::run() const { - Logger()->messagebf(LOG_INFO, ">>> %s compiling slice '%s'...", __PRETTY_FUNCTION__, slice); - - IceCompile::CPtr bc(new BuildComms(slice)); - IceCompile::CPtr bds(new BuildShared(slice, { bc })); - IceCompile::CPtr bd(new BuildDaemon(slice, { bds })); - bd->Update(); - - auto library = bd->Open(); - Logger()->messagebf(LOG_INFO, " %s starting...", __PRETTY_FUNCTION__); Ice::ObjectAdapterPtr adapter = ic->createObjectAdapterWithEndpoints(adapterName, adapterEndpoint); - IceDaemonAdapterHandlerPtr interfacePtr = IceDaemonAdapterHandlerLoader::createNew(interface); - interfacePtr->add(adapter, this, ic); + std::set<IceDaemonAdapterHandlerPtr> interfaces; + InstanceSet<IceDaemonAdapterHandlerLoader>::OnAll([this, adapter, &interfaces](IceDaemonAdapterHandlerLoader * loader) { + IceDaemonAdapterHandlerPtr interfacePtr = loader->create(); + interfacePtr->add(adapter, this, ic); + interfaces.insert(interfacePtr); + }); adapter->activate(); Logger()->messagebf(LOG_INFO, " %s running...", __PRETTY_FUNCTION__); - interfacePtr->remove(adapter, ic); + BOOST_FOREACH(const auto & interfacePtr, interfaces) { + interfacePtr->remove(adapter, ic); + } ic->waitForShutdown(); Logger()->messagebf(LOG_INFO, " %s stopped...", __PRETTY_FUNCTION__); Logger()->messagebf(LOG_INFO, "<<< %s", __PRETTY_FUNCTION__); } -class IceDaemonFlatViewHost : public virtual CommonObjects, public virtual CheckHost { +class IceDaemonViewHost : public virtual CommonObjects, public virtual CheckHost { public: - IceDaemonFlatViewHost(ScriptNodePtr s) : + IceDaemonViewHost(ScriptNodePtr s) : CommonObjects(s), CheckHost(s) { @@ -93,6 +98,7 @@ class IceDaemonFlatViewHost : public virtual CommonObjects, public virtual Check void executeView(RowSetPresenterPtr presenter, ExecContext * ec) const { loadScriptComponents(); + runChecks(ec); view->execute(presenter.get(), ec); // Caches might open transactions BOOST_FOREACH(const CommonObjects::DataSources::value_type & ds, CommonObjects::datasources) { @@ -127,12 +133,12 @@ class IceCallContext : public ExecContext { }; void -IceDaemon::executeView(const std::string & name, RowSetPresenterPtr p, const ParamMap & pm) const +IceDaemon::executeView(const std::string & name, Slicer::ModelPartPtr p, const ParamMap & pm) const { ScriptNodePtr s = ScriptReader::resolveScript(IceDaemon::viewRoot, name, false)->root(); - IceDaemonFlatViewHost f(s); + IceDaemonViewHost f(s); IceCallContext icc(pm); - f.executeView(p, &icc); + f.executeView(new IceViewSerializer(p), &icc); } class IceDaemonTaskHost : public TaskHost { @@ -159,3 +165,15 @@ IceDaemon::executeTask(const std::string & name, const ParamMap & pm) const t.executeTask(&icc); } +IceCompile::CPtr +IceDaemon::GetComponentCompiler(const std::string & slice, const IceCompile::Deps & deps) +{ + return IceCompile::CPtr(new BuildDaemon(slice, deps)); +} + +void +IceDaemon::ClearSlice() +{ + libs.clear(); +} + diff --git a/project2/ice/iceDaemon.h b/project2/ice/iceDaemon.h index 49af50b..623da11 100644 --- a/project2/ice/iceDaemon.h +++ b/project2/ice/iceDaemon.h @@ -3,9 +3,14 @@ #include <daemon.h> #include "iceModule.h" +#include "iceBase.h" -class IceDaemon : public Daemon { +class IceDaemon : public Daemon, IceBase { public: + typedef boost::tuple<IceCompile::CPtr, std::thread *> LibCompile; + typedef boost::variant<LibCompile, IceCompile::LibHandle> LibPromise; + typedef std::vector<LibPromise> Libs; + IceDaemon(int & argc, char ** argv); virtual ~IceDaemon(); @@ -13,18 +18,21 @@ class IceDaemon : public Daemon { void shutdown() const; void executeTask(const std::string & name, const ParamMap & params) const; - void executeView(const std::string & name, RowSetPresenterPtr p, const ParamMap & params) const; + void executeView(const std::string & name, Slicer::ModelPartPtr p, const ParamMap & params) const; INITOPTIONS; static std::string adapterName; static std::string adapterEndpoint; - static std::string interface; - static std::string slice; static std::string viewRoot; static std::string taskRoot; + static Libs libs; + + static IceCompile::CPtr GetComponentCompiler(const std::string & slice, const IceCompile::Deps &); private: Ice::CommunicatorPtr ic; + + static void ClearSlice(); }; #endif diff --git a/project2/ice/iceDataSource.cpp b/project2/ice/iceDataSource.cpp index 064a69f..c3d5b36 100644 --- a/project2/ice/iceDataSource.cpp +++ b/project2/ice/iceDataSource.cpp @@ -1,18 +1,18 @@ #include <pch.hpp> -#include "iceDataSource.h" -#include "buildComms.h" -#include "buildShared.h" #include "buildClient.h" +#include "iceDataSource.h" #include <Ice/Ice.h> -IceDataSource::Libs IceDataSource::libs; +IceBase::Libs IceDataSource::libs; IceDataSource::Proxies IceDataSource::proxies; DECLARE_OPTIONS(IceDataSource, "ICE Data Source") -("ice.client.slice", Options::functions(boost::bind(&IceDataSource::SetSlice, _1), boost::bind(&IceDataSource::ClearSlice)), +("ice.client.slice", Options::functions(boost::bind(&IceBase::SetSlice, boost::ref(IceDataSource::libs), &IceDataSource::GetComponentCompiler, _1, true, true), boost::bind(&IceDataSource::ClearSlice)), "The ICE Slice file(s) to compile") -("ice.client.sliceclient", Options::functions(boost::bind(&IceDataSource::SetSliceClient, _1), boost::bind(&IceDataSource::ClearSlice)), +("ice.client.sliceclient", Options::functions(boost::bind(&IceBase::SetSlice, boost::ref(IceDataSource::libs), &IceDataSource::GetComponentCompiler, _1, false, true), boost::bind(&IceDataSource::ClearSlice)), "The ICE Slice file(s) to compile (client only, assumes comms library referenced)") +("ice.client.slicerclient", Options::functions(boost::bind(&IceBase::SetSlice, boost::ref(IceDataSource::libs), &IceDataSource::GetComponentCompiler, _1, false, false), boost::bind(&IceDataSource::ClearSlice)), + "The ICE Slice file(s) to compile (client only, assumes comms library referenced and built with Slicer support)") END_OPTIONS(IceDataSource); int dummy = 0; @@ -21,57 +21,13 @@ IceDataSource::IceDataSource(ScriptNodePtr p) : endpoint(p, "endpoint"), ic(Ice::initialize(dummy, NULL)) { + Logger()->messagebf(LOG_DEBUG, "%s: endpoint: %s", __PRETTY_FUNCTION__, endpoint(NULL)); } -void -IceDataSource::SetSlice(const VariableType & vslice) -{ - auto slice = vslice.as<std::string>(); - IceCompile::CPtr bc(new BuildComms(slice)); - bc->Update(IceCompile::UpdateBuild); - IceCompile::CPtr bcs(new BuildShared(slice, { bc })); - IceCompile::CPtr bcl(new BuildClient(slice, { bcs })); - libs.push_back(LibCompile(bcl, new std::thread(&IceCompile::Update, bcl.get(), - IceCompile::UpdateBuild | IceCompile::UpdateCompile | IceCompile::UpdateLink))); -} - -void -IceDataSource::SetSliceClient(const VariableType & vslice) -{ - auto slice = vslice.as<std::string>(); - IceCompile::CPtr bc(new BuildComms(slice)); - bc->Update(IceCompile::UpdateBuild); - IceCompile::CPtr bcs(new BuildShared(slice, { })); - IceCompile::CPtr bcl(new BuildClient(slice, { bcs })); - libs.push_back(LibCompile(bcl, new std::thread(&IceCompile::Update, bcl.get(), - IceCompile::UpdateBuild | IceCompile::UpdateCompile | IceCompile::UpdateLink))); -} - -class WaitAndLoad : public boost::static_visitor<> { - public: - WaitAndLoad(IceDataSource::LibPromise & l) : lib(l) { } - - void operator()(IceDataSource::LibCompile & th) const - { - boost::get<1>(th)->join(); - delete boost::get<1>(th); - lib = boost::get<0>(th)->Open(); - } - - void operator()(IceCompile::LibHandle) const - { - } - - private: - IceDataSource::LibPromise & lib; -}; - -void -IceDataSource::FinaliseLoad() +IceCompile::CPtr +IceDataSource::GetComponentCompiler(const std::string & slice, const IceCompile::Deps & deps) { - BOOST_FOREACH(auto & lib, libs) { - boost::apply_visitor(WaitAndLoad(lib), lib); - } + return IceCompile::CPtr(new BuildClient(slice, deps)); } void @@ -84,7 +40,7 @@ IceDataSource::ClearSlice() class IceDataSourceLoader : public ElementLoader::For<IceDataSource> { public: void onConfigLoad() override { - IceDataSource::FinaliseLoad(); + IceBase::FinaliseLoad(IceDataSource::libs); } }; diff --git a/project2/ice/iceDataSource.h b/project2/ice/iceDataSource.h index 47af13b..9881a41 100644 --- a/project2/ice/iceDataSource.h +++ b/project2/ice/iceDataSource.h @@ -3,20 +3,13 @@ #include <dataSource.h> #include <options.h> -#include <variables.h> -#include "iceCompile.h" #include <Ice/Communicator.h> -#include <thread> -#include <boost/tuple/tuple.hpp> +#include "iceBase.h" -class IceDataSource : public DataSource { +class IceDataSource : public DataSource, IceBase { public: INITOPTIONS; - typedef boost::tuple<IceCompile::CPtr, std::thread *> LibCompile; - typedef boost::variant<LibCompile, IceCompile::LibHandle> LibPromise; - typedef std::vector<LibPromise> Libs; - IceDataSource(ScriptNodePtr p); template <typename Interface> @@ -32,14 +25,11 @@ class IceDataSource : public DataSource { } const Ice::CommunicatorPtr GetCommunicator() const { return ic; } - static void FinaliseLoad(); + static IceCompile::CPtr GetComponentCompiler(const std::string & slice, const IceCompile::Deps &); - private: - static void SetSlice(const VariableType &); - static void SetSliceClient(const VariableType &); static void ClearSlice(); static Libs libs; - + private: const Variable endpoint; const Ice::CommunicatorPtr ic; diff --git a/project2/ice/iceModule.cpp b/project2/ice/iceModule.cpp index 1738bef..c1e035e 100644 --- a/project2/ice/iceModule.cpp +++ b/project2/ice/iceModule.cpp @@ -9,8 +9,8 @@ IceDaemonModule::IceDaemonModule(const IceDaemon * id) : } void -IceDaemonModule::executeView(const std::string & name, RowSetPresenterPtr p, const ParamMap & params) const { - iceDaemon->executeView(name, p, params); +IceDaemonModule::executeView(const std::string & name, Slicer::ModelPartPtr mpp, const ParamMap & params) const { + iceDaemon->executeView(name, mpp, params); } void diff --git a/project2/ice/iceModule.h b/project2/ice/iceModule.h index 246c9b8..3886aef 100644 --- a/project2/ice/iceModule.h +++ b/project2/ice/iceModule.h @@ -7,6 +7,7 @@ #include <presenter.h> #include <safeMapFind.h> #include <boost/function.hpp> +#include <slicer/modelParts.h> typedef std::map<std::string, VariableType> ParamMap; class IceDaemon; @@ -15,8 +16,9 @@ class IceDaemonModule { protected: IceDaemonModule(const IceDaemon *); + protected: void executeTask(const std::string & name, const ParamMap & params) const; - void executeView(const std::string & name, RowSetPresenterPtr p, const ParamMap & params) const; + void executeView(const std::string & name, Slicer::ModelPartPtr p, const ParamMap & params) const; private: const IceDaemon * const iceDaemon; @@ -31,40 +33,5 @@ class IceDaemonAdapterHandler : public IntrusivePtrBase { typedef boost::intrusive_ptr<IceDaemonAdapterHandler> IceDaemonAdapterHandlerPtr; typedef GenLoader<IceDaemonAdapterHandler, std::string> IceDaemonAdapterHandlerLoader; -template <typename IC> -class IcePresenter : public RowSetPresenter { - public: - typedef boost::function<void (typename IC::value_type *, const VariableType &)> TargetAssigner; - typedef std::map<Glib::ustring, TargetAssigner> MemberTargets; - SimpleMessageException(NoSuchMember); - - IcePresenter(IC & t); - virtual void addNamedValue(const Glib::ustring & member, const VariableType & value) const - { - safeMapLookup<NoSuchMember>(memberTargets, member)(&*current, value); - } - virtual void addNewRow(const Glib::ustring&) const - { - target.push_back(typename IC::value_type()); - } - virtual void finishRow() const - { - current = target.end(); - } - // The target array already exists, so these need not do anything - virtual void addNewArray(const Glib::ustring&, bool) const { } - virtual void finishArray(bool) const { } - virtual void init() { } - private: - IC & target; - mutable typename IC::iterator current; - const MemberTargets memberTargets; - - template <typename T, typename M> static void memberAssign(T * t, M T::*m, const VariableType & v) { - t->*m = v.as<M>(); - } -}; - - #endif diff --git a/project2/ice/iceRows.cpp b/project2/ice/iceRows.cpp new file mode 100644 index 0000000..77519cd --- /dev/null +++ b/project2/ice/iceRows.cpp @@ -0,0 +1,108 @@ +#include <pch.hpp> +#include "iceRows.h" + +using namespace Slicer; + +class IceRowState : public RowState { + public: + class Assign : public ValueTarget, + public TValueTarget<boost::posix_time::ptime> { + public: + Assign(VariableType & v) : vt(v) + { + } + + void get(const boost::posix_time::ptime & v) const override { vt = v; } + void get(const bool & v) const override { vt = v; } + void get(const Ice::Byte & v) const override { vt = v; } + void get(const Ice::Short & v) const override { vt = v; } + void get(const Ice::Int & v) const override { vt = v; } + void get(const Ice::Long & v) const override { vt = v; } + void get(const Ice::Float & v) const override { vt = v; } + void get(const Ice::Double & v) const override { vt = v; } + void get(const std::string & v) const override { vt = v; } + + private: + VariableType & vt; + }; + + IceRowState(ModelPartPtr mp) + { + unsigned int idx = 0; + mp->OnEachChild(boost::bind(&IceRowState::AddColumn, this, boost::ref(idx), _1)); + fields.resize(columns.size()); + } + + void AddColumn(unsigned int & c, const std::string & name) + { + columns.insert(new Column(c++, name)); + } + + const Columns & getColumns() const { return columns; } + + void IterateOver(ModelPartPtr mp, const RowProcessorCallback & rp) + { + auto field = fields.begin(); + mp->OnEachChild(boost::bind(&IceRowState::AssignFieldValue, this, boost::ref(field), _2)); + this->process(rp); + } + + void AssignFieldValue(FieldValues::iterator & field, ModelPartPtr domp) + { + domp->GetValue(new Assign(*field++)); + } + + Columns columns; +}; + +RowProcSerializer::RowProcSerializer(const RowProcessorCallback & r) : + rpc(r) +{ +} + +void +RowProcSerializer::Serialize(ModelPartPtr mp) +{ + if (mp) { + switch (mp->GetType()) { + case mpt_Null: + return; + case mpt_Simple: + case mpt_Complex: + case mpt_Dictionary: + throw std::runtime_error("Not a sequence of things"); + case mpt_Sequence: + IceRowState * irs = NULL; + mp->OnEachChild(boost::bind(&RowProcSerializer::SerializeRow, this, boost::ref(irs), _2)); + if (irs) { + delete irs; + } + break; + } + } + +} + +void +RowProcSerializer::SerializeRow(IceRowState * & irs, ModelPartPtr mp) +{ + if (mp) { + switch (mp->GetType()) { + case mpt_Null: + return; + case mpt_Sequence: + case mpt_Dictionary: + case mpt_Simple: + throw std::runtime_error("Not a complex object"); + break; + case mpt_Complex: + if (!irs) { + irs = new IceRowState(mp); + } + irs->IterateOver(mp, rpc); + break; + } + } + +} + diff --git a/project2/ice/iceRows.h b/project2/ice/iceRows.h index 654de50..4c15217 100644 --- a/project2/ice/iceRows.h +++ b/project2/ice/iceRows.h @@ -4,70 +4,21 @@ #include <rowSet.h> #include "iceConvert.h" #include "iceClient.h" +#include <slicer/modelParts.h> +#include <slicer/serializer.h> -template <typename Type> -class IceRowState : public RowState { - public: - IceRowState() - { - unsigned int idx = 0; - IceType<Type>::CreateColumns(boost::bind(&IceRowState::AddColumn, this, boost::ref(idx), _1)); - fields.resize(columns.size()); - } - - void AddColumn(unsigned int & c, const std::string & name) - { - columns.insert(new Column(c++, name)); - } - - const Columns & getColumns() const { return columns; } - - void IterateOver(const Type & record, const RowProcessorCallback & rp) { - auto field = fields.begin(); - IceType<Type>::ForEachDataMember(record, boost::bind(&IceRowState::AssignFieldValue, this, boost::ref(field), _1)); - this->process(rp); - } - - void AssignFieldValue(FieldValues::iterator & field, const VariableType & vt) - { - *field++ = vt; - } +class IceRowState; - Columns columns; -}; - -template <typename Type> -class IceRowState<std::vector<Type> > : public RowState { +class RowProcSerializer : public Slicer::Serializer { public: - typedef std::vector<Type> RangeType; - IceRowState() - { - unsigned int idx = 0; - IceType<Type>::CreateColumns(boost::bind(&IceRowState::AddColumn, this, boost::ref(idx), _1)); - fields.resize(columns.size()); - } + RowProcSerializer(const RowProcessorCallback &); - void AddColumn(unsigned int & c, const std::string & name) - { - columns.insert(new Column(c++, name)); - } + void Serialize(Slicer::ModelPartPtr) override; - const Columns & getColumns() const { return columns; } - - void IterateOver(const RangeType & records, const RowProcessorCallback & rp) { - BOOST_FOREACH(const auto & record, records) { - auto field = fields.begin(); - IceType<Type>::ForEachDataMember(record, boost::bind(&IceRowState::AssignFieldValue, this, boost::ref(field), _1)); - this->process(rp); - } - } - - void AssignFieldValue(FieldValues::iterator & field, const VariableType & vt) - { - *field++ = vt; - } + private: + void SerializeRow(IceRowState * &, Slicer::ModelPartPtr); - Columns columns; + const RowProcessorCallback & rpc; }; template <typename Interface> diff --git a/project2/ice/iceViewSerializer.cpp b/project2/ice/iceViewSerializer.cpp new file mode 100644 index 0000000..2a95f9f --- /dev/null +++ b/project2/ice/iceViewSerializer.cpp @@ -0,0 +1,54 @@ +#include "iceViewSerializer.h" +#include <slicer/serializer.h> + +using namespace Slicer; + +class Assign : public ValueSource, + public TValueSource<boost::posix_time::ptime> { + public: + Assign(const VariableType & v) : vt(v) + { + } + + void set(boost::posix_time::ptime & v) const override { v = vt; } + void set(bool & v) const override { v = vt; } + void set(Ice::Byte & v) const override { v = boost::numeric_cast<Ice::Byte>(vt.as<int>()); } + void set(Ice::Short & v) const override { v = boost::numeric_cast<Ice::Byte>(vt.as<int>()); } + void set(Ice::Int & v) const override { v = vt; } + void set(Ice::Long & v) const override { v = vt; } + void set(Ice::Float & v) const override { v = vt.as<double>(); } + void set(Ice::Double & v) const override { v = vt; } + void set(std::string & v) const override { v = vt.as<std::string>(); } + + private: + const VariableType & vt; +}; + +IceViewSerializer::IceViewSerializer(ModelPartPtr m) : + mpp(m) +{ +} + +void +IceViewSerializer::addNamedValue(const Glib::ustring & name, const VariableType & vt) const +{ + if (rowmpp) { + ModelPartPtr field = rowmpp->GetChild(name); + if (field) { + field->SetValue(new Assign(vt)); + } + } +} + +void +IceViewSerializer::addNewRow(const Glib::ustring & name) const +{ + rowmpp = mpp->GetChild(name); +} + +void +IceViewSerializer::finishRow() const +{ + rowmpp = NULL; +} + diff --git a/project2/ice/iceViewSerializer.h b/project2/ice/iceViewSerializer.h new file mode 100644 index 0000000..ff4188d --- /dev/null +++ b/project2/ice/iceViewSerializer.h @@ -0,0 +1,21 @@ +#ifndef ICEVIEWSERIALIZER_H +#define ICEVIEWSERIALIZER_H + +#include <slicer/modelParts.h> +#include <presenter.h> + +class IceViewSerializer : public RowSetPresenter { + public: + IceViewSerializer(Slicer::ModelPartPtr mpp); + + void addNamedValue(const Glib::ustring & name, const VariableType & value) const override; + void addNewRow(const Glib::ustring & name) const override; + void finishRow() const override; + + private: + Slicer::ModelPartPtr mpp; + mutable Slicer::ModelPartPtr rowmpp; +}; + +#endif + diff --git a/project2/ice/pch.hpp b/project2/ice/pch.hpp index c74eebf..21f44dc 100644 --- a/project2/ice/pch.hpp +++ b/project2/ice/pch.hpp @@ -15,6 +15,8 @@ #include <Slice/Parser.h> #include <string> #include <variables.h> +#include <slicer/modelParts.h> +#include <slicer/serializer.h> #endif #endif diff --git a/project2/ice/slice2Common.cpp b/project2/ice/slice2Common.cpp new file mode 100644 index 0000000..5088120 --- /dev/null +++ b/project2/ice/slice2Common.cpp @@ -0,0 +1,71 @@ +#include "slice2Common.h" +#include <Slice/CPlusPlusUtil.h> +#include <boost/foreach.hpp> + +Slice2Common::Slice2Common(FILE * c) : + code(c) +{ +} + +void +Slice2Common::FunctionBegin(Slice::OperationPtr o) +{ + // Create typed variables for call + BOOST_FOREACH(const auto & p, o->parameters()) { + if (p->optional()) { + fprintf(code, "\t\t\t\t\t\tconst auto _%s = IceConvert< ::IceUtil::Optional< %s > >::FromVariable(%s(ec));\n", + p->name().c_str(), + Slice::typeToString(p->type()).c_str(), + p->name().c_str()); + } + else { + fprintf(code, "\t\t\t\t\t\tconst auto _%s = IceConvert< %s >::FromVariable(%s(ec));\n", + p->name().c_str(), + Slice::typeToString(p->type()).c_str(), + p->name().c_str()); + } + } + fprintf(code, "\n"); + + // Log call and parameters + fprintf(code, "\t\t\t\t\t\tLogger()->messagebf(LOG_DEBUG, \"%%s: "); + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "%s = %%s, ", p->name().c_str()); + } + fprintf(code, "ice @ %%p\", \n"); + fprintf(code, "\t\t\t\t\t\t\t\t__PRETTY_FUNCTION__, "); + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "_%s, ", p->name().c_str()); + } + fprintf(code, "ice);\n"); + + // Create default Ice context + fprintf(code, "\n"); + fprintf(code, "\t\t\t\t\t\tIce::Context ctx;\n"); +} + +void +Slice2Common::ParameterVariables(Slice::OperationPtr o) +{ + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "\t\t\t\t\tconst Variable %s;\n", p->name().c_str()); + } +} + +void +Slice2Common::Declaration(Slice::OperationPtr o) +{ + fprintf(code, "\t\t\tDECLARE_LOADER(\"%s-%s-%s\", %s);\n\n", + module.c_str(), interface.c_str(), o->name().c_str(), o->name().c_str()); +} + +void +Slice2Common::CallOperation(Slice::OperationPtr o) +{ + fprintf(code, "service->%s(", o->name().c_str()); + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "_%s, ", p->name().c_str()); + } + fprintf(code, "ctx)"); +} + diff --git a/project2/ice/slice2Common.h b/project2/ice/slice2Common.h new file mode 100644 index 0000000..bb4719b --- /dev/null +++ b/project2/ice/slice2Common.h @@ -0,0 +1,23 @@ +#ifndef SLICE2COMMON_H +#define SLICE2COMMON_H + +#include <Slice/Parser.h> + +class Slice2Common : public Slice::ParserVisitor { + public: + Slice2Common(FILE * c); + + void FunctionBegin(Slice::OperationPtr o); + void ParameterVariables(Slice::OperationPtr o); + void Declaration(Slice::OperationPtr o); + void CallOperation(Slice::OperationPtr o); + + protected: + FILE * code; + + std::string interface; + std::string module; +}; + +#endif + diff --git a/project2/ice/slice2Daemon.cpp b/project2/ice/slice2Daemon.cpp index 6a8e5fa..3e66339 100644 --- a/project2/ice/slice2Daemon.cpp +++ b/project2/ice/slice2Daemon.cpp @@ -44,8 +44,8 @@ Slice2Daemon::visitOperation(const Slice::OperationPtr & o) visitParameterMap(o); if (o->returnType()) { fprintf(code, "\t\t\t\t%s rtn;\n", o->returnType()->typeId().c_str()); - fprintf(code, "\t\t\t\tRowSetPresenterPtr ipp = new IcePresenter< %s >(rtn);\n", o->returnType()->typeId().c_str()); - fprintf(code, "\t\t\t\texecuteView(\"%s/%s/%s\", ipp, params);\n", module.c_str(), interface.c_str(), o->name().c_str()); + fprintf(code, "\t\t\t\tSlicer::ModelPartPtr mpp = new Slicer::ModelPartForSequence< %s >(rtn);\n", o->returnType()->typeId().c_str()); + fprintf(code, "\t\t\t\texecuteView(\"%s/%s/%s\", mpp, params);\n", module.c_str(), interface.c_str(), o->name().c_str()); fprintf(code, "\t\t\t\treturn rtn;\n"); } else { diff --git a/project2/ice/slice2Presenter.cpp b/project2/ice/slice2Presenter.cpp deleted file mode 100644 index 3cfb422..0000000 --- a/project2/ice/slice2Presenter.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include <pch.hpp> -#include "slice2Presenter.h" -#include <Slice/CPlusPlusUtil.h> - -Slice2Presenter::Slice2Presenter(FILE * c) : - code(c) -{ -} - -bool -Slice2Presenter::visitModuleStart(const Slice::ModulePtr & m) -{ - module = m->name(); - fprintf(code, "// Specialized functions for IcePresenters in module %s\n\n", module.c_str()); - return true; -} - -void -Slice2Presenter::visitModuleEnd(const Slice::ModulePtr &) -{ - fprintf(code, "// End Specialized functions for IcePresenters in module %s\n\n", module.c_str()); - module.clear(); -} - -bool -Slice2Presenter::visitStructStart(const Slice::StructPtr & s) -{ - strct = s->name(); - fprintf(code, "template <>\nIcePresenter<std::vector< %s::%s >>::IcePresenter(std::vector< %s::%s > & t) :\n", - module.c_str(), s->name().c_str(), - module.c_str(), s->name().c_str()); - fprintf(code, "\ttarget(t),\n\tcurrent(target.end()),\n"); - fprintf(code, "\tmemberTargets({\n"); - return true; -} - -void -Slice2Presenter::visitDataMember(const Slice::DataMemberPtr & m) -{ - fprintf(code, "\t\t{\"%s\", boost::bind(&IcePresenter<std::vector< %s::%s >>::memberAssign< %s::%s, %s >, _1, &%s::%s::%s, _2)},\n", - m->name().c_str(), - module.c_str(), strct.c_str(), - module.c_str(), strct.c_str(), - typeToString(m->type()).c_str(), - module.c_str(), strct.c_str(), m->name().c_str() - - ); -} - -void -Slice2Presenter::visitStructEnd(const Slice::StructPtr&) -{ - fprintf(code, "\t})\n{\n"); - - //fprintf(code, "boost::bind(&IcePresenter<std::vector<P2TV::Recording>>::memberAssign<P2TV::Recording, int>, NULL, &P2TV::Recording::recordingId, 1);\n"); - - fprintf(code, "}\n\n"); - strct.clear(); -} - diff --git a/project2/ice/slice2Presenter.h b/project2/ice/slice2Presenter.h deleted file mode 100644 index 892f2c1..0000000 --- a/project2/ice/slice2Presenter.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef ICEBUILDPRESENTER_H -#define ICEBUILDPRESENTER_H - -#include <Slice/Parser.h> - -class Slice2Presenter : public Slice::ParserVisitor { - public: - Slice2Presenter(FILE * c); - virtual bool visitModuleStart(const Slice::ModulePtr & m); - virtual void visitModuleEnd(const Slice::ModulePtr & m); - virtual bool visitStructStart(const Slice::StructPtr&); - virtual void visitStructEnd(const Slice::StructPtr&); - virtual void visitDataMember(const Slice::DataMemberPtr&); - - private: - FILE * code; - std::string module; - std::string strct; -}; - -#endif - - diff --git a/project2/ice/slice2Rows.cpp b/project2/ice/slice2Rows.cpp index a90b643..3534aff 100644 --- a/project2/ice/slice2Rows.cpp +++ b/project2/ice/slice2Rows.cpp @@ -4,7 +4,7 @@ #include <Slice/CPlusPlusUtil.h> Slice2Rows::Slice2Rows(FILE * c) : - code(c) + Slice2Common(c) { } @@ -42,48 +42,17 @@ Slice2Rows::visitOperation(const Slice::OperationPtr & o) // Execute fprintf(code, "\t\t\t\t\tvoid execute(const Glib::ustring &, const RowProcessorCallback & rp, ExecContext * ec) const\n"); fprintf(code, "\t\t\t\t\t{\n"); - fprintf(code, "\t\t\t\t\t\tLogger()->messagebf(LOG_DEBUG, \"%%s: "); - BOOST_FOREACH(const auto & p, o->parameters()) { - fprintf(code, "%s = %%s, ", p->name().c_str()); - } - fprintf(code, "ice @ %%p\", \n"); - fprintf(code, "\t\t\t\t\t\t\t\t__PRETTY_FUNCTION__, "); - BOOST_FOREACH(const auto & p, o->parameters()) { - fprintf(code, "%s(ec), ", p->name().c_str()); - } - fprintf(code, "ice);\n"); - fprintf(code, "\t\t\t\t\t\tIce::Context ctx;\n"); - BOOST_FOREACH(const auto & p, o->parameters()) { - if (p->optional()) { - fprintf(code, "\t\t\t\t\t\tauto _%s = IceConvert< ::IceUtil::Optional< %s > >::FromVariable(%s(ec));\n", - p->name().c_str(), - Slice::typeToString(p->type()).c_str(), - p->name().c_str()); - } - else { - fprintf(code, "\t\t\t\t\t\tauto _%s = IceConvert< %s >::FromVariable(%s(ec));\n", - p->name().c_str(), - Slice::typeToString(p->type()).c_str(), - p->name().c_str()); - } - } - fprintf(code, "\t\t\t\t\t\tIceRowState<decltype(service->%s(", o->name().c_str()); - BOOST_FOREACH(const auto & p, o->parameters()) { - fprintf(code, "_%s, ", p->name().c_str()); - } - fprintf(code, "ctx))> irs;\n"); - fprintf(code, "\t\t\t\t\t\tirs.IterateOver(service->%s(", o->name().c_str()); - BOOST_FOREACH(const auto & p, o->parameters()) { - fprintf(code, "_%s, ", p->name().c_str()); - } - fprintf(code, "ctx), rp);\n"); + FunctionBegin(o); + fprintf(code, "\t\t\t\t\t\tSlicer::SerializerPtr toRpc = new RowProcSerializer(rp);\n"); + fprintf(code, "\t\t\t\t\t\tauto result = "); + CallOperation(o); + fprintf(code, ";\n"); + fprintf(code, "\t\t\t\t\t\tSlicer::ModelPartPtr mp = new Slicer::ModelPartForSequence<decltype(result)>(&result);\n"); + fprintf(code, "\t\t\t\t\t\ttoRpc->Serialize(mp);\n"); fprintf(code, "\t\t\t\t\t}\n\n"); - // Parameter variables - BOOST_FOREACH(const auto & p, o->parameters()) { - fprintf(code, "\t\t\t\t\tconst Variable %s;\n", p->name().c_str()); - } + ParameterVariables(o); fprintf(code, "\t\t\t};\n"); - fprintf(code, "\t\t\tDECLARE_LOADER(\"%s-%s-%s\", %s);\n\n", module.c_str(), interface.c_str(), o->name().c_str(), o->name().c_str()); + Declaration(o); } } diff --git a/project2/ice/slice2Rows.h b/project2/ice/slice2Rows.h index b97f009..c85e4b8 100644 --- a/project2/ice/slice2Rows.h +++ b/project2/ice/slice2Rows.h @@ -1,21 +1,17 @@ #ifndef ICEBUILDVIEW_H #define ICEBUILDVIEW_H -#include <Slice/Parser.h> +#include "slice2Common.h" -class Slice2Rows : public Slice::ParserVisitor { +class Slice2Rows : public Slice2Common { public: Slice2Rows(FILE * c); + virtual bool visitModuleStart(const Slice::ModulePtr & m); virtual bool visitClassDefStart(const Slice::ClassDefPtr & c); virtual void visitOperation(const Slice::OperationPtr & o); virtual void visitClassDefEnd(const Slice::ClassDefPtr & c); virtual void visitModuleEnd(const Slice::ModulePtr & m); - - private: - FILE * code; - std::string interface; - std::string module; }; #endif diff --git a/project2/ice/slice2Task.cpp b/project2/ice/slice2Task.cpp index 54f05a8..1fbacaf 100644 --- a/project2/ice/slice2Task.cpp +++ b/project2/ice/slice2Task.cpp @@ -4,7 +4,7 @@ #include <Slice/CPlusPlusUtil.h> Slice2Task::Slice2Task(FILE * c) : - code(c) + Slice2Common(c) { } @@ -43,38 +43,14 @@ Slice2Task::visitOperation(const Slice::OperationPtr & o) // Execute fprintf(code, "\t\t\t\t\tvoid execute(ExecContext * ec) const\n"); fprintf(code, "\t\t\t\t\t{\n"); - fprintf(code, "\t\t\t\t\t\tLogger()->messagebf(LOG_DEBUG, \"%%s: "); - BOOST_FOREACH(const auto & p, o->parameters()) { - fprintf(code, "%s = %%s, ", p->name().c_str()); - } - fprintf(code, "ice @ %%p\", \n"); - fprintf(code, "\t\t\t\t\t\t\t\t__PRETTY_FUNCTION__, "); - BOOST_FOREACH(const auto & p, o->parameters()) { - fprintf(code, "%s(ec), ", p->name().c_str()); - } - fprintf(code, "ice);\n"); - fprintf(code, "\t\t\t\t\t\tIce::Context ctx;\n"); - fprintf(code, "\t\t\t\t\t\tservice->%s(", o->name().c_str()); - BOOST_FOREACH(const auto & p, o->parameters()) { - if (p->optional()) { - fprintf(code, "IceConvert< ::IceUtil::Optional< %s > >::FromVariable(%s(ec)), ", - Slice::typeToString(p->type()).c_str(), - p->name().c_str()); - } - else { - fprintf(code, "IceConvert< %s >::FromVariable(%s(ec)), ", - Slice::typeToString(p->type()).c_str(), - p->name().c_str()); - } - } - fprintf(code, "ctx);\n"); + FunctionBegin(o); + fprintf(code, "\t\t\t\t\t\t"); + CallOperation(o); + fprintf(code, ";\n"); fprintf(code, "\t\t\t\t\t}\n\n"); - // Parameter variables - BOOST_FOREACH(const auto & p, o->parameters()) { - fprintf(code, "\t\t\t\t\tconst Variable %s;\n", p->name().c_str()); - } + ParameterVariables(o); fprintf(code, "\t\t\t};\n"); - fprintf(code, "\t\t\tDECLARE_LOADER(\"%s-%s-%s\", %s);\n\n", module.c_str(), interface.c_str(), o->name().c_str(), o->name().c_str()); + Declaration(o); } } diff --git a/project2/ice/slice2Task.h b/project2/ice/slice2Task.h index d3bd0fe..20287cb 100644 --- a/project2/ice/slice2Task.h +++ b/project2/ice/slice2Task.h @@ -1,9 +1,9 @@ #ifndef SLICE2TASK_H #define SLICE2TASK_H -#include <Slice/Parser.h> +#include "slice2Common.h" -class Slice2Task : public Slice::ParserVisitor { +class Slice2Task : public Slice2Common { public: Slice2Task(FILE * c); @@ -12,13 +12,7 @@ class Slice2Task : public Slice::ParserVisitor { virtual void visitOperation(const Slice::OperationPtr & o); virtual void visitClassDefEnd(const Slice::ClassDefPtr & c); virtual void visitModuleEnd(const Slice::ModulePtr & m); - - private: - FILE * code; - std::string interface; - std::string module; }; #endif - diff --git a/project2/ice/slice2Type.cpp b/project2/ice/slice2Type.cpp deleted file mode 100644 index 9c3404e..0000000 --- a/project2/ice/slice2Type.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include <pch.hpp> -#include "slice2Type.h" -#include <Slice/CPlusPlusUtil.h> -#include <boost/foreach.hpp> - -Slice2Type::Slice2Type(FILE * c) : - code(c) -{ -} - -bool -Slice2Type::visitModuleStart(const Slice::ModulePtr & m) -{ - module = m->name(); - return true; -} - -void -Slice2Type::visitModuleEnd(const Slice::ModulePtr &) -{ - module.clear(); -} - -void -Slice2Type::visitClassDecl(const Slice::ClassDeclPtr&) -{ -} - -bool -Slice2Type::visitExceptionStart(const Slice::ExceptionPtr & e) -{ - if (e->hasMetaData("project2:type")) { - fprintf(code, "template <>\nvoid IceType< %s::%s >::ForEachDataMember(const %s::%s & obj, const IceEachDataMemberValue & func)\n{\n", - module.c_str(), e->name().c_str(), - module.c_str(), e->name().c_str()); - membersToVariables(e->dataMembers(), "obj."); - fprintf(code, "}\n\n"); - - fprintf(code, "template <>\nvoid IceType< %s::%s >::CreateColumns(const IceEachDataMemberName & func)\n{\n", - module.c_str(), e->name().c_str()); - membersToColumns(e->dataMembers()); - fprintf(code, "}\n\n"); - } - return false; -} - -bool -Slice2Type::visitClassDefStart(const Slice::ClassDefPtr & c) -{ - if (c->hasMetaData("project2:type")) { - fprintf(code, "template <>\nvoid IceType< IceInternal::Handle< %s::%s > >::ForEachDataMember(const IceInternal::Handle< %s::%s > & ptr, const IceEachDataMemberValue & func)\n{\n", - module.c_str(), c->name().c_str(), - module.c_str(), c->name().c_str()); - membersToVariables(c->dataMembers(), "ptr->"); - fprintf(code, "}\n\n"); - - fprintf(code, "template <>\nvoid IceType< IceInternal::Handle< %s::%s > >::CreateColumns(const IceEachDataMemberName & func)\n{\n", - module.c_str(), c->name().c_str()); - membersToColumns(c->dataMembers()); - fprintf(code, "}\n\n"); - } - return false; -} - -bool -Slice2Type::visitStructStart(const Slice::StructPtr & s) -{ - if (s->hasMetaData("project2:type")) { - fprintf(code, "template <>\nvoid IceType< %s::%s >::ForEachDataMember(const %s::%s & obj, const IceEachDataMemberValue & func)\n{\n", - module.c_str(), s->name().c_str(), - module.c_str(), s->name().c_str()); - membersToVariables(s->dataMembers(), "obj."); - fprintf(code, "}\n\n"); - - fprintf(code, "template <>\nvoid IceType< %s::%s >::CreateColumns(const IceEachDataMemberName & func)\n{\n", - module.c_str(), s->name().c_str()); - membersToColumns(s->dataMembers()); - fprintf(code, "}\n\n"); - } - return false; -} - -void -Slice2Type::membersToVariables(const Slice::DataMemberList & members, const std::string & access) const -{ - BOOST_FOREACH(const auto & m, members) { - if (m->optional()) { - fprintf(code, "\tfunc(IceConvert< IceUtil::Optional< %s> >::ToVariable(%s%s));\n", - Slice::typeToString(m->type()).c_str(), - access.c_str(), - m->name().c_str()); - } - else { - fprintf(code, "\tfunc(IceConvert< %s >::ToVariable(%s%s));\n", - Slice::typeToString(m->type()).c_str(), - access.c_str(), - m->name().c_str()); - } - } -} - -void -Slice2Type::membersToColumns(const Slice::DataMemberList & members) const -{ - BOOST_FOREACH(const auto & m, members) { - fprintf(code, "\tfunc(\"%s\");\n", - m->name().c_str()); - } -} - diff --git a/project2/ice/slice2Type.h b/project2/ice/slice2Type.h deleted file mode 100644 index e2b94fc..0000000 --- a/project2/ice/slice2Type.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef ICEBUILDPRESENTER_H -#define ICEBUILDPRESENTER_H - -#include <Slice/Parser.h> - -class Slice2Type : public Slice::ParserVisitor { - public: - Slice2Type(FILE * c); - virtual bool visitModuleStart(const Slice::ModulePtr & m); - virtual void visitModuleEnd(const Slice::ModulePtr & m); - virtual void visitClassDecl(const Slice::ClassDeclPtr&); - virtual bool visitExceptionStart(const Slice::ExceptionPtr&); - virtual bool visitClassDefStart(const Slice::ClassDefPtr&); - virtual bool visitStructStart(const Slice::StructPtr&); - - private: - void membersToVariables(const Slice::DataMemberList &, const std::string &) const; - void membersToColumns(const Slice::DataMemberList &) const; - FILE * code; - std::string module; -}; - -#endif - - diff --git a/project2/ice/tests/Jamfile.jam b/project2/ice/tests/Jamfile.jam deleted file mode 100644 index 976f34d..0000000 --- a/project2/ice/tests/Jamfile.jam +++ /dev/null @@ -1,25 +0,0 @@ -import testing ; - -lib test : - test.ice - : - <library>..//Ice - <library>..//IceUtil - <library>..//pthread - ; - -path-constant me : . ; - -unit-test testClient : - [ glob testClient.cpp ] - : - <define>ROOT=\"$(me)\" - <dependency>test.ice - <library>..//p2iceclient - <library>../../ut//p2ut - <library>../../basics//p2basics - <library>..//Ice - <library>..//IceUtil - <library>..//boost_filesystem - ; - diff --git a/project2/ice/tests/test.ice b/project2/ice/tests/test.ice deleted file mode 100644 index 3c18999..0000000 --- a/project2/ice/tests/test.ice +++ /dev/null @@ -1,9 +0,0 @@ -module test { - interface a - { - ["project2:task"] - void someTask(); - - }; -}; - diff --git a/project2/ice/tests/testClient.cpp b/project2/ice/tests/testClient.cpp deleted file mode 100644 index 7cd960f..0000000 --- a/project2/ice/tests/testClient.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#define BOOST_TEST_MODULE Client -#include <boost/test/unit_test.hpp> -#include <boost/filesystem/operations.hpp> -#include "iceClient.h" -#include <testOptionsSource.h> - -#define XSTR(s) STR(s) -#define STR(s) #s -const auto self = boost::filesystem::canonical("/proc/self/exe"); -const boost::filesystem::path iceroot(XSTR(ROOT)); - -BOOST_AUTO_TEST_CASE( compile_client_full ) -{ - const std::string tmpdir = "/tmp/ut/project2.slice/full"; - boost::filesystem::remove_all(tmpdir); - - TestOptionsSource::LoadTestOptions({ - { "ice.compile.tmpdir", tmpdir }, - { "ice.client.slice", (iceroot / "test.ice").string() } - }); -} - -BOOST_AUTO_TEST_CASE( compile_client_clientOnly ) -{ - const std::string tmpdir = "/tmp/ut/project2.slice/clientOnly"; - boost::filesystem::remove_all(tmpdir); - - TestOptionsSource::LoadTestOptions({ - { "library", (self.parent_path() / "libtest.so").string() }, - { "ice.compile.tmpdir", tmpdir }, - { "ice.client.sliceclient", (iceroot / "test.ice").string() } - }); -} - diff --git a/project2/ice/unittests/Jamfile.jam b/project2/ice/unittests/Jamfile.jam new file mode 100644 index 0000000..a793918 --- /dev/null +++ b/project2/ice/unittests/Jamfile.jam @@ -0,0 +1,94 @@ +import testing ; + +lib unittest : + unittest.ice + : + <slicer>no + <library>..//Ice + <library>..//IceUtil + <library>..//pthread + ; + +lib unittestr : + unittest.ice + : + <slicer>yes + <library>..//Ice + <library>..//slicer + <library>..//IceUtil + <library>..//pthread + : : + <include>. + ; + +path-constant me : . ; + +unit-test testClientCompile : + [ glob testClientCompile.cpp ] + : + <define>ROOT=\"$(me)\" + <dependency>unittest.ice + <dependency>unittest + <dependency>unittestr + <library>..//p2iceclient + <library>../../ut//p2ut + <library>../../xml//p2xml + <library>../../basics//p2basics + <library>..//Ice + <library>..//IceUtil + <library>..//boost_filesystem + <dependency>testClient.xml + ; + +unit-test testClient : + [ glob testClient.cpp ] + : + <define>ROOT=\"$(me)\" + <dependency>unittest.ice + <library>unittestr + <implicit-dependency>unittestr + <library>..//p2iceclient + <library>../../ut//p2ut + <library>../../xml//p2xml + <library>../../basics//p2basics + <library>..//Ice + <library>..//IceUtil + <library>..//boost_filesystem + <dependency>testClient.xml + ; + +unit-test testDaemonCompile : + [ glob testDaemonCompile.cpp ] + : + <define>ROOT=\"$(me)\" + <dependency>unittest.ice + <dependency>unittest + <dependency>unittestr + <library>..//p2icedaemon + <library>../../ut//p2ut + <library>../../basics//p2basics + <library>..//Ice + <library>..//IceUtil + <library>..//boost_filesystem + ; + +unit-test testDaemon : + [ glob testDaemon.cpp ] + : + <define>ROOT=\"$(me)\" + <dependency>unittest.ice + <library>unittestr + <implicit-dependency>unittestr + <library>..//p2icedaemon + <library>../../ut//p2ut + <library>../../xml//p2xml + <library>../../basics//p2basics + <library>..//Ice + <library>..//IceUtil + <library>..//boost_filesystem +#<dependency>testDaemon/task.xml +#<dependency>testDaemon/taskParams.xml +#<dependency>testDaemon/view.xml +#<dependency>testDaemon/viewParams.xml + ; + diff --git a/project2/ice/unittests/expected/clientPresenter.log b/project2/ice/unittests/expected/clientPresenter.log new file mode 100644 index 0000000..cda61fc --- /dev/null +++ b/project2/ice/unittests/expected/clientPresenter.log @@ -0,0 +1,29 @@ +init +addNewRowSet: somerows +addNewArray: rec(1) +addNewRow: rec +addNamedValue: a=1 +addNamedValue: b=test a +finishRow +addNewRow: rec +addNamedValue: a=2 +addNamedValue: b=test b +finishRow +finishArray: (1) +finishRowSet +addNewRowSet: somerowsparams +addNewArray: rec(1) +addNewRow: rec +addNamedValue: a=0 +addNamedValue: b=before +finishRow +addNewRow: rec +addNamedValue: a=2 +addNamedValue: b=second +finishRow +addNewRow: rec +addNamedValue: a=2 +addNamedValue: b=after +finishRow +finishArray: (1) +finishRowSet diff --git a/project2/ice/unittests/testClient.cpp b/project2/ice/unittests/testClient.cpp new file mode 100644 index 0000000..e5d45b7 --- /dev/null +++ b/project2/ice/unittests/testClient.cpp @@ -0,0 +1,122 @@ +#define BOOST_TEST_MODULE Client +#include <boost/test/unit_test.hpp> +#include <boost/filesystem/operations.hpp> +#include "iceClient.h" +#include <testOptionsSource.h> +#include <task.h> +#include <exceptions.h> +#include <scripts.h> +#include <xmlScriptParser.h> +#include <testScriptHost.h> +#include <scopeObject.h> +#include <unittest.h> + +#define XSTR(s) STR(s) +#define STR(s) #s +const auto bindir = boost::filesystem::canonical("/proc/self/exe").parent_path(); +const boost::filesystem::path iceroot(XSTR(ROOT)); +const auto headers = iceroot.parent_path().parent_path(); + +class Dummy : public UnitTest::SimpleInterface { + public: + Dummy() : + execCount(0) + { + } + + UnitTest::Simples SomeRows(const Ice::Current&) + { + UnitTest::Simples rtn { + new UnitTest::Simple { 1, "test a" }, + new UnitTest::Simple { 2, "test b" } + }; + execCount += 1; + return rtn; + } + + UnitTest::Simples SomeRowsParams(Ice::Int pi, const std::string & ps, const Ice::Current&) + { + UnitTest::Simples rtn { + new UnitTest::Simple { 0, "before" }, + new UnitTest::Simple { pi, ps }, + new UnitTest::Simple { 2, "after" } + }; + execCount += 1; + return rtn; + } + + void SomeTask(const Ice::Current&) + { + execCount += 1; + } + + void SomeTaskParams(Ice::Int, const std::string&, const Ice::Current&) + { + execCount += 1; + } + + unsigned int execCount; +}; + + +static +void +commonTests() +{ + BOOST_TEST_CHECKPOINT("Verify loaded"); + BOOST_REQUIRE(ElementLoader::getFor("UnitTest-SimpleInterface-SomeTask")); + BOOST_REQUIRE(ElementLoader::getFor("UnitTest-SimpleInterface-SomeTaskParams")); + BOOST_REQUIRE(ElementLoader::getFor("UnitTest-SimpleInterface-SomeRows")); + BOOST_REQUIRE(ElementLoader::getFor("UnitTest-SimpleInterface-SomeRowsParams")); + + BOOST_TEST_CHECKPOINT("Load test script"); + ScriptReaderPtr r = new XmlScriptParser(iceroot / "testClient.xml"); + + BOOST_TEST_CHECKPOINT("Initialize ICE service"); + int paramCount = 0; + Ice::CommunicatorPtr ic = Ice::initialize(paramCount, NULL); + auto adapter = ic->createObjectAdapterWithEndpoints("Adp", "tcp -p 12000"); + IceUtil::Handle<Dummy> dummy = new Dummy(); + adapter->add(dummy, ic->stringToIdentity("testObject")); + adapter->activate(); + ScopeObject _([&ic]{ ic->destroy(); }); + + BOOST_TEST_CHECKPOINT("Execute test script"); + boost::intrusive_ptr<TestScriptHost> sr = new TestScriptHost(r); + BOOST_REQUIRE_EQUAL(dummy->execCount, 0); + sr->process(NULL); + BOOST_REQUIRE_EQUAL(dummy->execCount, 4); + BOOST_REQUIRE_EQUAL(sr->GetPresenterData(), iceroot / "expected" / "clientPresenter.log"); +} + +static +void +unloadTests() +{ + BOOST_TEST_CHECKPOINT("Verify unloaded"); + BOOST_REQUIRE_THROW(ElementLoader::getFor("UnitTest-SimpleInterface-SomeTask"), NotSupported); + BOOST_REQUIRE_THROW(ElementLoader::getFor("UnitTest-SimpleInterface-SomeTaskParams"), NotSupported); + BOOST_REQUIRE_THROW(ElementLoader::getFor("UnitTest-SimpleInterface-SomeRows"), NotSupported); + BOOST_REQUIRE_THROW(ElementLoader::getFor("UnitTest-SimpleInterface-SomeRowsParams"), NotSupported); +} + +BOOST_AUTO_TEST_CASE( test_client ) +{ + const std::string tmpdir = "/tmp/ut/project2.slice-client"; + BOOST_TEST_CHECKPOINT("Clean up"); + boost::filesystem::remove_all(tmpdir); + + BOOST_TEST_CHECKPOINT("Configure, compile, link, load"); + TestOptionsSource::LoadTestOptions({ + { "library", (bindir / "slicer-yes" / "libunittestr.so").string() }, + { "common.datasourceRoot", iceroot.string() }, + { "ice.compile.tmpdir", tmpdir }, + { "ice.compile.headers", headers.string() }, + { "ice.client.slicerclient", (iceroot / "unittest.ice").string() } + }); + commonTests(); + + TestOptionsSource::LoadTestOptions({ }); + unloadTests(); +} + diff --git a/project2/ice/unittests/testClient.xml b/project2/ice/unittests/testClient.xml new file mode 100644 index 0000000..4ae33b1 --- /dev/null +++ b/project2/ice/unittests/testClient.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<test xmlns:xi="http://www.w3.org/2001/XInclude" + xmlns:p2="http://project2.randomdan.homeip.net"> + <p2:UnitTest-SimpleInterface-SomeTask datasource="unittest-ice-datasource" objectId="testObject" /> + <p2:UnitTest-SimpleInterface-SomeTaskParams datasource="unittest-ice-datasource" objectId="testObject" a="1" b="first" /> + <p2:UnitTest-SimpleInterface-SomeRows name="rows" datasource="unittest-ice-datasource" objectId="testObject" /> + <p2:UnitTest-SimpleInterface-SomeRowsParams name="rowsParams" datasource="unittest-ice-datasource" objectId="testObject" a="2" b="second" /> + <p2:view source="rows" recordname="rec" rootname="somerows" /> + <p2:view source="rowsParams" recordname="rec" rootname="somerowsparams" /> +</test> diff --git a/project2/ice/unittests/testClientCompile.cpp b/project2/ice/unittests/testClientCompile.cpp new file mode 100644 index 0000000..c86b826 --- /dev/null +++ b/project2/ice/unittests/testClientCompile.cpp @@ -0,0 +1,104 @@ +#define BOOST_TEST_MODULE ClientCompile +#include <boost/test/unit_test.hpp> +#include <boost/filesystem/operations.hpp> +#include "iceClient.h" +#include <testOptionsSource.h> +#include <task.h> +#include <exceptions.h> +#include <scripts.h> +#include <xmlScriptParser.h> +#include <testScriptHost.h> +#include <scopeObject.h> + +#define XSTR(s) STR(s) +#define STR(s) #s +const auto bindir = boost::filesystem::canonical("/proc/self/exe").parent_path(); +const boost::filesystem::path iceroot(XSTR(ROOT)); +const auto headers = iceroot.parent_path().parent_path(); + +static +void +commonTests() +{ + BOOST_TEST_CHECKPOINT("Verify loaded"); + BOOST_REQUIRE(ElementLoader::getFor("UnitTest-SimpleInterface-SomeTask")); + BOOST_REQUIRE(ElementLoader::getFor("UnitTest-SimpleInterface-SomeTaskParams")); + BOOST_REQUIRE(ElementLoader::getFor("UnitTest-SimpleInterface-SomeRows")); + BOOST_REQUIRE(ElementLoader::getFor("UnitTest-SimpleInterface-SomeRowsParams")); + + BOOST_TEST_CHECKPOINT("Load test script"); + ScriptReaderPtr r = new XmlScriptParser(iceroot / "testClient.xml"); + BOOST_TEST_CHECKPOINT("Execute test script"); + boost::intrusive_ptr<TestScriptHost> sr = new TestScriptHost(r); +} + +static +void +unloadTests() +{ + BOOST_TEST_CHECKPOINT("Verify unloaded"); + BOOST_REQUIRE_THROW(ElementLoader::getFor("UnitTest-SimpleInterface-SomeTask"), NotSupported); + BOOST_REQUIRE_THROW(ElementLoader::getFor("UnitTest-SimpleInterface-SomeTaskParams"), NotSupported); + BOOST_REQUIRE_THROW(ElementLoader::getFor("UnitTest-SimpleInterface-SomeRows"), NotSupported); + BOOST_REQUIRE_THROW(ElementLoader::getFor("UnitTest-SimpleInterface-SomeRowsParams"), NotSupported); +} + +BOOST_AUTO_TEST_CASE( compile_client_full ) +{ + const std::string tmpdir = "/tmp/ut/project2.slice-clientCompile/full"; + BOOST_TEST_CHECKPOINT("Clean up"); + boost::filesystem::remove_all(tmpdir); + + BOOST_TEST_CHECKPOINT("Configure, compile, link, load"); + TestOptionsSource::LoadTestOptions({ + { "common.datasourceRoot", iceroot.string() }, + { "ice.compile.tmpdir", tmpdir }, + { "ice.compile.headers", headers.string() }, + { "ice.client.slice", (iceroot / "unittest.ice").string() } + }); + commonTests(); + + TestOptionsSource::LoadTestOptions({ }); + unloadTests(); +} + +BOOST_AUTO_TEST_CASE( compile_client_clientOnly ) +{ + const std::string tmpdir = "/tmp/ut/project2.slice-clientCompile/clientOnly"; + BOOST_TEST_CHECKPOINT("Clean up"); + boost::filesystem::remove_all(tmpdir); + + BOOST_TEST_CHECKPOINT("Configure, compile, link, load"); + TestOptionsSource::LoadTestOptions({ + { "library", (bindir / "libunittest.so").string() }, + { "common.datasourceRoot", iceroot.string() }, + { "ice.compile.tmpdir", tmpdir }, + { "ice.compile.headers", headers.string() }, + { "ice.client.sliceclient", (iceroot / "unittest.ice").string() } + }); + commonTests(); + + TestOptionsSource::LoadTestOptions({ }); + unloadTests(); +} + +BOOST_AUTO_TEST_CASE( compile_client_slicer ) +{ + const std::string tmpdir = "/tmp/ut/project2.slice-clientCompile/slicer"; + BOOST_TEST_CHECKPOINT("Clean up"); + boost::filesystem::remove_all(tmpdir); + + BOOST_TEST_CHECKPOINT("Configure, compile, link, load"); + TestOptionsSource::LoadTestOptions({ + { "library", (bindir / "slicer-yes" / "libunittestr.so").string() }, + { "common.datasourceRoot", iceroot.string() }, + { "ice.compile.tmpdir", tmpdir }, + { "ice.compile.headers", headers.string() }, + { "ice.client.slicerclient", (iceroot / "unittest.ice").string() } + }); + commonTests(); + + TestOptionsSource::LoadTestOptions({ }); + unloadTests(); +} + diff --git a/project2/ice/unittests/testDaemon.cpp b/project2/ice/unittests/testDaemon.cpp new file mode 100644 index 0000000..ce2630c --- /dev/null +++ b/project2/ice/unittests/testDaemon.cpp @@ -0,0 +1,48 @@ +#define BOOST_TEST_MODULE Daemon +#include <boost/test/unit_test.hpp> +#include <boost/filesystem/operations.hpp> +#include <testOptionsSource.h> +#include <unittest.h> +#include <iceDaemon.h> + +#define XSTR(s) STR(s) +#define STR(s) #s +const auto bindir = boost::filesystem::canonical("/proc/self/exe").parent_path(); +const boost::filesystem::path iceroot(XSTR(ROOT)); +const auto headers = iceroot.parent_path().parent_path(); + +static +void +commonTests() +{ + BOOST_TEST_CHECKPOINT("Verify loaded"); + BOOST_REQUIRE(IceDaemonAdapterHandlerLoader::getFor("UnitTest")); +} + +static +void +unloadTests() +{ + BOOST_TEST_CHECKPOINT("Verify unloaded"); + BOOST_REQUIRE_THROW(IceDaemonAdapterHandlerLoader::createNew("UnitTest"), NotSupported); +} + +BOOST_AUTO_TEST_CASE( test_daemon ) +{ + const std::string tmpdir = "/tmp/ut/project2.slice-daemon"; + BOOST_TEST_CHECKPOINT("Clean up"); + boost::filesystem::remove_all(tmpdir); + + BOOST_TEST_CHECKPOINT("Configure, compile, link, load"); + TestOptionsSource::LoadTestOptions({ + { "library", (bindir / "slicer-yes" / "libunittestr.so").string() }, + { "ice.compile.tmpdir", tmpdir }, + { "ice.compile.headers", headers.string() }, + { "ice.daemon.slicerdaemon", (iceroot / "unittest.ice").string() } + }); + commonTests(); + + TestOptionsSource::LoadTestOptions({ }); + unloadTests(); +} + diff --git a/project2/ice/unittests/testDaemonCompile.cpp b/project2/ice/unittests/testDaemonCompile.cpp new file mode 100644 index 0000000..7bda6dd --- /dev/null +++ b/project2/ice/unittests/testDaemonCompile.cpp @@ -0,0 +1,83 @@ +#define BOOST_TEST_MODULE DaemonCompile +#include <boost/test/unit_test.hpp> +#include <boost/filesystem/operations.hpp> +#include <testOptionsSource.h> +#include <exceptions.h> +#include <iceDaemon.h> + +#define XSTR(s) STR(s) +#define STR(s) #s +const auto bindir = boost::filesystem::canonical("/proc/self/exe").parent_path(); +const boost::filesystem::path iceroot(XSTR(ROOT)); +const auto headers = iceroot.parent_path().parent_path(); + +static +void +commonTests() +{ + BOOST_REQUIRE(IceDaemonAdapterHandlerLoader::getFor("UnitTest")); +} + +static +void +unloadTests() +{ + BOOST_REQUIRE_THROW(IceDaemonAdapterHandlerLoader::createNew("UnitTest"), NotSupported); +} + +BOOST_AUTO_TEST_CASE( compile_daemon_full ) +{ + const std::string tmpdir = "/tmp/ut/project2.slice-daemonCompile/full"; + BOOST_TEST_CHECKPOINT("Clean up"); + boost::filesystem::remove_all(tmpdir); + + BOOST_TEST_CHECKPOINT("Configure, compile, link, load"); + TestOptionsSource::LoadTestOptions({ + { "ice.compile.tmpdir", tmpdir }, + { "ice.compile.headers", headers.string() }, + { "ice.daemon.slice", (iceroot / "unittest.ice").string() } + }); + commonTests(); + + TestOptionsSource::LoadTestOptions({ }); + unloadTests(); +} + +BOOST_AUTO_TEST_CASE( compile_daemon_daemonOnly ) +{ + const std::string tmpdir = "/tmp/ut/project2.slice-daemonCompile/daemonOnly"; + BOOST_TEST_CHECKPOINT("Clean up"); + boost::filesystem::remove_all(tmpdir); + + BOOST_TEST_CHECKPOINT("Configure, compile, link, load"); + TestOptionsSource::LoadTestOptions({ + { "library", (bindir / "libunittest.so").string() }, + { "ice.compile.tmpdir", tmpdir }, + { "ice.compile.headers", headers.string() }, + { "ice.daemon.slicedaemon", (iceroot / "unittest.ice").string() } + }); + commonTests(); + + TestOptionsSource::LoadTestOptions({ }); + unloadTests(); +} + +BOOST_AUTO_TEST_CASE( compile_daemon_slicer ) +{ + const std::string tmpdir = "/tmp/ut/project2.slice-daemonCompile/slicer"; + BOOST_TEST_CHECKPOINT("Clean up"); + boost::filesystem::remove_all(tmpdir); + + BOOST_TEST_CHECKPOINT("Configure, compile, link, load"); + TestOptionsSource::LoadTestOptions({ + { "library", (bindir / "slicer-yes" / "libunittestr.so").string() }, + { "ice.compile.tmpdir", tmpdir }, + { "ice.compile.headers", headers.string() }, + { "ice.daemon.slicerdaemon", (iceroot / "unittest.ice").string() } + }); + commonTests(); + + TestOptionsSource::LoadTestOptions({ }); + unloadTests(); +} + diff --git a/project2/ice/unittests/unittest-ice-datasource.xml b/project2/ice/unittests/unittest-ice-datasource.xml new file mode 100644 index 0000000..0d067d9 --- /dev/null +++ b/project2/ice/unittests/unittest-ice-datasource.xml @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<p2:icedatasource xmlns:p2="http://project2.randomdan.homeip.net" name="unittest-ice-datasource"> + <endpoint>tcp -p 12000</endpoint> +</p2:icedatasource> diff --git a/project2/ice/unittests/unittest.ice b/project2/ice/unittests/unittest.ice new file mode 100644 index 0000000..60e44bb --- /dev/null +++ b/project2/ice/unittests/unittest.ice @@ -0,0 +1,22 @@ +module UnitTest { + ["project2:type"] + class Simple { + int a; + string b; + }; + + sequence<Simple> Simples; + + interface SimpleInterface + { + ["project2:rows"] + Simples SomeRows(); + ["project2:rows"] + Simples SomeRowsParams(int a, string b); + ["project2:task"] + void SomeTask(); + ["project2:task"] + void SomeTaskParams(int a, string b); + }; +}; + diff --git a/project2/ut/testScriptHost.cpp b/project2/ut/testScriptHost.cpp new file mode 100644 index 0000000..dfdb6ed --- /dev/null +++ b/project2/ut/testScriptHost.cpp @@ -0,0 +1,130 @@ +#include "testScriptHost.h" +#include <glibmm/exception.h> +#include <cxxabi.h> +#include <logger.h> +#include <fstream> + +TestScriptHost::TestScriptHost(ScriptReaderPtr script) : + SourceObject(script->root()), + CommonObjects(script->root()), + CheckHost(script->root()), + TaskHost(script->root()), + ViewHost(script->root()), + MultiRowSetPresenter(Default) +{ + Logger()->message(LOG_DEBUG, __PRETTY_FUNCTION__); +} + +TestScriptHost::~TestScriptHost() +{ + Logger()->message(LOG_DEBUG, __PRETTY_FUNCTION__); +} + +MultiRowSetPresenterPtr TestScriptHost::getPresenter(ExecContext *) const +{ + return const_cast<TestScriptHost *>(this); +} + +void TestScriptHost::process(ExecContext * ec) +{ + runChecks(ec); + execute(ec); + executeViews(ec); +} + +void +TestScriptHost::addNamedValue(const Glib::ustring & name, const VariableType & value) const +{ + presenterData.push_back(stringbf("%s: %s=%s", __FUNCTION__, name, value)); +} + +void +TestScriptHost::addNewRow(const Glib::ustring & name) const +{ + presenterData.push_back(stringbf("%s: %s", __FUNCTION__, name)); +} + +void +TestScriptHost::finishRow() const +{ + presenterData.push_back(stringbf("%s", __FUNCTION__)); +} + +void +TestScriptHost::addNewRowSet(const Glib::ustring & name) const +{ + presenterData.push_back(stringbf("%s: %s", __FUNCTION__, name)); +} + +void +TestScriptHost::addNewRowSet(const Glib::ustring & name, const Glib::ustring & ns) const +{ + presenterData.push_back(stringbf("%s: %s:%s", __FUNCTION__, ns, name)); +} + +void +TestScriptHost::finishRowSet() const +{ + presenterData.push_back(stringbf("%s", __FUNCTION__)); +} + +void +TestScriptHost::addNewArray(const Glib::ustring & name, bool objects) const +{ + presenterData.push_back(stringbf("%s: %s(%s)", __FUNCTION__, name, objects)); +} + +void +TestScriptHost::finishArray(bool objects) const +{ + presenterData.push_back(stringbf("%s: (%s)", __FUNCTION__, objects)); +} + +void +TestScriptHost::init(ExecContext *) +{ + presenterData.push_back(stringbf("%s", __FUNCTION__)); +} + +const PresenterData & +TestScriptHost::GetPresenterData() const +{ + return presenterData; +} + +namespace std { + std::istream & + operator>>(std::istream & s, PresenterData & v) + { + while (true) { + char buf[BUFSIZ]; + s.getline(buf, sizeof(buf)); + if (!s.eof()) { + v.push_back(buf); + } + else { + break; + } + } + return s; + } + + std::ostream & + operator<<(std::ostream & s, const PresenterData & v) + { + BOOST_FOREACH(const auto & e, v) { + s << "[" << e << "]" << std::endl; + } + return s; + } + + bool + operator==(const PresenterData & left, const boost::filesystem::path & rightPath) + { + PresenterData right; + fstream strm(rightPath.string()); + strm >> right; + return (left == right); + } +} + diff --git a/project2/ut/testScriptHost.h b/project2/ut/testScriptHost.h new file mode 100644 index 0000000..a843a4a --- /dev/null +++ b/project2/ut/testScriptHost.h @@ -0,0 +1,42 @@ +#ifndef TESTSCRIPTHOST_H +#define TESTSCRIPTHOST_H + +#include <taskHost.h> +#include <viewHost.h> +#include <presenter.h> +#include <boost/filesystem/path.hpp> + +typedef std::vector<std::string> PresenterData; + +class TestScriptHost : public TaskHost, public ViewHost, public MultiRowSetPresenter { + public: + TestScriptHost(ScriptReaderPtr script); + ~TestScriptHost(); + + MultiRowSetPresenterPtr getPresenter(ExecContext *) const override; + + void process(ExecContext * ec); + void addNamedValue(const Glib::ustring & name, const VariableType & value) const override; + void addNewRow(const Glib::ustring & name) const override; + void finishRow() const override; + void addNewRowSet(const Glib::ustring & name) const override; + void addNewRowSet(const Glib::ustring & name, const Glib::ustring & ns) const override; + void finishRowSet() const override; + void addNewArray(const Glib::ustring & name, bool objects) const override; + void finishArray(bool objects) const override; + void init(ExecContext *) override; + + const PresenterData & GetPresenterData() const; + + private: + mutable PresenterData presenterData; +}; + +namespace std { + bool operator==(const PresenterData &, const boost::filesystem::path &); + std::ostream & operator<<(std::ostream & s, const PresenterData & v); + std::istream & operator>>(std::istream & s, PresenterData & v); +} + +#endif + |