unity-scopes-api-0.4.2+14.04.20140408/0000755000015301777760000000000012320776463017340 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/tools/0000755000015301777760000000000012320776463020500 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/tools/zmq-monitor-host.py0000755000015301777760000000266612320776161024331 0ustar pbusernogroup00000000000000#!/usr/bin/env python # # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michal Hruby # # Binary used to host the monitoring proxy, which forwards messages # from all monitor publishers to all subscribers. # To use the zmq-parser.py you need to have this daemon running. import zmq context = zmq.Context() aggregator = context.socket(zmq.XSUB) aggregator.bind("ipc:///tmp/scopes-monitor") sender = context.socket(zmq.XPUB) sender.bind("ipc:///tmp/scopes-monitor2") poller = zmq.Poller() poller.register(aggregator, zmq.POLLIN) poller.register(sender, zmq.POLLIN) while True: sockets = dict(poller.poll()) # forward XSUB messages to XPUB and vice versa if aggregator in sockets: msg = aggregator.recv() sender.send(msg) if sender in sockets: msg = sender.recv() aggregator.send(msg) unity-scopes-api-0.4.2+14.04.20140408/tools/formatcode.in0000755000015301777760000000366012320776161023156 0ustar pbusernogroup00000000000000#!/bin/sh # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # Simple script to format files with astyle, followed by clang-format (which # undoes some damage that's done by astyle, without wiping out astyle edits we want # to happen). # # usage: formatcode [FILE]... # # If no arguments are provided, we format stdin and write to stdout. astyle="@ASTYLE_COMMAND@" format="@CLANG_FORMAT_COMMAND@" dos2unix="@DOS2UNIX_COMMAND@" # Check that the format commands were found. [ "$astyle" = "ASTYLE_COMMAND-NOTFOUND" -o \ "$dos2unix" = "DOS2UNIX_COMMAND-NOTFOUND" -o \ "$format" = "CLANG_FORMAT_COMMAND-NOTFOUND" ] && { echo "formatcode: cmake did not find all formatting tools" >&2 exit 1 } # If no arguments were provided, read stdin and write stdout. # Recent versions of astyle can't read stdin: http://sourceforge.net/p/astyle/bugs/63/ # astyle 2.03 writes DOS line endings: https://sourceforge.net/p/astyle/bugs/268/ [ $# -eq 0 ] && { tmp=`mktemp` cat >$tmp "$astyle" -q --options=@CMAKE_SOURCE_DIR@/astyle-config -n $tmp "$dos2unix" -q $tmp "$format" -i -style=file $tmp cat $tmp rm -f $tmp exit $? } # Format files in place. "$astyle" --options=@CMAKE_SOURCE_DIR@/astyle-config -n "$@" [ $? -ne 0 ] && exit $? "$dos2unix" -q "$@" "$format" -i -style=file $files "$@" exit $? unity-scopes-api-0.4.2+14.04.20140408/tools/CMakeLists.txt0000644000015301777760000000005112320776161023227 0ustar pbusernogroup00000000000000configure_file(formatcode.in formatcode) unity-scopes-api-0.4.2+14.04.20140408/tools/format-files.sh0000755000015301777760000000303212320776161023420 0ustar pbusernogroup00000000000000#!/bin/sh # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # Simple script to run the code base through astyle, followed by clang-format (which # undoes some damage that's done by astyle, without wiping out astyle edits we want # to happen). # # If either program makes a mess of some file such that it won't compile anymore # or otherwise gets adorned with unacceptable edits, add the file to the list # of files to filter out (grep -v below). usage() { echo usage: format-files project_dir astyle_cmd clang_format_cmd 2>&1 exit 1 } [ $# -ne 3 ] && usage dir="$1" astyle="$2" format="$3" files=`find "$dir" -name '*.h' -o -name '*.cpp' -o -name '*.c' \ | grep -v UnityScopesApi_tp.h` "$astyle" --options="$dir"/astyle-config -n $files [ $? -ne 0 ] && exit $? # astyle 2.03 writes DOS line endings: https://sourceforge.net/p/astyle/bugs/268/ dos2unix -q $files "$format" -i -style=file $files exit $? unity-scopes-api-0.4.2+14.04.20140408/tools/zmq-parser.py0000755000015301777760000000666012320776161023161 0ustar pbusernogroup00000000000000#!/usr/bin/env python # # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michal Hruby # # A monitor listening to all scopes capnproto messages passed via zeromq. # Meant to be used for debugging. Note that you need to enable the monitoring # code inside ZmqObject for this to capture anything - this is currently done # via a cmake option (-DIPC_MONITORING=ON). You also need to run # the zmq-monitor-host.py script. import zmq import sys import capnp from datetime import datetime schema_base_dir = "../src/scopes/internal/zmq_middleware/capnproto/" # location of c++.capnp import_dirs = ["/usr/include", "/usr/local/include"] # Careful here! Order matters, capnp can crash otherwise proxy_capnp = capnp.load(schema_base_dir + "Proxy.capnp", None, import_dirs) valdict_capnp = capnp.load(schema_base_dir + "ValueDict.capnp", None, import_dirs) scope_capnp = capnp.load(schema_base_dir + "Scope.capnp", None, import_dirs) scoped_capnp = capnp.load(schema_base_dir + "ScopeDict.capnp", None, import_dirs) msg_capnp = capnp.load(schema_base_dir + "Message.capnp", None, import_dirs) query_capnp = capnp.load(schema_base_dir + "Query.capnp", None, import_dirs) queryc_capnp = capnp.load(schema_base_dir + "QueryCtrl.capnp", None, import_dirs) reg_capnp = capnp.load(schema_base_dir + "Registry.capnp", None, import_dirs) reply_capnp = capnp.load(schema_base_dir + "Reply.capnp", None, import_dirs) context = zmq.Context() receiver = context.socket(zmq.SUB) # the second argument can't be unicode, using encode() will make it work in py3 receiver.setsockopt(zmq.SUBSCRIBE, "".encode()) receiver.connect("ipc:///tmp/scopes-monitor2") def increase_indent(text, num_spaces = 2): prefix = " " * num_spaces return "\n".join(map(lambda x: prefix + x, text.split('\n'))) msg_num = 0 while True: message = receiver.recv(0, False) cur_time = datetime.now().strftime("%H:%M:%S.%f") print(cur_time, "received", len(message.bytes), "byte message:") # FIXME: how come we never see Reply messages? request = msg_capnp.Request.from_bytes(message.bytes) print(request) inParams = request.inParams nested = None if inParams: # capnp message don't include their own schema, so let's hackity hack if request.opName == "create_query": nested = inParams.as_struct(scope_capnp.CreateQueryRequest) elif request.opName == "run": nested = inParams.as_struct(query_capnp.RunRequest) elif request.opName == "push": nested = inParams.as_struct(reply_capnp.PushRequest) if nested: print(" inParams as <%s>:" % nested.schema.node.displayName) print(increase_indent(str(nested))) elif request._has("inParams"): print(" inParams: [unknown message type]") print("==========================================") msg_num = msg_num + 1 unity-scopes-api-0.4.2+14.04.20140408/tools/create_globalheader.py0000755000015301777760000000262612320776161025012 0ustar pbusernogroup00000000000000#!/usr/bin/env python3 # # Copyright (C) 2014 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Jussi Pakkanen from glob import glob import sys, os def build_header(outfile, incroots): ofile = open(outfile, 'w') headers = [] for r in incroots: headers += glob(os.path.join(r, 'unity/scopes', '*.h')) headers = [os.path.split(f)[1] for f in headers] headers.sort() ofile.write("#ifndef UNITY_SCOPES_H\n") ofile.write("#define UNITY_SCOPES_H\n") for f in headers: line = '#include\n' % f ofile.write(line) ofile.write("#endif\n") if __name__ == '__main__': if len(sys.argv) <= 3: print(sys.argv[0], 'outfile include_roots') sys.exit(1) outfile = sys.argv[1] incroots = sys.argv[2:] build_header(outfile, incroots) unity-scopes-api-0.4.2+14.04.20140408/valgrind-suppress0000644000015301777760000000436612320776161022757 0ustar pbusernogroup00000000000000# Leak suppressions for Ice below are all for bogus "possibly lost" reports. # In all cases, we ultimately end up in the std::string library, which does # weird things with pointers that point somewhere into the middle of an allocated # block to avoid copies. In turn, that causes bogus reports from valgrind. # Bogus "possibly leaked" reports for pthreads { Thread create leak Memcheck:Leak fun:calloc fun:_dl_allocate_tls fun:pthread_create@@GLIBC_2.2.5 ... } # Bogus "possibly leaked" reports for glib .ini file parser { g_keyfile_new_leak Memcheck:Leak ... fun:g_key_file_new ... } { g_keyfile_load_leak Memcheck:Leak ... fun:g_key_file_load_from_file ... } # Bogus "possibly lost" report for # # string s("hello"); # foo(s + " world"); { StringCatenation Memcheck:Leak fun:_Znwm fun:_ZNSs4_Rep9_S_createEmmRKSaIcE fun:_ZNSs4_Rep8_M_cloneERKSaIcEm fun:_ZNSs7reserveEm fun:_ZNSs6appendEPKcm ... } # Leak in dynamic linker { DynLinker Memcheck:Leak fun:calloc obj:* fun:_Z24__tracepoints__ptrs_initv fun:call_init.part.0 fun:_dl_init obj:/lib/x86_64-linux-gnu/ld-2.18.so } { DynLinker2 Memcheck:Leak fun:calloc obj:* fun:__tracepoints__ptrs_init fun:call_init.part.0 fun:_dl_init obj:/lib/x86_64-linux-gnu/ld-2.18.so } # False positives for memory leaks in Qt { QNetworkConfigurationManager Memcheck:Leak fun:*alloc ... fun:_ZN35QNetworkConfigurationManagerPrivate20updateConfigurationsEv fun:_ZN35QNetworkConfigurationManagerPrivate10initializeEv } { QCoreApplication Memcheck:Leak fun:realloc ... fun:_ZN7QObject5eventEP6QEvent fun:_ZN16QCoreApplication6notifyEP7QObjectP6QEvent } { QNetworkAccessManager Memcheck:Leak ... fun:_ZN21QNetworkAccessManager13createRequestENS_9OperationERK15QNetworkRequestP9QIODevice fun:_ZN21QNetworkAccessManager3getERK15QNetworkRequest } { QFactoryLoader Memcheck:Leak fun:*alloc ... fun:_ZNK14QFactoryLoader8instanceEi } # Bogus "invalid read" reports for ::putenv and ::genenv { putenv_read Memcheck:Addr1 ... fun:putenv ... } { getenv_read Memcheck:Addr2 ... fun:getenv ... } unity-scopes-api-0.4.2+14.04.20140408/cmake/0000755000015301777760000000000012320776463020420 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/cmake/modules/0000755000015301777760000000000012320776463022070 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/cmake/modules/FindLcov.cmake0000644000015301777760000000172012320776161024571 0ustar pbusernogroup00000000000000# - Find lcov # Will define: # # LCOV_EXECUTABLE - the lcov binary # GENHTML_EXECUTABLE - the genhtml executable # # Copyright (C) 2010 by Johannes Wienke # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General # Public License as published by the Free Software Foundation; # either version 2, 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. # INCLUDE(FindPackageHandleStandardArgs) FIND_PROGRAM(LCOV_EXECUTABLE lcov) FIND_PROGRAM(GENHTML_EXECUTABLE genhtml) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lcov DEFAULT_MSG LCOV_EXECUTABLE GENHTML_EXECUTABLE) # only visible in advanced view MARK_AS_ADVANCED(LCOV_EXECUTABLE GENHTML_EXECUTABLE) unity-scopes-api-0.4.2+14.04.20140408/cmake/modules/EnableCoverageReport.cmake0000644000015301777760000001641412320776161027131 0ustar pbusernogroup00000000000000# - Creates a special coverage build type and target on GCC. # # Defines a function ENABLE_COVERAGE_REPORT which generates the coverage target # for selected targets. Optional arguments to this function are used to filter # unwanted results using globbing expressions. Moreover targets with tests for # the source code can be specified to trigger regenerating the report if the # test has changed # # ENABLE_COVERAGE_REPORT(TARGETS target... [FILTER filter...] [TESTS test targets...]) # # To generate a coverage report first build the project with # CMAKE_BUILD_TYPE=coverage, then call make test and afterwards make coverage. # # The coverage report is based on gcov. Depending on the availability of lcov # a HTML report will be generated and/or an XML report of gcovr is found. # The generated coverage target executes all found solutions. Special targets # exist to create e.g. only the xml report: coverage-xml. # # Copyright (C) 2010 by Johannes Wienke # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General # Public License as published by the Free Software Foundation; # either version 2, 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. # INCLUDE(ParseArguments) FIND_PACKAGE(Lcov) FIND_PACKAGE(gcovr) FUNCTION(ENABLE_COVERAGE_REPORT) # argument parsing PARSE_ARGUMENTS(ARG "FILTER;TARGETS;TESTS" "" ${ARGN}) SET(COVERAGE_RAW_FILE "${CMAKE_BINARY_DIR}/coverage.raw.info") SET(COVERAGE_FILTERED_FILE "${CMAKE_BINARY_DIR}/coverage.info") SET(COVERAGE_REPORT_DIR "${CMAKE_BINARY_DIR}/coveragereport") SET(COVERAGE_XML_FILE "${CMAKE_BINARY_DIR}/coverage.xml") SET(COVERAGE_XML_COMMAND_FILE "${CMAKE_BINARY_DIR}/coverage-xml.cmake") # decide if there is any tool to create coverage data SET(TOOL_FOUND FALSE) IF(LCOV_FOUND OR GCOVR_FOUND) SET(TOOL_FOUND TRUE) ENDIF() IF(NOT TOOL_FOUND) MESSAGE(STATUS "Cannot enable coverage targets because neither lcov nor gcovr are found.") ENDIF() STRING(TOLOWER "${CMAKE_BUILD_TYPE}" COVERAGE_BUILD_TYPE) IF(CMAKE_COMPILER_IS_GNUCXX AND TOOL_FOUND AND "${COVERAGE_BUILD_TYPE}" MATCHES "coverage") MESSAGE(STATUS "Coverage support enabled for targets: ${ARG_TARGETS}") # create coverage build type SET(CMAKE_CXX_FLAGS_COVERAGE ${CMAKE_CXX_FLAGS_DEBUG} PARENT_SCOPE) SET(CMAKE_C_FLAGS_COVERAGE ${CMAKE_C_FLAGS_DEBUG} PARENT_SCOPE) SET(CMAKE_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPES} coverage PARENT_SCOPE) # instrument targets SET_TARGET_PROPERTIES(${ARG_TARGETS} PROPERTIES COMPILE_FLAGS --coverage LINK_FLAGS --coverage) # html report IF (LCOV_FOUND) MESSAGE(STATUS "Enabling HTML coverage report") # set up coverage target ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_RAW_FILE} COMMAND ${LCOV_EXECUTABLE} -c -d ${CMAKE_BINARY_DIR} -o ${COVERAGE_RAW_FILE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Collecting coverage data" DEPENDS ${ARG_TARGETS} ${ARG_TESTS} VERBATIM) # filter unwanted stuff LIST(LENGTH ARG_FILTER FILTER_LENGTH) IF(${FILTER_LENGTH} GREATER 0) SET(FILTER COMMAND ${LCOV_EXECUTABLE}) FOREACH(F ${ARG_FILTER}) SET(FILTER ${FILTER} -r ${COVERAGE_FILTERED_FILE} ${F}) ENDFOREACH() SET(FILTER ${FILTER} -o ${COVERAGE_FILTERED_FILE}) ELSE() SET(FILTER "") ENDIF() ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_FILTERED_FILE} COMMAND ${LCOV_EXECUTABLE} -e ${COVERAGE_RAW_FILE} "${CMAKE_SOURCE_DIR}*" -o ${COVERAGE_FILTERED_FILE} ${FILTER} DEPENDS ${COVERAGE_RAW_FILE} COMMENT "Filtering recorded coverage data for project-relevant entries" VERBATIM) ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_REPORT_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory ${COVERAGE_REPORT_DIR} COMMAND ${GENHTML_EXECUTABLE} --legend --show-details -t "${PROJECT_NAME} test coverage" -o ${COVERAGE_REPORT_DIR} ${COVERAGE_FILTERED_FILE} DEPENDS ${COVERAGE_FILTERED_FILE} COMMENT "Generating HTML coverage report in ${COVERAGE_REPORT_DIR}" VERBATIM) ADD_CUSTOM_TARGET(coverage-html DEPENDS ${COVERAGE_REPORT_DIR}) ENDIF() # xml coverage report IF(GCOVR_FOUND) MESSAGE(STATUS "Enabling XML coverage report") # filter unwanted stuff SET(GCOV_FILTER "") LIST(LENGTH ARG_FILTER FILTER_LENGTH) IF(${FILTER_LENGTH} GREATER 0) FOREACH(F ${ARG_FILTER}) SET(GCOV_FILTER "${GCOV_FILTER} -e \"${F}\"") ENDFOREACH() ENDIF() # gcovr cannot write directly to a file so the execution needs to # be wrapped in a cmake file that generates the file output FILE(WRITE ${COVERAGE_XML_COMMAND_FILE} "SET(ENV{LANG} en)\n") FILE(APPEND ${COVERAGE_XML_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND \"${GCOVR_EXECUTABLE}\" -x -r \"${CMAKE_SOURCE_DIR}\" ${GCOV_FILTER} OUTPUT_FILE \"${COVERAGE_XML_FILE}\" WORKING_DIRECTORY \"${CMAKE_BINARY_DIR}\")\n") ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_XML_FILE} COMMAND ${CMAKE_COMMAND} ARGS -P ${COVERAGE_XML_COMMAND_FILE} COMMENT "Generating coverage XML report" VERBATIM) ADD_CUSTOM_TARGET(coverage-xml DEPENDS ${COVERAGE_XML_FILE}) ENDIF() # provide a global coverage target executing both steps if available SET(GLOBAL_DEPENDS "") IF(LCOV_FOUND) LIST(APPEND GLOBAL_DEPENDS ${COVERAGE_REPORT_DIR}) ENDIF() IF(GCOVR_FOUND) LIST(APPEND GLOBAL_DEPENDS ${COVERAGE_XML_FILE}) ENDIF() IF(LCOV_FOUND OR GCOVR_FOUND) ADD_CUSTOM_TARGET(coverage DEPENDS ${GLOBAL_DEPENDS}) ENDIF() ENDIF() # This gets rid of any stale .gcda files. Run this if a running a binary causes lots of messages about # about a "merge mismatch for summaries". ADD_CUSTOM_TARGET(clean-coverage COMMAND find ${CMAKE_BINARY_DIR} -name '*.gcda' | xargs rm -f) ENDFUNCTION() unity-scopes-api-0.4.2+14.04.20140408/cmake/modules/Findgcovr.cmake0000644000015301777760000000170212320776161025006 0ustar pbusernogroup00000000000000# - Find gcovr scrip # Will define: # # GCOVR_EXECUTABLE - the gcovr script # # Uses: # # GCOVR_ROOT - root to search for the script # # Copyright (C) 2011 by Johannes Wienke # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General # Public License as published by the Free Software Foundation; # either version 2, 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. # INCLUDE(FindPackageHandleStandardArgs) FIND_PROGRAM(GCOVR_EXECUTABLE gcovr HINTS ${GCOVR_ROOT} "${GCOVR_ROOT}/bin") FIND_PACKAGE_HANDLE_STANDARD_ARGS(gcovr DEFAULT_MSG GCOVR_EXECUTABLE) # only visible in advanced view MARK_AS_ADVANCED(GCOVR_EXECUTABLE) unity-scopes-api-0.4.2+14.04.20140408/cmake/modules/ParseArguments.cmake0000644000015301777760000000340612320776161026030 0ustar pbusernogroup00000000000000# Parse arguments passed to a function into several lists separated by # upper-case identifiers and options that do not have an associated list e.g.: # # SET(arguments # hello OPTION3 world # LIST3 foo bar # OPTION2 # LIST1 fuz baz # ) # PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "OPTION1;OPTION2;OPTION3" ${arguments}) # # results in 7 distinct variables: # * ARG_DEFAULT_ARGS: hello;world # * ARG_LIST1: fuz;baz # * ARG_LIST2: # * ARG_LIST3: foo;bar # * ARG_OPTION1: FALSE # * ARG_OPTION2: TRUE # * ARG_OPTION3: TRUE # # taken from http://www.cmake.org/Wiki/CMakeMacroParseArguments MACRO(PARSE_ARGUMENTS prefix arg_names option_names) SET(DEFAULT_ARGS) FOREACH(arg_name ${arg_names}) SET(${prefix}_${arg_name}) ENDFOREACH(arg_name) FOREACH(option ${option_names}) SET(${prefix}_${option} FALSE) ENDFOREACH(option) SET(current_arg_name DEFAULT_ARGS) SET(current_arg_list) FOREACH(arg ${ARGN}) SET(larg_names ${arg_names}) LIST(FIND larg_names "${arg}" is_arg_name) IF (is_arg_name GREATER -1) SET(${prefix}_${current_arg_name} ${current_arg_list}) SET(current_arg_name ${arg}) SET(current_arg_list) ELSE (is_arg_name GREATER -1) SET(loption_names ${option_names}) LIST(FIND loption_names "${arg}" is_option) IF (is_option GREATER -1) SET(${prefix}_${arg} TRUE) ELSE (is_option GREATER -1) SET(current_arg_list ${current_arg_list} ${arg}) ENDIF (is_option GREATER -1) ENDIF (is_arg_name GREATER -1) ENDFOREACH(arg) SET(${prefix}_${current_arg_name} ${current_arg_list}) ENDMACRO(PARSE_ARGUMENTS) unity-scopes-api-0.4.2+14.04.20140408/test/0000755000015301777760000000000012320776463020317 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/0000755000015301777760000000000012320776463021445 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/0000755000015301777760000000000012320776463022741 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Category/0000755000015301777760000000000012320776463024516 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Category/Category_test.cpp0000644000015301777760000000431412320776161030033 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include using namespace std; using namespace unity; using namespace unity::scopes; using namespace unity::scopes::internal; TEST(Category, basic) { CategoryRegistry reg; CategoryRenderer rdr("{\"a\":1}"); auto cat = reg.register_category("a", "title", "icon", rdr); EXPECT_TRUE(cat != nullptr); EXPECT_EQ("a", cat->id()); EXPECT_EQ("title", cat->title()); EXPECT_EQ("icon", cat->icon()); EXPECT_EQ("{\"a\":1}", cat->renderer_template().data()); } TEST(Category, serialize) { CategoryRegistry reg; CategoryRenderer rdr("{\"a\":1}"); { auto cat = reg.register_category("a", "title", "icon", rdr); auto vm = cat->serialize(); EXPECT_EQ("a", vm["id"].get_string()); EXPECT_EQ("title", vm["title"].get_string()); EXPECT_EQ("icon", vm["icon"].get_string()); EXPECT_EQ("{\"a\":1}", vm["renderer_template"].get_string()); } } TEST(Category, deserialize) { VariantMap vm; vm["id"] = "b"; vm["title"] = "title"; vm["icon"] = "icon"; vm["renderer_template"] = "{\"a\":1}"; CategoryRegistry reg; auto cat = reg.register_category(vm); EXPECT_TRUE(cat != nullptr); EXPECT_EQ("b", cat->id()); EXPECT_EQ("title", cat->title()); EXPECT_EQ("icon", cat->icon()); EXPECT_EQ("{\"a\":1}", cat->renderer_template().data()); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Category/CMakeLists.txt0000644000015301777760000000020312320776161027244 0ustar pbusernogroup00000000000000add_executable(Category_test Category_test.cpp) target_link_libraries(Category_test ${TESTLIBS}) add_test(Category Category_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/0000755000015301777760000000000012320776463024555 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/JsonNode/0000755000015301777760000000000012320776463026274 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/JsonNode/JsonNode_test.cpp0000644000015301777760000001360612320776161031557 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include #include #include #include using namespace testing; using namespace unity::scopes; using namespace unity::scopes::internal; namespace { class JsonNodeTest : public Test { public: JsonNodeTest() : root_node_(new JsonCppNode()) { } protected: JsonNodeInterface::SPtr root_node_; }; TEST_F(JsonNodeTest, flat_values) { std::string json_string = R"({ "firstName": "John", "age": 25, "human": true })"; std::string value_str; int value_int; bool value_bool; // parse json EXPECT_NO_THROW(root_node_->read_json(json_string)); EXPECT_EQ(3, root_node_->size()); auto members = root_node_->member_names(); EXPECT_EQ(3u, members.size()); EXPECT_TRUE(std::find(members.begin(), members.end(), "firstName") != members.end()); EXPECT_TRUE(std::find(members.begin(), members.end(), "age") != members.end()); EXPECT_TRUE(std::find(members.begin(), members.end(), "human") != members.end()); // get root value EXPECT_NO_THROW(value_str = root_node_->get_node("firstName")->as_string()); EXPECT_EQ("John", value_str); EXPECT_NO_THROW(value_int = root_node_->get_node("age")->as_int()); EXPECT_EQ(25, value_int); EXPECT_NO_THROW(value_bool = root_node_->get_node("human")->as_bool()); EXPECT_EQ(true, value_bool); // try get invalid value EXPECT_FALSE(root_node_->has_node("lastName")); EXPECT_THROW(root_node_->get_node("lastName"), unity::Exception); } TEST_F(JsonNodeTest, array_values) { std::string json_string = R"({ "phoneNumbers": [ "1234", "5678" ] })"; std::string value; JsonNodeInterface::SPtr node; // parse json EXPECT_NO_THROW(root_node_->read_json(json_string)); EXPECT_EQ(1, root_node_->size()); // get array values EXPECT_NO_THROW(node = root_node_->get_node("phoneNumbers")); EXPECT_EQ(2, node->size()); EXPECT_NO_THROW(value = node->get_node(0)->as_string()); EXPECT_EQ("1234", value); EXPECT_NO_THROW(value = node->get_node(1)->as_string()); EXPECT_EQ("5678", value); // get invalid array value EXPECT_THROW(node->get_node(2), unity::Exception); } TEST_F(JsonNodeTest, nested_values) { std::string json_string = R"({ "address": { "city": "New York" }, "phoneNumbers": [ { "type": "home", "number": "212 555-1234" }, { "type": "fax", "number": "646 555-4567" } ] })"; std::string value; JsonNodeInterface::SPtr node; // parse json EXPECT_NO_THROW(root_node_->read_json(json_string)); EXPECT_EQ(2, root_node_->size()); // get nested value EXPECT_NO_THROW(node = root_node_->get_node("address")); EXPECT_EQ(1, node->size()); EXPECT_NO_THROW(value = node->get_node("city")->as_string()); EXPECT_EQ("New York", value); // get nested array values EXPECT_NO_THROW(node = root_node_->get_node("phoneNumbers")); EXPECT_EQ(2, node->size()); EXPECT_NO_THROW(node = node->get_node(0)); EXPECT_EQ(2, node->size()); EXPECT_NO_THROW(value = node->get_node("type")->as_string()); EXPECT_EQ("home", value); EXPECT_NO_THROW(value = node->get_node("number")->as_string()); EXPECT_EQ("212 555-1234", value); } TEST_F(JsonNodeTest, from_variant) { VariantArray va({Variant(1), Variant(2), Variant(true)}); VariantMap vm; vm["foo"] = "bar"; vm["baz"] = 1; vm["boo"] = 2.0f; vm["zee"] = true; vm["wee"] = Variant(va); Variant var(vm); JsonCppNode node(var); EXPECT_EQ("bar", node.get_node("foo")->as_string()); EXPECT_EQ(1, node.get_node("baz")->as_int()); EXPECT_TRUE(node.get_node("boo")->as_double() - 2.0f < 0.00001f); EXPECT_TRUE(node.get_node("zee")->as_bool()); EXPECT_EQ(1, node.get_node("wee")->get_node(0)->as_int()); EXPECT_EQ(2, node.get_node("wee")->get_node(1)->as_int()); EXPECT_EQ(true, node.get_node("wee")->get_node(2)->as_bool()); } TEST_F(JsonNodeTest, to_variant) { std::string json_string = R"({"a":1, "b": 2.0, "c":null, "d":[1,true,"foo"]})"; JsonCppNode node(json_string); auto var = node.to_variant(); auto outer = var.get_dict(); EXPECT_EQ(4u, outer.size()); EXPECT_EQ(1, outer["a"].get_int()); EXPECT_TRUE(outer["b"].get_double() - 2.0f < 0.00001f); EXPECT_TRUE(outer["c"].is_null()); auto arr = outer["d"].get_array(); EXPECT_EQ(3u, arr.size()); EXPECT_EQ(1, arr[0].get_int()); EXPECT_TRUE(arr[1].get_bool()); EXPECT_EQ("foo", arr[2].get_string()); } } // namespace unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/JsonNode/CMakeLists.txt0000644000015301777760000000033512320776161031030 0ustar pbusernogroup00000000000000include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) add_executable( JsonNode_test JsonNode_test.cpp ) target_link_libraries( JsonNode_test ${TESTLIBS} ) add_test( JsonNode JsonNode_test ) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/0000755000015301777760000000000012320776463027120 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/SmartScopesClient/0000755000015301777760000000000012320776463032522 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/SmartScopesClient/FakeSss.pyunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/SmartScopesClient/FakeS0000755000015301777760000000731012320776161033435 0ustar pbusernogroup00000000000000#!/usr/bin/env python # # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Marcus Tomlinson # from wsgiref.simple_server import make_server import sys preview1_complete = False def response(environ, start_response): global preview1_complete status = '200 OK' response_headers = [('Content-Type', 'application/json')] start_response(status, response_headers) if environ['PATH_INFO'] == '/remote-scopes': return [remote_scopes_response] if environ['PATH_INFO'] == '/demo/search' and environ['QUERY_STRING'] != '': return [search_response] if environ['PATH_INFO'] == '/demo/preview' and environ['QUERY_STRING'] != '': if preview1_complete == False: preview1_complete = True return [preview_response] if preview1_complete == True: return [preview_response2] return '' serving = False port = 1024 while serving == False: try: httpd = make_server('127.0.0.1', port, response) serving = True except: port += 1 print(str(port)) sys.stdout.flush() remote_scopes_response = '\ [{"base_url": "http://127.0.0.1:' + str(port) + '/fail", "id" : "fail.scope", "name": "Fail Scope", "description": "Fails due to no author.", "icon": "icon" },\ {"base_url": "http://127.0.0.1:' + str(port) + '/demo", "id" : "dummy.scope", "name": "Dummy Demo Scope", "description": "Dummy demo scope.", "author": "Mr.Fake", "icon": "icon" },\ {"base_url": "http://127.0.0.1:' + str(port) + '/fail2", "name": "Fail Scope 2", "description": "Fails due to no id.", "author": "Mr.Fake", "icon": "icon" },\ {"base_url": "http://127.0.0.1:' + str(port) + '/demo2", "id" : "dummy.scope.2", "name": "Dummy Demo Scope 2", "description": "Dummy demo scope 2.", "author": "Mr.Fake", "art": "art", "invisible": true },\ {"id" : "fail.scope.3", "name": "Fail Scope 3", "description": "Fails due to no base_url.", "author": "Mr.Fake", "art": "art" }]' search_response = '\ {"category": {"render_template": "{}", "id": "cat1", "title": "Category 1"}}\r\n\ {"result": {"cat_id": "cat1", "art": "https://dash.ubuntu.com/imgs/amazon.png", "uri": "URI", "title": "Stuff"}}\r\n\ {"result": {"cat_id": "cat1", "icon": "https://dash.ubuntu.com/imgs/google.png", "uri": "URI2", "title": "Things"}}\r\n\ {"result": {"cat_id": "cat2", "art": "https://dash.ubuntu.com/imgs/cat_fail.png", "uri": "URI3", "title": "Category Fail"}}' preview_response = '\ {"columns": [[["widget_id_A", "widget_id_B", "widget_id_C"]], [["widget_id_A"], ["widget_id_B", "widget_id_C"]], [["widget_id_A"], ["widget_id_B"], ["widget_id_C"]]]}\r\n\ {"widget": {"id": "widget_id_A", "type": "text", "title": "Widget A", "text": "First widget."}}\r\n\ {"widget": {"id": "widget_id_B", "type": "text", "title": "Widget B", "text": "Second widget."}}\r\n\ {"widget": {"id": "widget_id_C", "type": "text", "title": "Widget C", "text": "Third widget."}}' preview_response2 = '\ {"widget": {"id": "widget_id_A", "type": "text", "title": "Widget A", "text": "First widget."}}\r\n\ {"widget": {"id": "widget_id_B", "type": "text", "title": "Widget B", "text": "Second widget."}}' httpd.serve_forever() ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/SmartScopesClient/CMakeLists.txtunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/SmartScopesClient/CMake0000644000015301777760000000052512320776161033422 0ustar pbusernogroup00000000000000include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) add_definitions(-DFAKE_SSS_PATH="${CMAKE_CURRENT_SOURCE_DIR}/FakeSss.py") add_executable( SmartScopesClient_test SmartScopesClient_test.cpp ) target_link_libraries( SmartScopesClient_test ${TESTLIBS} ) add_test( SmartScopesClient SmartScopesClient_test ) ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/SmartScopesClient/Smart0000644000015301777760000002064412320776161033534 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include #include #include "../RaiiServer.h" #include #include #include using namespace testing; using namespace unity::scopes; using namespace unity::scopes::internal; using namespace unity::scopes::internal::smartscopes; using namespace unity::test::scopes::internal::smartscopes; namespace { class SmartScopesClientTest : public Test { public: SmartScopesClientTest() : http_client_(new HttpClientQt(20000)), json_node_(new JsonCppNode()), server_(FAKE_SSS_PATH) { sss_url_ = "http://127.0.0.1:" + std::to_string(server_.port_); ssc_ = std::make_shared(http_client_, json_node_, sss_url_); } protected: std::string sss_url_; HttpClientInterface::SPtr http_client_; JsonNodeInterface::SPtr json_node_; SmartScopesClient::SPtr ssc_; RaiiServer server_; }; TEST_F(SmartScopesClientTest, remote_scopes) { std::vector scopes; EXPECT_TRUE(ssc_->get_remote_scopes(scopes, "", false)); ASSERT_EQ(2u, scopes.size()); EXPECT_EQ("dummy.scope", scopes[0].id); EXPECT_EQ("Dummy Demo Scope", scopes[0].name); EXPECT_EQ("Dummy demo scope.", scopes[0].description); EXPECT_EQ("Mr.Fake", scopes[0].author); EXPECT_EQ(sss_url_ + "/demo", scopes[0].base_url); EXPECT_EQ("icon", *scopes[0].icon); EXPECT_EQ(nullptr, scopes[0].art); EXPECT_FALSE(scopes[0].invisible); EXPECT_EQ("dummy.scope.2", scopes[1].id); EXPECT_EQ("Dummy Demo Scope 2", scopes[1].name); EXPECT_EQ("Dummy demo scope 2.", scopes[1].description); EXPECT_EQ("Mr.Fake", scopes[1].author); EXPECT_EQ(sss_url_ + "/demo2", scopes[1].base_url); EXPECT_EQ(nullptr, scopes[1].icon); EXPECT_EQ("art", *scopes[1].art); EXPECT_TRUE(scopes[1].invisible); } TEST_F(SmartScopesClientTest, search) { auto search_handle = ssc_->search(sss_url_ + "/demo", "stuff", "", "session_id", 0, "platform"); std::vector results = search_handle->get_search_results(); ASSERT_EQ(3u, results.size()); EXPECT_EQ("URI", results[0].uri); EXPECT_EQ(nullptr, results[0].other_params["dnd_uri"]); EXPECT_EQ("Stuff", results[0].other_params["title"]->as_string()); EXPECT_EQ(nullptr, results[0].other_params["icon"]); EXPECT_EQ("https://dash.ubuntu.com/imgs/amazon.png", results[0].other_params["art"]->as_string()); EXPECT_EQ("cat1", results[0].category->id); EXPECT_EQ("Category 1", results[0].category->title); EXPECT_EQ("", results[0].category->icon); EXPECT_EQ("{}", results[0].category->renderer_template); EXPECT_EQ("URI2", results[1].uri); EXPECT_EQ(nullptr, results[1].other_params["dnd_uri"]); EXPECT_EQ("Things", results[1].other_params["title"]->as_string()); EXPECT_EQ("https://dash.ubuntu.com/imgs/google.png", results[1].other_params["icon"]->as_string()); EXPECT_EQ(nullptr, results[1].other_params["art"]); EXPECT_EQ("cat1", results[1].category->id); EXPECT_EQ("Category 1", results[1].category->title); EXPECT_EQ("", results[1].category->icon); EXPECT_EQ("{}", results[1].category->renderer_template); EXPECT_EQ("URI3", results[2].uri); EXPECT_EQ(nullptr, results[2].other_params["dnd_uri"]); EXPECT_EQ("Category Fail", results[2].other_params["title"]->as_string()); EXPECT_EQ(nullptr, results[2].other_params["icon"]); EXPECT_EQ("https://dash.ubuntu.com/imgs/cat_fail.png", results[2].other_params["art"]->as_string()); EXPECT_EQ(nullptr, results[2].category); } TEST_F(SmartScopesClientTest, preview) { auto preview_handle = ssc_->preview(sss_url_ + "/demo", "result", "session_id", "platform", 0); auto results = preview_handle->get_preview_results(); PreviewHandle::Columns columns = results.first; PreviewHandle::Widgets widgets = results.second; ASSERT_EQ(3u, columns.size()); // column 1 ASSERT_EQ(1u, columns[0].size()); ASSERT_EQ(3u, columns[0][0].size()); EXPECT_EQ("widget_id_A", columns[0][0][0]); EXPECT_EQ("widget_id_B", columns[0][0][1]); EXPECT_EQ("widget_id_C", columns[0][0][2]); // column 2 ASSERT_EQ(2u, columns[1].size()); ASSERT_EQ(1u, columns[1][0].size()); EXPECT_EQ("widget_id_A", columns[1][0][0]); ASSERT_EQ(2u, columns[1][1].size()); EXPECT_EQ("widget_id_B", columns[1][1][0]); EXPECT_EQ("widget_id_C", columns[1][1][1]); // column 3 ASSERT_EQ(3u, columns[2].size()); ASSERT_EQ(1u, columns[2][0].size()); EXPECT_EQ("widget_id_A", columns[2][0][0]); ASSERT_EQ(1u, columns[2][1].size()); EXPECT_EQ("widget_id_B", columns[2][1][0]); ASSERT_EQ(1u, columns[2][2].size()); EXPECT_EQ("widget_id_C", columns[2][2][0]); ASSERT_EQ(3u, widgets.size()); EXPECT_EQ("{\"id\":\"widget_id_A\",\"text\":\"First widget.\",\"title\":\"Widget A\",\"type\":\"text\"}\n", widgets[0]); EXPECT_EQ("{\"id\":\"widget_id_B\",\"text\":\"Second widget.\",\"title\":\"Widget B\",\"type\":\"text\"}\n", widgets[1]); EXPECT_EQ("{\"id\":\"widget_id_C\",\"text\":\"Third widget.\",\"title\":\"Widget C\",\"type\":\"text\"}\n", widgets[2]); } TEST_F(SmartScopesClientTest, consecutive_searches) { auto search_handle1 = ssc_->search(sss_url_ + "/demo", "stuff", "", "session_id", 0, "platform"); auto search_handle2 = ssc_->search(sss_url_ + "/demo", "stuff", "", "session_id", 0, "platform"); auto search_handle3 = ssc_->search(sss_url_ + "/demo", "stuff", "", "session_id", 0, "platform"); auto search_handle4 = ssc_->search(sss_url_ + "/demo", "stuff", "", "session_id", 0, "platform"); auto search_handle5 = ssc_->search(sss_url_ + "/demo", "stuff", "", "session_id", 0, "platform"); std::vector results = search_handle1->get_search_results(); EXPECT_EQ(3u, results.size()); results = search_handle2->get_search_results(); EXPECT_EQ(3u, results.size()); results = search_handle3->get_search_results(); EXPECT_EQ(3u, results.size()); results = search_handle4->get_search_results(); EXPECT_EQ(3u, results.size()); results = search_handle5->get_search_results(); EXPECT_EQ(3u, results.size()); } TEST_F(SmartScopesClientTest, consecutive_cancels) { for (int i = 0; i < 50; ++i) { auto search_handle = ssc_->search(sss_url_ + "/demo", "stuff", "", "session_id", 0, "platform"); search_handle->cancel_search(); EXPECT_THROW(search_handle->get_search_results(), std::exception); } auto search_handle = ssc_->search(sss_url_ + "/demo", "stuff", "", "session_id", 0, "platform"); std::vector results = search_handle->get_search_results(); EXPECT_EQ(3u, results.size()); } TEST_F(SmartScopesClientTest, reset_url) { // check initial values to be expected test values EXPECT_EQ(sss_url_, ssc_->url()); // empty the environment var (in case there already is one set) std::string server_url_env = "SMART_SCOPES_SERVER="; ::putenv(const_cast(server_url_env.c_str())); // reset url and check that we now have falback contant url EXPECT_NO_THROW(ssc_->reset_url()); EXPECT_EQ("https://dash.ubuntu.com/smartscopes/v2", ssc_->url()); // set the environment var server_url_env = "SMART_SCOPES_SERVER=http://hello.com/there"; ::putenv(const_cast(server_url_env.c_str())); // reset url and check that we now have the environment var url EXPECT_NO_THROW(ssc_->reset_url()); EXPECT_EQ("http://hello.com/there", ssc_->url()); // force url EXPECT_NO_THROW(ssc_->reset_url("http://hello.com:2000/there")); EXPECT_EQ("http://hello.com:2000/there", ssc_->url()); } } // namespace unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/HttpClient/0000755000015301777760000000000012320776463031176 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/HttpClient/FakeServer.pyunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/HttpClient/FakeServer.p0000755000015301777760000000307312320776161033415 0ustar pbusernogroup00000000000000#!/usr/bin/env python # # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Marcus Tomlinson # from wsgiref.simple_server import make_server from random import randint import sys import time def response(environ, start_response): if environ['QUERY_STRING'] == 'x': status = '404 Not Found' response_headers = [('Content-Type', 'text/plain')] start_response(status, response_headers) return '' else: status = '200 OK' response_headers = [('Content-Type', 'text/plain')] if environ['QUERY_STRING'] != '': time.sleep(int(environ['QUERY_STRING'])) start_response(status, response_headers) return 'Hello there' serving = False port = randint(49152, 65535) while serving == False: try: httpd = make_server('127.0.0.1', port, response) serving = True except: port = randint(49152, 65535) print(str(port)) sys.stdout.flush() httpd.serve_forever() ././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/HttpClient/HttpClient_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/HttpClient/HttpClient_t0000644000015301777760000001104312320776161033514 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include "../RaiiServer.h" #include #include #include using namespace testing; using namespace unity::scopes::internal::smartscopes; using namespace unity::test::scopes::internal::smartscopes; namespace { const std::string c_test_url = "http://127.0.0.1"; class HttpClientTest : public Test { public: HttpClientTest(uint no_reply_timeout = 20000) : http_client_(new HttpClientQt(no_reply_timeout)), server_(FAKE_SERVER_PATH) { test_url_ = c_test_url + ":" + std::to_string(server_.port_); } protected: HttpClientInterface::SPtr http_client_; RaiiServer server_; std::string test_url_; }; class HttpClientTestQuick : public HttpClientTest { public: HttpClientTestQuick() : HttpClientTest(2000) {} }; TEST_F(HttpClientTest, no_server) { int dead_port; { // spawn a server, so it allocates a free port RaiiServer server(FAKE_SERVER_PATH); dead_port = server.port_; // RaiiServer goes out of scope, so it gets killed } // no server HttpResponseHandle::SPtr response = http_client_->get(c_test_url + ":" + std::to_string(dead_port)); response->wait(); EXPECT_THROW(response->get(), unity::Exception); } TEST_F(HttpClientTest, bad_server) { // bad server HttpResponseHandle::SPtr response = http_client_->get(test_url_ + "?x"); response->wait(); EXPECT_THROW(response->get(), unity::Exception); } TEST_F(HttpClientTest, good_server) { // responds immediately HttpResponseHandle::SPtr response = http_client_->get(test_url_); response->wait(); std::string response_str; EXPECT_NO_THROW(response_str = response->get()); EXPECT_EQ("Hello there", response_str); } TEST_F(HttpClientTestQuick, ok_server) { // responds in 1 second HttpResponseHandle::SPtr response = http_client_->get(test_url_ + "?1"); response->wait(); std::string response_str; EXPECT_NO_THROW(response_str = response->get()); EXPECT_EQ("Hello there", response_str); } TEST_F(HttpClientTestQuick, slow_server) { // responds in 3 seconds HttpResponseHandle::SPtr response = http_client_->get(test_url_ + "?3"); response->wait(); EXPECT_THROW(response->get(), unity::Exception); } TEST_F(HttpClientTest, multiple_sessions) { HttpResponseHandle::SPtr response1 = http_client_->get(test_url_); HttpResponseHandle::SPtr response2 = http_client_->get(test_url_); HttpResponseHandle::SPtr response3 = http_client_->get(test_url_); HttpResponseHandle::SPtr response4 = http_client_->get(test_url_); HttpResponseHandle::SPtr response5 = http_client_->get(test_url_); response1->wait(); response2->wait(); response3->wait(); response4->wait(); response5->wait(); std::string response_str; EXPECT_NO_THROW(response_str = response1->get()); EXPECT_EQ("Hello there", response_str); EXPECT_NO_THROW(response_str = response2->get()); EXPECT_EQ("Hello there", response_str); EXPECT_NO_THROW(response_str = response3->get()); EXPECT_EQ("Hello there", response_str); EXPECT_NO_THROW(response_str = response4->get()); EXPECT_EQ("Hello there", response_str); EXPECT_NO_THROW(response_str = response5->get()); EXPECT_EQ("Hello there", response_str); } TEST_F(HttpClientTest, cancel_get) { HttpResponseHandle::SPtr response = http_client_->get(test_url_ + "?18"); response->cancel(); response->wait(); EXPECT_THROW(response->get(), unity::Exception); } TEST_F(HttpClientTest, percent_encoding) { std::string encoded_str = http_client_->to_percent_encoding(" \"%<>\\^`{|}!*'();:@&=+$,/?#[]"); EXPECT_EQ("%20%22%25%3C%3E%5C%5E%60%7B%7C%7D%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D", encoded_str); } } // namespace ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/HttpClient/CMakeLists.txtunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/HttpClient/CMakeLists.t0000644000015301777760000000047012320776161033356 0ustar pbusernogroup00000000000000include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) add_definitions(-DFAKE_SERVER_PATH="${CMAKE_CURRENT_SOURCE_DIR}/FakeServer.py") add_executable( HttpClient_test HttpClient_test.cpp ) target_link_libraries( HttpClient_test ${TESTLIBS} ) add_test( HttpClient HttpClient_test ) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/CMakeLists.txt0000644000015301777760000000014412320776161031652 0ustar pbusernogroup00000000000000add_subdirectory(HttpClient) add_subdirectory(SmartScopesClient) add_subdirectory(smartscopesproxy) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/RaiiServer.h0000644000015301777760000000514712320776161031346 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_TEST_SCOPES_INTERNAL_SMARTSCOPES_RAIISERVER_H #define UNITY_TEST_SCOPES_INTERNAL_SMARTSCOPES_RAIISERVER_H #include #include #include #include namespace unity { namespace test { namespace scopes { namespace internal { namespace smartscopes { class RaiiServer { public: RaiiServer(std::string const& server_path) { int pipefd[2]; if (pipe(pipefd) < 0) { throw unity::ResourceException("Pipe creation failed"); } switch (pid_ = fork()) { case -1: throw unity::ResourceException("Failed to fork process"); case 0: // child close(STDOUT_FILENO); // close stdout close(pipefd[0]); // close read if (dup(pipefd[1]) < 0) // open write { throw unity::ResourceException("Write pipe duplication failed"); } execl(server_path.c_str(), "", NULL); throw unity::ResourceException("Failed to execute fake server script"); default: // parent close(pipefd[1]); // close write char port_str[10]; ssize_t bytes_read = read(pipefd[0], port_str, sizeof(port_str) - 1); if(bytes_read < 0) { throw unity::ResourceException("Failed to read from pipe"); } port_str[bytes_read] = '\0'; port_ = std::atoi(port_str); } } ~RaiiServer() { kill(pid_, SIGABRT); int status; waitpid(pid_, &status, 0); } pid_t pid_ = -1; int port_ = 0; }; } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace test } // namespace unity #endif // UNITY_TEST_SCOPES_INTERNAL_SMARTSCOPES_RAIISERVER_H unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/smartscopesproxy/0000755000015301777760000000000012320776463032565 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/smartscopesproxy/Zmq.ini.inunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/smartscopesproxy/Zmq.in0000644000015301777760000000007312320776161033657 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp ././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/smartscopesproxy/smartscopesproxy_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/smartscopesproxy/smarts0000644000015301777760000003206512320776161034022 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include #include #include #include #include #include #include #include #include #include #include "../RaiiServer.h" #include #include #include using namespace testing; using namespace unity::scopes; using namespace unity::scopes::internal; using namespace unity::scopes::internal::smartscopes; using namespace unity::test::scopes::internal::smartscopes; namespace { class smartscopesproxytest : public Test { public: smartscopesproxytest() : server_(FAKE_SSS_PATH) , reg_id_("SSRegistryTest") , scope_id_("SmartScopeTest") { // Instantiate SS registry and scopes runtimes reg_rt_ = RuntimeImpl::create(reg_id_, SS_RUNTIME_PATH); scope_rt_ = RuntimeImpl::create(scope_id_, SS_RUNTIME_PATH); // Get registry config RegistryConfig reg_conf(reg_id_, reg_rt_->registry_configfile()); std::string mw_kind = reg_conf.mw_kind(); std::string mw_configfile = reg_conf.mw_configfile(); // Get middleware handles from runtimes reg_mw_ = reg_rt_->factory()->find(reg_id_, mw_kind); scope_mw_ = scope_rt_->factory()->create(scope_id_, mw_kind, mw_configfile); // Instantiate a SS registry and scope objects reg_ = SSRegistryObject::SPtr(new SSRegistryObject(reg_mw_, scope_mw_->get_scope_endpoint(), 20000, 60, "http://127.0.0.1:" + std::to_string(server_.port_), false)); scope_ = SSScopeObject::UPtr(new SSScopeObject(scope_id_, scope_mw_, reg_)); // Add objects to the middlewares reg_mw_->add_registry_object(reg_rt_->registry_identity(), reg_); scope_mw_->add_dflt_scope_object(std::move(scope_)); } ~smartscopesproxytest() { scope_mw_->stop(); scope_mw_->wait_for_shutdown(); reg_mw_->stop(); reg_mw_->wait_for_shutdown(); } protected: RaiiServer server_; std::string reg_id_; std::string scope_id_; RuntimeImpl::UPtr reg_rt_; RuntimeImpl::UPtr scope_rt_; MiddlewareBase::SPtr reg_mw_; MiddlewareBase::SPtr scope_mw_; SSRegistryObject::SPtr reg_; SSScopeObject::UPtr scope_; }; TEST_F(smartscopesproxytest, ss_registry) { // locate should throw (direct) EXPECT_THROW(reg_->locate("dummy.scope"), RegistryException); // list scopes (direct) MetadataMap scopes = reg_->list(); EXPECT_EQ(2u, scopes.size()); // visible scope (direct) ScopeMetadata meta = reg_->get_metadata("dummy.scope"); EXPECT_EQ("dummy.scope", meta.scope_id()); EXPECT_EQ("Dummy Demo Scope", meta.display_name()); EXPECT_EQ("Dummy demo scope.", meta.description()); EXPECT_EQ("Mr.Fake", meta.author()); EXPECT_EQ("icon", meta.icon()); EXPECT_FALSE(meta.invisible()); // non-existant scope (direct) EXPECT_THROW(reg_->get_metadata("dummy.scope.3"), NotFoundException); // locate should throw (via mw) MWRegistryProxy mw_reg = reg_mw_->create_registry_proxy(reg_id_, reg_mw_->get_scope_endpoint()); EXPECT_THROW(mw_reg->locate("Dummy Demo Scope"), RegistryException); // list scopes (via mw) scopes = mw_reg->list(); EXPECT_EQ(2u, scopes.size()); // visible scope (via mw) meta = mw_reg->get_metadata("dummy.scope"); EXPECT_EQ("dummy.scope", meta.scope_id()); EXPECT_EQ("Dummy Demo Scope", meta.display_name()); EXPECT_EQ("Dummy demo scope.", meta.description()); EXPECT_EQ("Mr.Fake", meta.author()); EXPECT_EQ("icon", meta.icon()); EXPECT_FALSE(meta.invisible()); // non-existant scope (via mw) EXPECT_THROW(mw_reg->get_metadata("dummy.scope.3"), NotFoundException); } class Receiver : public SearchListenerBase { public: virtual void push(CategorisedResult result) override { if (count_ == 0) { EXPECT_EQ("URI", result.uri()); EXPECT_EQ("Stuff", result.title()); EXPECT_EQ("https://dash.ubuntu.com/imgs/amazon.png", result.art()); EXPECT_EQ("", result.dnd_uri()); EXPECT_EQ("cat1", result.category()->id()); EXPECT_EQ("Category 1", result.category()->title()); EXPECT_EQ("", result.category()->icon()); EXPECT_EQ("{}", result.category()->renderer_template().data()); } else if (count_ == 1) { EXPECT_EQ("URI2", result.uri()); EXPECT_EQ("Things", result.title()); EXPECT_EQ("", result.art()); EXPECT_EQ("", result.dnd_uri()); EXPECT_EQ("cat1", result.category()->id()); EXPECT_EQ("Category 1", result.category()->title()); EXPECT_EQ("", result.category()->icon()); EXPECT_EQ("{}", result.category()->renderer_template().data()); } count_++; last_result_ = std::make_shared(result); } virtual void finished(ListenerBase::Reason reason, std::string const& error_message) override { EXPECT_EQ(Finished, reason); EXPECT_EQ("", error_message); EXPECT_EQ(2, count_); // signal wait_until_finished std::unique_lock lock(mutex_); query_complete_ = true; cond_.notify_one(); } void wait_until_finished() { std::unique_lock lock(mutex_); cond_.wait(lock, [this] { return this->query_complete_; }); } std::shared_ptr last_result() { return last_result_; } private: int count_ = 0; bool query_complete_; std::mutex mutex_; std::condition_variable cond_; std::shared_ptr last_result_; }; TEST_F(smartscopesproxytest, search) { auto reply = std::make_shared(); ScopeMetadata meta = reg_->get_metadata("dummy.scope"); meta.proxy()->search("search_string", SearchMetadata("en", "phone"), reply); reply->wait_until_finished(); } TEST_F(smartscopesproxytest, consecutive_queries) { ScopeMetadata meta = reg_->get_metadata("dummy.scope"); std::vector> replies; for (int i = 0; i < 10; ++i) { replies.push_back(std::make_shared()); meta.proxy()->search("search_string", SearchMetadata("en", "phone"), replies.back()); } for (int i = 0; i < 10; ++i) { replies[i]->wait_until_finished(); } } class PreviewerWithCols : public PreviewListenerBase { public: virtual void push(PreviewWidgetList const& widget_list) override { EXPECT_EQ(3u, widget_list.size()); // widget 1 auto it = widget_list.begin(); EXPECT_EQ("widget_id_A", it->id()); EXPECT_EQ("text", it->widget_type()); EXPECT_EQ("Widget A", it->attribute_values()["title"].get_string()); EXPECT_EQ("First widget.", it->attribute_values()["text"].get_string()); // widget 2 std::advance(it, 1); EXPECT_EQ("widget_id_B", it->id()); EXPECT_EQ("text", it->widget_type()); EXPECT_EQ("Widget B", it->attribute_values()["title"].get_string()); EXPECT_EQ("Second widget.", it->attribute_values()["text"].get_string()); // widget 3 std::advance(it, 1); EXPECT_EQ("widget_id_C", it->id()); EXPECT_EQ("text", it->widget_type()); EXPECT_EQ("Widget C", it->attribute_values()["title"].get_string()); EXPECT_EQ("Third widget.", it->attribute_values()["text"].get_string()); widget_pushes_++; } virtual void push(std::string const&, Variant const&) override { widget_pushes_++; } virtual void push(ColumnLayoutList const& column_list) override { ASSERT_EQ(3u, column_list.size()); // column 1 auto it = column_list.begin(); ASSERT_EQ(1, it->number_of_columns()); ASSERT_EQ(3u, it->column(0).size()); EXPECT_EQ("widget_id_A", it->column(0)[0]); EXPECT_EQ("widget_id_B", it->column(0)[1]); EXPECT_EQ("widget_id_C", it->column(0)[2]); // column 2 std::advance(it, 1); ASSERT_EQ(2, it->number_of_columns()); ASSERT_EQ(1u, it->column(0).size()); EXPECT_EQ("widget_id_A", it->column(0)[0]); ASSERT_EQ(2u, it->column(1).size()); EXPECT_EQ("widget_id_B", it->column(1)[0]); EXPECT_EQ("widget_id_C", it->column(1)[1]); // column 3 std::advance(it, 1); ASSERT_EQ(3, it->number_of_columns()); ASSERT_EQ(1u, it->column(0).size()); EXPECT_EQ("widget_id_A", it->column(0)[0]); ASSERT_EQ(1u, it->column(1).size()); EXPECT_EQ("widget_id_B", it->column(1)[0]); ASSERT_EQ(1u, it->column(2).size()); EXPECT_EQ("widget_id_C", it->column(2)[0]); col_pushes_++; } virtual void finished(ListenerBase::Reason reason, std::string const& error_message) override { EXPECT_EQ(Finished, reason); EXPECT_EQ("", error_message); EXPECT_EQ(1, widget_pushes_); EXPECT_EQ(1, col_pushes_); // Signal wait_until_finished std::unique_lock lock(mutex_); query_complete_ = true; cond_.notify_one(); } void wait_until_finished() { std::unique_lock lock(mutex_); cond_.wait(lock, [this] { return this->query_complete_; }); } private: int widget_pushes_ = 0; int col_pushes_ = 0; bool query_complete_ = false; std::mutex mutex_; std::condition_variable cond_; }; class PreviewerNoCols : public PreviewListenerBase { public: virtual void push(PreviewWidgetList const& widget_list) override { EXPECT_EQ(2u, widget_list.size()); // widget 1 auto it = widget_list.begin(); EXPECT_EQ("widget_id_A", it->id()); EXPECT_EQ("text", it->widget_type()); EXPECT_EQ("Widget A", it->attribute_values()["title"].get_string()); EXPECT_EQ("First widget.", it->attribute_values()["text"].get_string()); // widget 2 std::advance(it, 1); EXPECT_EQ("widget_id_B", it->id()); EXPECT_EQ("text", it->widget_type()); EXPECT_EQ("Widget B", it->attribute_values()["title"].get_string()); EXPECT_EQ("Second widget.", it->attribute_values()["text"].get_string()); widget_pushes_++; } virtual void push(std::string const&, Variant const&) override { widget_pushes_++; } virtual void push(ColumnLayoutList const&) override { col_pushes_++; } virtual void finished(ListenerBase::Reason reason, std::string const& error_message) override { EXPECT_EQ(Finished, reason); EXPECT_EQ("", error_message); EXPECT_EQ(1, widget_pushes_); EXPECT_EQ(0, col_pushes_); // Signal wait_until_finished std::unique_lock lock(mutex_); query_complete_ = true; cond_.notify_one(); } void wait_until_finished() { std::unique_lock lock(mutex_); cond_.wait(lock, [this] { return this->query_complete_; }); } private: int widget_pushes_ = 0; int col_pushes_ = 0; bool query_complete_ = false; std::mutex mutex_; std::condition_variable cond_; }; TEST_F(smartscopesproxytest, preview) { auto reply = std::make_shared(); ScopeMetadata meta = reg_->get_metadata("dummy.scope"); meta.proxy()->search("search_string", SearchMetadata("en", "phone"), reply); reply->wait_until_finished(); auto result = reply->last_result(); EXPECT_TRUE(result.get() != nullptr); // with columns returned auto previewer_with_cols = std::make_shared(); meta.proxy()->preview(*(result.get()), ActionMetadata("en", "phone"), previewer_with_cols); previewer_with_cols->wait_until_finished(); // without columns returned auto previewer_no_cols = std::make_shared(); meta.proxy()->preview(*(result.get()), ActionMetadata("en", "phone"), previewer_no_cols); previewer_no_cols->wait_until_finished(); } } // namespace ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/smartscopesproxy/SSRegistryTest.ini.inunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/smartscopesproxy/SSRegi0000644000015301777760000000032312320776161033635 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = SSRegistryTest [Registry] Middleware = Zmq Zmq.Endpoint = ipc:///tmp/SSRegistryTest Zmq.EndpointDir = /tmp Zmq.ConfigFile = Zmq.ini Scope.InstallDir = /tmp Scoperunner.Path = /tmp ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/smartscopesproxy/CMakeLists.txtunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/smartscopesproxy/CMakeL0000644000015301777760000000121612320776161033577 0ustar pbusernogroup00000000000000configure_file(SSRegistryTest.ini.in ${CMAKE_CURRENT_BINARY_DIR}/SSRegistryTest.ini) configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini) configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini) add_definitions(-DSS_RUNTIME_PATH="${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini") add_definitions(-DFAKE_SSS_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../SmartScopesClient/FakeSss.py") include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) add_executable( smartscopesproxy_test smartscopesproxy_test.cpp ) target_link_libraries( smartscopesproxy_test ${TESTLIBS} ) add_test( smartscopesproxy smartscopesproxy_test ) ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/smartscopesproxy/Runtime.ini.inunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/smartscopes/smartscopesproxy/Runtim0000644000015301777760000000027612320776161033766 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = SSRegistryTest Registry.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/SSRegistryTest.ini Default.Middleware = Zmq Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/CategoryRegistry/0000755000015301777760000000000012320776463030063 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/CategoryRegistry/CMakeLists.txt0000644000015301777760000000025312320776161032616 0ustar pbusernogroup00000000000000add_executable(CategoryRegistry_test CategoryRegistry_test.cpp) target_link_libraries(CategoryRegistry_test ${TESTLIBS}) add_test(CategoryRegistry CategoryRegistry_test) ././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/CategoryRegistry/CategoryRegistry_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/CategoryRegistry/CategoryRegistry_t0000644000015301777760000000330412320776161033632 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include using namespace std; using namespace unity; using namespace unity::scopes; using namespace unity::scopes::internal; TEST(CategoryRegistry, basic) { CategoryRegistry reg; { CategoryRenderer rdr; EXPECT_EQ(nullptr, reg.lookup_category("a")); auto cat = reg.register_category("a", "title", "icon", rdr); EXPECT_TRUE(cat != nullptr); auto cat1 = reg.lookup_category("a"); EXPECT_TRUE(cat1 != nullptr); EXPECT_TRUE(cat == cat1); } } TEST(CategoryRegistry, exceptions) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("a", "title", "icon", rdr); EXPECT_THROW(reg.register_category("a", "title1", "icon1", rdr), InvalidArgumentException); EXPECT_THROW(reg.register_category(cat), InvalidArgumentException); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/0000755000015301777760000000000012320776463026755 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/Counters.cpp0000644000015301777760000000356212320776161031264 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "Counters.h" #include using namespace std; namespace { int create_calls; int destroy_calls; int start_calls; int stop_calls; std::mutex count_mutex; } // Helper functions to read and increment the number of calls under protection of a mutex. // We use this for the tests to track how often each function was called from the scope thread. int num_create() { lock_guard lock(count_mutex); return create_calls; } void inc_create() { lock_guard lock(count_mutex); ++create_calls; } int num_destroy() { lock_guard lock(count_mutex); return destroy_calls; } void inc_destroy() { lock_guard lock(count_mutex); ++destroy_calls; } int num_start() { lock_guard lock(count_mutex); return start_calls; } void inc_start() { lock_guard lock(count_mutex); ++start_calls; } int num_stop() { lock_guard lock(count_mutex); return stop_calls; } void inc_stop() { lock_guard lock(count_mutex); ++stop_calls; } void reset_counters() { lock_guard lock(count_mutex); create_calls = 0; destroy_calls = 0; start_calls = 0; stop_calls = 0; } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/ScopeB.cpp0000644000015301777760000000306312320776161030631 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "MyScope.h" #include "Counters.h" #include "PerScopeVariables.h" #include #include #include using namespace std; class ScopeA : public MyScope { public: virtual int start(std::string const&, unity::scopes::RegistryProxy const&) override { inc_start(); return VERSION; } virtual void stop() override { inc_stop(); } }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { inc_create(); return new ScopeA; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { inc_destroy(); delete scope_base; set_scopeB_var(2); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/ThrowUnityExFromRun.cpp0000644000015301777760000000265412320776161033425 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "MyScope.h" #include "Counters.h" #include #include #include using namespace std; class EXPORT MyThrowingScope : public MyScope { public: virtual void run() override { inc_run(); throw unity::LogicException("run failure"); } }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { inc_create(); return new MyThrowingScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { inc_destroy(); delete scope_base; } } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/ThrowUnityExFromStart.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/ThrowUnityExFromStart.c0000644000015301777760000000275612320776161033421 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "MyScope.h" #include "Counters.h" #include #include #include using namespace std; class EXPORT MyThrowingScope : public MyScope { public: virtual int start(std::string const&, unity::scopes::RegistryProxy const&) override { inc_start(); throw unity::LogicException("start failure"); } }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { inc_create(); return new MyThrowingScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { inc_destroy(); delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/PerScopeVariables.h0000644000015301777760000000173712320776161032502 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef SCOPELOADERTEST_PERSCOPEVARIABLES #define SCOPELOADERTEST_PERSCOPEVARIABLES #include "TestExports.h" int EXPORT get_scopeA_var(); void EXPORT set_scopeA_var(int val); int EXPORT get_scopeB_var(); void EXPORT set_scopeB_var(int val); void EXPORT clear_vars(); #endif unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/NullReturn.cpp0000644000015301777760000000252612320776161031573 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "MyScope.h" #include "Counters.h" #include #include extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { inc_create(); return nullptr; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { inc_destroy(); // We use an abort instead of EXPECT_EQ because we can't see the symbols // in gtest.a here. if (scope_base != nullptr) { abort(); } } } ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/ThrowUnityExFromStop.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/ThrowUnityExFromStop.cp0000644000015301777760000000266512320776161033430 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "MyScope.h" #include "Counters.h" #include #include #include using namespace std; class EXPORT MyThrowingScope : public MyScope { public: virtual void stop() override { inc_stop(); throw unity::LogicException("stop failure"); } }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { inc_create(); return new MyThrowingScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { inc_destroy(); delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/ScopeA.cpp0000644000015301777760000000306312320776161030630 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "MyScope.h" #include "Counters.h" #include "PerScopeVariables.h" #include #include #include using namespace std; class ScopeA : public MyScope { public: virtual int start(std::string const&, unity::scopes::RegistryProxy const&) override { inc_start(); return VERSION; } virtual void stop() override { inc_stop(); } }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { inc_create(); return new ScopeA; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { inc_destroy(); delete scope_base; set_scopeA_var(1); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/Counters.h0000644000015301777760000000202712320776161030724 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef SCOPELOADERTEST_COUNTERS #define SCOPELOADERTEST_COUNTERS #include "TestExports.h" int EXPORT num_create(); void EXPORT inc_create(); int EXPORT num_destroy(); void EXPORT inc_destroy(); int EXPORT num_start(); void EXPORT inc_start(); int EXPORT num_stop(); void EXPORT inc_stop(); void EXPORT reset_counters(); #endif ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/ThrowUnknownExFromStop.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/ThrowUnknownExFromStop.0000644000015301777760000000255712320776161033434 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "MyScope.h" #include "Counters.h" #include #include using namespace std; class EXPORT MyThrowingScope : public MyScope { public: virtual void stop() override { inc_stop(); throw 42; } }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { inc_create(); return new MyThrowingScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { inc_destroy(); delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/MyScope.h0000644000015301777760000000327312320776161030505 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef SCOPELOADERTEST_MYSCOPE #define SCOPELOADERTEST_MYSCOPE #include "Counters.h" #include // Test scope class that allows us to count the number of calls to start(), run(), and stop(). class EXPORT MyScope : public unity::scopes::ScopeBase { public: MyScope() {} virtual ~MyScope() {} virtual int start(std::string const&, unity::scopes::RegistryProxy const&) override { inc_start(); return VERSION; } virtual void stop() override { inc_stop(); } virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&, unity::scopes::SearchMetadata const&) override { return nullptr; } virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&, unity::scopes::ActionMetadata const&) override { return nullptr; } }; #endif ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/ThrowUnknownExFromStart.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/ThrowUnknownExFromStart0000644000015301777760000000264712320776161033526 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "MyScope.h" #include "Counters.h" #include #include using namespace std; class EXPORT MyThrowingScope : public MyScope { public: virtual int start(std::string const&, unity::scopes::RegistryProxy const&) override { inc_start(); throw 42; } }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { inc_create(); return new MyThrowingScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { inc_destroy(); delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/TestScope.cpp0000644000015301777760000000225012320776161031364 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "MyScope.h" #include "Counters.h" #include extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { inc_create(); return new MyScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { inc_destroy(); delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/CMakeLists.txt0000644000015301777760000000154712320776161031517 0ustar pbusernogroup00000000000000add_executable(ScopeLoader_test ScopeLoader_test.cpp) target_link_libraries(ScopeLoader_test ${TESTLIBS} SharedState) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_library(SharedState SHARED Counters.cpp PerScopeVariables.cpp) add_library(BadVersion MODULE BadVersion.cpp) add_library(NoDestroy MODULE NoDestroy.cpp) add_library(NullReturn MODULE NullReturn.cpp) add_library(ScopeA MODULE ScopeA.cpp) add_library(ScopeB MODULE ScopeB.cpp) add_library(TestScope MODULE TestScope.cpp) add_library(ThrowUnityExFromStart MODULE ThrowUnityExFromStart.cpp) add_library(ThrowUnityExFromStop MODULE ThrowUnityExFromStop.cpp) add_library(ThrowStdExFromStop MODULE ThrowStdExFromStop.cpp) add_library(ThrowUnknownExFromStart MODULE ThrowUnknownExFromStart.cpp) add_library(ThrowUnknownExFromStop MODULE ThrowUnknownExFromStop.cpp) add_test(ScopeLoader ScopeLoader_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/ScopeLoader_test.cpp0000644000015301777760000003674512320776161032732 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include // Use Boost implementation until http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631 is fixed. #include #include "Counters.h" #include "PerScopeVariables.h" #include using namespace std; using namespace unity::scopes; using namespace unity::scopes::internal; namespace { char const* scope_lib = TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeLoader/libTestScope.so"; char const* bad_version_lib = TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeLoader/libBadVersion.so"; char const* no_destroy_lib = TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeLoader/libNoDestroy.so"; char const* null_return_lib = TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeLoader/libNullReturn.so"; char const* throw_unity_ex_from_start_lib = TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeLoader/libThrowUnityExFromStart.so"; char const* throw_unity_ex_from_stop_lib = TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeLoader/libThrowUnityExFromStop.so"; char const* throw_std_ex_from_stop_lib = TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeLoader/libThrowStdExFromStop.so"; char const* throw_unknown_ex_from_start_lib = TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeLoader/libThrowUnknownExFromStart.so"; char const* throw_unknown_ex_from_stop_lib = TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeLoader/libThrowUnknownExFromStop.so"; char const* scopeA = TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeLoader/libScopeA.so"; char const* scopeB = TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeLoader/libScopeB.so"; } // Need to make a dummy registry proxy because, if we pass a null shared_ptr to load(), // load() throws an exception. RegistryProxy registry(make_shared(nullptr, (RuntimeImpl*)0x1)); // Basic test. TEST(ScopeLoader, basic) { reset_counters(); { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, registry); EXPECT_EQ(1, num_create()); EXPECT_EQ(0, num_destroy()); EXPECT_EQ("testScope", sl->scope_id()); EXPECT_EQ(scope_lib, sl->libpath()); EXPECT_EQ(TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeLoader", sl->scope_base()->scope_directory()); } EXPECT_EQ(1, num_create()); EXPECT_EQ(1, num_destroy()); EXPECT_EQ(0, num_start()); EXPECT_EQ(0, num_stop()); } TEST(ScopeLoader, version_mismatch) { reset_counters(); try { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", bad_version_lib, registry); sl->start(); sl->unload(); FAIL(); } catch (unity::Exception const& e) { boost::regex r("unity::ResourceException: Scope testScope: terminated due to exception in start\\(\\):\n" " unity::ResourceException: Scope testScope was compiled with major version 666 of the " "Unity scopes run time. This version is incompatible with the current major version " "\\([0-9]+\\)\\."); EXPECT_TRUE(boost::regex_match(e.what(), r)) << e.what(); } EXPECT_EQ(1, num_create()); EXPECT_EQ(1, num_destroy()); EXPECT_EQ(1, num_start()); EXPECT_EQ(1, num_stop()); } TEST(ScopeLoader, stop) { reset_counters(); { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, registry); // Check that calling stop on a stopped thread does nothing. sl->stop(); EXPECT_EQ(0, num_start()); EXPECT_EQ(0, num_stop()); EXPECT_TRUE(sl->scope_base()); // Just so we get coverage sl->stop(); EXPECT_EQ(0, num_start()); EXPECT_EQ(0, num_stop()); // Check transition to start state and that calling start more than once does nothing. sl->start(); EXPECT_EQ(1, num_start()); EXPECT_EQ(0, num_stop()); sl->start(); EXPECT_EQ(1, num_start()); EXPECT_EQ(0, num_stop()); // Call stop/start/stop and check counts. sl->stop(); EXPECT_EQ(1, num_stop()); sl->start(); sl->stop(); EXPECT_EQ(2, num_start()); EXPECT_EQ(2, num_stop()); } } // Test that letting the ScopeLoader go out of scope while the scope is running shuts down the scope. TEST(ScopeLoader, unload_while_started) { reset_counters(); { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, registry); sl->start(); EXPECT_EQ(1, num_start()); EXPECT_EQ(0, num_stop()); } EXPECT_EQ(1, num_start()); EXPECT_EQ(1, num_stop()); EXPECT_EQ(1, num_create()); EXPECT_EQ(1, num_destroy()); } // Test that things behave as expected if the library can't be loaded. TEST(ScopeLoader, no_library) { reset_counters(); try { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", "no_such_lib", registry); FAIL(); } catch (unity::Exception const& e) { EXPECT_STREQ("unity::ResourceException: no_such_lib: cannot open shared object file: No such file or directory", e.what()); EXPECT_EQ(0, num_create()); EXPECT_EQ(0, num_destroy()); } } // Test that things behave as expected if the create or destroy function isn't found. TEST(ScopeLoader, no_load) { reset_counters(); try { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", no_destroy_lib, registry); FAIL(); } catch (unity::Exception const& e) { boost::regex r("unity::ResourceException: .*/libNoDestroy.so: undefined symbol: unity_scope_destroy"); EXPECT_TRUE(boost::regex_match(e.what(), r)); EXPECT_EQ(0, num_create()); EXPECT_EQ(0, num_destroy()); } } // Test that things behave as expected if the create function returns nullptr. TEST(ScopeLoader, null_return) { reset_counters(); try { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", null_return_lib, registry); FAIL(); } catch (unity::Exception const& e) { EXPECT_STREQ("unity::ResourceException: Scope testScope returned nullptr from unity_scope_create", e.what()); EXPECT_EQ(1, num_create()); EXPECT_EQ(0, num_destroy()); } } // Same thing again, but this time with an explicit unload TEST(ScopeLoader, null_return_unload) { reset_counters(); try { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", null_return_lib, registry); sl->unload(); FAIL(); } catch (unity::Exception const& e) { EXPECT_STREQ("unity::ResourceException: Scope testScope returned nullptr from unity_scope_create", e.what()); EXPECT_EQ(1, num_create()); EXPECT_EQ(0, num_destroy()); } } // Test that things behave as expected if start() throws a Unity exception. TEST(ScopeLoader, throw_unity_exception_from_start) { reset_counters(); { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib, registry); try { sl->start(); sl->unload(); FAIL(); } catch (unity::Exception const& e) { EXPECT_STREQ("unity::ResourceException: Scope testScope: terminated due to exception in start():\n" " unity::LogicException: start failure", e.what()); } } EXPECT_EQ(0, num_stop()); EXPECT_EQ(1, num_create()); EXPECT_EQ(1, num_destroy()); } // Same again, but without an explicit unload, just so we get coverage in the destructor. TEST(ScopeLoader, throw_unity_exception_from_start_no_unload) { reset_counters(); { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib, registry); try { sl->start(); FAIL(); } catch (unity::Exception const& e) { EXPECT_STREQ("unity::ResourceException: Scope testScope: terminated due to exception in start():\n" " unity::LogicException: start failure", e.what()); } } EXPECT_EQ(0, num_stop()); EXPECT_EQ(1, num_create()); EXPECT_EQ(1, num_destroy()); } // Test that things behave as expected if start() throws an unknown exception. TEST(ScopeLoader, throw_unknown_exception_from_start) { reset_counters(); { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unknown_ex_from_start_lib, registry); try { sl->start(); sl->unload(); EXPECT_TRUE(sl->scope_base()); FAIL(); } catch (unity::Exception const& e) { EXPECT_STREQ("unity::ResourceException: Scope testScope: terminated due to exception in start():\n" " unknown exception", e.what()); } } EXPECT_EQ(0, num_stop()); EXPECT_EQ(1, num_create()); EXPECT_EQ(1, num_destroy()); } // Test that things behave as expected if stop() throws a Unity exception. TEST(ScopeLoader, throw_unity_exception_from_stop) { reset_counters(); try { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_stop_lib, registry); sl->start(); sl->stop(); EXPECT_EQ(1, num_start()); EXPECT_EQ(1, num_stop()); EXPECT_EQ(1, num_create()); EXPECT_EQ(1, num_destroy()); sl->unload(); EXPECT_TRUE(sl->scope_base()); FAIL(); } catch (unity::ResourceException const& e) { EXPECT_STREQ("unity::ResourceException: Scope testScope: terminated due to exception in stop():\n" " unity::LogicException: stop failure", e.what()); } } // Test that things behave as expected if stop() throws a std exception. TEST(ScopeLoader, throw_std_exception_from_stop) { reset_counters(); try { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_std_ex_from_stop_lib, registry); sl->start(); sl->stop(); EXPECT_EQ(1, num_start()); EXPECT_EQ(1, num_stop()); EXPECT_EQ(1, num_create()); EXPECT_EQ(1, num_destroy()); sl->unload(); EXPECT_TRUE(sl->scope_base()); FAIL(); } catch (unity::ResourceException const& e) { EXPECT_STREQ("unity::ResourceException: Scope testScope: terminated due to exception in stop():\n" " stop failure", e.what()); } } // Test that things behave as expected if stop() throws an unknown exception. TEST(ScopeLoader, throw_unknown_exception_from_stop) { reset_counters(); try { ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unknown_ex_from_stop_lib, registry); sl->start(); sl->stop(); EXPECT_EQ(1, num_start()); EXPECT_EQ(1, num_stop()); EXPECT_EQ(1, num_create()); EXPECT_EQ(1, num_destroy()); sl->unload(); FAIL(); } catch (unity::ResourceException const& e) { EXPECT_STREQ("unity::ResourceException: Scope testScope: terminated due to exception in stop():\n" " unknown exception", e.what()); } } // Test that things behave as expected if unload is called more than once TEST(ScopeLoader, unload) { reset_counters(); ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, registry); sl->start(); sl->stop(); sl->unload(); sl->unload(); EXPECT_EQ(1, num_start()); EXPECT_EQ(1, num_stop()); EXPECT_EQ(1, num_create()); EXPECT_EQ(1, num_destroy()); } // Test that things behave as expected if unload is called while the scope is running and stop() throws TEST(ScopeLoader, unload_stop_exception) { reset_counters(); ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_stop_lib, registry); sl->start(); try { sl->unload(); FAIL(); } catch (unity::Exception const& e) { EXPECT_STREQ("unity::ResourceException: Scope testScope: terminated due to exception in stop():\n" " unity::LogicException: stop failure", e.what()); } // Call unload again to make sure that the second time, it doesn't throw. try { sl->unload(); } catch (...) { FAIL(); } } // Test that start() throws an exception after unload() TEST(ScopeLoader, restart_exception) { reset_counters(); ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, registry); sl->start(); sl->unload(); try { sl->start(); FAIL(); } catch (unity::Exception const& e) { EXPECT_STREQ("unity::LogicException: Cannot start scope testScope in Finished state", e.what()); } } // Test that stop() throws an exception after unload() TEST(ScopeLoader, stop_after_unload_exception) { reset_counters(); ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, registry); sl->start(); sl->unload(); try { sl->stop(); FAIL(); } catch (unity::Exception const& e) { EXPECT_STREQ("unity::LogicException: Cannot stop scope testScope in Finished state", e.what()); } } // Test that start() and stop() throw for scope in Failed state TEST(ScopeLoader, restart_failed) { reset_counters(); ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib, registry); try { sl->start(); sl->unload(); FAIL(); } catch (unity::Exception const&) { } try { sl->start(); } catch (unity::Exception const& e) { EXPECT_STREQ("unity::LogicException: Cannot start scope testScope in Failed state", e.what()); } try { sl->stop(); } catch (unity::Exception const& e) { EXPECT_STREQ("unity::LogicException: Cannot stop scope testScope in Failed state", e.what()); } } // Test that we can have more than one scope loaded without getting confused which one we are talking to. TEST(ScopeLoader, two_scopes) { reset_counters(); clear_vars(); ScopeLoader::UPtr slA = ScopeLoader::load("scopeA", scopeA, registry); slA->start(); EXPECT_EQ(1, num_create()); EXPECT_EQ(1, num_start()); ScopeLoader::UPtr slB = ScopeLoader::load("scopeB", scopeB, registry); slB->start(); EXPECT_EQ(2, num_create()); EXPECT_EQ(2, num_start()); EXPECT_EQ(0, get_scopeA_var()); EXPECT_EQ(0, get_scopeB_var()); slA->unload(); EXPECT_EQ(1, get_scopeA_var()); EXPECT_EQ(0, get_scopeB_var()); slB->unload(); EXPECT_EQ(1, get_scopeA_var()); EXPECT_EQ(2, get_scopeB_var()); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/NoDestroy.cpp0000644000015301777760000000204012320776161031376 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "MyScope.h" #include "Counters.h" #include // Library that doesn't have the expected destroy method extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { inc_create(); return new MyScope; } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/TestExports.h0000644000015301777760000000146512320776161031433 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef TESTEXPORTS_H #define TESTEXPORTS_H #define EXPORT __attribute__ ((visibility ("default"))) #endif unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/PerScopeVariables.cpp0000644000015301777760000000270412320776161033030 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "PerScopeVariables.h" #include using namespace std; namespace { int scopeA_var; int scopeB_var; std::mutex count_mutex; } // Helper functions to get and set scopeA_var and scopeB_var so we can test that multiple scopes in the // same address space work correctly. void set_scopeA_var(int val) { lock_guard lock(count_mutex); scopeA_var = val; } int get_scopeA_var() { lock_guard lock(count_mutex); return scopeA_var; } void set_scopeB_var(int val) { lock_guard lock(count_mutex); scopeB_var = val; } int get_scopeB_var() { lock_guard lock(count_mutex); return scopeB_var; } void clear_vars() { lock_guard lock(count_mutex); scopeA_var = 0; scopeB_var = 0; } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/ThrowStdExFromStop.cpp0000644000015301777760000000261512320776161033225 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "MyScope.h" #include "Counters.h" #include #include using namespace std; class EXPORT MyThrowingScope : public MyScope { public: virtual void stop() override { inc_stop(); throw std::logic_error("stop failure"); } }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { inc_create(); return new MyThrowingScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { inc_destroy(); delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeLoader/BadVersion.cpp0000644000015301777760000000414012320776161031507 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ // Force Version.h to use the specified version, so we get coverage on the version check. #define UNITY_SCOPES_VERSION_MAJOR 666 #include "Counters.h" #include #include #include class EXPORT MyScope : public unity::scopes::ScopeBase { public: MyScope() {} virtual ~MyScope() {} virtual int start(std::string const&, unity::scopes::RegistryProxy const&) override { inc_start(); return VERSION; } virtual void stop() override { inc_stop(); } virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&, unity::scopes::SearchMetadata const&) override { return nullptr; } virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&, unity::scopes::ActionMetadata const&) override { return nullptr; } }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { inc_create(); return new MyScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { inc_destroy(); delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/MiddlewareFactory/0000755000015301777760000000000012320776463030162 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/MiddlewareFactory/MiddlewareFactory_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/MiddlewareFactory/MiddlewareFactory0000644000015301777760000000310712320776161033506 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; using namespace unity::scopes; using namespace unity::scopes::internal; TEST(MiddlewareFactory, basic) { MiddlewareFactory f((RuntimeImpl*)0x1); EXPECT_EQ(nullptr, f.find("nosuchscope", "Zmq")); MiddlewareBase::SPtr not_found; MiddlewareBase::SPtr mw = f.find("testscope", "Zmq"); EXPECT_EQ(not_found, mw); mw = f.find("testscope", "NoSuchMiddleware"); EXPECT_EQ(not_found, mw); } TEST(MiddlewareFactory, BadKind) { try { MiddlewareFactory f((RuntimeImpl*)0x1); f.create("somescope", "NoSuchMiddleware", "Zmq.ini"); FAIL(); } catch (ConfigException const& e) { EXPECT_STREQ("unity::scopes::ConfigException: Invalid middleware kind: NoSuchMiddleware", e.what()); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/MiddlewareFactory/CMakeLists.txt0000644000015301777760000000026012320776161032713 0ustar pbusernogroup00000000000000add_executable(MiddlewareFactory_test MiddlewareFactory_test.cpp) target_link_libraries(MiddlewareFactory_test ${TESTLIBS}) add_test(MiddlewareFactory MiddlewareFactory_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeConfig/0000755000015301777760000000000012320776463027326 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeConfig/MWEmpty.ini.in0000644000015301777760000000013712320776161031772 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = Registry Registry.ConfigFile = Registry.ini Default.Middleware = unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeConfig/RegFileEmpty.ini.in0000644000015301777760000000012612320776161032762 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = Registry Registry.ConfigFile = Default.Middleware = Zmq unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeConfig/RegIDEmpty.ini.in0000644000015301777760000000013212320776161032374 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = Registry.ConfigFile = Registry.ini Default.Middleware = Zmq unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeConfig/BadRegID.ini.in0000644000015301777760000000014412320776161031767 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = Regi/stry Registry.ConfigFile = Registry.ini Default.Middleware = Zmq ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeConfig/RuntimeConfig_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeConfig/RuntimeConfig_test.cp0000644000015301777760000000432512320776161033461 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include using namespace std; using namespace unity::scopes; using namespace unity::scopes::internal; TEST(RuntimeConfig, basic) { RuntimeConfig c(""); EXPECT_EQ("Registry", c.registry_identity()); EXPECT_EQ(DFLT_REGISTRY_INI, c.registry_configfile()); EXPECT_EQ("Zmq", c.default_middleware()); } TEST(RuntimeConfig, BadRegistryID) { try { RuntimeConfig c("BadRegID.ini"); FAIL(); } catch (ConfigException const& e) { EXPECT_STREQ("unity::scopes::ConfigException: \"BadRegID.ini\": Illegal character in value for " "Registry.Identity: \"Regi/stry\": identity cannot contain '/'", e.what()); } } TEST(RuntimeConfig, MiddlewareEmpty) { try { RuntimeConfig c("MWEmpty.ini"); FAIL(); } catch (ConfigException const& e) { EXPECT_STREQ("unity::scopes::ConfigException: \"MWEmpty.ini\": Illegal empty value for Default.Middleware", e.what()); } } TEST(RuntimeConfig, BadMiddleware) { try { RuntimeConfig c("BadMW.ini"); FAIL(); } catch (ConfigException const& e) { EXPECT_STREQ("unity::scopes::ConfigException: \"BadMW.ini\": Illegal value for Default.Middleware: " "\"Foo\": legal values are \"Zmq\" and \"REST\"", e.what()); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeConfig/BadMW.ini.in0000644000015301777760000000014312320776161031357 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = Registry Registry.ConfigFile = Registry.ini Default.Middleware = Foo unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeConfig/CMakeLists.txt0000644000015301777760000000065512320776161032067 0ustar pbusernogroup00000000000000configure_file(BadMW.ini.in BadMW.ini) configure_file(BadRegID.ini.in BadRegID.ini) configure_file(MWEmpty.ini.in MWEmpty.ini) configure_file(RegFileEmpty.ini.in RegFileEmpty.ini) configure_file(RegIDEmpty.ini.in RegIDEmpty.ini) configure_file(Runtime.ini.in Runtime.ini) add_executable(RuntimeConfig_test RuntimeConfig_test.cpp) target_link_libraries(RuntimeConfig_test ${TESTLIBS}) add_test(RuntimeConfig RuntimeConfig_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeConfig/Runtime.ini.in0000644000015301777760000000017412320776161032054 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = Registry Registry.ConfigFile = Registry.ini Default.Middleware = Zmq Zmq.ConfigFile = Zmq.ini unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/Reaper/0000755000015301777760000000000012320776463025773 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/Reaper/Reaper_test.cpp0000644000015301777760000001567012320776161030760 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; using namespace unity::scopes; using namespace unity::scopes::internal; class Counter { public: Counter() : c(0) {} void reset() { lock_guard l(m); c = 0; } int get() { lock_guard l(m); return c; } void increment() { lock_guard l(m); ++c; } void increment_throw() { lock_guard l(m); ++c; throw 42; } private: int c; mutex m; }; // Basic tests. TEST(Reaper, basic) { { Reaper::create(1, 5); // Just to check that we can create and destroy without doing anything else } { Reaper::create(1, 5, Reaper::CallbackOnDestroy); // Again, with the other policy } { // Make sure it's OK for the reaper to go out of scope while there are still ReapItems on it. // Check that none of the callbacks are called in this case. Counter c; { auto r = Reaper::create(5, 5); for (auto i = 0; i < 10; ++i) { r->add(bind(&Counter::increment, &c)); } EXPECT_EQ(10u, r->size()); } EXPECT_EQ(0, c.get()); } { // Same again, but with CallbackOnDestroy. // Check that all of the callbacks are called in this case. Counter c; { auto r = Reaper::create(5, 5, Reaper::CallbackOnDestroy); for (auto i = 0; i < 10; ++i) { r->add(bind(&Counter::increment, &c)); } EXPECT_EQ(10u, r->size()); } EXPECT_EQ(10, c.get()); } { // Make sure it's OK to invoke methods on a ReapItem after the reaper has gone out of scope. Counter c; vector v; { auto r = Reaper::create(5, 5); for (auto i = 0; i < 10; ++i) { v.push_back(r->add(bind(&Counter::increment, &c))); } EXPECT_EQ(10u, r->size()); } EXPECT_EQ(0, c.get()); v[0]->refresh(); // Does nothing v[1]->destroy(); // Does nothing v[1]->destroy(); // Safe to call more than once v[1]->refresh(); // Safe to call after destroy } { // Make sure that calling destroy on a ReapItem removes that item from the reaper. Counter c; vector v; { auto r = Reaper::create(5, 5); for (auto i = 0; i < 10; ++i) { v.push_back(r->add(bind(&Counter::increment, &c))); } EXPECT_EQ(10u, r->size()); v[0]->destroy(); v[4]->destroy(); v[9]->destroy(); EXPECT_EQ(7u, r->size()); // We call destroy again, to make sure that it's safe to call it twice even though the first time // around, the destroy actually removed the item. v[0]->destroy(); v[4]->destroy(); v[9]->destroy(); EXPECT_EQ(7u, r->size()); } EXPECT_EQ(0, c.get()); } { // Make sure that, after refreshing an item, it still can be destroyed, that is, that the ReapItem // is correctly located in the reaper list even after having been moved. Counter c; vector v; { auto r = Reaper::create(5, 5); v.push_back(r->add(bind(&Counter::increment, &c))); v.push_back(r->add(bind(&Counter::increment, &c))); v.push_back(r->add(bind(&Counter::increment, &c))); EXPECT_EQ(3u, r->size()); v[0]->refresh(); // Moves this element from the tail to the head EXPECT_EQ(3u, r->size()); v[0]->destroy(); EXPECT_EQ(2u, r->size()); v[0]->destroy(); // no-op EXPECT_EQ(2u, r->size()); v[1]->destroy(); v[2]->destroy(); EXPECT_EQ(0u, r->size()); } EXPECT_EQ(0, c.get()); } } TEST(Reaper, expiry) { { Counter c; auto r = Reaper::create(1, 2); // Entries expire after 2 seconds. auto e1 = r->add(bind(&Counter::increment, &c)); auto e2 = r->add(bind(&Counter::increment, &c)); // One second later, they still must both be there. this_thread::sleep_for(chrono::milliseconds(1000)); EXPECT_EQ(2u, r->size()); EXPECT_EQ(0, c.get()); // Refresh one of the entries. e2->refresh(); // 1.2 seconds later, one of them must have disappeared. this_thread::sleep_for(chrono::milliseconds(1200)); EXPECT_EQ(1u, r->size()); EXPECT_EQ(1, c.get()); // 0.6 seconds later, the second entry must still be around. this_thread::sleep_for(chrono::milliseconds(600)); EXPECT_EQ(1u, r->size()); EXPECT_EQ(1, c.get()); // 0.4 seconds later, the second entry must have disappeared. this_thread::sleep_for(chrono::milliseconds(400)); EXPECT_EQ(0u, r->size()); EXPECT_EQ(2, c.get()); } } TEST(Reaper, exceptions) { try { Reaper::create(0, 5); FAIL(); } catch (unity::InvalidArgumentException const& e) { EXPECT_STREQ("unity::InvalidArgumentException: Reaper: invalid reap_interval (0). Interval must be > 0.", e.what()); } try { Reaper::create(2, 1); FAIL(); } catch (unity::LogicException const& e) { EXPECT_STREQ("unity::LogicException: Reaper: reap_interval (2) must be <= expiry_interval (1).", e.what()); } try { auto r = Reaper::create(1, 2); r->add(std::function()); FAIL(); } catch (unity::InvalidArgumentException const& e) { EXPECT_STREQ("unity::InvalidArgumentException: Reaper: invalid null callback passed to add().", e.what()); } // Make sure that if a callback throws an exception, this does no harm. Counter c; { auto r = Reaper::create(5, 5, Reaper::CallbackOnDestroy); r->add(bind(&Counter::increment_throw, &c)); EXPECT_EQ(1u, r->size()); EXPECT_EQ(0, c.get()); } EXPECT_EQ(1, c.get()); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/Reaper/CMakeLists.txt0000644000015301777760000000017112320776161030525 0ustar pbusernogroup00000000000000add_executable(Reaper_test Reaper_test.cpp) target_link_libraries(Reaper_test ${TESTLIBS}) add_test(Reaper Reaper_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/UniqueID/0000755000015301777760000000000012320776463026240 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/UniqueID/UniqueID_test.cpp0000644000015301777760000000305512320776161031464 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace std; using namespace unity::scopes::internal; bool has_suffix(string const& s, string const& suffix) { auto s_len = s.length(); auto suffix_len = suffix.length(); if (s_len >= suffix_len) { return s.compare(s_len - suffix_len, suffix_len, suffix) == 0; } return false; } TEST(UniqueID, basic) { UniqueID u; string id = u.gen(); EXPECT_EQ(16u, id.size()); EXPECT_TRUE(has_suffix(id, "00000000")); string id2 = u.gen(); EXPECT_TRUE(has_suffix(id2, "00000001")); UniqueID v; id = v.gen(); EXPECT_TRUE(has_suffix(id, "00000000")); // New generator starts new sequence } TEST(UniqueID, seed) { UniqueID u(1); UniqueID v(1); string id = u.gen(); string id2 = v.gen(); EXPECT_EQ(id, id2); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/UniqueID/CMakeLists.txt0000644000015301777760000000020312320776161030766 0ustar pbusernogroup00000000000000add_executable(UniqueID_test UniqueID_test.cpp) target_link_libraries(UniqueID_test ${TESTLIBS}) add_test(UniqueID UniqueID_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/DynamicLoader/0000755000015301777760000000000012320776463027270 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/DynamicLoader/badtestlib.cpp0000644000015301777760000000173012320776161032105 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "TestExports.h" extern "C" { EXPORT void // cppcheck-suppress unusedFunction test_function() { } EXPORT int // cppcheck-suppress unusedFunction unresolved() { extern int foo(); return foo(); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/DynamicLoader/testlib.cpp0000644000015301777760000000156212320776161031441 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "TestExports.h" extern "C" { EXPORT void // cppcheck-suppress unusedFunction test_function() { } EXPORT int test_variable; } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/DynamicLoader/CMakeLists.txt0000644000015301777760000000036312320776161032025 0ustar pbusernogroup00000000000000add_executable(DynamicLoader_test DynamicLoader_test.cpp) target_link_libraries(DynamicLoader_test ${TESTLIBS}) add_library(testlib MODULE testlib.cpp) add_library(badtestlib MODULE badtestlib.cpp) add_test(DynamicLoader DynamicLoader_test) ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/DynamicLoader/DynamicLoader_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/DynamicLoader/DynamicLoader_test.cp0000644000015301777760000000660512320776161033370 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include // Use Boost implementation until http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631 is fixed. #include using namespace std; using namespace unity::scopes::internal; namespace { char const* goodlib = TEST_BUILD_ROOT "/gtest/scopes/internal/DynamicLoader/libtestlib.so"; char const* badlib = TEST_BUILD_ROOT "/gtest/scopes/internal/DynamicLoader/libbadtestlib.so"; } // Basic test. TEST(DynamicLoader, basic) { { DynamicLoader::UPtr dl = DynamicLoader::create(goodlib); DynamicLoader::VoidFunc f = dl->find_function("test_function"); EXPECT_NE(nullptr, f); f(); // Call it just to be sure it works int* p = static_cast(dl->find_variable("test_variable")); EXPECT_NE(nullptr, p); *p = 42; // Assign it just to be sure it works } { // For coverage testing DynamicLoader::UPtr dl = DynamicLoader::create(goodlib, DynamicLoader::Binding::lazy, DynamicLoader::Unload::noclose); } } // Make sure that lazy and immediate binding work as intended. TEST(DynamicLoader, flags) { { DynamicLoader::UPtr dl = DynamicLoader::create(badlib); DynamicLoader::VoidFunc f = dl->find_function("test_function"); // Must work despite unreslved(). EXPECT_NE(nullptr, f); } try { // Must fail because of unresolved symbol. DynamicLoader::UPtr dl = DynamicLoader::create(badlib, DynamicLoader::Binding::now); } catch (unity::ResourceException const& e) { boost::regex r("unity::ResourceException: .*/libbadtestlib.so: undefined symbol: foo"); EXPECT_TRUE(boost::regex_match(e.what(), r)); } } TEST(DynamicLoader, exceptions) { { try { DynamicLoader::UPtr dl = DynamicLoader::create("no_such_lib"); } catch (unity::ResourceException const& e) { EXPECT_STREQ("unity::ResourceException: no_such_lib: cannot open shared object file: No such file or directory", e.what()); } } { DynamicLoader::UPtr dl = DynamicLoader::create(goodlib); try { dl->find_function("no_such_symbol"); } catch (unity::ResourceException const& e) { boost::regex r("unity::ResourceException: .*/libtestlib.so: undefined symbol: no_such_symbol"); EXPECT_TRUE(boost::regex_match(e.what(), r)); } } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/DynamicLoader/TestExports.h0000644000015301777760000000146512320776161031746 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef TESTEXPORTS_H #define TESTEXPORTS_H #define EXPORT __attribute__ ((visibility ("default"))) #endif unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ThreadPool/0000755000015301777760000000000012320776463026616 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ThreadPool/CMakeLists.txt0000644000015301777760000000021512320776161031347 0ustar pbusernogroup00000000000000add_executable(ThreadPool_test ThreadPool_test.cpp) target_link_libraries(ThreadPool_test ${TESTLIBS}) add_test(ThreadPool ThreadPool_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ThreadPool/ThreadPool_test.cpp0000644000015301777760000000425012320776161032416 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace std; using namespace unity::scopes::internal; TEST(ThreadPool, basic) { // Creation and destruction in quick succession { ThreadPool p(1); } { ThreadPool p(5); } { ThreadPool p(20); } } atomic_int count; void f() { ++count; this_thread::sleep_for(chrono::milliseconds(200)); } void g() { ++count; } TEST(ThreadPool, submit) { { ThreadPool p(1); p.submit(f); p.submit(f); } { ThreadPool p(5); p.submit(f); p.submit(f); } { count = 0; ThreadPool p(20); p.submit(f); p.submit(f); this_thread::sleep_for(chrono::milliseconds(300)); EXPECT_EQ(2, count); } { count = 0; ThreadPool p(20); p.submit(g); p.submit(g); p.submit(g); this_thread::sleep_for(chrono::milliseconds(300)); EXPECT_EQ(3, count); } } TEST(ThreadPool, exception) { try { ThreadPool p(0); } catch (unity::InvalidArgumentException const& e) { EXPECT_STREQ("unity::InvalidArgumentException: ThreadPool(): invalid pool size: 0", e.what()); } try { ThreadPool p(-1); } catch (unity::InvalidArgumentException const& e) { EXPECT_STREQ("unity::InvalidArgumentException: ThreadPool(): invalid pool size: -1", e.what()); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/0000755000015301777760000000000012320776463025705 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/0000755000015301777760000000000012320776463031167 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/TestProvider2_tp.cunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/TestProvider0000644000015301777760000000146312320776161033543 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #define TRACEPOINT_CREATE_PROBES #include #include ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/TestProvider_tp.cunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/TestProvider0000644000015301777760000000146212320776161033542 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #define TRACEPOINT_CREATE_PROBES #include #include ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/TestProvider2_tp.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/TestProvider0000644000015301777760000000146112320776161033541 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #define TRACEPOINT_DEFINE #define TRACEPOINT_PROBE_DYNAMIC_LINKAGE #include ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/SimpleTracepoint_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/SimpleTracep0000644000015301777760000000466312320776161033506 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include #include #include // Basic trace test. TEST(SimpleTracepoint, basic_trace_test) { dlopen( TRACEPOINT_LIB, RTLD_NOW ); // ensure that the LTTng session daemon is running in the background // (this call is harmless if the daemon is already running) system("lttng-sessiond -d"); system("rm -R -f ./lttng-trace"); system("lttng create trace_session -o ./lttng-trace"); system("lttng enable-event -a -s trace_session -u"); system("lttng start trace_session"); simple_tracepoint( test_provider, event1, 0, 1, 2.3, "four" ); simple_tracepoint( test_provider, event2, 5.6, 7 ); simple_tracepoint( test_provider2, event3, 8, 9, 10.11, "twelve" ); simple_tracepoint( test_provider2, event4, 13.14, 15 ); system("lttng stop trace_session"); system("lttng view -t ./lttng-trace > ./lttng-trace/trace.txt"); system("lttng destroy trace_session"); std::ifstream trace_file("./lttng-trace/trace.txt"); std::string trace((std::istreambuf_iterator(trace_file)), std::istreambuf_iterator()); EXPECT_NE( std::string::npos, trace.find("test_provider:event1:") ); EXPECT_NE( std::string::npos, trace.find("{ a = 0, b = 1, c = 2.3, d = \"four\" }") ); EXPECT_NE( std::string::npos, trace.find("test_provider:event2:") ); EXPECT_NE( std::string::npos, trace.find("{ a = 5.6, b = 7 }") ); EXPECT_NE( std::string::npos, trace.find("test_provider2:event3:") ); EXPECT_NE( std::string::npos, trace.find("{ a = 8, b = 9, c = 10.11, d = \"twelve\" }") ); EXPECT_NE( std::string::npos, trace.find("test_provider2:event4:") ); EXPECT_NE( std::string::npos, trace.find("{ a = 13.14, b = 15 }") ); } ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/TestProvider_tp.hunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/TestProvider0000644000015301777760000000253112320776161033540 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #if !defined(SIMPLETRACEPOINTTEST_TESTPROVIDER_TP_H) || defined(TRACEPOINT_HEADER_MULTI_READ) #define SIMPLETRACEPOINTTEST_TESTPROVIDER_TP_H #undef TRACEPOINT_PROVIDER #undef TRACEPOINT_INCLUDE #define TRACEPOINT_PROVIDER test_provider #define TRACEPOINT_INCLUDE #include #include SIMPLE_TRACEPOINT( event1, TRACE_DEBUG, stp_integer(int64_t, a), stp_integer(int, b), stp_float(float, c), stp_string(d) ) SIMPLE_TRACEPOINT( event2, TRACE_DEBUG, stp_float(double, a), stp_integer(uint32_t, b) ) #endif /* SIMPLETRACEPOINTTEST_TESTPROVIDER_TP_H */ ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/CMakeLists.txtunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/CMakeLists.t0000644000015301777760000000100712320776161033344 0ustar pbusernogroup00000000000000include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) add_executable( SimpleTracepoint_test SimpleTracepoint_test.cpp TestProvider_tp.cpp TestProvider2_tp.cpp ) add_library( testtracer SHARED TestProvider_tp.c TestProvider2_tp.c ) add_definitions(-DTRACEPOINT_LIB="${CMAKE_CURRENT_BINARY_DIR}/libtesttracer.so") target_link_libraries( SimpleTracepoint_test ${TESTLIBS} ) target_link_libraries( testtracer lttng-ust urcu-bp dl ) add_test( SimpleTracepoint SimpleTracepoint_test ) ././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/TestProvider_tp.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/TestProvider0000644000015301777760000000146012320776161033540 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #define TRACEPOINT_DEFINE #define TRACEPOINT_PROBE_DYNAMIC_LINKAGE #include ././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/TestProvider2_tp.hunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/SimpleTracepoint/TestProvider0000644000015301777760000000253612320776161033545 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #if !defined(SIMPLETRACEPOINTTEST_TESTPROVIDER2_TP_H) || defined(TRACEPOINT_HEADER_MULTI_READ) #define SIMPLETRACEPOINTTEST_TESTPROVIDER2_TP_H #undef TRACEPOINT_PROVIDER #undef TRACEPOINT_INCLUDE #define TRACEPOINT_PROVIDER test_provider2 #define TRACEPOINT_INCLUDE #include #include SIMPLE_TRACEPOINT( event3, TRACE_DEBUG, stp_integer(int64_t, a), stp_integer(int, b), stp_float(float, c), stp_string(d) ) SIMPLE_TRACEPOINT( event4, TRACE_DEBUG, stp_float(double, a), stp_integer(uint32_t, b) ) #endif /* SIMPLETRACEPOINTTEST_TESTPROVIDER2_TP_H */ unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/lttng/CMakeLists.txt0000644000015301777760000000004412320776161030436 0ustar pbusernogroup00000000000000#add_subdirectory(SimpleTracepoint) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeMetadataImpl/0000755000015301777760000000000012320776463030111 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeMetadataImpl/Zmq.ini.in0000644000015301777760000000007312320776161031761 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeMetadataImpl/CMakeLists.txt0000644000015301777760000000032412320776161032643 0ustar pbusernogroup00000000000000configure_file(Zmq.ini.in Zmq.ini) add_executable(ScopeMetadataImpl_test ScopeMetadataImpl_test.cpp) target_link_libraries(ScopeMetadataImpl_test ${TESTLIBS}) add_test(ScopeMetadataImpl ScopeMetadataImpl_test) ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl0000644000015301777760000003626212320776161033374 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include // Use Boost implementation until http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631 is fixed. #include #include using namespace std; using namespace unity; using namespace unity::scopes; using namespace unity::scopes::internal; using namespace unity::scopes::internal::zmq_middleware; TEST(ScopeMetadataImpl, basic) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeMetadataImpl/Zmq.ini", (RuntimeImpl*)0x1); unique_ptr mi(new ScopeMetadataImpl(&mw)); mi->set_scope_id("scope_id"); auto mw_proxy = mw.create_scope_proxy("identity", "endpoint"); mi->set_proxy(ScopeImpl::create(mw_proxy, mw.runtime(), "scope_id")); mi->set_display_name("display_name"); mi->set_description("description"); mi->set_author("author"); // Keep a copy for tests below unique_ptr mi2(new ScopeMetadataImpl(*mi)); // Create the public instance and check that the values match auto m = ScopeMetadataImpl::create(move(mi)); EXPECT_EQ("scope_id", m.scope_id()); EXPECT_EQ("identity", m.proxy()->identity()); EXPECT_EQ("endpoint", m.proxy()->endpoint()); EXPECT_EQ("display_name", m.display_name()); EXPECT_EQ("description", m.description()); EXPECT_EQ("author", m.author()); EXPECT_EQ(0, m.appearance_attributes().size()); // Check that optional fields that are not set throw try { m.art(); FAIL(); } catch (NotFoundException const& e) { EXPECT_STREQ("unity::scopes::NotFoundException: attribute not set (name = art)", e.what()); } try { m.icon(); FAIL(); } catch (NotFoundException const& e) { EXPECT_STREQ("unity::scopes::NotFoundException: attribute not set (name = icon)", e.what()); } try { m.search_hint(); FAIL(); } catch (NotFoundException const& e) { EXPECT_STREQ("unity::scopes::NotFoundException: attribute not set (name = search_hint)", e.what()); } try { m.hot_key(); FAIL(); } catch (NotFoundException const& e) { EXPECT_STREQ("unity::scopes::NotFoundException: attribute not set (name = hot_key)", e.what()); } try { m.scope_directory(); FAIL(); } catch (NotFoundException const& e) { EXPECT_STREQ("unity::scopes::NotFoundException: attribute not set (name = scope_directory)", e.what()); } // when "invisible" is not set, false is returned EXPECT_FALSE(m.invisible()); // Check that the copy has the same values as the original EXPECT_EQ("scope_id", mi2->scope_id()); EXPECT_EQ("identity", mi2->proxy()->identity()); EXPECT_EQ("endpoint", mi2->proxy()->endpoint()); EXPECT_EQ("display_name", mi2->display_name()); EXPECT_EQ("description", mi2->description()); EXPECT_EQ("author", mi2->author()); EXPECT_EQ(0, mi2->appearance_attributes().size()); VariantMap attrs; attrs["foo"] = "bar"; // Set optional fields on copy. mi2->set_art("art"); mi2->set_icon("icon"); mi2->set_search_hint("search_hint"); mi2->set_hot_key("hot_key"); mi2->set_invisible(true); mi2->set_appearance_attributes(attrs); mi2->set_scope_directory("/foo"); // Make another copy, so we get coverage on the entire copy constructor unique_ptr mi3(new ScopeMetadataImpl(*mi2)); // Check that optional fields are set correctly m = ScopeMetadataImpl::create(move(mi2)); EXPECT_EQ("search_hint", m.search_hint()); EXPECT_EQ("hot_key", m.hot_key()); EXPECT_TRUE(m.invisible()); EXPECT_EQ("bar", m.appearance_attributes()["foo"].get_string()); // Make another value unique_ptr ti(new ScopeMetadataImpl(&mw)); ti->set_scope_id("tmp scope_id"); mw_proxy = mw.create_scope_proxy("tmp identity", "tmp endpoint"); ti->set_proxy(ScopeImpl::create(mw_proxy, mw.runtime(), "tmp scope_id")); ti->set_display_name("tmp display_name"); ti->set_description("tmp description"); ti->set_author("tmp author"); ti->set_art("tmp art"); ti->set_icon("tmp icon"); ti->set_search_hint("tmp search_hint"); ti->set_hot_key("tmp hot_key"); ti->set_invisible(true); ti->set_scope_directory("/foo"); ti->set_appearance_attributes(attrs); // Check impl assignment operator ScopeMetadataImpl ci(&mw); ci = *ti; EXPECT_EQ("tmp scope_id", ci.scope_id()); EXPECT_EQ("tmp identity", ci.proxy()->identity()); EXPECT_EQ("tmp endpoint", ci.proxy()->endpoint()); EXPECT_EQ("tmp display_name", ci.display_name()); EXPECT_EQ("tmp description", ci.description()); EXPECT_EQ("tmp author", ci.author()); EXPECT_EQ("tmp art", ci.art()); EXPECT_EQ("tmp icon", ci.icon()); EXPECT_EQ("tmp search_hint", ci.search_hint()); EXPECT_EQ("tmp hot_key", ci.hot_key()); EXPECT_EQ("/foo", ci.scope_directory()); EXPECT_EQ("bar", ci.appearance_attributes()["foo"].get_string()); EXPECT_TRUE(ci.invisible()); // Check public assignment operator auto tmp = ScopeMetadataImpl::create(move(ti)); m = tmp; EXPECT_EQ("tmp scope_id", m.scope_id()); EXPECT_EQ("tmp identity", m.proxy()->identity()); EXPECT_EQ("tmp endpoint", m.proxy()->endpoint()); EXPECT_EQ("tmp display_name", m.display_name()); EXPECT_EQ("tmp description", m.description()); EXPECT_EQ("tmp author", m.author()); EXPECT_EQ("tmp art", m.art()); EXPECT_EQ("tmp icon", m.icon()); EXPECT_EQ("tmp search_hint", m.search_hint()); EXPECT_EQ("tmp hot_key", m.hot_key()); EXPECT_EQ("/foo", m.scope_directory()); EXPECT_EQ("bar", m.appearance_attributes()["foo"].get_string()); EXPECT_TRUE(m.invisible()); // Self-assignment tmp = tmp; EXPECT_EQ("tmp scope_id", tmp.scope_id()); EXPECT_EQ("tmp identity", tmp.proxy()->identity()); EXPECT_EQ("tmp endpoint", tmp.proxy()->endpoint()); EXPECT_EQ("tmp display_name", tmp.display_name()); EXPECT_EQ("tmp description", tmp.description()); EXPECT_EQ("tmp author", tmp.author()); EXPECT_EQ("tmp art", tmp.art()); EXPECT_EQ("tmp icon", tmp.icon()); EXPECT_EQ("tmp search_hint", tmp.search_hint()); EXPECT_EQ("tmp hot_key", tmp.hot_key()); EXPECT_EQ("bar", tmp.appearance_attributes()["foo"].get_string()); EXPECT_EQ("/foo", tmp.scope_directory()); EXPECT_TRUE(tmp.invisible()); // Copy constructor ScopeMetadata tmp2(tmp); EXPECT_EQ("tmp scope_id", tmp2.scope_id()); EXPECT_EQ("tmp identity", tmp2.proxy()->identity()); EXPECT_EQ("tmp endpoint", tmp2.proxy()->endpoint()); EXPECT_EQ("tmp display_name", tmp2.display_name()); EXPECT_EQ("tmp description", tmp2.description()); EXPECT_EQ("tmp author", tmp2.author()); EXPECT_EQ("tmp art", tmp2.art()); EXPECT_EQ("tmp icon", tmp2.icon()); EXPECT_EQ("tmp search_hint", tmp2.search_hint()); EXPECT_EQ("tmp hot_key", tmp2.hot_key()); EXPECT_EQ("/foo", tmp2.scope_directory()); EXPECT_EQ("bar", tmp2.appearance_attributes()["foo"].get_string()); EXPECT_TRUE(tmp2.invisible()); } TEST(ScopeMetadataImpl, serialize) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeMetadataImpl/Zmq.ini", (RuntimeImpl*)0x1); unique_ptr mi(new ScopeMetadataImpl(&mw)); mi->set_scope_id("scope_id"); auto mw_proxy = mw.create_scope_proxy("identity", "endpoint"); mi->set_proxy(ScopeImpl::create(mw_proxy, mw.runtime(), "scope_id")); mi->set_display_name("display_name"); mi->set_description("description"); mi->set_author("author"); mi->set_art("art"); mi->set_icon("icon"); mi->set_search_hint("search_hint"); mi->set_hot_key("hot_key"); mi->set_scope_directory("/foo"); mi->set_invisible(false); // Check that serialize() sets the map values correctly auto m = ScopeMetadataImpl::create(move(mi)); auto var = m.serialize(); EXPECT_EQ(11u, var.size()); EXPECT_EQ("scope_id", var["scope_id"].get_string()); EXPECT_EQ("display_name", var["display_name"].get_string()); EXPECT_EQ("description", var["description"].get_string()); EXPECT_EQ("author", var["author"].get_string()); EXPECT_EQ("art", var["art"].get_string()); EXPECT_EQ("icon", var["icon"].get_string()); EXPECT_EQ("search_hint", var["search_hint"].get_string()); EXPECT_EQ("hot_key", var["hot_key"].get_string()); EXPECT_EQ("/foo", var["scope_dir"].get_string()); EXPECT_FALSE(var["invisible"].get_bool()); // Make another instance from the VariantMap and check its fields ScopeMetadataImpl c(var, &mw); EXPECT_EQ("scope_id", c.scope_id()); EXPECT_EQ("identity", c.proxy()->identity()); EXPECT_EQ("endpoint", c.proxy()->endpoint()); EXPECT_EQ("display_name", c.display_name()); EXPECT_EQ("description", c.description()); EXPECT_EQ("author", c.author()); EXPECT_EQ("art", c.art()); EXPECT_EQ("icon", c.icon()); EXPECT_EQ("search_hint", c.search_hint()); EXPECT_EQ("hot_key", c.hot_key()); EXPECT_FALSE(c.invisible()); } TEST(ScopeMetadataImpl, serialize_exceptions) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeMetadataImpl/Zmq.ini", (RuntimeImpl*)0x1); ScopeMetadataImpl mi(&mw); try { mi.serialize(); FAIL(); } catch (InvalidArgumentException const&e) { EXPECT_STREQ("unity::InvalidArgumentException: ScopeMetadata: required attribute 'scope_id' is empty", e.what()); } try { mi.set_scope_id("scope_id"); mi.serialize(); FAIL(); } catch (InvalidArgumentException const&e) { EXPECT_STREQ("unity::InvalidArgumentException: ScopeMetadataImpl::serialize(): required attribute 'proxy' is null", e.what()); } try { auto mw_proxy = mw.create_scope_proxy("identity", "endpoint"); mi.set_proxy(ScopeImpl::create(mw_proxy, mw.runtime(), "scope_id")); mi.serialize(); FAIL(); } catch (InvalidArgumentException const&e) { EXPECT_STREQ("unity::InvalidArgumentException: ScopeMetadata: required attribute 'display_name' is empty", e.what()); } try { mi.set_display_name("display_name"); mi.serialize(); FAIL(); } catch (InvalidArgumentException const&e) { EXPECT_STREQ("unity::InvalidArgumentException: ScopeMetadata: required attribute 'description' is empty", e.what()); } try { mi.set_description("description"); mi.serialize(); FAIL(); } catch (InvalidArgumentException const&e) { EXPECT_STREQ("unity::InvalidArgumentException: ScopeMetadata: required attribute 'author' is empty", e.what()); } } TEST(ScopeMetadataImpl, deserialize_exceptions) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/ScopeMetadataImpl/Zmq.ini", (RuntimeImpl*)0x1); VariantMap m; try { ScopeMetadataImpl mi(m, &mw); mi.deserialize(m); FAIL(); } catch (InvalidArgumentException const&e) { EXPECT_STREQ("unity::InvalidArgumentException: ScopeMetadata::deserialize(): required attribute " "'scope_id' is missing", e.what()); } m["scope_id"] = "scope_id"; try { ScopeMetadataImpl mi(m, &mw); mi.deserialize(m); FAIL(); } catch (InvalidArgumentException const&e) { EXPECT_STREQ("unity::InvalidArgumentException: ScopeMetadata::deserialize(): required attribute " "'proxy' is missing", e.what()); } VariantMap proxy; m["proxy"] = proxy; try { ScopeMetadataImpl mi(m, &mw); mi.deserialize(m); FAIL(); } catch (InvalidArgumentException const&e) { EXPECT_STREQ("unity::InvalidArgumentException: ScopeMetadataImpl::deserialize(): missing 'proxy.identity'", e.what()); } proxy["identity"] = "identity"; m["proxy"] = proxy; try { ScopeMetadataImpl mi(m, &mw); mi.deserialize(m); FAIL(); } catch (InvalidArgumentException const&e) { EXPECT_STREQ("unity::InvalidArgumentException: ScopeMetadataImpl::deserialize(): missing 'proxy.endpoint'", e.what()); } proxy["endpoint"] = "endpoint"; m["proxy"] = proxy; try { ScopeMetadataImpl mi(m, &mw); mi.deserialize(m); FAIL(); } catch (InvalidArgumentException const&e) { EXPECT_STREQ("unity::InvalidArgumentException: ScopeMetadata::deserialize(): required attribute " "'display_name' is missing", e.what()); } m["display_name"] = "display_name"; try { ScopeMetadataImpl mi(m, &mw); mi.deserialize(m); FAIL(); } catch (InvalidArgumentException const&e) { EXPECT_STREQ("unity::InvalidArgumentException: ScopeMetadata::deserialize(): required attribute " "'description' is missing", e.what()); } m["description"] = "description"; try { ScopeMetadataImpl mi(m, &mw); mi.deserialize(m); FAIL(); } catch (InvalidArgumentException const&e) { EXPECT_STREQ("unity::InvalidArgumentException: ScopeMetadata::deserialize(): required attribute " "'author' is missing", e.what()); } m["author"] = "author"; // Optional attributes m["art"] = "art"; m["icon"] = "icon"; m["search_hint"] = "search_hint"; m["hot_key"] = "hot_key"; ScopeMetadataImpl mi(m, &mw); mi.deserialize(m); EXPECT_EQ("scope_id", mi.scope_id()); EXPECT_EQ("identity", mi.proxy()->identity()); EXPECT_EQ("endpoint", mi.proxy()->endpoint()); EXPECT_EQ("display_name", mi.display_name()); EXPECT_EQ("description", mi.description()); EXPECT_EQ("author", mi.author()); EXPECT_EQ("art", mi.art()); EXPECT_EQ("icon", mi.icon()); EXPECT_EQ("search_hint", mi.search_hint()); EXPECT_EQ("hot_key", mi.hot_key()); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RegistryConfig/0000755000015301777760000000000012320776463027513 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RegistryConfig/RegistryConfig_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RegistryConfig/RegistryConfig_test.0000644000015301777760000000364112320776161033510 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include using namespace std; using namespace unity; using namespace unity::scopes; using namespace unity::scopes::internal; TEST(RegistryConfig, basic) { RegistryConfig c("Registry", "Registry.ini"); EXPECT_EQ("Registry", c.identity()); EXPECT_EQ("Zmq", c.mw_kind()); EXPECT_EQ("ipc:///tmp/socket_for_registry", c.endpoint()); EXPECT_EQ("Zmq.ini", c.mw_configfile()); } TEST(RegistryConfig, RegistryIDEmpty) { try { RegistryConfig c("", "Registry.ini"); FAIL(); } catch (InvalidArgumentException const& e) { EXPECT_STREQ("unity::InvalidArgumentException: Registry identity cannot be an empty string", e.what()); } } TEST(RegistryConfig, ScoperunnerRelativePath) { try { RegistryConfig c("Registry", "ScoperunnerRelativePath.ini"); FAIL(); } catch (ConfigException const& e) { EXPECT_STREQ("unity::scopes::ConfigException: ScoperunnerRelativePath.ini: Scoperunner.Path " "must be an absolute path", e.what()); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RegistryConfig/Registry.ini.in0000644000015301777760000000031712320776161032425 0ustar pbusernogroup00000000000000[Registry] Middleware = Zmq Zmq.Endpoint = ipc:///tmp/socket_for_registry Zmq.EndpointDir = /tmp/socket_for_registry Zmq.ConfigFile = Zmq.ini Scope.InstallDir = /SomeDir Scoperunner.Path = /SomeAbsolutePath unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RegistryConfig/CMakeLists.txt0000644000015301777760000000043212320776161032245 0ustar pbusernogroup00000000000000configure_file(Registry.ini.in Registry.ini) configure_file(ScoperunnerRelativePath.ini.in ScoperunnerRelativePath.ini) add_executable(RegistryConfig_test RegistryConfig_test.cpp) target_link_libraries(RegistryConfig_test ${TESTLIBS}) add_test(RegistryConfig RegistryConfig_test) ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RegistryConfig/ScoperunnerRelativePath.ini.inunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RegistryConfig/ScoperunnerRelativeP0000644000015301777760000000031612320776161033550 0ustar pbusernogroup00000000000000[Registry] Middleware = Zmq Zmq.Endpoint = ipc:///tmp/socket_for_registry Zmq.EndpointDir = /tmp/socket_for_registry Zmq.ConfigFile = Zmq.ini Scope.InstallDir = /SomeDir Scoperunner.Path = SomeRelativePath unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ResultReplyObject/0000755000015301777760000000000012320776463030176 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ResultReplyObject/Zmq.ini.in0000644000015301777760000000007312320776161032046 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ResultReplyObject/Registry.ini.in0000644000015301777760000000026012320776161033105 0ustar pbusernogroup00000000000000[Registry] Middleware = Zmq Zmq.Endpoint = ipc:///tmp/socket_for_registry Zmq.EndpointDir = /tmp Zmq.ConfigFile = Zmq.ini Scope.InstallDir = /unused Scoperunner.Path = /unused unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ResultReplyObject/CMakeLists.txt0000644000015301777760000000060012320776161032725 0ustar pbusernogroup00000000000000configure_file(Registry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Registry.ini) configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini) configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini) add_executable(ResultReplyObject_test ResultReplyObject_test.cpp) target_link_libraries(ResultReplyObject_test ${TESTLIBS}) add_test(ResultReplyObject ResultReplyObject_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ResultReplyObject/Runtime.ini.in0000644000015301777760000000017412320776161032724 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = Registry Registry.ConfigFile = Registry.ini Default.Middleware = Zmq Zmq.ConfigFile = Zmq.ini ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ResultReplyObject/ResultReplyObject_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ResultReplyObject/ResultReplyObject0000644000015301777760000001024012320776161033532 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; class DummyReceiver : public SearchListenerBase { public: DummyReceiver(std::function departments_push_func) { departments_push_func_ = departments_push_func; }; void push(CategorisedResult) override {} void push(DepartmentList const& departments, std::string const& current_department_id) { departments_push_func_(departments, current_department_id); } void finished(Reason /* r */, std::string const& /* error_message */) override {} std::function departments_push_func_; }; TEST(ResultReplyObject, departments_push) { // valid department data { DepartmentList received_deps; std::string received_current_dep_id; auto df = []() -> void {}; auto runtime = internal::RuntimeImpl::create("", "Runtime.ini"); auto receiver = std::make_shared([&received_deps, &received_current_dep_id](DepartmentList const& departments, std::string const& current_dep) { received_deps = departments; received_current_dep_id = current_dep; }); internal::ResultReplyObject reply(receiver, runtime.get(), "ipc:///tmp/scope-foo#scope-foo!c=Scope", 0); reply.set_disconnect_function(df); CannedQuery const query1("scope-foo", "", "dep1"); CannedQuery const query2("scope-foo", "", "dep2"); DepartmentList input_deps { Department(query1, "Dep1"), Department(query2, "Dep2") }; std::string const input_current_dep("dep1"); reply.process_data(internal::DepartmentImpl::serialize_departments(input_deps, input_current_dep)); EXPECT_EQ(2, received_deps.size()); EXPECT_EQ("dep1", received_deps.front().id()); EXPECT_EQ("dep2", received_deps.back().id()); EXPECT_EQ("dep1", received_current_dep_id); } // invalid department data { DepartmentList received_deps; std::string received_current_dep_id; auto df = []() -> void {}; auto runtime = internal::RuntimeImpl::create("", "Runtime.ini"); auto receiver = std::make_shared([&received_deps, &received_current_dep_id](DepartmentList const& departments, std::string const& current_dep) { received_deps = departments; received_current_dep_id = current_dep; }); internal::ResultReplyObject reply(receiver, runtime.get(), "ipc:///tmp/scope-foo#scope-foo!c=Scope", 0); reply.set_disconnect_function(df); CannedQuery const query1("scope-foo", "", "dep1"); DepartmentList input_deps { Department(query1, "Dep1") }; std::string const input_current_dep("dep1"); // missing 'current_dep' { auto var = internal::DepartmentImpl::serialize_departments(input_deps, input_current_dep); var.erase("current_department"); EXPECT_THROW(reply.process_data(var), unity::InvalidArgumentException); } } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeImpl/0000755000015301777760000000000012320776463027022 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeImpl/Zmq.ini.in0000644000015301777760000000007312320776161030672 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeImpl/Registry.ini.in0000644000015301777760000000030612320776161031732 0ustar pbusernogroup00000000000000[Registry] Middleware = Zmq Zmq.Endpoint = ipc:///tmp/socket_for_registry Zmq.EndpointDir = /tmp Zmq.ConfigFile = Zmq.ini Scoperunner.Path = /SomePath Scope.ConfigDir = /tmp Scope.InstallDir = /tmp unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeImpl/RuntimeImpl_test.cpp0000644000015301777760000000471212320776161033031 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include using namespace std; using namespace unity; using namespace unity::scopes; using namespace unity::scopes::internal; TEST(RuntimeImpl, basic) { RuntimeImpl::UPtr rt = RuntimeImpl::create("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/RuntimeImpl/Runtime.ini"); EXPECT_TRUE(rt->registry().get() != nullptr); EXPECT_TRUE(rt->factory()); cerr << "reg: " << rt->registry_configfile() << endl; EXPECT_EQ(TEST_BUILD_ROOT "/gtest/scopes/internal/RuntimeImpl/Registry.ini", rt->registry_configfile()); rt->destroy(); try { rt->registry(); FAIL(); } catch (LogicException const& e) { EXPECT_STREQ("unity::LogicException: registry(): Cannot obtain registry for already destroyed run time", e.what()); } rt->destroy(); try { rt->factory(); FAIL(); } catch (LogicException const& e) { EXPECT_STREQ("unity::LogicException: factory(): Cannot obtain factory for already destroyed run time", e.what()); } } TEST(RuntimeImpl, error) { try { RuntimeImpl::UPtr rt = RuntimeImpl::create("testscope", "NoSuchFile.ini"); } catch (ConfigException const& e) { EXPECT_STREQ("unity::scopes::ConfigException: Cannot instantiate run time for testscope, " "config file: NoSuchFile.ini:\n" " unity::FileException: Could not load ini file NoSuchFile.ini: No such file or directory (errno = 4)", e.what()); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeImpl/CMakeLists.txt0000644000015301777760000000041612320776161031556 0ustar pbusernogroup00000000000000configure_file(Zmq.ini.in Zmq.ini) configure_file(Registry.ini.in Registry.ini) configure_file(Runtime.ini.in Runtime.ini) add_executable(RuntimeImpl_test RuntimeImpl_test.cpp) target_link_libraries(RuntimeImpl_test ${TESTLIBS}) add_test(RuntimeImpl RuntimeImpl_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/RuntimeImpl/Runtime.ini.in0000644000015301777760000000022712320776161031547 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = Registry Registry.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Registry.ini Default.Middleware = Zmq Zmq.ConfigFile = Zmq.ini unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/CMakeLists.txt0000644000015301777760000000111412320776161027305 0ustar pbusernogroup00000000000000add_subdirectory(CategoryRegistry) add_subdirectory(ConfigBase) add_subdirectory(DynamicLoader) add_subdirectory(JsonNode) add_subdirectory(lttng) add_subdirectory(MiddlewareFactory) add_subdirectory(Reaper) add_subdirectory(RegistryConfig) add_subdirectory(RuntimeConfig) add_subdirectory(RuntimeImpl) add_subdirectory(ResultReplyObject) add_subdirectory(ScopeConfig) add_subdirectory(ScopeLoader) add_subdirectory(ScopeMetadataImpl) add_subdirectory(smartscopes) add_subdirectory(ThreadPool) add_subdirectory(ThreadSafeQueue) add_subdirectory(UniqueID) add_subdirectory(zmq_middleware) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/0000755000015301777760000000000012320776463027561 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/VariantConverter/0000755000015301777760000000000012320776463033055 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/VariantConverter/VariantConverter_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/VariantConverter/Var0000644000015301777760000000513712320776161033531 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include using namespace std; using namespace unity; using namespace unity::scopes; using namespace unity::scopes::internal::zmq_middleware; // This test checks conversions between Variant/VariantMap and Value/ValueDict (capnproto) // performed by VariantConverter utility functions (to_value, to_variant). TEST(VariantConverter, basic) { // convert a Variant into capnproto Value ::capnp::MallocMessageBuilder message; auto builder = message.initRoot(); { VariantMap m; VariantMap inner; inner["iron"] = Variant("maiden"); VariantArray arry { Variant(1), Variant(true) }; m["hints"] = inner; m["foo"] = Variant(1); m["bar"] = Variant(true); m["nil"] = Variant::null(); m["baz"] = arry; Variant v(m); to_value(v, builder); } // convert capnproto Value back to Variant auto reader = message.getRoot(); EXPECT_EQ(capnproto::Value::Which::DICT_VAL, reader.which()); auto resultVar = to_variant(reader); EXPECT_EQ(Variant::Dict, resultVar.which()); auto outerDict = resultVar.get_dict(); EXPECT_EQ(1, outerDict["foo"].get_int()); EXPECT_EQ(true, outerDict["bar"].get_bool()); EXPECT_TRUE(outerDict["nil"].is_null()); EXPECT_EQ(Variant::Array, outerDict["baz"].which()); auto varArray = outerDict["baz"].get_array(); EXPECT_EQ(2u, varArray.size()); EXPECT_EQ(1, varArray[0].get_int()); EXPECT_EQ(true, varArray[1].get_bool()); auto innerDict = outerDict["hints"].get_dict(); EXPECT_EQ("maiden", innerDict["iron"].get_string()); } ././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/VariantConverter/CMakeLists.txtunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/VariantConverter/CMa0000644000015301777760000000025312320776161033433 0ustar pbusernogroup00000000000000add_executable(VariantConverter_test VariantConverter_test.cpp) target_link_libraries(VariantConverter_test ${TESTLIBS}) add_test(VariantConverter VariantConverter_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/Util/0000755000015301777760000000000012320776463030476 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/Util/Util_test.cpp0000644000015301777760000000356112320776161033156 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include // Use Boost implementation until http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631 is fixed. #include #include #include using namespace std; using namespace unity; using namespace unity::scopes; using namespace unity::scopes::internal::zmq_middleware; TEST(Util, basic) { struct sockaddr_un addr; auto const maxlen = sizeof(addr.sun_path) - 1; const string schema = "ipc://"; const string short_endpoint = schema + "/tmp/blah"; const string max_endpoint = schema + string(maxlen, 'x'); const string max_endpoint_plus_one = schema + string(maxlen + 1, 'x'); throw_if_bad_endpoint(short_endpoint); // Must not throw throw_if_bad_endpoint(max_endpoint); // Must throw try { throw_if_bad_endpoint(max_endpoint_plus_one); // Must throw FAIL(); } catch (MiddlewareException const& e) { boost::regex r("unity::scopes::MiddlewareException: Socket path name too long \\(max = [0-9]+\\)\\: x+"); EXPECT_TRUE(boost::regex_match(e.what(), r)); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/Util/CMakeLists.txt0000644000015301777760000000015712320776161033234 0ustar pbusernogroup00000000000000add_executable(Util_test Util_test.cpp) target_link_libraries(Util_test ${TESTLIBS}) add_test(Util Util_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ServantBase/0000755000015301777760000000000012320776463031776 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ServantBase/Zmq.ini.inunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ServantBase/Zmq.ini.0000644000015301777760000000007312320776161033317 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp ././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ServantBase/CMakeLists.txtunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ServantBase/CMakeLis0000644000015301777760000000033212320776161033342 0ustar pbusernogroup00000000000000configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini) add_executable(ServantBase_test ServantBase_test.cpp) target_link_libraries(ServantBase_test ${LIBS} ${TESTLIBS}) add_test(ServantBase ServantBase_test) ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ServantBase/ServantBase_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ServantBase/ServantB0000644000015301777760000001530012320776161033437 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include using namespace std; using namespace unity; using namespace unity::scopes; using namespace unity::scopes::internal; using namespace unity::scopes::internal::zmq_middleware; // Test servant that throws the exception passed to the constructor from the op() method. class MyDelegate : public AbstractObject { }; using namespace std::placeholders; class MyServant : public ServantBase { public: enum ThrowType { NoException, UnityException, StdException, OtherException }; MyServant(ThrowType t) : ServantBase(make_shared(), { { "op", bind(&MyServant::op, this, _1, _2, _3) } }), t_(t) { } virtual void op(Current const&, capnp::AnyPointer::Reader&, capnproto::Response::Builder& r) { EXPECT_NE(nullptr, del().get()); // Just so we get coverage switch (t_) { case NoException: { r.setStatus(capnproto::ResponseStatus::SUCCESS); break; } case UnityException: { throw SyscallException("system call blew up", 99); break; } case StdException: { throw std::bad_alloc(); break; } case OtherException: { throw 42; break; } default: { assert(false); } } } private: ThrowType t_; }; TEST(ServantBase, success) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ServantBase/Zmq.ini", (RuntimeImpl*)0x1); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); Current current; current.op_name = "op"; current.adapter = &a; // Dummy needed for the throw code to get at the adapter name and endpoint. MyServant s(MyServant::NoException); capnp::MallocMessageBuilder b; auto response = b.initRoot(); capnp::AnyPointer::Reader in_params; s.safe_dispatch_(current, in_params, response); EXPECT_EQ(capnproto::ResponseStatus::SUCCESS, response.getStatus()); } TEST(ServantBase, ping) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ServantBase/Zmq.ini", (RuntimeImpl*)0x1); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); Current current; current.op_name = "ping"; current.adapter = &a; // Dummy needed for the throw code to get at the adapter name and endpoint. MyServant s(MyServant::NoException); capnp::MallocMessageBuilder b; auto response = b.initRoot(); capnp::AnyPointer::Reader in_params; s.safe_dispatch_(current, in_params, response); EXPECT_EQ(capnproto::ResponseStatus::SUCCESS, response.getStatus()); } TEST(ServantBase, exceptions) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ServantBase/Zmq.ini", (RuntimeImpl*)0x1); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); Current current; current.op_name = "op"; current.adapter = &a; // Dummy needed for the throw code to get at the adapter name and endpoint. { MyServant s(MyServant::UnityException); capnp::MallocMessageBuilder b; auto response = b.initRoot(); capnp::AnyPointer::Reader in_params; s.safe_dispatch_(current, in_params, response); EXPECT_EQ(capnproto::ResponseStatus::RUNTIME_EXCEPTION, response.getStatus()); auto ex = response.getPayload().getAs(); EXPECT_EQ(capnproto::RuntimeException::UNKNOWN, ex.which()); EXPECT_STREQ("unity::SyscallException: system call blew up (errno = 99)", ex.getUnknown().cStr()); } { MyServant s(MyServant::StdException); capnp::MallocMessageBuilder b; auto response = b.initRoot(); capnp::AnyPointer::Reader in_params; s.safe_dispatch_(current, in_params, response); EXPECT_EQ(capnproto::ResponseStatus::RUNTIME_EXCEPTION, response.getStatus()); auto ex = response.getPayload().getAs(); EXPECT_EQ(capnproto::RuntimeException::UNKNOWN, ex.which()); EXPECT_STREQ("std::bad_alloc", ex.getUnknown().cStr()); } { MyServant s(MyServant::OtherException); capnp::MallocMessageBuilder b; auto response = b.initRoot(); capnp::AnyPointer::Reader in_params; s.safe_dispatch_(current, in_params, response); EXPECT_EQ(capnproto::ResponseStatus::RUNTIME_EXCEPTION, response.getStatus()); auto ex = response.getPayload().getAs(); EXPECT_EQ(capnproto::RuntimeException::UNKNOWN, ex.which()); EXPECT_STREQ("unknown exception", ex.getUnknown().cStr()); } { // Servant doesn't raise an exception, but invocation contains non-existent operation. MyServant s(MyServant::NoException); capnp::MallocMessageBuilder b; auto response = b.initRoot(); capnp::AnyPointer::Reader in_params; current.op_name = "no_such_op"; s.safe_dispatch_(current, in_params, response); EXPECT_EQ(capnproto::ResponseStatus::RUNTIME_EXCEPTION, response.getStatus()); auto ex = response.getPayload().getAs(); EXPECT_EQ(capnproto::RuntimeException::OPERATION_NOT_EXIST, ex.which()); EXPECT_STREQ("no_such_op", ex.getOperationNotExist().getOpName().cStr()); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ObjectAdapter/0000755000015301777760000000000012320776463032270 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini.inunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.in0000644000015301777760000000007312320776161033362 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ObjectAdapter/ObjectAdapter_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Object0000644000015301777760000012027112320776161033417 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include // Use Boost implementation until http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631 is fixed. #include #include #include using namespace std; using namespace unity; using namespace unity::scopes; using namespace unity::scopes::internal; using namespace unity::scopes::internal::zmq_middleware; // We use this to sleep in between adapter creation and shutdown. That's // necessary because zmq closes sockets asynchronously. Without the wait, // because we are binding to the same endpoint each time, we can get // an occastional "address in use" exception because the new socket // tries to bind while the old one is still in the process of destroying itself. void wait(int millisec = 20) { this_thread::sleep_for(chrono::milliseconds(millisec)); } // Basic test. TEST(ObjectAdapter, basic) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); // Instantiate and destroy oneway and twoway adapters with single and multiple threads. { ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); EXPECT_EQ(&mw, a.mw()); EXPECT_EQ("testscope", a.name()); EXPECT_EQ("ipc://testscope", a.endpoint()); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Oneway, 1); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 5); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Oneway, 10); } // Same thing, but with activation. { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); a.activate(); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Oneway, 1); a.activate(); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 5); a.activate(); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Oneway, 10); a.activate(); } // Again, with explicit deactivation and waiting. { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); a.activate(); a.shutdown(); a.wait_for_shutdown(); a.wait_for_shutdown(); // Second call benign, returns immediately } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Oneway, 1); a.activate(); a.shutdown(); a.wait_for_shutdown(); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 5); a.activate(); a.shutdown(); a.wait_for_shutdown(); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Oneway, 10); a.activate(); a.shutdown(); a.wait_for_shutdown(); } } TEST(ObjectAdapter, state_change) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 2); // We fire a bunch of activate requests in a loop, in the hope that we end up // getting coverage for the transition to the Active state. for (auto i = 0; i < 500; ++i) { a.activate(); } a.shutdown(); a.wait_for_shutdown(); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Oneway, 2); // We fire a bunch of activate requests in a loop, in the hope that we end up // getting coverage for the transition to the Active state. for (auto i = 0; i < 500; ++i) { a.activate(); } a.shutdown(); a.wait_for_shutdown(); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Oneway, 2); // Try to reactivate after shutdown a.activate(); a.shutdown(); a.wait_for_shutdown(); try { a.activate(); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: Object adapter in Destroyed " "state (adapter: testscope)", e.what()); } } { // Two adapters on the same endpoint. Second one must enter failed state. wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Oneway, 2); a.activate(); ObjectAdapter b(mw, "testscope", "ipc://testscope", RequestMode::Oneway, 2); try { b.activate(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: ObjectAdapter::run_workers(): broker thread " "failure (adapter: testscope):\n" " unity::scopes::MiddlewareException: ObjectAdapter: broker thread failure " "(adapter: testscope):\n" " Address already in use", e.what()); } try { b.shutdown(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: Object adapter in Failed state (adapter: testscope)\n" " Exception history:\n" " Exception #1:\n" " unity::scopes::MiddlewareException: ObjectAdapter: broker thread failure " "(adapter: testscope):\n" " Address already in use", e.what()); } try { b.wait_for_shutdown(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: Object adapter in Failed state (adapter: testscope)\n" " Exception history:\n" " Exception #1:\n" " unity::scopes::MiddlewareException: ObjectAdapter: broker thread failure " "(adapter: testscope):\n" " Address already in use", e.what()); } } } TEST(ObjectAdapter, wait_for_shutdown) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); // Start the adapter and call shutdown() from a different thread after a delay, and wait for the // shutdown to complete. We check that the shutdown happens after at least the delay that was specified, // so we can be sure that wait_for_shutdown() actually waits. wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 5); a.activate(); int delay_millisecs = 100; packaged_task task([&] { wait(delay_millisecs); a.shutdown(); }); auto const start_time = chrono::steady_clock::now(); thread(move(task)).detach(); a.wait_for_shutdown(); auto const now = chrono::steady_clock::now(); auto const delay = chrono::duration_cast(now - start_time); EXPECT_TRUE(delay_millisecs <= delay.count()); } class MyDelegate : public AbstractObject { }; using namespace std::placeholders; // Mock servant that does nothing but return success. class MyServant : public ServantBase { public: MyServant() : ServantBase(make_shared(), { { "success_op", bind(&MyServant::success_op, this, _1, _2, _3) } }) { } virtual void success_op(Current const&, capnp::AnyPointer::Reader&, capnproto::Response::Builder& r) { r.setStatus(capnproto::ResponseStatus::SUCCESS); } }; TEST(ObjectAdapter, add_remove_find) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 5); try { a.add("", nullptr); FAIL(); } catch (InvalidArgumentException const& e) { EXPECT_STREQ("unity::InvalidArgumentException: ObjectAdapter::add(): invalid empty id (adapter: testscope)", e.what()); } try { a.add("fred", nullptr); FAIL(); } catch (InvalidArgumentException const& e) { EXPECT_STREQ("unity::InvalidArgumentException: ObjectAdapter::add(): invalid nullptr object (adapter: testscope)", e.what()); } shared_ptr o(new MyServant); a.add("fred", o); auto f = a.find("fred"); EXPECT_EQ(o, f); try { a.add("fred", o); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: ObjectAdapter::add(): cannot add id \"fred\":" " id already in use (adapter: testscope)", e.what()); } a.remove("fred"); try { a.remove("fred"); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: ObjectAdapter::remove(): cannot remove id \"fred\":" " id not present (adapter: testscope)", e.what()); } EXPECT_EQ(nullptr, a.find("fred").get()); } TEST(ObjectAdapter, dispatch_oneway_to_twoway) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); a.activate(); zmqpp::socket s(*mw.context(), zmqpp::socket_type::request); s.connect("ipc://testscope"); ZmqSender sender(s); ZmqReceiver receiver(s); capnp::MallocMessageBuilder b; auto request = b.initRoot(); request.setMode(capnproto::RequestMode::ONEWAY); // No good for twoway adapter. request.setId("id"); request.setCat("cat"); request.setOpName("operation_name"); auto segments = b.getSegmentsForOutput(); sender.send(segments); segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); EXPECT_EQ(response.getStatus(), capnproto::ResponseStatus::RUNTIME_EXCEPTION); auto ex = response.getPayload().getAs(); EXPECT_EQ(capnproto::RuntimeException::UNKNOWN, ex.which()); EXPECT_STREQ("ObjectAdapter: oneway invocation sent to twoway adapter" " (id: id, adapter: testscope, op: operation_name)", ex.getUnknown().cStr()); } TEST(ObjectAdapter, dispatch_twoway_to_oneway) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Oneway, 1); a.activate(); zmqpp::socket s(*mw.context(), zmqpp::socket_type::push); s.connect("ipc://testscope"); ZmqSender sender(s); capnp::MallocMessageBuilder b; auto request = b.initRoot(); request.setMode(capnproto::RequestMode::TWOWAY); // No good for oneway adapter. request.setId("id"); request.setId("cat"); request.setOpName("operation_name"); auto segments = b.getSegmentsForOutput(); sender.send(segments); // We need to wait a little while, otherwise the adapter will have shut down before // it receives the oneway message. No real test here--this is for coverage. wait(100); } TEST(ObjectAdapter, dispatch_not_exist) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); a.activate(); // No servant registered, check that we get an ObjectNotExistException zmqpp::socket s(*mw.context(), zmqpp::socket_type::request); s.connect("ipc://testscope"); ZmqSender sender(s); ZmqReceiver receiver(s); capnp::MallocMessageBuilder b; auto request = b.initRoot(); request.setMode(capnproto::RequestMode::TWOWAY); request.setId("id"); request.setCat("cat"); request.setOpName("operation_name"); auto segments = b.getSegmentsForOutput(); sender.send(segments); segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); EXPECT_EQ(response.getStatus(), capnproto::ResponseStatus::RUNTIME_EXCEPTION); auto ex = response.getPayload().getAs(); EXPECT_EQ(capnproto::RuntimeException::OBJECT_NOT_EXIST, ex.which()); auto one = ex.getObjectNotExist(); EXPECT_TRUE(one.hasProxy()); auto proxy = one.getProxy(); EXPECT_EQ(a.endpoint(), proxy.getEndpoint().cStr()); EXPECT_STREQ("id", proxy.getIdentity().cStr()); EXPECT_TRUE(one.hasAdapter()); EXPECT_STREQ("testscope", one.getAdapter().cStr()); } TEST(ObjectAdapter, bad_header) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); a.activate(); zmqpp::socket s(*mw.context(), zmqpp::socket_type::request); s.connect("ipc://testscope"); ZmqSender sender(s); ZmqReceiver receiver(s); capnp::MallocMessageBuilder b; auto request = b.initRoot(); request.setMode(capnproto::RequestMode::TWOWAY); request.setId("id"); request.setCat("cat"); // Bad header: missing operation name auto segments = b.getSegmentsForOutput(); sender.send(segments); segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); EXPECT_EQ(response.getStatus(), capnproto::ResponseStatus::RUNTIME_EXCEPTION); auto ex = response.getPayload().getAs(); EXPECT_EQ(capnproto::RuntimeException::UNKNOWN, ex.which()); EXPECT_STREQ("Invalid message header", ex.getUnknown().cStr()); } // Invalid message header a second time, with oneway adapter (for coverage) { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Oneway, 1); a.activate(); zmqpp::socket s(*mw.context(), zmqpp::socket_type::push); s.connect("ipc://testscope"); ZmqSender sender(s); capnp::MallocMessageBuilder b; auto request = b.initRoot(); request.setMode(capnproto::RequestMode::ONEWAY); request.setId("id"); request.setCat("cat"); // Bad header: missing operation name auto segments = b.getSegmentsForOutput(); sender.send(segments); wait(); // Give message time to get out before destroying the adapter // No test here, for coverage only. } } TEST(ObjectAdapter, corrupt_header) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); a.activate(); zmqpp::socket s(*mw.context(), zmqpp::socket_type::request); s.connect("ipc://testscope"); ZmqSender sender(s); ZmqReceiver receiver(s); // Make a malformed message header so we get coverage on the exception case. capnp::word buf[1]; *reinterpret_cast(buf) = 0x99; kj::ArrayPtr badword(&buf[0], 1); kj::ArrayPtr const> segments(&badword, 1); sender.send(segments); segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); EXPECT_EQ(response.getStatus(), capnproto::ResponseStatus::RUNTIME_EXCEPTION); auto ex = response.getPayload().getAs(); EXPECT_EQ(capnproto::RuntimeException::UNKNOWN, ex.which()); string msg = ex.getUnknown().cStr(); boost::regex r("ObjectAdapter: error unmarshaling request header.*"); EXPECT_TRUE(boost::regex_match(msg, r)); } // Malformed message header a second time, with oneway adapter (for coverage) { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Oneway, 1); a.activate(); zmqpp::socket s(*mw.context(), zmqpp::socket_type::push); s.connect("ipc://testscope"); ZmqSender sender(s); ZmqReceiver receiver(s); // Make a malformed message header so we get coverage on the exception case. capnp::word buf[1]; *reinterpret_cast(buf) = 0x99; kj::ArrayPtr badword(&buf[0], 1); kj::ArrayPtr const> segments(&badword, 1); sender.send(segments); wait(); // Give message time to get out before destroying the adapter // No test here, for coverage only. } } TEST(ObjectAdapter, invoke_ok) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); a.activate(); zmqpp::socket s(*mw.context(), zmqpp::socket_type::request); s.connect("ipc://testscope"); ZmqSender sender(s); ZmqReceiver receiver(s); shared_ptr o(new MyServant); a.add("some_id", o); capnp::MallocMessageBuilder b; auto request = b.initRoot(); request.setMode(capnproto::RequestMode::TWOWAY); request.setId("some_id"); request.setCat("some_cat"); request.setOpName("success_op"); auto segments = b.getSegmentsForOutput(); sender.send(segments); segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); EXPECT_EQ(response.getStatus(), capnproto::ResponseStatus::SUCCESS); } // Servant that returns object not exist class ThrowONEServant : public ServantBase { public: ThrowONEServant() : ServantBase(make_shared(), { { "ONE_op", bind(&ThrowONEServant::ONE_op, this, _1, _2, _3) } }) { } virtual void ONE_op(Current const& current, capnp::AnyPointer::Reader&, capnproto::Response::Builder& r) { r.setStatus(capnproto::ResponseStatus::RUNTIME_EXCEPTION); marshal_object_not_exist_exception(r, current); } }; TEST(ObjectAdapter, invoke_object_not_exist) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); a.activate(); zmqpp::socket s(*mw.context(), zmqpp::socket_type::request); s.connect("ipc://testscope"); ZmqSender sender(s); ZmqReceiver receiver(s); shared_ptr o(new ThrowONEServant); a.add("some_id", o); capnp::MallocMessageBuilder b; auto request = b.initRoot(); request.setMode(capnproto::RequestMode::TWOWAY); request.setId("some_id"); request.setCat("some_cat"); request.setOpName("ONE_op"); auto segments = b.getSegmentsForOutput(); sender.send(segments); segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); EXPECT_EQ(response.getStatus(), capnproto::ResponseStatus::RUNTIME_EXCEPTION); auto ex = response.getPayload().getAs(); EXPECT_EQ(capnproto::RuntimeException::OBJECT_NOT_EXIST, ex.which()); auto one = ex.getObjectNotExist(); EXPECT_TRUE(one.hasProxy()); auto proxy = one.getProxy(); EXPECT_EQ(a.endpoint(), proxy.getEndpoint().cStr()); EXPECT_STREQ("some_id", proxy.getIdentity().cStr()); EXPECT_STREQ("some_cat", proxy.getCategory().cStr()); EXPECT_TRUE(one.hasAdapter()); EXPECT_STREQ("testscope", one.getAdapter().cStr()); } TEST(ObjectAdapter, invoke_operation_not_exist) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); a.activate(); zmqpp::socket s(*mw.context(), zmqpp::socket_type::request); s.connect("ipc://testscope"); ZmqSender sender(s); ZmqReceiver receiver(s); shared_ptr o(new MyServant); a.add("some_id", o); capnp::MallocMessageBuilder b; auto request = b.initRoot(); request.setMode(capnproto::RequestMode::TWOWAY); request.setId("some_id"); request.setCat("some_cat"); request.setOpName("operation_name"); auto segments = b.getSegmentsForOutput(); sender.send(segments); segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); EXPECT_EQ(response.getStatus(), capnproto::ResponseStatus::RUNTIME_EXCEPTION); auto ex = response.getPayload().getAs(); EXPECT_EQ(capnproto::RuntimeException::OPERATION_NOT_EXIST, ex.which()); auto opne = ex.getOperationNotExist(); EXPECT_TRUE(opne.hasProxy()); auto proxy = opne.getProxy(); EXPECT_EQ(a.endpoint(), proxy.getEndpoint().cStr()); EXPECT_STREQ("some_id", proxy.getIdentity().cStr()); EXPECT_STREQ("some_cat", proxy.getCategory().cStr()); EXPECT_TRUE(opne.hasAdapter()); EXPECT_STREQ("testscope", opne.getAdapter().cStr()); EXPECT_TRUE(opne.hasAdapter()); EXPECT_STREQ("operation_name", opne.getOpName().cStr()); } // Make sure that we do actually run threaded if the adapter has more than one thread. class CountingServant : public ServantBase { public: CountingServant(int delay_millisecs) : ServantBase(make_shared(), { { "count_op", bind(&CountingServant::count_op, this, _1, _2, _3) } }), concurrent_(0), max_concurrent_(0), num_invocations_(0), delay_(delay_millisecs) { } virtual void count_op(Current const&, capnp::AnyPointer::Reader&, capnproto::Response::Builder& r) { ++num_invocations_; atomic_int num(++concurrent_); max_concurrent_.store(max(num, max_concurrent_)); wait(delay_); --concurrent_; r.setStatus(capnproto::ResponseStatus::SUCCESS); } int max_concurrent() const noexcept { return max_concurrent_; } int num_invocations() const noexcept { return num_invocations_; } private: atomic_int concurrent_; atomic_int max_concurrent_; atomic_int num_invocations_; int delay_; }; void invoke_thread(ZmqMiddleware* mw, RequestMode t) { zmqpp::socket s(*mw->context(), t == RequestMode::Twoway ? zmqpp::socket_type::request : zmqpp::socket_type::push); s.connect("ipc://testscope"); ZmqSender sender(s); ZmqReceiver receiver(s); capnp::MallocMessageBuilder b; auto request = b.initRoot(); request.setMode(t == RequestMode::Twoway ? capnproto::RequestMode::TWOWAY : capnproto::RequestMode::ONEWAY); request.setId("some_id"); request.setCat("some_cat"); request.setOpName("count_op"); auto segments = b.getSegmentsForOutput(); sender.send(segments); if (t == RequestMode::Twoway) { auto reply_segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(reply_segments); auto response = reader.getRoot(); EXPECT_EQ(response.getStatus(), capnproto::ResponseStatus::SUCCESS); } else { wait(50); // Allow some time for oneway requests to actually make it on the wire. } } TEST(ObjectAdapter, twoway_threading) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); // Single servant to which we send requests concurrently. shared_ptr o(new CountingServant(100)); const int num_threads = 5; const int num_requests = 20; { ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, num_threads); a.activate(); a.add("some_id", o); // Send num_requests, each from its own thread. vector invokers; for (auto i = 0; i < num_requests; ++i) { invokers.push_back(thread(invoke_thread, &mw, RequestMode::Twoway)); } for (auto& i : invokers) { i.join(); } } // We must have had num_requests in total, at most num_threads of which were processed concurrently. The delay // in the servant ensures that we actually reach the maximum of num_threads concurrent invocations. EXPECT_EQ(num_requests, o->num_invocations()); EXPECT_EQ(num_threads, o->max_concurrent()); } TEST(ObjectAdapter, oneway_threading) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); // Single servant to which we send requests concurrently. shared_ptr o(new CountingServant(100)); const int num_threads = 5; const int num_requests = 20; { ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Oneway, num_threads); a.activate(); a.add("some_id", o); // Send num_requests, each from its own thread. vector invokers; for (auto i = 0; i < num_requests; ++i) { invokers.push_back(thread(invoke_thread, &mw, RequestMode::Oneway)); } for (auto& i : invokers) { i.join(); } // We need to delay here, otherwise we end up destroying the adapter before // the oneway invocations are processed. We process num_threads requests // in parallel, so the total time will be roughly the number of requests // divided by the number of threads (which is the number of "batches"), // plus a bit of slack. wait(((num_requests / num_threads) + 1) * 100 + 100); } // We must have had num_requests in total, at most num_threads of which were processed concurrently. The delay // in the servant ensures that we actually reach the maximum of num_threads concurrent invocations. EXPECT_EQ(num_requests, o->num_invocations()); EXPECT_EQ(num_threads, o->max_concurrent()); } using namespace std::placeholders; // Servant that updates the servant map in various ways from its destructor, to verify // that no deadlock can arise if a servant does this. class UpdaterServant : public ServantBase { public: UpdaterServant(function func) : ServantBase(make_shared(), { { "op", bind(&UpdaterServant::op, this, _1, _2, _3) } }), func(func) { } ~UpdaterServant() { func(); } virtual void op(Current const&, capnp::AnyPointer::Reader&, capnproto::Response::Builder& r) { r.setStatus(capnproto::ResponseStatus::SUCCESS); } function func; }; TEST(ObjectAdapter, servant_map_destructor) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 5); // Servant calls remove on itself from its destructor after adapter is destroyed auto test_func = [&]() { try { a.remove("fred"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: Object adapter in Destroyed state (adapter: testscope)", e.what()); } }; a.add("fred", make_shared(test_func)); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 5); // Servant calls remove on itself from its destructor while adapter is inactive auto test_func = [&]() { try { a.remove("fred"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: ObjectAdapter::remove(): " "cannot remove id \"fred\": id not present (adapter: testscope)", e.what()); } }; auto servant = make_shared(test_func); a.add("fred", servant); a.remove("fred"); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 5); // Servant calls remove on itself from its destructor while adapter is active auto test_func = [&]() { try { a.remove("fred"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: ObjectAdapter::remove(): " "cannot remove id \"fred\": id not present (adapter: testscope)", e.what()); } }; auto servant = make_shared(test_func); a.add("fred", servant); a.activate(); a.remove("fred"); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 5); // Servant removes another servant from its destructor while adapter is active auto test_func = [&]() { EXPECT_NO_THROW(a.remove("joe")); }; a.add("fred", make_shared(test_func)); a.add("joe", make_shared()); a.activate(); a.remove("fred"); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 5); // Destroy active adapter with a bunch of servants in it a.add("fred", make_shared()); a.add("joe", make_shared()); a.add("mary", make_shared()); a.activate(); } { wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 5); // Try adding and finding servant after adapter is destroyed a.add("fred", make_shared()); a.activate(); a.shutdown(); a.wait_for_shutdown(); try { a.add("joe", make_shared()); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: Object adapter in Destroyed " "state (adapter: testscope)", e.what()); } try { a.find("joe"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: Object adapter in Destroyed " "state (adapter: testscope)", e.what()); } } } namespace { bool test_finished; std::mutex server_mutex; std::condition_variable server_done; } void mock_server(string const& endpoint, zmqpp::socket_type stype) { // Simulate a server bound to the endpoint already zmqpp::context c; zmqpp::socket s(c, stype); s.set(zmqpp::socket_option::linger, 0); s.set(zmqpp::socket_option::receive_timeout, 500); s.bind(endpoint); // Wait for test to tell us to go away unique_lock lock(server_mutex); server_done.wait(lock, []{ return test_finished; }); } TEST(ObjectAdapter, double_bind) { const string endpoint = "ipc://testscope"; { // Simulate a server bound to the endpoint already { lock_guard lock(server_mutex); test_finished = false; } std::thread t(&mock_server, endpoint, zmqpp::socket_type::router); wait(200); // Give zmq some time to finish the bind. ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); wait(); try { ObjectAdapter a(mw, "testscope", endpoint, RequestMode::Twoway, 5); a.activate(); a.shutdown(); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: ObjectAdapter::run_workers(): broker thread failure " "(adapter: testscope):\n" " unity::scopes::MiddlewareException: ObjectAdapter: broker thread failure " "(adapter: testscope): address in use: ipc://testscope", e.what()); } { lock_guard lock(server_mutex); test_finished = true; server_done.notify_one(); } t.join(); } // Same test again, but for pull socket { // Simulate a server bound to the endpoint already { lock_guard lock(server_mutex); test_finished = false; } std::thread t(&mock_server, endpoint, zmqpp::socket_type::pull); wait(200); // Give zmq some time to finish the bind. ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); wait(); try { ObjectAdapter a(mw, "testscope", endpoint, RequestMode::Twoway, 5); a.activate(); a.shutdown(); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: ObjectAdapter::run_workers(): broker thread failure " "(adapter: testscope):\n" " unity::scopes::MiddlewareException: ObjectAdapter: broker thread failure " "(adapter: testscope): address in use: ipc://testscope", e.what()); } { lock_guard lock(server_mutex); test_finished = true; server_done.notify_one(); } t.join(); } } TEST(ObjectAdapter, dflt_servant) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); a.activate(); zmqpp::socket s(*mw.context(), zmqpp::socket_type::request); s.connect("ipc://testscope"); ZmqSender sender(s); ZmqReceiver receiver(s); shared_ptr o(new MyServant); a.add_dflt_servant("some_cat", o); try { a.add_dflt_servant("some_cat", o); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: ObjectAdapter::add_dflt_servant(): " "cannot add category \"some_cat\": category already in use (adapter: testscope)", e.what()); } capnp::MallocMessageBuilder b; auto request = b.initRoot(); request.setMode(capnproto::RequestMode::TWOWAY); request.setId("some_id"); request.setCat("some_cat"); request.setOpName("success_op"); auto segments = b.getSegmentsForOutput(); sender.send(segments); segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); EXPECT_EQ(response.getStatus(), capnproto::ResponseStatus::SUCCESS); a.remove_dflt_servant("some_cat"); try { a.remove_dflt_servant("some_cat"); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: ObjectAdapter::remove_dflt_servant(): " "cannot remove category \"some_cat\": category not present (adapter: testscope)", e.what()); } } TEST(ObjectAdapter, dflt_servant_exceptions) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini", (RuntimeImpl*)0x1); wait(); ObjectAdapter a(mw, "testscope", "ipc://testscope", RequestMode::Twoway, 1); a.activate(); try { a.add_dflt_servant("", nullptr); FAIL(); } catch (InvalidArgumentException const& e) { EXPECT_STREQ("unity::InvalidArgumentException: ObjectAdapter::add_dflt_servant(): " "invalid nullptr object (adapter: testscope)", e.what()); } ObjectAdapter b(mw, "testscope2", "ipc://testscope", RequestMode::Oneway, 2); EXPECT_THROW(b.activate(), MiddlewareException); try { shared_ptr o(new MyServant); b.add_dflt_servant("some_cat", o); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: Object adapter in Failed state (adapter: testscope2)", e.what()); } try { shared_ptr o(new MyServant); b.remove_dflt_servant("some_cat"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: Object adapter in Failed state (adapter: testscope2)", e.what()); } try { shared_ptr o(new MyServant); b.find_dflt_servant("some_cat"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: Object adapter in Failed state (adapter: testscope2)", e.what()); } } ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ObjectAdapter/CMakeLists.txtunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ObjectAdapter/CMakeL0000644000015301777760000000031012320776161033274 0ustar pbusernogroup00000000000000configure_file(Zmq.ini.in Zmq.ini) add_executable(ObjectAdapter_test ObjectAdapter_test.cpp) target_link_libraries(ObjectAdapter_test ${LIBS} ${TESTLIBS}) add_test(ObjectAdapter ObjectAdapter_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/CMakeLists.txt0000644000015301777760000000026412320776161032316 0ustar pbusernogroup00000000000000add_subdirectory(ObjectAdapter) add_subdirectory(RegistryI) add_subdirectory(ServantBase) add_subdirectory(Util) add_subdirectory(VariantConverter) add_subdirectory(ZmqMiddleware) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/RegistryI/0000755000015301777760000000000012320776463031502 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/RegistryI/TestRegistry.ini.inunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/RegistryI/TestRegist0000644000015301777760000000036512320776161033521 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = TestRegistry [Registry] Middleware = Zmq Zmq.Endpoint = ipc:///tmp/TestRegistry Zmq.EndpointDir = /tmp Zmq.ConfigFile = Zmq.ini Scope.InstallDir = /tmp Scoperunner.Path = @CMAKE_BINARY_DIR@/scoperunner/scoperunner unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/RegistryI/Zmq.ini.in0000644000015301777760000000007312320776161033352 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/RegistryI/RegistryI_0000644000015301777760000004555312320776161033514 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace unity; using namespace unity::scopes; using namespace unity::scopes::internal; using namespace unity::scopes::internal::zmq_middleware; namespace { struct Scope { Scope() : trap(core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_chld})), death_observer(core::posix::ChildProcess::DeathObserver::create_once_with_signal_trap(trap)), worker([this]() { trap->run(); }) { } ~Scope() { trap->stop(); if (worker.joinable()) worker.join(); } std::shared_ptr trap; std::unique_ptr death_observer; std::thread worker; } scope; ScopeMetadata make_meta(const string& scope_id, MWScopeProxy const& proxy, MiddlewareBase::SPtr const& mw) { unique_ptr mi(new ScopeMetadataImpl(mw.get())); mi->set_scope_id(scope_id); mi->set_art("art " + scope_id); mi->set_display_name("display name " + scope_id); mi->set_description("description " + scope_id); mi->set_author("author " + scope_id); mi->set_search_hint("search hint " + scope_id); mi->set_hot_key("hot key " + scope_id); mi->set_scope_directory("/foo"); ScopeProxy p = ScopeImpl::create(proxy, mw->runtime(), scope_id); mi->set_proxy(p); return ScopeMetadataImpl::create(move(mi)); } } TEST(RegistryI, get_metadata) { RegistryObject::ScopeExecData dummy_exec_data; RuntimeImpl::UPtr runtime = RuntimeImpl::create( "TestRegistry", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/RegistryI/Runtime.ini"); string identity = runtime->registry_identity(); RegistryConfig c(identity, runtime->registry_configfile()); string mw_kind = c.mw_kind(); string mw_endpoint = c.endpoint(); string mw_configfile = c.mw_configfile(); MiddlewareBase::SPtr middleware = runtime->factory()->create(identity, mw_kind, mw_configfile); RegistryObject::SPtr ro(make_shared(*scope.death_observer)); auto registry = middleware->add_registry_object(identity, ro); auto p = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1"); EXPECT_TRUE(ro->add_local_scope("scope1", move(make_meta("scope1", p, middleware)), dummy_exec_data)); auto r = runtime->registry(); auto scope = r->get_metadata("scope1"); EXPECT_EQ("scope1", scope.scope_id()); } TEST(RegistryI, list) { RuntimeImpl::UPtr runtime = RuntimeImpl::create( "TestRegistry", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/RegistryI/Runtime.ini"); string identity = runtime->registry_identity(); RegistryConfig c(identity, runtime->registry_configfile()); string mw_kind = c.mw_kind(); string mw_endpoint = c.endpoint(); string mw_configfile = c.mw_configfile(); MiddlewareBase::SPtr middleware = runtime->factory()->create(identity, mw_kind, mw_configfile); RegistryObject::SPtr ro(make_shared(*scope.death_observer)); auto registry = middleware->add_registry_object(identity, ro); auto r = runtime->registry(); auto scopes = r->list(); EXPECT_TRUE(scopes.empty()); RegistryObject::ScopeExecData dummy_exec_data; auto proxy = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1"); EXPECT_TRUE(ro->add_local_scope("scope1", move(make_meta("scope1", proxy, middleware)), dummy_exec_data)); scopes = r->list(); EXPECT_EQ(1u, scopes.size()); EXPECT_NE(scopes.end(), scopes.find("scope1")); ro->remove_local_scope("scope1"); scopes = r->list(); EXPECT_EQ(0u, scopes.size()); set ids; for (int i = 0; i < 10; ++i) { string long_id = "0000000000000000000000000000000000000000000000" + to_string(i); EXPECT_TRUE(ro->add_local_scope(long_id, move(make_meta(long_id, proxy, middleware)), dummy_exec_data)); ids.insert(long_id); } scopes = r->list(); EXPECT_EQ(10u, scopes.size()); for (auto& id : ids) { auto it = scopes.find(id); EXPECT_NE(scopes.end(), it); EXPECT_NE(ids.end(), ids.find(it->first)); } } TEST(RegistryI, add_remove) { RuntimeImpl::UPtr runtime = RuntimeImpl::create( "TestRegistry", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/RegistryI/Runtime.ini"); string identity = runtime->registry_identity(); RegistryConfig c(identity, runtime->registry_configfile()); string mw_kind = c.mw_kind(); string mw_endpoint = c.endpoint(); string mw_configfile = c.mw_configfile(); MiddlewareBase::SPtr middleware = runtime->factory()->create(identity, mw_kind, mw_configfile); RegistryObject::SPtr ro(make_shared(*scope.death_observer)); auto registry = middleware->add_registry_object(identity, ro); auto r = runtime->registry(); auto scopes = r->list(); EXPECT_TRUE(scopes.empty()); RegistryObject::ScopeExecData dummy_exec_data; auto proxy = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1"); EXPECT_TRUE(ro->add_local_scope("scope1", move(make_meta("scope1", proxy, middleware)), dummy_exec_data)); scopes = r->list(); EXPECT_EQ(1u, scopes.size()); EXPECT_NE(scopes.end(), scopes.find("scope1")); EXPECT_FALSE(ro->add_local_scope("scope1", move(make_meta("scope1", proxy, middleware)), dummy_exec_data)); EXPECT_TRUE(ro->remove_local_scope("scope1")); scopes = r->list(); EXPECT_EQ(0u, scopes.size()); EXPECT_FALSE(ro->remove_local_scope("scope1")); set ids; for (int i = 0; i < 10; ++i) { string long_id = "0000000000000000000000000000000000000000000000" + to_string(i); ro->add_local_scope(long_id, move(make_meta(long_id, proxy, middleware)), dummy_exec_data); ids.insert(long_id); } scopes = r->list(); EXPECT_EQ(10u, scopes.size()); for (auto& id : ids) { auto it = scopes.find(id); EXPECT_NE(scopes.end(), it); EXPECT_NE(ids.end(), ids.find(it->first)); } } TEST(RegistryI, exceptions) { RuntimeImpl::UPtr runtime = RuntimeImpl::create( "TestRegistry", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/RegistryI/Runtime.ini"); string identity = runtime->registry_identity(); RegistryConfig c(identity, runtime->registry_configfile()); string mw_kind = c.mw_kind(); string mw_endpoint = c.endpoint(); string mw_configfile = c.mw_configfile(); MiddlewareBase::SPtr middleware = runtime->factory()->create(identity, mw_kind, mw_configfile); RegistryObject::SPtr ro(make_shared(*scope.death_observer)); RegistryObject::ScopeExecData dummy_exec_data; auto registry = middleware->add_registry_object(identity, ro); auto proxy = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1"); ro->add_local_scope("scope1", move(make_meta("scope1", proxy, middleware)), dummy_exec_data); auto r = runtime->registry(); try { r->get_metadata("fred"); FAIL(); } catch (NotFoundException const& e) { EXPECT_STREQ("unity::scopes::NotFoundException: Registry::get_metadata(): no such scope (name = fred)", e.what()); } try { r->get_metadata(""); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: unity::InvalidArgumentException: " "RegistryObject::get_metadata(): Cannot search for scope with empty id", e.what()); } try { auto proxy = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1"); ro->add_local_scope("", move(make_meta("blah", proxy, middleware)), dummy_exec_data); FAIL(); } catch (InvalidArgumentException const& e) { EXPECT_STREQ("unity::InvalidArgumentException: RegistryObject::add_local_scope(): Cannot add scope with empty id", e.what()); } try { ro->remove_local_scope(""); FAIL(); } catch (InvalidArgumentException const& e) { EXPECT_STREQ("unity::InvalidArgumentException: RegistryObject::remove_local_scope(): Cannot remove scope with empty id", e.what()); } } // RegistryObject that overrides the locate() method, so we can test it without having to run // a full registry that spawns new processes. class MockRegistryObject : public RegistryObject { public: MockRegistryObject(core::posix::ChildProcess::DeathObserver& death_observer) : RegistryObject(death_observer) { } virtual ObjectProxy locate(string const& identity) override { if (identity == "no_such_scope") { throw NotFoundException("no can find", identity); } if (identity == "error_scope") { throw RegistryException("Couldn't start error_scope"); } return get_metadata(identity).proxy(); } }; TEST(RegistryI, locate_mock) { RuntimeImpl::UPtr runtime = RuntimeImpl::create( "TestRegistry", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/RegistryI/Runtime.ini"); string identity = runtime->registry_identity(); RegistryConfig c(identity, runtime->registry_configfile()); string mw_kind = c.mw_kind(); string mw_endpoint = c.endpoint(); string mw_configfile = c.mw_configfile(); RegistryObject::ScopeExecData dummy_exec_data; MiddlewareBase::SPtr middleware = runtime->factory()->create(identity, mw_kind, mw_configfile); MockRegistryObject::SPtr mro(make_shared(*scope.death_observer)); auto r = middleware->add_registry_object(identity, mro); auto r_proxy = dynamic_pointer_cast(r); auto proxy = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1"); mro->add_local_scope("scope1", move(make_meta("scope1", proxy, middleware)), dummy_exec_data); auto p = r_proxy->locate("scope1"); EXPECT_EQ("scope1", p->identity()); EXPECT_EQ("ipc:///tmp/scope1", p->endpoint()); try { r_proxy->locate("no_such_scope"); FAIL(); } catch (NotFoundException const& e) { EXPECT_STREQ("unity::scopes::NotFoundException: Registry::locate(): no such object (name = no_such_scope)", e.what()); } try { r_proxy->locate("error_scope"); FAIL(); } catch (RegistryException const& e) { EXPECT_STREQ("unity::scopes::RegistryException: Couldn't start error_scope", e.what()); } try { auto proxy = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1"); mro->add_local_scope("", move(make_meta("blah", proxy, middleware)), dummy_exec_data); FAIL(); } catch (InvalidArgumentException const& e) { EXPECT_STREQ("unity::InvalidArgumentException: RegistryObject::add_local_scope(): Cannot add scope with empty id", e.what()); } try { mro->remove_local_scope(""); FAIL(); } catch (InvalidArgumentException const& e) { EXPECT_STREQ("unity::InvalidArgumentException: RegistryObject::remove_local_scope(): Cannot remove scope with empty id", e.what()); } } std::string exec_cmd(std::string const& cmd) { FILE* pipe = popen(cmd.c_str(), "r"); if (!pipe) { return ""; } char buffer[128]; std::string result; while (!feof(pipe)) { if (fgets(buffer, 128, pipe) != NULL) { result += buffer; } } pclose(pipe); return result; } int first_child_pid() { return stoi(exec_cmd("ps --ppid " + std::to_string(getpid()) + " --no-headers")); } int process_count() { return stoi(exec_cmd("ps --ppid " + std::to_string(getpid()) + " | wc -l")); } TEST(RegistryI, locate) { // get number of processes belonging to this test instance int start_process_count = process_count(); int current_process_count = 0; { // configure registry std::string rt_config = TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/RegistryI/Runtime.ini"; RuntimeImpl::UPtr rt = RuntimeImpl::create("TestRegistry", rt_config); string reg_id = rt->registry_identity(); RegistryConfig c(reg_id, rt->registry_configfile()); string mw_kind = c.mw_kind(); string scoperunner_path = c.scoperunner_path(); MiddlewareBase::SPtr mw = rt->factory()->find(reg_id, mw_kind); RegistryObject::SPtr reg(new RegistryObject(*scope.death_observer)); mw->add_registry_object(reg_id, reg); mw->add_state_receiver_object("StateReceiver", reg->state_receiver()); // configure scopes ///! TODO: HACK: /// we have to start scope-C and scope-D before starting scope-B here, as B aggregates C and D. /// (When re-binding logic is introduced, this will be unnecessary) std::array scope_ids = {"scope-A", "scope-C", "scope-D", "scope-B", "scope-N", "scope-S"}; std::map proxies; for (auto& scope_id : scope_ids) { proxies[scope_id] = ScopeImpl::create(mw->create_scope_proxy(scope_id), mw->runtime(), scope_id); unique_ptr mi(new ScopeMetadataImpl(mw.get())); mi->set_scope_id(scope_id); mi->set_display_name(scope_id); mi->set_description(scope_id); mi->set_author("Canonical Ltd."); mi->set_proxy(proxies[scope_id]); mi->set_scope_directory("/foo"); auto meta = ScopeMetadataImpl::create(move(mi)); RegistryObject::ScopeExecData exec_data; exec_data.scope_id = scope_id; exec_data.scoperunner_path = scoperunner_path; exec_data.runtime_config = rt_config; exec_data.scope_config = TEST_BUILD_ROOT "/../demo/scopes/" + scope_id + "/" + scope_id + ".ini"; reg->add_local_scope(scope_id, move(meta), exec_data); } // test initial state { // check that no scope processes are running for (auto const& scope_id : scope_ids) { EXPECT_FALSE(reg->is_scope_running(scope_id)); } // check that no new processes have been started yet current_process_count = process_count(); EXPECT_EQ(0, current_process_count - start_process_count); } // test scope death and re-locate { // locate first scope EXPECT_EQ(proxies[scope_ids[0]], reg->locate(scope_ids[0])); // check that the first scope is running EXPECT_TRUE(reg->is_scope_running(scope_ids[0])); // check that 1 new process was started current_process_count = process_count(); EXPECT_EQ(1, current_process_count - start_process_count); // kill first scope int scope1_pid = first_child_pid(); kill(scope1_pid, SIGKILL); // wait for the SIGCHLD signal to reach the registry while (reg->is_scope_running(scope_ids[0])) { std::this_thread::sleep_for(std::chrono::milliseconds{10}); } // check that we now have no running scopes current_process_count = process_count(); EXPECT_EQ(0, current_process_count - start_process_count); // locate first scope EXPECT_EQ(proxies[scope_ids[0]], reg->locate(scope_ids[0])); // check that the first scope is running EXPECT_TRUE(reg->is_scope_running(scope_ids[0])); // check that 1 new process was started current_process_count = process_count(); EXPECT_EQ(1, current_process_count - start_process_count); } // test locating all scopes { // locate all scopes (hense starting all scope processes) for (auto const& scope_id : scope_ids) { EXPECT_EQ(proxies[scope_id], reg->locate(scope_id)); } // check that all scopes processes are running for (auto const& scope_id : scope_ids) { EXPECT_TRUE(reg->is_scope_running(scope_id)); } // check that 6 new processes were started current_process_count = process_count(); EXPECT_EQ(6, current_process_count - start_process_count); } // test locating the same scope multiple times { // locate the second scope multiple times for (int i = 0; i < 1000; ++i) { EXPECT_EQ(proxies[scope_ids[1]], reg->locate(scope_ids[1])); } // check that no new processes were started current_process_count = process_count(); EXPECT_EQ(6, current_process_count - start_process_count); } // test removing a scope { // remove a scope (hense killing the process) EXPECT_TRUE(reg->remove_local_scope(scope_ids[0])); // check that we now have 5 scopes running current_process_count = process_count(); EXPECT_EQ(5, current_process_count - start_process_count); } // reg falls out of scope here and gets deleted (hense closing all scope processes) } // check that we are back to the original number of processes current_process_count = process_count(); EXPECT_EQ(0, current_process_count - start_process_count); } ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/RegistryI/CMakeLists.txtunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/RegistryI/CMakeLists0000644000015301777760000000055012320776161033417 0ustar pbusernogroup00000000000000configure_file(TestRegistry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/TestRegistry.ini) configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini) configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini) add_executable(RegistryI_test RegistryI_test.cpp) target_link_libraries(RegistryI_test ${LIBS} ${TESTLIBS}) add_test(RegistryI RegistryI_test) ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/RegistryI/Runtime.ini.inunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/RegistryI/Runtime.in0000644000015301777760000000027212320776161033451 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = TestRegistry Registry.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/TestRegistry.ini Default.Middleware = Zmq Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/0000755000015301777760000000000012320776463032326 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/Zmq.ini.inunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/Zmq.in0000644000015301777760000000007312320776161033420 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMiddleware_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMid0000644000015301777760000002225312320776161033451 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include using namespace std; using namespace unity::scopes; using namespace unity::scopes::internal; using namespace unity::scopes::internal::zmq_middleware; // Basic test. TEST(ZmqMiddleware, basic) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/Zmq.ini", (RuntimeImpl*)0x1); mw.start(); sleep(1); mw.stop(); } TEST(ZmqMiddleware, string_to_proxy) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/Zmq.ini", (RuntimeImpl*)0x1); ObjectProxy p; ScopeProxy sp; p = mw.string_to_proxy("nullproxy:"); EXPECT_EQ(nullptr, p); p = mw.string_to_proxy("ipc://path#id"); EXPECT_EQ("ipc://path", p->endpoint()); EXPECT_EQ("id", p->identity()); EXPECT_EQ(-1, p->timeout()); sp = dynamic_pointer_cast(p); ASSERT_NE(nullptr, sp); p = mw.string_to_proxy("ipc://path#id!t=-1"); EXPECT_EQ("ipc://path", p->endpoint()); EXPECT_EQ("id", p->identity()); EXPECT_EQ(-1, p->timeout()); p = mw.string_to_proxy("ipc://path#id!t=500"); EXPECT_EQ("ipc://path", p->endpoint()); EXPECT_EQ("id", p->identity()); EXPECT_EQ(500, p->timeout()); p = mw.string_to_proxy("ipc://path#id!t=500!c=Registry"); EXPECT_EQ("ipc://path", p->endpoint()); EXPECT_EQ("id", p->identity()); EXPECT_EQ(500, p->timeout()); p = mw.string_to_proxy("ipc://path#id!t=500!c=Scope!m=t"); EXPECT_EQ("ipc://path", p->endpoint()); EXPECT_EQ("id", p->identity()); EXPECT_EQ(500, p->timeout()); } TEST(ZmqMiddleware, string_to_proxy_ex) { ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/Zmq.ini", (RuntimeImpl*)0x1); try { mw.string_to_proxy(""); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): proxy string cannot be empty", e.what()); } try { mw.string_to_proxy("x"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy scheme prefix: " "\"x\" (expected \"ipc://\")", e.what()); } try { mw.string_to_proxy("ipc://abc"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: missing # separator: " "ipc://abc", e.what()); } try { mw.string_to_proxy("ipc://#abc"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: empty endpoint path: " "ipc://#abc", e.what()); } try { mw.string_to_proxy("ipc://path#"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: empty identity: " "ipc://path#", e.what()); } try { mw.string_to_proxy("ipc://path#!"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: empty identity: " "ipc://path#!", e.what()); } try { mw.string_to_proxy("ipc://path#id!"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: invalid empty " "field specification: ipc://path#id!", e.what()); } try { mw.string_to_proxy("ipc://path#id!t=1!"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: invalid empty " "field specification: ipc://path#id!t=1!", e.what()); } try { mw.string_to_proxy("ipc://path#id!!t=1!"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: invalid empty " "field specification: ipc://path#id!!t=1!", e.what()); } try { mw.string_to_proxy("ipc://path#id!t=1!!"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: invalid empty " "field specification: ipc://path#id!t=1!!", e.what()); } try { mw.string_to_proxy("ipc://path#id!t"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: bad field " "specification (\"t\"): ipc://path#id!t", e.what()); } try { mw.string_to_proxy("ipc://path#id!tt"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: bad field " "specification (\"tt\"): ipc://path#id!tt", e.what()); } try { mw.string_to_proxy("ipc://path#id!x=1"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: invalid field " "identifier (\"x=1\"): ipc://path#id!x=1", e.what()); } try { mw.string_to_proxy("ipc://path#id!t=1!t=1"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: duplicate " "field specification (\"t=\"): ipc://path#id!t=1!t=1", e.what()); } try { mw.string_to_proxy("ipc://path#id!m="); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: bad mode " "(\"m=\"): ipc://path#id!m=", e.what()); } try { mw.string_to_proxy("ipc://path#id!t="); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: bad timeout " "value (\"t=\"): ipc://path#id!t=", e.what()); } try { mw.string_to_proxy("ipc://path#id!t=x"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: bad timeout " "value (\"t=x\"): ipc://path#id!t=x", e.what()); } try { mw.string_to_proxy("ipc://path#id!t=1x"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: bad timeout " "value (\"t=1x\"): ipc://path#id!t=1x", e.what()); } try { mw.string_to_proxy("ipc://path#id!t=-2"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: string_to_proxy(): invalid proxy: bad timeout " "value (\"t=-2\"): ipc://path#id!t=-2", e.what()); } try { mw.string_to_proxy("ipc://path#id!t=500!c=Scope!m=o"); FAIL(); } catch (MiddlewareException const& e) { EXPECT_STREQ("unity::scopes::MiddlewareException: make_typed_proxy(): cannot create oneway proxies", e.what()); } } ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/CMakeLists.txtunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/CMakeL0000644000015301777760000000034412320776161033341 0ustar pbusernogroup00000000000000configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini) add_executable(ZmqMiddleware_test ZmqMiddleware_test.cpp) target_link_libraries(ZmqMiddleware_test ${LIBS} ${TESTLIBS}) add_test(ZmqMiddleware ZmqMiddleware_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ThreadSafeQueue/0000755000015301777760000000000012320776463027570 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ThreadSafeQueue/CMakeLists.txt0000644000015301777760000000024612320776161032325 0ustar pbusernogroup00000000000000add_executable(ThreadSafeQueue_test ThreadSafeQueue_test.cpp) target_link_libraries(ThreadSafeQueue_test ${TESTLIBS}) add_test(ThreadSafeQueue ThreadSafeQueue_test) ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ThreadSafeQueue/ThreadSafeQueue_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ThreadSafeQueue/ThreadSafeQueue_tes0000644000015301777760000000710012320776161033372 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; using namespace unity::scopes::internal; TEST(ThreadSafeQueue, basic) { ThreadSafeQueue q; EXPECT_TRUE(q.empty()); EXPECT_EQ(0u, q.size()); int n; EXPECT_FALSE(q.try_pop(n)); q.push(5); // R-value EXPECT_FALSE(q.empty()); EXPECT_EQ(1u, q.size()); n = q.wait_and_pop(); EXPECT_EQ(5, n); EXPECT_TRUE(q.empty()); EXPECT_EQ(0u, q.size()); n = 6; // L-value q.push(n); EXPECT_EQ(1u, q.size()); auto r = q.wait_and_pop(); EXPECT_EQ(6, r); EXPECT_EQ(0u, q.size()); n = 7; q.push(n); EXPECT_EQ(1u, q.size()); EXPECT_TRUE(q.try_pop(r)); EXPECT_EQ(7, r); } promise waiter_ready; void waiter_thread(ThreadSafeQueue* q) { EXPECT_EQ("fred", q->wait_and_pop()); waiter_ready.set_value(); try { q->wait_and_pop(); FAIL(); } catch (std::runtime_error const& e) { EXPECT_STREQ("ThreadSafeQueue: queue destroyed while thread was blocked in wait_and_pop()", e.what()); } } TEST(ThreadSafeQueue, exception) { unique_ptr> q(new ThreadSafeQueue); q->push("fred"); auto f = waiter_ready.get_future(); auto t = thread(waiter_thread, q.get()); f.wait(); this_thread::sleep_for(chrono::milliseconds(50)); // Make sure child thread has time to call wait_and_pop() q.reset(); t.join(); } atomic_int count; void int_reader_thread(ThreadSafeQueue* q) { try { q->wait_and_pop(); FAIL(); } catch (std::runtime_error const&) { ++count; } } TEST(ThreadSafeQueue, wait_for_threads) { ThreadSafeQueue q; count = 0; vector threads; for (auto i = 0; i < 20; ++i) { threads.push_back(thread(int_reader_thread, &q)); } this_thread::sleep_for(chrono::milliseconds(300)); // Destroy the queue while multiple threads are sleeping in wait_and_pop(). q.destroy(); for (auto& t : threads) { t.join(); } EXPECT_EQ(20, count); } class MoveOnly { public: MoveOnly(string s) : s_(s) { } MoveOnly(MoveOnly const&) = delete; MoveOnly& operator=(MoveOnly const&) = delete; MoveOnly(MoveOnly&& other) = default; MoveOnly& operator=(MoveOnly&& rhs) = default; string const& val() { return s_; } private: string s_; }; TEST(ThreadSafeQueue, move_only) { ThreadSafeQueue q; q.push(move(MoveOnly("hello"))); q.push(move(MoveOnly("world"))); q.push(move(MoveOnly("again"))); MoveOnly m(""); EXPECT_TRUE(q.try_pop(m)); EXPECT_EQ("hello", m.val()); EXPECT_TRUE(q.try_pop(m)); EXPECT_EQ("world", m.val()); m = q.wait_and_pop(); EXPECT_EQ("again", m.val()); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ConfigBase/0000755000015301777760000000000012320776463026555 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ConfigBase/Test.ini.in0000644000015301777760000000016112320776161030573 0ustar pbusernogroup00000000000000[SomeGroup] Empty = Zmq.Middleware = Zmq REST.Middleware = REST Zmq.BadMiddleware = foo REST.BadMiddleware = bar unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ConfigBase/ConfigBase_test.cpp0000644000015301777760000000646112320776161032322 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include //#include // Use Boost implementation until http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631 is fixed. using namespace std; using namespace unity; using namespace unity::scopes; using namespace unity::scopes::internal; class MyConfig : public ConfigBase { public: MyConfig(string const& configfile) : ConfigBase(configfile) { } void error() { throw_ex("error"); } }; TEST(ConfigBase, basic) { MyConfig c("Test.ini"); EXPECT_TRUE(c.parser().get()); } TEST(ConfigBase, optional_string) { MyConfig c("Test.ini"); EXPECT_EQ("", c.get_optional_string("SomeGroup", "NoSuchKey")); EXPECT_EQ("", c.get_optional_string("SomeGroup", "Empty")); } TEST(ConfigBase, non_optional_string) { MyConfig c("Test.ini"); try { c.get_string("SomeGroup", "Empty"); FAIL(); } catch (ConfigException const& e) { EXPECT_STREQ("unity::scopes::ConfigException: \"Test.ini\": Illegal empty value for Empty", e.what()); } } TEST(ConfigBase, middleware) { MyConfig c("Test.ini"); EXPECT_EQ("Zmq", c.get_middleware("SomeGroup", "Zmq.Middleware")); EXPECT_EQ("REST", c.get_middleware("SomeGroup", "REST.Middleware")); try { c.get_middleware("SomeGroup", "Zmq.BadMiddleware"); FAIL(); } catch (ConfigException const& e) { EXPECT_STREQ("unity::scopes::ConfigException: \"Test.ini\": Illegal value for Zmq.BadMiddleware: \"foo\": " "legal values are \"Zmq\" and \"REST\"", e.what()); } try { c.get_middleware("SomeGroup", "REST.BadMiddleware"); FAIL(); } catch (ConfigException const& e) { EXPECT_STREQ("unity::scopes::ConfigException: \"Test.ini\": Illegal value for REST.BadMiddleware: \"bar\": " "legal values are \"Zmq\" and \"REST\"", e.what()); } } TEST(ConfigBase, throw_ex) { MyConfig c("Test.ini"); EXPECT_TRUE(c.parser().get()); try { c.error(); } catch (ConfigException const& e) { EXPECT_STREQ("unity::scopes::ConfigException: \"Test.ini\": error", e.what()); } } TEST(ConfigBase, FileException) { try { MyConfig c("no_such_file"); } catch (FileException const& e) { EXPECT_STREQ("unity::FileException: Could not load ini file no_such_file: No such file or directory (errno = 4)", e.what()); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ConfigBase/CMakeLists.txt0000644000015301777760000000026312320776161031311 0ustar pbusernogroup00000000000000configure_file(Test.ini.in Test.ini) add_executable(ConfigBase_test ConfigBase_test.cpp) target_link_libraries(ConfigBase_test ${TESTLIBS}) add_test(ConfigBase ConfigBase_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeConfig/0000755000015301777760000000000012320776463026754 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeConfig/configtest2.ini.in0000644000015301777760000000025212320776161032303 0ustar pbusernogroup00000000000000[ScopeConfig] DisplayName = Scope name Description = Scope description Art = scope art Author = Canonical Icon = an icon SearchHint = a search hint string HotKey = a key unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeConfig/CMakeLists.txt0000644000015301777760000000050712320776161031511 0ustar pbusernogroup00000000000000configure_file(configtest1.ini.in configtest1.ini copyonly) configure_file(configtest2.ini.in configtest2.ini copyonly) configure_file(configtest3.ini.in configtest3.ini copyonly) add_executable(ScopeConfig_test ScopeConfig_test.cpp) target_link_libraries(ScopeConfig_test ${TESTLIBS}) add_test(ScopeConfig ScopeConfig_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeConfig/configtest3.ini.in0000644000015301777760000000031112320776161032300 0ustar pbusernogroup00000000000000[ScopeConfig] DisplayName = Scope name Description = Scope description Art = scope art Author = Canonical Icon = an icon SearchHint = a search hint string HotKey = a key ScopeRunner = /my/scope/runner unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeConfig/configtest1.ini.in0000644000015301777760000000033612320776161032305 0ustar pbusernogroup00000000000000[ScopeConfig] DisplayName = Scope name Description = Scope description Art = scope art Author = Canonical Icon = an icon SearchHint = a search hint string HotKey = a key [Appearance] arbitrary_key = foo another_one = bar unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp0000644000015301777760000000464712320776161032724 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; TEST(ScopeConfig, basic) { { ScopeConfig cfg("configtest1.ini"); EXPECT_EQ("Scope name", cfg.display_name()); EXPECT_EQ("scope art", cfg.art()); EXPECT_EQ("Canonical", cfg.author()); EXPECT_EQ("an icon", cfg.icon()); EXPECT_EQ("a search hint string", cfg.search_hint()); EXPECT_EQ("a key", cfg.hot_key()); auto attrs = cfg.appearance_attributes(); EXPECT_EQ(2, attrs.size()); EXPECT_EQ("foo", attrs["arbitrary_key"].get_string()); EXPECT_EQ("bar", attrs["another_one"].get_string()); EXPECT_THROW(cfg.scope_runner(), unity::scopes::NotFoundException); } { ScopeConfig cfg("configtest2.ini"); EXPECT_EQ("Scope name", cfg.display_name()); EXPECT_EQ("scope art", cfg.art()); EXPECT_EQ("Canonical", cfg.author()); EXPECT_EQ("an icon", cfg.icon()); EXPECT_EQ("a search hint string", cfg.search_hint()); EXPECT_EQ("a key", cfg.hot_key()); EXPECT_EQ(0, cfg.appearance_attributes().size()); } { ScopeConfig cfg("configtest3.ini"); EXPECT_EQ("Scope name", cfg.display_name()); EXPECT_EQ("scope art", cfg.art()); EXPECT_EQ("Canonical", cfg.author()); EXPECT_EQ("an icon", cfg.icon()); EXPECT_EQ("a search hint string", cfg.search_hint()); EXPECT_EQ("a key", cfg.hot_key()); EXPECT_EQ("/my/scope/runner", cfg.scope_runner()); EXPECT_EQ(0, cfg.appearance_attributes().size()); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/CategoryRenderer/0000755000015301777760000000000012320776463026205 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/CategoryRenderer/CategoryRenderer_test.cpp0000644000015301777760000000363112320776161033212 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; TEST(CategoryRenderer, basic) { CategoryRenderer rdr; EXPECT_FALSE(rdr.data().empty()); EXPECT_EQ(DEFAULT_RENDERER, rdr.data()); } TEST(CategoryRenderer, from_file) { const std::string input_file(TEST_BUILD_ROOT "/gtest/scopes/CategoryRenderer/renderer.json"); EXPECT_THROW(CategoryRenderer::from_file("/non-existing-file"), unity::FileException); EXPECT_NO_THROW(CategoryRenderer::from_file(input_file)); auto rdr = CategoryRenderer::from_file(input_file); EXPECT_FALSE(rdr.data().empty()); } TEST(CategoryRenderer, exceptions) { try { // only dict is allowed CategoryRenderer rdr("[1,2]"); FAIL(); } catch (unity::InvalidArgumentException const&) { } try { // invalid JSON CategoryRenderer rdr("{"); FAIL(); } catch (unity::InvalidArgumentException const&) { } try { CategoryRenderer rdr("{}"); } catch (...) { FAIL(); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/CategoryRenderer/renderer.json0000644000015301777760000000025112320776161030677 0ustar pbusernogroup00000000000000{ "template" : { "renderer": "grid", "overlay-mode": null }, "components": { "title": "title", "subtitle": "subtitle", "art": "art" } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/CategoryRenderer/CMakeLists.txt0000644000015301777760000000035712320776161030745 0ustar pbusernogroup00000000000000configure_file(renderer.json ${CMAKE_CURRENT_BINARY_DIR}/ COPYONLY) add_executable(CategoryRenderer_test CategoryRenderer_test.cpp) target_link_libraries(CategoryRenderer_test ${TESTLIBS}) add_test(CategoryRenderer CategoryRenderer_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/CategorisedResult/0000755000015301777760000000000012320776463026371 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/CategorisedResult/CategorisedResult_test.cpp0000644000015301777760000003360512320776161033566 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; // basic test of CategorisedResult setters and getters TEST(CategorisedResult, basic) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); auto cat2 = reg.register_category("2", "title", "icon", rdr); { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); result.set_title("a title"); result.set_art("an icon"); result.set_dnd_uri("http://canonical.com"); EXPECT_EQ("http://ubuntu.com", result.uri()); EXPECT_EQ("a title", result.title()); EXPECT_EQ("an icon", result.art()); EXPECT_EQ("http://canonical.com", result.dnd_uri()); EXPECT_EQ("http://ubuntu.com", result.value("uri").get_string()); EXPECT_EQ("a title", result.value("title").get_string()); EXPECT_EQ("an icon", result.value("art").get_string()); EXPECT_EQ("http://canonical.com", result.dnd_uri()); EXPECT_EQ("1", result.category()->id()); result.set_category(cat2); EXPECT_EQ("2", result.category()->id()); } } // test for [] operator TEST(CategorisedResult, indexop) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); { CategorisedResult result(cat); result["uri"] = Variant("http://ubuntu.com"); result["title"] = Variant("a title"); result["art"] = "an icon"; result["dnd_uri"] = "http://canonical.com"; result["foo"] = Variant("bar"); // referencing non-existing attribute creates it EXPECT_NO_THROW(result["nonexisting"]); EXPECT_TRUE(result.contains("nonexisting")); EXPECT_EQ(Variant::Type::Null, result["nonexisting"].which()); EXPECT_EQ("http://ubuntu.com", result.uri()); EXPECT_EQ("http://ubuntu.com", result["uri"].get_string()); EXPECT_EQ("a title", result.title()); EXPECT_EQ("a title", result["title"].get_string()); EXPECT_EQ("an icon", result.art()); EXPECT_EQ("an icon", result["art"].get_string()); EXPECT_EQ("http://canonical.com", result.dnd_uri()); EXPECT_EQ("http://canonical.com", result["dnd_uri"].get_string()); EXPECT_TRUE(result.contains("foo")); EXPECT_EQ("bar", result["foo"].get_string()); EXPECT_EQ("bar", result.value("foo").get_string()); EXPECT_EQ("bar", result.serialize()["attrs"].get_dict()["foo"].get_string()); EXPECT_EQ("1", result.category()->id()); } { CategorisedResult result(cat); result["uri"] = Variant("http://ubuntu.com"); // force const operator[] const CategorisedResult result2 = result; EXPECT_EQ("http://ubuntu.com", result2["uri"].get_string()); // referencing non-existing attribute of const result object throws EXPECT_THROW(result2["nonexisting"], unity::InvalidArgumentException); EXPECT_FALSE(result2.contains("nonexisting")); } } TEST(CategorisedResult, copy) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); // copy ctor { CategorisedResult result(cat); result.set_uri("uri a"); result.set_title("title a"); result.set_art("icon a"); result.set_dnd_uri("dnd_uri a"); result["common"] = "o"; CategorisedResult copy(result); copy.set_uri("uri b"); copy.set_title("title b"); copy.set_art("icon b"); copy.set_dnd_uri("dnd_uri b"); result["foo"] = Variant("bar"); result["unique"] = Variant(123); copy["foo"] = Variant("xyz"); { auto attrsvar = result.serialize()["attrs"].get_dict(); EXPECT_EQ("uri a", result.uri()); EXPECT_EQ("title a", result.title()); EXPECT_EQ("icon a", result.art()); EXPECT_EQ("dnd_uri a", result.dnd_uri()); EXPECT_EQ("o", attrsvar["common"].get_string()); EXPECT_EQ(123, attrsvar["unique"].get_int()); EXPECT_EQ("bar", attrsvar["foo"].get_string()); EXPECT_EQ("1", result.category()->id()); } { auto attrsvar = copy.serialize()["attrs"].get_dict(); EXPECT_EQ("uri b", copy.uri()); EXPECT_EQ("title b", copy.title()); EXPECT_EQ("icon b", copy.art()); EXPECT_EQ("dnd_uri b", copy.dnd_uri()); EXPECT_EQ("o", attrsvar["common"].get_string()); EXPECT_TRUE(attrsvar.find("unique") == attrsvar.end()); EXPECT_EQ("xyz", attrsvar["foo"].get_string()); EXPECT_EQ("1", copy.category()->id()); } } // assignment copy { CategorisedResult result(cat); result.set_uri("uri a"); result.set_title("title a"); result.set_art("icon a"); result.set_dnd_uri("dnd_uri a"); CategorisedResult copy = result; copy.set_uri("uri b"); copy.set_title("title b"); copy.set_art("icon b"); copy.set_dnd_uri("dnd_uri b"); result["foo"] = Variant("bar"); copy["foo"] = Variant("xyz"); EXPECT_EQ("uri a", result.uri()); EXPECT_EQ("title a", result.title()); EXPECT_EQ("icon a", result.art()); EXPECT_EQ("dnd_uri a", result.dnd_uri()); EXPECT_EQ("bar", result.serialize()["attrs"].get_dict()["foo"].get_string()); EXPECT_EQ("1", result.category()->id()); EXPECT_EQ("uri b", copy.uri()); EXPECT_EQ("title b", copy.title()); EXPECT_EQ("icon b", copy.art()); EXPECT_EQ("dnd_uri b", copy.dnd_uri()); EXPECT_EQ("xyz", copy.serialize()["attrs"].get_dict()["foo"].get_string()); EXPECT_EQ("1", copy.category()->id()); CategorisedResult copy2(cat); copy2 = copy; EXPECT_EQ("uri b", copy2.uri()); EXPECT_EQ("title b", copy2.title()); EXPECT_EQ("icon b", copy2.art()); EXPECT_EQ("dnd_uri b", copy2.dnd_uri()); EXPECT_EQ("xyz", copy2.serialize()["attrs"].get_dict()["foo"].get_string()); EXPECT_EQ("1", copy2.category()->id()); } } // test conversion to VariantMap TEST(CategorisedResult, serialize) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); result.set_title("a title"); result.set_art("an icon"); result.set_dnd_uri("http://canonical.com"); EXPECT_EQ("http://ubuntu.com", result.uri()); EXPECT_EQ("a title", result.title()); EXPECT_EQ("an icon", result.art()); EXPECT_EQ("http://canonical.com", result.dnd_uri()); auto outer_var = result.serialize(); auto var = outer_var["attrs"].get_dict(); EXPECT_EQ("http://ubuntu.com", var["uri"].get_string()); EXPECT_EQ("a title", var["title"].get_string()); EXPECT_EQ("an icon", var["art"].get_string()); EXPECT_EQ("http://canonical.com", var["dnd_uri"].get_string()); EXPECT_EQ("1", outer_var["internal"].get_dict()["cat_id"].get_string()); } { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); result.set_dnd_uri("http://canonical.com"); auto outer_var = result.serialize(); auto var = outer_var["attrs"].get_dict(); EXPECT_EQ("http://ubuntu.com", var["uri"].get_string()); EXPECT_TRUE(var.find("title") == var.end()); EXPECT_TRUE(var.find("art") == var.end()); EXPECT_EQ("http://canonical.com", var["dnd_uri"].get_string()); EXPECT_EQ("1", outer_var["internal"].get_dict()["cat_id"].get_string()); } } // test exceptions when converting to VariantMap TEST(CategorisedResult, serialize_excp) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); CategorisedResult result(cat); { // throw until mandatory 'uri' attribute is not empty EXPECT_THROW(result.serialize(), unity::InvalidArgumentException); result.set_uri("http://ubuntu.com"); EXPECT_NO_THROW(result.serialize()); } { result["uri"] = Variant(0); EXPECT_THROW(result.serialize(), unity::InvalidArgumentException); result["uri"] = "http://ubuntu.com"; result["dnd_uri"] = Variant(0); EXPECT_THROW(result.serialize(), unity::InvalidArgumentException); result["dnd_uri"] = "http://ubuntu.com"; EXPECT_NO_THROW(result.serialize()); } } TEST(CategorisedResult, exceptions) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); Category::SCPtr null_cat; { try { CategorisedResult r(null_cat); FAIL(); } catch (const unity::InvalidArgumentException& e) {} } { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); EXPECT_THROW(result.value("nonexisting"), unity::InvalidArgumentException); } { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); result.set_dnd_uri("http://canonical.com"); EXPECT_THROW(result.set_category(nullptr), unity::InvalidArgumentException); } { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); result.set_title("a title"); result.set_art("an icon"); result.set_dnd_uri("http://canonical.com"); } } // test conversion from VariantMap TEST(CategorisedResult, deserialize) { { VariantMap vm; vm["uri"] = "http://ubuntu.com"; vm["dnd_uri"] = "http://canonical.com"; vm["title"] = "a title"; vm["art"] = "an icon"; vm["foo"] = "bar"; // custom attribute VariantMap intvm; intvm["cat_id"] = "2"; VariantMap outer; outer["attrs"] = vm; outer["internal"] = intvm; CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); auto result = internal::CategorisedResultImpl::create_result(new CategorisedResultImpl(cat, outer)); auto outer_var = result.serialize(); auto var = outer_var["attrs"].get_dict(); EXPECT_EQ("http://ubuntu.com", var["uri"].get_string()); EXPECT_EQ("a title", var["title"].get_string()); EXPECT_EQ("an icon", var["art"].get_string()); EXPECT_EQ("http://canonical.com", var["dnd_uri"].get_string()); EXPECT_EQ("bar", var["foo"].get_string()); EXPECT_EQ("1", outer_var["internal"].get_dict()["cat_id"].get_string()); } { VariantMap vm; vm["uri"] = "http://ubuntu.com"; vm["dnd_uri"] = "http://canonical.com"; vm["foo"] = "bar"; // custom attribute VariantMap intvm; intvm["cat_id"] = "2"; VariantMap outer; outer["attrs"] = vm; outer["internal"] = intvm; CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); auto result = internal::CategorisedResultImpl::create_result(new internal::CategorisedResultImpl(cat, outer)); EXPECT_EQ("http://ubuntu.com", result.uri()); EXPECT_EQ("http://canonical.com", result.dnd_uri()); EXPECT_EQ("", result.title()); EXPECT_EQ("", result.art()); EXPECT_FALSE(result.contains("title")); EXPECT_FALSE(result.contains("art")); EXPECT_EQ("bar", result["foo"].get_string()); } } TEST(CategorisedResult, store) { CategoryRenderer rdr; CategoryRegistry input_reg; CategoryRegistry output_reg; auto incat = input_reg.register_category("1", "title", "icon", rdr); auto outcat = output_reg.register_category("2", "title", "icon", rdr); CategorisedResult outresult(outcat); outresult.set_uri("uri1"); outresult.set_title("title1"); outresult.set_art("icon1"); outresult.set_dnd_uri("dnduri1"); EXPECT_THROW(outresult.store(outresult), unity::InvalidArgumentException); // cannot store self EXPECT_FALSE(outresult.has_stored_result()); { CategorisedResult inresult(incat); inresult.set_uri("uri1"); inresult.set_title("title1"); inresult.set_art("icon1"); inresult.set_dnd_uri("dnduri1"); outresult.store(inresult); } EXPECT_TRUE(outresult.has_stored_result()); EXPECT_EQ("uri1", outresult.uri()); EXPECT_EQ("title1", outresult.title()); EXPECT_EQ("icon1", outresult.art()); EXPECT_EQ("dnduri1", outresult.dnd_uri()); EXPECT_EQ("2", outresult.category()->id()); auto inresult = outresult.retrieve(); EXPECT_EQ("uri1", inresult.uri()); EXPECT_EQ("title1", inresult.title()); EXPECT_EQ("icon1", inresult.art()); EXPECT_EQ("dnduri1", inresult.dnd_uri()); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/CategorisedResult/CMakeLists.txt0000644000015301777760000000026012320776161031122 0ustar pbusernogroup00000000000000add_executable(CategorisedResult_test CategorisedResult_test.cpp) target_link_libraries(CategorisedResult_test ${TESTLIBS}) add_test(CategorisedResult CategorisedResult_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/0000755000015301777760000000000012320776463024551 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/Zmq.ini.in0000644000015301777760000000007312320776161026421 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/Registry_test.cpp0000644000015301777760000000671712320776161030132 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include #include #include #include #include using namespace unity::scopes; class Receiver : public SearchListenerBase { public: virtual void push(CategorisedResult /* result */) override { } virtual void finished(ListenerBase::Reason /* reason */, std::string const& /* error_message */) override { } }; TEST(Registry, metadata) { Runtime::UPtr rt = Runtime::create(TEST_RUNTIME_FILE); RegistryProxy r = rt->registry(); auto meta = r->get_metadata("testscopeA"); EXPECT_EQ("testscopeA", meta.scope_id()); EXPECT_EQ("Canonical Ltd.", meta.author()); EXPECT_EQ("scope-A.DisplayName", meta.display_name()); EXPECT_EQ("scope-A.Description", meta.description()); EXPECT_EQ("/foo/scope-A.Art", meta.art()); EXPECT_EQ("/foo/scope-A.Icon", meta.icon()); EXPECT_EQ("scope-A.HotKey", meta.hot_key()); EXPECT_EQ("scope-A.SearchHint", meta.search_hint()); EXPECT_EQ(TEST_RUNTIME_PATH "/scopes/testscopeA", meta.scope_directory()); const char *bart = TEST_RUNTIME_PATH "/scopes/testscopeB/data/scope-B.Art"; const char *bicon = TEST_RUNTIME_PATH "/scopes/testscopeB/data/scope-B.Icon"; meta = r->get_metadata("testscopeB"); EXPECT_EQ("testscopeB", meta.scope_id()); EXPECT_EQ("Canonical Ltd.", meta.author()); EXPECT_EQ("scope-B.DisplayName", meta.display_name()); EXPECT_EQ("scope-B.Description", meta.description()); EXPECT_EQ(bart, meta.art()); EXPECT_EQ(bicon, meta.icon()); EXPECT_EQ("scope-B.HotKey", meta.hot_key()); EXPECT_EQ("scope-B.SearchHint", meta.search_hint()); EXPECT_EQ(TEST_RUNTIME_PATH "/scopes/testscopeB", meta.scope_directory()); auto sp = meta.proxy(); SearchListenerBase::SPtr reply(new Receiver); SearchMetadata metadata("C", "desktop"); // search would fail if testscopeB can't be executed try { auto ctrl = sp->search("foo", metadata, reply); } catch (...) { FAIL(); } } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); auto rpid = fork(); if (rpid == 0) { const char* const args[] = {"scoperegistry [Registry test]", TEST_RUNTIME_FILE, nullptr}; if (execv(TEST_REGISTRY_PATH "/scoperegistry", const_cast(args)) < 0) { perror("Error starting scoperegistry:"); } return 1; } else if (rpid > 0) { auto rc = RUN_ALL_TESTS(); kill(rpid, SIGTERM); return rc; } else { perror("Failed to fork:"); } return 1; } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/scopes/0000755000015301777760000000000012320776463026045 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/scopes/testscopeA/0000755000015301777760000000000012320776463030157 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.cpp0000644000015301777760000000451212320776161032772 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include #define EXPORT __attribute__ ((visibility ("default"))) using namespace std; using namespace unity::scopes; class MyQuery : public SearchQueryBase { public: MyQuery(CannedQuery const& query) : query_(query) { } virtual void cancelled() override { } virtual void run(SearchReplyProxy const&) override { } private: CannedQuery query_; }; class MyPreview : public PreviewQueryBase { public: virtual void cancelled() override { } virtual void run(PreviewReplyProxy const&) override { } }; class MyScope : public ScopeBase { public: virtual int start(string const&, RegistryProxy const&) override { return VERSION; } virtual void stop() override {} virtual SearchQueryBase::UPtr search(CannedQuery const& q, SearchMetadata const&) override { SearchQueryBase::UPtr query(new MyQuery(q)); return query; } virtual PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const&) override { PreviewQueryBase::UPtr preview(new MyPreview()); return preview; } }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { return new MyScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/scopes/testscopeA/CMakeLists.txt0000644000015301777760000000013712320776161032713 0ustar pbusernogroup00000000000000add_library(testscopeA MODULE testscopeA.cpp) configure_file(testscopeA.ini.in testscopeA.ini) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.ini.in0000644000015301777760000000032212320776161033367 0ustar pbusernogroup00000000000000[ScopeConfig] DisplayName = scope-A.DisplayName Description = scope-A.Description Art = /foo/scope-A.Art Author = Canonical Ltd. Icon = /foo/scope-A.Icon SearchHint = scope-A.SearchHint HotKey = scope-A.HotKey unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/scopes/testscopeB/0000755000015301777760000000000012320776463030160 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/scopes/testscopeB/CMakeLists.txt0000644000015301777760000000022112320776161032706 0ustar pbusernogroup00000000000000add_executable(testscopeB testscopeB.cpp) target_link_libraries(testscopeB ${UNITY_SCOPES_LIB}) configure_file(testscopeB.ini.in testscopeB.ini) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/scopes/testscopeB/testscopeB.cpp0000644000015301777760000000535512320776161033002 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include #include #include #include using namespace std; using namespace unity::scopes; class MyQuery : public SearchQueryBase { public: virtual void cancelled() override { } virtual void run(SearchReplyProxy const& reply) override { CategoryRenderer rdr; auto cat = reply->register_category("cat1", "Category 1", "", rdr); CategorisedResult res(cat); res.set_uri("uri"); reply->push(res); } }; class MyPreview : public PreviewQueryBase { public: MyPreview(string const& uri) : uri_(uri) { } ~MyPreview() { } virtual void cancelled() override { } virtual void run(PreviewReplyProxy const& reply) override { PreviewWidgetList widgets; widgets.emplace_back(PreviewWidget(R"({"id": "header", "type": "header", "title": "title", "subtitle": "author", "rating": "rating"})")); reply->push(widgets); } private: string uri_; }; class MyScope : public ScopeBase { public: virtual int start(string const&, RegistryProxy const&) override { return VERSION; } virtual void stop() override {} virtual SearchQueryBase::UPtr search(CannedQuery const&, SearchMetadata const&) override { SearchQueryBase::UPtr query(new MyQuery()); return query; } virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const&) override { PreviewQueryBase::UPtr preview(new MyPreview(result.uri())); return preview; } }; int main(int /* argc */, char ** /* argv */) { MyScope scope; auto runtime = Runtime::create_scope_runtime("testscopeB", TEST_RUNTIME_FILE); runtime->run_scope(&scope, TEST_RUNTIME_PATH "/scopes/testscopeB/testscopeB.ini"); return 0; } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/scopes/testscopeB/testscopeB.ini.in0000644000015301777760000000040612320776161033374 0ustar pbusernogroup00000000000000[ScopeConfig] DisplayName = scope-B.DisplayName Description = scope-B.Description Art = data/scope-B.Art Author = Canonical Ltd. Icon = data/scope-B.Icon SearchHint = scope-B.SearchHint HotKey = scope-B.HotKey ScopeRunner = @CMAKE_CURRENT_BINARY_DIR@/testscopeB unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/scopes/CMakeLists.txt0000644000015301777760000000007212320776161030577 0ustar pbusernogroup00000000000000add_subdirectory(testscopeA) add_subdirectory(testscopeB) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/CMakeLists.txt0000644000015301777760000000120512320776161027302 0ustar pbusernogroup00000000000000include_directories(${CMAKE_CURRENT_SOURCE_DIR}) configure_file(RegistryTest.ini.in ${CMAKE_CURRENT_BINARY_DIR}/RegistryTest.ini) configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini) configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini) add_definitions(-DTEST_RUNTIME_PATH="${CMAKE_CURRENT_BINARY_DIR}") add_definitions(-DTEST_RUNTIME_FILE="${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini") add_definitions(-DTEST_REGISTRY_PATH="${PROJECT_BINARY_DIR}/scoperegistry") add_executable(Registry_test Registry_test.cpp) target_link_libraries(Registry_test ${TESTLIBS}) add_test(Registry Registry_test) add_subdirectory(scopes) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/Runtime.ini.in0000644000015301777760000000027212320776161027276 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = RegistryTest Registry.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/RegistryTest.ini Default.Middleware = Zmq Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Registry/RegistryTest.ini.in0000644000015301777760000000043412320776161030323 0ustar pbusernogroup00000000000000[Registry] Middleware = Zmq Zmq.Endpoint = ipc:///tmp/RegistryTest Zmq.EndpointDir = /tmp Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini Scope.InstallDir = @CMAKE_CURRENT_BINARY_DIR@/scopes OEM.InstallDir = /unused Scoperunner.Path = @PROJECT_BINARY_DIR@/scoperunner/scoperunner unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Variant/0000755000015301777760000000000012320776463024345 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Variant/Variant_test.cpp0000644000015301777760000001554412320776161027520 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include using namespace std; using namespace unity; using namespace unity::scopes; TEST(Variant, basic) { { Variant v; EXPECT_EQ(Variant::Type::Null, v.which()); // No exception here means that v was initialized to an int with unknown value. } { Variant v(42); EXPECT_EQ(Variant::Type::Int, v.which()); EXPECT_EQ(42, v.get_int()); } { Variant v(10.5f); EXPECT_EQ(Variant::Type::Double, v.which()); EXPECT_TRUE(v.get_double() - 10.5f < 0.00001f); } { Variant v(true); EXPECT_EQ(Variant::Type::Bool, v.which()); EXPECT_EQ(true, v.get_bool()); } { Variant v(string("hello")); EXPECT_EQ(Variant::Type::String, v.which()); EXPECT_EQ("hello", v.get_string()); } { Variant v("hello"); EXPECT_EQ(Variant::Type::String, v.which()); EXPECT_EQ("hello", v.get_string()); } { VariantMap m; VariantMap inner; inner["iron"] = Variant("maiden"); m["foo"] = Variant("bar"); m["hints"] = inner; Variant v(m); EXPECT_EQ(Variant::Type::Dict, v.which()); EXPECT_EQ("bar", v.get_dict()["foo"].get_string()); EXPECT_EQ(Variant::Type::Dict, v.get_dict()["hints"].which()); EXPECT_EQ("maiden", v.get_dict()["hints"].get_dict()["iron"].get_string()); } { VariantArray varr {Variant(1), Variant("foo")}; Variant v(varr); EXPECT_EQ(Variant::Type::Array, v.which()); EXPECT_EQ(2u, v.get_array().size()); EXPECT_EQ(1, v.get_array()[0].get_int()); EXPECT_EQ("foo", v.get_array()[1].get_string()); } { // Copy constructor Variant v(42); Variant v2(v); EXPECT_EQ(42, v2.get_int()); } { // Assignment operators Variant v("hello"); Variant v2(42); v = v2; EXPECT_EQ(42, v.get_int()); v = 99; EXPECT_EQ(99, v.get_int()); v = 10.5f; EXPECT_TRUE(v.get_double() - 10.5f < 0.00001f); v = false; EXPECT_FALSE(v.get_bool()); v = "hello"; EXPECT_EQ("hello", v.get_string()); v = string("world"); EXPECT_EQ("world", v.get_string()); } { // Comparison operators Variant v1(1); Variant v2(2); EXPECT_TRUE(v1 < v2); EXPECT_FALSE(v1 == v2); v2 = "hello"; EXPECT_TRUE(v1 < v2); // Any int is less than any string EXPECT_FALSE(v2 < v1); EXPECT_TRUE(v1 < v2); EXPECT_FALSE(v1 == v2); v1 = v2; EXPECT_FALSE(v1 < v2); EXPECT_FALSE(v2 < v1); EXPECT_TRUE(v1 == v2); v1 = 5; v2 = false; EXPECT_TRUE(v1 < v2); // Any int is less than any bool v1 = true; v2 = ""; EXPECT_TRUE(v1 < v2); // Any bool is less than any string } { // swap Variant v1(1); Variant v2(2); swap(v1, v2); EXPECT_EQ(2, v1.get_int()); EXPECT_EQ(1, v2.get_int()); v2 = "hello"; swap(v1, v2); EXPECT_EQ("hello", v1.get_string()); EXPECT_EQ(2, v2.get_int()); } } TEST(Variant, null) { Variant v0(0); EXPECT_FALSE(v0.is_null()); Variant v1 = Variant::null(); EXPECT_TRUE(v1.is_null()); Variant v2 = v1; EXPECT_TRUE(v2.is_null()); Variant v3(v1); EXPECT_TRUE(v3.is_null()); EXPECT_TRUE(v1 == v2); EXPECT_FALSE(v1 < v2); EXPECT_FALSE(v2 < v1); } TEST(Variant, exceptions) { try { Variant v; v.get_bool(); FAIL(); } catch (LogicException const& e) { EXPECT_STREQ("unity::LogicException: Variant does not contain a bool value:\n" " boost::bad_get: failed value get using boost::get", e.what()); } try { Variant v; v.get_string(); FAIL(); } catch (LogicException const& e) { EXPECT_STREQ("unity::LogicException: Variant does not contain a string value:\n" " boost::bad_get: failed value get using boost::get", e.what()); } try { Variant v("hello"); v.get_int(); FAIL(); } catch (LogicException const& e) { EXPECT_STREQ("unity::LogicException: Variant does not contain an int value:\n" " boost::bad_get: failed value get using boost::get", e.what()); } } TEST(Variant, serialize_json) { { Variant v; EXPECT_EQ("null\n", v.serialize_json()); } { Variant v(42); EXPECT_EQ("42\n", v.serialize_json()); } { Variant v(10.5f); EXPECT_EQ("10.50\n", v.serialize_json()); } { Variant v(true); EXPECT_EQ("true\n", v.serialize_json()); } { Variant v("hello"); EXPECT_EQ("\"hello\"\n", v.serialize_json()); } { VariantMap m; m["foo"] = Variant("bar"); Variant v(m); EXPECT_EQ("{\"foo\":\"bar\"}\n", v.serialize_json()); } { VariantArray varr {Variant(1), Variant("foo")}; Variant v(varr); EXPECT_EQ("[1,\"foo\"]\n", v.serialize_json()); } } TEST(Variant, deserialize_json) { Variant v = Variant::deserialize_json("null"); EXPECT_TRUE(v.is_null()); v = Variant::deserialize_json("42"); EXPECT_EQ(42, v.get_int()); v = Variant::deserialize_json("10.5"); EXPECT_EQ(10.5f, v.get_double()); v = Variant::deserialize_json("false"); EXPECT_FALSE(v.get_bool()); v = Variant::deserialize_json("\"hello\""); EXPECT_EQ("hello", v.get_string()); v = Variant::deserialize_json("{\"foo\": \"bar\"}"); VariantMap vm = v.get_dict(); EXPECT_EQ(1, vm.size()); EXPECT_EQ("bar", vm.at("foo").get_string()); v = Variant::deserialize_json("[1, \"two\"]"); VariantArray va = v.get_array(); EXPECT_EQ(2, va.size()); EXPECT_EQ(1, va[0].get_int()); EXPECT_EQ("two", va[1].get_string()); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Variant/CMakeLists.txt0000644000015301777760000000017612320776161027104 0ustar pbusernogroup00000000000000add_executable(Variant_test Variant_test.cpp) target_link_libraries(Variant_test ${TESTLIBS}) add_test(Variant Variant_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/CannedQuery/0000755000015301777760000000000012320776463025157 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/CannedQuery/CannedQuery_test.cpp0000644000015301777760000001044712320776161031141 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; // basic test of CannedQuery setters and getters TEST(CannedQuery, basic) { { CannedQuery q("scope-A"); EXPECT_EQ("scope-A", q.scope_id()); EXPECT_EQ("", q.query_string()); EXPECT_EQ("", q.department_id()); } { CannedQuery q("scope-A"); q.set_query_string("foo"); q.set_department_id("dep1"); EXPECT_EQ("scope-A", q.scope_id()); EXPECT_EQ("foo", q.query_string()); EXPECT_EQ("dep1", q.department_id()); } } TEST(CannedQuery, copy) { { CannedQuery a("scope-A", "foo", "dep1"); CannedQuery b(a); EXPECT_EQ(a.scope_id(), b.scope_id()); EXPECT_EQ(a.department_id(), b.department_id()); EXPECT_EQ(a.query_string(), b.query_string()); a.set_query_string("bar"); a.set_department_id("dep2"); EXPECT_EQ("foo", b.query_string()); EXPECT_EQ("dep1", b.department_id()); } { CannedQuery a("scope-A", "foo", "dep1"); CannedQuery b = a; EXPECT_EQ(a.scope_id(), b.scope_id()); EXPECT_EQ(a.department_id(), b.department_id()); EXPECT_EQ(a.query_string(), b.query_string()); a.set_query_string("bar"); a.set_department_id("dep2"); EXPECT_EQ("foo", b.query_string()); EXPECT_EQ("dep1", b.department_id()); } } // test of serialization into a canned query string TEST(CannedQuery, to_string) { { CannedQuery q("scope-A"); q.set_query_string("foo"); q.set_department_id("dep1"); EXPECT_EQ("scope://scope-A?q=foo&department=dep1", q.to_string()); } { CannedQuery q("scope-A"); EXPECT_EQ("scope://scope-A?q=", q.to_string()); } } TEST(CannedQuery, serialize) { CannedQuery q("scope-A"); q.set_query_string("foo"); q.set_department_id("dep1"); auto var = q.serialize(); EXPECT_EQ("scope-A", var["scope"].get_string()); EXPECT_EQ("dep1", var["department_id"].get_string()); EXPECT_EQ("foo", var["query_string"].get_string()); EXPECT_TRUE(var.find("filter_state") != var.end()); } TEST(CannedQuery, deserialize) { { VariantMap vm; vm["scope"] = "scope-A"; vm["query_string"] = "foo"; vm["department_id"] = "dep1"; vm["filter_state"] = Variant(VariantMap()); auto q = internal::CannedQueryImpl::create(vm); EXPECT_EQ("scope-A", q.scope_id()); EXPECT_EQ("foo", q.query_string()); EXPECT_EQ("dep1", q.department_id()); } } TEST(CannedQuery, exceptions) { EXPECT_THROW(CannedQuery(""), unity::InvalidArgumentException); { VariantMap vm; try { // missing 'scope' internal::CannedQueryImpl::create(vm); FAIL(); } catch (unity::InvalidArgumentException const& e) { } vm["scope"] = ""; vm["filter_state"] = Variant(VariantMap()); try { // empty 'scope' not allowed internal::CannedQueryImpl::create(vm); FAIL(); } catch (unity::InvalidArgumentException const& e) { } vm["scope"] = "scope-A"; vm["filter_state"] = Variant(VariantMap()); try { internal::CannedQueryImpl::create(vm); } catch (unity::InvalidArgumentException const& e) { FAIL(); } } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/CannedQuery/CMakeLists.txt0000644000015301777760000000022212320776161027706 0ustar pbusernogroup00000000000000add_executable(CannedQuery_test CannedQuery_test.cpp) target_link_libraries(CannedQuery_test ${TESTLIBS}) add_test(CannedQuery CannedQuery_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/PreviewWidget/0000755000015301777760000000000012320776463025526 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/PreviewWidget/CMakeLists.txt0000644000015301777760000000023412320776161030260 0ustar pbusernogroup00000000000000add_executable(PreviewWidget_test PreviewWidget_test.cpp) target_link_libraries(PreviewWidget_test ${TESTLIBS}) add_test(PreviewWidget PreviewWidget_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/PreviewWidget/PreviewWidget_test.cpp0000644000015301777760000001027512320776161032056 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; TEST(PreviewWidget, basic) { { PreviewWidget w("i1", "image"); w.add_attribute_value("foo", Variant(10)); w.add_attribute_mapping("boo", "bar"); EXPECT_EQ("i1", w.id()); EXPECT_EQ("image", w.widget_type()); EXPECT_EQ(1u, w.attribute_values().size()); EXPECT_EQ(10, w.attribute_values()["foo"].get_int()); EXPECT_EQ(1u, w.attribute_mappings().size()); EXPECT_EQ("bar", w.attribute_mappings()["boo"]); } } TEST(PreviewWidget, to_json) { PreviewWidget w("i1", "image"); w.add_attribute_value("foo", Variant(10)); w.add_attribute_mapping("boo", "bar"); internal::JsonCppNode node(w.data()); EXPECT_EQ("i1", node.get_node("id")->as_string()); EXPECT_EQ("image", node.get_node("type")->as_string()); EXPECT_EQ(10, node.get_node("foo")->as_int()); EXPECT_EQ("bar", node.get_node("components")->get_node("boo")->as_string()); } TEST(PreviewWidget, from_json) { PreviewWidget w(R"({"id": "i1", "type": "header", "title": "foo", "components": {"rating": "boo"}})"); // from json EXPECT_EQ("i1", w.id()); EXPECT_EQ("header", w.widget_type()); EXPECT_EQ("foo", w.attribute_values()["title"].get_string()); EXPECT_EQ("boo", w.attribute_mappings()["rating"]); } TEST(PreviewWidget, exceptions) { { try { PreviewWidget w("", "image"); FAIL(); } catch (unity::InvalidArgumentException const&) {} } { try { PreviewWidget w("id", ""); FAIL(); } catch (unity::InvalidArgumentException const&) {} } { PreviewWidget w("a", "image"); EXPECT_THROW(w.add_attribute_value("id", Variant("x")), unity::InvalidArgumentException); EXPECT_THROW(w.add_attribute_value("type", Variant("x")), unity::InvalidArgumentException); EXPECT_THROW(w.add_attribute_mapping("id", "x"), unity::InvalidArgumentException); EXPECT_THROW(w.add_attribute_mapping("type", "x"), unity::InvalidArgumentException); } } TEST(PreviewWidget, serialize) { { PreviewWidget w("i1", "image"); w.add_attribute_value("foo", Variant(10)); w.add_attribute_mapping("boo", "bar"); auto var = w.serialize(); EXPECT_EQ("i1", var["id"].get_string()); EXPECT_EQ("image", var["type"].get_string()); EXPECT_EQ(10, var["attributes"].get_dict()["foo"].get_int()); EXPECT_EQ("bar", var["components"].get_dict()["boo"].get_string()); } } TEST(PreviewWidget, deserialize) { { VariantMap attrs; attrs["foo"] = "bar"; VariantMap comps; comps["bee"] = "cee"; VariantMap outer; outer["id"] = "i1"; outer["type"] = "image"; outer["attributes"] = Variant(attrs); outer["components"] = Variant(comps); auto w = internal::PreviewWidgetImpl::create(outer); EXPECT_EQ("i1", w.id()); EXPECT_EQ("image", w.widget_type()); EXPECT_EQ(1u, w.attribute_values().size()); EXPECT_EQ("bar", w.attribute_values()["foo"].get_string()); EXPECT_EQ(1u, w.attribute_mappings().size()); EXPECT_EQ("cee", w.attribute_mappings()["bee"]); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Runtime/0000755000015301777760000000000012320776463024364 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Runtime/Zmq.ini.in0000644000015301777760000000007312320776161026234 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Runtime/PusherScope.cpp0000644000015301777760000000422212320776161027323 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "PusherScope.h" #include #include #include #include #include using namespace std; using namespace unity::scopes; class PusherQuery : public SearchQueryBase { public: PusherQuery(int cardinality) : cardinality_(cardinality) { } virtual void cancelled() override { } virtual void run(SearchReplyProxy const& reply) override { auto cat = reply->register_category("cat1", "Category 1", ""); CategorisedResult res(cat); res.set_uri("uri"); res.set_title("title"); res.set_art("art"); res.set_dnd_uri("dnd_uri"); // We push 100 results. we check that last valid push // and the ones following it return false. for (int i = 1; i <= 100; ++i) { EXPECT_EQ(i < cardinality_, reply->push(res)); } } private: int cardinality_; }; int PusherScope::start(string const&, RegistryProxy const &) { return VERSION; } void PusherScope::stop() { } void PusherScope::run() { } SearchQueryBase::UPtr PusherScope::search(CannedQuery const& /* query */, SearchMetadata const& md) { return SearchQueryBase::UPtr(new PusherQuery(md.cardinality())); } PreviewQueryBase::UPtr PusherScope::preview(Result const& /* result */, ActionMetadata const& /* metadata */) { abort(); // Not called } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Runtime/Registry.ini.in0000644000015301777760000000026012320776161027273 0ustar pbusernogroup00000000000000[Registry] Middleware = Zmq Zmq.Endpoint = ipc:///tmp/socket_for_registry Zmq.EndpointDir = /tmp Zmq.ConfigFile = Zmq.ini Scope.InstallDir = /unused Scoperunner.Path = /unused unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Runtime/TestScope.h0000644000015301777760000000224012320776161026437 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: James Henstridge */ #include using namespace std; using namespace unity::scopes; class TestScope : public ScopeBase { public: virtual int start(string const&, RegistryProxy const &) override; virtual void stop() override; virtual void run() override; virtual SearchQueryBase::UPtr search(CannedQuery const &, SearchMetadata const &) override; virtual PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const &) override; }; unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Runtime/TestScope.cpp0000644000015301777760000000576312320776161027007 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: James Henstridge */ #include #include #include #include #include #include #include #include #include "TestScope.h" using namespace std; using namespace unity::scopes; class TestQuery : public SearchQueryBase { public: TestQuery(CannedQuery const& query) : query_(query) { } virtual void cancelled() override { } virtual void run(SearchReplyProxy const& reply) override { Department dep("news", query_, "News"); dep.set_subdepartments({{"subdep1", query_, "Europe"},{"subdep2", query_, "US"}}); reply->register_departments({dep}, "news"); auto cat = reply->register_category("cat1", "Category 1", ""); CategorisedResult res(cat); res.set_uri("uri"); res.set_title("title"); res.set_art("art"); res.set_dnd_uri("dnd_uri"); reply->push(res); CannedQuery query("scope-A", "foo", "dep1"); Annotation annotation(Annotation::Type::Link); annotation.add_link("Link1", query); reply->register_annotation(annotation); } private: CannedQuery query_; }; class TestPreview : public PreviewQueryBase { public: virtual void cancelled() override { } virtual void run(PreviewReplyProxy const& reply) override { PreviewWidgetList widgets; widgets.emplace_back(PreviewWidget(R"({"id": "header", "type": "header", "title": "title", "subtitle": "author", "rating": "rating"})")); widgets.emplace_back(PreviewWidget(R"({"id": "id", "type": "image", "art": "screenshot-url"})")); reply->push(widgets); reply->push("author", Variant("Foo")); reply->push("rating", Variant("Bar")); } }; int TestScope::start(string const&, RegistryProxy const &) { return VERSION; } void TestScope::stop() { } void TestScope::run() { } SearchQueryBase::UPtr TestScope::search(CannedQuery const& query, SearchMetadata const &) { return SearchQueryBase::UPtr(new TestQuery(query)); } PreviewQueryBase::UPtr TestScope::preview(Result const&, ActionMetadata const &) { return PreviewQueryBase::UPtr(new TestPreview()); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Runtime/CMakeLists.txt0000644000015301777760000000055412320776161027123 0ustar pbusernogroup00000000000000configure_file(Registry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Registry.ini) configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini) configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini) add_executable(Runtime_test Runtime_test.cpp TestScope.cpp PusherScope.cpp) target_link_libraries(Runtime_test ${TESTLIBS}) add_test(Runtime Runtime_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Runtime/PusherScope.h0000644000015301777760000000225312320776161026772 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include using namespace std; using namespace unity::scopes; class PusherScope : public ScopeBase { public: virtual int start(string const&, RegistryProxy const &) override; virtual void stop() override; virtual void run() override; virtual SearchQueryBase::UPtr search(CannedQuery const &, SearchMetadata const &) override; virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const& metadata) override; }; unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Runtime/Runtime.ini.in0000644000015301777760000000017412320776161027112 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = Registry Registry.ConfigFile = Registry.ini Default.Middleware = Zmq Zmq.ConfigFile = Zmq.ini unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Runtime/Runtime_test.cpp0000644000015301777760000002202612320776161027547 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "TestScope.h" #include "PusherScope.h" using namespace std; using namespace unity::scopes; TEST(Runtime, basic) { Runtime::UPtr rt = Runtime::create("Runtime.ini"); EXPECT_TRUE(rt->registry().get() != nullptr); rt->destroy(); } class Receiver : public SearchListenerBase { public: Receiver() : query_complete_(false), count_(0), dep_count_(0), annotation_count_(0) { } virtual void push(DepartmentList const& departments, std::string const& current_department_id) override { EXPECT_EQ(current_department_id, "news"); EXPECT_EQ(1u, departments.size()); auto subdeps = departments.front().subdepartments(); EXPECT_EQ(2u, subdeps.size()); EXPECT_EQ("subdep1", subdeps.front().id()); EXPECT_EQ("Europe", subdeps.front().label()); EXPECT_EQ("test", subdeps.front().query().query_string()); EXPECT_EQ("subdep2", subdeps.back().id()); EXPECT_EQ("US", subdeps.back().label()); EXPECT_EQ("test", subdeps.back().query().query_string()); dep_count_++; } virtual void push(CategorisedResult result) override { EXPECT_EQ("uri", result.uri()); EXPECT_EQ("title", result.title()); EXPECT_EQ("art", result.art()); EXPECT_EQ("dnd_uri", result.dnd_uri()); count_++; last_result_ = std::make_shared(result); } virtual void push(Annotation annotation) override { EXPECT_EQ(1u, annotation.links().size()); EXPECT_EQ("Link1", annotation.links().front()->label()); auto query = annotation.links().front()->query(); EXPECT_EQ("scope-A", query.scope_id()); EXPECT_EQ("foo", query.query_string()); EXPECT_EQ("dep1", query.department_id()); annotation_count_++; } virtual void finished(ListenerBase::Reason reason, string const& error_message) override { EXPECT_EQ(Finished, reason); EXPECT_EQ("", error_message); EXPECT_EQ(1, count_); EXPECT_EQ(1, dep_count_); EXPECT_EQ(1, annotation_count_); // Signal that the query has completed. unique_lock lock(mutex_); query_complete_ = true; cond_.notify_one(); } void wait_until_finished() { unique_lock lock(mutex_); cond_.wait(lock, [this] { return this->query_complete_; }); } std::shared_ptr last_result() { return last_result_; } private: bool query_complete_; mutex mutex_; condition_variable cond_; int count_; int dep_count_; int annotation_count_; std::shared_ptr last_result_; }; class PreviewReceiver : public PreviewListenerBase { public: PreviewReceiver() : query_complete_(false), widgets_pushes_(0), data_pushes_(0) { } virtual void push(PreviewWidgetList const& widgets) override { EXPECT_EQ(2u, widgets.size()); widgets_pushes_++; } virtual void push(std::string const& key, Variant const&) override { EXPECT_TRUE(key == "author" || key == "rating"); data_pushes_++; } virtual void push(ColumnLayoutList const&) override { } virtual void finished(ListenerBase::Reason reason, string const& error_message) override { EXPECT_EQ(Finished, reason); EXPECT_EQ("", error_message); EXPECT_EQ(1, widgets_pushes_); EXPECT_EQ(2, data_pushes_); // Signal that the query has completed. unique_lock lock(mutex_); query_complete_ = true; cond_.notify_one(); } void wait_until_finished() { unique_lock lock(mutex_); cond_.wait(lock, [this] { return this->query_complete_; }); } private: bool query_complete_; mutex mutex_; condition_variable cond_; int widgets_pushes_; int data_pushes_; }; class PushReceiver : public SearchListenerBase { public: PushReceiver(int pushes_expected) : query_complete_(false), pushes_expected_(pushes_expected), count_(0) { } virtual void push(CategorisedResult /* result */) override { if (++count_ > pushes_expected_) { FAIL(); } } virtual void finished(ListenerBase::Reason reason, string const& /* error_message */) override { EXPECT_EQ(Finished, reason); EXPECT_EQ(pushes_expected_, count_); // Signal that the query has completed. unique_lock lock(mutex_); query_complete_ = true; cond_.notify_one(); } void wait_until_finished() { unique_lock lock(mutex_); cond_.wait(lock, [this] { return this->query_complete_; }); } private: bool query_complete_; mutex mutex_; condition_variable cond_; atomic_int pushes_expected_; atomic_int count_; }; TEST(Runtime, search) { // connect to scope and run a query auto rt = internal::RuntimeImpl::create("", "Runtime.ini"); auto mw = rt->factory()->create("TestScope", "Zmq", "Zmq.ini"); mw->start(); auto proxy = mw->create_scope_proxy("TestScope"); auto scope = internal::ScopeImpl::create(proxy, rt.get(), "TestScope"); auto receiver = make_shared(); auto ctrl = scope->search("test", SearchMetadata("en", "phone"), receiver); receiver->wait_until_finished(); } TEST(Runtime, preview) { // connect to scope and run a query auto rt = internal::RuntimeImpl::create("", "Runtime.ini"); auto mw = rt->factory()->create("TestScope", "Zmq", "Zmq.ini"); mw->start(); auto proxy = mw->create_scope_proxy("TestScope"); auto scope = internal::ScopeImpl::create(proxy, rt.get(), "TestScope"); // run a query first, so we have a result to preview auto receiver = make_shared(); auto ctrl = scope->search("test", SearchMetadata("pl", "phone"), receiver); receiver->wait_until_finished(); auto result = receiver->last_result(); EXPECT_TRUE(result.get() != nullptr); auto target = result->target_scope_proxy(); EXPECT_TRUE(target != nullptr); auto previewer = make_shared(); auto preview_ctrl = target->preview(*(result.get()), ActionMetadata("en", "phone"), previewer); previewer->wait_until_finished(); } TEST(Runtime, cardinality) { // connect to scope and run a query auto rt = internal::RuntimeImpl::create("", "Runtime.ini"); auto mw = rt->factory()->create("PusherScope", "Zmq", "Zmq.ini"); mw->start(); auto proxy = mw->create_scope_proxy("PusherScope"); auto scope = internal::ScopeImpl::create(proxy, rt.get(), "PusherScope"); // Run a query with unlimited cardinality. We check that the // scope returns 100 results. auto receiver = make_shared(100); scope->search("test", SearchMetadata(100, "unused", "unused"), receiver); receiver->wait_until_finished(); // Run a query with 20 cardinality. We check that we receive only 20 results and, // in the scope, check that push() returns true for the first 19, and false afterwards. receiver = make_shared(20); scope->search("test", SearchMetadata(20, "unused", "unused"), receiver); receiver->wait_until_finished(); } void scope_thread(Runtime::SPtr const& rt) { TestScope scope; rt->run_scope(&scope, "/foo"); } void pusher_thread(Runtime::SPtr const& rt) { PusherScope scope; rt->run_scope(&scope, "/foo"); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); Runtime::SPtr srt = move(Runtime::create_scope_runtime("TestScope", "Runtime.ini")); std::thread scope_t(scope_thread, srt); Runtime::SPtr prt = move(Runtime::create_scope_runtime("PusherScope", "Runtime.ini")); std::thread pusher_t(pusher_thread, prt); auto rc = RUN_ALL_TESTS(); srt->destroy(); scope_t.join(); prt->destroy(); pusher_t.join(); return rc; } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ActivationResponse/0000755000015301777760000000000012320776463026561 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ActivationResponse/ActivationResponse_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ActivationResponse/ActivationResponse_test.c0000644000015301777760000001643112320776161033604 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; TEST(ActivationResponse, basic) { { ActivationResponse resp(ActivationResponse::Status::NotHandled); EXPECT_EQ(ActivationResponse::Status::NotHandled, resp.status()); EXPECT_TRUE(resp.scope_data().is_null()); } { ActivationResponse resp(ActivationResponse::Status::ShowPreview); EXPECT_EQ(ActivationResponse::Status::ShowPreview, resp.status()); EXPECT_TRUE(resp.scope_data().is_null()); } { ActivationResponse resp(ActivationResponse::Status::HideDash); VariantMap var; var["foo"] = "bar"; resp.set_scope_data(Variant(var)); EXPECT_EQ(ActivationResponse::Status::HideDash, resp.status()); EXPECT_EQ(1u, resp.scope_data().get_dict().size()); EXPECT_EQ("bar", resp.scope_data().get_dict()["foo"].get_string()); EXPECT_THROW(resp.query(), unity::LogicException); } { CannedQuery const query("scope-foo"); ActivationResponse resp(query); EXPECT_EQ(ActivationResponse::Status::PerformQuery, resp.status()); } // Search only allowed with CannedQuery { try { ActivationResponse resp(ActivationResponse::Status::PerformQuery); FAIL(); } catch (unity::InvalidArgumentException const&) {} } } TEST(ActivationResponse, serialize) { { ActivationResponse resp(ActivationResponse::Status::HideDash); { VariantMap var; var["foo"] = "bar"; resp.set_scope_data(Variant(var)); } auto var = resp.serialize(); EXPECT_EQ(ActivationResponse::Status::HideDash, static_cast(var["status"].get_int())); EXPECT_EQ("bar", var["scope_data"].get_dict()["foo"].get_string()); } { CannedQuery const query("scope-foo"); ActivationResponse resp(query); auto var = resp.serialize(); EXPECT_EQ(ActivationResponse::Status::PerformQuery, static_cast(var["status"].get_int())); EXPECT_EQ("scope-foo", var["query"].get_dict()["scope"].get_string()); } } TEST(ActivationResponse, deserialize) { // invalid variant { VariantMap var; try { internal::ActivationResponseImpl res(var); FAIL(); } catch (unity::LogicException const &e) { } } // invalid variant - missing 'status' { VariantMap var; var["scope_data"] = VariantMap(); try { internal::ActivationResponseImpl::create(var); FAIL(); } catch (unity::LogicException const &e) { } } // invalid variant - missing 'query' { VariantMap hints; hints["foo"] = "bar"; VariantMap var; var["scope_data"] = hints; var["status"] = static_cast(ActivationResponse::Status::PerformQuery); try { internal::ActivationResponseImpl res(var); FAIL(); } catch (unity::LogicException const &e) {} } // valid variant { VariantMap hints; hints["foo"] = "bar"; VariantMap var; var["scope_data"] = hints; var["status"] = static_cast(ActivationResponse::Status::HideDash); try { internal::ActivationResponseImpl res(var); EXPECT_EQ("bar", res.scope_data().get_dict()["foo"].get_string()); EXPECT_EQ(ActivationResponse::Status::HideDash, res.status()); } catch (unity::LogicException const &e) { FAIL(); } } // valid variant { CannedQuery query("scope-foo"); VariantMap var; var["scope_data"] = VariantMap(); var["status"] = static_cast(ActivationResponse::Status::PerformQuery); var["query"] = query.serialize(); try { internal::ActivationResponseImpl res(var); EXPECT_EQ(ActivationResponse::Status::PerformQuery, res.status()); EXPECT_EQ("scope-foo", res.query().scope_id()); } catch (unity::LogicException const &e) { FAIL(); } } // valid variant { VariantMap var; var["scope_data"] = Variant("foobar"); var["status"] = static_cast(ActivationResponse::Status::HideDash); try { internal::ActivationResponseImpl res(var); EXPECT_EQ("foobar", res.scope_data().get_string()); EXPECT_EQ(ActivationResponse::Status::HideDash, res.status()); } catch (unity::LogicException const &e) { FAIL(); } } } TEST(ActivationResponse, copy_ctor) { { ActivationResponse resp(ActivationResponse::Status::HideDash); ActivationResponse copy(resp); { VariantMap var; var["foo"] = "bar"; resp.set_scope_data(Variant(var)); } { VariantMap var; var["iron"] = "maiden"; copy.set_scope_data(Variant(var)); } EXPECT_EQ(ActivationResponse::Status::HideDash, resp.status()); EXPECT_EQ(ActivationResponse::Status::HideDash, copy.status()); EXPECT_EQ(1u, resp.scope_data().get_dict().size()); EXPECT_EQ("bar", resp.scope_data().get_dict()["foo"].get_string()); EXPECT_EQ(1u, copy.scope_data().get_dict().size()); EXPECT_EQ("maiden", copy.scope_data().get_dict()["iron"].get_string()); } } TEST(ActivationResponse, assign_op_copy) { { ActivationResponse resp(ActivationResponse::Status::HideDash); ActivationResponse copy = resp; { VariantMap var; var["foo"] = "bar"; resp.set_scope_data(Variant(var)); } { VariantMap var; var["iron"] = "maiden"; copy.set_scope_data(Variant(var)); } EXPECT_EQ(ActivationResponse::Status::HideDash, resp.status()); EXPECT_EQ(ActivationResponse::Status::HideDash, copy.status()); EXPECT_EQ(1u, resp.scope_data().get_dict().size()); EXPECT_EQ("bar", resp.scope_data().get_dict()["foo"].get_string()); EXPECT_EQ(1u, copy.scope_data().get_dict().size()); EXPECT_EQ("maiden", copy.scope_data().get_dict()["iron"].get_string()); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ActivationResponse/CMakeLists.txt0000644000015301777760000000026512320776161031317 0ustar pbusernogroup00000000000000add_executable(ActivationResponse_test ActivationResponse_test.cpp) target_link_libraries(ActivationResponse_test ${TESTLIBS}) add_test(ActivationResponse ActivationResponse_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Activation/0000755000015301777760000000000012320776463025042 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Activation/Zmq.ini.in0000644000015301777760000000007312320776161026712 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Activation/Registry.ini.in0000644000015301777760000000026012320776161027751 0ustar pbusernogroup00000000000000[Registry] Middleware = Zmq Zmq.Endpoint = ipc:///tmp/socket_for_registry Zmq.EndpointDir = /tmp Zmq.ConfigFile = Zmq.ini Scope.InstallDir = /unused Scoperunner.Path = /unused unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Activation/TestScope.h0000644000015301777760000000662512320776161027130 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include #include #include #ifndef UNITY_SCOPES_TEST_SCOPE_H #define UNITY_SCOPES_TEST_SCOPE_H namespace unity { namespace scopes { class TestQuery : public SearchQueryBase { public: virtual void cancelled() override {} virtual void run(SearchReplyProxy const& reply) override { auto cat = reply->register_category("cat1", "Category 1", ""); CategorisedResult res(cat); res.set_uri("uri"); res.set_dnd_uri("dnd_uri"); res.set_intercept_activation(); reply->push(res); } }; class TestActivation : public ActivationQueryBase { public: TestActivation(std::string const& hint, std::string const& hint_val, std::string const &uri, Variant const& hints) : hint_key_(hint), hint_val_(hint_val), uri_(uri), recv_hints_(hints) { } virtual ActivationResponse activate() override { ActivationResponse resp(ActivationResponse::Status::ShowDash); VariantMap var; var[hint_key_] = hint_val_; var["received_hints"] = recv_hints_; // send received hints back for testing var["activated_uri"] = uri_; //send activated uri back for testing resp.set_scope_data(Variant(var)); return resp; } private: std::string hint_key_; std::string hint_val_; std::string uri_; Variant recv_hints_; }; class TestScope : public ScopeBase { public: virtual int start(std::string const&, RegistryProxy const &) override { return VERSION; } virtual void stop() override {} virtual void run() override {} virtual SearchQueryBase::UPtr search(CannedQuery const &, SearchMetadata const &) override { return SearchQueryBase::UPtr(new TestQuery()); } virtual PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const &) override { return nullptr; } virtual ActivationQueryBase::UPtr activate(Result const& result, ActionMetadata const& hints) override { return ActivationQueryBase::UPtr(new TestActivation("foo", "bar", result.uri(), hints.scope_data())); } virtual ActivationQueryBase::UPtr perform_action(Result const& result, ActionMetadata const& hints, std::string const& widget_id, std::string const& action_id) override { return ActivationQueryBase::UPtr(new TestActivation("activated action", widget_id + action_id, result.uri(), hints.scope_data())); } }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Activation/CMakeLists.txt0000644000015301777760000000061712320776161027601 0ustar pbusernogroup00000000000000include_directories(${CMAKE_CURRENT_SOURCE_DIR}) configure_file(Registry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Registry.ini) configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini) configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini) add_executable(Activation_test Activation_test.cpp) target_link_libraries(Activation_test ${TESTLIBS}) add_test(Activation Activation_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Activation/Runtime.ini.in0000644000015301777760000000017412320776161027570 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = Registry Registry.ConfigFile = Registry.ini Default.Middleware = Zmq Zmq.ConfigFile = Zmq.ini unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Activation/Activation_test.cpp0000644000015301777760000005535212320776161030713 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; class DummyReceiver : public SearchListenerBase { public: DummyReceiver(std::function push_func) { push_func_ = push_func; }; void push(CategorisedResult result) override { push_func_(result); } void finished(Reason /* r */, std::string const& /* error_message */) override {} std::function push_func_; }; class WaitUntilFinished { public: void wait_until_finished() { std::unique_lock lock(mutex_); cond_.wait(lock, [this] { return this->query_complete_; }); } protected: void notify() { // Signal that the query has completed. std::unique_lock lock(mutex_); query_complete_ = true; cond_.notify_one(); } private: bool query_complete_; std::mutex mutex_; std::condition_variable cond_; }; class SearchReceiver : public SearchListenerBase, public WaitUntilFinished { public: virtual void push(CategorisedResult result) override { this->result = std::make_shared(result); } virtual void finished(ListenerBase::Reason /* reason */, std::string const& /* error_message */) override { notify(); } std::shared_ptr result; }; class ActivationReceiver : public ActivationListenerBase, public WaitUntilFinished { public: virtual void activated(ActivationResponse const& response) override { this->response = std::make_shared(response); } void finished(Reason /* r */, std::string const& /* error_message */) override { notify(); } std::shared_ptr response; }; // helper function to serialize category and result into a dict expected by ResultReplyObject VariantMap serialize_data(Category::SCPtr category, CategorisedResult const& result) { VariantMap var; var["category"] = category->serialize(); var["result"] = result.serialize(); return var; } TEST(Activation, exceptions) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); result.set_dnd_uri("http://canonical.com"); EXPECT_TRUE(result.direct_activation()); result.set_intercept_activation(); EXPECT_FALSE(result.direct_activation()); EXPECT_THROW(result.target_scope_proxy(), unity::LogicException); } } TEST(Activation, direct_activation) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); // activation interception not set { std::shared_ptr received_result; auto df = []() -> void {}; auto runtime = internal::RuntimeImpl::create("", "Runtime.ini"); auto receiver = std::make_shared([&received_result](CategorisedResult result) { received_result.reset(new CategorisedResult(result)); }); internal::ResultReplyObject reply(receiver, runtime.get(), "ipc:///tmp/scope-foo#scope-foo!c=Scope", 0); reply.set_disconnect_function(df); { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); result.set_dnd_uri("http://canonical.com"); // push category and result through ResultReplyObject reply.process_data(serialize_data(cat, result)); } EXPECT_TRUE(received_result != nullptr); EXPECT_TRUE(received_result->direct_activation()); EXPECT_TRUE(received_result->target_scope_proxy()->to_string().find("scope-foo") != std::string::npos); // direct activation, but name is still available } } // direct activation with an aggregator; aggregator scope doesn't store the original result, just passes it TEST(Activation, direct_activation_agg_scope_doesnt_store) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); { std::shared_ptr received_result; auto df = []() -> void {}; auto runtime = internal::RuntimeImpl::create("", "Runtime.ini"); auto receiver = std::make_shared([&received_result](CategorisedResult result) { received_result.reset(new CategorisedResult(result)); }); internal::ResultReplyObject reply(receiver, runtime.get(), "ipc:///tmp/scope-foo#scope-foo!c=Scope", 0); reply.set_disconnect_function(df); { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); result.set_dnd_uri("http://canonical.com"); // push category and result through ResultReplyObject reply.process_data(serialize_data(cat, result)); } EXPECT_TRUE(received_result != nullptr); EXPECT_TRUE(received_result->direct_activation()); EXPECT_TRUE(received_result->target_scope_proxy()->to_string().find("ipc:///tmp/scope-foo#scope-foo!c=Scope") != std::string::npos); // simulate aggregator scope std::shared_ptr agg_received_result; auto aggreceiver = std::make_shared([&agg_received_result](CategorisedResult result) { agg_received_result.reset(new CategorisedResult(result)); }); internal::ResultReplyObject aggreply(aggreceiver, runtime.get(), "ipc:///tmp/scope-bar#scope-bar!c=Scope", 0); aggreply.set_disconnect_function(df); { // push category and unchanged result through ResultReplyObject aggreply.process_data(serialize_data(cat, *received_result)); } EXPECT_TRUE(agg_received_result != nullptr); EXPECT_FALSE(agg_received_result->has_stored_result()); EXPECT_TRUE(agg_received_result->direct_activation()); EXPECT_TRUE(agg_received_result->target_scope_proxy()->to_string().find("scope-foo") != std::string::npos); } } // direct activation with an aggregator; aggregator scope stores the original result TEST(Activation, direct_activation_agg_scope_stores) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); { std::shared_ptr received_result; auto df = []() -> void {}; auto runtime = internal::RuntimeImpl::create("", "Runtime.ini"); auto receiver = std::make_shared([&received_result](CategorisedResult result) { received_result.reset(new CategorisedResult(result)); }); internal::ResultReplyObject reply(receiver, runtime.get(), "ipc:///scope-foo#scope-foo!c=Scope", 0); reply.set_disconnect_function(df); { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); result.set_dnd_uri("http://canonical.com"); // push category and result through ResultReplyObject reply.process_data(serialize_data(cat, result)); } EXPECT_TRUE(received_result != nullptr); EXPECT_TRUE(received_result->direct_activation()); EXPECT_TRUE(received_result->target_scope_proxy()->to_string().find("scope-foo") != std::string::npos); // simulate aggregator scope std::shared_ptr agg_received_result; auto aggreceiver = std::make_shared([&agg_received_result](CategorisedResult result) { agg_received_result.reset(new CategorisedResult(result)); }); internal::ResultReplyObject aggreply(aggreceiver, runtime.get(), "ipc:///scope-bar#scope-bar!c=Scope", 0); aggreply.set_disconnect_function(df); { CategorisedResult outerresult(cat); outerresult.set_uri("http://ubuntu.com/2"); outerresult.set_dnd_uri("http://canonical.com/2"); outerresult.store(*received_result, false); // push category and result through ResultReplyObject aggreply.process_data(serialize_data(cat, outerresult)); } EXPECT_TRUE(agg_received_result != nullptr); EXPECT_TRUE(agg_received_result->has_stored_result()); EXPECT_TRUE(agg_received_result->direct_activation()); // target_scope_proxy points to the leaf scope EXPECT_TRUE(agg_received_result->target_scope_proxy()->to_string().find("scope-foo") != std::string::npos); } } // an aggregator scope just passes the result and doesn't set InterceptActivation TEST(Activation, agg_scope_doesnt_store_and_doesnt_intercept) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); { std::shared_ptr received_result; auto df = []() -> void {}; auto runtime = internal::RuntimeImpl::create("", "Runtime.ini"); auto receiver = std::make_shared([&received_result](CategorisedResult result) { received_result.reset(new CategorisedResult(result)); }); internal::ResultReplyObject reply(receiver, runtime.get(), "ipc:///tmp/scope-foo#scope-foo!c=Scope", 0); reply.set_disconnect_function(df); { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); result.set_dnd_uri("http://canonical.com"); result.set_intercept_activation(); // push category and result through ResultReplyObject reply.process_data(serialize_data(cat, result)); } EXPECT_TRUE(received_result != nullptr); EXPECT_FALSE(received_result->direct_activation()); EXPECT_TRUE(received_result->target_scope_proxy()->to_string().find("scope-foo") != std::string::npos); // simulate aggregator scope std::shared_ptr agg_received_result; auto aggreceiver = std::make_shared([&agg_received_result](CategorisedResult result) { agg_received_result.reset(new CategorisedResult(result)); }); internal::ResultReplyObject aggreply(aggreceiver, runtime.get(), "ipc:///tmp/scope-bar#scope-bar!c=Scope", 0); aggreply.set_disconnect_function(df); { // push category and unchanged result through ResultReplyObject aggreply.process_data(serialize_data(cat, *received_result)); } EXPECT_TRUE(agg_received_result != nullptr); EXPECT_FALSE(agg_received_result->has_stored_result()); EXPECT_FALSE(agg_received_result->direct_activation()); // target_scope_proxy unchanged since aggregator doesn't intercept activation EXPECT_TRUE(agg_received_result->target_scope_proxy()->to_string().find("scope-foo") != std::string::npos); } } // an aggregator scope just passes the result and sets InterceptActivation TEST(Activation, agg_scope_doesnt_store_and_sets_intercept) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); { std::shared_ptr received_result; auto df = []() -> void {}; auto runtime = internal::RuntimeImpl::create("", "Runtime.ini"); auto receiver = std::make_shared([&received_result](CategorisedResult result) { received_result.reset(new CategorisedResult(result)); }); internal::ResultReplyObject reply(receiver, runtime.get(), "ipc:///tmp/scope-foo#scope-foo!c=Scope", 0); reply.set_disconnect_function(df); { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); result.set_dnd_uri("http://canonical.com"); result.set_intercept_activation(); // push category and result through ResultReplyObject reply.process_data(serialize_data(cat, result)); } EXPECT_TRUE(received_result != nullptr); EXPECT_FALSE(received_result->direct_activation()); EXPECT_TRUE(received_result->target_scope_proxy()->to_string().find("scope-foo") != std::string::npos); // simulate aggregator scope std::shared_ptr agg_received_result; auto aggreceiver = std::make_shared([&agg_received_result](CategorisedResult result) { agg_received_result.reset(new CategorisedResult(result)); }); internal::ResultReplyObject aggreply(aggreceiver, runtime.get(), "ipc:///tmp/scope-bar#scope-bar!c=Scope", 0); aggreply.set_disconnect_function(df); { received_result->set_intercept_activation(); // agg scope want to receive activation // push category and unchanged result through ResultReplyObject aggreply.process_data(serialize_data(cat, *received_result)); } EXPECT_TRUE(agg_received_result != nullptr); EXPECT_FALSE(agg_received_result->has_stored_result()); EXPECT_FALSE(agg_received_result->direct_activation()); // target_scope_proxy changed since aggregator intercepts activation EXPECT_TRUE(agg_received_result->target_scope_proxy()->to_string().find("scope-bar") != std::string::npos); } } // an aggregator scope stores the original result but doesn't set InterceptActivation TEST(Activation, agg_scope_stores_and_doesnt_intercept) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); { std::shared_ptr received_result; auto df = []() -> void {}; auto runtime = internal::RuntimeImpl::create("", "Runtime.ini"); auto receiver = std::make_shared([&received_result](CategorisedResult result) { received_result.reset(new CategorisedResult(result)); }); internal::ResultReplyObject reply(receiver, runtime.get(), "ipc:///tmp/scope-foo#scope-foo!c=Scope", 0); reply.set_disconnect_function(df); { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); result.set_dnd_uri("http://canonical.com"); result.set_intercept_activation(); // push category and result through ResultReplyObject reply.process_data(serialize_data(cat, result)); } EXPECT_TRUE(received_result != nullptr); EXPECT_FALSE(received_result->direct_activation()); EXPECT_TRUE(received_result->target_scope_proxy()->to_string().find("scope-foo") != std::string::npos); // simulate aggregator scope std::shared_ptr agg_received_result; auto aggreceiver = std::make_shared([&agg_received_result](CategorisedResult result) { agg_received_result.reset(new CategorisedResult(result)); }); internal::ResultReplyObject aggreply(aggreceiver, runtime.get(), "ipc:///tmp/scope-bar#scope-bar!c=Scope", 0); aggreply.set_disconnect_function(df); { CategorisedResult outerresult(cat); outerresult.set_uri("http://ubuntu.com/2"); outerresult.set_dnd_uri("http://canonical.com/2"); outerresult.store(*received_result, false); // push category and result through ResultReplyObject aggreply.process_data(serialize_data(cat, outerresult)); } EXPECT_TRUE(agg_received_result != nullptr); EXPECT_TRUE(agg_received_result->has_stored_result()); EXPECT_FALSE(agg_received_result->direct_activation()); // target_scope_proxy unchanged since aggregator doesn't intercept activation EXPECT_TRUE(agg_received_result->target_scope_proxy()->to_string().find("scope-foo") != std::string::npos); } } // an aggregator scope stores the original result and sets InterceptActivation TEST(Activation, agg_scope_stores_and_intercepts) { CategoryRegistry reg; CategoryRenderer rdr; auto cat = reg.register_category("1", "title", "icon", rdr); { std::shared_ptr received_result; auto df = []() -> void {}; auto runtime = internal::RuntimeImpl::create("", "Runtime.ini"); auto receiver = std::make_shared([&received_result](CategorisedResult result) { received_result.reset(new CategorisedResult(result)); }); internal::ResultReplyObject reply(receiver, runtime.get(), "ipc:///tmp/scope-foo#scope-foo!c=Scope", 0); reply.set_disconnect_function(df); { CategorisedResult result(cat); result.set_uri("http://ubuntu.com"); result.set_dnd_uri("http://canonical.com"); result.set_intercept_activation(); // push category and result through ResultReplyObject reply.process_data(serialize_data(cat, result)); } EXPECT_TRUE(received_result != nullptr); EXPECT_FALSE(received_result->direct_activation()); EXPECT_TRUE(received_result->target_scope_proxy()->to_string().find("scope-foo") != std::string::npos); // simulate aggregator scope std::shared_ptr agg_received_result; auto aggreceiver = std::make_shared([&agg_received_result](CategorisedResult result) { agg_received_result.reset(new CategorisedResult(result)); }); internal::ResultReplyObject aggreply(aggreceiver, runtime.get(), "ipc:///tmp/scope-bar#scope-bar!c=Scope", 0); aggreply.set_disconnect_function(df); { CategorisedResult outerresult(cat); outerresult.set_uri("http://ubuntu.com/2"); outerresult.set_dnd_uri("http://canonical.com/2"); outerresult.store(*received_result, false); outerresult.set_intercept_activation(); // push category and result through ResultReplyObject aggreply.process_data(serialize_data(cat, outerresult)); } EXPECT_TRUE(agg_received_result != nullptr); EXPECT_TRUE(agg_received_result->has_stored_result()); EXPECT_FALSE(agg_received_result->direct_activation()); // scope changed to agg scope because it intercepts activation EXPECT_TRUE(agg_received_result->target_scope_proxy()->to_string().find("scope-bar") != std::string::npos); } } void scope_thread(Runtime::SPtr const& rt) { TestScope scope; rt->run_scope(&scope, "/"); } // does actual activation with a test scope TEST(Activation, scope) { // parent: connect to scope and run a query auto rt = internal::RuntimeImpl::create("", "Runtime.ini"); auto mw = rt->factory()->create("TestScope", "Zmq", "Zmq.ini"); mw->start(); auto proxy = mw->create_scope_proxy("TestScope"); auto scope = internal::ScopeImpl::create(proxy, rt.get(), "TestScope"); VariantMap hints; auto receiver = std::make_shared(); auto ctrl = scope->search("test", SearchMetadata("pl", "phone"), receiver); receiver->wait_until_finished(); auto result = receiver->result; EXPECT_TRUE(result != nullptr); EXPECT_FALSE(result->direct_activation()); EXPECT_EQ("uri", result->uri()); EXPECT_EQ("dnd_uri", result->dnd_uri()); auto target = result->target_scope_proxy(); EXPECT_TRUE(target != nullptr); EXPECT_TRUE(target->to_string().find("TestScope") != std::string::npos); // activate result { auto act_receiver = std::make_shared(); hints["iron"] = "maiden"; ActionMetadata metadata("C", "phone"); metadata.set_scope_data(Variant(hints)); ctrl = target->activate(*result, metadata, act_receiver); act_receiver->wait_until_finished(); auto response = act_receiver->response; EXPECT_TRUE(response != nullptr); EXPECT_EQ(ActivationResponse::Status::ShowDash, response->status()); EXPECT_EQ("bar", response->scope_data().get_dict()["foo"].get_string()); EXPECT_EQ("maiden", response->scope_data().get_dict()["received_hints"].get_dict()["iron"].get_string()); EXPECT_EQ("uri", response->scope_data().get_dict()["activated_uri"].get_string()); } // activate action { auto act_receiver = std::make_shared(); ActionMetadata meta("en", "phone"); hints["iron"] = "maiden"; meta.set_scope_data(Variant(hints)); ctrl = target->perform_action(*result, meta, "widget1", "action1", act_receiver); act_receiver->wait_until_finished(); auto response = act_receiver->response; EXPECT_TRUE(response != nullptr); EXPECT_EQ(ActivationResponse::Status::ShowDash, response->status()); EXPECT_EQ("widget1action1", response->scope_data().get_dict()["activated action"].get_string()); EXPECT_EQ("maiden", response->scope_data().get_dict()["received_hints"].get_dict()["iron"].get_string()); EXPECT_EQ("uri", response->scope_data().get_dict()["activated_uri"].get_string()); } } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); Runtime::SPtr rt = move(Runtime::create_scope_runtime("TestScope", "Runtime.ini")); std::thread scope_t(scope_thread, rt); auto rc = RUN_ALL_TESTS(); rt->destroy(); scope_t.join(); return rc; } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ColumnLayout/0000755000015301777760000000000012320776463025374 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ColumnLayout/CMakeLists.txt0000644000015301777760000000022712320776161030130 0ustar pbusernogroup00000000000000add_executable(ColumnLayout_test ColumnLayout_test.cpp) target_link_libraries(ColumnLayout_test ${TESTLIBS}) add_test(ColumnLayout ColumnLayout_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ColumnLayout/ColumnLayout_test.cpp0000644000015301777760000000573612320776161031600 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; TEST(ColumnLayout, basic) { { ColumnLayout cl(1); EXPECT_EQ(1, cl.number_of_columns()); EXPECT_EQ(0, cl.size()); cl.add_column({"widget1", "widget2"}); EXPECT_EQ(1, cl.number_of_columns()); EXPECT_EQ(1, cl.size()); EXPECT_EQ(2u, cl.column(0).size()); EXPECT_EQ("widget1", cl.column(0)[0]); } { ColumnLayout cl(2); EXPECT_EQ(2, cl.number_of_columns()); EXPECT_EQ(0, cl.size()); cl.add_column({"widget1", "widget2"}); cl.add_column({"widget3"}); EXPECT_EQ(2, cl.number_of_columns()); EXPECT_EQ(2, cl.size()); EXPECT_EQ("widget1", cl.column(0)[0]); EXPECT_EQ("widget2", cl.column(0)[1]); EXPECT_EQ("widget3", cl.column(1)[0]); } } TEST(ColumnLayout, exceptions) { { ColumnLayout cl(1); cl.add_column({"widget1", "widget2"}); EXPECT_THROW(cl.column(1), unity::InvalidArgumentException); EXPECT_THROW(cl.add_column({"widget3"}), unity::LogicException); EXPECT_EQ(1, cl.size()); } { VariantMap var; EXPECT_THROW(ColumnLayoutImpl::create(var), unity::InvalidArgumentException); } } TEST(ColumnLayout, serialize) { { ColumnLayout cl(1); cl.add_column({"widget1", "widget2"}); auto var = cl.serialize(); auto outer = var["column_data"]; EXPECT_EQ(1u, outer.get_array().size()); auto inner = outer.get_array()[0]; EXPECT_EQ(2u, inner.get_array().size()); } } TEST(ColumnLayout, deserialize) { { VariantArray outer; VariantArray inner({Variant("widget1"), Variant("widget2")}); outer.push_back(Variant(inner)); VariantMap var; var["column_data"] = Variant(outer); auto layout = ColumnLayoutImpl::create(var); EXPECT_EQ(1, layout.size()); EXPECT_EQ(1, layout.number_of_columns()); EXPECT_EQ(2u, layout.column(0).size()); EXPECT_EQ("widget1", layout.column(0)[0]); EXPECT_EQ("widget2", layout.column(0)[1]); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Department/0000755000015301777760000000000012320776463025044 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Department/Department_test.cpp0000644000015301777760000000451512320776161030712 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; TEST(Department, basic) { CannedQuery query("fooscope", "foo", "dep1"); Department dep(query, "News"); EXPECT_EQ("dep1", dep.id()); EXPECT_EQ("dep1", dep.query().department_id()); EXPECT_EQ("fooscope", dep.query().scope_id()); EXPECT_EQ("News", dep.label()); dep.set_subdepartments({{"subdep1", query, "Europe"}}); EXPECT_EQ(1u, dep.subdepartments().size()); EXPECT_EQ("subdep1", dep.subdepartments().front().id()); EXPECT_EQ("subdep1", dep.subdepartments().front().query().department_id()); EXPECT_EQ("Europe", dep.subdepartments().front().label()); } TEST(Department, serialize_and_deserialize) { VariantMap var; { CannedQuery query("fooscope", "foo", "dep1"); Department dep(query, "News"); dep.set_subdepartments({{"subdep1", query, "Europe"},{"subdep2", query, "US"}}); var = dep.serialize(); } // deserialize back auto dep2 = internal::DepartmentImpl::create(var); EXPECT_EQ("dep1", dep2.id()); EXPECT_EQ("dep1", dep2.query().department_id()); EXPECT_EQ("fooscope", dep2.query().scope_id()); EXPECT_EQ("News", dep2.label()); EXPECT_EQ(2u, dep2.subdepartments().size()); EXPECT_EQ("subdep1", dep2.subdepartments().front().id()); EXPECT_EQ("subdep1", dep2.subdepartments().front().query().department_id()); EXPECT_EQ("Europe", dep2.subdepartments().front().label()); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Department/CMakeLists.txt0000644000015301777760000000021512320776161027575 0ustar pbusernogroup00000000000000add_executable(Department_test Department_test.cpp) target_link_libraries(Department_test ${TESTLIBS}) add_test(Department Department_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/0000755000015301777760000000000012320776463024416 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/Statistics/0000755000015301777760000000000012320776463026550 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/Statistics/config.h.in0000644000015301777760000000202712320776161030567 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CONFIG_H #define CONFIG_H #include namespace testing { double parse_double_from_cmake_variable() { std::stringstream ss{"@STATISTICS_TEST_CONFIDENCE_LEVEL@"}; double result; ss >> result; return result; } const double alpha { 1. - parse_double_from_cmake_variable() }; } // namespace testing #endif unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/Statistics/Statistics_test.cpp0000644000015301777760000001633212320776161032445 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace acc = boost::accumulators; namespace { struct Sample : public unity::scopes::testing::Sample { std::vector raw; double mean; double variance; std::size_t get_size() const { return raw.size(); } ValueType get_mean() const { return mean; } ValueType get_variance() const { return variance; } void enumerate(const Enumerator& enumerator) const { for (const auto& observation : raw) { enumerator(observation); } } }; typedef std::chrono::duration Microseconds; typedef acc::accumulator_set< Microseconds::rep, acc::stats< acc::tag::count, acc::tag::mean, acc::tag::variance > > Statistics; template Sample a_sample_of_size(std::size_t size, Sampler sampler) { Statistics stats { acc::tag::density::num_bins = 10, acc::tag::density::cache_size = 10 }; Sample sample; sample.raw.resize(size); sample.mean = -1.f; sample.variance = -1.f; for (std::size_t i = 0; i < size; i++) { auto s = sampler(); sample.raw[i] = s; stats(s); } sample.mean = acc::mean(stats); sample.variance = acc::variance(stats); return sample; } Sample a_normally_distributed_sample(std::size_t size, double mean = 0, double variance = 1) { std::random_device rd; std::mt19937 gen(rd()); gen.seed(42); std::normal_distribution<> normal(mean, variance); return a_sample_of_size(size, [&]() { return normal(gen); }); } Sample a_uniformly_distributed_sample(std::size_t size) { std::random_device rd; std::mt19937 gen(rd()); gen.seed(); std::uniform_real_distribution<> uniform; return a_sample_of_size(size, [&]() { return uniform(gen); }); } } TEST(StudentsTTestOneSample, eq_is_detected_correctly) { auto r1 = a_normally_distributed_sample(10000, 0, 1); auto result = unity::scopes::testing::StudentsTTest().one_sample(r1, 0., 1.); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::not_rejected, result.both_means_are_equal(::testing::alpha)); } TEST(StudentsTTestOneSample, lt_is_detected_correctly) { auto r1 = a_normally_distributed_sample(10000, 0, 1); auto result = unity::scopes::testing::StudentsTTest().one_sample(r1, 2., 1.); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::rejected, result.both_means_are_equal(::testing::alpha)); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::not_rejected, result.sample1_mean_lt_sample2_mean(::testing::alpha)); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::rejected, result.sample1_mean_gt_sample2_mean(::testing::alpha)); } TEST(StudentsTTestOneSample, gt_is_detected_correctly) { auto r1 = a_normally_distributed_sample(10000, 2, 1); auto result = unity::scopes::testing::StudentsTTest().one_sample(r1, 0., 1.); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::rejected, result.both_means_are_equal(::testing::alpha)); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::rejected, result.sample1_mean_lt_sample2_mean(::testing::alpha)); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::not_rejected, result.sample1_mean_gt_sample2_mean(::testing::alpha)); } TEST(StudentsTTestTwoSample, eq_is_detected_correctly) { auto r1 = a_normally_distributed_sample(10000, 0, 1); auto r2 = a_normally_distributed_sample(10000, 0, 1); auto result = unity::scopes::testing::StudentsTTest().two_independent_samples(r1, r2); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::not_rejected, result.both_means_are_equal(::testing::alpha)); } TEST(StudentsTTestTwoSample, lt_is_detected_correctly) { auto r1 = a_normally_distributed_sample(10000, 0, 1); auto r2 = a_normally_distributed_sample(10000, 2, 1); auto result = unity::scopes::testing::StudentsTTest().two_independent_samples(r1, r2); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::rejected, result.both_means_are_equal(::testing::alpha)); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::not_rejected, result.sample1_mean_lt_sample2_mean(::testing::alpha)); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::rejected, result.sample1_mean_gt_sample2_mean(::testing::alpha)); } TEST(StudentsTTestTwoSample, gt_is_detected_correctly) { auto r1 = a_normally_distributed_sample(10000, 2, 1); auto r2 = a_normally_distributed_sample(10000, 0, 1); auto result = unity::scopes::testing::StudentsTTest().two_independent_samples(r1, r2); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::rejected, result.both_means_are_equal(::testing::alpha)); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::rejected, result.sample1_mean_lt_sample2_mean(::testing::alpha)); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::not_rejected, result.sample1_mean_gt_sample2_mean(::testing::alpha)); } TEST(AndersonDarlingTest, responds_with_not_rejected_for_data_from_normal_distribution) { auto result = a_normally_distributed_sample(1000); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::not_rejected, unity::scopes::testing::AndersonDarlingTest() .for_normality(result) .data_fits_normal_distribution( unity::scopes::testing::Confidence::zero_point_five_percent)); } TEST(AndersonDarlingTest, responds_with_rejected_for_data_from_uniform_distribution) { auto result = a_uniformly_distributed_sample(1000); EXPECT_EQ(unity::scopes::testing::HypothesisStatus::rejected, unity::scopes::testing::AndersonDarlingTest() .for_normality(result) .data_fits_normal_distribution( unity::scopes::testing::Confidence::zero_point_five_percent)); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/Statistics/CMakeLists.txt0000644000015301777760000000063612320776161031310 0ustar pbusernogroup00000000000000set( STATISTICS_TEST_CONFIDENCE_LEVEL 0.95 CACHE STRING "Confidence level for statistical evaluation.") configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_executable(Statistics_test Statistics_test.cpp) target_link_libraries(Statistics_test ${TESTLIBS}) add_test(Statistics Statistics_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScope/0000755000015301777760000000000012320776463027154 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScope/scope.h0000644000015301777760000000341212320776161030431 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: James Henstridge * Thomas Voß */ #include namespace testing { class Scope : public unity::scopes::ScopeBase { public: int start(std::string const&, unity::scopes::RegistryProxy const &) override; void stop() override; void run() override; unity::scopes::SearchQueryBase::UPtr search( unity::scopes::CannedQuery const &, unity::scopes::SearchMetadata const &) override; unity::scopes::ActivationQueryBase::UPtr activate( unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata) override; unity::scopes::ActivationQueryBase::UPtr perform_action( unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata, std::string const& widget_id, std::string const& action_id) override; unity::scopes::PreviewQueryBase::UPtr preview( unity::scopes::Result const&, unity::scopes::ActionMetadata const &) override; }; } // namespace testing unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScope/scope.cpp0000644000015301777760000001120212320776161030760 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: James Henstridge * Thomas Voß */ #include #include #include #include #include #include #include #include #include "scope.h" #include namespace testing { class ActivationShowingDash : public unity::scopes::ActivationQueryBase { public: ActivationShowingDash() { } unity::scopes::ActivationResponse activate() override { std::this_thread::sleep_for(std::chrono::milliseconds{500}); return unity::scopes::ActivationResponse{unity::scopes::ActivationResponse::ShowDash}; } }; class LongRunningActivation : public unity::scopes::ActivationQueryBase { public: LongRunningActivation() { } unity::scopes::ActivationResponse activate() override { return unity::scopes::ActivationResponse{unity::scopes::ActivationResponse::ShowDash}; } }; class Query : public unity::scopes::SearchQueryBase { public: Query(unity::scopes::CannedQuery const& query) : query_(query) { } void cancelled() override { } void run(unity::scopes::SearchReplyProxy const& reply) override { unity::scopes::Department dep("news", query_, "News"); dep.set_subdepartments({{"subdep1", query_, "Europe"},{"subdep2", query_, "US"}}); reply->register_departments({dep}, "news"); auto cat = reply->register_category("cat1", "Category 1", ""); unity::scopes::CategorisedResult res(cat); res.set_uri("uri"); res.set_title("title"); res.set_art("art"); res.set_dnd_uri("dnd_uri"); reply->push(res); unity::scopes::CannedQuery query("scope-A", "foo", "dep1"); unity::scopes::Annotation annotation(unity::scopes::Annotation::Type::Link); annotation.add_link("Link1", query); reply->register_annotation(annotation); } private: unity::scopes::CannedQuery query_; }; class Preview : public unity::scopes::PreviewQueryBase { public: void cancelled() override { } void run(unity::scopes::PreviewReplyProxy const& reply) override { unity::scopes::PreviewWidgetList widgets; widgets.emplace_back(unity::scopes::PreviewWidget(R"({"id": "header", "type": "header", "title": "title", "subtitle": "author", "rating": "rating"})")); widgets.emplace_back(unity::scopes::PreviewWidget(R"({"id": "id", "type": "image", "art": "screenshot-url"})")); reply->push(widgets); reply->push("author", unity::scopes::Variant("Foo")); reply->push("rating", unity::scopes::Variant("Bar")); } }; } // namespace testing int testing::Scope::start(std::string const&, unity::scopes::RegistryProxy const &) { return VERSION; } void testing::Scope::stop() { } void testing::Scope::run() { } unity::scopes::SearchQueryBase::UPtr testing::Scope::search( unity::scopes::CannedQuery const& query, unity::scopes::SearchMetadata const &) { return unity::scopes::SearchQueryBase::UPtr(new testing::Query(query)); } unity::scopes::ActivationQueryBase::UPtr testing::Scope::activate( unity::scopes::Result const&, unity::scopes::ActionMetadata const&) { return unity::scopes::ActivationQueryBase::UPtr{new testing::ActivationShowingDash()}; } unity::scopes::ActivationQueryBase::UPtr testing::Scope::perform_action( unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::string const&, std::string const&) { return unity::scopes::ActivationQueryBase::UPtr{new testing::LongRunningActivation()}; } unity::scopes::PreviewQueryBase::UPtr testing::Scope::preview( unity::scopes::Result const&, unity::scopes::ActionMetadata const &) { return unity::scopes::PreviewQueryBase::UPtr(new testing::Preview()); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScope/CMakeLists.txt0000644000015301777760000000024612320776161031711 0ustar pbusernogroup00000000000000add_executable(IsolatedScope_test IsolatedScope_test.cpp scope.cpp) target_link_libraries(IsolatedScope_test ${TESTLIBS}) add_test(IsolatedScope IsolatedScope_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScope/IsolatedScope_test.cpp0000644000015301777760000001171312320776161033453 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include #include #include #include #include #include "scope.h" namespace { typedef unity::scopes::testing::TypedScopeFixture TestScopeFixture; static const std::string scope_id{"does.not.exist.scope"}; static const std::string scope_query_string{"does.not.exist.scope.query_string"}; static const std::string default_locale{"C"}; static const std::string default_form_factor{"SuperDuperPhablet"}; } TEST(Category, construction_passes_on_arguments) { const std::string id{"does.not.exist.id"}; const std::string title{"does.not.exist.title"}; const std::string icon{"does.not.exist.icon"}; const unity::scopes::CategoryRenderer renderer{}; unity::scopes::testing::Category category { id, title, icon, renderer }; EXPECT_EQ(id, category.id()); EXPECT_EQ(title, category.title()); EXPECT_EQ(icon, category.icon()); EXPECT_EQ(renderer, category.renderer_template()); } TEST(ScopeMetadataBuilder, construction_in_case_of_missing_mandatory_arguments_aborts) { unity::scopes::testing::ScopeMetadataBuilder builder; builder.scope_id(scope_id) .display_name("does.not.exist.display_name") .description("does.not.exist.description"); EXPECT_EXIT(builder(), ::testing::KilledBySignal(SIGABRT), ".*"); } TEST_F(TestScopeFixture, creating_a_search_query_and_checking_for_pushed_results_works) { using namespace ::testing; const std::string id{"does.not.exist.id"}; const std::string title{"does.not.exist.title"}; const std::string icon{"does.not.exist.icon"}; const unity::scopes::CategoryRenderer renderer{}; NiceMock reply; EXPECT_CALL(reply, register_departments(_, _)).Times(1); EXPECT_CALL(reply, register_category(_, _, _, _)) .Times(1) .WillOnce( Return( unity::scopes::Category::SCPtr { new unity::scopes::testing::Category { id, title, icon, renderer } })); EXPECT_CALL(reply, register_annotation(_)) .Times(1) .WillOnce(Return(true)); EXPECT_CALL(reply, push(_)) .Times(1) .WillOnce(Return(true)); unity::scopes::SearchReplyProxy search_reply_proxy { &reply, [](unity::scopes::SearchReply*) {} }; unity::scopes::CannedQuery query{scope_id}; query.set_query_string(scope_query_string); unity::scopes::SearchMetadata meta_data{default_locale, default_form_factor}; auto search_query = scope->search(query, meta_data); ASSERT_NE(nullptr, search_query); search_query->run(search_reply_proxy); } TEST_F(TestScopeFixture, activating_a_result_works) { using namespace ::testing; unity::scopes::ActionMetadata meta_data{default_locale, default_form_factor}; unity::scopes::testing::Result result; auto activation = scope->activate(result, meta_data); EXPECT_NE(nullptr, activation); EXPECT_EQ(unity::scopes::ActivationResponse::ShowDash, activation->activate().status()); } TEST_F(TestScopeFixture, performing_an_action_works) { using namespace ::testing; static const std::string action_id{"action"}; static const std::string widget_id{"widget"}; unity::scopes::ActionMetadata meta_data{default_locale, default_form_factor}; unity::scopes::testing::Result result; auto activation = scope->perform_action( result, meta_data, widget_id, action_id); EXPECT_NE(nullptr, activation); EXPECT_EQ(unity::scopes::ActivationResponse::ShowDash, activation->activate().status()); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/CMakeLists.txt0000644000015301777760000000020312320776161027144 0ustar pbusernogroup00000000000000add_subdirectory(IsolatedScope) if (${slowtests}) add_subdirectory(IsolatedScopeBenchmark) endif() add_subdirectory(Statistics)unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScopeBenchmark/0000755000015301777760000000000012320776463030767 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.h0000644000015301777760000000372612320776161032254 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: James Henstridge * Thomas Voß */ #include #include #include namespace testing { class Scope : public unity::scopes::ScopeBase { public: Scope(const std::chrono::milliseconds& mean, const std::chrono::milliseconds& variance); int start(std::string const&, unity::scopes::RegistryProxy const &) override; void stop() override; void run() override; unity::scopes::SearchQueryBase::UPtr search( unity::scopes::CannedQuery const &, unity::scopes::SearchMetadata const &) override; unity::scopes::ActivationQueryBase::UPtr activate( unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata) override; unity::scopes::ActivationQueryBase::UPtr perform_action( unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata, std::string const& widget_id, std::string const& action_id) override; unity::scopes::PreviewQueryBase::UPtr preview( unity::scopes::Result const&, unity::scopes::ActionMetadata const &) override; protected: std::mt19937 gen; std::normal_distribution<> normal; }; } // namespace testing unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScopeBenchmark/config.h.in0000644000015301777760000000220012320776161032777 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CONFIG_H #define CONFIG_H #include namespace testing { double parse_double_from_cmake_variable() { std::stringstream ss{"@BENCHMARKING_TEST_CONFIDENCE_LEVEL@"}; double result; ss >> result; return result; } const double alpha { 1. - parse_double_from_cmake_variable() }; constexpr const char* reference_result_file { "@CMAKE_CURRENT_SOURCE_DIR@/reference_result.xml" }; } // namespace testing #endif unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.cpp0000644000015301777760000001177112320776161032606 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: James Henstridge * Thomas Voß */ #include #include #include #include #include #include #include #include #include "scope.h" #include namespace testing { struct ActivationShowingDash : public unity::scopes::ActivationQueryBase { std::mt19937& gen; std::normal_distribution<>& normal; ActivationShowingDash(std::mt19937& gen, std::normal_distribution<>& normal) : gen(gen), normal(normal) { } unity::scopes::ActivationResponse activate() override { std::this_thread::sleep_for( std::chrono::milliseconds { static_cast(normal(gen)) }); return unity::scopes::ActivationResponse{unity::scopes::ActivationResponse::ShowDash}; } }; struct LongRunningActivation : public unity::scopes::ActivationQueryBase { std::mt19937& gen; std::normal_distribution<>& normal; LongRunningActivation(std::mt19937& gen, std::normal_distribution<>& normal) : gen(gen), normal(normal) { } unity::scopes::ActivationResponse activate() override { std::this_thread::sleep_for( std::chrono::milliseconds { static_cast(normal(gen)) }); return unity::scopes::ActivationResponse{unity::scopes::ActivationResponse::ShowDash}; } }; struct Query : public unity::scopes::SearchQueryBase { std::mt19937& gen; std::normal_distribution<>& normal; Query(std::mt19937& gen, std::normal_distribution<>& normal) : gen(gen), normal(normal) { } void cancelled() override { } void run(unity::scopes::SearchReplyProxy const&) override { std::this_thread::sleep_for( std::chrono::milliseconds { static_cast(normal(gen)) }); } }; struct Preview : public unity::scopes::PreviewQueryBase { std::mt19937& gen; std::normal_distribution<>& normal; Preview(std::mt19937& gen, std::normal_distribution<>& normal) : gen(gen), normal(normal) { } void cancelled() override { } void run(unity::scopes::PreviewReplyProxy const&) override { std::this_thread::sleep_for( std::chrono::milliseconds { static_cast(normal(gen)) }); } }; } // namespace testing testing::Scope::Scope( const std::chrono::milliseconds& mean, const std::chrono::milliseconds& variance) : gen(0), normal(mean.count(), variance.count()) { } int testing::Scope::start(std::string const&, unity::scopes::RegistryProxy const &) { return VERSION; } void testing::Scope::stop() { } void testing::Scope::run() { } unity::scopes::SearchQueryBase::UPtr testing::Scope::search( unity::scopes::CannedQuery const&, unity::scopes::SearchMetadata const &) { return unity::scopes::SearchQueryBase::UPtr{new testing::Query(gen, normal)}; } unity::scopes::ActivationQueryBase::UPtr testing::Scope::activate( unity::scopes::Result const&, unity::scopes::ActionMetadata const&) { return unity::scopes::ActivationQueryBase::UPtr{new testing::ActivationShowingDash(gen, normal)}; } unity::scopes::ActivationQueryBase::UPtr testing::Scope::perform_action( unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::string const&, std::string const&) { return unity::scopes::ActivationQueryBase::UPtr{new testing::LongRunningActivation(gen, normal)}; } unity::scopes::PreviewQueryBase::UPtr testing::Scope::preview( unity::scopes::Result const&, unity::scopes::ActionMetadata const &) { return unity::scopes::PreviewQueryBase::UPtr{new testing::Preview(gen, normal)}; } ././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScopeBenchmark/reference_result.xmlunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScopeBenchmark/reference_res0000644000015301777760000000752412320776161033524 0ustar pbusernogroup00000000000000 25 0.064717161999999995 0.14149899499999999 0.10772000999999999 0.019595591480048233 -0.49701807910641982 -0.33652909226963756 25 0 0.123679945 0.10672701699999999 0.101793199 0.102323816 0.072440738000000005 0.130526225 0.095372340999999999 0.098436177 0.097431814000000005 0.064717161999999995 0.099288761000000003 0.12833877399999999 0.122781996 0.093433830999999995 0.124227929 0.073763796000000006 0.108859318 0.098337763999999994 0.12838344400000001 0.097912972000000001 0.14149899499999999 0.105334833 0.113452682 0.13246867700000001 0.13146804400000001 12 0 0.058136255699999993 0 0.064717161999999995 0.040000000000000001 0.071298068299999989 0.080000000000000002 0.077878974599999998 0 0.084459880899999992 0 0.091040787200000001 0.12 0.097621693499999995 0.23999999999999999 0.10420259979999999 0.12 0.11078350609999998 0.040000000000000001 0.11736441239999999 0.080000000000000002 0.1239453187 0.12 0.130526225 0.16 ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScopeBenchmark/IsolatedScopeBenchmark_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScopeBenchmark/IsolatedScope0000644000015301777760000003272112320776161033450 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include #include #include "config.h" #include "scope.h" #include #include #include namespace { std::chrono::milliseconds mean{100}; std::chrono::milliseconds variance{20}; } namespace unity { namespace scopes { namespace testing { template<> struct ScopeTraits<::testing::Scope> { inline static const char* name() { return "BenchmarkingScope"; } inline static std::shared_ptr<::testing::Scope> construct() { return std::make_shared<::testing::Scope>(mean, variance); } }; } } } namespace { typedef unity::scopes::testing::TypedScopeFixture BenchmarkScopeFixture; static const std::string scope_id{"does.not.exist.scope"}; static const std::string scope_query_string{"does.not.exist.scope.query_string"}; static const std::string default_locale{"C"}; static const std::string default_form_factor{"SuperDuperPhablet"}; std::pair< unity::scopes::testing::Benchmark::Result::Timing::Seconds, unity::scopes::testing::Benchmark::Result::Timing::Seconds > reference_query_performance() { return std::make_pair( unity::scopes::testing::Benchmark::Result::Timing::Seconds { mean }, unity::scopes::testing::Benchmark::Result::Timing::Seconds { std::sqrt(variance.count()) // We have to consider std. dev. for the statistical test. }); } std::pair< unity::scopes::testing::Benchmark::Result::Timing::Seconds, unity::scopes::testing::Benchmark::Result::Timing::Seconds > reference_preview_performance() { return std::make_pair( unity::scopes::testing::Benchmark::Result::Timing::Seconds { mean }, unity::scopes::testing::Benchmark::Result::Timing::Seconds { std::sqrt(variance.count()) // We have to consider std. dev. for the statistical test. }); } std::pair< unity::scopes::testing::Benchmark::Result::Timing::Seconds, unity::scopes::testing::Benchmark::Result::Timing::Seconds > reference_activation_performance() { return std::make_pair( unity::scopes::testing::Benchmark::Result::Timing::Seconds { mean }, unity::scopes::testing::Benchmark::Result::Timing::Seconds { std::sqrt(variance.count()) // We have to consider std. dev. for the statistical test. }); } std::pair< unity::scopes::testing::Benchmark::Result::Timing::Seconds, unity::scopes::testing::Benchmark::Result::Timing::Seconds > reference_action_performance() { return std::make_pair( unity::scopes::testing::Benchmark::Result::Timing::Seconds { mean }, unity::scopes::testing::Benchmark::Result::Timing::Seconds { std::sqrt(variance.count()) // We have to consider std. dev. for the statistical test. }); } } TEST(BenchmarkResult, saving_and_loading_works) { const std::string fn{"test.result"}; std::remove(fn.c_str()); unity::scopes::testing::Benchmark::Result reference; reference.sample_size = 100; { std::ofstream out{fn.c_str()}; ASSERT_NO_THROW(reference.save_to(out)); } { unity::scopes::testing::Benchmark::Result result; std::ifstream in{fn.c_str()}; ASSERT_NO_THROW(result.load_from(in)); EXPECT_EQ(reference, result); } } TEST(BenchmarkResultXml, saving_and_loading_works) { const std::string fn{"test.result"}; std::remove(fn.c_str()); unity::scopes::testing::Benchmark::Result reference; reference.sample_size = std::rand(); { std::ofstream out{fn.c_str()}; ASSERT_NO_THROW(reference.save_to_xml(out)); } { unity::scopes::testing::Benchmark::Result result; std::ifstream in{fn.c_str()}; ASSERT_NO_THROW(result.load_from_xml(in)); EXPECT_EQ(reference, result); } } // This test relies on real world benchmarking data from previous runs to // ensure that the performance of the system does not degrade. For that, we work // under the hypothesis that a change will not result in any significant change in // performance. If it does result in a change, we fail the test and either have to // investigate why the performance degraded or take the new results as our new // performance baseline. TEST_F(BenchmarkScopeFixture, benchmarking_a_scope_query_performance_oop_works) { unity::scopes::testing::OutOfProcessBenchmark benchmark; unity::scopes::testing::Benchmark::Result reference_result; { std::ifstream in{testing::reference_result_file}; reference_result.load_from_xml(in); } unity::scopes::CannedQuery query{scope_id}; query.set_query_string(scope_query_string); unity::scopes::SearchMetadata meta_data{default_locale, default_form_factor}; unity::scopes::testing::Benchmark::QueryConfiguration config; config.sampler = [query, meta_data]() { return std::make_pair(query, meta_data); }; auto result = benchmark.for_query(scope, config); // We store the potential new reference such that we can copy over if // the last test fails. std::ofstream out{"ref.xml"}; result.save_to_xml(out); EXPECT_FALSE(result.timing.is_significantly_faster_than_reference(reference_result.timing)); EXPECT_FALSE(result.timing.is_significantly_slower_than_reference(reference_result.timing)); } TEST_F(BenchmarkScopeFixture, benchmarking_a_scope_preview_performance_oop_works) { unity::scopes::testing::OutOfProcessBenchmark benchmark; unity::scopes::testing::Result search_result; unity::scopes::ActionMetadata meta_data{default_locale, default_form_factor}; unity::scopes::testing::Benchmark::PreviewConfiguration config; config.sampler = [search_result, meta_data]() { return std::make_pair(search_result, meta_data); }; auto result = benchmark.for_preview(scope, config); auto reference = reference_preview_performance(); EXPECT_FALSE(result.timing.is_significantly_faster_than_reference( reference.first.count(), reference.second.count())); EXPECT_FALSE(result.timing.is_significantly_slower_than_reference( reference.first.count(), reference.second.count())); } TEST_F(BenchmarkScopeFixture, benchmarking_a_scope_activation_performance_oop_works) { unity::scopes::testing::OutOfProcessBenchmark benchmark; unity::scopes::testing::Result search_result; unity::scopes::ActionMetadata meta_data{default_locale, default_form_factor}; unity::scopes::testing::Benchmark::ActivationConfiguration config; config.sampler = [search_result, meta_data]() { return std::make_pair(search_result, meta_data); }; auto result = benchmark.for_activation(scope, config); auto reference = reference_activation_performance(); EXPECT_FALSE(result.timing.is_significantly_faster_than_reference( reference.first.count(), reference.second.count())); EXPECT_FALSE(result.timing.is_significantly_slower_than_reference( reference.first.count(), reference.second.count())); } TEST_F(BenchmarkScopeFixture, benchmarking_a_scope_action_performance_oop_works) { unity::scopes::testing::InProcessBenchmark benchmark; unity::scopes::testing::Result search_result; unity::scopes::ActionMetadata meta_data{default_locale, default_form_factor}; static const std::string widget_id{"does.not.exist.widget"}; static const std::string action_id{"does.not.exist.action"}; unity::scopes::testing::Benchmark::ActionConfiguration config; config.sampler = [search_result, meta_data]() { return std::make_tuple(search_result, meta_data, widget_id, action_id); }; auto result = benchmark.for_action(scope, config); auto reference = reference_action_performance(); EXPECT_FALSE(result.timing.is_significantly_faster_than_reference( reference.first.count(), reference.second.count())); EXPECT_FALSE(result.timing.is_significantly_slower_than_reference( reference.first.count(), reference.second.count())); } TEST_F(BenchmarkScopeFixture, benchmarking_a_scope_query_performance_works) { unity::scopes::testing::InProcessBenchmark benchmark; unity::scopes::CannedQuery query{scope_id}; query.set_query_string(scope_query_string); unity::scopes::SearchMetadata meta_data{default_locale, default_form_factor}; unity::scopes::testing::Benchmark::QueryConfiguration config; config.sampler = [query, meta_data]() { return std::make_pair(query, meta_data); }; auto result = benchmark.for_query(scope, config); auto reference = reference_query_performance(); EXPECT_FALSE(result.timing.is_significantly_faster_than_reference( reference.first.count(), reference.second.count())); EXPECT_FALSE(result.timing.is_significantly_slower_than_reference( reference.first.count(), reference.second.count())); } TEST_F(BenchmarkScopeFixture, benchmarking_a_scope_preview_performance_works) { unity::scopes::testing::InProcessBenchmark benchmark; unity::scopes::testing::Result search_result; unity::scopes::ActionMetadata meta_data{default_locale, default_form_factor}; unity::scopes::testing::Benchmark::PreviewConfiguration config; config.sampler = [search_result, meta_data]() { return std::make_pair(search_result, meta_data); }; auto result = benchmark.for_preview(scope, config); auto reference = reference_preview_performance(); EXPECT_FALSE(result.timing.is_significantly_faster_than_reference( reference.first.count(), reference.second.count())); EXPECT_FALSE(result.timing.is_significantly_slower_than_reference( reference.first.count(), reference.second.count())); } TEST_F(BenchmarkScopeFixture, benchmarking_a_scope_activation_performance_works) { unity::scopes::testing::InProcessBenchmark benchmark; unity::scopes::testing::Result search_result; unity::scopes::ActionMetadata meta_data{default_locale, default_form_factor}; unity::scopes::testing::Benchmark::ActivationConfiguration config; config.sampler = [search_result, meta_data]() { return std::make_pair(search_result, meta_data); }; config.trial_configuration.statistics_configuration.histogram_bin_count = 20; auto result = benchmark.for_activation(scope, config); std::ofstream out("histogram.txt"); for (const auto& bin : result.timing.histogram) out << bin.first.count() << " " << bin.second << std::endl; auto reference = reference_preview_performance(); EXPECT_FALSE(result.timing.is_significantly_faster_than_reference( reference.first.count(), reference.second.count())); EXPECT_FALSE(result.timing.is_significantly_slower_than_reference( reference.first.count(), reference.second.count())); } TEST_F(BenchmarkScopeFixture, benchmarking_a_scope_action_performance_works) { unity::scopes::testing::InProcessBenchmark benchmark; unity::scopes::testing::Result search_result; unity::scopes::ActionMetadata meta_data{default_locale, default_form_factor}; static const std::string widget_id{"does.not.exist.widget"}; static const std::string action_id{"does.not.exist.action"}; unity::scopes::testing::Benchmark::ActionConfiguration config; config.sampler = [search_result, meta_data]() { return std::make_tuple(search_result, meta_data, widget_id, action_id); }; auto result = benchmark.for_action(scope, config); auto reference = reference_preview_performance(); EXPECT_FALSE(result.timing.is_significantly_faster_than_reference( reference.first.count(), reference.second.count())); EXPECT_FALSE(result.timing.is_significantly_slower_than_reference( reference.first.count(), reference.second.count())); } ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScopeBenchmark/CMakeLists.txtunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/testing/IsolatedScopeBenchmark/CMakeLists.tx0000644000015301777760000000111612320776161033335 0ustar pbusernogroup00000000000000# Please adjust this value with extreme care. # It is common sense to keep the confidence level at 95%. set( BENCHMARKING_TEST_CONFIDENCE_LEVEL 0.95 CACHE STRING "Confidence level for statistical evaluation.") configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_executable(IsolatedScopeBenchmark_test IsolatedScopeBenchmark_test.cpp scope.cpp) target_link_libraries(IsolatedScopeBenchmark_test ${TESTLIBS}) add_test(IsolatedScopeBenchmark IsolatedScopeBenchmark_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ScopeBase/0000755000015301777760000000000012320776463024605 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ScopeBase/scopelib.cpp0000644000015301777760000000340412320776161027105 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #define EXPORT __attribute__ ((visibility("default"))) class EXPORT MyScope : public unity::scopes::ScopeBase { public: MyScope() {} virtual int start(std::string const&, unity::scopes::RegistryProxy const&) override { return VERSION; } virtual void stop() override {} virtual void run() override {} virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&, unity::scopes::SearchMetadata const&) override { return nullptr; } virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&, unity::scopes::ActionMetadata const&) override { return nullptr; } protected: virtual ~MyScope() {} }; EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { return new MyScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope) { delete scope; } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ScopeBase/ScopeBase_test.cpp0000644000015301777760000000476512320776161030223 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; namespace { char const* scopelib = TEST_BUILD_ROOT "/gtest/scopes/ScopeBase/libscopelib.so"; } bool create_called = false; // This test loads the scope library via the DynamicLoader and calls the library's create entry point // (unity_scope_create(), which returns a pointer to a ScopeBase). It then calls the derived instance's // start(), and stop() member functions before calling the library's destroy entry point // (unity_scope_destroy(), which deallocates the dervied instance again. // // If all this works without any exceptions or crashes, we know that the basic mechanism of loading and unloading // scopes from shared libraries, and getting a thread of control into the scope works correctly. TEST(ScopeBase, basic) { DynamicLoader::UPtr dl = DynamicLoader::create(scopelib); char const* create_sym = UNITY_SCOPE_CREATE_SYMSTR; unity::scopes::CreateFunction create = reinterpret_cast(dl->find_function(create_sym)); char const* destroy_sym = UNITY_SCOPE_DESTROY_SYMSTR; unity::scopes::DestroyFunction destroy = reinterpret_cast(dl->find_function(destroy_sym)); ScopeBase* b = create(); EXPECT_NE(nullptr, b); // For coverage testing int vmajor; int vminor; int vmicro; b->runtime_version(vmajor, vminor, vmicro); EXPECT_EQ(UNITY_SCOPES_VERSION_MAJOR, vmajor); EXPECT_EQ(UNITY_SCOPES_VERSION_MINOR, vminor); EXPECT_EQ(UNITY_SCOPES_VERSION_MICRO, vmicro); b->start("some_scope", nullptr); b->stop(); destroy(b); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ScopeBase/CMakeLists.txt0000644000015301777760000000026312320776161027341 0ustar pbusernogroup00000000000000add_executable(ScopeBase_test ScopeBase_test.cpp) target_link_libraries(ScopeBase_test ${TESTLIBS}) add_library(scopelib SHARED scopelib.cpp) add_test(ScopeBase ScopeBase_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ScopeExceptions/0000755000015301777760000000000012320776463026054 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ScopeExceptions/ScopeExceptions_test.cpp0000644000015301777760000000364512320776161032735 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace std; using namespace unity::scopes; TEST(MiddlewareException, state) { { MiddlewareException e("some error"); EXPECT_STREQ("unity::scopes::MiddlewareException: some error", e.what()); EXPECT_THROW(rethrow_exception(e.self()), MiddlewareException); MiddlewareException e2("blah"); e2 = e; EXPECT_EQ(e.reason(), e2.reason()); } } TEST(ConfigException, state) { { ConfigException e("some error"); EXPECT_STREQ("unity::scopes::ConfigException: some error", e.what()); EXPECT_THROW(rethrow_exception(e.self()), ConfigException); ConfigException e2("blah"); e2 = e; EXPECT_EQ(e.reason(), e2.reason()); } } TEST(NotFoundException, state) { { NotFoundException e("some error", "name"); EXPECT_STREQ("unity::scopes::NotFoundException: some error (name = name)", e.what()); EXPECT_EQ("name", e.name()); EXPECT_THROW(rethrow_exception(e.self()), NotFoundException); NotFoundException e2("blah", "name"); e2 = e; EXPECT_EQ(e.reason(), e2.reason()); EXPECT_EQ(e.name(), e2.name()); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/ScopeExceptions/CMakeLists.txt0000644000015301777760000000024612320776161030611 0ustar pbusernogroup00000000000000add_executable(ScopeExceptions_test ScopeExceptions_test.cpp) target_link_libraries(ScopeExceptions_test ${TESTLIBS}) add_test(ScopeExceptions ScopeExceptions_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/QueryMetadata/0000755000015301777760000000000012320776463025507 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/QueryMetadata/QueryMetadata_test.cpp0000644000015301777760000001056212320776161032017 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include using namespace unity; using namespace unity::scopes; TEST(SearchMetadata, basic) { { SearchMetadata meta("pl", "phone"); EXPECT_EQ(0, meta.cardinality()); EXPECT_EQ("pl", meta.locale()); EXPECT_EQ("phone", meta.form_factor()); } { SearchMetadata meta(50, "pl", "phone"); EXPECT_EQ(50, meta.cardinality()); EXPECT_EQ("pl", meta.locale()); EXPECT_EQ("phone", meta.form_factor()); } { SearchMetadata meta(50, "pl", "phone"); meta.set_cardinality(100); meta["foo"] = "bar"; meta.set_hint("baz", Variant(1000)); EXPECT_EQ(100, meta.cardinality()); EXPECT_EQ("bar", meta["foo"].get_string()); EXPECT_EQ("bar", meta.hints()["foo"].get_string()); EXPECT_EQ(1000, meta.hints()["baz"].get_int()); EXPECT_TRUE(meta.contains_hint("foo")); } { // referencing non-existing hint with a const object throws SearchMetadata const meta(50, "pl", "phone"); EXPECT_THROW(meta["foo"], unity::LogicException); EXPECT_FALSE(meta.contains_hint("foo")); } } TEST(SearchMetadata, serialize) { { SearchMetadata meta("pl", "phone"); meta["foo"] = "bar"; auto var = meta.serialize(); EXPECT_EQ("search_metadata", var["type"].get_string()); EXPECT_EQ("pl", var["locale"].get_string()); EXPECT_EQ("phone", var["form_factor"].get_string()); EXPECT_EQ("bar", var["hints"].get_dict()["foo"].get_string()); } } TEST(SearchMetadata, copy) { { SearchMetadata meta(100, "pl", "phone"); auto meta2 = meta; meta.set_cardinality(0); EXPECT_EQ(0, meta.cardinality()); EXPECT_EQ(100, meta2.cardinality()); } { SearchMetadata meta(100, "pl", "phone"); SearchMetadata meta2(meta); meta.set_cardinality(0); EXPECT_EQ(0, meta.cardinality()); EXPECT_EQ(100, meta2.cardinality()); } } TEST(ActionMetadata, basic) { { VariantMap var; var["foo"] = "bar"; ActionMetadata meta("pl", "phone"); meta.set_scope_data(Variant(var)); EXPECT_EQ("pl", meta.locale()); EXPECT_EQ("phone", meta.form_factor()); EXPECT_EQ("bar", meta.scope_data().get_dict()["foo"].get_string()); } } TEST(ActionMetadata, serialize_and_deserialize) { { ActionMetadata meta("pl", "phone"); meta.set_scope_data(Variant(1234)); auto var = meta.serialize(); EXPECT_EQ("action_metadata", var["type"].get_string()); EXPECT_EQ("pl", var["locale"].get_string()); EXPECT_EQ("phone", var["form_factor"].get_string()); EXPECT_EQ(1234, var["scope_data"].get_int()); // deserialize auto meta2 = internal::ActionMetadataImpl::create(var); EXPECT_EQ("pl", meta2.locale()); EXPECT_EQ("phone", meta2.form_factor()); EXPECT_EQ(1234, meta2.scope_data().get_int()); } } TEST(ActionMetadata, copy) { { ActionMetadata meta("pl", "phone"); auto meta2 = meta; Variant var("foo"); meta.set_scope_data(var); EXPECT_TRUE(meta2.scope_data().is_null()); EXPECT_EQ("foo", meta.scope_data().get_string()); } { ActionMetadata meta("pl", "phone"); ActionMetadata meta2(meta); Variant var(10); meta.set_scope_data(var); EXPECT_TRUE(meta2.scope_data().is_null()); EXPECT_EQ(10, meta.scope_data().get_int()); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/QueryMetadata/CMakeLists.txt0000644000015301777760000000023412320776161030241 0ustar pbusernogroup00000000000000add_executable(QueryMetadata_test QueryMetadata_test.cpp) target_link_libraries(QueryMetadata_test ${TESTLIBS}) add_test(QueryMetadata QueryMetadata_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/CMakeLists.txt0000644000015301777760000000123212320776161025472 0ustar pbusernogroup00000000000000add_subdirectory(internal) add_subdirectory(testing) add_subdirectory(Registry) add_subdirectory(Runtime) add_subdirectory(Activation) add_subdirectory(ActivationResponse) add_subdirectory(Annotation) add_subdirectory(CannedQuery) add_subdirectory(Department) add_subdirectory(Filters) add_subdirectory(ScopeBase) add_subdirectory(ScopeExceptions) add_subdirectory(Category) add_subdirectory(CategorisedResult) add_subdirectory(CategoryRenderer) add_subdirectory(ColumnLayout) add_subdirectory(PreviewWidget) add_subdirectory(QueryMetadata) add_subdirectory(OptionSelectorFilter) add_subdirectory(Variant) add_subdirectory(VariantBuilder) add_subdirectory(Version) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Version/0000755000015301777760000000000012320776463024366 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Version/Version_test.cpp0000644000015301777760000000206312320776161027552 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace unity::scopes; TEST(Version, basic) { EXPECT_EQ(major_version(), UNITY_SCOPES_VERSION_MAJOR); EXPECT_EQ(minor_version(), UNITY_SCOPES_VERSION_MINOR); EXPECT_EQ(micro_version(), UNITY_SCOPES_VERSION_MICRO); EXPECT_STREQ(version_string(), UNITY_SCOPES_VERSION_STRING); } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Version/CMakeLists.txt0000644000015301777760000000017612320776161027125 0ustar pbusernogroup00000000000000add_executable(Version_test Version_test.cpp) target_link_libraries(Version_test ${TESTLIBS}) add_test(Version Version_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/VariantBuilder/0000755000015301777760000000000012320776463025654 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/VariantBuilder/VariantBuilder_test.cpp0000644000015301777760000000402112320776161032322 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include using namespace unity; using namespace unity::scopes; TEST(VariantBuilder, basic) { VariantBuilder builder; { // create an array of tuples: // [{"a" : 1, b : 2}, {"c" : null, "d" : "xyz"}] builder.add_tuple({{"a", Variant(1)}, {"b", Variant(2)}}); builder.add_tuple({{"c", Variant::null()}, {"d", Variant("xyz")}}); auto arr = builder.end().get_array(); EXPECT_EQ(2u, arr.size()); EXPECT_EQ(1, arr[0].get_dict()["a"].get_int()); EXPECT_EQ(2, arr[0].get_dict()["b"].get_int()); EXPECT_TRUE(arr[1].get_dict()["c"].is_null()); EXPECT_EQ("xyz", arr[1].get_dict()["d"].get_string()); } // reusing a builder { EXPECT_THROW(builder.end(), unity::LogicException); builder.add_tuple({{"a", Variant(0)}}); EXPECT_EQ(1u, builder.end().get_array().size()); } } TEST(VariantBuilder, copy) { { VariantBuilder builder; builder.add_tuple({{"a", Variant(0)}}); VariantBuilder builder2 = builder; EXPECT_EQ(1u, builder.end().get_array().size()); EXPECT_EQ(1u, builder2.end().get_array().size()); } } namespace unity { namespace scopes { } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/VariantBuilder/CMakeLists.txt0000644000015301777760000000024112320776161030404 0ustar pbusernogroup00000000000000add_executable(VariantBuilder_test VariantBuilder_test.cpp) target_link_libraries(VariantBuilder_test ${TESTLIBS}) add_test(VariantBuilder VariantBuilder_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Annotation/0000755000015301777760000000000012320776463025053 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Annotation/Annotation_test.cpp0000644000015301777760000002026612320776161030731 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; TEST(Annotation, link) { { CannedQuery query("scope-A", "foo", "dep1"); Annotation annotation(Annotation::Type::Link); annotation.add_link("Link1", query); EXPECT_EQ(1u, annotation.links().size()); auto link = annotation.links().front(); EXPECT_EQ("Link1", link->label()); EXPECT_EQ(query.scope_id(), link->query().scope_id()); EXPECT_EQ(query.department_id(), link->query().department_id()); EXPECT_EQ(query.query_string(), link->query().query_string()); } } // emblem link is a regular link + an icon TEST(Annotation, emblemLink) { { CannedQuery query("scope-A", "foo", "dep1"); Annotation annotation(Annotation::Type::Link); annotation.set_icon("icon"); annotation.add_link("Link1", query); EXPECT_EQ("icon", annotation.icon()); EXPECT_EQ(1u, annotation.links().size()); auto link = annotation.links().front(); EXPECT_EQ("Link1", link->label()); EXPECT_EQ(query.scope_id(), link->query().scope_id()); EXPECT_EQ(query.department_id(), link->query().department_id()); EXPECT_EQ(query.query_string(), link->query().query_string()); } } TEST(Annotation, link_exceptions) { { CannedQuery query("scope-A", "foo", "dep1"); Annotation annotation(Annotation::Type::Link); annotation.add_link("Link1", query); EXPECT_THROW(annotation.add_link("Link2", query), unity::InvalidArgumentException); // only one link allowed EXPECT_EQ(1u, annotation.links().size()); EXPECT_NO_THROW(annotation.set_label("label")); // no design case for link with a label (makes sense for a group only), but we shouldn't throw EXPECT_NO_THROW(annotation.label()); } } TEST(Annotation, groupedLink) { { CannedQuery query1("scope-A", "foo", "dep1"); CannedQuery query2("scope-B", "foo", "dep1"); Annotation annotation(Annotation::Type::GroupedLink); annotation.set_label("Group"); annotation.add_link("Link1", query1); annotation.add_link("Link2", query2); EXPECT_EQ("Group", annotation.label()); EXPECT_EQ(2u, annotation.links().size()); auto link1 = annotation.links().front(); auto link2 = annotation.links().back(); EXPECT_EQ("Link1", link1->label()); EXPECT_EQ(query1.scope_id(), link1->query().scope_id()); EXPECT_EQ(query1.department_id(), link1->query().department_id()); EXPECT_EQ(query1.query_string(), link1->query().query_string()); EXPECT_EQ("Link2", link2->label()); EXPECT_EQ(query2.scope_id(), link2->query().scope_id()); EXPECT_EQ(query2.department_id(), link2->query().department_id()); EXPECT_EQ(query2.query_string(), link2->query().query_string()); } } TEST(Annotation, groupedLink_exceptions) { { CannedQuery query1("scope-A", "foo", "dep1"); CannedQuery query2("scope-B", "foo", "dep1"); Annotation annotation(Annotation::Type::GroupedLink); annotation.set_label("Group"); annotation.add_link("Link1", query1); annotation.add_link("Link2", query2); // no design case for link group with an icon, but we shouldn't throw EXPECT_NO_THROW(annotation.set_icon("icon")); EXPECT_NO_THROW(annotation.icon()); } } TEST(Annotation, serialize) { { CannedQuery query("scope-A", "foo", "dep1"); Annotation annotation(Annotation::Type::Link); annotation.add_link("Link1", query); auto vm = annotation.serialize(); EXPECT_EQ("link", vm["type"].get_string()); EXPECT_TRUE(vm.find("label") == vm.end()); EXPECT_TRUE(vm.find("icon") == vm.end()); auto links = vm["links"].get_array(); EXPECT_EQ(1u, links.size()); auto linkvm = links[0].get_dict(); EXPECT_EQ("Link1", linkvm["label"].get_string()); CannedQuery qout = internal::CannedQueryImpl::create(linkvm["query"].get_dict()); EXPECT_EQ("scope-A", qout.scope_id()); EXPECT_EQ("foo", qout.query_string()); EXPECT_EQ("dep1", qout.department_id()); } } TEST(Annotation, deserialize) { CannedQuery query("scope-A", "foo", "dep1"); { Annotation annotation(Annotation::Type::GroupedLink); annotation.set_label("Foo"); annotation.add_link("Link1", query); auto var = annotation.serialize(); AnnotationImpl impl(var); } { Annotation annotation(Annotation::Type::Link); annotation.set_icon("Icon"); annotation.add_link("Link1", query); auto var = annotation.serialize(); AnnotationImpl impl(var); } } TEST(Annotation, deserialize_exceptions) { { CannedQuery query("scope-A", "foo", "dep1"); { VariantMap var; try { AnnotationImpl impl(var); FAIL(); } catch (unity::InvalidArgumentException const& e) {} } { VariantMap var; var["type"] = ""; try { AnnotationImpl impl(var); FAIL(); } catch (unity::InvalidArgumentException const& e) {} } { VariantMap var; var["type"] = "link"; try { AnnotationImpl impl(var); FAIL(); } catch (unity::InvalidArgumentException const& e) {} } { VariantMap var; var["type"] = "groupedlink"; try { AnnotationImpl impl(var); FAIL(); } catch (unity::InvalidArgumentException const& e) {} } { VariantMap var; var["type"] = "card"; try { AnnotationImpl impl(var); FAIL(); } catch (unity::InvalidArgumentException const& e) {} } { VariantMap var; var["type"] = "card"; var["icon"] = "Icon"; var["cat_id"] = "unknowncat"; try { AnnotationImpl impl(var); FAIL(); } catch (unity::InvalidArgumentException const& e) {} } { // deserialize with empty links array Annotation annotation(Annotation::Type::Link); annotation.add_link("Link1", query); auto var = annotation.serialize(); var["links"] = VariantArray(); try { AnnotationImpl impl(var); FAIL(); } catch (unity::InvalidArgumentException const& e) {} } } } TEST(Annotation, copy) { { CannedQuery query("scope-A", "foo", "dep1"); Annotation annotation(Annotation::Type::GroupedLink); annotation.set_label("Group"); annotation.add_link("Link1", query); Annotation copy(annotation); EXPECT_EQ("Group", copy.label()); EXPECT_EQ(Annotation::Type::GroupedLink, copy.annotation_type()); annotation.add_link("Link2", query); EXPECT_EQ(1u, copy.links().size()); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Annotation/CMakeLists.txt0000644000015301777760000000021512320776161027604 0ustar pbusernogroup00000000000000add_executable(Annotation_test Annotation_test.cpp) target_link_libraries(Annotation_test ${TESTLIBS}) add_test(Annotation Annotation_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Filters/0000755000015301777760000000000012320776463024351 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Filters/Zmq.ini.in0000644000015301777760000000007312320776161026221 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Filters/Registry.ini.in0000644000015301777760000000026012320776161027260 0ustar pbusernogroup00000000000000[Registry] Middleware = Zmq Zmq.Endpoint = ipc:///tmp/socket_for_registry Zmq.EndpointDir = /tmp Zmq.ConfigFile = Zmq.ini Scope.InstallDir = /unused Scoperunner.Path = /unused unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Filters/Filters_test.cpp0000644000015301777760000001035312320776161027521 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; class WaitUntilFinished { public: void wait_until_finished() { std::unique_lock lock(mutex_); cond_.wait(lock, [this] { return this->query_complete_; }); } protected: void notify() { // Signal that the query has completed. std::unique_lock lock(mutex_); query_complete_ = true; cond_.notify_one(); } private: bool query_complete_; std::mutex mutex_; std::condition_variable cond_; }; class SearchReceiver : public SearchListenerBase, public WaitUntilFinished { public: virtual void push(CategorisedResult /* result */) override {} virtual void push(Filters const& filters, FilterState const& filter_state) override { this->filters = filters; this->filter_state = filter_state; } virtual void finished(ListenerBase::Reason /* reason */, std::string const& /* error_message */) override { notify(); } Filters filters; FilterState filter_state; }; void scope_thread(Runtime::SPtr const& rt) { TestScope scope; rt->run_scope(&scope, "/"); } TEST(Filters, scope) { // parent: connect to scope and run a query auto rt = internal::RuntimeImpl::create("", "Runtime.ini"); auto mw = rt->factory()->create("TestScope", "Zmq", "Zmq.ini"); mw->start(); auto proxy = mw->create_scope_proxy("TestScope"); auto scope = internal::ScopeImpl::create(proxy, rt.get(), "TestScope"); SearchMetadata hints("pl", "phone"); auto receiver = std::make_shared(); auto ctrl = scope->search("test", hints, receiver); receiver->wait_until_finished(); auto filter_state = receiver->filter_state; // copy filter state, it will be sent with 2nd query { auto filters = receiver->filters; EXPECT_EQ(1u, filters.size()); EXPECT_EQ("f1", filters.front()->id()); auto filter_type = filters.front()->filter_type(); EXPECT_EQ("option_selector", filter_type); auto selector = std::dynamic_pointer_cast(filters.front()); EXPECT_EQ(2u, selector->options().size()); EXPECT_EQ(0u, selector->active_options(filter_state).size()); auto option1 = selector->options().front(); selector->update_state(filter_state, option1, true); // activate filter option } // send 2nd query, this time with filter state (one active option) receiver = std::make_shared(); ctrl = scope->search("test2", filter_state, hints, receiver); receiver->wait_until_finished(); { auto filters = receiver->filters; auto filter_state2 = receiver->filter_state; auto selector = std::dynamic_pointer_cast(filters.front()); EXPECT_EQ(1u, selector->active_options(filter_state2).size()); auto option1 = *(selector->active_options(filter_state2).begin()); EXPECT_EQ("o1", option1->id()); } } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); Runtime::SPtr rt = move(Runtime::create_scope_runtime("TestScope", "Runtime.ini")); std::thread scope_t(scope_thread, rt); auto rc = RUN_ALL_TESTS(); rt->destroy(); scope_t.join(); return rc; } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Filters/TestScope.h0000644000015301777760000000467512320776161026442 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include #ifndef UNITY_SCOPES_TEST_SCOPE_H #define UNITY_SCOPES_TEST_SCOPE_H namespace unity { namespace scopes { class TestQuery : public SearchQueryBase { public: TestQuery(CannedQuery const& q) : SearchQueryBase(), query_(q) { } virtual void cancelled() override {} virtual void run(SearchReplyProxy const& reply) override { Filters filters; auto filter = OptionSelectorFilter::create("f1", "Choose an option", false); filter->add_option("o1", "Option 1"); filter->add_option("o2", "Option 2"); filters.push_back(filter); auto active_opts = filter->active_options(query_.filter_state()); reply->push(filters, query_.filter_state()); // send unmodified state back auto cat = reply->register_category("cat1", "Category 1", ""); CategorisedResult res(cat); res.set_uri("uri"); res.set_dnd_uri("dnd_uri"); reply->push(res); } private: CannedQuery query_; }; class TestScope : public ScopeBase { public: virtual int start(std::string const&, RegistryProxy const &) override { return VERSION; } virtual void stop() override {} virtual void run() override {} virtual SearchQueryBase::UPtr search(CannedQuery const &q, SearchMetadata const &) override { return SearchQueryBase::UPtr(new TestQuery(q)); } virtual PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const &) override { return nullptr; } }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Filters/CMakeLists.txt0000644000015301777760000000060012320776161027100 0ustar pbusernogroup00000000000000include_directories(${CMAKE_CURRENT_SOURCE_DIR}) configure_file(Registry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Registry.ini) configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini) configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini) add_executable(Filters_test Filters_test.cpp) target_link_libraries(Filters_test ${TESTLIBS}) add_test(Filters Filters_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/Filters/Runtime.ini.in0000644000015301777760000000017412320776161027077 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = Registry Registry.ConfigFile = Registry.ini Default.Middleware = Zmq Zmq.ConfigFile = Zmq.ini unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/OptionSelectorFilter/0000755000015301777760000000000012320776463027060 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/OptionSelectorFilter/OptionSelectorFilter_test.cppunity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/OptionSelectorFilter/OptionSelectorFilter_te0000644000015301777760000001263512320776161033614 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; TEST(OptionSelectorFilter, basic) { auto filter1 = OptionSelectorFilter::create("f1", "Options", false); EXPECT_EQ("f1", filter1->id()); EXPECT_EQ("Options", filter1->label()); EXPECT_FALSE(filter1->multi_select()); filter1->add_option("1", "Option 1"); filter1->add_option("2", "Option 2"); auto opts = filter1->options(); EXPECT_EQ(2u, opts.size()); EXPECT_EQ("1", opts.front()->id()); EXPECT_EQ("Option 1", opts.front()->label()); EXPECT_EQ("2", opts.back()->id()); EXPECT_EQ("Option 2", opts.back()->label()); } TEST(OptionSelectorFilter, single_selection) { auto filter1 = OptionSelectorFilter::create("f1", "Options", false); auto option1 = filter1->add_option("1", "Option 1"); auto option2 = filter1->add_option("2", "Option 2"); FilterState fstate; EXPECT_FALSE(fstate.has_filter("f1")); // enable option1 filter1->update_state(fstate, option1, true); EXPECT_TRUE(fstate.has_filter("f1")); auto active = filter1->active_options(fstate); EXPECT_EQ(1u, active.size()); EXPECT_TRUE(active.find(option1) != active.end()); // enable option2, option1 get disabled filter1->update_state(fstate, option2, true); active = filter1->active_options(fstate); EXPECT_EQ(1u, active.size()); EXPECT_TRUE(active.find(option2) != active.end()); // disable option1; filter state remains in the FilterState, just no options are selected filter1->update_state(fstate, option2, false); EXPECT_TRUE(fstate.has_filter("f1")); EXPECT_EQ(0u, filter1->active_options(fstate).size()); } TEST(OptionSelectorFilter, multi_selection) { auto filter1 = OptionSelectorFilter::create("f1", "Options", true); auto option1 = filter1->add_option("1", "Option 1"); auto option2 = filter1->add_option("2", "Option 2"); filter1->add_option("3", "Option 3"); FilterState fstate; // enable option1 & option2 filter1->update_state(fstate, option1, true); filter1->update_state(fstate, option2, true); EXPECT_TRUE(fstate.has_filter("f1")); auto active = filter1->active_options(fstate); EXPECT_EQ(2u, active.size()); EXPECT_TRUE(active.find(option1) != active.end()); EXPECT_TRUE(active.find(option2) != active.end()); // disable option1 filter1->update_state(fstate, option1, false); EXPECT_EQ(1u, filter1->active_options(fstate).size()); EXPECT_TRUE(active.find(option1) != active.end()); // disable option2 filter1->update_state(fstate, option2, false); EXPECT_TRUE(fstate.has_filter("f1")); EXPECT_EQ(0u, filter1->active_options(fstate).size()); } TEST(OptionSelectorFilter, serialize) { auto filter1 = OptionSelectorFilter::create("f1", "Options", true); filter1->add_option("1", "Option 1"); filter1->add_option("2", "Option 2"); auto var = filter1->serialize(); EXPECT_EQ("f1", var["id"].get_string()); EXPECT_EQ("option_selector", var["filter_type"].get_string()); EXPECT_EQ("Options", var["label"].get_string()); auto optarr = var["options"].get_array(); EXPECT_EQ(2u, optarr.size()); EXPECT_EQ("1", optarr[0].get_dict()["id"].get_string()); EXPECT_EQ("Option 1", optarr[0].get_dict()["label"].get_string()); EXPECT_EQ("2", optarr[1].get_dict()["id"].get_string()); EXPECT_EQ("Option 2", optarr[1].get_dict()["label"].get_string()); } TEST(OptionSelectorFilter, deserialize) { VariantMap var; { try { internal::OptionSelectorFilterImpl filter(var); FAIL(); } catch (unity::LogicException const&) {} } { var["id"] = "f1"; var["filter_type"] = "option_selector"; // missing attributes of option selector try { internal::OptionSelectorFilterImpl filter(var); } catch (unity::LogicException const&) {} } { var["id"] = "f1"; var["filter_type"] = "option_selector"; var["label"] = "Filter 1"; var["multi_select"] = true; VariantArray optarr; VariantMap opt; opt["id"] = "1"; opt["label"] = "Option 1"; optarr.push_back(Variant(opt)); var["options"] = optarr; internal::OptionSelectorFilterImpl filter(var); EXPECT_EQ("f1", filter.id()); EXPECT_EQ("Filter 1", filter.label()); EXPECT_EQ(true, filter.multi_select()); EXPECT_EQ(1u, filter.options().size()); EXPECT_EQ("1", filter.options().front()->id()); } } unity-scopes-api-0.4.2+14.04.20140408/test/gtest/scopes/OptionSelectorFilter/CMakeLists.txt0000644000015301777760000000027712320776161031621 0ustar pbusernogroup00000000000000add_executable(OptionSelectorFilter_test OptionSelectorFilter_test.cpp) target_link_libraries(OptionSelectorFilter_test ${TESTLIBS}) add_test(OptionSelectorFilter OptionSelectorFilter_test) unity-scopes-api-0.4.2+14.04.20140408/test/gtest/CMakeLists.txt0000644000015301777760000000166212320776161024205 0ustar pbusernogroup00000000000000if (NOT DEFINED GMOCK_ROOT) set(GMOCK_ROOT /usr/src/gmock) endif() add_subdirectory(${GMOCK_ROOT} gmock) # Selectively switch off warnings about missing field initializers when building gmock and gtest set_property(TARGET gmock APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-missing-field-initializers") set_property(TARGET gmock_main APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-missing-field-initializers") set_property(TARGET gtest APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-missing-field-initializers") include_directories(${GMOCK_ROOT}/gtest/include) set(LIBGTEST gtest gmock gmock_main) set(TESTLIBS ${TESTLIBS} ${LIBGTEST} boost_regex) add_subdirectory(scopes) set(TEST_SRC ) foreach(src ${TEST_SRC}) get_filename_component(name ${src} NAME_WE) add_executable(${name} ${src}) target_link_libraries(${name} ${TESTLIBS}) string(REPLACE "_test" "" test_name ${name}) add_test(${test_name} ${name}) endforeach(src) unity-scopes-api-0.4.2+14.04.20140408/test/copyright/0000755000015301777760000000000012320776463022327 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/copyright/check_copyright.sh0000755000015301777760000000317512320776161026034 0ustar pbusernogroup00000000000000#!/bin/sh # # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # # # Check that, somewhere in the first 30 lines of each file, the string "Copyright" (case independent) appears. # Print out a messsage for each file without a copyright notice and exit with non-zero status # if any such file is found. # usage() { echo "usage: check_copyright dir [ignore_dir]" >&2 exit 2 } [ $# -lt 1 ] && usage [ $# -gt 2 ] && usage ignore_pat="\\.sci$" # # We don't use the -i option of licensecheck to add ignore_dir to the pattern because Jenkins creates directories # with names that contain regex meta-characters, such as "." and "+". Instead, if ingnore_dir is set, we post-filter # the output with grep -F, so we don't get false positives from licensecheck. # [ $# -eq 2 ] && ignore_dir="$2" if [ -n "$ignore_dir" ] then licensecheck -i "$ignore_pat" -r "$1" | grep -F "$ignore_dir" -v | grep 'No copyright' else licensecheck -i "$ignore_pat" -r "$1" | grep 'No copyright' fi [ $? -eq 0 ] && exit 1 exit 0 unity-scopes-api-0.4.2+14.04.20140408/test/copyright/CMakeLists.txt0000644000015301777760000000025512320776161025064 0ustar pbusernogroup00000000000000# # Test that all source files contain a copyright header. # add_test(copyright ${CMAKE_CURRENT_SOURCE_DIR}/check_copyright.sh ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}) unity-scopes-api-0.4.2+14.04.20140408/test/scope-api-testconfig.h.in0000644000015301777760000000027112320776161025113 0ustar pbusernogroup00000000000000/* This file contains all configuration data needed to run unit tests. */ #ifndef SCOPE_API_TESTCONFIG #define SCOPE_API_TESTCONFIG #define TEST_BUILD_ROOT "@TEST_BUILD_ROOT@" #endifunity-scopes-api-0.4.2+14.04.20140408/test/headers/0000755000015301777760000000000012320776463021732 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/headers/check_global_usage.py0000755000015301777760000000246712320776161026074 0ustar pbusernogroup00000000000000#! /usr/bin/env python3 # # Copyright (C) 2014 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Jussi Pakkanen import os, sys def check_headers(subdirs): errors = 0 for d in subdirs: for root, dirs, files in os.walk(d): for f in files: if f.endswith('.h'): fname = os.path.join(root, f) if 'unity-scopes.h' in open(fname, encoding='utf-8').read(): print("Global header included in", fname) errors += 1 return errors if __name__ == '__main__': if len(sys.argv) < 2: print(sys.argv[0], "header directories to check") sys.exit(1) sys.exit(check_headers(sys.argv[1:])) unity-scopes-api-0.4.2+14.04.20140408/test/headers/compile_headers.py0000755000015301777760000001363012320776161025430 0ustar pbusernogroup00000000000000#! /usr/bin/env python3 # # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # # # Little helper program to test that header files are stand-alone compilable (and therefore don't depend on # other headers being included first). # # Usage: compile_headers.py directory compiler [compiler_flags] # # The directory specifies the location of the header files. All files in that directory ending in .h (but not # in subdirectories) are tested. # # The compiler argument specifies the compiler to use (such as "gcc"), and the compiler_flags argument (which # must be a single string argument, not a bunch of separate strings) specifies any additional flags, such # as "-I -g". The flags need not include "-c". # # For each header file in the specified directory, the script create a corresponding .cpp that includes the # header file. The .cpp file is created in the current directory (which isn't necessarily the same one as # the directory the header files are in). The script runs the compiler on the generated .cpp file and, if the # compiler returns non-zero exit status, it prints a message (on stdout) reporting the failure. # # The script does not stop if a file fails to compile. If all source files compile successfully, no output (other # than the output from the compiler) is written, and the exit status is zero. If one or more files do not compile, # or there are any other errors, such as not being able to open a file, exit status is non-zero. # # Messages about files that fail to compile are written to stdout. Message about other problems, such as non-existent # files and the like, are written to stderr. # # The compiler's output goes to whatever stream the compiler writes to and is left alone. # import argparse import os import re import shlex import subprocess import sys import tempfile # # Write the supplied message to stderr, preceded by the program name. # def error(msg): print(os.path.basename(sys.argv[0]) + ": " + msg, file=sys.stderr) # # Write the supplied message to stdout, preceded by the program name. # def message(msg): print(os.path.basename(sys.argv[0]) + ": " + msg) # # Create a source file in the current directory that includes the specified header, compile it, # and check exit status from the compiler. Throw if the compile command itself fails, # return False if the compile command worked but reported errors, True if the compile succeeded. # def run_compiler(hdr, compiler, copts, verbose): try: src = tempfile.NamedTemporaryFile(suffix='.cpp', dir='.') src.write(bytes("#include <" + hdr + ">" + "\n", 'UTF-8')) src.flush() # Need this to make the file visible src_name = os.path.join('.', src.name) if verbose: print(compiler + " -c " + src_name + " " + copts) status = subprocess.call([compiler] + shlex.split(copts) + ["-c", src_name]) if status != 0: message("cannot compile \"" + hdr + "\"") # Yes, write to stdout because this is expected output obj = os.path.splitext(src_name)[0] + ".o" try: os.unlink(obj) except: pass gcov = os.path.splitext(src_name)[0] + ".gcno" try: os.unlink(gcov) except: pass return status == 0 except OSError as e: error(e.strerror) raise # # For each of the supplied headers, create a source file in the current directory that includes the header # and then try to compile the header. Returns normally if all files could be compiled successfully and # throws, otherwise. # def test_files(hdrs, compiler, copts, verbose): num_errs = 0 for h in hdrs: try: if not run_compiler(h, compiler, copts, verbose): num_errs += 1 except OSError: num_errs += 1 pass # Error reported already if num_errs != 0: msg = str(num_errs) + " file" if num_errs != 1: msg += "s" msg += " failed to compile" message(msg) # Yes, write to stdout because this is expected output sys.exit(1) def run(): # # Parse arguments. # parser = argparse.ArgumentParser(description = 'Test that all headers in the passed directory compile stand-alone.') parser.add_argument('-v', '--verbose', action='store_true', help = 'Trace invocations of the compiler') parser.add_argument('dir', nargs = 1, help = 'The directory to look for header files ending in ".h"') parser.add_argument('compiler', nargs = 1, help = 'The compiler executable, such as "gcc"') parser.add_argument('copts', nargs = '?', default="", help = 'The compiler options (excluding -c), such as "-g -Wall -I." as a single string.') args = parser.parse_args() # # Find all the .h files in specified directory and do the compilation for each one. # hdr_dir = args.dir[0] try: files = os.listdir(hdr_dir) except OSError as e: msg = "cannot open \"" + hdr_dir + "\": " + e.strerror error(msg) sys.exit(1) hdrs = [hdr for hdr in files if hdr.endswith('.h')] try: test_files(hdrs, args.compiler[0], args.copts, args.verbose) except OSError: sys.exit(1) # Errors were written earlier if __name__ == '__main__': run() unity-scopes-api-0.4.2+14.04.20140408/test/headers/includechecker.py0000755000015301777760000000554512320776161025263 0ustar pbusernogroup00000000000000#!/usr/bin/python3 -tt # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Jussi Pakkanen """A script that traverses all header files in a given directory and scans them for forbidden includes.""" import os, sys, stat forbidden = {'boost', 'gobject', 'gtk', 'Qt', 'dbus.h', 'Ice', } # # List of exceptions. For each of the directory prefixes in the list, allow the #include directive to start # with one of the specified prefixes. # allowed = { 'unity/shell': { 'Qt' } # Anything under unity/shell can include anything starting with Qt } def check_file(filename, permitted_includes): errors_found = False linenum = 0 for line in open(filename, encoding='utf-8'): line = line.strip() if line.startswith('#include'): for f in (forbidden - permitted_includes): if f in line: msg = 'Forbidden include: %s:%d - %s'\ % (filename, linenum, line) print(msg) errors_found = True; linenum += 1 return errors_found def check_headers(incdir): errors_found = False suffixes = ('h', 'hpp', 'hh', 'hxx', 'H', 'h.in', ) for root, dirs, files in os.walk(incdir): if 'internal' in dirs: dirs.remove('internal') for filename in files: if filename.endswith(suffixes): fullname = os.path.join(root, filename) permitted_includes = set() for path, names in allowed.items(): if fullname.startswith(os.path.join(incdir, path)): permitted_includes = names break if check_file(fullname, permitted_includes): errors_found = True return errors_found if __name__ == '__main__': if len(sys.argv) != 2: print(sys.argv[0], '') sys.exit(1) incdir = sys.argv[1] if not stat.S_ISDIR(os.stat(incdir).st_mode): print("Argument", incdir, "is not a directory.") sys.exit(1) if check_headers(incdir): sys.exit(1) unity-scopes-api-0.4.2+14.04.20140408/test/headers/check_public_headers.py0000755000015301777760000000617612320776161026422 0ustar pbusernogroup00000000000000#! /usr/bin/env python3 # # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # # # Little helper program to test that public header files don't include internal header files. # # Usage: check_public_headers.py directory # # The directory specifies the location of the header files. All files in that directory ending in .h (but not # in subdirectories) are tested. # import argparse import os import sys import re # # Write the supplied message to stderr, preceded by the program name. # def error(msg): print(os.path.basename(sys.argv[0]) + ": " + msg, file=sys.stderr) # # Write the supplied message to stdout, preceded by the program name. # def message(msg): print(os.path.basename(sys.argv[0]) + ": " + msg) # # For each of the supplied headers, check whether that header includes something in an internal directory. # Return the count of headers that do this. # def test_files(hdr_dir, hdrs): num_errs = 0 for hdr in hdrs: try: hdr_name = os.path.join(hdr_dir, hdr) file = open(hdr_name, "r") except OSError as e: error("cannot open \"" + hdr_name + "\": " + e.strerror) sys.exit(1) include_pat = re.compile(r'#[ \t]*include[ \t]+[<"](.*?)[>"]') lines = file.readlines() line_num = 0 for l in lines: line_num += 1 include_mo = include_pat.match(l) if include_mo: hdr_path = include_mo.group(1) if 'internal/' in hdr_path: num_errs += 1 # Yes, write to stdout because this is expected output message(hdr_name + " includes an internal header at line " + str(line_num) + ": " + hdr_path) return num_errs def run(): # # Parse arguments. # parser = argparse.ArgumentParser(description = 'Test that no public header includes an internal header.') parser.add_argument('dir', nargs = 1, help = 'The directory to look for header files ending in ".h"') args = parser.parse_args() # # Find all the .h files in specified directory and look for #include directives that mention "internal/". # hdr_dir = args.dir[0] try: files = os.listdir(hdr_dir) except OSError as e: error("cannot open \"" + hdr_dir + "\": " + e.strerror) sys.exit(1) hdrs = [hdr for hdr in files if hdr.endswith('.h')] if test_files(hdr_dir, hdrs) != 0: sys.exit(1) # Errors were reported earlier if __name__ == '__main__': run() unity-scopes-api-0.4.2+14.04.20140408/test/headers/CMakeLists.txt0000644000015301777760000000315712320776161024473 0ustar pbusernogroup00000000000000# # Test that all header files compile stand-alone and that no public header includes an internal one. # set(root_inc_dir ${CMAKE_SOURCE_DIR}/include) set(subdirs unity/scopes ) foreach(dir ${OTHER_INCLUDE_DIRS}) set(other_inc_dirs "${other_inc_dirs} -I${dir}") endforeach() set(other_inc_dirs "${other_inc_dirs} -I${CMAKE_BINARY_DIR}/include -I${CMAKE_BINARY_DIR}") foreach(dir ${subdirs}) string(REPLACE "/" "-" location ${dir}) set(public_inc_dir ${root_inc_dir}/${dir}) set(internal_inc_dir ${public_inc_dir}/internal) # Test that each public header compiles stand-alone. add_test(stand-alone-${location}-headers ${CMAKE_CURRENT_SOURCE_DIR}/compile_headers.py ${public_inc_dir} ${CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER_ARG1} -fsyntax-only -I${root_inc_dir} -I${public_inc_dir} ${other_inc_dirs} ${CMAKE_CXX_FLAGS}") # Test that each internal header compiles stand-alone. add_test(stand-alone-${location}-internal-headers ${CMAKE_CURRENT_SOURCE_DIR}/compile_headers.py ${internal_inc_dir} ${CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER_ARG1} -fsyntax-only -I${root_inc_dir} -I${internal_inc_dir} ${other_inc_dirs} ${CMAKE_CXX_FLAGS}") # Test that no public header includes an internal header add_test(clean-public-${location}-headers ${CMAKE_CURRENT_SOURCE_DIR}/check_public_headers.py ${public_inc_dir}) endforeach() add_test(cleanincludes ${CMAKE_CURRENT_SOURCE_DIR}/includechecker.py ${CMAKE_SOURCE_DIR}/include) add_test(noglobalincludes ${CMAKE_CURRENT_SOURCE_DIR}/check_global_usage.py ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include) unity-scopes-api-0.4.2+14.04.20140408/test/whitespace/0000755000015301777760000000000012320776463022453 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/test/whitespace/check_whitespace.sh0000755000015301777760000000275412320776161026306 0ustar pbusernogroup00000000000000#!/bin/sh # # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # # # Check that files below the specified directory don't have lines with trailing whitespace. # Print out a messsage for each file with trailing whitespace and exit with non-zero status # if any such file is found. # usage() { echo "usage: check_whitespace.sh dir [ignore_dir]" >&2 exit 2 } [ $# -lt 1 ] && usage [ $# -gt 2 ] && usage ignore="grep -v CMakeFile" [ $# -eq 2 ] && { ignore="$ignore | grep -v \"$2\"" } err=no for file in `find "$1" \ -name '*.cpp' -o \ -name '*.h' -o \ -name '*.py' -o \ -name '*.sh' -o \ -name 'CMakeLists.txt' -o \ -name '*.cmake' \ | grep -v CMakeFiles \ | eval $ignore` do grep -q '[ ]$' "$file" [ $? -eq 0 ] && { echo "$file: trailing whitespace" err=yes } done [ $err = yes ] && exit 1 exit 0 unity-scopes-api-0.4.2+14.04.20140408/test/whitespace/check_whitespace.py0000755000015301777760000000746612320776161026331 0ustar pbusernogroup00000000000000#! /usr/bin/env python3 # # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # # # Little helper program to test that source files do not contain trailing whitespace # or tab indentation. # # Usage: check_whitespace.py directory [ignore_prefix] # # The directory specifies the (recursive) location of the source files. Any # files with a path that starts with ignore_prefix are not checked. This is # useful to exclude files that are generated into the build directory. # # See the file_pat definition below for a list of files that are checked. # import argparse import os import re import sys # Print msg on stderr, preceded by program name and followed by newline def error(msg): print(os.path.basename(sys.argv[0]) + ": " + msg, file=sys.stderr) # Function to raise errors encountered by os.walk def raise_error(e): raise e # Scan lines in file_path for bad whitespace. For each file, # print the line numbers that have whitespace issues whitespace_pat = re.compile(r'.*[ \t]$') tab_indent_pat = re.compile(r'^ *\t') def scan_for_bad_whitespace(file_path): global tab_indent_pat, whitespace_pat errors = [] newlines_at_end = 0 with open(file_path, 'rt', encoding='utf-8') as ifile: for lino, line in enumerate(ifile, start=1): if whitespace_pat.match(line) or tab_indent_pat.match(line): errors.append(lino) if line == "\n": newlines_at_end += 1 else: newlines_at_end = 0 if 0 < len(errors) <= 10: if len(errors) > 1: plural = 's' else: plural = '' print("%s: bad whitespace in line%s %s" % (file_path, plural, ", ".join((str(i) for i in errors)))) elif errors: print("%s: bad whitespace in multiple lines" % file_path) if newlines_at_end: print("%s: multiple new lines at end of file" % file_path) return bool(errors) or newlines_at_end # Parse args parser = argparse.ArgumentParser(description = 'Test that source files do not contain trailing whitespace.') parser.add_argument('dir', nargs = 1, help = 'The directory to (recursively) search for source files') parser.add_argument('ignore_prefix', nargs = '?', default=None, help = 'Ignore source files with a path that starts with the given prefix.') args = parser.parse_args() # Files we want to check for trailing whitespace. file_pat = r'(.*\.(c|cpp|h|hpp|hh|in|install|js|py|qml|sh)$)|(.*CMakeLists\.txt$)' pat = re.compile(file_pat) # Find all the files with matching file extension in the specified # directory and check them for trailing whitespace. directory = os.path.abspath(args.dir[0]) ignore = args.ignore_prefix and os.path.abspath(args.ignore_prefix) or None found_whitespace = False try: for root, dirs, files in os.walk(directory, onerror = raise_error): for file in files: path = os.path.join(root, file) if not (ignore and path.startswith(ignore)) and pat.match(file): if scan_for_bad_whitespace(path): found_whitespace = True except OSError as e: error("cannot create file list for \"" + dir + "\": " + e.strerror) sys.exit(1) if found_whitespace: sys.exit(1) unity-scopes-api-0.4.2+14.04.20140408/test/whitespace/CMakeLists.txt0000644000015301777760000000030512320776161025204 0ustar pbusernogroup00000000000000# # Test that all source files, cmakefiles, etc. do not contain trailing whitespace. # add_test(whitespace ${CMAKE_CURRENT_SOURCE_DIR}/check_whitespace.py ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}) unity-scopes-api-0.4.2+14.04.20140408/test/CMakeLists.txt0000644000015301777760000000046012320776161023052 0ustar pbusernogroup00000000000000set(TEST_BUILD_ROOT ${CMAKE_CURRENT_BINARY_DIR}) configure_file(scope-api-testconfig.h.in scope-api-testconfig.h @ONLY) include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_subdirectory(gtest) if(${slowtests}) add_subdirectory(headers) endif() add_subdirectory(copyright) add_subdirectory(whitespace) unity-scopes-api-0.4.2+14.04.20140408/tsan-suppress0000644000015301777760000000017612320776161022111 0ustar pbusernogroup00000000000000race:epoll_ctl race:close race:operator delete(void*) race:memcmp race:strlen race:memcpy race:free race:QThread::setPriority unity-scopes-api-0.4.2+14.04.20140408/astyle-config0000644000015301777760000000216712320776161022030 0ustar pbusernogroup00000000000000# Options for formatting code with astyle. # # This helps to make code match the style guide. # # Use like this: # # astyle --options=astyle-config mfile.h myfile.cpp # # Occasionally, astyle does something silly (particularly with lambdas), so it's # still necessary to scan the changes for things that are wrong. # But, for most files, it does a good job. # # Please consider using this before checking code in for review. Code reviews shouldn't # have to deal with layout issues, they are just a distraction. It's better to be able # to focus on semantics in a code review, with style issues out of the way. --formatted --style=allman --min-conditional-indent=2 --indent-switches --max-instatement-indent=120 --pad-header --align-pointer=type --align-reference=type --add-brackets --convert-tabs --close-templates --max-code-length=120 # --pad-oper # # Commented out for now. It changes # # for (int i=0; i<10; ++i) # to # for (int i = 0; i < 10; ++i) # # Unfortunately, it also messes with rvalue references: # # ResourcePtr& operator=(ResourcePtr&& r); # # becomes: # # ResourcePtr& operator=(ResourcePtr && r); unity-scopes-api-0.4.2+14.04.20140408/scoperunner/0000755000015301777760000000000012320776463021703 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/scoperunner/scoperunner.cpp0000644000015301777760000002166112320776161024753 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace unity::scopes; using namespace unity::scopes::internal; namespace { char const* prog_name; void error(string const& msg) { assert(!msg.empty()); cerr << prog_name << ": " << msg << endl; } bool has_suffix(string const& s, string const& suffix) { auto s_len = s.length(); auto suffix_len = suffix.length(); if (s_len >= suffix_len) { return s.compare(s_len - suffix_len, suffix_len, suffix) == 0; } return false; } string strip_suffix(string const& s, string const& suffix) { auto s_len = s.length(); auto suffix_len = suffix.length(); if (s_len >= suffix_len) { if (s.compare(s_len - suffix_len, suffix_len, suffix) == 0) { return string(s, 0, s_len - suffix_len); } } return s; } // One thread for each scope, plus a future that the thread sets when it finishes. struct ThreadFuture { thread t; std::future f; }; // Each thread provides its own ID on a queue when it finishes. That allows us to // then locate the thread in the map. The promise is set by the thread so we can // find out what happened to it and join with it. Unfortunately, we have to jump // through these hoops because there is no way to wait on multiple futures in C++ 11. unordered_map threads; ThreadSafeQueue finished_threads; // Scope thread start function. void scope_thread(std::shared_ptr trap, MWStateReceiverProxy reg_state_receiver, string const& mw_kind, string const& mw_config, string const& runtime_config, string const& scope_id, string const& lib_dir, promise finished_promise) { try { // Instantiate the run time, create the middleware, load the scope from its // shared library, and call the scope's start() method. auto rt = RuntimeImpl::create(scope_id, runtime_config); auto mw = rt->factory()->create(scope_id, mw_kind, mw_config); ScopeLoader::SPtr loader = ScopeLoader::load(scope_id, lib_dir + "lib" + scope_id + ".so", rt->registry()); loader->start(); // Give a thread to the scope to do with as it likes. If the scope doesn't want to use it and // immediately returns from run(), that's fine. auto run_future = std::async(launch::async, [loader] { loader->scope_base()->run(); }); // Create a servant for the scope and register the servant. auto scope = unique_ptr(new ScopeObject(rt.get(), loader->scope_base())); auto proxy = mw->add_scope_object(scope_id, move(scope)); trap->signal_raised().connect([loader, mw, reg_state_receiver, scope_id](core::posix::Signal) { // Inform the registry that this scope is shutting down reg_state_receiver->push_state(scope_id, StateReceiverObject::State::ScopeStopping); loader->stop(); mw->stop(); }); // Inform the registry that this scope is now ready to process requests reg_state_receiver->push_state(scope_id, StateReceiverObject::State::ScopeReady); mw->wait_for_shutdown(); // Collect exit status from the run thread. If this throws, the ScopeLoader // destructor will still call stop() on the scope. run_future.get(); finished_promise.set_value(); } catch (...) { finished_promise.set_exception(current_exception()); } finished_threads.push(this_thread::get_id()); } // Run each of the scopes in config_files in a separate thread and wait for each thread to finish. // Return the number of threads that did not terminate normally. int run_scopes(string const& runtime_config, vector config_files) { auto trap = core::posix::trap_signals_for_all_subsequent_threads( { core::posix::Signal::sig_hup, core::posix::Signal::sig_term }); std::thread trap_worker([trap]() { trap->run(); }); // Retrieve the registry middleware and create a proxy to its state receiver RuntimeConfig rt_config(runtime_config); RegistryConfig reg_conf(rt_config.registry_identity(), rt_config.registry_configfile()); auto reg_runtime = RuntimeImpl::create(rt_config.registry_identity(), runtime_config); auto reg_mw = reg_runtime->factory()->find(reg_runtime->registry_identity(), reg_conf.mw_kind()); auto reg_state_receiver = reg_mw->create_state_receiver_proxy("StateReceiver"); for (auto file : config_files) { string file_name = basename(const_cast(string(file).c_str())); // basename() modifies its argument auto dir_len = file.size() - file_name.size(); string dir = file.substr(0, dir_len); if (*dir.rbegin() != '/') { dir += "/"; } string scope_id = strip_suffix(file_name, ".ini"); // For each scope, create a thread that loads the scope and initializes it. // Each thread gets a promise to indicate when it is finished. When a thread // completes, it fulfils the promise, and pushes its ID onto the finished queue. // We collect exit status from the thread via the future from each promise. promise p; auto f = p.get_future(); thread t(scope_thread, trap, reg_state_receiver, reg_conf.mw_kind(), reg_conf.mw_configfile(), runtime_config, scope_id, dir, move(p)); auto id = t.get_id(); threads[id] = ThreadFuture { move(t), move(f) }; } // Now wait for the threads to finish (in any order). int num_errors = 0; for (int i = threads.size(); i > 0; --i) { try { auto id = finished_threads.wait_and_pop(); auto it = threads.find(id); assert(it != threads.end()); it->second.t.join(); it->second.f.get(); // This will throw if the thread terminated due to an exception } catch (std::exception const& e) { error(e.what()); ++num_errors; } catch (...) { error("unknown exception"); ++num_errors; } } trap->stop(); if (trap_worker.joinable()) trap_worker.join(); return num_errors; } } // namespace int main(int argc, char* argv[]) { // sig masks are inherited by child processes when forked. // we do not want to inherit our parent's (scoperegistry) // sig mask, hence we clear it immediately on entry. sigset_t set; ::sigemptyset(&set); ::pthread_sigmask(SIG_SETMASK, &set, nullptr); prog_name = basename(argv[0]); if (argc < 3) { cerr << "usage: " << prog_name << " runtime.ini configfile.ini [configfile.ini ...]" << endl; return 2; } char const* const runtime_config = argv[1]; int exit_status = 1; try { vector config_files; for (int i = 2; i < argc; ++i) { if (!has_suffix(argv[i], ".ini")) { throw ConfigException(string("invalid config file name: \"") + argv[i] + "\": missing .ini extension"); } config_files.push_back(argv[i]); } exit_status = run_scopes(runtime_config, config_files); } catch (std::exception const& e) { error(e.what()); } catch (string const& e) { error("fatal error: " + e); } catch (char const* e) { error(string("fatal error: ") + e); } catch (...) { error("terminated due to unknown exception"); } return exit_status; } unity-scopes-api-0.4.2+14.04.20140408/scoperunner/CMakeLists.txt0000644000015301777760000000033012320776161024432 0ustar pbusernogroup00000000000000set(SRC scoperunner.cpp) add_executable(scoperunner ${SRC}) target_link_libraries(scoperunner ${UNITY_SCOPES_LIB} ${OTHER_LIBS}) install(TARGETS scoperunner RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/scoperunner) unity-scopes-api-0.4.2+14.04.20140408/demo/0000755000015301777760000000000012320776463020264 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/demo/Zmq.ini.in0000644000015301777760000000007312320776161022134 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp unity-scopes-api-0.4.2+14.04.20140408/demo/Registry.ini.in0000644000015301777760000000062712320776161023202 0ustar pbusernogroup00000000000000[Registry] Middleware = Zmq Zmq.Endpoint = ipc:///tmp/Registry Zmq.EndpointDir = /tmp Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini Scope.InstallDir = @CMAKE_CURRENT_BINARY_DIR@/scopes OEM.InstallDir = /custom/usr/lib/@CMAKE_LIBRARY_ARCHITECTURE@/unity/scopes Scoperunner.Path = @CMAKE_BINARY_DIR@/scoperunner/scoperunner SS.Registry.Identity = SSRegistry SS.Registry.Endpoint = ipc:///tmp/SSRegistry unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/0000755000015301777760000000000012320776463021560 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-N/0000755000015301777760000000000012320776463023064 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-N/scope-N.ini.in0000644000015301777760000000015212320776161025467 0ustar pbusernogroup00000000000000[ScopeConfig] DisplayName = scope-N.DisplayName Description = scope-N.Description Author = Canonical Ltd. unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-N/CMakeLists.txt0000644000015301777760000000012412320776161025614 0ustar pbusernogroup00000000000000add_library(scope-N MODULE scope-N.cpp) configure_file(scope-N.ini.in scope-N.ini) unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-N/scope-N.cpp0000644000015301777760000000446112320776161025074 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #define EXPORT __attribute__ ((visibility ("default"))) using namespace std; using namespace unity::scopes; // Simplest possible scope: does absolutely nothing other than to implement the pure virtuals // it inherits from its base classes. Despite this, the scope works correctly with a client. class MyQuery : public SearchQueryBase { public: MyQuery() { } ~MyQuery() { } virtual void cancelled() override { cerr << "scope-no-op: received cancel request" << endl; } virtual void run(SearchReplyProxy const&) override { cerr << "scope-no-op: received query" << endl; this_thread::sleep_for(chrono::seconds(3)); cerr << "scope-no-op: query complete" << endl; } }; class MyScope : public ScopeBase { public: virtual int start(string const&, RegistryProxy const&) override { return VERSION; } virtual void stop() override {} virtual SearchQueryBase::UPtr search(CannedQuery const&, SearchMetadata const&) override { return SearchQueryBase::UPtr(new MyQuery); } virtual PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const&) override { return nullptr; } }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { return new MyScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-B/0000755000015301777760000000000012320776463023050 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-B/scope-B.ini.in0000644000015301777760000000015212320776161025437 0ustar pbusernogroup00000000000000[ScopeConfig] DisplayName = scope-B.DisplayName Description = scope-B.Description Author = Canonical Ltd. unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-B/scope-B.cpp0000644000015301777760000001274212320776161025045 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ // In this demo we include individual headers. You may also, // if you prefer, include just the unity-scopes.h convenience // header. #include #include #include #include #include #include #include #include #include #include #define EXPORT __attribute__ ((visibility ("default"))) using namespace std; using namespace unity::scopes; // Example scope B: aggregates from scope C and D. // A Receiver instance remembers the query string and the reply object that was passed // from upstream. Results from the child scopes are sent to that upstream reply object. class Receiver: public SearchListenerBase { public: virtual void push(Category::SCPtr category) override { cout << "received category: id=" << category->id() << endl; } virtual void push(CategorisedResult result) override { cout << "received result from " << scope_id_ << ": " << result.uri() << ", " << result.title() << endl; try { result.set_category(upstream_->lookup_category("catB")); upstream_->push(std::move(result)); } catch (const unity::InvalidArgumentException &e) { cerr << "error pushing result: " << e.what() << endl; } } virtual void finished(Reason reason, string const& error_message) override { cout << "query to " << scope_id_ << " complete, status: " << to_string(reason); if (reason == ListenerBase::Error) { cout << ": " << error_message; } cout << endl; } Receiver(string const& scope_id, SearchReplyProxy const& upstream) : scope_id_(scope_id), upstream_(upstream) { } private: string scope_id_; SearchReplyProxy upstream_; }; class MyQuery : public SearchQueryBase { public: MyQuery(string const& scope_id, CannedQuery const& query, ScopeProxy const& scope_c, ScopeProxy const& scope_d) : scope_id_(scope_id), query_(query), scope_c_(scope_c), scope_d_(scope_d) { } virtual void cancelled() { cout << "query to " << scope_id_ << " was cancelled" << endl; } virtual void run(SearchReplyProxy const& upstream_reply) { // note, category id must mach categories received from scope C and D, otherwise result pushing will fail. try { CategoryRenderer rdr; upstream_reply->register_category("catB", "title", "icon", rdr); } catch (const unity::InvalidArgumentException &e) // this shouldn't happen { cerr << "error registering category: " << e.what() << endl; assert(0); } SearchListenerBase::SPtr reply(new Receiver(scope_id_, upstream_reply)); subsearch(scope_c_, query_.query_string(), reply); subsearch(scope_d_, query_.query_string(), reply); } private: string scope_id_; CannedQuery query_; ScopeProxy scope_c_; ScopeProxy scope_d_; }; // MyScope aggregates from C and D. class MyScope : public ScopeBase { public: virtual int start(string const& scope_id, RegistryProxy const& registry) override { scope_id_ = scope_id; if (!registry) { throw ConfigException(scope_id + ": No registry available, cannot locate child scopes"); } // Lock up scopes C and D in the registry and remember their proxies. auto meta_c = registry->get_metadata("scope-C"); scope_c_ = meta_c.proxy(); auto meta_d = registry->get_metadata("scope-D"); scope_d_ = meta_d.proxy(); return VERSION; } virtual void stop() override {} virtual SearchQueryBase::UPtr search(CannedQuery const& q, SearchMetadata const&) override { SearchQueryBase::UPtr query(new MyQuery(scope_id_, q, scope_c_, scope_d_)); cout << "scope-B: created query: \"" << q.query_string() << "\"" << endl; return query; } virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const&) override { cout << "scope-B: preview: \"" << result.uri() << "\"" << endl; return nullptr; } private: string scope_id_; ScopeProxy scope_c_; ScopeProxy scope_d_; }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { return new MyScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-B/CMakeLists.txt0000644000015301777760000000012412320776161025600 0ustar pbusernogroup00000000000000add_library(scope-B MODULE scope-B.cpp) configure_file(scope-B.ini.in scope-B.ini) unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-S/0000755000015301777760000000000012320776463023071 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-S/scope-S.ini.in0000644000015301777760000000015212320776161025501 0ustar pbusernogroup00000000000000[ScopeConfig] DisplayName = scope-S.DisplayName Description = scope-S.Description Author = Canonical Ltd. unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-S/scope-S.cpp0000644000015301777760000000703412320776161025105 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #define EXPORT __attribute__ ((visibility ("default"))) using namespace std; using namespace unity::scopes; // Example scope A: replies synchronously to a query. (Replies are returned before returning from the run() method.) class MyQuery : public SearchQueryBase { public: MyQuery(CannedQuery const& query, CategoryRenderer const& renderer) : query_(query), renderer_(renderer) { cerr << "MyQuery/" << query.query_string() << " created" << endl; } ~MyQuery() { cerr << "MyQuery/" << query_.query_string() << " destroyed" << endl; } virtual void cancelled() override { cerr << "MyQuery/" << query_.query_string() << " cancelled" << endl; } virtual void run(SearchReplyProxy const& reply) override { cerr << "scope-slow: run called for \"" << query_.query_string() << "\"" << endl; this_thread::sleep_for(chrono::seconds(20)); auto cat = reply->register_category("cat1", "Category 1", "", renderer_); CategorisedResult result(cat); result.set_uri("uri"); result.set_title("scope-slow: result 1 for query \"" + query_.query_string() + "\""); reply->push(result); cout << "scope-slow: query \"" << query_.query_string() << "\" complete" << endl; } private: CannedQuery query_; CategoryRenderer renderer_; }; class MyScope : public ScopeBase { public: virtual int start(string const&, RegistryProxy const&) override { return VERSION; } virtual void stop() override {} virtual SearchQueryBase::UPtr search(CannedQuery const& q, SearchMetadata const& hints) override { SearchQueryBase::UPtr query(new MyQuery(q, renderer_)); cout << "scope-slow: created query: \"" << q.query_string() << "\"" << endl; if (hints.cardinality() > 0) { cerr << "result cardinality: " << hints.cardinality() << endl; } cerr << "locale: " << hints.locale() << endl; return query; } virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const&) override { cout << "scope-S: preview: \"" << result.uri() << "\"" << endl; return nullptr; } private: CategoryRenderer renderer_; }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { return new MyScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-S/CMakeLists.txt0000644000015301777760000000012412320776161025621 0ustar pbusernogroup00000000000000add_library(scope-S MODULE scope-S.cpp) configure_file(scope-S.ini.in scope-S.ini) unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-A/0000755000015301777760000000000012320776463023047 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-A/scope-A.ini.in0000644000015301777760000000031012320776161025431 0ustar pbusernogroup00000000000000[ScopeConfig] DisplayName = scope-A.DisplayName Description = scope-A.Description Art = scope-A.Art Author = Canonical Ltd. Icon = scope-A.Icon SearchHint = scope-A.SearchHint HotKey = scope-A.HotKey unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-A/scope-A.cpp0000644000015301777760000001202212320776161025032 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ // You may also include individual headers if you prefer. #include #include #define EXPORT __attribute__ ((visibility ("default"))) using namespace std; using namespace unity::scopes; // Example scope A: replies synchronously to a query. (Replies are returned before returning from the run() method.) class MyQuery : public SearchQueryBase { public: MyQuery(CannedQuery const& query) : query_(query) { } ~MyQuery() { } virtual void cancelled() override { } virtual void run(SearchReplyProxy const& reply) override { DepartmentList departments({{"news", query_, "News", {{"news-world", query_, "World"}, {"news-europe", query_, "Europe"}}}, {"sport", query_, "Sport"}}); reply->register_departments(departments); Filters filters; auto filter = OptionSelectorFilter::create("f1", "Options"); filter->add_option("1", "Option 1"); filter->add_option("2", "Option 2"); filters.push_back(filter); FilterState filter_state; // TODO: push real state from query obj reply->push(filters, filter_state); CategoryRenderer rdr; auto cat = reply->register_category("cat1", "Category 1", "", rdr); CategorisedResult res(cat); res.set_uri("uri"); res.set_title("scope-A: result 1 for query \"" + query_.query_string() + "\""); res.set_art("icon"); res.set_dnd_uri("dnd_uri"); reply->push(res); CannedQuery q("scope-A", query_.query_string(), ""); Annotation annotation(Annotation::Type::Link); annotation.add_link("More...", q); reply->register_annotation(annotation); cout << "scope-A: query \"" << query_.query_string() << "\" complete" << endl; } private: CannedQuery query_; }; class MyPreview : public PreviewQueryBase { public: MyPreview(string const& uri) : uri_(uri) { } ~MyPreview() { } virtual void cancelled() override { } virtual void run(PreviewReplyProxy const& reply) override { PreviewWidgetList widgets; widgets.emplace_back(PreviewWidget(R"({"id": "header", "type": "header", "title": "title", "subtitle": "author", "rating": "rating"})")); widgets.emplace_back(PreviewWidget(R"({"id": "img", "type": "image", "art": "screenshot-url"})")); PreviewWidget w("img2", "image"); w.add_attribute_value("zoomable", Variant(false)); w.add_attribute_mapping("art", "screenshot-url"); widgets.emplace_back(w); ColumnLayout layout1col(1); layout1col.add_column({"header", "title"}); ColumnLayout layout2col(2); layout2col.add_column({"header", "title"}); layout2col.add_column({"author", "rating"}); ColumnLayout layout3col(3); layout3col.add_column({"header", "title"}); layout3col.add_column({"author"}); layout3col.add_column({"rating"}); reply->register_layout({layout1col, layout2col, layout3col}); reply->push(widgets); reply->push("author", Variant("Foo")); reply->push("rating", Variant("4 blah")); cout << "scope-A: preview for \"" << uri_ << "\" complete" << endl; } private: string uri_; }; class MyScope : public ScopeBase { public: virtual int start(string const&, RegistryProxy const&) override { return VERSION; } virtual void stop() override {} virtual SearchQueryBase::UPtr search(CannedQuery const& q, SearchMetadata const&) override { SearchQueryBase::UPtr query(new MyQuery(q)); cout << "scope-A: created query: \"" << q.query_string() << "\"" << endl; return query; } virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const&) override { PreviewQueryBase::UPtr preview(new MyPreview(result.uri())); cout << "scope-A: created previewer: \"" << result.uri() << "\"" << endl; return preview; } }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { return new MyScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-A/scope-A.map0000644000015301777760000000016612320776161025033 0ustar pbusernogroup00000000000000{ global: "unity_scope_create"; "unity_scope_destroy"; local: extern "C++" { *; }; }; unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-A/CMakeLists.txt0000644000015301777760000000101012320776161025572 0ustar pbusernogroup00000000000000set(symbol_map "${CMAKE_CURRENT_SOURCE_DIR}/scope-A.map") add_library(scope-A MODULE scope-A.cpp) # Add_dependencies should be used sparingly. In this case we need the global # header to be generated before we start building the client binary. add_dependencies(scope-A globalheader) set_target_properties(scope-A PROPERTIES LINK_FLAGS "${ldflags} -Wl,--version-script,${symbol_map}") set_target_properties(scope-A PROPERTIES LINK_DEPENDS ${symbol_map}) configure_file(scope-A.ini.in scope-A.ini) unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-D/0000755000015301777760000000000012320776463023052 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-D/scope-D.cpp0000644000015301777760000002054612320776161025052 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define EXPORT __attribute__ ((visibility ("default"))) using namespace std; using namespace unity::scopes; // Simple queue that stores query-string/reply pairs, using MyQuery* as a key for removal. // The put() method adds a pair at the tail, and the get() method returns a pair at the head. // get() suspends the caller until an item is available or until the queue is told to finish. // get() returns true if it returns a pair, false if the queue was told to finish. // remove() searches for the entry with the given key and erases it. class MyQuery; class Queue { public: void put(MyQuery const* query, string const& query_string, SearchReplyProxy const& reply_proxy) { std::lock_guard lock(mutex_); queries_.push_back(QueryData { query, query_string, reply_proxy }); condvar_.notify_one(); } bool get(string& query_string, SearchReplyProxy& reply_proxy) { std::unique_lock lock(mutex_); condvar_.wait(lock, [this] { return !queries_.empty() || done_; }); if (done_) { condvar_.notify_all(); } else { auto qd = queries_.front(); queries_.pop_front(); query_string = qd.query_string; reply_proxy = qd.reply_proxy; } return !done_; } void remove(MyQuery const* query) { std::lock_guard lock(mutex_); QueryData qd { query, "", nullptr }; auto it = std::find(queries_.begin(), queries_.end(), qd); if (it != queries_.end()) { cerr << "Queue: removed query: " << it->query_string << endl; queries_.erase(it); } else { cerr << "Queue: did not find entry to be removed" << endl; } } void finish() { std::unique_lock lock(mutex_); queries_.clear(); done_ = true; condvar_.notify_all(); } Queue() : done_(false) { } private: struct QueryData { MyQuery const* query; string query_string; SearchReplyProxy reply_proxy; bool operator==(QueryData const& rhs) const { return query == rhs.query; } }; std::list queries_; bool done_; std::mutex mutex_; std::condition_variable condvar_; }; class MyQuery : public SearchQueryBase { public: MyQuery(string const& scope_id, CannedQuery const& query, Queue& queue) : scope_id_(scope_id), query_(query), queue_(queue) { cerr << "query instance for \"" << scope_id_ << ":" << query.query_string() << "\" created" << endl; } virtual ~MyQuery() { cerr << "query instance for \"" << scope_id_ << ":" << query_.query_string() << "\" destroyed" << endl; } virtual void cancelled() override { // Informational callback to let a query know when it was cancelled. The query should // clean up any resources it has allocated, stop pushing results, and arrange for // run() to return (if still active). // Ignoring query cancellation does not do any direct harm, but wastes CPU cycles: any // results that are pushed once a query is cancelled are ignored anyway. // The main purpose of this callback to give queries a chance to stop doing whatever // work may still be in progress on a query. Note that cancellations are frequent; // not responding to cancelled() correctly causes loss of performance. cerr << "query for \"" << scope_id_ << ":" << query_.query_string() << "\" cancelled" << endl; } virtual void run(SearchReplyProxy const& reply) override { // The query can do anything it likes with this method, that is, run() can push results // directly on the provided reply, or it can save the reply for later use and return from // run(). It is OK to push results on the reply from a different thread. // The only obligation on run() is that, if cancelled() is called, and run() is still active // at that time, run() must tidy up and return in a timely fashion. queue_.put(this, query_.query_string(), reply); } private: string scope_id_; CannedQuery query_; Queue& queue_; }; // Example scope D: replies asynchronously to queries. // The scope's run() method is used as a worker thread that pulls queries from a queue. // The MyQuery object's run() method adds the query string and the reply proxy to the queue // and signals the worker thread, and then returns. The worker thread pushes the results. class MyScope : public ScopeBase { public: virtual int start(string const& scope_id, RegistryProxy const&) override { scope_id_ = scope_id; return VERSION; } virtual void stop() override { queue_.finish(); done_.store(true); } virtual void run() override { CategoryRenderer rdr; // What run() does is up to the scope. For example, we could set up and run an event loop here. // It's OK for run() to be empty and return immediately, or to take as long it likes to complete. // The only obligation is that, if the scopes run time calls stop(), run() must tidy up and return // in as timely a manner as possible. while (!done_.load()) { string query; SearchReplyProxy reply_proxy; if (queue_.get(query, reply_proxy) && !done_.load()) { auto cat = reply_proxy->register_category("cat1", "Category 1", "", rdr); for (int i = 1; i < 5; ++i) { CategorisedResult result(cat); result.set_uri("uri"); result.set_title(scope_id_ + ": result " + to_string(i) + " for query \"" + query + "\""); result.set_art("icon"); result.set_dnd_uri("dnd_uri"); if (!reply_proxy->push(result)) { break; // Query was cancelled } sleep(1); } cerr << scope_id_ << ": query \"" << query << "\" complete" << endl; } } } virtual SearchQueryBase::UPtr search(CannedQuery const& q, SearchMetadata const&) override { SearchQueryBase::UPtr query(new MyQuery(scope_id_, q, queue_)); cerr << scope_id_ << ": created query: \"" << q.query_string() << "\"" << endl; return query; } virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const&) override { cout << scope_id_ << ": preview: \"" << result.uri() << "\"" << endl; return nullptr; } MyScope() : done_(false) { } private: string scope_id_; Queue queue_; std::atomic_bool done_; }; // External entry points to allocate and deallocate the scope. extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { return new MyScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-D/scope-D.ini.in0000644000015301777760000000015212320776161025443 0ustar pbusernogroup00000000000000[ScopeConfig] DisplayName = scope-D.DisplayName Description = scope-D.Description Author = Canonical Ltd. unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-D/CMakeLists.txt0000644000015301777760000000012412320776161025602 0ustar pbusernogroup00000000000000add_library(scope-D MODULE scope-D.cpp) configure_file(scope-D.ini.in scope-D.ini) unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/CMakeLists.txt0000644000015301777760000000023412320776161024312 0ustar pbusernogroup00000000000000add_subdirectory(scope-A) add_subdirectory(scope-B) add_subdirectory(scope-C) add_subdirectory(scope-D) add_subdirectory(scope-N) add_subdirectory(scope-S) unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-C/0000755000015301777760000000000012320776463023051 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-C/scope-C.ini.in0000644000015301777760000000015212320776161025441 0ustar pbusernogroup00000000000000[ScopeConfig] DisplayName = scope-C.DisplayName Description = scope-C.Description Author = Canonical Ltd. unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-C/scope-C.cpp0000644000015301777760000001664712320776161025057 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define EXPORT __attribute__ ((visibility ("default"))) using namespace std; using namespace unity::scopes; // Simple queue that stores query-string/reply pairs, using MyQuery* as a key for removal. // The put() method adds a pair at the tail, and the get() method returns a pair at the head. // get() suspends the caller until an item is available or until the queue is told to finish. // get() returns true if it returns a pair, false if the queue was told to finish. // remove() searches for the entry with the given key and erases it. class MyQuery; class Queue { public: void put(MyQuery const* query, string const& query_string, SearchReplyProxy const& reply_proxy) { std::lock_guard lock(mutex_); queries_.push_back(QueryData { query, query_string, reply_proxy }); condvar_.notify_one(); } bool get(string& query_string, SearchReplyProxy& reply_proxy) { std::unique_lock lock(mutex_); condvar_.wait(lock, [this] { return !queries_.empty() || done_; }); if (done_) { condvar_.notify_all(); } else { auto qd = queries_.front(); queries_.pop_front(); query_string = qd.query_string; reply_proxy = qd.reply_proxy; } return !done_; } void remove(MyQuery const* query) { std::lock_guard lock(mutex_); QueryData qd { query, "", nullptr }; auto it = std::find(queries_.begin(), queries_.end(), qd); if (it != queries_.end()) { cerr << "Queue: removed query: " << it->query_string << endl; queries_.erase(it); } else { cerr << "Queue: did not find entry to be removed" << endl; } } void finish() { std::unique_lock lock(mutex_); queries_.clear(); done_ = true; condvar_.notify_all(); } Queue() : done_(false) { } private: struct QueryData { MyQuery const* query; string query_string; SearchReplyProxy reply_proxy; bool operator==(QueryData const& rhs) const { return query == rhs.query; } }; std::list queries_; bool done_; std::mutex mutex_; std::condition_variable condvar_; }; // Example scope C: Does not use the query's run() method other than to remember the query. // The run() method of the scope acts as a worker thread to push replies to remembered queries. // This example shows that letting run() return immediately is OK, and that the MyQuery instance stays // alive as long as it can still be cancelled, which is while there is at least one // SearchReplyProxy still in existence for this query. class MyQuery : public SearchQueryBase { public: MyQuery(CannedQuery const& query, Queue& queue) : query_(query), queue_(queue) { cerr << "My Query created" << endl; } ~MyQuery() { cerr << "My Query destroyed" << endl; } virtual void cancelled() override { // Remove this query from the queue, if it is still there. // If it isn't, and the worker thread is still working on this // query, the worker thread's next call to push() will return false, // causing the worker thread to stop working on this query. queue_.remove(this); cerr << "scope-C: \"" + query_.to_string() + "\" cancelled" << endl; } virtual void run(SearchReplyProxy const& reply) override { queue_.put(this, query_.query_string(), reply); cerr << "scope-C: run() returning" << endl; } private: CannedQuery query_; Queue& queue_; }; class MyActivation : public ActivationQueryBase { ActivationResponse activate() override { return ActivationResponse(ActivationResponse::Status::ShowDash); } }; class MyScope : public ScopeBase { public: virtual int start(string const& scope_id, RegistryProxy const&) override { scope_id_ = scope_id; return VERSION; } virtual void stop() override { queue.finish(); } virtual void run() override { for (;;) { string query; SearchReplyProxy reply; if (!queue.get(query, reply)) { cerr << "worker thread terminating, queue was cleared" << endl; break; // stop() was called. } auto cat = reply->lookup_category("cat1"); if (cat == nullptr) { CategoryRenderer rdr; cat = reply->register_category("cat1", "Category 1", "", rdr); } for (int i = 1; i < 4; ++i) { CategorisedResult result(cat); result.set_uri("uri"); result.set_title("scope-C: result " + to_string(i) + " for query \"" + query + "\""); result.set_art("icon"); result.set_dnd_uri("dnd_uri"); result.set_intercept_activation(); if (!reply->push(result)) { break; // Query was cancelled } sleep(1); } } } virtual SearchQueryBase::UPtr search(CannedQuery const& q, SearchMetadata const&) override { cout << scope_id_ << ": created query: \"" << q.query_string() << "\"" << endl; return SearchQueryBase::UPtr(new MyQuery(q, queue)); } virtual ActivationQueryBase::UPtr activate(Result const& result, ActionMetadata const& /* hints */) override { cout << scope_id_ << ": activate: \"" << result.uri() << "\"" << endl; return ActivationQueryBase::UPtr(new MyActivation()); } virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const&) override { cout << "scope-C: preview: \"" << result.uri() << "\"" << endl; return nullptr; } private: string scope_id_; Queue queue; }; extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { return new MyScope; } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { delete scope_base; } } unity-scopes-api-0.4.2+14.04.20140408/demo/scopes/scope-C/CMakeLists.txt0000644000015301777760000000012412320776161025601 0ustar pbusernogroup00000000000000add_library(scope-C MODULE scope-C.cpp) configure_file(scope-C.ini.in scope-C.ini) unity-scopes-api-0.4.2+14.04.20140408/demo/CMakeLists.txt0000644000015301777760000000103612320776161023017 0ustar pbusernogroup00000000000000add_subdirectory(scopes) add_subdirectory(stand-alone) configure_file(Runtime.ini.in Runtime.ini) configure_file(Registry.ini.in Registry.ini) configure_file(Zmq.ini.in Zmq.ini) add_definitions(-DDEMO_RUNTIME_PATH="${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini") add_executable(client client.cpp) # Add_dependencies should be used sparingly. In this case we need the global # header to be generated before we start building the client binary. add_dependencies(client globalheader) target_link_libraries(client ${UNITY_SCOPES_LIB} ${OTHER_LIBS}) unity-scopes-api-0.4.2+14.04.20140408/demo/stand-alone/0000755000015301777760000000000012320776463022471 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/demo/stand-alone/Zmq.ini.in0000644000015301777760000000007312320776161024341 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp unity-scopes-api-0.4.2+14.04.20140408/demo/stand-alone/stand-alone-client.cpp0000644000015301777760000000653012320776161026655 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ // You may also include individual headers if you prefer. #include #include #include #include #include #include #include #include #include using namespace std; using namespace unity::scopes; class Receiver : public SearchListenerBase { public: Receiver() : query_complete_(false) { } virtual void push(CategorisedResult result) override { cout << "received result: uri=" << result.uri() << endl; } virtual void finished(ListenerBase::Reason reason, string const& /* error_message */) override { cout << "query complete, status: " << to_string(reason) << endl; lock_guard lock(mutex_); query_complete_ = true; condvar_.notify_one(); } void wait_until_finished() { unique_lock lock(mutex_); condvar_.wait(lock, [this] { return this->query_complete_; }); } private: bool query_complete_; mutex mutex_; condition_variable condvar_; }; int main() { try { Runtime::UPtr rt = Runtime::create(DEMO_RUNTIME_PATH); try { rt->registry(); assert(false); } catch (ConfigException const& e) { cerr << e.what() << endl; } // Create a proxy to scope-A from a string. // Syntax: ipc://#!! // // "ipc://" - prefix for all proxies // "/tmp/scope-A - endpoint at which the scope listens // "scope-A - scope ID (must be the same as last component of endpoint path) // "t=300" - optional timeout (infinite if not specified) // "c=Scope" - type of proxy (must be "c=Scope") ObjectProxy p = rt->string_to_proxy("ipc:///tmp/scope-A#scope-A!t=300!c=Scope"); assert(p); // The returned proxy is of type ObjectProxy and must be down-cast to a scope proxy: ScopeProxy sp = dynamic_pointer_cast(p); assert(sp); // We can now use the returned proxy to create a query. shared_ptr reply(new Receiver); SearchMetadata metadata("C", "desktop"); metadata.set_cardinality(10); auto ctrl = sp->search("query string", metadata, reply); // May raise TimeoutException cout << "client: created query" << endl; reply->wait_until_finished(); cout << "client: wait returned" << endl; } catch (std::exception const& e) { cerr << e.what() << endl; return 1; } return 0; } unity-scopes-api-0.4.2+14.04.20140408/demo/stand-alone/CMakeLists.txt0000644000015301777760000000075112320776161025227 0ustar pbusernogroup00000000000000configure_file(Runtime.ini.in Runtime.ini) configure_file(Zmq.ini.in Zmq.ini) add_executable(stand-alone-client stand-alone-client.cpp) # Add_dependencies should be used sparingly. In this case we need the global # header to be generated before we start building the client binary. add_dependencies(stand-alone-client globalheader) add_definitions(-DDEMO_RUNTIME_PATH="${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini") target_link_libraries(stand-alone-client ${UNITY_SCOPES_LIB} ${OTHER_LIBS}) unity-scopes-api-0.4.2+14.04.20140408/demo/stand-alone/Runtime.ini.in0000644000015301777760000000012712320776161025215 0ustar pbusernogroup00000000000000[Runtime] Default.Middleware = Zmq Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini unity-scopes-api-0.4.2+14.04.20140408/demo/stand-alone/README0000644000015301777760000000113712320776161023346 0ustar pbusernogroup00000000000000This is a very simple demo to show how, for testing purposes, you can run a scope without adding the scope to the registry. The Runtime.ini file does *not* define where to find the registry. Calling Runtime::registry() throws a ConfigException in this case. To reach the scope, the client uses a stringified proxy and calls Runtime::string_to_proxy() to turn the string back into a scope proxy. To run this demo (from the build/demo/stand-alone directory): In one terminal: $ ../../scoperunner/scoperunner Runtime.ini ../scopes/scope-A/scope-A.ini in another terminal: $ ./stand-alone-client unity-scopes-api-0.4.2+14.04.20140408/demo/client.cpp0000644000015301777760000003341612320776161022250 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ // You may also include individual headers if you prefer. #include #include #include #include #include #include #include #include #include using namespace std; using namespace unity::scopes; // conver filter to a string std::string to_string(FilterBase const& filter) { std::ostringstream str; auto const ftype = filter.filter_type(); cout << "filter id=" << filter.id() << endl; if (ftype == "option_selector") { auto const& selfilter = dynamic_cast(filter); str << "OptionSelectorFilter" << endl; str << " label: " << selfilter.label() << endl; str << " multi-select: " << selfilter.multi_select() << endl; str << " options:" << endl; for (auto op: selfilter.options()) { str << " id: " << op->id() << ", label: " << op->label() << endl; } } else { str << "Unknown filter type: " << ftype; } return str.str(); } std::string to_string(Department const& dep, std::string const& indent = "") { std::ostringstream str; str << indent << "department id=" << dep.id() << ", name=" << dep.label() << endl; auto const subdeps = dep.subdepartments(); if (!subdeps.empty()) { str << indent << "\tsubdepartments:" << endl; for (auto const& d: subdeps) { str << indent << to_string(d, indent + "\t\t"); } } return str.str(); } // output variant in a json-like format; note, it doesn't do escaping etc., // so the output is not suitable input for a json parser, it's only for // debugging purposes. std::string to_string(Variant const& var) { std::ostringstream str; switch (var.which()) { case Variant::Type::Int: str << var.get_int(); break; case Variant::Type::Null: str << "null"; break; case Variant::Type::Bool: str << std::boolalpha << var.get_bool(); break; case Variant::Type::String: str << "\"" << var.get_string() << "\""; break; case Variant::Type::Double: str << var.get_double(); break; case Variant::Type::Dict: str << "{"; for (auto kv: var.get_dict()) { str << "\"" << kv.first << "\":" << to_string(kv.second) << ", "; } str << "}"; break; case Variant::Type::Array: str << "["; for (auto v: var.get_array()) { str << to_string(v) << ","; } str << "]"; break; default: assert(0); } return str.str(); } class Receiver : public SearchListenerBase { public: Receiver(int index_to_save) : index_to_save_(index_to_save), push_result_count_(0) { } virtual void push(DepartmentList const& departments, std::string const& current_department_id) override { cout << "\treceived departments:" << endl; for (auto const& dep: departments) { cout << to_string(dep); } cout << "\tcurrent department=" << current_department_id << endl; } virtual void push(Category::SCPtr category) override { cout << "received category: id=" << category->id() << " title=" << category->title() << " icon=" << category->icon() << " template=" << category->renderer_template().data() << endl; } virtual void push(CategorisedResult result) override { cout << "received result: uri=" << result.uri() << " title=" << result.title() << " category id: " << result.category()->id() << endl; ++push_result_count_; if (index_to_save_ > 0 && push_result_count_ == index_to_save_) { saved_result_ = std::make_shared(result); } } virtual void push(Annotation annotation) override { auto links = annotation.links(); cout << "received annotation of type " << annotation.annotation_type() << " with " << links.size() << " link(s):" << endl; for (auto link: links) { cout << " " << link->query().to_string() << endl; } } void push(Filters const& filters, FilterState const& /* filter_state */) override { cout << "received " << filters.size() << " filters" << endl; for (auto f: filters) { cout << to_string(*f) << endl; } } virtual void finished(ListenerBase::Reason reason, string const& error_message) override { cout << "query complete, status: " << to_string(reason); if (reason == ListenerBase::Error) { cout << ": " << error_message; } cout << endl; { unique_lock lock(mutex_); query_complete_ = true; } condvar_.notify_one(); } void wait_until_finished() { unique_lock lock(mutex_); condvar_.wait(lock, [this] { return this->query_complete_; }); } std::shared_ptr saved_result() const { return saved_result_; } int result_count() const { return push_result_count_; } Receiver() : query_complete_(false) { } private: bool query_complete_; int index_to_save_; mutex mutex_; condition_variable condvar_; int push_result_count_ = 0; std::shared_ptr saved_result_; }; class ActivationReceiver : public ActivationListenerBase { public: void activated(ActivationResponse const& response) override { cout << "\tGot activation response: " << response.status() << endl; } void finished(Reason r, std::string const& error_message) { cout << "\tActivation finished, reason: " << r << ", error_message: " << error_message << endl; condvar_.notify_one(); } void wait_until_finished() { unique_lock lock(mutex_); condvar_.wait(lock); } private: mutex mutex_; condition_variable condvar_; }; class PreviewReceiver : public PreviewListenerBase { public: void push(ColumnLayoutList const& columns) override { cout << "\tGot column layouts:" << endl; for (auto const& col: columns) { cout << "\t\tLayout for " << col.size() << " column(s):" << endl; for (int i = 0; iattribute_values())) << endl << "\t\t components: {"; for (const auto kv: it->attribute_mappings()) { cout << "\"" << kv.first << "\": \"" << kv.second << "\", "; } cout << "}" << endl; } } void push(std::string const& key, Variant const& value) override { cout << "\tPushed preview data: \"" << key << "\", value: "; cout << to_string(value) << endl; } void finished(Reason r, std::string const& error_message) override { cout << "\tPreview finished, reason: " << r << ", error_message: " << error_message << endl; condvar_.notify_one(); } void wait_until_finished() { unique_lock lock(mutex_); condvar_.wait(lock); } private: mutex mutex_; condition_variable condvar_; }; void print_usage() { cerr << "usage: ./client query [activate n] | [preview n]" << endl; cerr << " or: ./client list" << endl; cerr << "For example: ./client scope-B iron" << endl; cerr << " or: ./client scope-B iron activate 1" << endl; cerr << " or: ./client scope-B iron preview 1" << endl; exit(1); } enum class ResultOperation { None, Activation, Preview }; int main(int argc, char* argv[]) { int result_index = 0; //the default index of 0 won't activate ResultOperation result_op = ResultOperation::None; bool do_list = false; // poor man's getopt if (argc == 5) { if (strcmp(argv[3], "activate") == 0) { result_index = atoi(argv[4]); result_op = ResultOperation::Activation; } else if (strcmp(argv[3], "preview") == 0) { result_index = atoi(argv[4]); result_op = ResultOperation::Preview; } else { print_usage(); } } else if (argc == 2 && strcmp(argv[1], "list") == 0) { do_list = true; } else if (argc != 3) { print_usage(); } try { Runtime::UPtr rt = Runtime::create(DEMO_RUNTIME_PATH); RegistryProxy r = rt->registry(); if (do_list) { cout << "Scopes:" << endl; auto mmap = r->list(); for (auto meta: mmap) { cout << "\t" << meta.second.scope_id() << endl; } return 0; } string scope_id = argv[1]; string search_string = argv[2]; auto meta = r->get_metadata(scope_id); cout << "Scope metadata: " << endl; cout << "\tscope_id: " << meta.scope_id() << endl; cout << "\tdisplay_name: " << meta.display_name() << endl; cout << "\tdescription: " << meta.description() << endl; string tmp; try { tmp = meta.art(); cout << "\tart: " << meta.art() << endl; } catch (NotFoundException const& e) { } try { tmp = meta.icon(); cout << "\ticon: " << meta.icon() << endl; } catch (NotFoundException const& e) { } try { tmp = meta.search_hint(); cout << "\tsearch_hint: " << meta.search_hint() << endl; } catch (NotFoundException const& e) { } try { tmp = meta.hot_key(); cout << "\thot_key: " << meta.hot_key() << endl; } catch (NotFoundException const& e) { } shared_ptr reply(new Receiver(result_index)); SearchMetadata metadata("C", "desktop"); metadata.set_cardinality(10); auto ctrl = meta.proxy()->search(search_string, metadata, reply); // May raise TimeoutException cout << "client: created query" << endl; reply->wait_until_finished(); cout << "client: wait returned" << endl; // handle activation if (result_index > 0) { auto result = reply->saved_result(); if (!result) { cout << "Nothing to activate! Requested result with index " << result_index << " but got " << reply->result_count() << " result(s) only" << endl; return 1; } if (result_op == ResultOperation::Activation) { shared_ptr act_reply(new ActivationReceiver); cout << "client: activating result item #" << result_index << ", uri:" << result->uri() << endl; bool direct_activation = result->direct_activation(); cout << "\tdirect activation: " << direct_activation << endl; if (!direct_activation) { ActionMetadata const metadata("en", "desktop"); auto target_scope = result->target_scope_proxy(); cout << "\tactivation scope: " << target_scope->to_string() << endl; target_scope->activate(*result, metadata, act_reply); act_reply->wait_until_finished(); } } else if (result_op == ResultOperation::Preview) { ActionMetadata const metadata("en", "desktop"); shared_ptr preview_reply(new PreviewReceiver); cout << "client: previewing result item #" << result_index << ", uri:" << result->uri() << endl; auto target_scope = result->target_scope_proxy(); cout << "\tactivation scope ID: " << target_scope->to_string() << endl; target_scope->preview(*result, metadata, preview_reply); preview_reply->wait_until_finished(); } } } catch (unity::Exception const& e) { cerr << e.to_string() << endl; return 1; } return 0; } unity-scopes-api-0.4.2+14.04.20140408/demo/Runtime.ini.in0000644000015301777760000000026212320776161023010 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = Registry Registry.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Registry.ini Default.Middleware = Zmq Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini unity-scopes-api-0.4.2+14.04.20140408/demo/README0000644000015301777760000000212512320776161021137 0ustar pbusernogroup00000000000000Leaf scopes in this demo: - scope-A: returns 1 result - scope-C: returns 3 results - scope-D: returns 4 results - scope-N: minimal no-op scope that illustrates the simplest possible implementation - scope-S: slow scope; returns 1 result after 20 seconds Aggregating scopes: - scope-B aggregates from scope-C and scope-D, so it returns 7 results Processes: The scopes run as separate process, except for scope-B and scope-C, which run collocated in a single process. To start the registry, which automatically starts the processes, run $ ../scoperegistry/scoperegistry Runtime.ini You do not need to run the registry from the current directory. Just adjust the path to Runtime.ini to point at the Runtime.ini file in *this* directory. Note that, for testing purposes, you may want to run a scope without having to configure a registry. See the stand-alone directory for details. To send a query to a scope, run $ ./client For example: $ ./client B testquery TODO: The client currently looks for Runtime.ini in the current directory, so you need to run it from here. unity-scopes-api-0.4.2+14.04.20140408/data/0000755000015301777760000000000012320776463020251 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/data/Zmq.ini.in0000644000015301777760000000007312320776161022121 0ustar pbusernogroup00000000000000[Zmq] EndpointDir.Public = /tmp EndpointDir.Private = /tmp unity-scopes-api-0.4.2+14.04.20140408/data/SSRegistry.ini.in0000644000015301777760000000051212320776161023426 0ustar pbusernogroup00000000000000[Registry] Middleware = Zmq Zmq.Endpoint = ipc:///tmp/SSRegistry Zmq.EndpointDir = /tmp Zmq.ConfigFile = @CMAKE_INSTALL_PREFIX@/@SCOPES_DEFAULT_CONFIGDIR@/Zmq.ini Scope.InstallDir = @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/unity-scopes Scoperunner.Path = @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/scoperunner/scoperunner unity-scopes-api-0.4.2+14.04.20140408/data/Registry.ini.in0000644000015301777760000000073612320776161023170 0ustar pbusernogroup00000000000000[Registry] Middleware = Zmq Zmq.Endpoint = ipc:///tmp/Registry Zmq.EndpointDir = /tmp Zmq.ConfigFile = @CMAKE_INSTALL_PREFIX@/@SCOPES_DEFAULT_CONFIGDIR@/Zmq.ini Scope.InstallDir = @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/unity-scopes OEM.InstallDir = /custom/lib/@CMAKE_LIBRARY_ARCHITECTURE@/unity-scopes Scoperunner.Path = @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/scoperunner/scoperunner SS.Registry.Identity = SSRegistry SS.Registry.Endpoint = ipc:///tmp/SSRegistry unity-scopes-api-0.4.2+14.04.20140408/data/scope-registry.conf.in0000644000015301777760000000036612320776161024504 0ustar pbusernogroup00000000000000description "Scope registry" author "Michal Hruby " start on started smart-scopes-proxy stop on desktop-end respawn respawn limit 10 60 exec @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/scoperegistry/scoperegistry unity-scopes-api-0.4.2+14.04.20140408/data/smart-scopes-proxy.conf.in0000644000015301777760000000042412320776161025317 0ustar pbusernogroup00000000000000description "Smart scopes proxy" author "Marcus Tomlinson " start on scope-ui-starting stop on desktop-end respawn respawn limit 10 60 expect stop exec @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/smartscopesproxy/smartscopesproxy upstart unity-scopes-api-0.4.2+14.04.20140408/data/CMakeLists.txt0000644000015301777760000000300112320776161022776 0ustar pbusernogroup00000000000000# Set up package config. configure_file(lib${UNITY_SCOPES_LIB}.pc.in lib${UNITY_SCOPES_LIB}.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib${UNITY_SCOPES_LIB}.pc DESTINATION ${LIB_INSTALL_PREFIX}/pkgconfig) # scope framework config files configure_file(Runtime.ini.in Runtime.ini @ONLY) configure_file(Registry.ini.in Registry.ini @ONLY) configure_file(Zmq.ini.in Zmq.ini @ONLY) configure_file(SSRuntime.ini.in SSRuntime.ini @ONLY) configure_file(SSRegistry.ini.in SSRegistry.ini @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini ${CMAKE_CURRENT_BINARY_DIR}/Registry.ini ${CMAKE_CURRENT_BINARY_DIR}/SSRuntime.ini ${CMAKE_CURRENT_BINARY_DIR}/SSRegistry.ini ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini DESTINATION ${SCOPES_DEFAULT_CONFIGDIR}) # upstart job for smart scopes proxy configure_file(smart-scopes-proxy.conf.in smart-scopes-proxy.conf @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/smart-scopes-proxy.conf DESTINATION ${CMAKE_INSTALL_DATADIR}/upstart/sessions) # upstart job for scope registry configure_file(scope-registry.conf.in scope-registry.conf @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/scope-registry.conf DESTINATION ${CMAKE_INSTALL_DATADIR}/upstart/sessions) # Empty directory for scopes to put their conf files into # If we start install our own conf files here, this can be # removed (installing files implicitly creates the subdirs) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/unity-scopes) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/unity-scopes DESTINATION ${CMAKE_INSTALL_LIBDIR}) unity-scopes-api-0.4.2+14.04.20140408/data/SSRuntime.ini.in0000644000015301777760000000034412320776161023244 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = SSRegistry Registry.ConfigFile = @CMAKE_INSTALL_PREFIX@/@SCOPES_DEFAULT_CONFIGDIR@/SSRegistry.ini Default.Middleware = Zmq Zmq.ConfigFile = @CMAKE_INSTALL_PREFIX@/@SCOPES_DEFAULT_CONFIGDIR@/Zmq.ini unity-scopes-api-0.4.2+14.04.20140408/data/libunity-scopes.pc.in0000644000015301777760000000202712320776161024327 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # prefix=@CMAKE_INSTALL_PREFIX@ includedir=${prefix}/@HDR_INSTALL_DIR@ libdir=${prefix}/@LIBDIR@ scopesdir=${libdir}/unity-scopes Name: lib@UNITY_SCOPES_LIB@ Description: Unity Scopes API library Requires: libunity-api Version: @UNITY_SCOPES_MAJOR@.@UNITY_SCOPES_MINOR@.@UNITY_SCOPES_MICRO@ Libs: -L${libdir} -l@UNITY_SCOPES_LIB@ Cflags: -I${includedir} unity-scopes-api-0.4.2+14.04.20140408/data/Runtime.ini.in0000644000015301777760000000034012320776161022772 0ustar pbusernogroup00000000000000[Runtime] Registry.Identity = Registry Registry.ConfigFile = @CMAKE_INSTALL_PREFIX@/@SCOPES_DEFAULT_CONFIGDIR@/Registry.ini Default.Middleware = Zmq Zmq.ConfigFile = @CMAKE_INSTALL_PREFIX@/@SCOPES_DEFAULT_CONFIGDIR@/Zmq.ini unity-scopes-api-0.4.2+14.04.20140408/unity-scopes.map0000644000015301777760000000206612320776161022500 0ustar pbusernogroup00000000000000{ global: extern "C++" { unity::scopes::[!i]*; typeinfo?for?unity::scopes::[!i]*; typeinfo?name?for?unity::scopes::[!i]*; VTT?for?unity::scopes::[!i]*; virtual?thunk?to?unity::scopes::[!i]*; vtable?for?unity::scopes::[!i]*; unity::scopes::internal::MiddlewareBase::*; unity::scopes::internal::MiddlewareFactory::*; unity::scopes::internal::RegistryConfig::*; unity::scopes::internal::RegistryObject::*; unity::scopes::internal::RuntimeImpl::*; unity::scopes::internal::RuntimeConfig::*; unity::scopes::internal::ScopeConfig::*; unity::scopes::internal::ScopeImpl::*; unity::scopes::internal::ScopeLoader::*; unity::scopes::internal::ScopeMetadataImpl::*; unity::scopes::internal::ScopeObject::*; unity::scopes::internal::StateReceiverObject::*; unity::scopes::internal::smartscopes::SSRegistryObject::*; unity::scopes::internal::smartscopes::SSScopeObject::*; }; local: extern "C++" { *; }; }; unity-scopes-api-0.4.2+14.04.20140408/INSTALL0000644000015301777760000000432712320776161020372 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # ------------------------------------------------------------------------------------- NOTE: Before making changes to the code, please read the README file in its entirety! ------------------------------------------------------------------------------------- Build dependencies ------------------ See debian/control for the list of packages required to build and test the code. Most notably: $ sudo apt-get install libunity-api-dev liblttng-ust-dev libzmq3-dev libzmqpp-dev libcapnp-dev Building the code ----------------- The simplest case is: $ mkdir build $ cd build $ cmake .. $ make By default, the code is built in release mode. To build a debug version, use $ mkdir builddebug $ cd builddebug $ cmake -DCMAKE_BUILD_TYPE=debug .. $ make Running the tests ----------------- $ make $ make test Documentation ------------- To generate the doc: $ make doc By default, this target generates documentation only for the public API. You can set the cmake option DEVEL_DOCS=ON to generate documentation that includes the internal API: $ cmake -DDEVEL_DOCS=ON .. This is useful mainly for browsing--the internal API does not include doxygen comments. Installation ------------ To get files that form part of an installation, run a "make install" in the build directory. By default, this installs them in the "install" subdirectory of the build directory. If you want to install into a different directory, use $ cmake -DCMAKE_INSTALL_PREFIX=/usr/local # Or wherever... $ make release $ make install unity-scopes-api-0.4.2+14.04.20140408/HACKING0000644000015301777760000001550712320776161020332 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # ------------------------------------------------------------------------------------- NOTE: Before making changes to the code, please read the README file in its entirety! ------------------------------------------------------------------------------------- Building the code ----------------- By default, the code is built in release mode. To build a debug version, use $ mkdir builddebug $ cd builddebug $ cmake -DCMAKE_BUILD_TYPE=debug .. $ make For a release version, use -DCMAKE_BUILD_TYPE=release Running the tests ----------------- $ make $ make test Note that "make test" alone is dangerous because it does not rebuild any tests if either the library or the test files themselves need rebuilding. It's not possible to fix this with cmake because cmake cannot add build dependencies to built-in targets. To make sure that everything is up-to-date, run "make" before running "make test"! To run the tests with valgrind: $ make valgrind Coverage -------- To build with the flags for coverage testing enabled and get coverage: $ mkdir buildcoverage $ cd buildcoverage $ cmake -DCMAKE_BUILD_TYPE=coverage $ make $ make test $ make coverage Note that, with gcc 4.7.2 and cmake 2.8.10, you may get a bunch of warnings. To fix this, you can build cmake 2.8.10 with the following patch: http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=61ace1df2616e472d056b302e4269cbf112fb020#patch1 Unfortunately, it is not possibly to get 100% coverage for some files, mainly due to gcc's generation of two destructors for dynamic and non- dynamic instances. For abstract base classes and for classes that prevent stack and static allocation, this causes one of the destructors to be reported as uncovered. There are also issues with some functions in header files that are incorrectly reported as uncovered due to inlining, as well as the impossibility of covering defensive assert(false) statements, such as an assert in the default branch of a switch, where the switch is meant to handle all possible cases explicitly. If you run a binary and get lots of warnings about a "merge mismatch for summaries", this is caused by having made changes to the source that add or remove code that was previously run, so the new coverage output cannot sensibly be merged into the old coverage output. You can get rid of this problem by running $ make clean-coverage This deletes all the .gcda files, allowing the merge to succeed again. If lcov complains about unrecognized lines involving '=====', you can patch geninfo and gcovr as explained here: https://bugs.launchpad.net/gcovr/+bug/1086695/comments/2 To run the static C++ checks: $ make cppcheck Code style ---------- We use a format tool that fixes a whole lot of issues regarding code style. The formatting changes made by the tool are generally sensible (even though they may not be your personal preference in all case). If there is a case where the formatting really messes things up, consider re-arranging the code to avoid the problem. The convenience of running the entire code base through the pretty-printer far outweighs any minor glitches with pretty printing, and it means that we get consistent code style for free, rather than endlessly having to watch out for formatting issues during code reviews. To format specific files: ${CMAKE_BINARY_DIR}/tools/formatcode x.cpp x.h If no arguments are provided, formatcode reads stdin and writes stdout, so you can easily pipe code into the tool from within an editor. For example, to reformat the entire file in vi (assuming ${CMAKE_BINARY_DIR}/tools is in your PATH): 1G!Gformatcode To re-format all source and header files in the tree: $ make formatcode Thread and address sanitizer ---------------- Set SANITIZER to "thread" or "address" to build with the corresponding sanitizer enabled. zmq (as 3.2.3 and 4.0.3) causes a large number of warnings from thread sanitizer. It appears impossible to avoid these; they are caused by issues in the zmq library. The tsan-suppress file supresses the benign race conditions we currently know about. To run the tests (from the build directory) with these suppressions enabled, use: $ TSAN_OPTIONS="suppressions=../tsan-suppress" make test Updating symbols file --------------------- To easily spot new/removed/changed symbols in the library, the debian package is maintaining a .symbols file which lists all exported symbols present in the library .so. If you add new public symbols to the library, it's necessary to refresh the symbols file, otherwise the package will fail to build. The easiest way to do that is using bzr-builddeb: $ bzr bd $ # this will exit with an error if symbols file isn't up-to-date $ cd ../build-area/unity-scopes-api-[version] $ cat ./debian/libunity-scopes1/DEBIAN/symbols | c++filt | sed 's/^ \(.*@Base\)/ (c++)"\1"/' | uniq | diff -u debian/libunity-scopes1.symbols - | sed 's/^+ \(.*@Base"\)\( .*\)/+ \1 0replaceme/' > /tmp/symbols.diff $ cd - $ # review the symbol differences and if everything is ok, apply the diff $ patch -p0 < /tmp/symbols.diff Debugging IPC ------------- There are lots of messages being passed between the various scope processes, and therefore it might be sometimes useful to see those to help with debugging. There is a special monitoring code that is enabled if you pass -DIPC_MONITORING=ON to cmake. When you build the library with this code, the messages can be introspected using the python scripts in the tools directory. Note that the tools require python dependencies that are otherwise not required for regular builds, to get those, grab python-zmq and python-capnproto. As of time of writing this, python-capnproto is not present in the distro, so get it from https://github.com/jparyani/pycapnp.git, also note that the master branch is compatible with capnproto 0.3, not 0.4 which we're using, so you need to switch to the "feature/v0.4" branch. Once you have the extra python dependencies you need to run: $ ./zmq-monitor-host.py & This runs a monitor proxy that forwards the monitored messages from all publishers to all subscribers. Then you can run a subscriber that will display content of the messages: $ ./zmq-parser.py unity-scopes-api-0.4.2+14.04.20140408/_clang-format0000644000015301777760000000262312320776161021772 0ustar pbusernogroup00000000000000--- AccessModifierOffset: -4 AlignEscapedNewlinesLeft: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortFunctionsOnASingleLine: false AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AlwaysBreakBeforeMultilineStrings: true AlwaysBreakTemplateDeclarations: true BinPackParameters: false BreakBeforeBinaryOperators: false BreakBeforeBraces: Allman BreakBeforeTernaryOperators: false BreakConstructorInitializersBeforeComma: true ColumnLimit: 120 ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerBinding: true ExperimentalAutoDetectBinPacking: false IndentCaseLabels: true IndentFunctionDeclarationAfterType: true IndentWidth: 4 Language: Cpp MaxEmptyLinesToKeep: 1 NamespaceIndentation: None ObjCSpaceBeforeProtocolList: false PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakComment: 60 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 200 PointerBindsToType: true SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 2 SpacesInAngles: false SpacesInCStyleCastParentheses: false SpacesInParentheses: false Standard: Cpp11 TabWidth: 8 UseTab: Never ... unity-scopes-api-0.4.2+14.04.20140408/doc/0000755000015301777760000000000012320776463020105 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/doc/tutorial.dox0000644000015301777760000007041212320776161022463 0ustar pbusernogroup00000000000000/*! \mainpage notitle \section overview What are scopes \subsection intro Introduction One of Unity’s core features on the desktop is the Dash. The Dash allows users to search for and discover virtually anything from local files and applications, to web content and other online data. The Dash achieves this by interfacing with one or more search plug-ins called “scopes” (e.g. “Apps”, “Music”, “Videos”, or “Amazon”, “Wikipedia”, “Youtube”). On the phone and tablet, scopes make up the central user interface, as they provide everything a user needs from an operating system. Scopes enable users to locate and launch applications, access local files, play music and videos, search the web, manage their favourite social network, keep up with the latest news, and much more. Each scope is a dedicated search engine for the category / data source it represents. The data source could be a local database, a web service, or even an aggregation of other scopes (e.g. the “Music” scope aggregates “Local Music” and “Online Music” scopes). A scope is primarily responsible for performing the actual search logic and returning the best possible results for each query it receives. This document describes how to implement, test and package your own scope using the Unity Scopes C++ API (unity-scopes-api). \subsection LvsR Local vs remote scopes Local scopes are scopes that are located and run on the user’s device, while remote scopes (or “Smart Scopes”) are scopes that are located and run remotely on the Ubuntu Smart Scopes Server (or “SSS”). (Note: Although local scopes execute as local processes, they may still query online services in order to retrieve search results). A local scope usually requires local data, and therefore, can only be run locally, while a remote scope can effectively be run both locally and remotely. When deciding on whether to write a local or remote scope, keep the user’s privacy in mind. For security reasons, a scope should not access the user’s personal data unless absolutely necessary (i.e. The scope requires account information or local data to perform searches). It is only in these situations that a scope should be written to run locally. By default, a scope should be written with the intention of running remotely on the Smart Scopes Server. (For more information on how to deploy your scope to the Smart Scopes Server, or how to implement a native remote scope using the SSS REST API see: link_not_yet_available) \section develop Developing scopes \subsection starting Getting started A simple C++ scope template with cmake build system is currently available on Launchpad, to use it install the packages required for scope development: \verbatim sudo apt-get install libunity-scopes-dev \endverbatim Clone the bazaar branch with the scope template and build the scope: \verbatim bzr branch lp:~jpakkane/+junk/scopetemplate cd scopetemplate mkdir build cd build cmake .. make \endverbatim Now you're ready to explore and modify the sample code in the src/ directory. \subsection impl Implementing scope This short tutorial covers the basic steps and building blocks needed for implementing your own scope with unity-scopes-api, using C++. For complete examples of various scopes see demo/scopes subdirectory of the unity-scopes-api source project. A typical scope implementation needs to implement interfaces of the following classes from the Scopes API:
  • unity::scopes::ScopeBase - the main scope class and an entry point for all incoming requests.
  • unity::scopes::SearchQueryBase - the handler of search request.
  • unity::scopes::PreviewQueryBase - the handler of preview requests (only if handling previews).
  • unity::scopes::ActivationQueryBase - the handler of activation and preview action requests (only if handling previews and activation)
  • unity::scopes::SearchListenerBase - the handler of search replies (only in aggreagator scopes, to pull results from other scopes)
The following sections show them in more detail. \subsubsection simplescope Case 1: A simple scope which doesn't query other scopes. This is the typical case: a scope that connects to a remote or local backend, database etc. and provides results in response to search queries coming from a client (i.e. Unity Dash or another scope). \paragraph scopebase Create a scope class that implements ScopeBase inteface. There are a few pure virtual methods that need to be implemented; at the very minimum you need to provide a non-empty implementation of \link unity::scopes::ScopeBase::start() start\endlink and unity::scopes::ScopeBase::search() and unity::scopes::ScopeBase::preview() methods. \code{.cpp} class MyScope: public unity::scopes::ScopeBase { public: virtual int start(std::string const&, unity::scopes::RegistryProxy const&) override; virtual void stop() override; virtual void run() override; virtual unity::scopes::SearchQueryBase::UPtr search(CannedQuery const& query, SearchMetadata const& metadata) override; virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata) override; } \endcode The \link unity::scopes::ScopeBase::start() start\endlink method must, at the very least return unity::scopes::ScopeBase::VERSION, e.g. \code{.cpp} int MyScope::start(string const&, unity::scopes::RegistryProxy const&) { return ScopeBase::VERSION; } \endcode The \link unity::scopes::ScopeBase::stop() stop\endlink method should release any resources, such as network connections where applicable. See the documentation of \link unity::scopes::ScopeBase ScopeBase\endlink for an explanation of when \link unity::scopes::ScopeBase::run() ScopeBase::run\endlink; is useful; for typical and simple cases the implementation of run can be an empty function. \paragraph handlingsearch Handling search The unity::scopes::ScopeBase::search() method of scope implementation is the entry point of every search - it receives search queries from the Dash or other scopes. This method must return an instance of an object that implements unity::scopes::SearchQueryBase interface, e.g: \code{.cpp} SearchQueryBase::UPtr MyScope::search(CannedQuery const& query, SearchMetadata const& metadata) { SearchQueryBase::UPtr q(new MyQuery(query)); return q; } \endcode The search() method receives two arguments: a unity::scopes::CannedQuery query object that carries actual query string (among other information) and additional parameters of the search request, stored in unity::scopes::SearchMetadata - such as locale string, form factor string and cardinality. Cardinality is the maximum number of results expected from the scope (the value of 0 should be treated as if no limit was set). For optimal performance scopes should provide no more results than requested; if they however fail to handle cardinality constraint, any excessive results will be ignored by scopes API. \paragraph querybase Create a query class that implements SearchQueryBase interface. The central and most important method that needs to be implemented in this interface is unity::scopes::SearchQueryBase::run(). This is where actual processing of current search query takes place, and this is the spot where you may want to query local or remote data source for results matching the query. The unity::scopes::SearchQueryBase::run() method gets passed an instance of SearchReplyProxy, which represents a receiver of query results. Please note that SearchReplyProxy is just a shared pointer for \link unity::scopes::SearchReply SearchReply\endlink object. The two most important methods of SearchReply object that every scope have to use are \link unity::scopes::SearchReply::register_category register_category\endlink and \link unity::scopes::SearchReply::push push\endlink. The \link unity::scopes::SearchReply::register_category register_category\endlink method is a factory method for creating new categories (see \link unity::scopes::Category\endlink). Categories can be created at any point during query processing inside run method, but it's recommended to create them as soon as possible (ideally as soon as they are known to the scope). When creating a category, one of its parameters is a \link unity::scopes::CategoryRenderer \endlink instance, which specifies how will a particular category be rendered. See the unity::scopes::CategoryRenderer documentation for more on that subject. The actual search results have to be wrapped inside \link unity::scopes::CategorisedResult CategorisedResult\endlink objects and passed to \link unity::scopes::SearchReply::push push\endlink. A typical implementation of run may look like this: \code{.cpp} void MyQuery::run(SearchReplyProxy const& reply) { auto category = reply->register_category("recommended", "Recommended", icon); //... query a local or remote backend for (auto res: backend.get_results(search_query)) // for every result returned by a backend { ... CategorisedResult result(category); // create a result item in "recommended" category result.set_uri(...); result.set_title(...); result.set_art(...); result.set_dnd_uri(...); result["my-custom-attribute"] = Variant(...); // add arbitrary data as needed if (!reply->push(result)) // send result to the client { break; // false from push() means search was cancelled } } } \endcode \paragraph handlingpreview Handling previews Scopes are responsible for handling preview requests for results they created; this needs to be implemented by overriding unity::scopes::ScopeBase::preview() method: \code{.cpp} class MyScope: public unity::scopes::ScopeBase { public: ... virtual unity::scopes::PreviewQueryBase::UPtr preview(unitu::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata) override; ... } \endcode This method must return an instance derived from unity::scopes::PreviewQueryBase. The implementation of unity::scopes::PreviewQueryBase interface is similar to unity::scopes::SearchQueryBase in that its central method is unity::scopes::PreviewQueryBase::run(). This method is responsible for gathering preview data (from local or remote sources) and passing it along with the definition of preview look to unity::scopes::PreviewReplyProxy (this is a pointer to unity::scopes::PreviewReplyBasel; the run() method receives a pointer to an instance of unity::scopes::PreviewReply). A preview consists of one or more preview widgets - these are the basic building blocks for previews, such as a header with a title and subtitle, an image, a gallery with multiple images, a list of audio tracks etc.; see unity::scopes::PreviewWidget for a detailed documentation and a list of supported widget types. So, the implementation of unity::scopes::PreviewQueryBase::run() needs to create and populate one or more instances of unity::scopes::PreviewWidget and push them to the client with unity::scopes::PreviewReply::push(). Every unity::scopes::PreviewWidget has a unique identifier, a type name and a set of attributes determined by its type. For example, a widget of "image" type expects two attributes: "source", which should point to an image (an uri) and "zoomable" boolean flag, which determines if the image should be zoomable. Values of such attributes can either be specified directly, or they can reference values present already in the unity::scopes::Result instance, or pushed spearately during the execution of unity::scopes::PreviewQueryBase::run(). Attributes can be specified directly with unity::scopes::PreviewWidget::add_attribute_value() method, e.g: \code{.cpp} PreviewWidget image_widget("myimage", "image"); image_widget.add_attribute_value("source", Variant("file:///tmp/image.jpg")); image_widget.add_attribute_value("zoomable", Variant(false)); \endcode To reference values from results or arbitrary values pushed separately, use unity::scopes::PreviewWidget::add_attribute_mapping() method: \code{.cpp} PreviewWidget image_widget("myimage", "image"); image_widget.add_attribute_mapping("source", "art"); // use 'art' attribute from the result image_widget.add_attribute_mapping("zoomable", "myzoomable"); // 'myzoomable' not specified, but pushed below reply->push("myzoomable", Variant(true)); \endcode To push preview widgets to the client, use unity::scopes::PreviewReply::push(): \code{.cpp} PreviewWidget image_widget("myimage", "image"); PreviewWidget header_widget("myheader", "header"); // fill in widget attributes ... PreviewWidgetList widgets { image_widget, header_widget }; reply->push(widgets); \endcode \paragraph previewactions Preview actions Previews can have actions (i.e. buttons) that user can activate - they are supported by unity::scopes::PreviewWidget of "actions" type. This type of widget takes one or more action button definitions, where every button is constituted by an unique identifier, a label and an optional icon. For example, a widget with two buttons: "Open" and "Download" can be defined as follows (using unity::scopes::VariantBuilder helper class): \code{.cpp} PreviewWidget buttons("mybuttons", "actions"); VariantBuilder builder; builder.add_tuple({ {"id", Variant("open")}, {"label", Variant("Open")} }); builder.add_tuple({ {"id", Variant("download")}, {"label", Variant("Download")} }); buttons.add_attribute_value("actions", builder.end()); \endcode To handle activation of preview actions, scope needs to implement the following method of unity::scopes::ScopeBase: \code{.cpp} class MyScope: public unity::scopes::ScopeBase { virtual ActivationQueryBase::UPtr perform_action(Result const& result, ActionMetadata const& metadata, std::string const& widget_id, std::string const& action_id) override ... } \endcode This method receives a widget identifier and action identifier that was activated. This method needs to return an instance derived from unity::scopes::ActivationQueryBase. The derived class needs to reimplement unity::scopes::ActivationQueryBase::activate() method and put any activation logic in there. This method needs to respond with an instance of unity::scopes::ActivationResponse, which informs the shell about status of activation and the expected behaviour of the UI. For example, activate() may request a new search query to be executed as follows: \code{.cpp} class MyActivation : public unity::scopes::ActivationQueryBase { virtual unity::scopes::ActivationResponse activate() override { ... if (action_id == "search-grooveshark") { CannedQuery query("com.canonical.scopes.grooveshark"); query.set_query_string("metal"); return unity::scopes::ActivationResponse(query); } ... } } \endcode \paragraph handlingactivation Handling result activation In many cases search results can be activated (i.e. when user taps or clicks them) directly by the shell - as long as a desktop schema (such as "http://") of result's uri has a handler in the system. If this is the case, then there is nothing to do in terms of activation handling in the scope code. If however a scope relies on a schema handler that's not present in the system, the offending result will be ignored by Unity shell and nothing will happen on activation. In cases where scope wants to intercept and handle activation request (e.g. when no handler for specifc type of uri exists, or to do some extra work on activation), it has to reimplement unity::scopes::ScopeBase::activate() method: \code{.cpp} class MyScope : public ScopeBase { virtual ActivationQueryBase::UPtr activate(Result const& result, ActionMetadata const& metadata) override; ... } \endcode and also call Result::set_intercept_activation() for all results that should trigger unity::scopes::ScopeBase::activate() on activation. The implementation of unity::scopes::ScopeBase::activate() should follow the same guidelines as unity::scopes::ScopeBase::perform_action(), the only difference with result activation being the lack of widget or action identifiers, as those are specific to preview widgets. \paragraph export Exporting the scope The scope needs to be compiled into a .so shared library and to be succesfully loaded at runtime it must provide two C functions to create and destroy it - a typical code snippet to do this looks as follows: \code{.cpp} extern "C" { EXPORT unity::scopes::ScopeBase* UNITY_SCOPE_CREATE_FUNCTION() { return new MyScope(); } EXPORT void UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { delete scope_base; } } \endcode \subsubsection aggscope Case 2: A simple aggregator scope. Aggregator scope is not much different from regular scopes, except for its data sources can include any other scope(s). The main difference is in the implementation of run method of unity::scopes::SearchQueryBase and in the new class that has to implement \link unity::scopes::SearchListenerBase SearchListenerBase\endlink interface, which receives result from other scope(s). \paragraph subquery Query another scopes via SearchQueryBase::subsearch() To send search query to another scope, use one of the `subsearch()` overloads of unity::scopes::SearchQueryBase inside your implementation of unity::scopes::SearchQueryBase. This method requires - among search query string - an instance of \link unity::scopes::ScopeProxy ScopeProxy\endlink that points to the target scope and an instance of class that implements \link unity::scopes::SearchListenerBase SearchListenerBase\endlink interface. ScopeProxy can be obtained from unity::scopes::RegistryProxy and the right place to do this is in the implementation of \link unity::scopes::ScopeBase::start() start()\endlink method of \link unity::scopes::ScopeBase ScopeBase\endlink interface. \code{.cpp} int MyScope::start(std::string const&, unity::scopes::RegistryProxy const& registry) { try { auto meta = registry->get_metadata("scope-A"); scope_to_query_ = meta.proxy(); // store the proxy for passing it further in search } catch (NotFoundException const& e) { ... } return VERSION; } unity::scopes::QueryBase::UPtr MyScope::search(CannedQuery const& query, unity::scopes::SearchMetadata const&) { SearchQueryBase::UPtr q(new MyQuery(query, scope_to_query_)); return q; } ... void MyQuery::run(unity::scopes::SearchReplyProxy const& upstream_reply) { auto category = reply->register_category("recommended", "Recommended", icon, ""); SearchListenerBase::SPtr reply(new MyReceiver(upstream_reply, category)); subsearch(scope_to_query_, query_, reply); ... } \endcode \paragraph receiver Create a class that implements SearchListenerBase interface The \link unity::scopes::SearchListenerBase SearchListenerBase\endlink is an abstract class to receive the results of a query sent to a scope. Its virtual push methods let the implementation receive \link unity::scopes::SearchListenerBase::push result items and categories\endlink returned by that query. A simple implementation of an aggregator scope may just register all categories it receives and push all received results upstream to the query originator, e.g. \code{.cpp} void push(Category::SCPtr category) { upstream_->register_category(category); } void MyReceiver::push(CategorisedResult result) { upstream_->push(std::move(result)); } \endcode A more sophisticated aggregator scope can rearrange results it receives into a different set of categories, alter or enrich the results before pushing them upstream etc. \paragraph aggactiv Activation and previews of results processed by aggregator scopes If an aggregator scope just forwards results it receives from other scopes, possibly only changing their category assignment, then there is nothing to do in terms of handling previews, preview actions and result activation: preview and perform_action requests will trigger respective methods of unity::scopes::ScopeBase for the scope that created results. Result activation will trigger unity::scopes::ScopeBase::activate() method for the scope that produced the result as long as it set interception flag for it. In other words, when aggreagor scope just forwards results (and makes only minor adjustements to them, such as category assignment), it is not involved in preview or activation handling at all. If, however, aggregator scope changes attributes of results (or creates completely new results that "replace" received results), then some extra care needs to be taken:
  • if original scope should still handle preview (and activation) requests, then aggregator has to store a copy of original result in the modified (or brand new) result. This can be done with unity::scopes::Result::store method. Preview request for such result will automatically trigger a scope that created the most inner stored result, and that scope will receive the stored result. It will also do the same for activation as long as the original scope set interception flag on that result. \note Making substantial changes to received results and failing to store original results with them may result in unexpected behavior: a scope will suddenly receive a modified version of it and depending on the level of changes, it may or may not be able to correctly handle it.
  • if aggregator scope creates a completly new result that replaces original one, but doesn't store a copy of the original result, it is expected to handle preview (and potentially activation requests - if interception activation flag is set) - this is no different than for normal scopes, see \ref handlingpreview and \ref handlingactivation .
Consider the following example of implementation of unity::scopes::SearchListenerBase interface that modifies results and stores their copies, so that original scope can handle previews and activation for them: \code{.cpp} void MyReceiver::push(CategorisedResult original_result) { CategorisedResult result(agg_category); // agg_category is a category that aggregates all results from other scopes result.set_uri(original_result.uri()); result.set_title(original_result.title() + "(aggregated)"); result.set_art(original_result.art()); result.store(original_result); upstream_->push(std::move(result)); } \endcode \subsection scopetesting Testing Unity Scopes API provides testing helpers based on well-known and established testing frameworks: googletest and googlemock. Please see respective documentation of those projects for general information about how to use Google C++ Testing Framework. All the helper classes provided by Scopes API are located in unity::scopes::testing namespace. The most important ones are:
  • unity::scopes::testing::TypedScopeFixture - template class that takes your scope class name as a template argument and creates a test fixture that can be used in tests.
  • unity::scopes::testing::MockSearchReply - a mock of unity::scopes::SearchReply that makes it possible to intercept responses to search request sent from the scope to a client, making it easy to test if your scope returns all expected data.
  • unity::scopes::testing::MockPreviewReply - a mock of unity::scopes::PreviewReply that makes is possible to intercept and test responses to preview request sent from the scope to a client.
  • unity::scopes::testing::Result - a simple class defined on top of unity::scopes::Result that provides a default constructor, making it possible to create dummy results (with no attributes) for testing purposes.
  • unity::scopes::testing::category - a simple class defined on top of unity::scopes::Category that makes it possible to create dummy categories (which would otherwise require an instance of unity::scopes::SearchReply and a call to unity::scopes::SearchReply::register_category()).
With the above classes a test case that checks if MyScope calls appropriate methods of unity::scopes::SearchReply may look like this (note that it just checks if proper methods get called and uses _ matchers that match any values; put actual values in there for stricts checks): \code{.cpp} typedef unity::scopes::testing::TypedScopeFixture TestScopeFixutre; using namespace ::testing; TEST_F(TestScopeFixutre, search_results) { const unity::scopes::CategoryRenderer renderer; NiceMock reply; EXPECT_CALL(reply, register_departments(_, _)).Times(1); EXPECT_CALL(reply, register_category(_, _, _, _)) .Times(1) .WillOnce( Return( unity::scopes::Category::SCPtr(new unity::scopes::testing::Category("id", "title", "icon", renderer)) ) ); EXPECT_CALL(reply, register_annotation(_)) .Times(1) .WillOnce(Return(true)); EXPECT_CALL(reply, push(_)) .Times(1) .WillOnce(Return(true)); unity::scopes::SearchReplyProxy reply_proxy(&reply, [](unity::scopes::SearchReplyBase*) {}); // note: this is a std::shared_ptr with empty deleter unity::scopes::CannedQuery query(scope_id, "", ""); unity::scopes::SearchMetadata meta_data("en_EN", "phone"); auto search_query = scope->search(query, meta_data); ASSERT_NE(nullptr, search_query); search_query->run(reply_proxy); } \endcode \subsection deployment Deployment Installing a scope is as simple as running `make install` when using the scope template. You might need to restart the global scope registry when a new scope is installed by running: \verbatim restart scope-registry \endverbatim The scope will be installed under one of the "scopes directories" scanned by the scope registry. Currently these default to:
  • /usr/lib/${arch}/unity-scopes
  • /custom/lib/${arch}/unity-scopes
Individual scopes are installed into a subdirectory matching the scope's name. At a minimum, the directory structure should contain the following: -+- ${scopesdir} `-+- scopename |--- scopename.ini `--- libscopename.so That is, a scope metadata file and a shared library containing the scope code. The scope author is free to ship additional data in this directory (e.g. icons and screenshots). The scope metadata file uses the standard ini file format, with the following keys: [ScopeConfig] DisplayName = human readable name of scope Description = description of scope Author = Author Icon = path to icon representing the scope Art = path to screenshot of the scope SearchHint = hint text displayed to user when viewing scope HotKey = In addition to allowing the registry to make the scope available, this information controls how the scope appears in the "Scopes" scope. \subsection scopetool Previewing scope To help with the development of a scope and to be able to see how will the dash render the dynamically-specified categories (see unity::scopes::CategoryRenderer), a specialized tool to preview a scope is provided - the "Unity Scope Tool". You can install it from the Ubuntu archive using: \verbatim sudo apt-get install unity-scope-tool \endverbatim After installation, you can run the scope-tool with a parameter specifying path to your scope configuration file (for example `unity-scope-tool ~/dev/myscope/build/myscope.ini`). If a binary for your scope can be found in the same directory (ie there's `~/dev/myscope/build/libmyscope.so`), the scope-tool will display surfacing and search results provided by your scope, and allow you to perform searches, invoke previews and actions within previews. Note that the scope-tool is using the same rendering mechanism as Unity itself, and therefore what you see in the scope-tool is what you get in Unity. It can also be used to fine-tune the category definitions, as it allows you to manipulate the definitions on the fly, and once you're happy with the result you can just copy the JSON definition back into your scope (see unity::scopes::CategoryRenderer::CategoryRenderer()). The scope-tool supports a few command line arguments: \arg by default (without any arguments) it will communicate with all scopes installed on the system and available on the smart scopes server. \arg When a path to a scope configuration file is provided, only that scope is initialized, but you can either pass multiple configuration files or the `--include-system-scopes` / `--include-server-scopes` option to allow development of aggregating scopes. */ unity-scopes-api-0.4.2+14.04.20140408/doc/index.html0000644000015301777760000000056612320776161022104 0ustar pbusernogroup00000000000000 Unity Scopes API - Page Redirection

You will be redirected automatically, otherwise please click here.

unity-scopes-api-0.4.2+14.04.20140408/doc/Doxyfile-devel.in0000644000015301777760000022657012320776161023324 0ustar pbusernogroup00000000000000# Doxyfile 1.8.1.2 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = "Unity Scopes API (internal)" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = @PROJECT_BINARY_DIR@/doc # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@ @PROJECT_BINARY_DIR@ # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = @PROJECT_SOURCE_DIR@/include @PROJECT_BINARY_DIR@/include # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all # comments according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. MARKDOWN_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be # set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given # their name and scope. Since this can be an expensive process and often the # same symbol appear multiple times in the code, doxygen keeps a cache of # pre-resolved symbols. If the cache is too small doxygen will become slower. # If the cache is too large, memory is wasted. The cache size is given by this # formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE =YES # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. EXTRACT_PACKAGE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = YES # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. #WARN_LOGFILE = @CMAKE_BINARY_DIR@/doxygen-warnings.txt #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @PROJECT_SOURCE_DIR@/doc/tutorial.dox @PROJECT_BINARY_DIR@/include @PROJECT_SOURCE_DIR@/include @PROJECT_SOURCE_DIR@/src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.markdown \ *.md \ *.mm \ *.dox \ *.py \ *.f90 \ *.f \ *.for \ *.vhd \ *.vhdl # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C, C++ and Fortran comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = @PROJECT@ # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # style sheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of # entries shown in the various tree structured indices initially; the user # can expand and collapse entries dynamically later on. Doxygen will expand # the tree to such a level that at most the specified number of entries are # visible (unless a fully collapsed tree already exceeds this amount). # So setting the number of entries 1 will produce a full collapsed tree by # default. 0 is a special value representing an infinite number of entries # and will result in a full expanded tree by default. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. However, it is strongly recommended to install a local # copy of MathJax from http://www.mathjax.org before deployment. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = DOXYGEN_SKIP # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. DOT_PATH = @DOXYGEN_DOT_PATH@ # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Helvetica # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = NO # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # managable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES unity-scopes-api-0.4.2+14.04.20140408/doc/Doxyfile.in0000644000015301777760000022660312320776161022224 0ustar pbusernogroup00000000000000# Doxyfile 1.8.1.2 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = "Unity Scopes API" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = @PROJECT_BINARY_DIR@/doc # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@ @PROJECT_BINARY_DIR@ # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = @PROJECT_SOURCE_DIR@/include @PROJECT_BINARY_DIR@/include # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all # comments according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. MARKDOWN_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be # set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given # their name and scope. Since this can be an expensive process and often the # same symbol appear multiple times in the code, doxygen keeps a cache of # pre-resolved symbols. If the cache is too small doxygen will become slower. # If the cache is too large, memory is wasted. The cache size is given by this # formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = YES # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. #WARN_LOGFILE = @CMAKE_BINARY_DIR@/doxygen-warnings.txt #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @PROJECT_SOURCE_DIR@/doc/tutorial.dox @PROJECT_BINARY_DIR@/include @PROJECT_SOURCE_DIR@/include @PROJECT_SOURCE_DIR@/src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.markdown \ *.md \ *.mm \ *.dox \ *.py \ *.f90 \ *.f \ *.for \ *.vhd \ *.vhdl # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = */internal/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = *::internal::* # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C, C++ and Fortran comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = @PROJECT@ # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # style sheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of # entries shown in the various tree structured indices initially; the user # can expand and collapse entries dynamically later on. Doxygen will expand # the tree to such a level that at most the specified number of entries are # visible (unless a fully collapsed tree already exceeds this amount). # So setting the number of entries 1 will produce a full collapsed tree by # default. 0 is a special value representing an infinite number of entries # and will result in a full expanded tree by default. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. However, it is strongly recommended to install a local # copy of MathJax from http://www.mathjax.org before deployment. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = DOXYGEN_SKIP # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. DOT_PATH = @DOXYGEN_DOT_PATH@ # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Helvetica # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = NO # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # managable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES unity-scopes-api-0.4.2+14.04.20140408/STRUCTS0000644000015301777760000001000012320776161020414 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # ----------------------------------------------------------------------------- This document describes data structures that are serialized and exchanged by middleware. ----------------------------------------------------------------------------- Result (returned by serialize()): ================================= 'attrs' : { 'uri' : string 'title' : string 'art' : string 'dnd_uri' : string + any custom key-value attribute added by scope author. }, 'internal' : { 'result' : dictionary (serialized Result), optional 'flags' : integer, optional (activation/preview flags defined by ResultImpl::Flags enum) 'origin' : string (scope id) } CategorisedResult (returned by serialize()): ======================================= 'attrs' : { // all Result's attributes }, 'internal' : { 'cat_id' : string + all Result's internal values } Category (returned by serialize()): ===================================== 'id' : string 'title' : string 'icon' : string 'renderer_template' : string Department (returned by serialize()): ===================================== 'query' : dictionary (serialized Query) 'label' : string 'departments' : array of dictionaries (serialized Departments), optional ScopeMetadata (returned by serialize()): ===================================== 'scope_id' : string 'proxy' : dictionary 'identity' : string 'endpoint' : string 'display_name' : string 'description' : string 'scope_dir' : string, optional 'art' : string, optional 'icon' : string, optional 'search_hint' : string, optional 'hot_key' : string, optional Query (returned by serialize()) =============================== 'scope' : string 'query_string' : string 'department_id' : string 'filter_state' : dictionary (serialized FilterState) Link (returned by serialize()) ============================== 'label' : string 'query' : Query Annotation (returned by serialize()) ==================================== 'type' : string 'label' : string, optional 'icon' : string, optional 'links' : array of Links FilterState (returned by serialize()) ===================================== filter_id : Variant (arbitrary, depends on filter type) FilterOption ============ 'id' : string 'label' : string OptionSelectorFilter ==================== 'id' : string 'filter_type' : "option_selector" 'label' : string 'multi_select' : bool 'options' : array of FilterOption Filters + FilterState ===================== 'filter' : array of filters (implementations of FilterBase) 'filter_state' : FilterState PreviewResult (returned by serialize()) ======================================= 'id' : string 'type' : string 'attributes' : dict 'components' : dict PushRequest (capnproto structure) ================================= result : dictionary with: "category" and/or "result" or "annotation" or "departments" and "current_department" or "columns" key and serialized Category / CategorisedResult / Annotation / DepartmentList / ColumnLayoutList respectively. ActivationResponse (returned by serialize()) ============================================ 'status' : int (corresponds to ActivationResponse::Status enum) 'scope_data' : variant unity-scopes-api-0.4.2+14.04.20140408/TODO0000644000015301777760000000006612320776161020025 0ustar pbusernogroup00000000000000Consider adding make_unique, which will be in C++ 14. unity-scopes-api-0.4.2+14.04.20140408/CTestCustom.cmake.in0000644000015301777760000000044012320776161023155 0ustar pbusernogroup00000000000000# # Tests listed here will not be run by the valgrind target. # SET(CTEST_CUSTOM_MEMCHECK_IGNORE cleanincludes noglobalincludes stand-alone-unity-scopes-headers stand-alone-unity-scopes-internal-headers clean-public-unity-scopes-headers copyright whitespace) unity-scopes-api-0.4.2+14.04.20140408/RELEASE_NOTES.txt0000644000015301777760000000766412320776161022141 0ustar pbusernogroup00000000000000Release Notes for unity-scopes-api ================================== Changes in version 0.4.0 ======================== * Re-factored proxy class implementation. These changes are API compatible, but not ABI compatible. * Renaming of various API elements for consistency and clarity: PreviewWidget::add_attribute() -> PreviewWidget::add_attribute_value() PreviewWidget::attributes() -> PreviewWidget::attribute_values() PreviewWidget::add_component() -> PreviewWidget::add_attribute_mapping() PreviewWidget::components() -> PreviewWidget::attribute_mappings() ActivationListener -> ActivationListenerBase ActivationListenerBase::activation_response() -> ActivationListenerBase::activated() PreviewListener -> PreviewListenerBase SearchListener -> SearchListenerBase PreviewQuery -> PreviewQueryBase SearchQuery -> SearchQueryBase ActivationBase -> ActivationQueryBase ReplyBase -> Reply RegistryBase -> Registry Query -> CannedQuery CannedQuery::scope_name() -> CannedQuery::scope_id() ScopeMetadata::scope_name() -> CannedQuery::scope_id() Scope::create_query() -> Scope::search() ScopeBase::create_query() -> ScopeBase::search() SearchQuery::create_subquery() -> SearchQuery::subsearch() Variant::Type: changed ordinal values of enumerators Changes in version 0.3.2 ======================== - ActivationResponse::set_scope_data(Variant const&) and scope_data() methods have been added; they are meant to replace setHints() and hints() and use Variant instead of VariantMap for arbitrary scope data. The existing ActivationResponse::setHints(VariantMap const&) and hints() methods have been marked as deprecated and for removal in 0.4.0. Changes in version 0.3.1 ======================== - Scope::activate_preview_action() and ScopeBase::activate_preview_action() were renamed to perform_action(). They now also require widget identifier along with action id and hints. - Added SearchMetadata and ActionMetadata classes; these classes are now passed to create_query(), activate(), perform_action(), preview() methods of ScopeBase and Scope (ScopeProxy) instead of a plain VariantMap. - The 'Handled' state was removed from ActivationResponse::Status and two new values were added instead: ShowDash and HideDash. - Annotation API changes: annotations of 'Card' type were removed and Annotation doesn't support category attribute anymore. SearchReply::push() method for annotations was renamed to register_annotation(). Annotations are now going to be displayed in the order they were registered by scopes. - Result::activation_scope_name() method was renamed to target_scope_proxy() and it now returns ScopeProxy instead of a string. Client code can now use that proxy for result activation or preview calls, instead of having to do an extra registry lookup. Changes in version 0.3.0 ======================== - Preliminary API for filters has been added via OptionSelectorFilter and FilterState classes. This part of the API is not yet supported by Unity shell and should be considered highly experimental. - ScopeBase::create_query() method now takes Query object instance instead of just a search query string. Search query string is now encapsulated in the Query class and can be retrieved via Query::query_string(). - ScopeProxy class provides overloaded create_query methods for passing filter state and department id. Note: departments are not yet supported across the API. - The scoperegistry allows extra scopes to be added on the command line now: $ scoperegistry some/path/Runtime.ini some/other/path/Fred.ini Joe.ini This loads Fred and Joe scopes in addition to any scopes picked up via the normal configuration. If Fred or Joe appear in configuration as well as on the command line, the config file on the command line takes precedence. The .so for additional scopes is expected to be in the same directory as the corresponding .ini file. unity-scopes-api-0.4.2+14.04.20140408/CMakeLists.txt0000644000015301777760000003554612320776161022110 0ustar pbusernogroup00000000000000cmake_minimum_required(VERSION 2.8.10) # Default install location. Must be set here, before setting the project. if (NOT DEFINED CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH "" FORCE) endif() set(PROJECT unity-scopes-api) project(${PROJECT} C CXX) if(${PROJECT_BINARY_DIR} STREQUAL ${PROJECT_SOURCE_DIR}) message(FATAL_ERROR "In-tree build attempt detected, aborting. Set your build dir outside your source dir, delete CMakeCache.txt from source root and try again.") endif() include(CheckCXXSourceCompiles) CHECK_CXX_SOURCE_COMPILES("#ifdef __clang__\n#else\n#error \"Not clang.\"\n#endif\nint main(int argc, char **argv) { return 0; }" IS_CLANG) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) if(IS_CLANG) message(STATUS "Compiling with Clang, disabling lttng.") endif() string(TOLOWER "${CMAKE_BUILD_TYPE}" cmake_build_type_lower) # Build types should always be lowercase but sometimes they are not. # Static C++ checks find_program(CPPCHECK_COMMAND NAMES cppcheck) if (CPPCHECK_COMMAND) set(CPPCHECK_COMMAND_OPTIONS --check-config --inline-suppr --enable=all -q --error-exitcode=2) set(CPPCHECK_COMMAND_OPTIONS ${CPPCHECK_COMMAND_OPTIONS} --template "'{file}({line}): {severity} ({id}): {message}'") add_custom_target(cppcheck COMMAND ${CPPCHECK_COMMAND} ${CPPCHECK_COMMAND_OPTIONS} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/test ${CMAKE_BINARY_DIR}/test ) else() message(WARNING "Cannot find cppcheck: cppcheck target will not be available") endif() # # Definitions for testing with valgrind. # configure_file(CTestCustom.cmake.in CTestCustom.cmake) # Tests in CTestCustom.cmake are skipped for valgrind find_program(MEMORYCHECK_COMMAND NAMES valgrind) if (MEMORYCHECK_COMMAND) set(MEMORYCHECK_COMMAND_OPTIONS "--suppressions=${CMAKE_SOURCE_DIR}/valgrind-suppress --leak-check=full --num-callers=40 --error-exitcode=3" ) add_custom_target(valgrind DEPENDS NightlyMemCheck) else() message(WARNING "Cannot find valgrind: valgrind target will not be available") endif() include(FindPkgConfig) find_package(Boost COMPONENTS regex serialization REQUIRED) pkg_check_modules(UNITY_API libunity-api>=0.1.1 REQUIRED) pkg_check_modules(PROCESS_CPP process-cpp>=1.0.0 REQUIRED) pkg_check_modules(LTTNG_UST lttng-ust REQUIRED) pkg_check_modules(LIBURCU_BP liburcu-bp REQUIRED) find_program(LTTNG_EXECUTABLE lttng) if (NOT LTTNG_EXECUTABLE) message(SEND_ERROR "Cannot find LTTng executable: ensure that lttng-tools is installed") endif() # # Code style fixer. We put the code through astyle first because it makes some fixes that # clang-format won't do (such as "char *p" -> "char* p"). But astyle messes up other things # (particularly lambdas and assembly-style comments), which clang-format does right. # So, we run clang-format after running astyle, which undoes the damage done by astyle # without reverting desirable astyle fixes. # find_program(ASTYLE_COMMAND NAMES astyle) if (NOT ASTYLE_COMMAND) message(WARNING "Cannot find astyle: formatcode target will not be available") else() # astyle 2.03 creates DOS line endings, so we need to fix its output find_program(DOS2UNIX_COMMAND NAMES dos2unix) if (NOT DOS2UNIX_COMMAND) message(WARNING "Cannot find dos2unix: formatcode target will not be available") else() find_program(CLANG_FORMAT_COMMAND NAMES clang-format-3.5) if (NOT CLANG_FORMAT_COMMAND) message(WARNING "Cannot find clang-format >= clang-format-3.5: formatcode target will not be available") endif() endif() endif() if (ASTYLE_COMMAND AND DOS2UNIX_COMMAND AND CLANG_FORMAT_COMMAND) set(UNITY_SCOPES_LIB_HDRS ${UNITY_SCOPES_LIB_HDRS} ${fmt_h}) add_custom_target(formatcode ${PROJECT_SOURCE_DIR}/tools/format-files.sh ${PROJECT_SOURCE_DIR} ${ASTYLE_COMMAND} ${CLANG_FORMAT_COMMAND}) endif() find_program(CAPNPC_BIN capnpc) if(NOT CAPNPC_BIN) message(FATAL_ERROR "Capnp compiler not found.") endif() set(CAPNPC_FLAGS "" CACHE STRING "Extra flags for capnpc.") set(OTHER_INCLUDE_DIRS ${OTHER_INCLUDE_DIRS} ${UNITY_API_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${JSONCPP_INCLUDE_DIRS} ${PROCESS_CPP_INCLUDE_DIRS}) set(OTHER_LIBS ${UNITY_API_LDFLAGS} ${OTHER_LIBS}) # Standard install paths include(GNUInstallDirs) include_directories( include/ ${CMAKE_BINARY_DIR}/include ${CMAKE_BINARY_DIR}/src ${OTHER_INCLUDE_DIRS} ) # When building the library, we set the default symbol visibility # to "hidden", so we don't export things by default. # Exported functions and classes are prefixed by a UNITY_API macro, # which explicitly exports a symbol if UNITY_DLL_EXPORTS is defined. add_definitions(-DUNITY_DLL_EXPORTS) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -Wno-variadic-macros -Wextra -fPIC") # By default, all symbols are visible in the library. We strip out things we don't # want at link time, by running a version script (see unity-scopes.map and the # setting of LINK_FLAGS below). set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -Wall -Wextra") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic -Wall -Wextra") # Can't use -std=c++11 with C compiler # -fno-permissive causes warnings with clang, so we only enable it for gcc if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-permissive") endif() if ("${cmake_build_type_lower}" STREQUAL "release" OR "${cmake_build_type_lower}" STREQUAL "relwithdebinfo") option(Werror "Treat warnings as errors" ON) else() option(Werror "Treat warnings as errors" OFF) endif() # Some tests are slow, so make it possible not to run them # during day-to-day development. option(slowtests "Run slow tests" ON) if (${Werror}) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") if ("${cmake_build_type_lower}" STREQUAL "release" OR "${cmake_build_type_lower}" STREQUAL "relwithdebinfo") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=deprecated-declarations") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=deprecated-declarations") endif() endif() set(SANITIZER "" CACHE STRING "Build with -fsanitize= (legal values: thread, address)") if ("${SANITIZER}" STREQUAL "") # Do nothing elseif (${SANITIZER} STREQUAL "thread") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -fno-omit-frame-pointer") elseif (${SANITIZER} STREQUAL "address") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer") else() message(FATAL_ERROR "Invalid SANITIZER setting: ${SANITIZER}") endif() option(IPC_MONITORING "Enable IPC traffic monitoring") if(IPC_MONITORING) add_definitions(-DENABLE_IPC_MONITOR) endif() set(SCOPES_DEFAULT_CONFIGDIR ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT}) # API version set(UNITY_SCOPES_MAJOR 0) set(UNITY_SCOPES_MINOR 4) set(UNITY_SCOPES_MICRO 2) # Scopes library set(UNITY_SCOPES_LIB unity-scopes) # Version for testing, with all symbols visible set(UNITY_SCOPES_TEST_LIB unity-scopes-test) pkg_check_modules(JSONCPP jsoncpp REQUIRED) find_library(ZMQLIB zmq) if(NOT ZMQLIB) message(FATAL_ERROR "Zmq lib not found.") endif() find_library(ZMQPPLIB zmqpp) if(NOT ZMQPPLIB) message(FATAL_ERROR "Zmqpp lib not found.") endif() find_library(CAPNPLIB capnp) if(NOT CAPNPLIB) message(FATAL_ERROR "Cap'n Proto lib not found.") endif() find_library(KJLIB kj) if(NOT KJLIB) message(FATAL_ERROR "Kj lib not found.") endif() find_library(DLLIB dl) if(NOT DLLIB) message(FATAL_ERROR "Dl lib not found.") endif() # Other libraries we depend on set(OTHER_LIBS ${OTHER_LIBS} ${Boost_LIBRARIES} ${JSONCPP_LDFLAGS} ${PROCESS_CPP_LDFLAGS} ${ZMQPPLIB} ${ZMQLIB} ${CAPNPLIB} ${KJLIB} ${DLLIB} pthread smartscopes ) # All the libraries we need to link a normal executable that uses Unity scopes set(LIBS ${UNITY_SCOPES_LIB}) # All the libraries we need to link a gtest executable. (We link the tests against a static version # so we can do whitebox testing on internal classes. # TODO: HACK: static linking of the tests doesn't work because the tests won't pull in virtual methods in a # base class from a static library without an unresolved dependency. But, without static linking, we can't # do whitebox tests because of the visibility=hidden compile flags. For now, we link dynamically and # with visbility=default. set(TESTLIBS ${UNITY_SCOPES_TEST_LIB}) # Library install prefix set(LIB_INSTALL_PREFIX lib/${CMAKE_LIBRARY_ARCHITECTURE}) set(LIBDIR ${CMAKE_INSTALL_LIBDIR}) set(HDR_INSTALL_DIR include/unity-scopes-${UNITY_SCOPES_MAJOR}) # Tests include(CTest) enable_testing() # Add subdirectories. add_subdirectory(include) add_subdirectory(src) add_subdirectory(scoperegistry) add_subdirectory(scoperunner) add_subdirectory(smartscopesproxy) add_subdirectory(data) add_subdirectory(test) add_subdirectory(demo) add_subdirectory(tools) # Custom rules to compile .capnp files foreach(file ${CAPNPROTO_FILES}) string(REPLACE "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" build_dir ${file}) get_filename_component(build_dir ${build_dir} PATH) get_filename_component(proto_file ${file} NAME) string(REPLACE ".capnp" ".capnp.c++" src_file ${proto_file}) string(REPLACE ".capnp" ".capnp.h" hdr_file ${proto_file}) set(src_file ${build_dir}/${src_file}) set(hdr_file ${build_dir}/${hdr_file}) set(CAPNPROTO_HDRS ${CAPNPROTO_HDRS} ${hdr_file}) set(CAPNPROTO_SRC ${CAPNPROTO_SRC} ${src_file}) endforeach() # cmake cannot analyze include file dependencies of .capnproto files, so the easiest option is to recompile # all files if any one of them changes add_custom_command(OUTPUT ${CAPNPROTO_SRC} ${CAPNPROTO_HDRS} DEPENDS ${CAPNPROTO_FILES} COMMAND ${CAPNPC_BIN} ${CAPNPC_FLAGS} -oc++:${CMAKE_BINARY_DIR} --src-prefix=${CMAKE_SOURCE_DIR} ${CAPNPROTO_FILES}) # Set up coverage testing include(EnableCoverageReport) ##################################################################### # Enable code coverage calculation with gcov/gcovr/lcov # Usage: # * Switch build type to coverage (use ccmake or cmake-gui) # * Invoke make, make test, make coverage (or ninja if you use that backend) # * Find html report in subdir coveragereport # * Find xml report suitable for jenkins in coverage.xml ##################################################################### if(cmake_build_type_lower MATCHES coverage) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} --coverage") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") # We add -g when building with coverage so valgrind reports line numbers. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g" ) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g" ) endif() # Pseudo-library of object files. We need a version of the library for normal clients # that does not expose symbols in the unity::scopes::internal namespace, and another # version for whitebox tests, so we can write unit tests for classes in the internal namespaces. # Here, we create an object library that then is used to link the normal and the test libraries. set(UNITY_SCOPES_LIB_OBJ ${UNITY_SCOPES_LIB}-obj) add_library(${UNITY_SCOPES_LIB_OBJ} OBJECT ${UNITY_SCOPES_LIB_SRC} ${CAPNPROTO_SRC}) set_target_properties(${UNITY_SCOPES_LIB_OBJ} PROPERTIES COMPILE_FLAGS "-fPIC") # Use the object files to make the normal library. set(UNITY_SCOPES_SOVERSION 1) add_library(${UNITY_SCOPES_LIB} SHARED $) set_target_properties(${UNITY_SCOPES_LIB} PROPERTIES VERSION "${UNITY_SCOPES_MAJOR}.${UNITY_SCOPES_MINOR}.${UNITY_SCOPES_MICRO}" SOVERSION ${UNITY_SCOPES_SOVERSION} ) # Use the object files to make the test library. add_library(${UNITY_SCOPES_TEST_LIB} SHARED $) set_target_properties(${UNITY_SCOPES_TEST_LIB} PROPERTIES VERSION "${UNITY_SCOPES_MAJOR}.${UNITY_SCOPES_MINOR}.${UNITY_SCOPES_MICRO}" SOVERSION ${UNITY_SCOPES_SOVERSION} ) set(ldflags "") # Clang sanitizers don't work if --no-undefined is given as a linker argument. if(NOT IS_CLANG) set(ldflags "-Wl,--no-undefined") endif() set_target_properties(${UNITY_SCOPES_TEST_LIB} PROPERTIES LINK_FLAGS "${ldflags}") # We compile with all symbols visible by default. For the shipping library, we strip # out all symbols that (recursively) are in the unity::scopes::internal namespace, # except for a few exceptions that are needed by the scoperegistry, scoperunner, # smartscopesproxy, and any other binaries that reach into the internal namespace. set(symbol_map "${CMAKE_SOURCE_DIR}/unity-scopes.map") set_target_properties(${UNITY_SCOPES_LIB} PROPERTIES LINK_FLAGS "${ldflags} -Wl,--version-script,${symbol_map}") set_target_properties(${UNITY_SCOPES_LIB} PROPERTIES LINK_DEPENDS ${symbol_map}) target_link_libraries(${UNITY_SCOPES_LIB} ${OTHER_LIBS}) target_link_libraries(${UNITY_SCOPES_TEST_LIB} ${OTHER_LIBS}) # Only the normal library gets installed. install(TARGETS ${UNITY_SCOPES_LIB} LIBRARY DESTINATION ${LIB_INSTALL_PREFIX}) # Enable coverage testing if (cmake_build_type_lower MATCHES coverage) ENABLE_COVERAGE_REPORT(TARGETS ${UNITY_SCOPES_LIB} smartscopes FILTER /usr/include ${CMAKE_SOURCE_DIR}/test/* ${CMAKE_BINARY_DIR}/*) endif() # # Documentation # # Pass -DDEVEL_DOCS=ON to cmake for more detailed documentation option(DEVEL_DOCS "Enable detailed Doxygen documentation") set(CMAKE_INSTALL_DOCDIR doc) find_package(Doxygen) find_program(DOT_EXECUTABLE dot /usr/bin) if (NOT DOXYGEN_FOUND OR NOT DOT_EXECUTABLE) message(WARNING "Cannot generate documentation: doxygen and/or graphviz not found") else() if (DEVEL_DOCS) message(STATUS "Creating devel documentation") configure_file(${PROJECT_SOURCE_DIR}/doc/Doxyfile-devel.in ${PROJECT_BINARY_DIR}/doc/Doxyfile @ONLY IMMEDIATE) else() configure_file(${PROJECT_SOURCE_DIR}/doc/Doxyfile.in ${PROJECT_BINARY_DIR}/doc/Doxyfile @ONLY IMMEDIATE) endif() configure_file(${PROJECT_SOURCE_DIR}/doc/index.html ${PROJECT_BINARY_DIR}/doc/index.html COPYONLY) add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/${PROJECT}/index.html COMMAND ${DOXYGEN_EXECUTABLE} ${PROJECT_BINARY_DIR}/doc/Doxyfile DEPENDS ${PROJECT_BINARY_DIR}/doc/Doxyfile ${PROJECT_SOURCE_DIR}/doc/tutorial.dox ${UNITY_SCOPES_LIB_SRC} ${UNITY_SCOPES_LIB_HDRS}) add_custom_target(doc ALL DEPENDS ${PROJECT_BINARY_DIR}/doc/${PROJECT}/index.html) install(DIRECTORY ${PROJECT_BINARY_DIR}/doc/${PROJECT} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_INSTALL_DOCDIR}) endif() unity-scopes-api-0.4.2+14.04.20140408/COPYING0000644000015301777760000001674312320776161020401 0ustar pbusernogroup00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. unity-scopes-api-0.4.2+14.04.20140408/src/0000755000015301777760000000000012320776463020127 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/src/scopes/0000755000015301777760000000000012320776463021423 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/src/scopes/ListenerBase.cpp0000644000015301777760000000315712320776161024510 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; namespace unity { namespace scopes { //! @cond ListenerBase::ListenerBase() { } ListenerBase::~ListenerBase() { } // Possibly overkill, but safer than using the enum as the index into an array, // in case the enumeration is ever added to or the enumerators get re-ordered. static unordered_map const reasons = { pair(static_cast(ListenerBase::Finished), "finished"), pair(static_cast(ListenerBase::Cancelled), "cancelled"), pair(static_cast(ListenerBase::Error), "error") }; char const* to_string(ListenerBase::Reason reason) { assert(reasons.find(static_cast(reason)) != reasons.end()); return reasons.find(static_cast(reason))->second; } //! @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/Department.cpp0000644000015301777760000000452712320776161024235 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include namespace unity { namespace scopes { Department::Department(CannedQuery const& query, std::string const& label) : p(new internal::DepartmentImpl(query, label)) { } Department::Department(std::string const& department_id, CannedQuery const& query, std::string const& label) : p(new internal::DepartmentImpl(department_id, query, label)) { } Department::Department(std::string const& department_id, CannedQuery const& query, std::string const& label, DepartmentList const& subdepartments) : p(new internal::DepartmentImpl(department_id, query, label, subdepartments)) { } /// @cond Department::Department(Department const& other) : p(new internal::DepartmentImpl(*(other.p))) { } Department::Department(Department&&) = default; Department::~Department() = default; Department& Department::operator=(Department const& other) { if (this != &other) { p.reset(new internal::DepartmentImpl(*(other.p))); } return *this; } Department& Department::operator=(Department&&) = default; VariantMap Department::serialize() const { return p->serialize(); } /// @endcond void Department::set_subdepartments(DepartmentList const& departments) { p->set_subdepartments(departments); } std::string Department::id() const { return p->id(); } std::string Department::label() const { return p->label(); } CannedQuery Department::query() const { return p->query(); } DepartmentList Department::subdepartments() const { return p->subdepartments(); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/SearchListenerBase.cpp0000644000015301777760000000305212320776161025630 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include namespace unity { namespace scopes { //! @cond SearchListenerBase::SearchListenerBase() { } SearchListenerBase::~SearchListenerBase() { } void SearchListenerBase::push(DepartmentList const& /* departments */, std::string const& /* current_department_id */) { // Intentionally empty: "do nothing" default implementation. } void SearchListenerBase::push(Filters const& /* filters */, FilterState const& /* filter_state */) { // Intentionally empty: "do nothing" default implementation. } void SearchListenerBase::push(Category::SCPtr /* category */) { // Intentionally empty: "do nothing" default implementation. } void SearchListenerBase::push(Annotation /* annotation */) { // Intentionally empty: "do nothing" default implementation. } //! @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/0000755000015301777760000000000012320776463023237 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/CannedQueryImpl.cpp0000644000015301777760000000723212320776161027002 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include namespace unity { namespace scopes { namespace internal { CannedQueryImpl::CannedQueryImpl(std::string const& scope_id) : scope_id_(scope_id) { if (scope_id_.empty()) { throw InvalidArgumentException("CannedQuery(): scope ID cannot be empty"); } } CannedQueryImpl::CannedQueryImpl(std::string const& scope_id, std::string const& query_str, std::string const& department_id) : scope_id_(scope_id), query_string_(query_str), department_id_(department_id) { } CannedQueryImpl::CannedQueryImpl(VariantMap const& variant) { auto it = variant.find("scope"); if (it == variant.end()) { throw InvalidArgumentException("CannedQuery(): scope ID not set"); } scope_id_ = it->second.get_string(); if (scope_id_.empty()) { throw InvalidArgumentException("CannedQuery(): scope ID cannot be empty"); } it = variant.find("filter_state"); if (it == variant.end()) { throw InvalidArgumentException("CannedQuery(): filter_state is missing"); } filter_state_ = internal::FilterStateImpl::deserialize(it->second.get_dict()); it = variant.find("department_id"); if (it != variant.end()) { department_id_ = it->second.get_string(); } it = variant.find("query_string"); if (it != variant.end()) { query_string_ = it->second.get_string(); } } void CannedQueryImpl::set_department_id(std::string const& dep_id) { department_id_ = dep_id; } void CannedQueryImpl::set_query_string(std::string const& query_str) { query_string_ = query_str; } void CannedQueryImpl::set_filter_state(FilterState const& filter_state) { filter_state_ = filter_state; } std::string CannedQueryImpl::scope_id() const { return scope_id_; } std::string CannedQueryImpl::department_id() const { return department_id_; } std::string CannedQueryImpl::query_string() const { return query_string_; } FilterState CannedQueryImpl::filter_state() const { return filter_state_; } VariantMap CannedQueryImpl::serialize() const { VariantMap vm; vm["scope"] = scope_id_; vm["query_string"] = query_string_; vm["department_id"] = department_id_; vm["filter_state"] = filter_state_.serialize(); return vm; } std::string CannedQueryImpl::to_string() const { std::ostringstream s; s << "scope://" << scope_id_; s << "?q=" << query_string_; // FIXME: escape if (!department_id_.empty()) { s << "&department=" << department_id_; } return s.str(); } CannedQuery CannedQueryImpl::create(VariantMap const& var) { return CannedQuery(new CannedQueryImpl(var)); } CannedQuery CannedQueryImpl::from_string() { //TODO CannedQuery q(""); return q; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/smartscopes/0000755000015301777760000000000012320776463025602 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/smartscopes/SmartScopesClient.cpp0000644000015301777760000005110512320776161031705 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include #include #include #include #include #include #include #include static const std::string c_base_url = "https://dash.ubuntu.com/smartscopes/v2"; static const std::string c_remote_scopes_resource = "/remote-scopes"; static const std::string c_search_resource = "/search"; static const std::string c_preview_resource = "/preview"; static const std::string c_scopes_cache_dir = std::string(getenv("HOME")) + "/.cache/unity-scopes/"; static const std::string c_scopes_cache_filename = "remote-scopes.json"; using namespace unity::scopes; using namespace unity::scopes::internal::smartscopes; //-- SearchHandle SearchHandle::SearchHandle(uint search_id, SmartScopesClient::SPtr ssc) : search_id_(search_id) , ssc_(ssc) { } SearchHandle::~SearchHandle() { cancel_search(); } std::vector SearchHandle::get_search_results() { return ssc_->get_search_results(search_id_); } void SearchHandle::cancel_search() { ssc_->cancel_query(search_id_); } //-- PreviewHandle PreviewHandle::PreviewHandle(uint preview_id, SmartScopesClient::SPtr ssc) : preview_id_(preview_id) , ssc_(ssc) { } PreviewHandle::~PreviewHandle() { cancel_preview(); } std::pair PreviewHandle::get_preview_results() { return ssc_->get_preview_results(preview_id_); } void PreviewHandle::cancel_preview() { ssc_->cancel_query(preview_id_); } //-- SmartScopesClient SmartScopesClient::SmartScopesClient(HttpClientInterface::SPtr http_client, JsonNodeInterface::SPtr json_node, std::string const& url) : http_client_(http_client) , json_node_(json_node) , have_latest_cache_(false) , query_counter_(0) { // initialise url_ reset_url(url); // initialise cached_scopes_ read_cache(); } SmartScopesClient::~SmartScopesClient() { } void SmartScopesClient::reset_url(std::string const& url) { std::string base_url = url; // if a url was not provided, get the environment variable if (base_url.empty()) { char* sss_url_env = ::getenv("SMART_SCOPES_SERVER"); base_url = sss_url_env ? sss_url_env : ""; // if the env var was not provided, use the c_base_url constant if (base_url.empty()) { base_url = c_base_url; } } url_ = base_url; } std::string SmartScopesClient::url() { return url_; } // returns false if cache used bool SmartScopesClient::get_remote_scopes(std::vector& remote_scopes, std::string const& locale, bool caching_enabled) { std::string response_str; bool using_cache = false; try { std::ostringstream remote_scopes_uri; remote_scopes_uri << url_ << c_remote_scopes_resource << "?"; // optional parameters if (!locale.empty()) { remote_scopes_uri << "&locale=\"" << locale << "\""; } std::cout << "SmartScopesClient.get_remote_scopes(): GET " << remote_scopes_uri.str() << std::endl; HttpResponseHandle::SPtr response = http_client_->get(remote_scopes_uri.str()); response->wait(); response_str = response->get(); std::cout << "SmartScopesClient.get_remote_scopes(): Remote scopes:" << std::endl << response_str << std::endl; } catch (std::exception const& e) { std::cerr << "SmartScopesClient.get_remote_scopes(): Failed to retrieve remote scopes from uri: " << url_ << c_remote_scopes_resource << std::endl; if (caching_enabled) { std::cerr << e.what() << std::endl; std::cerr << "SmartScopesClient.get_remote_scopes(): Using remote scopes from cache" << std::endl; response_str = read_cache(); if (response_str.empty()) { throw ResourceException("SmartScopesClient.get_remote_scopes(): Remote scopes cache is empty"); } using_cache = true; } else { throw; } } JsonNodeInterface::SPtr root_node; JsonNodeInterface::SPtr child_node; try { std::lock_guard lock(json_node_mutex_); json_node_->read_json(response_str); root_node = json_node_->get_node(); } catch (std::exception const&) { std::cerr << "SmartScopesClient.get_remote_scopes() Failed to parse json response from uri: " << url_ << c_remote_scopes_resource << std::endl; throw; } for (int i = 0; i < root_node->size(); ++i) { RemoteScope scope; try { child_node = root_node->get_node(i); if (!child_node->has_node("id")) { std::cerr << "SmartScopesClient.get_remote_scopes(): Skipping scope with no id" << std::endl; continue; } scope.id = child_node->get_node("id")->as_string(); bool err = false; static std::array const mandatory = { { "name", "description", "author", "base_url" } }; for (auto const& field : mandatory) { if (!child_node->has_node(field)) { std::cerr << "SmartScopesClient.get_remote_scopes(): Scope: \"" << scope.id << "\" has no \"" << field << "\" field" << std::endl; err = true; } } if (err) { std::cerr << "SmartScopesClient.get_remote_scopes(): Skipping scope: \"" << scope.id << "\"" << std::endl; continue; } scope.id = child_node->get_node("id")->as_string(); scope.name = child_node->get_node("name")->as_string(); scope.description = child_node->get_node("description")->as_string(); scope.author = child_node->get_node("author")->as_string(); scope.base_url = child_node->get_node("base_url")->as_string(); if (child_node->has_node("icon")) { scope.icon.reset(new std::string(child_node->get_node("icon")->as_string())); } if (child_node->has_node("art")) { scope.art.reset(new std::string(child_node->get_node("art")->as_string())); } scope.invisible = child_node->has_node("invisible") ? child_node->get_node("invisible")->as_bool() : false; remote_scopes.push_back(scope); } catch (std::exception const& e) { std::cerr << "SmartScopesClient.get_remote_scopes(): Skipping scope: \"" << scope.id << "\" due to a json parsing failure" << std::endl; std::cerr << e.what() << std::endl; } } if (remote_scopes.empty()) { std::cerr << "SmartScopesClient.get_remote_scopes(): No valid remote scopes retrieved from uri: " << url_ << c_remote_scopes_resource << std::endl; } else if (!using_cache) { if (caching_enabled) { try { write_cache(response_str); } catch (std::exception const& e) { std::cerr << "SmartScopesClient.get_remote_scopes(): Failed to write to cache file: " << c_scopes_cache_dir << c_scopes_cache_filename << std::endl; std::cerr << e.what() << std::endl; } } std::cout << "SmartScopesClient.get_remote_scopes(): Retrieved remote scopes from uri: " << url_ << c_remote_scopes_resource << std::endl; } else { std::cout << "SmartScopesClient.get_remote_scopes(): Retrieved remote scopes from cache" << std::endl; } return !using_cache; } SearchHandle::UPtr SmartScopesClient::search(std::string const& base_url, std::string const& query, std::string const& department_id, std::string const& session_id, uint query_id, std::string const& platform, std::string const& locale, std::string const& country, uint limit) { std::ostringstream search_uri; search_uri << base_url << c_search_resource << "?"; // mandatory parameters search_uri << "q=" << http_client_->to_percent_encoding(query); search_uri << "&session_id=" << session_id; search_uri << "&query_id=" << std::to_string(query_id); search_uri << "&platform=" << platform; // optional parameters if (!department_id.empty()) { search_uri << "&department=" << http_client_->to_percent_encoding(department_id); } if (!locale.empty()) { search_uri << "&locale=" << locale; } if (!country.empty()) { search_uri << "&country=" << country; } if (limit != 0) { search_uri << "&limit=" << std::to_string(limit); } std::lock_guard lock(query_results_mutex_); uint search_id = ++query_counter_; std::cout << "SmartScopesClient.search(): GET " << search_uri.str() << std::endl; query_results_[search_id] = http_client_->get(search_uri.str()); return SearchHandle::UPtr(new SearchHandle(search_id, shared_from_this())); } PreviewHandle::UPtr SmartScopesClient::preview(std::string const& base_url, std::string const& result, std::string const& session_id, std::string const& platform, const uint widgets_api_version, std::string const& locale, std::string const& country) { std::ostringstream preview_uri; preview_uri << base_url << c_preview_resource << "?"; // mandatory parameters preview_uri << "result=" << http_client_->to_percent_encoding(result); preview_uri << "&session_id=" << session_id; preview_uri << "&platform=" << platform; preview_uri << "&widgets_api_version=" << std::to_string(widgets_api_version); // optional parameters if (!locale.empty()) { preview_uri << "&locale=" << locale; } if (!country.empty()) { preview_uri << "&country=" << country; } std::lock_guard lock(query_results_mutex_); uint preview_id = ++query_counter_; std::cout << "SmartScopesClient.preview(): GET " << preview_uri.str() << std::endl; query_results_[preview_id] = http_client_->get(preview_uri.str()); return PreviewHandle::UPtr(new PreviewHandle(preview_id, shared_from_this())); } std::vector SmartScopesClient::get_search_results(uint search_id) { try { HttpResponseHandle::SPtr query_result; std::string response_str; { std::lock_guard lock(query_results_mutex_); auto it = query_results_.find(search_id); if (it == query_results_.end()) { throw unity::LogicException("No search for query " + std::to_string(search_id) + " is active"); } query_result = it->second; } query_result->wait(); response_str = query_result->get(); { std::lock_guard lock(query_results_mutex_); std::cout << "SmartScopesClient.get_search_results():" << std::endl << response_str << std::endl; query_results_.erase(search_id); } std::vector results; std::map> categories; std::vector jsons = extract_json_stream(response_str); for (std::string& json : jsons) { JsonNodeInterface::SPtr root_node; JsonNodeInterface::SPtr child_node; { std::lock_guard lock(json_node_mutex_); json_node_->read_json(json); root_node = json_node_->get_node(); } if (root_node->has_node("category")) { child_node = root_node->get_node("category"); auto category = std::make_shared(); std::vector members = child_node->member_names(); for (auto& member : members) { if (member == "icon") { category->icon = child_node->get_node(member)->as_string(); } else if (member == "id") { category->id = child_node->get_node(member)->as_string(); } else if (member == "render_template") { category->renderer_template = child_node->get_node(member)->as_string(); } else if (member == "title") { category->title = child_node->get_node(member)->as_string(); } } categories[category->id] = category; } else if (root_node->has_node("result")) { child_node = root_node->get_node("result"); SearchResult result; result.json = child_node->to_json_string(); std::vector members = child_node->member_names(); for (auto& member : members) { if (member == "uri") { result.uri = child_node->get_node(member)->as_string(); } else if (member == "cat_id") { std::string category = child_node->get_node(member)->as_string(); result.category = categories.find(category) != categories.end() ? categories[category] : nullptr; } else { result.other_params[member] = child_node->get_node(member); } } results.push_back(result); } } std::cout << "SmartScopesClient.get_search_results(): Retrieved search results for query " << search_id << std::endl; return results; } catch (std::exception const& e) { std::cerr << "SmartScopesClient.get_search_results(): Failed to retrieve search results for query " << search_id << std::endl; throw; } } std::pair SmartScopesClient::get_preview_results(uint preview_id) { try { HttpResponseHandle::SPtr query_result; std::string response_str; { std::lock_guard lock(query_results_mutex_); auto it = query_results_.find(preview_id); if (it == query_results_.end()) { throw unity::LogicException("No preivew for query " + std::to_string(preview_id) + " is active"); } query_result = it->second; } query_result->wait(); response_str = query_result->get(); { std::lock_guard lock(query_results_mutex_); std::cout << "SmartScopesClient.get_preview_results():" << std::endl << response_str << std::endl; query_results_.erase(preview_id); } PreviewHandle::Columns columns; PreviewHandle::Widgets widgets; std::vector jsons = extract_json_stream(response_str); for (std::string& json : jsons) { JsonNodeInterface::SPtr root_node; JsonNodeInterface::SPtr child_node; { std::lock_guard lock(json_node_mutex_); json_node_->read_json(json); root_node = json_node_->get_node(); } if (root_node->has_node("columns")) { child_node = root_node->get_node("columns"); // for each column for (int column_i = 0; column_i < child_node->size(); ++column_i) { auto column_node = child_node->get_node(column_i); // for each widget layout within the column std::vector> widget_layouts; for (int widget_lo_i = 0; widget_lo_i < column_node->size(); ++widget_lo_i) { auto widget_lo_node = column_node->get_node(widget_lo_i); // for each widget within the widget layout std::vector widget_ids; for (int widget_i = 0; widget_i < widget_lo_node->size(); ++widget_i) { auto widget_node = widget_lo_node->get_node(widget_i); widget_ids.push_back(widget_node->as_string()); } widget_layouts.push_back(widget_ids); } columns.push_back(widget_layouts); } } else if (root_node->has_node("widget")) { child_node = root_node->get_node("widget"); widgets.push_back(child_node->to_json_string()); } } std::cout << "SmartScopesClient.get_preview_results(): Retrieved preview results for query " << preview_id << std::endl; return std::make_pair(columns, widgets); } catch (std::exception const& e) { std::cerr << "SmartScopesClient.get_preview_results(): Failed to retrieve preview results for query " << preview_id << std::endl; throw; } } std::vector SmartScopesClient::extract_json_stream(std::string const& json_stream) { std::vector jsons; uint start_pos = 0; while (start_pos < json_stream.size()) { int end_pos = json_stream.find("\r\n", start_pos); if (end_pos == -1) { end_pos = json_stream.size(); } std::string sub_json_str = json_stream.substr(start_pos, end_pos - start_pos); jsons.push_back(sub_json_str); start_pos = end_pos + 2; } return jsons; } void SmartScopesClient::cancel_query(uint query_id) { std::lock_guard lock(query_results_mutex_); auto it = query_results_.find(query_id); if (it != query_results_.end()) { it->second->cancel(); query_results_.erase(it); } } void SmartScopesClient::write_cache(std::string const& scopes_json) { // make cache directory (fails silently if already exists) mkdir(c_scopes_cache_dir.c_str(), 0755); // open cache for output std::ofstream cache_file(c_scopes_cache_dir + c_scopes_cache_filename); if (!cache_file.fail()) { cache_file << scopes_json; cache_file.close(); cached_scopes_ = scopes_json; have_latest_cache_ = true; } } std::string SmartScopesClient::read_cache() { if (have_latest_cache_) { return cached_scopes_; } // open cache for input std::ifstream cache_file(c_scopes_cache_dir + c_scopes_cache_filename); if (!cache_file.fail()) { cached_scopes_ = std::string((std::istreambuf_iterator(cache_file)), std::istreambuf_iterator()); have_latest_cache_ = true; } return cached_scopes_; } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/smartscopes/SSQueryCtrlObject.cpp0000644000015301777760000000341412320776161031632 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include using namespace std; using namespace unity::scopes::internal; namespace unity { namespace scopes { namespace internal { namespace smartscopes { SSQueryCtrlObject::SSQueryCtrlObject() : destroyed_(false) { } SSQueryCtrlObject::~SSQueryCtrlObject() { } void SSQueryCtrlObject::cancel(InvokeInfo const& info) { if (destroyed_) { return; } QueryObjectBase::SPtr qo = qo_.lock(); if (qo) { qo->cancel(info); } } void SSQueryCtrlObject::destroy(InvokeInfo const& /* info */) { if (destroyed_.exchange(true)) { return; } disconnect(); } // Called by create_query() to tell us what the query facade object // is. We use the query facade object to forward cancellation. void SSQueryCtrlObject::set_query(QueryObjectBase::SPtr const& qo) { assert(!qo_.lock()); qo_ = qo; } } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/smartscopes/HttpClientQt.cpp0000644000015301777760000000767012320776161030676 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include #include #include #include #include #include #include using namespace unity::scopes::internal::smartscopes; //-- HttpClientQt HttpClientQt::HttpClientQt(uint no_reply_timeout) : session_index_(0) , no_reply_timeout_(no_reply_timeout) , app_(nullptr) { if (!QCoreApplication::instance()) { int argc = 0; app_ = std::unique_ptr(new QCoreApplication(argc, nullptr)); } } HttpClientQt::~HttpClientQt() { } HttpResponseHandle::SPtr HttpClientQt::get(std::string const& request_url) { std::lock_guard lock(sessions_mutex_); // start new session auto session = std::make_shared(request_url, no_reply_timeout_); sessions_[session_index_] = session; return std::make_shared(shared_from_this(), session_index_++, session->get_future()); } void HttpClientQt::cancel_get(uint session_id) { std::lock_guard lock(sessions_mutex_); // if session_id in map, cancel it auto it = sessions_.find(session_id); if (it != sessions_.end()) { it->second->cancel_session(); sessions_.erase(it); } } std::string HttpClientQt::to_percent_encoding(std::string const& string) { return QUrl::toPercentEncoding(string.c_str()).constData(); } //-- HttpClientQt::HttpSession HttpClientQt::HttpSession::HttpSession(std::string const& request_url, uint timeout) : promise_(nullptr) , qt_thread_(nullptr) { promise_ = std::make_shared>(); get_thread_ = std::thread([this, request_url, timeout]() { QUrl url(request_url.c_str()); { std::lock_guard lock(qt_thread_mutex_); qt_thread_ = std::unique_ptr(new HttpClientQtThread(url, timeout)); } QEventLoop loop; QObject::connect(qt_thread_.get(), &HttpClientQtThread::finished, &loop, &QEventLoop::quit); qt_thread_->start(); qt_thread_ready_.set_value(); loop.exec(); std::string reply; bool success = qt_thread_->get_reply(reply); if (!success) { unity::ResourceException e(reply); promise_->set_exception(e.self()); } else { promise_->set_value(reply); } }); qt_thread_ready_.get_future().wait(); } HttpClientQt::HttpSession::~HttpSession() { cancel_session(); } std::future HttpClientQt::HttpSession::get_future() { return promise_->get_future(); } void HttpClientQt::HttpSession::cancel_session() { { std::lock_guard lock(qt_thread_mutex_); qt_thread_->cancel(); } wait_for_session(); } void HttpClientQt::HttpSession::wait_for_session() { if (get_thread_.joinable()) { get_thread_.join(); } } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/smartscopes/SSQueryObject.cpp0000644000015301777760000001771512320776161031016 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace unity::scopes::internal; namespace unity { namespace scopes { namespace internal { namespace smartscopes { SSQueryObject::SSQueryObject() : QueryObjectBase() { } SSQueryObject::~SSQueryObject() noexcept { } void SSQueryObject::run(MWReplyProxy const& reply, InvokeInfo const& /*info*/) noexcept { decltype(queries_.begin()) query_it; try { { std::lock_guard lock(queries_mutex_); // find the targeted query according to InvokeInfo query_it = queries_.find(reply->identity()); if (query_it == end(queries_)) { throw ObjectNotExistException("Query does not exist", reply->identity()); } } if (query_it->second->q_pushable) { if (query_it->second->q_type == SSQuery::Query) { run_query(query_it->second, reply); } else if (query_it->second->q_type == SSQuery::Preview) { run_preview(query_it->second, reply); } else if (query_it->second->q_type == SSQuery::Activation) { run_activation(query_it->second, reply); } } } catch (std::exception const& e) { std::lock_guard lock(queries_mutex_); query_it->second->q_pushable = false; // TODO: log error reply->finished(ListenerBase::Error, e.what()); // Oneway, can't block cerr << "SSQueryObject::run(): " << e.what() << endl; } catch (...) { std::lock_guard lock(queries_mutex_); query_it->second->q_pushable = false; // TODO: log error reply->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block cerr << "SSQueryObject::run(): unknown exception" << endl; } { std::lock_guard lock(queries_mutex_); // the query is complete so this is no longer needed queries_.erase(reply->identity()); } } void SSQueryObject::cancel(InvokeInfo const& info) { std::lock_guard lock(queries_mutex_); std::string reply_id = info.id; reply_id.resize(reply_id.size() - 2); // remove the ".c" suffix // find the targeted query according to InvokeInfo auto query_it = queries_.find(reply_id); if (query_it == end(queries_)) { throw ObjectNotExistException("Query does not exist", info.id); } QueryBase::SPtr const& q_base = query_it->second->q_base; MWReplyProxy const& q_reply = query_it->second->q_reply; // this query is cancelled so replies are no longer pushable query_it->second->q_pushable = false; auto rp = query_it->second->q_reply_proxy.lock(); if (rp) { // Send finished() to up-stream client to tell him the query is done. // We send via the MWReplyProxy here because that allows passing // a ListenerBase::Reason (whereas the public ReplyProxy does not). q_reply->finished(ListenerBase::Cancelled, ""); // Oneway, can't block } // Forward the cancellation to the query base (which in turn will forward it to any subqueries). // The query base also calls the cancelled() callback to inform the application code. q_base->cancel(); } bool SSQueryObject::pushable(InvokeInfo const& info) const noexcept { std::lock_guard lock(queries_mutex_); // find query in queries_ from reply ID auto query_it = queries_.find(info.id); assert(query_it != end(queries_)); return query_it->second->q_pushable; } int SSQueryObject::cardinality(InvokeInfo const& info) const noexcept { std::lock_guard lock(queries_mutex_); // find query in queries_ from reply ID auto query_it = queries_.find(info.id); assert(query_it != end(queries_)); return query_it->second->q_cardinality; } void SSQueryObject::set_self(QueryObjectBase::SPtr const& /*self*/) noexcept { ///! TODO: remove } void SSQueryObject::add_query(SSQuery::QueryType query_type, std::shared_ptr const& query_base, int cardinality, MWReplyProxy const& reply) { std::unique_lock lock(queries_mutex_); // add the new query struct to queries_ queries_[reply->identity()] = std::make_shared(query_type, query_base, cardinality, reply); } void SSQueryObject::add_query(SSQuery::QueryType query_type, std::shared_ptr const& query_base, MWReplyProxy const& reply) { add_query(query_type, query_base, 0, reply); } void SSQueryObject::run_query(SSQuery::SPtr query, MWReplyProxy const& reply) { QueryBase::SPtr q_base; SearchReplyProxy q_reply_proxy; SearchQueryBase::SPtr search_query; q_base = query->q_base; // Create the reply proxy and keep a weak_ptr, which we will need // if cancel() is called later. q_reply_proxy = make_shared(reply, shared_from_this()); assert(q_reply_proxy); query->q_reply_proxy = q_reply_proxy; search_query = dynamic_pointer_cast(q_base); assert(search_query); // Synchronous call into scope implementation. // On return, replies for the query may still be outstanding. search_query->run(q_reply_proxy); } void SSQueryObject::run_preview(SSQuery::SPtr query, MWReplyProxy const& reply) { QueryBase::SPtr q_base; PreviewReplyProxy q_reply_proxy; PreviewQueryBase::SPtr preview_query; q_base = query->q_base; // Create the reply proxy and keep a weak_ptr, which we will need // if cancel() is called later. q_reply_proxy = make_shared(reply, shared_from_this()); assert(q_reply_proxy); query->q_reply_proxy = q_reply_proxy; preview_query = dynamic_pointer_cast(q_base); assert(preview_query); // Synchronous call into scope implementation. // On return, replies for the query may still be outstanding. preview_query->run(q_reply_proxy); } void SSQueryObject::run_activation(SSQuery::SPtr query, MWReplyProxy const& reply) { QueryBase::SPtr q_base; ActivationQueryBase::SPtr activation_query; q_base = query->q_base; activation_query = dynamic_pointer_cast(q_base); assert(activation_query); // no need for intermediate proxy (like with ReplyImpl::create), // since we get single return value from the public API // and just push it ourseleves auto res = activation_query->activate(); reply->push(res.serialize()); reply->finished(ListenerBase::Finished, ""); } } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/smartscopes/HttpClientQtThread.cpp0000644000015301777760000000625712320776161032026 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include "unity/scopes/internal/smartscopes/HttpClientQtThread.h" #include #include #include #include namespace unity { namespace scopes { namespace internal { namespace smartscopes { HttpClientQtThread::HttpClientQtThread(const QUrl& url, uint timeout) : QThread() , url_(url) , timeout_(timeout) , success_(false) { } HttpClientQtThread::~HttpClientQtThread() { cancel(); wait(); } bool HttpClientQtThread::get_reply(std::string& reply) { std::lock_guard lock(reply_mutex_); reply = reply_; return success_; } void HttpClientQtThread::run() { QNetworkAccessManager* manager = new QNetworkAccessManager(); QNetworkRequest request(url_); QNetworkReply* reply = manager->get(request); connect(manager, &QNetworkAccessManager::finished, this, &HttpClientQtThread::got_reply, Qt::DirectConnection); connect(this, &HttpClientQtThread::abort, reply, &QNetworkReply::abort); QTimer timeout; timeout.singleShot(timeout_, this, SLOT(timeout())); QThread::exec(); // enter event loop delete reply; delete manager; } void HttpClientQtThread::cancel() { std::lock_guard lock(reply_mutex_); success_ = false; reply_ = "Request cancelled: " + url_.url().toStdString(); emit abort(); quit(); } void HttpClientQtThread::timeout() { std::lock_guard lock(reply_mutex_); success_ = false; reply_ = "Request timed out: " + url_.url().toStdString(); emit abort(); quit(); } void HttpClientQtThread::got_reply(QNetworkReply* reply) { std::lock_guard lock(reply_mutex_); if (!reply_.empty()) { return; } if (!reply) { // no reply success_ = false; reply_ = "No reply from " + url_.url().toStdString(); } else if (!reply->isFinished()) { // incomplete reply success_ = false; reply_ = "Incomplete reply from " + url_.url().toStdString(); } else if (reply->error() != QNetworkReply::NoError) { // communication error success_ = false; reply_ = reply->errorString().toStdString(); } else { success_ = true; QByteArray byte_array = reply->readAll(); reply_ = std::string(byte_array.constData(), byte_array.size()); } quit(); } } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/smartscopes/CMakeLists.txt0000644000015301777760000000140512320776161030335 0ustar pbusernogroup00000000000000set(SRC ${CMAKE_CURRENT_SOURCE_DIR}/SSQueryCtrlObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/SSQueryObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/SSRegistryObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/SSScopeObject.cpp ) set(UNITY_SCOPES_LIB_SRC ${UNITY_SCOPES_LIB_SRC} ${SRC} PARENT_SCOPE) # -- libsmartscopes -- set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) find_package(Qt5Core REQUIRED) include_directories(${Qt5Core_INCLUDE_DIRS}) add_library( smartscopes STATIC HttpClientQt.cpp ${CMAKE_SOURCE_DIR}/include/unity/scopes/internal/smartscopes/HttpClientQtThread.h HttpClientQtThread.cpp SmartScopesClient.cpp ) qt5_use_modules( smartscopes Core Network ) target_link_libraries( smartscopes ${UNITY_API_LDFLAGS} ) unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/smartscopes/SSRegistryObject.cpp0000644000015301777760000002174612320776161031520 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include #include #include #include #include #include #include static const uint c_failed_refresh_timeout = 10; ///! TODO get from config static const char* c_dbussend_cmd = "dbus-send /com/canonical/unity/scopes com.canonical.unity.scopes.InvalidateResults string:smart-scopes"; namespace unity { namespace scopes { namespace internal { namespace smartscopes { SSRegistryObject::SSRegistryObject(MiddlewareBase::SPtr middleware, std::string const& ss_scope_endpoint, uint http_reply_timeout, uint refresh_rate_in_sec, std::string const& sss_url, bool caching_enabled) : ssclient_(std::make_shared( std::make_shared(http_reply_timeout), std::make_shared(), sss_url)) , refresh_stopped_(false) , middleware_(middleware) , ss_scope_endpoint_(ss_scope_endpoint) , regular_refresh_timeout_(refresh_rate_in_sec) , next_refresh_timeout_(refresh_rate_in_sec) , caching_enabled_(caching_enabled) { // get remote scopes then start the auto-refresh background thread try { get_remote_scopes(); } catch (std::exception const& e) { std::cerr << "SSRegistryObject: get_remote_scopes() failed: " << e.what(); } refresh_thread_ = std::thread(&SSRegistryObject::refresh_thread, this); } SSRegistryObject::~SSRegistryObject() noexcept { // stop the refresh thread { std::lock_guard lock(refresh_mutex_); refresh_stopped_ = true; refresh_cond_.notify_all(); } refresh_thread_.join(); } ScopeMetadata SSRegistryObject::get_metadata(std::string const& scope_id) const { // If the id is empty, it was sent as empty by the remote client. if (scope_id.empty()) { throw unity::InvalidArgumentException("SSRegistryObject: Cannot search for scope with empty id"); } std::lock_guard lock(scopes_mutex_); auto const& it = scopes_.find(scope_id); if (it == scopes_.end()) { throw NotFoundException("SSRegistryObject::get_metadata(): no such scope", scope_id); } return it->second; } MetadataMap SSRegistryObject::list() const { std::lock_guard lock(scopes_mutex_); return scopes_; } ObjectProxy SSRegistryObject::locate(std::string const& /*identity*/) { throw internal::RegistryException("SSRegistryObject::locate(): operation not available"); } bool SSRegistryObject::has_scope(std::string const& scope_id) const { std::lock_guard lock(scopes_mutex_); auto const& it = scopes_.find(scope_id); if (it == scopes_.end()) { return false; } return true; } std::string SSRegistryObject::get_base_url(std::string const& scope_id) const { std::lock_guard lock(scopes_mutex_); auto base_url = base_urls_.find(scope_id); if (base_url != end(base_urls_)) { return base_url->second; } else { throw NotFoundException("SSRegistryObject::get_base_url(): no such scope", scope_id); } } SmartScopesClient::SPtr SSRegistryObject::get_ssclient() const { return ssclient_; } void SSRegistryObject::refresh_thread() { std::lock_guard lock(refresh_mutex_); while (!refresh_stopped_) { refresh_cond_.wait_for(refresh_mutex_, std::chrono::seconds(next_refresh_timeout_)); if (!refresh_stopped_) { try { get_remote_scopes(); } catch (std::exception const& e) { std::cerr << "SSRegistryObject: get_remote_scopes() failed: " << e.what(); } } } } // Must be called with refresh_mutex_ locked void SSRegistryObject::get_remote_scopes() { std::vector remote_scopes; try { // request remote scopes from smart scopes client ///! TODO: locale if (ssclient_->get_remote_scopes(remote_scopes, "", caching_enabled_)) { next_refresh_timeout_ = regular_refresh_timeout_; } else { next_refresh_timeout_ = c_failed_refresh_timeout; } } catch (std::exception const& e) { std::cerr << e.what() << std::endl; // refresh again soon as get_remote_scopes failed next_refresh_timeout_ = c_failed_refresh_timeout; return; } MetadataMap new_scopes_; std::map new_base_urls_; // loop through all available scopes and add() each visible scope for (RemoteScope const& scope : remote_scopes) { try { // construct a ScopeMetadata with remote scope info std::unique_ptr metadata(new ScopeMetadataImpl(nullptr)); metadata->set_scope_id(scope.id); metadata->set_display_name(scope.name); metadata->set_description(scope.description); metadata->set_author(scope.author); if (scope.icon) { metadata->set_icon(*scope.icon); } if (scope.art) { metadata->set_art(*scope.art); } metadata->set_invisible(scope.invisible); ScopeProxy proxy = ScopeImpl::create(middleware_->create_scope_proxy(scope.id, ss_scope_endpoint_), middleware_->runtime(), scope.id); metadata->set_proxy(proxy); auto meta = ScopeMetadataImpl::create(move(metadata)); // add scope info to collection add(scope, std::move(meta), new_scopes_, new_base_urls_); } catch (std::exception const& e) { std::cerr << e.what() << std::endl; std::cerr << "SSRegistryObject: skipping scope \"" << scope.id << "\"" << std::endl; } } bool changed = false; // replace previous scopes with new ones { std::lock_guard lock(scopes_mutex_); // check if base urls or list of available scopes has changed. // the urls is a map of (string, string), so rely on == operator. // when comparing scopes maps, only check if scope ids are same, i.e. // changes to scope metadata attributes are not detected. if (new_base_urls_ != base_urls_ || new_scopes_.size() != scopes_.size()) { changed = true; } else { for (auto const& p: new_scopes_) { if (scopes_.find(p.first) == scopes_.end()) { changed = true; break; } } } // replace current collection of remote scopes base_urls_ = new_base_urls_; scopes_ = new_scopes_; } if (changed) { // something has changed, send invalidate signal int result = system(c_dbussend_cmd); (void)result; } } bool SSRegistryObject::add(RemoteScope const& remotedata, ScopeMetadata const& metadata, MetadataMap& scopes, std::map& urls) { if (metadata.scope_id().empty()) { throw unity::InvalidArgumentException("SSRegistryObject: Cannot add scope with empty id"); } // store the base url under a scope ID key urls[metadata.scope_id()] = remotedata.base_url; // store the scope metadata in scopes_ auto const& pair = scopes.insert(make_pair(metadata.scope_id(), metadata)); if (!pair.second) { // Replace already existing entry with this one scopes.erase(pair.first); scopes.insert(make_pair(metadata.scope_id(), metadata)); return false; } return true; } } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/smartscopes/SSScopeObject.cpp0000644000015301777760000001537012320776161030755 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { namespace smartscopes { SSScopeObject::SSScopeObject(std::string const& ss_scope_id, MiddlewareBase::SPtr middleware, SSRegistryObject::SPtr ss_registry) : ss_scope_id_(ss_scope_id) , co_(std::make_shared()) , qo_(std::make_shared()) , smartscope_(new SmartScope(ss_registry)) , ss_registry_(ss_registry) { // Connect the query ctrl to the middleware. middleware->add_dflt_query_ctrl_object(co_); // Connect the query object to the middleware. middleware->add_dflt_query_object(qo_); // We tell the ctrl what the query facade is co_->set_query(qo_); } SSScopeObject::~SSScopeObject() noexcept { } MWQueryCtrlProxy SSScopeObject::search(CannedQuery const& q, SearchMetadata const& hints, MWReplyProxy const& reply, InvokeInfo const& info) { return query(info, reply, [&q, &hints, &info, this ]()->QueryBase::SPtr { return this->smartscope_->search(info.id, q, hints); }, [&reply, &hints, this](QueryBase::SPtr query_base) { qo_->add_query(SSQuery::Query, query_base, hints.cardinality(), reply); }); } MWQueryCtrlProxy SSScopeObject::activate(Result const& result, ActionMetadata const& hints, MWReplyProxy const& reply, InvokeInfo const& info) { return query(info, reply, [&result, &hints, &info, this ]()->QueryBase::SPtr { return this->smartscope_->activate(info.id, result, hints); }, [&reply, &info, this](QueryBase::SPtr query_base) { qo_->add_query(SSQuery::Activation, query_base, reply); }); } MWQueryCtrlProxy SSScopeObject::perform_action(Result const& result, ActionMetadata const& hints, std::string const& widget_id, std::string const& action_id, MWReplyProxy const& reply, InvokeInfo const& info) { return query(info, reply, [&result, &hints, &info, &widget_id, &action_id, this ]()->QueryBase::SPtr { return this->smartscope_->perform_action(info.id, result, hints, widget_id, action_id); }, [&reply, &info, this](QueryBase::SPtr query_base) { qo_->add_query(SSQuery::Activation, query_base, reply); }); } MWQueryCtrlProxy SSScopeObject::preview(Result const& result, ActionMetadata const& hints, MWReplyProxy const& reply, InvokeInfo const& info) { return query(info, reply, [&result, &hints, &info, this ]()->QueryBase::SPtr { return this->smartscope_->preview(info.id, result, hints); }, [&reply, &info, this](QueryBase::SPtr query_base) { qo_->add_query(SSQuery::Preview, query_base, reply); }); } MWQueryCtrlProxy SSScopeObject::query(InvokeInfo const& info, MWReplyProxy const& reply, std::function const& query_factory_fun, std::function const& query_object_fun) { if (!ss_registry_->has_scope(info.id)) { throw ObjectNotExistException("SSScopeObject::query(): Remote scope does not exist", info.id); } if (!reply) { // TODO: log error about incoming request containing an invalid reply proxy. throw LogicException("SSScopeObject: query() called with null reply proxy"); } // Ask scope to instantiate a new query. QueryBase::SPtr query_base; try { query_base = query_factory_fun(); if (!query_base) { // TODO: log error, scope returned null pointer. throw ResourceException("SmartScope returned nullptr from query_factory_fun()"); } } catch (...) { throw ResourceException("SmartScope threw an exception from query_factory_fun()"); } try { // add new query to SS query object query_object_fun(query_base); // Start the query via the middleware (calling run() in a different thread) MWQueryProxy query_proxy = info.mw->create_query_proxy(info.id, info.mw->get_query_endpoint()); query_proxy->run(reply); } catch (std::exception const& e) { try { reply->finished(ListenerBase::Error, e.what()); } catch (...) { } std::cerr << "query(): " << e.what() << std::endl; // TODO: log error throw; } catch (...) { try { reply->finished(ListenerBase::Error, "unknown exception"); } catch (...) { } std::cerr << "query(): unknown exception" << std::endl; // TODO: log error throw; } return info.mw->create_query_ctrl_proxy(reply->identity() + ".c", info.mw->get_query_ctrl_endpoint()); } } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/RegistryImpl.cpp0000644000015301777760000000355112320776161026374 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { RegistryImpl::RegistryImpl(MWRegistryProxy const& mw_proxy, RuntimeImpl*) : ObjectImpl(mw_proxy) { } RegistryImpl::~RegistryImpl() { } ScopeMetadata RegistryImpl::get_metadata(std::string const& scope_id) { return fwd()->get_metadata(scope_id); } MetadataMap RegistryImpl::list() { return fwd()->list(); } ObjectProxy RegistryImpl::locate(std::string const& identity) { return fwd()->locate(identity); } MetadataMap RegistryImpl::list_if(std::function predicate) { auto scope_map = list(); MetadataMap matching_entries; for (auto& pair : scope_map) { if (predicate(pair.second)) { matching_entries.emplace(pair); } } return matching_entries; } MWRegistryProxy RegistryImpl::fwd() const { return dynamic_pointer_cast(proxy()); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ScopeImpl.cpp0000644000015301777760000002076512320776161025643 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include #include #include // TODO: remove this once logging is added using namespace std; namespace unity { namespace scopes { namespace internal { ScopeImpl::ScopeImpl(MWScopeProxy const& mw_proxy, RuntimeImpl* runtime, std::string const& scope_id) : ObjectImpl(mw_proxy), runtime_(runtime), scope_id_(scope_id) { assert(runtime); } ScopeImpl::~ScopeImpl() { } QueryCtrlProxy ScopeImpl::search(std::string const& query_string, std::string const& department_id, FilterState const& filter_state, SearchMetadata const& metadata, SearchListenerBase::SPtr const& reply) { CannedQuery query(scope_id_, query_string, department_id); query.set_filter_state(filter_state); return search(query, metadata, reply); } QueryCtrlProxy ScopeImpl::search(std::string const& query_string, FilterState const& filter_state, SearchMetadata const& metadata, SearchListenerBase::SPtr const& reply) { CannedQuery query(scope_id_); query.set_query_string(query_string); query.set_filter_state(filter_state); return search(query, metadata, reply); } QueryCtrlProxy ScopeImpl::search(string const& query_string, SearchMetadata const& metadata, SearchListenerBase::SPtr const& reply) { CannedQuery query(scope_id_); query.set_query_string(query_string); return search(query, metadata, reply); } QueryCtrlProxy ScopeImpl::search(CannedQuery const& query, SearchMetadata const& metadata, SearchListenerBase::SPtr const& reply) { if (reply == nullptr) { throw unity::InvalidArgumentException("Scope::search(): invalid SearchListenerBase (nullptr)"); } QueryCtrlProxy ctrl; ReplyObject::SPtr ro(make_shared(reply, runtime_, to_string(), metadata.cardinality())); try { MWReplyProxy rp = fwd()->mw_base()->add_reply_object(ro); // Forward the search() method across the bus. This is a // synchronous twoway interaction with the scope, so it can return // the QueryCtrlProxy. This may block for some time, for example, if // the scope is not running and needs to be activated by the registry first. ctrl = fwd()->search(query, metadata.serialize(), rp); assert(ctrl); } catch (std::exception const& e) { try { ro->finished(ListenerBase::Error, e.what()); } catch (...) { } throw; } return ctrl; } QueryCtrlProxy ScopeImpl::activate(Result const& result, ActionMetadata const& metadata, ActivationListenerBase::SPtr const& reply) { if (reply == nullptr) { throw unity::InvalidArgumentException("Scope::activate(): invalid ActivationListenerBase (nullptr)"); } QueryCtrlProxy ctrl; ActivationReplyObject::SPtr ro(make_shared(reply, runtime_, to_string())); try { MWReplyProxy rp = fwd()->mw_base()->add_reply_object(ro); // Forward the activate() method across the bus. ctrl = fwd()->activate(result.p->activation_target(), metadata.serialize(), rp); assert(ctrl); } catch (std::exception const& e) { // TODO: log error cerr << "activate(): " << e.what() << endl; try { ro->finished(ListenerBase::Error, e.what()); throw; } catch (...) { cerr << "activate(): unknown exception" << endl; } throw; } return ctrl; } QueryCtrlProxy ScopeImpl::perform_action(Result const& result, ActionMetadata const& metadata, std::string const& widget_id, std::string const& action_id, ActivationListenerBase::SPtr const& reply) { if (reply == nullptr) { throw unity::InvalidArgumentException("Scope::perform_action(): invalid ActivationListenerBase (nullptr)"); } QueryCtrlProxy ctrl; try { // Create a middleware server-side object that can receive incoming // push() and finished() messages over the network. ActivationReplyObject::SPtr ro(make_shared(reply, runtime_, to_string())); MWReplyProxy rp = fwd()->mw_base()->add_reply_object(ro); // Forward the activate() method across the bus. ctrl = fwd()->perform_action(result.p->activation_target(), metadata.serialize(), widget_id, action_id, rp); assert(ctrl); } catch (std::exception const& e) { // TODO: log error cerr << "perform_action(): " << e.what() << endl; try { // TODO: if things go wrong, we need to make sure that the reply object // is disconnected from the middleware, so it gets deallocated. reply->finished(ListenerBase::Error, e.what()); throw; } catch (...) { cerr << "perform_action(): unknown exception" << endl; } throw; } return ctrl; } QueryCtrlProxy ScopeImpl::preview(Result const& result, ActionMetadata const& hints, PreviewListenerBase::SPtr const& reply) { if (reply == nullptr) { throw unity::InvalidArgumentException("Scope::preview(): invalid PreviewListenerBase (nullptr)"); } QueryCtrlProxy ctrl; PreviewReplyObject::SPtr ro(make_shared(reply, runtime_, to_string())); try { // Create a middleware server-side object that can receive incoming // push() and finished() messages over the network. MWReplyProxy rp = fwd()->mw_base()->add_reply_object(ro); // Forward the search() method across the bus. This is a // synchronous twoway interaction with the scope, so it can return // the QueryCtrlProxy. Because the Scope implementation has a separate // thread for search() calls, this is guaranteed not to block for // any length of time. (No application code other than the QueryBase constructor // is called by search() on the server side.) ctrl = fwd()->preview(result.p->activation_target(), hints.serialize(), rp); assert(ctrl); } catch (std::exception const& e) { // TODO: log error cerr << "preview(): " << e.what() << endl; try { ro->finished(ListenerBase::Error, e.what()); throw; } catch (...) { cerr << "preview(): unknown exception" << endl; } throw; } return ctrl; } ScopeProxy ScopeImpl::create(MWScopeProxy const& mw_proxy, RuntimeImpl* runtime, std::string const& scope_id) { return make_shared(mw_proxy, runtime, scope_id); } MWScopeProxy ScopeImpl::fwd() const { return dynamic_pointer_cast(proxy()); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/PreviewReplyImpl.cpp0000644000015301777760000000603212320776161027216 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski * Michi Henning */ #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { PreviewReplyImpl::PreviewReplyImpl(MWReplyProxy const& mw_proxy, shared_ptr const& qo) : ObjectImpl(mw_proxy), ReplyImpl(mw_proxy, qo), layouts_push_disallowed_(false) { } PreviewReplyImpl::~PreviewReplyImpl() { } bool PreviewReplyImpl::register_layout(unity::scopes::ColumnLayoutList const& layouts) { // basic check for consistency of layouts try { ColumnLayoutImpl::validate_layouts(layouts); } catch (unity::LogicException const &e) { throw unity::LogicException("PreviewReplyImpl::register_layout(): Failed to validate layouts"); } // OK to set this now because what follows can't go wrong unless the query is dead. if (layouts_push_disallowed_.exchange(true)) { throw unity::LogicException("PreviewReplyImpl::register_layout(): column layouts can only be registered " "once and before pushing preview widgets"); } VariantMap vm; VariantArray arr; for (auto const& layout: layouts) { arr.push_back(Variant(layout.serialize())); } vm["columns"] = arr; if (!ReplyImpl::push(vm)) { throw unity::LogicException("PreviewReplyImpl::register_layout(): cannot register layout with finished " "or cancelled query"); } return true; } bool PreviewReplyImpl::push(unity::scopes::PreviewWidgetList const& widgets) { // TODO: why is it possible to push more than one list of widgets without getting an exception? layouts_push_disallowed_ = true; VariantMap vm; VariantArray arr; for (auto const& widget : widgets) { arr.push_back(Variant(widget.serialize())); } vm["widgets"] = arr; return ReplyImpl::push(vm); } bool PreviewReplyImpl::push(string const& key, Variant const& value) { VariantMap vm; VariantMap nested; nested[key] = value; vm["preview-data"] = nested; return ReplyImpl::push(vm); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/QueryMetadataImpl.cpp0000644000015301777760000000364412320776161027335 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { namespace internal { QueryMetadataImpl::QueryMetadataImpl(std::string const& locale, std::string const& form_factor) : locale_(locale), form_factor_(form_factor) { } QueryMetadataImpl::QueryMetadataImpl(VariantMap const& var) { static const std::string context("QueryMetadataImpl()"); auto it = find_or_throw(context, var, "locale"); locale_ = it->second.get_string(); it = find_or_throw(context, var, "form_factor"); form_factor_ = it->second.get_string(); } std::string QueryMetadataImpl::locale() const { return locale_; } std::string QueryMetadataImpl::form_factor() const { return form_factor_; } void QueryMetadataImpl::serialize(VariantMap &var) const { var["type"] = metadata_type(); var["locale"] = locale_; var["form_factor"] = form_factor_; } VariantMap QueryMetadataImpl::serialize() const { VariantMap vm; serialize(vm); return vm; } std::string QueryMetadataImpl::metadata_type() const { static const std::string t("query_metadata"); return t; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/QueryCtrlObject.cpp0000644000015301777760000000332612320776161027023 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; using namespace unity::scopes::internal; namespace unity { namespace scopes { namespace internal { QueryCtrlObject::QueryCtrlObject() : destroyed_(false) { } QueryCtrlObject::~QueryCtrlObject() { } void QueryCtrlObject::cancel(InvokeInfo const& info) { if (destroyed_.exchange(true)) { return; } QueryObjectBase::SPtr qo = qo_.lock(); if (qo) { qo->cancel(info); } disconnect(); } void QueryCtrlObject::destroy(InvokeInfo const& /* info */) { if (destroyed_.exchange(true)) { return; } disconnect(); } // Called by create_query() to tell us what the query facade object // is. We use the query facade object to forward cancellation. void QueryCtrlObject::set_query(QueryObjectBase::SPtr const& qo) { assert(!qo_.lock()); qo_ = qo; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/CategoryRendererImpl.cpp0000644000015301777760000000353712320776161030034 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include namespace unity { namespace scopes { namespace internal { //! @cond CategoryRendererImpl::CategoryRendererImpl(std::string const& json_text) : data_(json_text) { try { const internal::JsonCppNode node(json_text); if (node.type() != internal::JsonNodeInterface::NodeType::Object) { throw unity::InvalidArgumentException("CategoryRenderer(): invalid JSON definition, template is not a dictionary"); } } catch (unity::ResourceException const&) { throw unity::InvalidArgumentException("CategoryRenderer(): invalid JSON definition"); } } CategoryRenderer CategoryRendererImpl::from_file(std::string const& path) { const std::string contents = unity::util::read_text_file(path); return CategoryRenderer(contents); } std::string CategoryRendererImpl::data() const { return data_; } //! @endcond } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/MWObject.cpp0000644000015301777760000000225612320776161025415 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace std; using namespace unity::scopes::internal; namespace unity { namespace scopes { namespace internal { MWObjectProxy::MWObjectProxy(MiddlewareBase* mw_base) : mw_base_(mw_base) { assert(mw_base); } MWObjectProxy::~MWObjectProxy() { } MiddlewareBase* MWObjectProxy::mw_base() const noexcept { return mw_base_; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/SearchReplyImpl.cpp0000644000015301777760000001107212320776161027002 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski * Michi Henning */ #include #include #include #include #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { SearchReplyImpl::SearchReplyImpl(MWReplyProxy const& mw_proxy, std::shared_ptr const& qo) : ObjectImpl(mw_proxy), ReplyImpl(mw_proxy, qo), cat_registry_(new CategoryRegistry()), cardinality_(qo->cardinality({ fwd()->identity(), fwd()->mw_base() })), num_pushes_(0) { } SearchReplyImpl::~SearchReplyImpl() { } void SearchReplyImpl::register_departments(DepartmentList const& departments, std::string current_department_id) { // basic consistency check try { DepartmentImpl::validate_departments(departments, current_department_id); } catch (unity::LogicException const &e) { throw unity::LogicException("Reply::register_departments(): Failed to validate departments"); } ReplyImpl::push(internal::DepartmentImpl::serialize_departments(departments, current_department_id)); // ignore return value? } void SearchReplyImpl::register_category(Category::SCPtr category) { cat_registry_->register_category(category); // will throw if that category id has already been registered push(category); } Category::SCPtr SearchReplyImpl::register_category(std::string const& id, std::string const& title, std::string const &icon, CategoryRenderer const& renderer_template) { // will throw if adding same category again auto cat = cat_registry_->register_category(id, title, icon, renderer_template); push(cat); return cat; } Category::SCPtr SearchReplyImpl::lookup_category(std::string const& id) { return cat_registry_->lookup_category(id); } bool SearchReplyImpl::register_annotation(unity::scopes::Annotation const& annotation) { VariantMap var; var["annotation"] = annotation.serialize(); return ReplyImpl::push(var); } bool SearchReplyImpl::push(unity::scopes::CategorisedResult const& result) { // If this is an aggregator scope, it may be pushing result items obtained // from ReplyObject without registering a category first. if (cat_registry_->lookup_category(result.category()->id()) == nullptr) { register_category(result.category()); } VariantMap var; var["result"] = result.serialize(); if (!ReplyImpl::push(var)) { return false; } // Enforce cardinality limit (0 means no limit). If the scope pushes more results // than requested, future pushes are ignored. push() returns false // on the last call that actually still pushed a result. // To the client, a query that exceeds the limit looks like a query // that returned the maximum number of results and finished normally. if (++num_pushes_ == cardinality_) { // At most one thread will execute this. finished(); return false; // This was the last successful push } return true; } bool SearchReplyImpl::push(unity::scopes::Filters const& filters, unity::scopes::FilterState const& filter_state) { VariantMap var; var["filters"] = internal::FilterBaseImpl::serialize_filters(filters); var["filter_state"] = filter_state.serialize(); return ReplyImpl::push(var); } bool SearchReplyImpl::push(Category::SCPtr category) { VariantMap var; var["category"] = category->serialize(); return ReplyImpl::push(var); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ReplyObject.cpp0000644000015301777760000001271112320776161026162 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include // TODO: remove this once logging is added using namespace std; using namespace unity::scopes::internal; namespace unity { namespace scopes { namespace internal { ReplyObject::ReplyObject(ListenerBase::SPtr const& receiver_base, RuntimeImpl const* runtime, std::string const& scope_proxy) : listener_base_(receiver_base), finished_(false), origin_proxy_(scope_proxy), num_push_(0) { assert(receiver_base); assert(runtime); reap_item_ = runtime->reply_reaper()->add([this] { cerr << "No activity on ReplyObject for scope " << this->origin_proxy_ << ": ReplyObject destroyed" << endl; this->disconnect(); }); } ReplyObject::~ReplyObject() { try { finished(ListenerBase::Finished, ""); } catch (...) { } } void ReplyObject::push(VariantMap const& result) noexcept { // We catch all exceptions so, if the application's push() method throws, // we can call finished(). Finished will be called exactly once, whether // push() or finished() throw or not. // // It is possible for a call to push() to arrive after finish() was // called. In particular, if the reaper times out this object while // a push() is in transit from the remote end, depending on scheduling // order, it is possible for push() to be called after finish() was // called. So, we enforce that finish() will be called exactly once, and that // push() will not be called once finished() was called. // // Calls to push() can be dispatched concurrently if the reply side is // configured with more than one thread. However, finished() is passed // to the application only once all executing concurrent push() calls have completed. if (finished_.load()) { return; // Ignore replies that arrive after finished(). } reap_item_->refresh(); { unique_lock lock(mutex_); assert(num_push_ >= 0); ++num_push_; } // Forward invocations to application outside synchronization bool stop = false; string error; try { stop = process_data(result); // Returns true if cardinality limit was reached } catch (std::exception const& e) { error = string("ReplyObject::push(VariantMap): ") + e.what(); } catch (...) { error = "ReplyObject::push(VariantMap): unknown exception"; } // Decrement number of pushes before potentially calling finished(), // because finished() waits for concurrent push() calls to complete. { unique_lock lock(mutex_); if (--num_push_ == 0) { idle_.notify_one(); } } // Safe to call finished now if something went wrong or cardinality was exceeded. if (!error.empty()) { // TODO: log error finished(ListenerBase::Error, error); } else if (stop) { // TODO: log error finished(ListenerBase::Finished, ""); } } void ReplyObject::finished(ListenerBase::Reason r, string const& error_message) noexcept { // We permit exactly one finished() call for a query. This avoids // a race condition where the executing down-stream query invokes // finished() concurrently with the QueryCtrl forwarding a cancel() // call to this reply's finished() method. if (finished_.exchange(true)) { return; } // Only one thread can reach this point, any others were thrown out above. reap_item_->destroy(); disconnect(); // Disconnect self from middleware, if this hasn't happened yet. // Wait until all currently executing calls to push() have completed. unique_lock lock(mutex_); assert(num_push_ >= 0); idle_.wait(lock, [this] { return num_push_ == 0; }); lock.unlock(); // Inform the application code that the query is complete outside synchronization. try { listener_base_->finished(r, error_message); } catch (std::exception const& e) { cerr << "ReplyObject::finished(): " << e.what() << endl; // TODO: log error } catch (...) { cerr << "ReplyObject::finished(): unknown exception" << endl; // TODO: log error } } std::string ReplyObject::origin_proxy() const { return origin_proxy_; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/CategoryRegistry.cpp0000644000015301777760000000410412320776161027243 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include namespace unity { namespace scopes { namespace internal { void CategoryRegistry::register_category(Category::SCPtr category) { std::lock_guard lock(mutex_); if (categories_.find(category->id()) != categories_.end()) { std::ostringstream s; s << "Category " << category->id() << " already defined"; throw InvalidArgumentException(s.str()); } categories_[category->id()] = category; } Category::SCPtr CategoryRegistry::register_category(VariantMap const& variant_map) { auto cat = std::shared_ptr(new Category(variant_map)); register_category(cat); return cat; } Category::SCPtr CategoryRegistry::register_category(std::string const& id, std::string const& title, std::string const& icon, CategoryRenderer const& renderer_template) { auto cat = std::shared_ptr(new Category(id, title, icon, renderer_template)); register_category(cat); return cat; } Category::SCPtr CategoryRegistry::lookup_category(std::string const& id) const { std::lock_guard lock(mutex_); auto it = categories_.find(id); if (it != categories_.end()) { return it->second; } return nullptr; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/VariantBuilderImpl.cpp0000644000015301777760000000512212320776161027473 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { namespace internal { VariantBuilderImpl::VariantBuilderImpl(VariantBuilderImpl const& other) { if (other.variant_) { variant_.reset(new Variant(*(other.variant_))); } } void VariantBuilderImpl::add_tuple(std::initializer_list> const& tuple) { VariantArray va; if (variant_ != nullptr) { if (variant_->which() == Variant::Type::Array) { va = variant_->get_array(); } else if (!variant_->is_null()) // if null (the initial type of the internal variant), then init it with an array, otherwise throw { throw unity::LogicException("Can only add tuple to a variant of array type"); } } va.push_back(Variant(VariantMap(tuple.begin(), tuple.end()))); variant_.reset(new Variant(std::move(va))); } void VariantBuilderImpl::add_tuple(std::vector> const& tuple) { VariantArray va; if (variant_ != nullptr) { if (variant_->which() == Variant::Type::Array) { va = variant_->get_array(); } else if (!variant_->is_null()) // if null (the initial type of the internal variant), then init it with an array, otherwise throw { throw unity::LogicException("Can only add tuple to a variant of array type"); } } va.push_back(Variant(VariantMap(tuple.begin(), tuple.end()))); variant_.reset(new Variant(std::move(va))); } Variant VariantBuilderImpl::end() { if (variant_ == nullptr) { throw unity::LogicException("VariantBuilder::end(): no Variant has been constructed"); } Variant v(std::move(*variant_)); variant_.reset(); return v; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/FilterBaseImpl.cpp0000644000015301777760000000535312320776161026606 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include namespace unity { namespace scopes { namespace internal { FilterBaseImpl::FilterBaseImpl(std::string const& id) : id_(id) { } FilterBaseImpl::FilterBaseImpl(VariantMap const& var) { auto it = var.find("id"); if (it == var.end()) { throw unity::LogicException("FilterBase: missing 'id'"); } id_ = it->second.get_string(); } FilterBaseImpl::~FilterBaseImpl() = default; std::string FilterBaseImpl::id() const { return id_; } VariantMap FilterBaseImpl::serialize() const { VariantMap vm; vm["id"] = id_; vm["filter_type"] = filter_type(); serialize(vm); return vm; } Variant FilterBaseImpl::get(FilterState const& filter_state, std::string const& filter_id) { return filter_state.p->get(filter_id); } VariantMap& FilterBaseImpl::get(FilterState const& filter_state) { return filter_state.p->get(); } FilterBase::SCPtr FilterBaseImpl::deserialize(VariantMap const& var) { auto it = var.find("filter_type"); if (it != var.end()) { auto ftype = it->second.get_string(); if (ftype == "option_selector") { return std::shared_ptr(new OptionSelectorFilter(var)); } throw unity::LogicException("Unknown filter type: " + ftype); } throw unity::LogicException("FilterBase: Missing 'filter_type'"); } VariantArray FilterBaseImpl::serialize_filters(Filters const& filters) { VariantArray var; for (auto const& f: filters) { var.push_back(Variant(f->serialize())); } return var; } Filters FilterBaseImpl::deserialize_filters(VariantArray const& var) { Filters filters; for (auto const& f: var) { filters.push_back(FilterBaseImpl::deserialize(f.get_dict())); } return filters; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/RuntimeConfig.cpp0000644000015301777760000000546712320776161026523 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { const char* RuntimeConfig::RUNTIME_CONFIG_GROUP = "Runtime"; namespace { const string registry_identity_str = "Registry.Identity"; const string registry_configfile_str = "Registry.ConfigFile"; const string default_middleware_str = "Default.Middleware"; const string default_middleware_configfile_str = "ConfigFile"; } RuntimeConfig::RuntimeConfig(string const& configfile) : ConfigBase(configfile) { if (configfile.empty()) // Default config { registry_identity_ = "Registry"; registry_configfile_ = DFLT_REGISTRY_INI; default_middleware_ = "Zmq"; default_middleware_configfile_ = "Zmq.ini"; } else { registry_identity_ = get_optional_string(RUNTIME_CONFIG_GROUP, registry_identity_str); auto pos = registry_identity_.find_first_of("@:/"); if (pos != string::npos) { throw_ex("Illegal character in value for " + registry_identity_str + ": \"" + registry_identity_ + "\": identity cannot contain '" + registry_identity_[pos] + "'"); } registry_configfile_ = get_optional_string(RUNTIME_CONFIG_GROUP, registry_configfile_str); default_middleware_ = get_middleware(RUNTIME_CONFIG_GROUP, default_middleware_str); default_middleware_configfile_ = get_string(RUNTIME_CONFIG_GROUP, default_middleware_ + "." + default_middleware_configfile_str); } } RuntimeConfig::~RuntimeConfig() { } string RuntimeConfig::registry_identity() const { return registry_identity_; } string RuntimeConfig::registry_configfile() const { return registry_configfile_; } string RuntimeConfig::default_middleware() const { return default_middleware_; } string RuntimeConfig::default_middleware_configfile() const { return default_middleware_configfile_; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/MWRegistry.cpp0000644000015301777760000000200012320776161026002 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include using namespace std; namespace unity { namespace scopes { namespace internal { MWRegistry::MWRegistry(MiddlewareBase* mw_base) : MWObjectProxy(mw_base) { } MWRegistry::~MWRegistry() { } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ScopeConfig.cpp0000644000015301777760000001202312320776161026133 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace { const string overrideable_str = "Override"; const string scope_id_str = "DisplayName"; const string description_str = "Description"; const string author_str = "Author"; const string art_str = "Art"; const string icon_str = "Icon"; const string search_hint_str = "SearchHint"; const string hot_key_str = "HotKey"; const string invisible_str = "Invisible"; const string scope_runner_exec = "ScopeRunner"; } ScopeConfig::ScopeConfig(string const& configfile) : ConfigBase(configfile) { try { overrideable_ = parser()->get_boolean(SCOPE_CONFIG_GROUP, overrideable_str); } catch (LogicException const&) { overrideable_ = false; } display_name_ = parser()->get_string(SCOPE_CONFIG_GROUP, scope_id_str); description_ = parser()->get_string(SCOPE_CONFIG_GROUP, description_str); author_ = parser()->get_string(SCOPE_CONFIG_GROUP, author_str); // For optional values, we store them in a unique_ptr so we can distinguish the "not set at all" case // from the "explicitly set to empty string" case. parser()->get_string throws LogicException if // the key is not present, so we ignore the exception for optional values. try { string art = parser()->get_string(SCOPE_CONFIG_GROUP, art_str); art_.reset(new string(art)); } catch (LogicException const&) { } try { string icon = parser()->get_string(SCOPE_CONFIG_GROUP, icon_str); icon_.reset(new string(icon)); } catch (LogicException const&) { } try { string hint = parser()->get_string(SCOPE_CONFIG_GROUP, search_hint_str); search_hint_.reset(new string(hint)); } catch (LogicException const&) { } try { string key = parser()->get_string(SCOPE_CONFIG_GROUP, hot_key_str); hot_key_.reset(new string(key)); } catch (LogicException const&) { } try { string key = parser()->get_string(SCOPE_CONFIG_GROUP, invisible_str); std::transform(begin(key), end(key), begin(key), ::toupper); invisible_.reset(new bool(key == "TRUE")); } catch (LogicException const&) { } // custom scope runner executable is optional try { string key = parser()->get_string(SCOPE_CONFIG_GROUP, scope_runner_exec); scope_runner_.reset(new string(key)); } catch (LogicException const&) { } // read all display attributes from SCOPE_DISPLAY_GROUP config group try { for (auto const& key: parser()->get_keys(SCOPE_DISPLAY_GROUP)) { appearance_attributes_[key] = parser()->get_string(SCOPE_DISPLAY_GROUP, key); } } catch (LogicException const&) { } } ScopeConfig::~ScopeConfig() { } bool ScopeConfig::overrideable() const { return overrideable_; } string ScopeConfig::display_name() const { return display_name_; } string ScopeConfig::description() const { return description_; } string ScopeConfig::author() const { return author_; } string ScopeConfig::art() const { if (!art_) { throw NotFoundException("Art not set", art_str); } return *art_; } string ScopeConfig::icon() const { if (!icon_) { throw NotFoundException("Icon not set", icon_str); } return *icon_; } string ScopeConfig::search_hint() const { if (!search_hint_) { throw NotFoundException("Hint not set", search_hint_str); } return *search_hint_; } string ScopeConfig::hot_key() const { if (!hot_key_) { throw NotFoundException("Key not set", hot_key_str); } return *hot_key_; } bool ScopeConfig::invisible() const { if (!invisible_) { return false; } return *invisible_; } string ScopeConfig::scope_runner() const { if (!scope_runner_) { throw NotFoundException("Runner binary not set", scope_runner_exec); } return *scope_runner_; } VariantMap ScopeConfig::appearance_attributes() const { return appearance_attributes_; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ColumnLayoutImpl.cpp0000644000015301777760000001043412320776161027215 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include namespace unity { namespace scopes { namespace internal { ColumnLayoutImpl::ColumnLayoutImpl(int num_of_columns) : num_of_columns_(num_of_columns) { if (num_of_columns_ <= 0 || num_of_columns_ > max_number_of_columns_) { // don't print allowed range since max_number_of_columns_ is an internal safeguard // and we don't really have a hardcoded limit defined for the API and shell. throw unity::InvalidArgumentException("ColumnLayout(): invalid number of columns"); } } ColumnLayoutImpl::ColumnLayoutImpl(VariantMap const& var) { auto it = var.find("column_data"); if (it == var.end()) { throw unity::InvalidArgumentException("ColumnLayoutImpl(): missing column_data"); } auto const& outerarr = it->second.get_array(); num_of_columns_ = outerarr.size(); for (auto const& arr: outerarr) { std::vector widgets; for (auto const& w: arr.get_array()) { widgets.push_back(w.get_string()); } columns_.push_back(widgets); } } void ColumnLayoutImpl::add_column(std::vector widget_ids) { if (static_cast(columns_.size()) >= num_of_columns_) { std::ostringstream str; str << "ColumnLayout::add_column(): excessive column, exepcting " << num_of_columns_ << " columns"; throw unity::LogicException(str.str()); } columns_.push_back(widget_ids); } int ColumnLayoutImpl::size() const noexcept { return columns_.size(); } int ColumnLayoutImpl::number_of_columns() const noexcept { return num_of_columns_; } std::vector ColumnLayoutImpl::column(int index) const { if (index >= static_cast(columns_.size())) { std::ostringstream str; str << "ColumnLayout::column(): invalid column index " << index << ", layout size is " << columns_.size(); throw unity::InvalidArgumentException(str.str()); } return columns_[index]; } VariantMap ColumnLayoutImpl::serialize() const { VariantArray outerarr; for (auto const& col: columns_) { VariantArray arr; for (auto const& w: col) { arr.push_back(Variant(w)); } outerarr.push_back(Variant(arr)); } VariantMap vm; vm["column_data"] = Variant(outerarr); return vm; } ColumnLayout ColumnLayoutImpl::create(VariantMap const& var) { return ColumnLayout(new ColumnLayoutImpl(var)); } void ColumnLayoutImpl::validate_layouts(ColumnLayoutList const& layouts) { std::unordered_set layout_number_lut; // lookup for number of columns to ensure we have only one layout for each column setup // basic check for consistency of layouts for (auto const& layout: layouts) { if (layout.size() != layout.number_of_columns()) { std::ostringstream str; str << "ColumnLayout::validate_layouts(): expected " << layout.number_of_columns() << " but only " << layout.size() << " defined"; throw LogicException(str.str()); } if (layout_number_lut.find(layout.number_of_columns()) != layout_number_lut.end()) { std::ostringstream str; str << "ColumnLayout::validate_layouts(): duplicate definition of layout with " << layout.number_of_columns() << " number of columns"; throw LogicException(str.str()); } layout_number_lut.insert(layout.size()); } } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/RuntimeImpl.cpp0000644000015301777760000001614212320776161026207 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // TODO: remove this once logging is added using namespace std; using namespace unity::scopes; namespace unity { namespace scopes { namespace internal { RuntimeImpl::RuntimeImpl(string const& scope_id, string const& configfile) : destroyed_(false), scope_id_(scope_id) { if (scope_id.empty()) { UniqueID id; scope_id_ = "c-" + id.gen(); } string config_file(configfile.empty() ? DFLT_RUNTIME_INI : configfile); configfile_ = config_file; try { // Create the middleware factory and get the registry identity and config filename. RuntimeConfig config(config_file); string default_middleware = config.default_middleware(); string middleware_configfile = config.default_middleware_configfile(); middleware_factory_.reset(new MiddlewareFactory(this)); registry_configfile_ = config.registry_configfile(); registry_identity_ = config.registry_identity(); middleware_ = middleware_factory_->create(scope_id_, default_middleware, middleware_configfile); middleware_->start(); if (registry_configfile_.empty() || registry_identity_.empty()) { cerr << "Warning: no registry configured" << endl; registry_identity_ = ""; } else { // Create the registry proxy. RegistryConfig reg_config(registry_identity_, registry_configfile_); string reg_mw_configfile = reg_config.mw_configfile(); registry_endpoint_ = reg_config.endpoint(); registry_endpointdir_ = reg_config.endpointdir(); auto registry_mw_proxy = middleware_->create_registry_proxy(registry_identity_, registry_endpoint_); registry_ = make_shared(registry_mw_proxy, this); } } catch (unity::Exception const& e) { throw ConfigException("Cannot instantiate run time for " + scope_id + ", config file: " + config_file); } } RuntimeImpl::~RuntimeImpl() { try { destroy(); } catch (std::exception const& e) // LCOV_EXCL_LINE { cerr << "~RuntimeImpl(): " << e.what() << endl; // TODO: log error } catch (...) // LCOV_EXCL_LINE { cerr << "~RuntimeImpl(): unknown exception" << endl; // TODO: log error } } RuntimeImpl::UPtr RuntimeImpl::create(string const& scope_id, string const& configfile) { return UPtr(new RuntimeImpl(scope_id, configfile)); } void RuntimeImpl::destroy() { if (!destroyed_.exchange(true)) { // TODO: not good enough. Need to wait for the middleware to stop and for the reaper // to terminate. Otherwise, it's possible that we exit while threads are still running // with undefined behavior. registry_ = nullptr; middleware_->stop(); middleware_ = nullptr; middleware_factory_.reset(nullptr); reply_reaper_ = nullptr; } } string RuntimeImpl::scope_id() const { return scope_id_; } string RuntimeImpl::configfile() const { return configfile_; } MiddlewareFactory const* RuntimeImpl::factory() const { if (destroyed_.load()) { throw LogicException("factory(): Cannot obtain factory for already destroyed run time"); } return middleware_factory_.get(); } RegistryProxy RuntimeImpl::registry() const { if (destroyed_.load()) { throw LogicException("registry(): Cannot obtain registry for already destroyed run time"); } if (!registry_) { throw ConfigException("registry(): no registry configured"); } return registry_; } string RuntimeImpl::registry_configfile() const { return registry_configfile_; } string RuntimeImpl::registry_identity() const { return registry_identity_; } string RuntimeImpl::registry_endpointdir() const { return registry_endpointdir_; } string RuntimeImpl::registry_endpoint() const { return registry_endpoint_; } Reaper::SPtr RuntimeImpl::reply_reaper() const { // We lazily create a reaper the first time we are asked for it, which happens when the first query is created. lock_guard lock(mutex_); if (!reply_reaper_) { reply_reaper_ = Reaper::create(10, 45); // TODO: configurable timeouts } return reply_reaper_; } void RuntimeImpl::run_scope(ScopeBase *const scope_base, std::string const& scope_ini_file) { auto mw = factory()->create(scope_id_, "Zmq", "Zmq.ini"); { // dirname modifies its argument, so we need a copy of scope lib path std::vector scope_ini(scope_ini_file.c_str(), scope_ini_file.c_str() + scope_ini_file.size() + 1); const std::string scope_dir(dirname(&scope_ini[0])); scope_base->p->set_scope_directory(scope_dir); } scope_base->start(scope_id_, registry()); // Ensure the scope gets stopped. unique_ptr cleanup_scope(scope_base, [](ScopeBase *scope_base) { scope_base->stop(); }); // Give a thread to the scope to do with as it likes. If the scope // doesn't want to use it and immediately returns from run(), // that's fine. auto run_future = std::async(launch::async, [scope_base] { scope_base->run(); }); // Create a servant for the scope and register the servant. auto scope = unique_ptr(new internal::ScopeObject(this, scope_base)); auto proxy = mw->add_scope_object(scope_id_, move(scope)); mw->wait_for_shutdown(); run_future.get(); } ObjectProxy RuntimeImpl::string_to_proxy(string const& s) const { auto mw = middleware_factory_->find(s); assert(mw); return mw->string_to_proxy(s); } string RuntimeImpl::proxy_to_string(ObjectProxy const& proxy) const { if (proxy == nullptr) { return "nullproxy:"; } return proxy->to_string(); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/DepartmentImpl.cpp0000644000015301777760000001227312320776161026670 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include namespace unity { namespace scopes { namespace internal { DepartmentImpl::DepartmentImpl(CannedQuery const& query, std::string const& label) : query_(query), label_(label) { } DepartmentImpl::DepartmentImpl(std::string const& department_id, CannedQuery const& query, std::string const& label) : query_(query), label_(label) { query_.set_department_id(department_id); } DepartmentImpl::DepartmentImpl(std::string const& department_id, CannedQuery const& query, std::string const& label, DepartmentList const& subdepartments) : query_(query), label_(label), departments_(subdepartments) { query_.set_department_id(department_id); } void DepartmentImpl::set_subdepartments(DepartmentList const& departments) { departments_ = departments; } std::string DepartmentImpl::id() const { return query_.department_id(); } std::string DepartmentImpl::label() const { return label_; } CannedQuery DepartmentImpl::query() const { return query_; } DepartmentList DepartmentImpl::subdepartments() const { return departments_; } VariantMap DepartmentImpl::serialize() const { VariantMap vm; vm["label"] = label_; vm["query"] = query_.serialize(); // sub-departments are optional if (!departments_.empty()) { VariantArray subdeparr; for (auto const& dep: departments_) { subdeparr.push_back(Variant(dep.serialize())); } vm["departments"] = Variant(subdeparr); } return vm; } Department DepartmentImpl::create(VariantMap const& var) { auto it = var.find("label"); if (it == var.end()) { throw unity::InvalidArgumentException("DepartmentImpl::create(): missing 'label'"); } auto label = it->second.get_string(); it = var.find("query"); if (it == var.end()) { throw unity::InvalidArgumentException("DepartmentImpl::create(): missing 'query'"); } auto query = CannedQueryImpl::create(it->second.get_dict()); Department department(query, label); it = var.find("departments"); if (it != var.end()) { DepartmentList subdeps; for (auto const& dep: it->second.get_array()) { subdeps.push_back(create(dep.get_dict())); } department.set_subdepartments(subdeps); } return department; } void DepartmentImpl::validate_departments(DepartmentList const& departments, std::unordered_set& lookup) { for (auto const& dep: departments) { if (lookup.find(dep.id()) != lookup.end()) { std::stringstream str; str << "DepartmentImpl::validate_departments(): Duplicate department: '" << dep.id() << "'"; throw unity::LogicException(str.str()); } lookup.insert(dep.id()); validate_departments(dep.subdepartments(), lookup); } } void DepartmentImpl::validate_departments(DepartmentList const& departments, std::string const ¤t_department_id) { if (departments.empty()) { throw unity::LogicException("DepartmentImpl::validate_departments(): empty departments list"); } // don't allow duplicated department ids. ensure at current_department_id matches one of the departments (if non-empty). std::unordered_set lookup; validate_departments(departments, lookup); if (!current_department_id.empty()) { if (lookup.find(current_department_id) == lookup.end()) { std::stringstream str; str << "DepartmentImpl::validate_departments(): current department '" << current_department_id << "' doesn't match any of the departments"; throw unity::LogicException(str.str()); } } } VariantMap DepartmentImpl::serialize_departments(DepartmentList const& departments, std::string const& current_department_id) { VariantMap vm; VariantArray arr; for (auto const& dep: departments) { arr.push_back(Variant(dep.serialize())); } vm["departments"] = arr; vm["current_department"] = current_department_id; return vm; } DepartmentList DepartmentImpl::deserialize_departments(VariantArray const& var) { DepartmentList departments; for (auto const& dep: var) { departments.push_back(DepartmentImpl::create(dep.get_dict())); } return departments; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ResultReplyObject.cpp0000644000015301777760000001027012320776161027357 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace unity::scopes::internal; namespace unity { namespace scopes { namespace internal { ResultReplyObject::ResultReplyObject(SearchListenerBase::SPtr const& receiver, RuntimeImpl const* runtime, std::string const& scope_id, int cardinality) : ReplyObject(std::static_pointer_cast(receiver), runtime, scope_id), receiver_(receiver), cat_registry_(new CategoryRegistry()), runtime_(runtime), cardinality_(cardinality), num_pushes_(0) { assert(receiver_); assert(runtime); } ResultReplyObject::~ResultReplyObject() { } bool ResultReplyObject::process_data(VariantMap const& data) { auto it = data.find("filters"); if (it != data.end()) { Filters const filters = FilterBaseImpl::deserialize_filters(it->second.get_array()); it = data.find("filter_state"); if (it != data.end()) { auto filter_state = FilterStateImpl::deserialize(it->second.get_dict()); receiver_->push(filters, filter_state); } else { throw InvalidArgumentException("ResultReplyObject::push(): filters present but missing filter_state data"); } } it = data.find("category"); if (it != data.end()) { auto cat = cat_registry_->register_category(it->second.get_dict()); receiver_->push(cat); } it = data.find("departments"); if (it != data.end()) { DepartmentList const departments = DepartmentImpl::deserialize_departments(it->second.get_array()); it = data.find("current_department"); if (it != data.end()) { receiver_->push(departments, it->second.get_string()); } else { throw InvalidArgumentException("ReplyObject::process_data(): departments present but missing current_department"); } } it = data.find("annotation"); if (it != data.end()) { auto result_var = it->second.get_dict(); Annotation annotation(new internal::AnnotationImpl(result_var)); receiver_->push(std::move(annotation)); } it = data.find("result"); if (it != data.end()) { // Enforce cardinality limit. if (cardinality_ != 0 && ++num_pushes_ > cardinality_) { return true; } auto result_var = it->second.get_dict(); auto impl = std::unique_ptr(new internal::CategorisedResultImpl(*cat_registry_, result_var)); impl->set_runtime(runtime_); // set result origin if (impl->origin().empty()) { impl->set_origin(origin_proxy()); } CategorisedResult result(impl.release()); receiver_->push(std::move(result)); } return false; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/SearchMetadataImpl.cpp0000644000015301777760000000667712320776161027446 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include namespace unity { namespace scopes { namespace internal { SearchMetadataImpl::SearchMetadataImpl(std::string const& locale, std::string const& form_factor) : QueryMetadataImpl(locale, form_factor), cardinality_(0) { } SearchMetadataImpl::SearchMetadataImpl(int cardinality, std::string const& locale, std::string const& form_factor) : QueryMetadataImpl(locale, form_factor), cardinality_(cardinality) { check_cardinality("SearchMetadataImpl()", cardinality); } SearchMetadataImpl::SearchMetadataImpl(VariantMap const& var) : QueryMetadataImpl(var) { auto it = find_or_throw("SearchMetadataImpl()", var, "cardinality"); cardinality_ = it->second.get_int(); check_cardinality("SearchMetadataImpl(VariantMap)", cardinality_); it = find_or_throw("SearchMetadataImpl()", var, "hints"); hints_ = it->second.get_dict(); } void SearchMetadataImpl::set_cardinality(int cardinality) { check_cardinality("SearchMetadataImpl::set_cardinality()", cardinality); cardinality_ = cardinality; } int SearchMetadataImpl::cardinality() const { return cardinality_; } Variant& SearchMetadataImpl::hint(std::string const& key) { return hints_[key]; } Variant const& SearchMetadataImpl::hint(std::string const& key) const { auto const& it = hints_.find(key); if (it != hints_.end()) { return it->second; } std::ostringstream s; s << "SearchMetadataImpl::hint(): requested key " << key << " doesn't exist"; throw unity::LogicException(s.str()); } void SearchMetadataImpl::set_hint(std::string const& key, Variant const& value) { hints_[key] = value; } VariantMap SearchMetadataImpl::hints() const { return hints_; } bool SearchMetadataImpl::contains_hint(std::string const& key) const { return hints_.find(key) != hints_.end(); } std::string SearchMetadataImpl::metadata_type() const { static const std::string t("search_metadata"); return t; } void SearchMetadataImpl::serialize(VariantMap &var) const { QueryMetadataImpl::serialize(var); var["cardinality"] = Variant(cardinality_); var["hints"] = hints_; } VariantMap SearchMetadataImpl::serialize() const { VariantMap vm; serialize(vm); return vm; } void SearchMetadataImpl::check_cardinality(std::string const& func_name, int cardinality) { if (cardinality < 0) { throw InvalidArgumentException(func_name + ": " + std::to_string(cardinality)); } } SearchMetadata SearchMetadataImpl::create(VariantMap const& var) { return SearchMetadata(new SearchMetadataImpl(var)); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/Utils.cpp0000644000015301777760000000242012320776161025034 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include namespace unity { namespace scopes { namespace internal { VariantMap::const_iterator find_or_throw(std::string const& context, VariantMap const& var, std::string const& key) { auto it = var.find(key); if (it == var.end()) { std::stringstream str; str << context << ": missing '" << key << "' element"; throw unity::InvalidArgumentException(str.str()); } return it; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/RegistryConfig.cpp0000644000015301777760000000571012320776161026677 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { constexpr char const* RegistryConfig::REGISTRY_CONFIG_GROUP; RegistryConfig::RegistryConfig(string const& identity, string const& configfile) : ConfigBase(configfile) { identity_ = identity; if (identity.empty()) { throw InvalidArgumentException("Registry identity cannot be an empty string"); } mw_kind_ = get_middleware(REGISTRY_CONFIG_GROUP, "Middleware"); endpointdir_ = get_string(REGISTRY_CONFIG_GROUP, mw_kind_ + ".EndpointDir"); endpoint_ = get_string(REGISTRY_CONFIG_GROUP, mw_kind_ + ".Endpoint"); mw_configfile_ = get_string(REGISTRY_CONFIG_GROUP, mw_kind_ + ".ConfigFile"); scope_installdir_ = get_string(REGISTRY_CONFIG_GROUP, "Scope.InstallDir"); oem_installdir_ = get_optional_string(REGISTRY_CONFIG_GROUP, "OEM.InstallDir"); scoperunner_path_ = get_string(REGISTRY_CONFIG_GROUP, "Scoperunner.Path"); if (scoperunner_path_[0] != '/') { throw ConfigException(configfile + ": Scoperunner.Path must be an absolute path"); } ss_registry_identity_ = get_optional_string(REGISTRY_CONFIG_GROUP, "SS.Registry.Identity"); ss_registry_endpoint_ = get_optional_string(REGISTRY_CONFIG_GROUP, "SS.Registry.Endpoint"); } RegistryConfig::~RegistryConfig() { } string RegistryConfig::identity() const { return identity_; } string RegistryConfig::mw_kind() const { return mw_kind_; } string RegistryConfig::endpointdir() const { return endpointdir_; } string RegistryConfig::endpoint() const { return endpoint_; } string RegistryConfig::mw_configfile() const { return mw_configfile_; } string RegistryConfig::scope_installdir() const { return scope_installdir_; } string RegistryConfig::oem_installdir() const { return oem_installdir_; } string RegistryConfig::scoperunner_path() const { return scoperunner_path_; } string RegistryConfig::ss_registry_identity() const { return ss_registry_identity_; } string RegistryConfig::ss_registry_endpoint() const { return ss_registry_endpoint_; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/StateReceiverObject.cpp0000644000015301777760000000236612320776161027641 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include namespace unity { namespace scopes { namespace internal { StateReceiverObject::StateReceiverObject() { } StateReceiverObject::~StateReceiverObject() { } void StateReceiverObject::push_state(std::string const& sender_id, State const& state) { state_received_(sender_id, state); } core::Signal const& StateReceiverObject::state_received() const { return state_received_; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ActivationQueryObject.cpp0000644000015301777760000000504612320776161030221 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include #include #include using namespace std; using namespace unity::scopes::internal; namespace unity { namespace scopes { namespace internal { ActivationQueryObject::ActivationQueryObject(std::shared_ptr const& act_base, MWReplyProxy const& reply, MWQueryCtrlProxy const& ctrl) : QueryObject(act_base, reply, ctrl), act_base_(act_base) { } ActivationQueryObject::~ActivationQueryObject() { // parent destructor will call ctrl_->destroy() } void ActivationQueryObject::run(MWReplyProxy const& reply, InvokeInfo const& /* info */) noexcept { assert(self_); // The reply proxy now holds our reference count high, so // we can drop our own smart pointer and disconnect from the middleware. self_ = nullptr; disconnect(); try { // no need for intermediate proxy (like with ReplyImpl::create), // since we get single return value from the public API // and just push it ourseleves auto res = act_base_->activate(); reply->push(res.serialize()); reply_->finished(ListenerBase::Finished, ""); } catch (std::exception const& e) { // TODO: log error reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block cerr << "ActivationQueryObject::run(): " << e.what() << endl; } catch (...) { // TODO: log error reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block cerr << "ActivationQueryObject::run(): unknown exception" << endl; } } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/AbstractObject.cpp0000644000015301777760000000352212320776161026632 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace std; namespace unity { namespace scopes { namespace internal { AbstractObject::AbstractObject() { } AbstractObject::~AbstractObject() { } void AbstractObject::set_disconnect_function(function func) noexcept { assert(func); lock_guard lock(mutex_); disconnect_func_ = func; } void AbstractObject::disconnect() noexcept { try { // Lock needed because disconnect() may be called // from another thread, such as the reaper. function disconnect_func; { lock_guard lock(mutex_); assert(disconnect_func_); disconnect_func = disconnect_func_; } disconnect_func(); } catch (...) { // Only happens if no servant with the corresponding identity is registered. // If we have concurrent calls into a servant, each of which tries to disconnect // the servant, only the first one succeeds; second and subsequent calls will be ignored. } } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/PreviewQueryObject.cpp0000644000015301777760000000543312320776161027541 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michal Hruby */ #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace unity::scopes::internal; namespace unity { namespace scopes { namespace internal { PreviewQueryObject::PreviewQueryObject(std::shared_ptr const& preview_base, MWReplyProxy const& reply, MWQueryCtrlProxy const& ctrl) : QueryObject(preview_base, reply, ctrl), preview_base_(preview_base) { assert(preview_base); } PreviewQueryObject::~PreviewQueryObject() { // parent destructor will call ctrl_->destroy() } void PreviewQueryObject::run(MWReplyProxy const& reply, InvokeInfo const& /* info */) noexcept { assert(self_); auto reply_proxy = make_shared(reply, self_); assert(reply_proxy); reply_proxy_ = reply_proxy; // The reply proxy now holds our reference count high, so // we can drop our own smart pointer and disconnect from the middleware. self_ = nullptr; disconnect(); // Synchronous call into scope implementation. // On return, replies for the query may still be outstanding. try { auto preview_query = dynamic_pointer_cast(query_base_); assert(preview_query); preview_query->run(reply_proxy); } catch (std::exception const& e) { pushable_ = false; // TODO: log error reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block cerr << "PreviewQueryObject::run(): " << e.what() << endl; } catch (...) { // TODO: log error reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block cerr << "PreviewQueryObject::run(): unknown exception" << endl; } } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ResultImpl.cpp0000644000015301777760000003060312320776161026040 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include namespace unity { namespace scopes { namespace internal { ResultImpl::ResultImpl() : flags_(Flags::ActivationNotHandled), runtime_(nullptr) { } ResultImpl::ResultImpl(VariantMap const& variant_map) : flags_(Flags::ActivationNotHandled), runtime_(nullptr) { deserialize(variant_map); } ResultImpl::ResultImpl(ResultImpl const& other) : attrs_(other.attrs_), origin_(other.origin_), flags_(other.flags_), runtime_(other.runtime_) { if (other.stored_result_) { stored_result_ = std::make_shared(*other.stored_result_); } } ResultImpl& ResultImpl::operator=(ResultImpl const& other) { if (this != &other) { attrs_ = other.attrs_; flags_ = other.flags_; origin_ = other.origin_; runtime_ = other.runtime_; if (other.stored_result_) { stored_result_ = std::make_shared(*other.stored_result_); } } return *this; } void ResultImpl::store(Result const& other, bool intercept_activation) { if (this == other.p.get()) { throw InvalidArgumentException("Result:: cannot store self"); } if (intercept_activation) { set_intercept_activation(); } stored_result_.reset(new VariantMap(other.serialize())); } bool ResultImpl::has_stored_result() const { return stored_result_ != nullptr; } Result ResultImpl::retrieve() const { if (stored_result_ == nullptr) { throw InvalidArgumentException("Result: no result has been stored"); } return Result(*stored_result_); } void ResultImpl::set_runtime(RuntimeImpl const* runtime) { assert(runtime); runtime_ = runtime; } void ResultImpl::set_origin(std::string const& scope_id) { origin_ = scope_id; } void ResultImpl::set_uri(std::string const& uri) { attrs_["uri"] = uri; } void ResultImpl::set_title(std::string const& title) { attrs_["title"] = title; } void ResultImpl::set_art(std::string const& art) { attrs_["art"] = art; } void ResultImpl::set_dnd_uri(std::string const& dnd_uri) { attrs_["dnd_uri"] = dnd_uri; } void ResultImpl::set_intercept_activation() { flags_ |= Flags::InterceptActivation; // clear the origin scope ID, ReplyObject with set it anew with correct scope ID (i.e. this scope); // this is needed to support the case where aggregator scope just passes the original result // upstream - in that case we want the original scope to receive activation. origin_.clear(); } bool ResultImpl::find_stored_result(std::function const& cmp_func, std::function const& found_func, std::function const& not_found_func) const { if (stored_result_ == nullptr) return false; // visit stored results recursively, // check if any of them intercepts activation; // if not, it is direct activation in the shell bool found = false; VariantMap stored = *stored_result_; while (!found) { auto it = stored.find("internal"); if (it == stored.end()) { throw LogicException("ResultImpl::find_stored_result(): Invalid structure of stored result, missing 'internal"); } const VariantMap internal_var = it->second.get_dict(); auto intit = internal_var.find("flags"); const Flags flags = (intit != internal_var.end() ? static_cast(intit->second.get_int()) : Flags::ActivationNotHandled); if (cmp_func(flags)) { found_func(stored); found = true; } else { not_found_func(stored); // nested stored result? intit = internal_var.find("result"); if (intit == internal_var.end()) break; // reached the most inner result and it doesn't match, so break the loop stored = intit->second.get_dict(); } } return found; } bool ResultImpl::direct_activation() const { if (flags_ & Flags::InterceptActivation) { return false; } // visit stored results recursively, // check if any of them intercepts activation; // if not, it is direct activation in the shell return !find_stored_result( [](Flags f) -> bool { return (f & Flags::InterceptActivation) != 0; }, [](VariantMap const&) {}, // do nothing if matches [](VariantMap const&) {}); // do nothing if doesn't match } ScopeProxy ResultImpl::target_scope_proxy() const { std::string target; if ((flags_ & Flags::InterceptActivation) || stored_result_ == nullptr) { target = origin_; } else { const auto get_origin = [](VariantMap const& var) -> std::string { auto it = var.find("internal"); if (it != var.end()) { auto intvar = it->second.get_dict(); it = intvar.find("origin"); if (it != intvar.end()) { return it->second.get_string(); } throw unity::LogicException("Result::target_scope_proxy(): 'origin' element missing"); } throw unity::LogicException("Result::target_scope_proxy(): 'internal' element missing"); }; // visit stored results recursively, // check if any of them intercepts activation; // if not, return the most inner origin find_stored_result( [](Flags f) -> bool { return (f & Flags::InterceptActivation) != 0; }, // condition [&target, &get_origin](VariantMap const& var) { // if found // target becomes the actual return value from target_scope_proxy(), since find_stored_result stops at this point. target = get_origin(var); }, [&target, &get_origin](VariantMap const& var) { // if not found // set target from current inner result, find_stored_result continues searching so it may get overwritten target = get_origin(var); }); } // runtime can be null if this instance wasn't passed through middleware, in which case activation scope cannot be determined yet if (target.empty() || runtime_ == nullptr) { throw LogicException("Result::target_scope_proxy(): undefined target scope"); } return std::dynamic_pointer_cast(runtime_->string_to_proxy(target)); } VariantMap ResultImpl::activation_target() const { if ((flags_ & Flags::InterceptActivation) || stored_result_ == nullptr) { return serialize(); } VariantMap res; VariantMap most_inner; // visit stored results recursively, // check if any of them intercepts activation, if so, return it.; // if not, return the most inner result. if (find_stored_result( [](Flags f) -> bool { return (f & Flags::InterceptActivation) != 0; }, // condition [&res](VariantMap const& var) { // if found res = var; }, [&most_inner](VariantMap const& var) { // if not found most_inner = var; }) ) { return res; } return most_inner; } int ResultImpl::flags() const { return flags_; } Variant& ResultImpl::operator[](std::string const& key) { return attrs_[key]; } Variant const& ResultImpl::operator[](std::string const& key) const { return value(key); } std::string ResultImpl::uri() const noexcept { auto const it = attrs_.find("uri"); if (it != attrs_.end() && it->second.which() == Variant::Type::String) { return it->second.get_string(); } return ""; } std::string ResultImpl::title() const noexcept { auto const it = attrs_.find("title"); if (it != attrs_.end() && it->second.which() == Variant::Type::String) { return it->second.get_string(); } return ""; } std::string ResultImpl::art() const noexcept { auto const it = attrs_.find("art"); if (it != attrs_.end() && it->second.which() == Variant::Type::String) { return it->second.get_string(); } return ""; } std::string ResultImpl::dnd_uri() const noexcept { auto const it = attrs_.find("dnd_uri"); if (it != attrs_.end() && it->second.which() == Variant::Type::String) { return it->second.get_string(); } return ""; } std::string ResultImpl::origin() const noexcept { return origin_; } bool ResultImpl::contains(std::string const& key) const { return attrs_.find(key) != attrs_.end(); } Variant const& ResultImpl::value(std::string const& key) const { auto const& it = attrs_.find(key); if (it != attrs_.end()) { return it->second; } std::ostringstream s; s << "Result::value(): requested key " << key << " doesn't exist"; throw InvalidArgumentException(s.str()); } void ResultImpl::throw_on_non_string(std::string const& name, Variant::Type vtype) const { if (vtype != Variant::Type::String) { throw InvalidArgumentException("ResultItem: wrong type of attribute: " + name); } } void ResultImpl::throw_on_empty(std::string const& name) const { auto const it = attrs_.find(name); if (it == attrs_.end()) { throw InvalidArgumentException("ResultItem: missing required attribute: " + name); } throw_on_non_string(name, it->second.which()); } void ResultImpl::serialize_internal(VariantMap& var) const { if (flags_ != 0) { var["flags"] = flags_; } if (!origin_.empty()) { var["origin"] = origin_; } if (stored_result_) { var["result"] = *stored_result_; } } VariantMap ResultImpl::serialize() const { throw_on_empty("uri"); auto it = attrs_.find("dnd_uri"); if (it != attrs_.end()) { throw_on_non_string("dnd_uri", it->second.which()); } VariantMap outer; outer["attrs"] = Variant(attrs_); VariantMap intvar; serialize_internal(intvar); outer["internal"] = std::move(intvar); return outer; } void ResultImpl::deserialize(VariantMap const& var) { // check for ["internal"]["result"] dict which holds stored result. auto it = var.find("internal"); if (it == var.end()) { throw InvalidArgumentException("Missing 'internal' element'"); } else { auto const& resvar = it->second.get_dict(); it = resvar.find("flags"); if (it != resvar.end()) { flags_ = it->second.get_int(); } it = resvar.find("origin"); if (it != resvar.end()) { origin_ = it->second.get_string(); } it = resvar.find("result"); if (it != resvar.end()) { stored_result_.reset(new VariantMap(it->second.get_dict())); } } // check for ["attrs"] dict which holds all attributes it = var.find("attrs"); if (it == var.end()) { throw InvalidArgumentException("Invalid variant structure"); } const VariantMap attrs = it->second.get_dict(); it = attrs.find("uri"); if (it == attrs.end()) throw InvalidArgumentException("Missing 'uri'"); for (auto const& kv: attrs) { this->operator[](kv.first) = kv.second; } } Result ResultImpl::create_result(VariantMap const& variant_map) { return Result(variant_map); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/MWQuery.cpp0000644000015301777760000000176112320776161025314 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include using namespace std; namespace unity { namespace scopes { namespace internal { MWQuery::MWQuery(MiddlewareBase* mw_base) : MWObjectProxy(mw_base) { } MWQuery::~MWQuery() { } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/MWScope.cpp0000644000015301777760000000176112320776161025260 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include using namespace std; namespace unity { namespace scopes { namespace internal { MWScope::MWScope(MiddlewareBase* mw_base) : MWObjectProxy(mw_base) { } MWScope::~MWScope() { } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/JsonCppNode.cpp0000644000015301777760000001704612320776161026130 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; JsonCppNode::JsonCppNode(std::string const& json_string) { if (!json_string.empty()) { read_json(json_string); } } JsonCppNode::JsonCppNode(const Json::Value& root) : root_(root) { } JsonCppNode::JsonCppNode(const Variant& var) { root_ = from_variant(var); } JsonCppNode::~JsonCppNode() { } Json::Value JsonCppNode::from_variant(Variant const& var) { switch (var.which()) { case Variant::Type::Int: return Json::Value(var.get_int()); case Variant::Type::Bool: return Json::Value(var.get_bool()); case Variant::Type::String: return Json::Value(var.get_string()); case Variant::Type::Double: return Json::Value(var.get_double()); case Variant::Type::Dict: { Json::Value val(Json::ValueType::objectValue); for (auto const& v: var.get_dict()) { val[v.first] = from_variant(v.second); } return val; } case Variant::Type::Array: { Json::Value val(Json::ValueType::arrayValue); for (auto const& v: var.get_array()) { val.append(from_variant(v)); } return val; } case Variant::Type::Null: return Json::Value(Json::ValueType::nullValue); default: { std::ostringstream s; s << "json_to_variant(): unsupported json type "; s << static_cast(var.which()); throw unity::LogicException(s.str()); } } } Variant JsonCppNode::to_variant(Json::Value const& value) { switch (value.type()) { case Json::ValueType::nullValue: return Variant::null(); case Json::ValueType::arrayValue: { VariantArray arr; for (unsigned int i=0; i(value.type()); throw unity::LogicException(s.str()); } } } Variant JsonCppNode::to_variant() const { return to_variant(root_); } void JsonCppNode::clear() { root_.clear(); } void JsonCppNode::read_json(std::string const& json_string) { Json::Reader reader; clear(); if (!reader.parse(json_string, root_)) { throw unity::ResourceException("Failed to parse json string: " + reader.getFormattedErrorMessages()); } } std::string JsonCppNode::to_json_string() const { Json::FastWriter writer; return writer.write(root_); } int JsonCppNode::size() const { return root_.size(); } std::vector JsonCppNode::member_names() const { if (root_.type() != Json::objectValue) { throw unity::LogicException("Root node is not an object"); } return root_.getMemberNames(); } JsonNodeInterface::NodeType JsonCppNode::type() const { switch (root_.type()) { case Json::nullValue: return Null; case Json::arrayValue: return Array; case Json::objectValue: return Object; case Json::stringValue: return String; case Json::intValue: return Int; case Json::uintValue: return UInt; case Json::realValue: return Real; case Json::booleanValue: return Bool; } return Null; } std::string JsonCppNode::as_string() const { if (!root_.isConvertibleTo(Json::stringValue)) { throw unity::LogicException("Node does not contain a string value"); } return root_.asString(); } int JsonCppNode::as_int() const { if (!root_.isConvertibleTo(Json::intValue)) { throw unity::LogicException("Node does not contain an int value"); } return root_.asInt(); } uint JsonCppNode::as_uint() const { if (!root_.isConvertibleTo(Json::uintValue)) { throw unity::LogicException("Node does not contain a uint value"); } return root_.asUInt(); } double JsonCppNode::as_double() const { if (!root_.isConvertibleTo(Json::realValue)) { throw unity::LogicException("Node does not contain a double value"); } return root_.asDouble(); } bool JsonCppNode::as_bool() const { if (!root_.isConvertibleTo(Json::booleanValue)) { throw unity::LogicException("Node does not contain a bool value"); } return root_.asBool(); } bool JsonCppNode::has_node(std::string const& node_name) const { return root_.isMember(node_name); } JsonNodeInterface::SPtr JsonCppNode::get_node() const { if (!root_) { throw unity::LogicException("Current node is empty"); } return std::make_shared(root_); } JsonNodeInterface::SPtr JsonCppNode::get_node(std::string const& node_name) const { if (!root_.isMember(node_name)) { throw unity::LogicException("Node " + node_name + " does not exist"); } const Json::Value& value_node = root_[node_name]; return std::make_shared(value_node); } JsonNodeInterface::SPtr JsonCppNode::get_node(uint node_index) const { if (root_.type() != Json::arrayValue) { throw unity::LogicException("Root node is not an array"); } else if (node_index >= root_.size()) { throw unity::LogicException("Invalid array index"); } const Json::Value& value_node = root_[node_index]; if (!value_node) { throw unity::LogicException("Node " + std::to_string(node_index) + " does not exist"); } return std::make_shared (value_node); } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ScopeLoader.cpp0000644000015301777760000001252012320776161026136 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include using namespace std; using namespace unity::scopes; using namespace unity::scopes::internal; namespace unity { namespace scopes { namespace internal { ScopeLoader::ScopeLoader(string const& scope_id, string const& libpath, RegistryProxy const& registry) : scope_id_(scope_id), dyn_loader_(DynamicLoader::create(libpath, DynamicLoader::Binding::now, DynamicLoader::Unload::noclose)), registry_(registry), scope_base_(nullptr, reinterpret_cast(dyn_loader_->find_function(UNITY_SCOPE_DESTROY_SYMSTR))), scope_state_(ScopeState::Stopped) { // Look for the scope create function in the plug-in and call it. // instance. If anything goes wrong below, scope_base_ takes care of destroying it again. CreateFunction create_func = reinterpret_cast( dyn_loader_->find_function(UNITY_SCOPE_CREATE_SYMSTR) ); scope_base_.reset(create_func()); if (!scope_base_) { throw unity::ResourceException("Scope " + scope_id_ + " returned nullptr from " + UNITY_SCOPE_CREATE_SYMSTR); } { // dirname modifies its argument, so we need a copy of scope lib path std::vector scope_lib(libpath.c_str(), libpath.c_str() + libpath.size() + 1); const std::string scope_dir(dirname(&scope_lib[0])); scope_base_->p->set_scope_directory(scope_dir); } } ScopeLoader::~ScopeLoader() { try { unload(); } catch (...) // LCOV_EXCL_LINE { } } ScopeLoader::UPtr ScopeLoader::load(string const& scope_id, string const& libpath, RegistryProxy const& registry) { return UPtr(new ScopeLoader(scope_id, libpath, registry)); } void ScopeLoader::unload() { if (scope_state_ == ScopeState::Failed) { scope_state_ = ScopeState::Finished; } if (scope_state_ == ScopeState::Finished) { return; } stop(); scope_base_.reset(nullptr); scope_state_ = ScopeState::Finished; } // Call the scope's start method. void ScopeLoader::start() { if (scope_state_ == ScopeState::Started) { return; } if (scope_state_ == ScopeState::Finished) { throw unity::LogicException("Cannot start scope " + scope_id_ + " in Finished state"); } if (scope_state_ == ScopeState::Failed) { throw unity::LogicException("Cannot start scope " + scope_id_ + " in Failed state"); } try { const int s_version = scope_base_->start(scope_id_, registry_); const int maj_version = major_version(); if (s_version != maj_version) { try { scope_base_->stop(); // Make sure to tell the scope to stop again before reporting version mismatch. } catch (...) { } throw unity::ResourceException("Scope " + scope_id_ + " was compiled with major version " + std::to_string(s_version) + " of the Unity scopes run time. This " + "version is incompatible with the current major " + "version (" + std::to_string(maj_version) + ")."); } } catch (...) { scope_state_ = ScopeState::Failed; throw unity::ResourceException("Scope " + scope_id_ +": terminated due to exception in start()"); } scope_state_ = ScopeState::Started; } // Call the scope's stop method. void ScopeLoader::stop() { if (scope_state_ == ScopeState::Stopped) { return; } if (scope_state_ == ScopeState::Finished) { throw unity::LogicException("Cannot stop scope " + scope_id_ + " in Finished state"); } if (scope_state_ == ScopeState::Failed) { throw unity::LogicException("Cannot stop scope " + scope_id_ + " in Failed state"); } try { scope_base_->stop(); scope_state_ = ScopeState::Stopped; } catch (...) { scope_state_ = ScopeState::Failed; throw unity::ResourceException("Scope " + scope_id_ +": terminated due to exception in stop()"); } } string ScopeLoader::scope_id() const noexcept { return scope_id_; } string ScopeLoader::libpath() const noexcept { return dyn_loader_->path(); } ScopeBase* ScopeLoader::scope_base() const { assert(scope_base_); return scope_base_.get(); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/MWQueryCtrl.cpp0000644000015301777760000000200512320776161026131 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include using namespace std; namespace unity { namespace scopes { namespace internal { MWQueryCtrl::MWQueryCtrl(MiddlewareBase* mw_base) : MWObjectProxy(mw_base) { } MWQueryCtrl::~MWQueryCtrl() { } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/QueryBaseImpl.cpp0000644000015301777760000000763012320776161026466 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { QueryBaseImpl::QueryBaseImpl() { } QueryBaseImpl::~QueryBaseImpl() { } QueryCtrlProxy QueryBaseImpl::subsearch(ScopeProxy const& scope, string const& query_string, SearchListenerBase::SPtr const& reply) { assert(search_metadata_); // Forward the create request to the child scope and remember the control. // This allows cancel() to forward incoming cancellations to subqueries // without intervention from the scope application code. QueryCtrlProxy qcp = scope->search(query_string, *search_metadata_, reply); subqueries_.push_back(qcp); return qcp; } QueryCtrlProxy QueryBaseImpl::subsearch(ScopeProxy const& scope, std::string const& query_string, FilterState const& filter_state, SearchListenerBase::SPtr const& reply) { assert(search_metadata_); QueryCtrlProxy qcp = scope->search(query_string, filter_state, *search_metadata_, reply); subqueries_.push_back(qcp); return qcp; } QueryCtrlProxy QueryBaseImpl::subsearch(ScopeProxy const& scope, std::string const& query_string, std::string const& department_id, FilterState const& filter_state, SearchListenerBase::SPtr const& reply) { assert(search_metadata_); QueryCtrlProxy qcp = scope->search(query_string, department_id, filter_state, *search_metadata_, reply); subqueries_.push_back(qcp); return qcp; } QueryCtrlProxy QueryBaseImpl::subsearch(ScopeProxy const& scope, std::string const& query_string, std::string const& department_id, FilterState const& filter_state, SearchMetadata const& metadata, SearchListenerBase::SPtr const& reply) { QueryCtrlProxy qcp = scope->search(query_string, department_id, filter_state, metadata, reply); subqueries_.push_back(qcp); return qcp; } void QueryBaseImpl::set_metadata(SearchMetadata const& metadata) { search_metadata_.reset(new SearchMetadata(metadata)); } void QueryBaseImpl::cancel() { for (auto& ctrl : subqueries_) { ctrl->cancel(); // Forward the cancellation to any subqueries that might be active } // We release the memory for the subquery controls here. That's just a micro-optimization // because this QueryBase will be destroyed shortly anyway, once the cancelled() method // of the application returns. (Not deallocating here would work too.) vector().swap(subqueries_); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/RegistryObject.cpp0000644000015301777760000003473312320776161026707 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { ///! TODO: get from config static const int c_process_wait_timeout = 2000; RegistryObject::RegistryObject(core::posix::ChildProcess::DeathObserver& death_observer) : death_observer_(death_observer), death_observer_connection_ { death_observer_.child_died().connect([this](const core::posix::ChildProcess& cp) { on_process_death(cp); }) }, state_receiver_(new StateReceiverObject()), state_receiver_connection_ { state_receiver_->state_received().connect([this](std::string const& id, StateReceiverObject::State const& s) { on_state_received(id, s); }) } { } RegistryObject::~RegistryObject() { // kill all scope processes for (auto& scope_process : scope_processes_) { try { // at this point the registry middleware is shutting down, hence we will not receive // "ScopeStopping" states from dying scopes. We manually set it here as to avoid // outputting bogus error messages. if (is_scope_running(scope_process.first)) { scope_process.second.update_state(ScopeProcess::Stopping); scope_process.second.kill(); } } catch(std::exception const& e) { cerr << "RegistryObject::~RegistryObject(): " << e.what() << endl; } } // clear scope maps scopes_.clear(); scope_processes_.clear(); } ScopeMetadata RegistryObject::get_metadata(std::string const& scope_id) const { lock_guard lock(mutex_); // If the id is empty, it was sent as empty by the remote client. if (scope_id.empty()) { throw unity::InvalidArgumentException("RegistryObject::get_metadata(): Cannot search for scope with empty id"); } // Look for the scope in both the local and the remote map. // Local scopes take precedence over remote ones of the same // id. (Ideally, this should never happen.) auto const& scope_it = scopes_.find(scope_id); if (scope_it != scopes_.end()) { return scope_it->second; } if (remote_registry_) { return remote_registry_->get_metadata(scope_id); } throw NotFoundException("RegistryObject::get_metadata(): no such scope: ", scope_id); } MetadataMap RegistryObject::list() const { lock_guard lock(mutex_); MetadataMap all_scopes(scopes_); // Local scopes // If a remote scope has the same id as a local one, // this will not overwrite a local scope with a remote // one if they have the same id. if (remote_registry_) { MetadataMap remote_scopes = remote_registry_->list(); all_scopes.insert(remote_scopes.begin(), remote_scopes.end()); } return all_scopes; } ObjectProxy RegistryObject::locate(std::string const& identity) { decltype(scopes_.cbegin()) scope_it; decltype(scope_processes_.begin()) proc_it; { lock_guard lock(mutex_); // If the id is empty, it was sent as empty by the remote client. if (identity.empty()) { throw unity::InvalidArgumentException("RegistryObject::locate(): Cannot locate scope with empty id"); } scope_it = scopes_.find(identity); if (scope_it == scopes_.end()) { throw NotFoundException("RegistryObject::locate(): Tried to locate unknown local scope", identity); } proc_it = scope_processes_.find(identity); if (proc_it == scope_processes_.end()) { throw NotFoundException("RegistryObject::locate(): Tried to exec unknown local scope", identity); } } proc_it->second.exec(death_observer_); return scope_it->second.proxy(); } bool RegistryObject::add_local_scope(std::string const& scope_id, ScopeMetadata const& metadata, ScopeExecData const& exec_data) { lock_guard lock(mutex_); bool return_value = true; if (scope_id.empty()) { throw unity::InvalidArgumentException("RegistryObject::add_local_scope(): Cannot add scope with empty id"); } if (scope_id.find('/') != std::string::npos) { throw unity::InvalidArgumentException("RegistryObject::add_local_scope(): Cannot create a scope with '/' in its id"); } if (scopes_.find(scope_id) != scopes_.end()) { scopes_.erase(scope_id); scope_processes_.erase(scope_id); return_value = false; } scopes_.insert(make_pair(scope_id, metadata)); scope_processes_.insert(make_pair(scope_id, ScopeProcess(exec_data))); return return_value; } bool RegistryObject::remove_local_scope(std::string const& scope_id) { lock_guard lock(mutex_); // If the id is empty, it was sent as empty by the remote client. if (scope_id.empty()) { throw unity::InvalidArgumentException("RegistryObject::remove_local_scope(): Cannot remove scope " "with empty id"); } scope_processes_.erase(scope_id); return scopes_.erase(scope_id) == 1; } void RegistryObject::set_remote_registry(MWRegistryProxy const& remote_registry) { lock_guard lock(mutex_); remote_registry_ = remote_registry; } bool RegistryObject::is_scope_running(std::string const& scope_id) { auto it = scope_processes_.find(scope_id); if (it != scope_processes_.end()) { return it->second.state() != ScopeProcess::ProcessState::Stopped; } throw NotFoundException("RegistryObject::is_scope_process_running(): no such scope: ", scope_id); } StateReceiverObject::SPtr RegistryObject::state_receiver() { return state_receiver_; } void RegistryObject::on_process_death(core::posix::Process const& process) { // the death observer has signaled that a child has died. // broadcast this message to each scope process until we have found the process in question. // (this is slightly more efficient than just connecting the signal to every scope process) pid_t pid = process.pid(); for (auto& scope_process : scope_processes_) { if (scope_process.second.on_process_death(pid)) break; } } void RegistryObject::on_state_received(std::string const& scope_id, StateReceiverObject::State const& state) { auto it = scope_processes_.find(scope_id); if (it != scope_processes_.end()) { switch (state) { case StateReceiverObject::ScopeReady: it->second.update_state(ScopeProcess::ProcessState::Running); break; case StateReceiverObject::ScopeStopping: it->second.update_state(ScopeProcess::ProcessState::Stopping); break; default: std::cerr << "RegistryObject::on_state_received(): unknown state received from scope: " << scope_id; } } // simply ignore states from scopes the registry does not know about } RegistryObject::ScopeProcess::ScopeProcess(ScopeExecData exec_data) : exec_data_(exec_data) { } RegistryObject::ScopeProcess::ScopeProcess(ScopeProcess const& other) : exec_data_(other.exec_data_) { } RegistryObject::ScopeProcess::~ScopeProcess() { try { kill(); } catch(std::exception const& e) { cerr << "RegistryObject::ScopeProcess::~ScopeProcess(): " << e.what() << endl; } } RegistryObject::ScopeProcess::ProcessState RegistryObject::ScopeProcess::state() const { std::lock_guard lock(process_mutex_); return state_; } void RegistryObject::ScopeProcess::update_state(ProcessState state) { std::lock_guard lock(process_mutex_); update_state_unlocked(state); } bool RegistryObject::ScopeProcess::wait_for_state(ProcessState state, int timeout_ms) const { std::unique_lock lock(process_mutex_); return wait_for_state(lock, state, timeout_ms); } void RegistryObject::ScopeProcess::exec(core::posix::ChildProcess::DeathObserver& death_observer) { std::unique_lock lock(process_mutex_); // 1. check if the scope is running. // 1.1. if scope already running, return. if (state_ == ScopeProcess::Running) { return; } // 1.2. if scope running but is “stopping”, wait for it to stop / kill it. else if (state_ == ScopeProcess::Stopping) { if (!wait_for_state(lock, ScopeProcess::Stopped, c_process_wait_timeout)) { cerr << "RegistryObject::ScopeProcess::exec(): Force killing process. Scope: \"" << exec_data_.scope_id << "\" took too long to stop." << endl; try { kill(lock); } catch(std::exception const& e) { cerr << "RegistryObject::ScopeProcess::exec(): " << e.what() << endl; } } } // 2. exec the scope. update_state_unlocked(Starting); const std::string program{exec_data_.scoperunner_path}; const std::vector argv = {exec_data_.runtime_config, exec_data_.scope_config}; std::map env; core::posix::this_process::env::for_each([&env](const std::string& key, const std::string& value) { env.insert(std::make_pair(key, value)); }); { process_ = core::posix::exec(program, argv, env, core::posix::StandardStream::stdin | core::posix::StandardStream::stdout); if (process_.pid() <= 0) { clear_handle_unlocked(); throw unity::ResourceException("RegistryObject::ScopeProcess::exec(): Failed to exec scope via command: \"" + exec_data_.scoperunner_path + " " + exec_data_.runtime_config + " " + exec_data_.scope_config + "\""); } } // 3. wait for scope to be "running". // 3.1. when ready, return. // 3.2. OR if timeout, kill process and throw. if (!wait_for_state(lock, ScopeProcess::Running, c_process_wait_timeout)) { try { kill(lock); } catch(std::exception const& e) { cerr << "RegistryObject::ScopeProcess::exec(): " << e.what() << endl; } throw unity::ResourceException("RegistryObject::ScopeProcess::exec(): exec aborted. Scope: \"" + exec_data_.scope_id + "\" took too long to start."); } cout << "RegistryObject::ScopeProcess::exec(): Process for scope: \"" << exec_data_.scope_id << "\" started" << endl; // 4. add the scope process to the death observer death_observer.add(process_); } void RegistryObject::ScopeProcess::kill() { std::unique_lock lock(process_mutex_); kill(lock); } bool RegistryObject::ScopeProcess::on_process_death(pid_t pid) { std::lock_guard lock(process_mutex_); // check if this is the process reported to have died if (pid == process_.pid()) { cout << "RegistryObject::ScopeProcess::on_process_death(): Process for scope: \"" << exec_data_.scope_id << "\" terminated" << endl; clear_handle_unlocked(); return true; } return false; } void RegistryObject::ScopeProcess::clear_handle_unlocked() { process_ = core::posix::ChildProcess::invalid(); update_state_unlocked(Stopped); } void RegistryObject::ScopeProcess::update_state_unlocked(ProcessState state) { if (state == state_) { return; } else if (state == Stopped && state_ != Stopping ) { cerr << "RegistryObject::ScopeProcess: Scope: \"" << exec_data_.scope_id << "\" closed unexpectedly. Either the process crashed or was killed forcefully." << endl; } state_ = state; state_change_cond_.notify_all(); } bool RegistryObject::ScopeProcess::wait_for_state(std::unique_lock& lock, ProcessState state, int timeout_ms) const { return state_change_cond_.wait_for(lock, std::chrono::milliseconds(timeout_ms), [this, &state]{return state_ == state;}); } void RegistryObject::ScopeProcess::kill(std::unique_lock& lock) { if (state_ == Stopped) { return; } try { // first try to close the scope process gracefully process_.send_signal_or_throw(core::posix::Signal::sig_term); if (!wait_for_state(lock, ScopeProcess::Stopped, c_process_wait_timeout)) { std::error_code ec; cerr << "RegistryObject::ScopeProcess::kill(): Scope: \"" << exec_data_.scope_id << "\" is taking longer than expected to terminate gracefully. " << "Killing the process instead." << endl; // scope is taking too long to close, send kill signal process_.send_signal(core::posix::Signal::sig_kill, ec); } // clear the process handle clear_handle_unlocked(); } catch (std::exception const&) { cerr << "RegistryObject::ScopeProcess::kill(): Failed to kill scope: \"" << exec_data_.scope_id << "\"" << endl; // clear the process handle // even on error, the previous handle will be unrecoverable at this point clear_handle_unlocked(); throw; } } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/lttng/0000755000015301777760000000000012320776463024367 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/lttng/UnityScopes_tp.c0000644000015301777760000000151512320776161027520 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #define TRACEPOINT_CREATE_PROBES #include #include unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/lttng/UnityScopes_tp.cpp0000644000015301777760000000151312320776161030056 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #define TRACEPOINT_DEFINE #define TRACEPOINT_PROBE_DYNAMIC_LINKAGE #include unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/lttng/CMakeLists.txt0000644000015301777760000000040312320776161027117 0ustar pbusernogroup00000000000000set( SRC ${CMAKE_CURRENT_SOURCE_DIR}/UnityScopes_tp.cpp ) set(UNITY_SCOPES_LIB_SRC ${UNITY_SCOPES_LIB_SRC} ${SRC} PARENT_SCOPE) add_library( lttngtracer SHARED UnityScopes_tp.c ) target_link_libraries( lttngtracer lttng-ust urcu-bp dl ) unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/LinkImpl.cpp0000644000015301777760000000355312320776161025463 0ustar pbusernogroup00000000000000/* Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include namespace unity { namespace scopes { namespace internal { LinkImpl::LinkImpl(std::string const& label, CannedQuery const& query) : label_(label), query_(std::make_shared(query)) { } LinkImpl::LinkImpl(VariantMap const& variant_map) { auto it = variant_map.find("label"); if (it == variant_map.end()) { throw InvalidArgumentException("Invalid variant, 'label' is missing"); } label_ = it->second.get_string(); it = variant_map.find("query"); if (it == variant_map.end()) { throw InvalidArgumentException("Invalid variant, 'query' is missing"); } query_.reset(new CannedQuery(internal::CannedQueryImpl::create(it->second.get_dict()))); } std::string LinkImpl::label() const { return label_; } CannedQuery LinkImpl::query() const { return *query_; } VariantMap LinkImpl::serialize() const { VariantMap vm; vm["label"] = label_; vm["query"] = query_->serialize(); return vm; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ObjectImpl.cpp0000644000015301777760000000277212320776161025776 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace std; namespace unity { namespace scopes { namespace internal { ObjectImpl::ObjectImpl(MWProxy const& mw_proxy) : mw_proxy_(mw_proxy) { } ObjectImpl::~ObjectImpl() { } string ObjectImpl::identity() { return mw_proxy_->identity(); } string ObjectImpl::category() { return mw_proxy_->category(); } string ObjectImpl::endpoint() { return mw_proxy_->endpoint(); } int64_t ObjectImpl::timeout() { return mw_proxy_->timeout(); } string ObjectImpl::to_string() { return mw_proxy_->to_string(); } void ObjectImpl::ping() { mw_proxy_->ping(); } MWProxy ObjectImpl::proxy() const { return mw_proxy_; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/MiddlewareFactory.cpp0000644000015301777760000000702512320776161027347 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include using namespace std; using namespace unity::scopes; namespace unity { namespace scopes { namespace internal { MiddlewareFactory::MiddlewareFactory(RuntimeImpl* runtime) : runtime_(runtime) { assert(runtime); } MiddlewareFactory::~MiddlewareFactory() { } MiddlewareBase::SPtr MiddlewareFactory::create(string const& server_name, string const& kind, string const& configfile) const { lock_guard lock(mutex_); MiddlewareBase::SPtr mw = find_unlocked(server_name, kind); if (mw) { return mw; } switch (to_kind(kind)) { case Kind_Zmq: { mw = make_shared(server_name, configfile, runtime_); break; } case Kind_REST: { // TODO abort(); break; } default: { assert(false); // LCOV_EXCL_LINE } } MiddlewareData d = { server_name, kind }; mw_map_[d] = mw; return mw; } MiddlewareBase::SPtr MiddlewareFactory::find(string const& server_name, string const& kind) const { lock_guard lock(mutex_); return find_unlocked(server_name, kind); } MiddlewareBase::SPtr MiddlewareFactory::find(string const& proxy_string) const { static const string zmq_scheme = "ipc:"; static const string rest_scheme = "rest:"; string kind; if (proxy_string.substr(0, zmq_scheme.size()) == zmq_scheme) { kind = "Zmq"; } else if (proxy_string.substr(0, rest_scheme.size()) == rest_scheme) { kind = "REST"; } else { throw MiddlewareException("Unknown scheme name for proxy: " + proxy_string); } lock_guard lock(mutex_); for (auto const& pair : mw_map_) { if (pair.first.kind == kind) { return pair.second; } } throw MiddlewareException("Cannot find middleware for proxy: " + proxy_string); } MiddlewareBase::SPtr MiddlewareFactory::find_unlocked(string const& server_name, string const& kind) const { MiddlewareData d = { server_name, kind }; auto it = mw_map_.find(d); return it != mw_map_.end() ? it->second : nullptr; } MiddlewareFactory::Kind MiddlewareFactory::to_kind(string const& kind) { Kind k; if (kind == "Zmq") { k = Kind_Zmq; } else if (kind == "REST") { k = Kind_REST; } else { throw ConfigException("Invalid middleware kind: " + kind); } return k; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/RegistryException.cpp0000644000015301777760000000253212320776161027427 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include using namespace std; namespace unity { namespace scopes { namespace internal { RegistryException::RegistryException(string const& reason) : Exception("unity::scopes::RegistryException", reason) { } RegistryException::RegistryException(RegistryException const&) = default; //! @cond RegistryException& RegistryException::operator=(RegistryException const&) = default; RegistryException::~RegistryException() = default; //! @endcond exception_ptr RegistryException::self() const { return make_exception_ptr(*this); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ScopeMetadataImpl.cpp0000644000015301777760000002326012320776161027275 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the Lesser GNU General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include using namespace std; using namespace unity; namespace unity { namespace scopes { namespace internal { ScopeMetadataImpl::ScopeMetadataImpl(MiddlewareBase* mw) : mw_(mw) { } ScopeMetadataImpl::ScopeMetadataImpl(const VariantMap& variant_map, MiddlewareBase* mw) : mw_(mw) { deserialize(variant_map); } ScopeMetadataImpl::ScopeMetadataImpl(ScopeMetadataImpl const& other) : mw_(other.mw_), scope_id_(other.scope_id_), proxy_(other.proxy_), display_name_(other.display_name_), description_(other.description_), author_(other.author_), appearance_attributes_(other.appearance_attributes_) { if (other.art_) { art_.reset(new string(*other.art_)); } if (other.icon_) { icon_.reset(new string(*other.icon_)); } if (other.search_hint_) { search_hint_.reset(new string(*other.search_hint_)); } if (other.hot_key_) { hot_key_.reset(new string(*other.hot_key_)); } if (other.invisible_) { invisible_.reset(new bool(*other.invisible_)); } if (other.scope_directory_) { scope_directory_.reset(new string(*other.scope_directory_)); } } ScopeMetadataImpl& ScopeMetadataImpl::operator=(ScopeMetadataImpl const& rhs) { if (this != &rhs) { mw_ = rhs.mw_; scope_id_ = rhs.scope_id_; proxy_ = rhs.proxy_; display_name_ = rhs.display_name_; description_ = rhs.description_; author_ = rhs.author_; art_.reset(rhs.art_ ? new string(*rhs.art_) : nullptr); icon_.reset(rhs.icon_ ? new string(*rhs.icon_) : nullptr); search_hint_.reset(rhs.search_hint_ ? new string(*rhs.search_hint_) : nullptr); hot_key_.reset(rhs.hot_key_ ? new string(*rhs.hot_key_) : nullptr); invisible_.reset(rhs.invisible_ ? new bool(*rhs.invisible_) : nullptr); appearance_attributes_ = rhs.appearance_attributes_; scope_directory_.reset(rhs.scope_directory_ ? new string(*rhs.scope_directory_) : nullptr); } return *this; } std::string ScopeMetadataImpl::scope_id() const { return scope_id_; } ScopeProxy ScopeMetadataImpl::proxy() const { return proxy_; } std::string ScopeMetadataImpl::display_name() const { return display_name_; } std::string ScopeMetadataImpl::description() const { return description_; } std::string ScopeMetadataImpl::author() const { return author_; } std::string ScopeMetadataImpl::art() const { if (art_) { return *art_; } throw NotFoundException("attribute not set", "art"); } std::string ScopeMetadataImpl::icon() const { if (icon_) { return *icon_; } throw NotFoundException("attribute not set", "icon"); } std::string ScopeMetadataImpl::search_hint() const { if (search_hint_) { return *search_hint_; } throw NotFoundException("attribute not set", "search_hint"); } std::string ScopeMetadataImpl::hot_key() const { if (hot_key_) { return *hot_key_; } throw NotFoundException("attribute not set", "hot_key"); } bool ScopeMetadataImpl::invisible() const { if (invisible_) { return *invisible_; } return false; } VariantMap ScopeMetadataImpl::appearance_attributes() const { return appearance_attributes_; } std::string ScopeMetadataImpl::scope_directory() const { if (scope_directory_) { return *scope_directory_; } throw NotFoundException("attribute not set", "scope_directory"); } void ScopeMetadataImpl::set_scope_id(std::string const& scope_id) { scope_id_ = scope_id; } void ScopeMetadataImpl::set_proxy(ScopeProxy const& proxy) { proxy_ = proxy; } void ScopeMetadataImpl::set_display_name(std::string const& display_name) { display_name_ = display_name; } void ScopeMetadataImpl::set_description(std::string const& description) { description_ = description; } void ScopeMetadataImpl::set_author(std::string const& author) { author_ = author; } void ScopeMetadataImpl::set_art(std::string const& art) { art_.reset(new string(art)); } void ScopeMetadataImpl::set_icon(std::string const& icon) { icon_.reset(new string(icon)); } void ScopeMetadataImpl::set_search_hint(std::string const& search_hint) { search_hint_.reset(new string(search_hint)); } void ScopeMetadataImpl::set_hot_key(std::string const& hot_key) { hot_key_.reset(new string(hot_key)); } void ScopeMetadataImpl::set_invisible(bool invisible) { invisible_.reset(new bool(invisible)); } void ScopeMetadataImpl::set_appearance_attributes(VariantMap const& appearance_attributes) { appearance_attributes_ = appearance_attributes; } void ScopeMetadataImpl::set_scope_directory(std::string const& path) { scope_directory_.reset(new string(path)); } namespace { void throw_on_empty(std::string const& name, std::string const& value) { if (value.empty()) { throw InvalidArgumentException("ScopeMetadata: required attribute '" + name + "' is empty"); } } } // namespace VariantMap ScopeMetadataImpl::serialize() const { throw_on_empty("scope_id", scope_id_); if (!proxy_) { throw InvalidArgumentException("ScopeMetadataImpl::serialize(): required attribute 'proxy' is null"); } throw_on_empty("display_name", display_name_); throw_on_empty("description", description_); throw_on_empty("author", author_); VariantMap var; var["scope_id"] = scope_id_; VariantMap proxy; proxy["identity"] = proxy_->identity(); proxy["endpoint"] = proxy_->endpoint(); var["proxy"] = proxy; var["display_name"] = display_name_; var["description"] = description_; var["author"] = author_; // Optional fields if (art_) { var["art"] = *art_; } if (icon_) { var["icon"] = *icon_; } if (search_hint_) { var["search_hint"] = *search_hint_; } if (hot_key_) { var["hot_key"] = *hot_key_; } if (invisible_) { var["invisible"] = *invisible_; } if (scope_directory_) { var["scope_dir"] = *scope_directory_; } if (appearance_attributes_.size() > 0) { var["appearance_attributes"] = appearance_attributes_; } return var; } namespace { VariantMap::const_iterator find_or_throw(VariantMap const& var, std::string const& name) { auto it = var.find(name); if (it == var.end()) { throw InvalidArgumentException("ScopeMetadata::deserialize(): required attribute '" + name + "' is missing"); } return it; } } // namespace void ScopeMetadataImpl::deserialize(VariantMap const& var) { auto it = find_or_throw(var, "scope_id"); scope_id_ = it->second.get_string(); throw_on_empty("scope_id", scope_id_); it = find_or_throw(var, "proxy"); auto proxy = it->second.get_dict(); auto it2 = proxy.find("identity"); if (it2 == proxy.end()) { throw InvalidArgumentException("ScopeMetadataImpl::deserialize(): missing 'proxy.identity'"); } auto identity = it2->second.get_string(); throw_on_empty("proxy.identity", identity); it2 = proxy.find("endpoint"); if (it2 == proxy.end()) { throw InvalidArgumentException("ScopeMetadataImpl::deserialize(): missing 'proxy.endpoint'"); } auto endpoint = it2->second.get_string(); throw_on_empty("proxy.endpoint", endpoint); auto mw_proxy = mw_->create_scope_proxy(identity, endpoint); proxy_ = ScopeImpl::create(mw_proxy, mw_->runtime(), scope_id_); it = find_or_throw(var, "display_name"); display_name_ = it->second.get_string(); it = find_or_throw(var, "description"); description_ = it->second.get_string(); it = find_or_throw(var, "author"); author_ = it->second.get_string(); // Optional fields it = var.find("art"); if (it != var.end()) { art_.reset(new string(it->second.get_string())); } it = var.find("icon"); if (it != var.end()) { icon_.reset(new string(it->second.get_string())); } it = var.find("search_hint"); if (it != var.end()) { search_hint_.reset(new string(it->second.get_string())); } it = var.find("hot_key"); if (it != var.end()) { hot_key_.reset(new string(it->second.get_string())); } it = var.find("scope_dir"); if (it != var.end()) { scope_directory_.reset(new string(it->second.get_string())); } it = var.find("invisible"); if (it != var.end()) { invisible_.reset(new bool(it->second.get_bool())); } it = var.find("appearance_attributes"); if (it != var.end()) { appearance_attributes_ = it->second.get_dict(); } } ScopeMetadata ScopeMetadataImpl::create(unique_ptr impl) { return ScopeMetadata(move(impl)); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/CategorisedResultImpl.cpp0000644000015301777760000000521412320776161030212 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include namespace unity { namespace scopes { namespace internal { CategorisedResultImpl::CategorisedResultImpl(CategorisedResultImpl const& other) : ResultImpl(other) { set_category(other.category_); } CategorisedResultImpl::CategorisedResultImpl(Category::SCPtr category) : ResultImpl() { set_category(category); } CategorisedResultImpl::CategorisedResultImpl(Category::SCPtr category, const VariantMap& variant_map) : ResultImpl(variant_map) { set_category(category); } CategorisedResultImpl::CategorisedResultImpl(internal::CategoryRegistry const& reg, const VariantMap &variant_map) : ResultImpl(variant_map) { auto it = variant_map.find("internal"); if (it == variant_map.end()) { throw InvalidArgumentException("Invalid variant, missing 'internal'"); } auto cat_id = it->second.get_dict()["cat_id"].get_string(); category_ = reg.lookup_category(cat_id); if (category_ == nullptr) { std::ostringstream s; s << "Category '" << cat_id << "' not found in the registry"; throw InvalidArgumentException(s.str()); } } Category::SCPtr CategorisedResultImpl::category() const { return category_; } void CategorisedResultImpl::set_category(Category::SCPtr category) { if (category == nullptr) { throw InvalidArgumentException("CategorisedResult::set_category(): Category must not be null"); } category_ = category; } void CategorisedResultImpl::serialize_internal(VariantMap& var) const { ResultImpl::serialize_internal(var); var["cat_id"] = category_->id(); } CategorisedResult CategorisedResultImpl::create_result(CategorisedResultImpl* impl) { return CategorisedResult(impl); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/QueryObject.cpp0000644000015301777760000001400312320776161026170 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace unity::scopes::internal; namespace unity { namespace scopes { namespace internal { QueryObject::QueryObject(std::shared_ptr const& query_base, MWReplyProxy const& reply, MWQueryCtrlProxy const& ctrl) : QueryObject(query_base, 0, reply, ctrl) { } QueryObject::QueryObject(std::shared_ptr const& query_base, int cardinality, MWReplyProxy const& reply, MWQueryCtrlProxy const& ctrl) : query_base_(query_base), reply_(reply), ctrl_(ctrl), pushable_(true), cardinality_(cardinality) { } QueryObject::~QueryObject() { assert(ctrl_); try { ctrl_->destroy(); // Oneway, won't block } catch (...) { // TODO: log error } } void QueryObject::run(MWReplyProxy const& reply, InvokeInfo const& /* info */) noexcept { // It is possible for a run() to be dispatched by the middleware *after* the query // was cancelled. This can happen because run() and cancel() are dispatched by different // thread pools. If the scope implementation uses a synchronous run(), a later run() // invocation will sit in the middleware queueing layer until an earlier run() // completes, by which time the query for the later run() call may have been // cancelled already. // If the query was cancelled by the client before we even receive the // run invocation, we never forward the run() to the implementation. if (!pushable_) { return; } // Create the reply proxy to pass to query_base_ and keep a weak_ptr, which we will need // if cancel() is called later. assert(self_); auto reply_proxy = make_shared(reply, self_); assert(reply_proxy); reply_proxy_ = reply_proxy; // The reply proxy now holds our reference count high, so // we can drop our own smart pointer and disconnect from the middleware. self_ = nullptr; disconnect(); // Synchronous call into scope implementation. // On return, replies for the query may still be outstanding. try { auto search_query = dynamic_pointer_cast(query_base_); assert(search_query); search_query->run(reply_proxy); } catch (std::exception const& e) { pushable_ = false; // TODO: log error reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block cerr << "ScopeBase::run(): " << e.what() << endl; } catch (...) { pushable_ = false; // TODO: log error reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block cerr << "ScopeBase::run(): unknown exception" << endl; } } void QueryObject::cancel(InvokeInfo const& /* info */) { pushable_ = false; auto rp = reply_proxy_.lock(); if (rp) { // Send finished() to up-stream client to tell him the query is done. // We send via the MWReplyProxy here because that allows passing // a ListenerBase::Reason (whereas the public ReplyProxy does not). reply_->finished(ListenerBase::Cancelled, ""); // Oneway, can't block } // Forward the cancellation to the query base (which in turn will forward it to any subqueries). // The query base also calls the cancelled() callback to inform the application code. query_base_->cancel(); } bool QueryObject::pushable(InvokeInfo const& /* info */) const noexcept { return pushable_; } int QueryObject::cardinality(InvokeInfo const& /* info */) const noexcept { return cardinality_; } // The point of keeping a shared_ptr to ourselves is to make sure this QueryObject cannot // go out of scope in between being created by the Scope, and the first ReplyProxy for this // query being created in QueryObject::run(). If the scope's run() method returns immediately, // by the time QueryObject::run() starts executing, Scope::create_query() may already have // returned and removed the query object from the middleware, causing this QueryObject's reference // count to reach zero and get deallocated. So, create_query() calls set_self(), which remembers // the the shared_ptr, increasing the refcount, and QueryObject::run() clears the shared_ptr after creating // the ReplyProxy, which decrements the refcount again. // // The net-effect is that this QueryObject stays alive exactly for as long as there is at least // one ReplyProxy for it in existence, or the scope's run() method is still executing (or both). // Whatever happens last (run() returning or the last ReplyProxy going out of scope) deallocates // this instance. void QueryObject::set_self(QueryObjectBase::SPtr const& self) noexcept { assert(self); assert(!self_); self_ = self; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/PreviewWidgetImpl.cpp0000644000015301777760000001357212320776161027355 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include namespace unity { namespace scopes { namespace internal { //! @cond PreviewWidgetImpl::PreviewWidgetImpl(std::string const& json_text) { //TODO: json validation const internal::JsonCppNode node(json_text); auto var = node.to_variant().get_dict(); // // the JSON representation of preview widget keeps all the attributes at the top level of the dict, // and has "components" sub-dictionary; split it into components and attributes and extract id & type. auto it = var.find("components"); if (it != var.end()) // components are optional { // convert VariantMap to map for (auto const& kv: it->second.get_dict()) { add_attribute_mapping(kv.first, kv.second.get_string()); } } // iterate over top-level attributes, skip 'components' key for (auto const& kv: var) { if (kv.first != "components") { if (kv.first == "id") { set_id(kv.second.get_string()); } else if (kv.first == "type") { set_widget_type(kv.second.get_string()); } else { add_attribute_value(kv.first, kv.second); } } } } PreviewWidgetImpl::PreviewWidgetImpl(std::string const& id, std::string const &widget_type) : id_(id), type_(widget_type) { throw_on_empty("id", id_); throw_on_empty("widget_type", type_); } PreviewWidgetImpl::PreviewWidgetImpl(VariantMap const& var) { auto it = var.find("id"); if (it == var.end()) { throw unity::InvalidArgumentException("PreviewWidgetImpl(): missing 'id'"); } set_id(it->second.get_string()); it = var.find("type"); if (it == var.end()) { throw unity::InvalidArgumentException("PreviewWidgetImpl(): missing 'type'"); } set_widget_type(it->second.get_string()); it = var.find("attributes"); if (it == var.end()) { throw unity::InvalidArgumentException("PreviewWidgetImpl(): missing 'attributes'"); } for (auto const& kv: it->second.get_dict()) { add_attribute_value(kv.first, kv.second); } it = var.find("components"); if (it == var.end()) { throw unity::InvalidArgumentException("PreviewWidgetImpl(): missing 'components'"); } for (auto const& kv: it->second.get_dict()) { add_attribute_mapping(kv.first, kv.second.get_string()); } } PreviewWidget PreviewWidgetImpl::create(VariantMap const& var) { return PreviewWidget(new PreviewWidgetImpl(var)); } void PreviewWidgetImpl::set_id(std::string const& id) { throw_on_empty("id", id); id_ = id; } void PreviewWidgetImpl::set_widget_type(std::string const& widget_type) { throw_on_empty("widget_type", widget_type); type_ = widget_type; } void PreviewWidgetImpl::add_attribute_value(std::string const& key, Variant const& value) { if (key == "id" || key == "type" || key == "components") { throw InvalidArgumentException("PreviewWidget::add_attribute_value(): Can't override '" + key + "'"); } attributes_[key] = value; } void PreviewWidgetImpl::add_attribute_mapping(std::string const& key, std::string const& field_name) { if (key == "id" || key == "type") { throw InvalidArgumentException("PreviewWidget::add_attribute_mapping(): Can't override component '" + key + "'"); } components_[key] = field_name; } std::string PreviewWidgetImpl::id() const { return id_; } std::string PreviewWidgetImpl::widget_type() const { return type_; } std::map PreviewWidgetImpl::attribute_mappings() const { return components_; } VariantMap PreviewWidgetImpl::attribute_values() const { return attributes_; } std::string PreviewWidgetImpl::data() const { // convert from map to VariantMap VariantMap cm; for (auto const& kv: components_) { cm[kv.first] = Variant(kv.second); } VariantMap var; var["id"] = id_; var["type"] = type_; var["components"] = Variant(cm); for (auto const& kv: attributes_) { var[kv.first] = kv.second; } const Variant outer(var); const internal::JsonCppNode node(outer); return node.to_json_string(); } void PreviewWidgetImpl::throw_on_empty(std::string const& name, std::string const& value) { if (value.empty()) { throw InvalidArgumentException("PreviewWidget: required attribute " + name + " is empty"); } } VariantMap PreviewWidgetImpl::serialize() const { // convert from map to VariantMap VariantMap cm; for (auto const& kv: components_) { cm[kv.first] = Variant(kv.second); } // note: the internal on-wire serialization doesn't exactly match the json definition VariantMap vm; vm["id"] = id_; vm["type"] = type_; vm["attributes"] = attributes_; vm["components"] = Variant(cm); return vm; } //! @endcond } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ActivationReplyObject.cpp0000644000015301777760000000273512320776161030211 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include namespace unity { namespace scopes { namespace internal { ActivationReplyObject::ActivationReplyObject(ActivationListenerBase::SPtr const& receiver, RuntimeImpl const* runtime, std::string const& scope_id) : ReplyObject(std::static_pointer_cast(receiver), runtime, scope_id), receiver_(receiver) { assert(receiver_); } bool ActivationReplyObject::process_data(VariantMap const& data) { ActivationResponse resp = ActivationResponseImpl::create(data); receiver_->activated(resp); return false; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/OptionSelectorFilterImpl.cpp0000644000015301777760000001474312320776161030710 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { OptionSelectorFilterImpl::OptionSelectorFilterImpl(std::string const& id, std::string const& label, bool multi_select) : FilterBaseImpl(id), label_(label), multi_select_(multi_select) { } OptionSelectorFilterImpl::OptionSelectorFilterImpl(VariantMap const& var) : FilterBaseImpl(var) { deserialize(var); } std::string OptionSelectorFilterImpl::label() const { return label_; } bool OptionSelectorFilterImpl::multi_select() const { return multi_select_; } void OptionSelectorFilterImpl::serialize(VariantMap& var) const { VariantArray ops = VariantArray(); for (auto const& opt: options_) { VariantMap vm; vm["id"] = opt->id(); vm["label"] = opt->label(); ops.push_back(Variant(vm)); } var["label"] = label_; var["options"] = ops; var["multi_select"] = multi_select_; } void OptionSelectorFilterImpl::throw_on_missing(VariantMap::const_iterator const& it, VariantMap::const_iterator const& endit, std::string const& name) { if (it == endit) { throw LogicException("OptionSelectorFilter: missing " + name); } } void OptionSelectorFilterImpl::deserialize(VariantMap const& var) { auto it = var.find("label"); throw_on_missing(it, var.end(), "label"); label_ = it->second.get_string(); it = var.find("multi_select"); throw_on_missing(it, var.end(), "multi_select"); multi_select_ = it->second.get_bool(); it = var.find("options"); throw_on_missing(it, var.end(), "options"); auto const opts = it->second.get_array(); for (auto const& opt: opts) { auto const optvar = opt.get_dict(); it = optvar.find("id"); throw_on_missing(it, optvar.end(), "option id"); auto opt_id = it->second.get_string(); it = optvar.find("label"); throw_on_missing(it, optvar.end(), "option label"); add_option(opt_id, it->second.get_string()); } } std::string OptionSelectorFilterImpl::filter_type() const { return "option_selector"; } FilterOption::SCPtr OptionSelectorFilterImpl::add_option(std::string const& id, std::string const& label) { auto opt = std::shared_ptr(new FilterOption(id, label)); options_.push_back(opt); return opt; } std::list OptionSelectorFilterImpl::options() const { return options_; } std::set OptionSelectorFilterImpl::active_options(FilterState const& filter_state) const { std::set opts; if (filter_state.has_filter(id())) { try { auto var = FilterBaseImpl::get(filter_state, id()).get_array(); // this can throw if of different type std::unordered_set opts_ids; // create set for faster lookup for (auto const& idvar: var) { opts_ids.insert(idvar.get_string()); } // insert selected options into opts for (auto const& opt: options_) { if (opts_ids.find(opt->id()) != opts_ids.end()) { opts.insert(opt); } } } catch (...) { // ignore all errors here - we could be getting an incorrect value for this filter // via a canned query from another scope, we shouldn't break this scope on it. } } return opts; } void OptionSelectorFilterImpl::update_state(FilterState& filter_state, FilterOption::SCPtr option, bool active) const { auto const oid(option->id()); auto it = std::find_if(options_.begin(), options_.end(), [oid](FilterOption::SCPtr const& opt) { return opt->id() == oid; }); if (it == options_.end()) { throw unity::InvalidArgumentException("OptionSelector::update_state(): unknown filter option: " + oid); } VariantMap& state = FilterBaseImpl::get(filter_state); // if this is single-selection filter, erase current state (only ensure only one option is active) if (active && !multi_select_) { auto it = state.find(id()); if (it != state.end()) { state.erase(it); } } update_state(filter_state, id(), option->id(), active); } void OptionSelectorFilterImpl::update_state(FilterState& filter_state, std::string const& filter_id, std::string const& option_id, bool value) { VariantMap& state = FilterBaseImpl::get(filter_state); auto it = state.find(filter_id); // do we have this filter already? if (it == state.end()) { if (value) { state[filter_id] = VariantArray({Variant(option_id)}); } else { state[filter_id] = VariantArray(); // no option active } } else // modify existing entry for this filter { VariantArray var = (it->second).get_array(); // may throw if this filter was used for different filter type // do we have this option already? auto opt_it = std::find_if(var.begin(), var.end(), [option_id](Variant const& v1) { return v1.get_string() == option_id; }); if (opt_it == var.end()) { if (value) { var.push_back(Variant(option_id)); } // else - option not selected, nothing to do } else // option already stored in the state { if (!value) // remove if it's now unselected { var.erase(opt_it); } } state[filter_id] = std::move(var); } } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/Reaper.cpp0000644000015301777760000002242412320776161025160 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include using namespace std; using namespace unity::scopes::internal::reaper_private; namespace unity { namespace scopes { namespace internal { mutex ReapItem::mutex_; ReapItem::ReapItem(weak_ptr const& reaper, reaper_private::Reaplist::iterator it) : reaper_(reaper), it_(it), destroyed_(false) { } ReapItem::~ReapItem() { // If we go out of scope, we remove ourselves from the reaper list. This // ensures that no more callbacks will be sent. destroy(); } void ReapItem::refresh() noexcept { if (destroyed_.load()) { return; // Calling refresh() after destroy() has no effect. } // If the reaper is still around, remove the entry from the list // and put it back on the front, updating the time stamp. weak_ptr wp_reaper; { lock_guard lock(mutex_); wp_reaper = reaper_; } auto const reaper = wp_reaper.lock(); if (reaper) { lock_guard reaper_lock(reaper->mutex_); assert(it_ != reaper->list_.end()); reaper_private::Item item(*it_); item.timestamp = chrono::steady_clock::now(); reaper->list_.erase(it_); reaper->list_.push_front(item); it_ = reaper->list_.begin(); } else { // The reaper has gone away, so we disable ourself. destroyed_.store(true); } } void ReapItem::destroy() noexcept { if (destroyed_.exchange(true)) // Only the first call to destroy has any effect. { return; } weak_ptr wp_reaper; { lock_guard lock(mutex_); wp_reaper = reaper_; } auto const reaper = wp_reaper.lock(); if (reaper) { lock_guard reaper_lock(reaper->mutex_); assert(it_ != reaper->list_.end()); reaper->list_.erase(it_); } #ifndef NDEBUG it_ = reaper->list_.end(); #endif } Reaper::Reaper(int reap_interval, int expiry_interval, DestroyPolicy p) : reap_interval_(chrono::seconds(reap_interval)), expiry_interval_(chrono::seconds(expiry_interval)), policy_(p), finish_(false) { if (reap_interval < 1) { ostringstream s; s << "Reaper: invalid reap_interval (" << reap_interval << "). Interval must be > 0."; throw unity::InvalidArgumentException(s.str()); } if (reap_interval > expiry_interval) { ostringstream s; s << "Reaper: reap_interval (" << reap_interval << ") must be <= expiry_interval (" << expiry_interval << ")."; throw unity::LogicException(s.str()); } } Reaper::~Reaper() { destroy(); } // Instantiate a new reaper. We call set_self() after instantiation so the reaper // can keep a weak_ptr to itself. That weak_ptr in turn is passed to each ReapItem, // so the ReapItem can manipulate the reap list. If the reaper goes out of scope // before a ReapItem, the ReapItem will notice this and deactivate itself. Reaper::SPtr Reaper::create(int reap_interval, int expiry_interval, DestroyPolicy p) { SPtr reaper(new Reaper(reap_interval, expiry_interval, p)); reaper->set_self(); reaper->start(); return reaper; } void Reaper::set_self() noexcept { self_ = shared_from_this(); } void Reaper::start() { reap_thread_ = thread(&Reaper::reap_func, this); } void Reaper::destroy() { // Let the reaper thread know that it needs to stop doing things { lock_guard lock(mutex_); if (finish_) { return; } finish_ = true; do_work_.notify_one(); } reap_thread_.join(); } // Add a new entry to the reaper. If the entry is not refreshed within the expiry interval, // the reaper removes the item from the list and calls cb to let the caller know about the expiry. ReapItem::SPtr Reaper::add(ReaperCallback const& cb) { if (!cb) { throw unity::InvalidArgumentException("Reaper: invalid null callback passed to add()."); } lock_guard lock(mutex_); if (finish_) { throw unity::LogicException("Reaper: cannot add item to destroyed reaper."); } // Put new Item at the head of the list. reaper_private::Reaplist::iterator ri; Item item(cb); list_.push_front(item); // LRU order ri = list_.begin(); if (list_.size() == 1) { do_work_.notify_one(); // Wake up reaper thread } // Make a new ReapItem. assert(self_.lock()); ReapItem::SPtr reap_item(new ReapItem(self_, ri)); // Now that the ReapItem is created, we can set the disable callback ri->disable_reap_item = [reap_item] { reap_item->destroy(); }; return reap_item; } size_t Reaper::size() const noexcept { lock_guard lock(mutex_); return list_.size(); } // Reaper thread void Reaper::reap_func() { unique_lock lock(mutex_); for (;;) { if (list_.empty()) { // If no items are in the list, we wait until there is at least one item // in the list or we are told to finish. (While there is nothing // to reap, there is no point in waking up periodically only to find the list empty.) do_work_.wait(lock, [this] { return !list_.empty() || finish_; }); } else { // There is at least one item on the list, we wait with a timeout. // The first-to-expire item is at the tail of the list. We sleep at least long enough // for that item to get a chance to expire. (There is no point in waking up earlier.) // But, if have just done a scan, we sleep for at least reap_interval_, so there is // at most one pass every reap_interval_. auto const now = chrono::steady_clock::now(); auto const oldest_item_age = chrono::duration_cast(now - list_.back().timestamp); auto const reap_interval = chrono::duration_cast(reap_interval_); auto const sleep_interval = max(expiry_interval_ - oldest_item_age, reap_interval); auto const wakeup_time = now + sleep_interval; do_work_.wait_until(lock, wakeup_time, [this]{ return finish_; }); } if (finish_ && policy_ == NoCallbackOnDestroy) { // If we are told to finish (which happens when the Reaper instance is destroyed), // if NoCallbackOnDestroy is set, we are done. return; } // We run along the list from the tail towards the head. For any entry on the list // that is too old, we copy it to a zombie list. We use a strictly less comparison for // the timestamp, so if the entry is exactly expiry_interval_ old, it will be reaped. reaper_private::Reaplist zombies; if (finish_ && policy_ == CallbackOnDestroy) { // Final pass for CallbackOnDestroy. We simply call back on everything. zombies.assign(list_.begin(), list_.end()); } else { // finish_ may or may not be set here. If it is set, we still do one final // reaping pass before returning below so, if the reaper is destroyed // while there are still entries on it, expired entries have their callbacks // invoked at destruction time. auto const now = chrono::steady_clock::now(); for (auto it = list_.rbegin(); it != list_.rend(); ++it) { if (now < it->timestamp + expiry_interval_) { break; // LRU order. Once we find an entry that's not expired, we can stop looking. } zombies.push_back(*it); } } // Callbacks are made outside the synchronization, so we can't deadlock if a // a callback invokes a method on the reaper or a ReapItem. lock.unlock(); remove_zombies(zombies); // noexcept lock.lock(); if (finish_) { return; } } } void Reaper::remove_zombies(reaper_private::Reaplist const& zombies) noexcept { for (auto& item : zombies) { assert(item.disable_reap_item); item.disable_reap_item(); // Calls destroy() on the ReapItem, so it removes itself from list_ assert(item.cb); try { item.cb(); // Informs the caller that the item timed out. } catch (...) { // Ignore exceptions raised by the application's callback function. } } } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/UniqueID.cpp0000644000015301777760000000237212320776161025425 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include using namespace std; namespace unity { namespace scopes { namespace internal { UniqueID::UniqueID() : UniqueID(random_device()()) { } UniqueID::UniqueID(std::mt19937::result_type seed) : engine(seed), counter(0) { s << hex << setfill('0'); } string UniqueID::gen() { lock_guard lock(m); s << setw(8) << uniform_dist(engine) << setw(8) << counter++; string id(s.str()); s.str(""); return id; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/FilterStateImpl.cpp0000644000015301777760000000332612320776161027012 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include namespace unity { namespace scopes { namespace internal { FilterStateImpl::FilterStateImpl(VariantMap const& var) : state_(var) { } bool FilterStateImpl::has_filter(std::string const& id) const { return state_.find(id) != state_.end(); } void FilterStateImpl::remove(std::string const& id) { state_.erase(id); } Variant FilterStateImpl::get(std::string const& filter_id) const { auto it = state_.find(filter_id); if (it != state_.end()) { return it->second; } throw InvalidArgumentException("Unknown fiter: " + filter_id); } VariantMap& FilterStateImpl::get() { return state_; } VariantMap FilterStateImpl::serialize() const { return state_; } FilterState FilterStateImpl::deserialize(VariantMap const& var) { return FilterState(new FilterStateImpl(var)); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ActivationResponseImpl.cpp0000644000015301777760000000635112320776161030405 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include namespace unity { namespace scopes { namespace internal { ActivationResponseImpl::ActivationResponseImpl(ActivationResponse::Status status) : status_(status) { if (status == ActivationResponse::Status::PerformQuery) { throw unity::InvalidArgumentException("ActivationResponse(): Status::PerformQuery allowed only with CannedQuery object"); } } ActivationResponseImpl::ActivationResponseImpl(CannedQuery const& query) : status_(ActivationResponse::Status::PerformQuery), query_(std::make_shared(query)) { } ActivationResponseImpl::ActivationResponseImpl(VariantMap const& var) { auto it = var.find("scope_data"); if (it == var.end()) { throw LogicException("ActivationResponseImpl(): Invalid data, missing 'scope_data'"); } scope_data_ = it->second; it = var.find("status"); if (it == var.end()) { throw LogicException("ActivationResponseImpl(): Invalid data, missing 'status'"); } status_ = static_cast(it->second.get_int()); if (status_ == ActivationResponse::Status::PerformQuery) { it = var.find("query"); if (it == var.end()) { throw LogicException("ActivationResponseImpl(): Invalid data, missing 'query'"); } query_ = std::make_shared(CannedQueryImpl::create(it->second.get_dict())); } } ActivationResponse::Status ActivationResponseImpl::status() const { return status_; } void ActivationResponseImpl::set_scope_data(Variant const& hints) { scope_data_ = hints; } Variant ActivationResponseImpl::scope_data() const { return scope_data_; } CannedQuery ActivationResponseImpl::query() const { if (query_) { assert(status_ == ActivationResponse::Status::PerformQuery); return *query_; } throw LogicException("ActivationResponse::query(): query is only available for status of Status::PerformQuery"); } VariantMap ActivationResponseImpl::serialize() const { VariantMap vm; vm["status"] = static_cast(status_); vm["scope_data"] = scope_data_; if (query_) { vm["query"] = query_->serialize(); } return vm; } ActivationResponse ActivationResponseImpl::create(VariantMap const& var) { return ActivationResponse(new ActivationResponseImpl(var)); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/CMakeLists.txt0000644000015301777760000000670712320776161026004 0ustar pbusernogroup00000000000000add_subdirectory(lttng) add_subdirectory(smartscopes) add_subdirectory(zmq_middleware) set(CAPNPROTO_FILES ${CAPNPROTO_FILES} PARENT_SCOPE) set(SRC ${CMAKE_CURRENT_SOURCE_DIR}/AbstractObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ActionMetadataImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ActivationQueryBaseImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ActivationQueryObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ActivationReplyObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ActivationResponseImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/AnnotationImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CannedQueryImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CategorisedResultImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CategoryImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CategoryRegistry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CategoryRendererImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ColumnLayoutImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ConfigBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/DepartmentImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/DynamicLoader.cpp ${CMAKE_CURRENT_SOURCE_DIR}/FilterBaseImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/FilterOptionImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/FilterStateImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/JsonCppNode.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LinkImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareFactory.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MWObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MWQuery.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MWQueryCtrl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MWRegistry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MWReply.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MWScope.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MWStateReceiver.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ObjectImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/OptionSelectorFilterImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PreviewQueryObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PreviewReplyImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PreviewReplyObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PreviewWidgetImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/QueryBaseImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/QueryCtrlImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/QueryCtrlObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/QueryMetadataImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/QueryObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Reaper.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RegistryConfig.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RegistryException.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RegistryImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RegistryObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ReplyImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ReplyObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ResultImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ResultReplyObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RuntimeConfig.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RuntimeImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ScopeBaseImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ScopeConfig.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ScopeImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ScopeLoader.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ScopeMetadataImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ScopeObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/SearchMetadataImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/SearchReplyImpl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/StateReceiverObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ThreadPool.cpp ${CMAKE_CURRENT_SOURCE_DIR}/UniqueID.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Utils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/VariantBuilderImpl.cpp ) set(UNITY_SCOPES_LIB_SRC ${UNITY_SCOPES_LIB_SRC} ${SRC} PARENT_SCOPE) unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ScopeObject.cpp0000644000015301777760000001756112320776161026150 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include #include // TODO: remove this once logging is added #include using namespace std; using namespace unity::scopes; using namespace unity::scopes::internal; namespace unity { namespace scopes { namespace internal { ScopeObject::ScopeObject(RuntimeImpl* runtime, ScopeBase* scope_base) : runtime_(runtime), scope_base_(scope_base) { assert(runtime); assert(scope_base); } ScopeObject::~ScopeObject() { } MWQueryCtrlProxy ScopeObject::query(MWReplyProxy const& reply, MiddlewareBase* mw_base, std::function const& query_factory_fun, std::function const& query_object_factory_fun) { if (!reply) { // We can't assert here because the null proxy may have been sent by a broken client, that is, // it can be null because it was sent by the remote end as null. This should never happen but, // to be safe, we don't assert, in case someone is running a broken client. // TODO: log error about incoming request containing an invalid reply proxy. throw LogicException("Scope \"" + runtime_->scope_id() + "\": query() called with null reply proxy"); } // Ask scope to instantiate a new query. QueryBase::SPtr query_base; try { query_base = query_factory_fun(); if (!query_base) { // TODO: log error, scope returned null pointer. throw ResourceException("Scope \"" + runtime_->scope_id() + "\" returned nullptr from query_factory_fun()"); } } catch (...) { throw ResourceException("Scope \"" + runtime_->scope_id() + "\" threw an exception from query_factory_fun()"); } MWQueryCtrlProxy ctrl_proxy; try { // Instantiate the query ctrl and connect it to the middleware. QueryCtrlObject::SPtr co(make_shared()); ctrl_proxy = mw_base->add_query_ctrl_object(co); // Instantiate the query. We tell it what the ctrl is so, // when the query completes, it can tell the ctrl object // to destroy itself. QueryObjectBase::SPtr qo(query_object_factory_fun(query_base, ctrl_proxy)); MWQueryProxy query_proxy = mw_base->add_query_object(qo); // We tell the ctrl what the query facade is so, when cancel() is sent // to the ctrl, it can forward it to the facade. co->set_query(qo); // Start the query. We call via the middleware, which calls // the run() implementation in a different thread, so we cannot block here. // We pass a shared_ptr to the qo to the qo itself, so the qo can hold the reference // count high until the run() request arrives in the query via the middleware. qo->set_self(qo); query_proxy->run(reply); } catch (std::exception const& e) { try { reply->finished(ListenerBase::Error, e.what()); } catch (...) { } cerr << "query(): " << e.what() << endl; // TODO: log error throw; } catch (...) { try { reply->finished(ListenerBase::Error, "unknown exception"); } catch (...) { } cerr << "query(): unknown exception" << endl; // TODO: log error throw; } return ctrl_proxy; } MWQueryCtrlProxy ScopeObject::search(CannedQuery const& q, SearchMetadata const& hints, MWReplyProxy const& reply, InvokeInfo const& info) { return query(reply, info.mw, [&q, &hints, this]() -> SearchQueryBase::UPtr { auto search_query = this->scope_base_->search(q, hints); search_query->set_metadata(hints); return search_query; }, [&reply, &hints](QueryBase::SPtr query_base, MWQueryCtrlProxy ctrl_proxy) -> QueryObjectBase::SPtr { return make_shared(query_base, hints.cardinality(), reply, ctrl_proxy); } ); } MWQueryCtrlProxy ScopeObject::activate(Result const& result, ActionMetadata const& hints, MWReplyProxy const& reply, InvokeInfo const& info) { return query(reply, info.mw, [&result, &hints, this]() -> QueryBase::SPtr { return this->scope_base_->activate(result, hints); }, [&reply](QueryBase::SPtr query_base, MWQueryCtrlProxy ctrl_proxy) -> QueryObjectBase::SPtr { auto activation_base = dynamic_pointer_cast(query_base); assert(activation_base); return make_shared(activation_base, reply, ctrl_proxy); } ); } MWQueryCtrlProxy ScopeObject::perform_action(Result const& result, ActionMetadata const& hints, std::string const& widget_id, std::string const& action_id, MWReplyProxy const &reply, InvokeInfo const& info) { return query(reply, info.mw, [&result, &hints, &widget_id, &action_id, this]() -> QueryBase::SPtr { return this->scope_base_->perform_action(result, hints, widget_id, action_id); }, [&reply](QueryBase::SPtr query_base, MWQueryCtrlProxy ctrl_proxy) -> QueryObjectBase::SPtr { auto activation_base = dynamic_pointer_cast(query_base); assert(activation_base); return make_shared(activation_base, reply, ctrl_proxy); } ); } MWQueryCtrlProxy ScopeObject::preview(Result const& result, ActionMetadata const& hints, MWReplyProxy const& reply, InvokeInfo const& info) { return query(reply, info.mw, [&result, &hints, this]() -> QueryBase::SPtr { return this->scope_base_->preview(result, hints); }, [&reply](QueryBase::SPtr query_base, MWQueryCtrlProxy ctrl_proxy) -> QueryObjectBase::SPtr { auto preview_query = dynamic_pointer_cast(query_base); assert(preview_query); return make_shared(preview_query, reply, ctrl_proxy); } ); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/CategoryImpl.cpp0000644000015301777760000000510112320776161026332 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { namespace internal { CategoryImpl::CategoryImpl(VariantMap const& variant_map) { deserialize(variant_map); } CategoryImpl::CategoryImpl(std::string const& id, std::string const& title, std::string const &icon, CategoryRenderer const& renderer_template) : id_(id), title_(title), icon_(icon), renderer_template_(renderer_template) { if (id.empty()) { throw InvalidArgumentException("Category id must not be empty"); } // it's ok if title and icon are empty. } std::string const& CategoryImpl::id() const { return id_; } std::string const& CategoryImpl::title() const { return title_; } std::string const& CategoryImpl::icon() const { return icon_; } CategoryRenderer const& CategoryImpl::renderer_template() const { return renderer_template_; } VariantMap CategoryImpl::serialize() const { VariantMap var; var["id"] = id_; var["title"] = title_; var["icon"] = icon_; var["renderer_template"] = renderer_template_.data(); return var; } void CategoryImpl::deserialize(VariantMap const& variant_map) { auto it = variant_map.find("id"); if (it == variant_map.end()) { throw InvalidArgumentException("Missing 'id'"); } id_ = it->second.get_string(); it = variant_map.find("title"); if (it != variant_map.end()) { title_ = it->second.get_string(); } it = variant_map.find("icon"); if (it != variant_map.end()) { icon_ = it->second.get_string(); } it = variant_map.find("renderer_template"); if (it != variant_map.end()) { renderer_template_ = CategoryRenderer(it->second.get_string()); // can throw if json is invalid } } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ThreadPool.cpp0000644000015301777760000000473512320776161026010 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { ThreadPool::ThreadPool(int size) : num_threads_(size) { if (size < 1) { throw InvalidArgumentException("ThreadPool(): invalid pool size: " + std::to_string(size)); } queue_.reset(new TaskQueue); try { { lock_guard lock(mutex_); threads_ready_ = std::promise(); } for (int i = 0; i < size; ++i) { threads_.push_back(std::thread(&ThreadPool::run, this)); } auto future = threads_ready_.get_future(); future.wait(); future.get(); } catch (std::exception const&) // LCOV_EXCL_LINE { throw ResourceException("ThreadPool(): exception during pool creation"); // LCOV_EXCL_LINE } } ThreadPool::~ThreadPool() { queue_->destroy(); try { for (size_t i = 0; i < threads_.size(); ++i) { threads_[i].join(); } } catch (...) // LCOV_EXCL_LINE { assert(false); // LCOV_EXCL_LINE } } void ThreadPool::run() { TaskQueue::value_type task; for (;;) { try { { lock_guard lock(mutex_); if (--num_threads_ == 0) { threads_ready_.set_value(); } } task = queue_->wait_and_pop(); } catch (runtime_error const&) { return; // wait_and_pop() throws if the queue is destroyed while threads are blocked on it. } task(); } } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/DynamicLoader.cpp0000644000015301777760000000604312320776161026454 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { DynamicLoader::LibraryHandles DynamicLoader::handles_; mutex DynamicLoader::mutex_; DynamicLoader::DynamicLoader(string const& path, Binding b, Unload ul) { // Prevent concurrent access to handles_ and guard against concurrent // calls to dlopen()/dlclose(), which are not thread-safe. lock_guard lock(mutex_); handle_ = nullptr; path_ = path; unload_ = ul; // If the caller doesn't want dlclose() to be called, we look whether we've loaded // this library previously and, if so, re-use its handle. if (ul == Unload::noclose) { auto it = handles_.find(path); if (it != handles_.end()) { handle_ = it->second; assert(handle_); return; } } assert(ul == Unload::automatic || handle_ == nullptr); if ((handle_ = dlopen(path.c_str(), b == Binding::lazy ? RTLD_LAZY : RTLD_NOW)) == nullptr) { throw ResourceException(dlerror()); } if (ul == Unload::noclose) { handles_[path] = handle_; // Remember the library for re-use. } } DynamicLoader::~DynamicLoader() { lock_guard lock(mutex_); if (unload_ == Unload::automatic) { assert(handle_); dlclose(handle_); } } DynamicLoader::UPtr DynamicLoader::create(string const& path, Binding b, Unload ul) { return UPtr(new DynamicLoader(path, b, ul)); } DynamicLoader::VoidFunc DynamicLoader::find_function(string const& symbol) { // The ugly cast is needed because a void* (returned by dlsym()) is not compatible with a function pointer. VoidFunc func; *(void**)&func = find_variable(symbol); return func; } void* DynamicLoader::find_variable(string const& symbol) { lock_guard lock(mutex_); dlerror(); // Clear any existing error void* p = dlsym(handle_, symbol.c_str()); char const* error = dlerror(); if (error) { throw ResourceException(error); } return p; } string DynamicLoader::path() const { lock_guard lock(mutex_); return path_; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/QueryCtrlImpl.cpp0000644000015301777760000000442312320776161026515 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include // TODO: remove this once logging is added using namespace std; namespace unity { namespace scopes { namespace internal { QueryCtrlImpl::QueryCtrlImpl(MWQueryCtrlProxy const& ctrl_proxy, MWReplyProxy const& reply_proxy) : ObjectImpl(ctrl_proxy), reply_proxy_(reply_proxy) { assert(ctrl_proxy); assert(reply_proxy); // We remember the reply proxy so, when the query is cancelled, we can // inform the reply object belonging to this query that the query is finished. } QueryCtrlImpl::~QueryCtrlImpl() { } void QueryCtrlImpl::cancel() { try { // Forward cancellation down-stream to the query. This does not block. fwd()->cancel(); // Indicate (to ourselves) that this query is complete. Calling via the MWReplyProxy ensures // the finished() call will be processed by a seperate server-side thread, // so we cannot block here. reply_proxy_->finished(ListenerBase::Cancelled, ""); } catch (std::exception const& e) { cerr << e.what() << endl; // TODO: log error } } MWQueryCtrlProxy QueryCtrlImpl::fwd() const { return dynamic_pointer_cast(proxy()); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ReplyImpl.cpp0000644000015301777760000000622212320776161025655 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include // TODO: remove this once logging is added using namespace std; namespace unity { namespace scopes { namespace internal { ReplyImpl::ReplyImpl(MWReplyProxy const& mw_proxy, std::shared_ptr const& qo) : ObjectImpl(mw_proxy), qo_(qo), finished_(false) { assert(mw_proxy); } ReplyImpl::~ReplyImpl() { try { finished(); } catch (...) { // TODO: log error } } bool ReplyImpl::push(VariantMap const& variant_map) { auto qo = dynamic_pointer_cast(qo_); assert(qo); if (!qo->pushable({ fwd()->identity(), fwd()->mw_base() })) { return false; // Query was cancelled or had an error. } if (finished_) { return false; } try { fwd()->push(variant_map); } catch (std::exception const&) { error(current_exception()); return false; } return true; } void ReplyImpl::finished() { finished(ListenerBase::Finished); } void ReplyImpl::finished(ListenerBase::Reason reason) { if (!finished_.exchange(true)) { try { fwd()->finished(reason, ""); } catch (std::exception const& e) { // TODO: log error cerr << e.what() << endl; } } } void ReplyImpl::error(exception_ptr ex) { if (finished_.exchange(true)) { // Only the first thread to encounter an error // reports the error to the client. return; } string error_message; try { rethrow_exception(ex); } catch (std::exception const& e) { error_message = e.what(); } catch (...) { error_message = "unknown exception"; } // TODO: log error cerr << error_message << endl; try { fwd()->finished(ListenerBase::Error, error_message); } catch (std::exception const& e) { // TODO: log error cerr << e.what() << endl; } } MWReplyProxy ReplyImpl::fwd() const { return dynamic_pointer_cast(proxy()); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/AnnotationImpl.cpp0000644000015301777760000001153112320776161026673 0ustar pbusernogroup00000000000000/* Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include #include #include namespace unity { namespace scopes { namespace internal { AnnotationImpl::AnnotationImpl(Annotation::Type annotation_type) : annotation_type_(annotation_type) { } AnnotationImpl::AnnotationImpl(const VariantMap &variant_map) { auto it = variant_map.find("type"); if (it == variant_map.end()) { throw InvalidArgumentException("Annotation(): Invalid variant, missing 'type'"); } auto typestr = it->second.get_string(); if (typestr == "link") { annotation_type_ = Annotation::Type::Link; } else if (typestr == "groupedlink") { annotation_type_ = Annotation::Type::GroupedLink; } it = variant_map.find("label"); if (it != variant_map.end()) { set_label(it->second.get_string()); } it = variant_map.find("icon"); if (it != variant_map.end()) { set_icon(it->second.get_string()); } it = variant_map.find("links"); if (it != variant_map.end()) { auto links_var = it->second.get_array(); for (auto const& h: links_var) { links_.push_back(std::shared_ptr(new Link(h.get_dict()))); } } throw_if_inconsistent(); } AnnotationImpl::~AnnotationImpl() { } void AnnotationImpl::set_label(std::string const& label) { if (annotation_type_ != Annotation::Type::GroupedLink) { std::cerr << "Annotation::set_label(): label is allowed in GroupedLink only" << std::endl; } label_ = label; } void AnnotationImpl::set_icon(std::string const& icon) { if (annotation_type_ != Annotation::Type::Link) { std::cerr << "Annotation::set_icon(): icon is allowed in Link annotations only" << std::endl; } icon_ = icon; } void AnnotationImpl::add_link(std::string const& label, CannedQuery const& query) { if (annotation_type_ != Annotation::Type::GroupedLink && !links_.empty()) { throw InvalidArgumentException("Annotation::add_link(): multiple links are supported by GroupedLink only"); } links_.push_back(std::shared_ptr(new Link(label, query))); } std::string AnnotationImpl::label() const { if (annotation_type_ != Annotation::Type::GroupedLink) { std::cerr << "Annotation::label(): label is allowed in GroupedLink only" << std::endl; } return label_; } std::string AnnotationImpl::icon() const { if (annotation_type_ != Annotation::Type::Link) { std::cerr << "Annotation::icon(): icon is allowed in Link annotations only" << std::endl; } return icon_; } std::list AnnotationImpl::links() const { return links_; } Annotation::Type AnnotationImpl::annotation_type() const { return annotation_type_; } void AnnotationImpl::throw_if_inconsistent() const { if (links_.empty()) { throw InvalidArgumentException("No links present"); } switch (annotation_type_) { case Annotation::Type::Link: // nothing to verify break; case Annotation::Type::GroupedLink: if (label_.empty()) { throw InvalidArgumentException("Label must not be empty for GroupedLink annotation"); } break; default: throw InvalidArgumentException("Unknown annotation type"); } } VariantMap AnnotationImpl::serialize() const { throw_if_inconsistent(); VariantMap vm; switch (annotation_type_) { case Annotation::Type::Link: vm["type"] = "link"; break; case Annotation::Type::GroupedLink: vm["type"] = "groupedlink"; break; default: assert(0); // should never happen } if (!label_.empty()) { vm["label"] = label_; } if (!icon_.empty()) { vm["icon"] = icon_; } VariantArray links_var; for (auto const& link: links_) { links_var.push_back(Variant(link->serialize())); } vm["links"] = links_var; return vm; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/0000755000015301777760000000000012320776463026243 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/Util.cpp0000644000015301777760000000326012320776161027660 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { // Make sure we get a meaningful error message if a UNIX domain // socket has a path that exceeds the maximum length. void throw_if_bad_endpoint(string const& endpoint) { const std::string transport_prefix = "ipc://"; if (endpoint.substr(0, transport_prefix.length()) != transport_prefix) { return; // We only check paths starting with "ipc://" } string path = endpoint.substr(transport_prefix.length()); struct sockaddr_un addr; auto const maxlen = sizeof(addr.sun_path) - 1; if (path.length() > maxlen) { throw MiddlewareException("Socket path name too long (max = " + to_string(maxlen) + "): " + path); } } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ZmqQuery.cpp0000644000015301777760000000377112320776161030547 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { /* interface Query { void run(Reply* r); }; */ ZmqQuery::ZmqQuery(ZmqMiddleware* mw_base, string const& endpoint, string const& identity, string const& category) : MWObjectProxy(mw_base), ZmqObjectProxy(mw_base, endpoint, identity, category, RequestMode::Oneway), MWQuery(mw_base) { } ZmqQuery::~ZmqQuery() { } void ZmqQuery::run(MWReplyProxy const& reply) { capnp::MallocMessageBuilder request_builder; auto request = make_request_(request_builder, "run"); auto in_params = request.initInParams().getAs(); auto proxy = in_params.initReplyProxy(); auto rp = dynamic_pointer_cast(reply); proxy.setEndpoint(rp->endpoint().c_str()); proxy.setIdentity(rp->identity().c_str()); proxy.setCategory(rp->category().c_str()); auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder); }); future.wait(); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ZmqMiddleware.cpp0000644000015301777760000006046612320776161031523 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // TODO: remove this once logging is added using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { namespace { char const* query_suffix = "-q"; // Appended to server_name_ to create query adapter name char const* ctrl_suffix = "-c"; // Appended to server_name_ to create control adapter name char const* reply_suffix = "-r"; // Appended to server_name_ to create reply adapter name char const* state_suffix = "-s"; // Appended to server_name_ to create state adapter name } // namespace ZmqMiddleware::ZmqMiddleware(string const& server_name, string const& configfile, RuntimeImpl* runtime) try : MiddlewareBase(runtime), server_name_(server_name), state_(Stopped), config_(configfile), twoway_timeout_(300), // TODO: get timeout from config locate_timeout_(1500) // TODO: get timeout from config { assert(!server_name.empty()); } catch (zmqpp::exception const& e) { rethrow_zmq_ex(e); } ZmqMiddleware::~ZmqMiddleware() { try { stop(); wait_for_shutdown(); } catch (std::exception const& e) { // TODO: log exception } catch (...) { // TODO: log exception } } void ZmqMiddleware::start() { unique_lock lock(state_mutex_); switch (state_) { case Started: case Starting: { return; // Already started, or about to start, no-op } case Stopped: { // TODO: get directory from config // TODO: get pool size from config { lock_guard lock(data_mutex_); invokers_.reset(new ThreadPool(1)); } state_ = Started; state_changed_.notify_all(); break; } default: { assert(false); // LCOV_EXCL_LINE } } } void ZmqMiddleware::stop() { unique_lock lock(state_mutex_); switch (state_) { case Stopped: { break; // Already stopped, or about to stop, no-op } case Starting: { // Wait until start in progress has completed before stopping // Coverage excluded here because the window for which we are in this state is too // small to hit with a test. state_changed_.wait(lock, [this] { return state_ == Started; }); // LCOV_EXCL_LINE // FALLTHROUGH } case Started: { { lock_guard lock(data_mutex_); // No more outgoing invocations invokers_.reset(); } auto adapter_map = move(am_); for (auto& pair : adapter_map) { pair.second->shutdown(); } state_ = Stopped; state_changed_.notify_all(); lock.unlock(); for (auto& pair : adapter_map) { pair.second->wait_for_shutdown(); } break; } default: { assert(false); // LCOV_EXCL_LINE } } } void ZmqMiddleware::wait_for_shutdown() { unique_lock lock(state_mutex_); state_changed_.wait(lock, [this] { return state_ == Stopped; }); // LCOV_EXCL_LINE } namespace { void bad_proxy_string(string const& msg) { throw MiddlewareException("string_to_proxy(): " + msg); } } // Poor man's URI parser (no boost) ObjectProxy ZmqMiddleware::string_to_proxy(string const& s) { if (s == "nullproxy:") { return nullptr; } if (s.empty()) { bad_proxy_string("proxy string cannot be empty"); } static const string scheme = "ipc://"; if (s.substr(0, scheme.size()) != scheme) { bad_proxy_string("invalid proxy scheme prefix: \"" + s + "\" (expected \"" + scheme + "\")"); } auto fragment_pos = s.find_first_of('#'); if (fragment_pos == string::npos) { bad_proxy_string("invalid proxy: missing # separator: " + s); } string endpoint(s.begin(), s.begin() + fragment_pos); // Everything up to the '#' if (endpoint.size() == scheme.size()) { bad_proxy_string("invalid proxy: empty endpoint path: " + s); } string fields(s.substr(fragment_pos + 1)); // Everything following the '#' auto excl_pos = fields.find_first_of('!'); auto end_it = excl_pos == string::npos ? fields.end() : fields.begin() + excl_pos; string identity(fields.begin(), end_it); if (identity.empty()) { bad_proxy_string("invalid proxy: empty identity: " + s); } fields = fields.substr(identity.size()); // Remaining fields are optional. Field assignments are separated by '!' // Collect field assignments in fvals. vector fvals; while (!fields.empty()) { if (fields[0] == '!') { fields = fields.substr(1); } excl_pos = fields.find_first_of('!'); end_it = excl_pos == string::npos ? fields.end() : fields.begin() + excl_pos; string val(fields.begin(), end_it); if (val.empty()) { bad_proxy_string("invalid proxy: invalid empty field specification: " + s); } fvals.push_back(val); fields = fields.substr(val.size()); } // fvals now contains field assignments. Insert each assignment into a map, so we // check for duplicate fields. map fmap; const string valid_fields = "cmt"; for (auto const& v : fvals) { if (v.size() < 2 || v[1] != '=') { bad_proxy_string("invalid proxy: bad field specification (\"" + v + "\"): " + s); } if (valid_fields.find(v[0]) == string::npos) { bad_proxy_string("invalid proxy: invalid field identifier (\"" + v + "\"): " + s); } if (fmap.find(v[0]) != fmap.end()) { bad_proxy_string("invalid proxy: duplicate field specification (\"" + string(1, v[0]) + "=\"): " + s); } fmap[v[0]] = string(v.begin() + 2, v.end()); } // Now run over the map and check each value string category = "Scope"; RequestMode mode = RequestMode::Twoway; int64_t timeout = -1; for (auto const& pair : fmap) { switch (pair.first) { case 'c': { category = pair.second; // Empty category is OK break; } case 'm': { if (pair.second.empty() || (pair.second != "o" && pair.second != "t")) { bad_proxy_string("invalid proxy: bad mode (\"m=" + pair.second + "\"): " + s); } mode = pair.second == "o" ? RequestMode::Oneway : RequestMode::Twoway; break; } case 't': { if (pair.second.empty()) { bad_proxy_string("invalid proxy: bad timeout value (\"t=" + pair.second + "\"): " + s); } size_t pos; try { timeout = std::stol(pair.second, &pos); } catch (std::exception const&) { pos = 0; } if (pair.second[pos] != '\0') // Did not consume all of the assignment { bad_proxy_string("invalid proxy: bad timeout value (\"t=" + pair.second + "\"): " + s); } if (timeout < -1) { bad_proxy_string("invalid proxy: bad timeout value (\"t=" + pair.second + "\"): " + s); } break; } default: { assert(false); // LCOV_EXCL_LINE } } } return make_typed_proxy(endpoint, identity, category, mode, timeout); } string ZmqMiddleware::proxy_to_string(MWProxy const& proxy) { if (!proxy) { return "nullproxy:"; } return proxy->to_string(); } MWRegistryProxy ZmqMiddleware::create_registry_proxy(string const& identity, string const& endpoint) { MWRegistryProxy proxy; try { proxy.reset(new ZmqRegistry(this, endpoint, identity, "Registry", twoway_timeout_)); } catch (zmqpp::exception const& e) { rethrow_zmq_ex(e); } return proxy; } MWScopeProxy ZmqMiddleware::create_scope_proxy(string const& identity) { MWScopeProxy proxy; try { string endpoint = "ipc://" + config_.private_dir() + "/" + identity; proxy.reset(new ZmqScope(this, endpoint, identity, "Scope", twoway_timeout_)); } catch (zmqpp::exception const& e) { rethrow_zmq_ex(e); } return proxy; } MWScopeProxy ZmqMiddleware::create_scope_proxy(string const& identity, string const& endpoint) { MWScopeProxy proxy; try { proxy.reset(new ZmqScope(this, endpoint, identity, "Scope", twoway_timeout_)); } catch (zmqpp::exception const& e) { rethrow_zmq_ex(e); } return proxy; } MWQueryProxy ZmqMiddleware::create_query_proxy(string const& identity, string const& endpoint) { MWQueryProxy proxy; try { proxy.reset(new ZmqQuery(this, endpoint, identity, "Query")); } catch (zmqpp::exception const& e) { rethrow_zmq_ex(e); } return proxy; } MWQueryCtrlProxy ZmqMiddleware::create_query_ctrl_proxy(string const& identity, string const& endpoint) { MWQueryCtrlProxy proxy; try { proxy.reset(new ZmqQueryCtrl(this, endpoint, identity, "QueryCtrl")); } catch (zmqpp::exception const& e) { rethrow_zmq_ex(e); } return proxy; } MWStateReceiverProxy ZmqMiddleware::create_state_receiver_proxy(std::string const& identity) { MWStateReceiverProxy proxy; try { proxy.reset(new ZmqStateReceiver(this, "ipc://" + config_.private_dir() + "/" + server_name_ + state_suffix, identity, "StateReceiver")); } catch (zmqpp::exception const& e) { rethrow_zmq_ex(e); } return proxy; } MWQueryCtrlProxy ZmqMiddleware::add_query_ctrl_object(QueryCtrlObjectBase::SPtr const& ctrl) { assert(ctrl); MWQueryCtrlProxy proxy; try { shared_ptr qci(make_shared(ctrl)); auto adapter = find_adapter(server_name_ + ctrl_suffix, config_.private_dir()); function df; auto proxy = safe_add(df, adapter, "", qci); ctrl->set_disconnect_function(df); return ZmqQueryCtrlProxy(new ZmqQueryCtrl(this, proxy->endpoint(), proxy->identity(), "QueryCtrl")); } catch (std::exception const& e) // Should never happen unless our implementation is broken { // TODO: log this cerr << "unexpected exception in add_query_ctrl_object(): " << e.what() << endl; throw; } return proxy; } void ZmqMiddleware::add_dflt_query_ctrl_object(QueryCtrlObjectBase::SPtr const& ctrl) { assert(ctrl); try { shared_ptr qci(make_shared(ctrl)); auto adapter = find_adapter(server_name_ + ctrl_suffix, config_.private_dir()); auto df = safe_dflt_add(adapter, "QueryCtrl", qci); ctrl->set_disconnect_function(df); } catch (std::exception const& e) // Should never happen unless our implementation is broken { // TODO: log this cerr << "unexpected exception in add_dflt_query_ctrl_object(): " << e.what() << endl; throw; } } MWQueryProxy ZmqMiddleware::add_query_object(QueryObjectBase::SPtr const& query) { assert(query); MWQueryProxy proxy; try { shared_ptr qi(make_shared(query)); auto adapter = find_adapter(server_name_ + query_suffix, config_.private_dir()); function df; auto proxy = safe_add(df, adapter, "", qi); query->set_disconnect_function(df); return ZmqQueryProxy(new ZmqQuery(this, proxy->endpoint(), proxy->identity(), "Query")); } catch (std::exception const& e) // Should never happen unless our implementation is broken { // TODO: log this cerr << "unexpected exception in add_query_object(): " << e.what() << endl; throw; } return proxy; } void ZmqMiddleware::add_dflt_query_object(QueryObjectBase::SPtr const& query) { assert(query); try { shared_ptr qi(make_shared(query)); auto adapter = find_adapter(server_name_ + query_suffix, config_.private_dir()); auto df = safe_dflt_add(adapter, "Query", qi); query->set_disconnect_function(df); } catch (std::exception const& e) // Should never happen unless our implementation is broken { // TODO: log this cerr << "unexpected exception in add_dflt_query_object(): " << e.what() << endl; throw; } } MWRegistryProxy ZmqMiddleware::add_registry_object(string const& identity, RegistryObjectBase::SPtr const& registry) { assert(!identity.empty()); assert(registry); MWRegistryProxy proxy; try { shared_ptr ri(make_shared(registry)); auto adapter = find_adapter(server_name_, runtime()->registry_endpointdir()); function df; auto proxy = safe_add(df, adapter, identity, ri); registry->set_disconnect_function(df); return ZmqRegistryProxy(new ZmqRegistry(this, proxy->endpoint(), proxy->identity(), "Registry", twoway_timeout_)); } catch (std::exception const& e) // Should never happen unless our implementation is broken { // TODO: log this cerr << "unexpected exception in add_registry_object(): " << e.what() << endl; throw; } return proxy; } MWReplyProxy ZmqMiddleware::add_reply_object(ReplyObjectBase::SPtr const& reply) { assert(reply); MWReplyProxy proxy; try { shared_ptr ri(make_shared(reply)); auto adapter = find_adapter(server_name_ + reply_suffix, config_.public_dir()); function df; auto proxy = safe_add(df, adapter, "", ri); reply->set_disconnect_function(df); return ZmqReplyProxy(new ZmqReply(this, proxy->endpoint(), proxy->identity(), "Reply")); } catch (std::exception const& e) // Should never happen unless our implementation is broken { // TODO: log this cerr << "unexpected exception in add_reply_object(): " << e.what() << endl; throw; } return proxy; } MWScopeProxy ZmqMiddleware::add_scope_object(string const& identity, ScopeObjectBase::SPtr const& scope) { assert(!identity.empty()); assert(scope); MWScopeProxy proxy; try { shared_ptr si(make_shared(scope)); auto adapter = find_adapter(server_name_, config_.private_dir()); function df; auto proxy = safe_add(df, adapter, identity, si); scope->set_disconnect_function(df); return ZmqScopeProxy(new ZmqScope(this, proxy->endpoint(), proxy->identity(), "Scope", twoway_timeout_)); } catch (std::exception const& e) // Should never happen unless our implementation is broken { // TODO: log this cerr << "unexpected exception in add_scope_object(): " << e.what() << endl; throw; } return proxy; } void ZmqMiddleware::add_dflt_scope_object(ScopeObjectBase::SPtr const& scope) { assert(scope); try { shared_ptr si(make_shared(scope)); auto adapter = find_adapter(server_name_, config_.private_dir()); auto df = safe_dflt_add(adapter, "Scope", si); scope->set_disconnect_function(df); } catch (std::exception const& e) // Should never happen unless our implementation is broken { // TODO: log this cerr << "unexpected exception in add_dflt_scope_object(): " << e.what() << endl; throw; } } MWStateReceiverProxy ZmqMiddleware::add_state_receiver_object(std::string const& identity, StateReceiverObject::SPtr const& state_receiver) { assert(!identity.empty()); assert(state_receiver); MWStateReceiverProxy proxy; try { shared_ptr sri(make_shared(state_receiver)); auto adapter = find_adapter(server_name_ + state_suffix, config_.private_dir()); function df; auto proxy = safe_add(df, adapter, identity, sri); state_receiver->set_disconnect_function(df); return ZmqStateReceiverProxy(new ZmqStateReceiver(this, proxy->endpoint(), proxy->identity(), "StateReceiver")); } catch (std::exception const& e) // Should never happen unless our implementation is broken { // TODO: log this cerr << "unexpected exception in add_state_receiver_object(): " << e.what() << endl; throw; } return proxy; } std::string ZmqMiddleware::get_scope_endpoint() { return "ipc://" + config_.private_dir() + "/" + server_name_; } std::string ZmqMiddleware::get_query_endpoint() { return "inproc://" + server_name_ + query_suffix; } std::string ZmqMiddleware::get_query_ctrl_endpoint() { return "ipc://" + config_.private_dir() + "/" + server_name_ + ctrl_suffix; } zmqpp::context* ZmqMiddleware::context() const noexcept { return const_cast(&context_); } ThreadPool* ZmqMiddleware::invoke_pool() { lock(state_mutex_, data_mutex_); unique_lock state_lock(state_mutex_, std::adopt_lock); lock_guard invokers_lock(data_mutex_, std::adopt_lock); if (state_ == Starting) { state_changed_.wait(state_lock, [this] { return state_ != Starting; }); // LCOV_EXCL_LINE } if (state_ == Stopped) { throw MiddlewareException("Cannot invoke operations while middleware is stopped"); } return invokers_.get(); } int64_t ZmqMiddleware::locate_timeout() const noexcept { return locate_timeout_; } ObjectProxy ZmqMiddleware::make_typed_proxy(string const& endpoint, string const& identity, string const& category, RequestMode mode, int64_t timeout) { // For the time being we only support Scope and Registry types for proxy creation, // both of which are twoway interfaces. if (mode != RequestMode::Twoway) { throw MiddlewareException("make_typed_proxy(): cannot create oneway proxies"); } if (category == "Scope") { auto p = make_shared(this, endpoint, identity, category, timeout); return ScopeImpl::create(p, runtime(), identity); } else if (category == "Registry") { auto p = make_shared(this, endpoint, identity, category, timeout); return make_shared(p, runtime()); } else { throw MiddlewareException("make_typed_proxy(): unknown category: " + category); } } namespace { bool has_suffix(string const& s, string const& suffix) { auto s_len = s.length(); auto suffix_len = suffix.length(); if (s_len >= suffix_len) { return s.compare(s_len - suffix_len, suffix_len, suffix) == 0; } return false; } } // namespace shared_ptr ZmqMiddleware::find_adapter(string const& name, string const& endpoint_dir) { lock_guard lock(data_mutex_); auto it = am_.find(name); if (it != am_.end()) { return it->second; } // We don't have the requested adapter yet, so we create it on the fly. int pool_size; RequestMode mode; if (has_suffix(name, query_suffix)) { // The query adapter is single or multi-threaded and supports oneway operations only. // TODO: get pool size from config pool_size = 1; mode = RequestMode::Oneway; } else if (has_suffix(name, ctrl_suffix)) { // The ctrl adapter is single-threaded and supports oneway operations only. pool_size = 1; mode = RequestMode::Oneway; } else if (has_suffix(name, reply_suffix)) { // The reply adapter is single- or multi-threaded and supports oneway operations only. // TODO: get pool size from config pool_size = 1; mode = RequestMode::Oneway; } else if (has_suffix(name, state_suffix)) { // The state adapter is single- or multi-threaded and supports oneway operations only. // TODO: get pool size from config pool_size = 1; mode = RequestMode::Oneway; } else { // The normal adapter is single- or multi-threaded and supports twoway operations only. // TODO: get pool size from config pool_size = 1; mode = RequestMode::Twoway; } // The query adapter is always inproc. string endpoint; if (has_suffix(name, query_suffix)) { endpoint = "inproc://" + name; } else { endpoint = "ipc://" + endpoint_dir + "/" + name; } shared_ptr a(new ObjectAdapter(*this, name, endpoint, mode, pool_size)); a->activate(); am_[name] = a; return a; } ZmqProxy ZmqMiddleware::safe_add(function& disconnect_func, shared_ptr const& adapter, string const& identity, shared_ptr const& servant) { string id = identity.empty() ? unique_id_.gen() : identity; disconnect_func = [adapter, id] { try { adapter->remove(id); } catch (...) { // No error here; for concurrent invocations that each disconnect the servant, // only one of them will succeed. } }; return adapter->add(id, servant); } function ZmqMiddleware::safe_dflt_add(shared_ptr const& adapter, string const& category, shared_ptr const& servant) { function disconnect_func = [adapter, category] { try { adapter->remove_dflt_servant(category); } catch (...) { // No error here; for concurrent invocations that each disconnect the servant, // only one of them will succeed. } }; adapter->add_dflt_servant(category, servant); return disconnect_func; } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/Current.cpp0000644000015301777760000000215212320776161030364 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { unity::scopes::internal::InvokeInfo to_info(Current const& c) { return { c.id, c.adapter->mw() }; } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ServantBase.cpp0000644000015301777760000000540012320776161031156 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { using namespace std::placeholders; ServantBase::ServantBase(shared_ptr const& delegate, DispatchTable funcs) : delegate_(delegate), dispatch_table_(move(funcs)) { assert(delegate); } ServantBase::~ServantBase() { } void ServantBase::dispatch_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r) { auto it = dispatch_table_.find(current.op_name); if (it == dispatch_table_.end()) { if (current.op_name == "ping") { r.setStatus(capnproto::ResponseStatus::SUCCESS); return; } marshal_operation_not_exist_exception(r, current); return; } auto dispatch_func = it->second; dispatch_func(current, in_params, r); } // Simple forwarding function around the dispatch_ method in a servant class. // It ensures that, if the application throws an exception, we marshal something // sensible back to the client. void ServantBase::safe_dispatch_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r) noexcept { string error; try { dispatch_(current, in_params, r); return; } catch (std::exception const& e) { error = e.what(); } catch (...) { error = "unknown exception"; } marshal_unknown_exception(r, error); r.setStatus(capnproto::ResponseStatus::RUNTIME_EXCEPTION); } shared_ptr ServantBase::del() const noexcept { return delegate_; } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ZmqStateReceiver.cpp0000644000015301777760000000503612320776161032203 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { /* interface StateReceiver { void push_state(std::string const& sender_id, StateReceiverObject::State state); // oneway }; */ ZmqStateReceiver::ZmqStateReceiver(ZmqMiddleware* mw_base, std::string const& endpoint, std::string const& identity, std::string const& category) : MWObjectProxy(mw_base), ZmqObjectProxy(mw_base, endpoint, identity, category, RequestMode::Oneway), MWStateReceiver(mw_base) { } ZmqStateReceiver::~ZmqStateReceiver() { } void ZmqStateReceiver::push_state(std::string const& sender_id, StateReceiverObject::State const& state) { capnp::MallocMessageBuilder request_builder; auto request = make_request_(request_builder, "push_state"); auto in_params = request.initInParams().getAs(); capnproto::StateReceiver::State s; switch (state) { case StateReceiverObject::ScopeReady: { s = capnproto::StateReceiver::State::SCOPE_READY; break; } case StateReceiverObject::ScopeStopping: { s = capnproto::StateReceiver::State::SCOPE_STOPPING; break; } default: { assert(false); } } in_params.setState(s); in_params.setSenderId(sender_id); auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder); }); future.wait(); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ReplyI.cpp0000644000015301777760000000566312320776161030160 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { /* interface Reply { void push(string result); void finished(); }; */ using namespace std::placeholders; ReplyI::ReplyI(ReplyObjectBase::SPtr const& ro) : ServantBase(ro, { { "push", bind(&ReplyI::push_, this, _1, _2, _3) }, { "finished", bind(&ReplyI::finished_, this, _1, _2, _3) } }) { } ReplyI::~ReplyI() { } void ReplyI::push_(Current const&, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder&) { auto req = in_params.getAs(); auto result = req.getResult(); auto delegate = dynamic_pointer_cast(del()); delegate->push(to_variant_map(result)); } void ReplyI::finished_(Current const&, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder&) { auto delegate = dynamic_pointer_cast(del()); auto req = in_params.getAs(); auto r = req.getReason(); ListenerBase::Reason reason; string err; switch (r) { case capnproto::Reply::FinishedReason::FINISHED: { reason = ListenerBase::Finished; break; } case capnproto::Reply::FinishedReason::CANCELLED: { reason = ListenerBase::Cancelled; break; } case capnproto::Reply::FinishedReason::ERROR: { reason = ListenerBase::Error; err = req.getError(); break; } default: { assert(false); // LCOV_EXCL_LINE reason = ListenerBase::Error; // LCOV_EXCL_LINE } } delegate->finished(reason, err); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/QueryCtrlI.cpp0000644000015301777760000000372212320776161031011 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { /* interface QueryCtrl { void cancel(); void destroy(); }; */ using namespace std::placeholders; QueryCtrlI::QueryCtrlI(QueryCtrlObjectBase::SPtr const& qo) : ServantBase(qo, { { "cancel", bind(&QueryCtrlI::cancel_, this, _1, _2, _3) }, { "destroy", bind(&QueryCtrlI::destroy_, this, _1, _2, _3) } }) { } QueryCtrlI::~QueryCtrlI() { } void QueryCtrlI::cancel_(Current const& current, capnp::AnyPointer::Reader&, capnproto::Response::Builder&) { auto delegate = dynamic_pointer_cast(del()); delegate->cancel(to_info(current)); } void QueryCtrlI::destroy_(Current const& current, capnp::AnyPointer::Reader&, capnproto::Response::Builder&) { auto delegate = dynamic_pointer_cast(del()); delegate->destroy(to_info(current)); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ZmqConfig.cpp0000644000015301777760000000311012320776161030632 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include using namespace std; namespace unity { namespace scopes { namespace internal { const char* ZmqConfig::ZMQ_CONFIG_GROUP = "Zmq"; namespace { const string public_dir_str = "EndpointDir.Public"; const string private_dir_str = "EndpointDir.Private"; } ZmqConfig::ZmqConfig(string const& configfile) : ConfigBase(configfile) { if (configfile.empty()) { public_dir_ = "/tmp"; private_dir_ = "/tmp"; } else { public_dir_ = get_string(ZMQ_CONFIG_GROUP, public_dir_str); private_dir_ = get_string(ZMQ_CONFIG_GROUP, private_dir_str); } } ZmqConfig::~ZmqConfig() { } string ZmqConfig::public_dir() const { return public_dir_; } string ZmqConfig::private_dir() const { return private_dir_; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ConnectionPool.cpp0000644000015301777760000000516512320776161031702 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { ConnectionPool::ConnectionPool(zmqpp::context& context) : context_(context) { } ConnectionPool::~ConnectionPool() { pool_.clear(); } zmqpp::socket& ConnectionPool::find(std::string const& endpoint, RequestMode m) { assert(!endpoint.empty()); lock_guard lock(mutex_); // Look for existing connection. If there is one, but with the wrong type, we throw. auto const& it = pool_.find(endpoint); if (it != pool_.end()) { if (it->second.mode != m) { string msg("ConnectionPool::find(): cannot send " + to_string(m) + " request via " + to_string(it->second.mode) + " connection (endpoint: " + endpoint + ")"); throw MiddlewareException(msg); } return it->second.socket; } // No existing connection yet, establish one. zmqpp::socket_type stype = m == RequestMode::Twoway ? zmqpp::socket_type::request : zmqpp::socket_type::push; zmqpp::socket s(context_, stype); s.set(zmqpp::socket_option::linger, 0); s.connect(endpoint); return pool_.emplace(endpoint, Connection { move(s), m }).first->second.socket; } void ConnectionPool::remove(std::string const& endpoint) { assert(!endpoint.empty()); lock_guard lock(mutex_); auto const& it = pool_.find(endpoint); if (it != pool_.end()) { pool_.erase(it); } } void ConnectionPool::register_socket(std::string const& endpoint, zmqpp::socket socket, RequestMode m) { assert(!endpoint.empty()); lock_guard lock(mutex_); pool_.emplace(endpoint, Connection { move(socket), m }); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ZmqReceiver.cpp0000644000015301777760000000640012320776161031176 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { ZmqReceiver::ZmqReceiver(zmqpp::socket& s) : s_(s) { } // Receive a message (as a single message or in parts) and convert to a capnp segment list. kj::ArrayPtr const> ZmqReceiver::receive() { // Clear previously received content, if any. parts_.clear(); copied_parts_.clear(); segments_.clear(); do { parts_.push_back(string()); string& str = parts_.back(); s_.receive(str); if (str.empty()) { // For pull sockets, receive() returns zero bytes when the socket is closed. throw std::runtime_error("ZmqReceiver::receive(): socket was closed"); } if (str.size() % sizeof(capnp::word) != 0) // Received message must contain an integral number of words. { throw std::runtime_error("ZmqReceiver::receive(): impossible message size (" + to_string(str.size()) + ")"); } auto num_words = str.size() / sizeof(capnp::word); char* buf = &str[0]; if (reinterpret_cast(buf) % sizeof(capnp::word) == 0) { // String buffer is word-aligned, point directly at the start of the string. segments_.push_back(kj::ArrayPtr(reinterpret_cast(buf), num_words)); } else { // No coverage here because std::string appears to always have its buffer word-aligned. // Because the standard doesn't guarantee this though, and it might change in the future, // the code below remains enabled. // // String buffer is not word-aligned, make a copy and point at that. unique_ptr words(new capnp::word[num_words]); // LCOV_EXCL_LINE memcpy(words.get(), buf, str.size()); // LCOV_EXCL_LINE segments_.push_back(kj::ArrayPtr(&words[0], num_words)); // LCOV_EXCL_LINE copied_parts_.push_back(move(words)); // LCOV_EXCL_LINE } } while (s_.has_more_parts()); return kj::ArrayPtr>(&segments_[0], segments_.size()); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ZmqSender.cpp0000644000015301777760000000312612320776161030654 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { ZmqSender::ZmqSender(zmqpp::socket& s) : s_(s) { } // Send a message provided as a capnp segment list. Each segment is sent as a separate zmq message part. void ZmqSender::send(kj::ArrayPtr const> segments) { auto it = segments.begin(); auto i = segments.size(); assert(i != 0); while (--i != 0) { s_.send_raw(reinterpret_cast(&(*it)[0]), it->size() * sizeof(capnp::word), zmqpp::socket::send_more); ++it; } s_.send_raw(reinterpret_cast(&(*it)[0]), it->size() * sizeof(capnp::word), zmqpp::socket::normal); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ZmqObject.cpp0000644000015301777760000001374712320776161030654 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { #define MONITOR_ENDPOINT "ipc:///tmp/scopes-monitor" ZmqObjectProxy::ZmqObjectProxy(ZmqMiddleware* mw_base, string const& endpoint, string const& identity, string const& category, RequestMode m, int64_t timeout) : MWObjectProxy(mw_base), endpoint_(endpoint), identity_(identity), category_(category), mode_(m), timeout_(timeout) { assert(m != Unknown); assert(timeout >= -1); throw_if_bad_endpoint(endpoint); // Make sure that fields have consistent settings for null proxies. if (endpoint.empty() || identity.empty()) { endpoint_ = ""; identity_ = ""; category_ = ""; } } ZmqObjectProxy::~ZmqObjectProxy() { } ZmqMiddleware* ZmqObjectProxy::mw_base() const noexcept { return dynamic_cast(MWObjectProxy::mw_base()); } string ZmqObjectProxy::endpoint() const { return endpoint_; } string ZmqObjectProxy::identity() const { return identity_; } string ZmqObjectProxy::category() const { return category_; } int64_t ZmqObjectProxy::timeout() const noexcept { return timeout_; } string ZmqObjectProxy::to_string() const { if (endpoint_.empty() || identity_.empty()) { return "nullproxy:"; } assert(!endpoint_.empty() && !identity_.empty()); string s = endpoint_ + "#" + identity_; if (!category_.empty()) { s += "!c=" + category_; } if (mode_ == RequestMode::Oneway) { s += "!m=o"; } if (timeout_ != -1) { s += "!t=" + std::to_string(timeout_); } return s; } void ZmqObjectProxy::ping() { capnp::MallocMessageBuilder request_builder; make_request_(request_builder, "ping"); auto future = mw_base()->invoke_pool()->submit([&] { this->invoke_(request_builder); }); future.wait(); } RequestMode ZmqObjectProxy::mode() const { return mode_; } // Returns a request message with the mode, operation name, endpoint, and identity set for this proxy. capnproto::Request::Builder ZmqObjectProxy::make_request_(capnp::MessageBuilder& b, std::string const& operation_name) const { auto request = b.initRoot(); request.setMode(mode_ == RequestMode::Oneway ? capnproto::RequestMode::ONEWAY : capnproto::RequestMode::TWOWAY); request.setOpName(operation_name.c_str()); request.setId(identity_.c_str()); request.setCat(category_.c_str()); return request; } void register_monitor_socket (ConnectionPool& pool, zmqpp::context_t const& context) { thread_local static bool monitor_initialized = false; if (!monitor_initialized) { monitor_initialized = true; zmqpp::socket monitor_socket(context, zmqpp::socket_type::publish); monitor_socket.connect(MONITOR_ENDPOINT); monitor_socket.set(zmqpp::socket_option::linger, 0); pool.register_socket(MONITOR_ENDPOINT, move(monitor_socket), RequestMode::Oneway); } } ZmqReceiver ZmqObjectProxy::invoke_(capnp::MessageBuilder& out_params) { return invoke_(out_params, timeout_); } // Get a socket to the endpoint for this proxy and write the request on the wire. // For a twoway request, poll for the reply with the timeout set for this proxy. // Return a receiver for the response (whether this is a oneway or twoway request). ZmqReceiver ZmqObjectProxy::invoke_(capnp::MessageBuilder& out_params, int64_t timeout) { // Each calling thread gets its own pool because zmq sockets are not thread-safe. thread_local static ConnectionPool pool(*mw_base()->context()); zmqpp::socket& s = pool.find(endpoint_, mode_); ZmqSender sender(s); auto segments = out_params.getSegmentsForOutput(); sender.send(segments); #ifdef ENABLE_IPC_MONITOR if (true) { register_monitor_socket(pool, *mw_base()->context()); zmqpp::socket& monitor = pool.find(MONITOR_ENDPOINT, RequestMode::Oneway); auto word_arr = capnp::messageToFlatArray(segments); monitor.send_raw(reinterpret_cast(&word_arr[0]), word_arr.size() * sizeof(capnp::word)); } #endif if (mode_ == RequestMode::Twoway) { zmqpp::poller p; p.add(s); p.poll(timeout); if (!p.has_input(s)) { // If a request times out, we must close the corresponding socket, otherwise // zmq gets confused: the reply will never be read, so the socket ends up // in a bad state. pool.remove(endpoint_); throw TimeoutException("Request timed out after " + std::to_string(timeout) + " milliseconds"); } } return ZmqReceiver(s); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/RethrowException.cpp0000644000015301777760000000230712320776161032255 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { // Convert a zmq exception to a unity::MiddlewareException and throw it. void rethrow_zmq_ex(zmqpp::exception const&) { throw unity::scopes::MiddlewareException("zmqpp exception"); } } // namespace ice_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ZmqException.cpp0000644000015301777760000001162312320776161031373 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { void marshal_unknown_exception(capnproto::Response::Builder& r, string const& s) { capnp::MallocMessageBuilder ex; auto payload = ex.initRoot(); capnp::Text::Reader text(s.c_str()); payload.setUnknown(text); r.setStatus(capnproto::ResponseStatus::RUNTIME_EXCEPTION); r.getPayload().setAs(ex.getRoot()); } void marshal_object_not_exist_exception(capnproto::Response::Builder& r, Current const& c) { capnp::MallocMessageBuilder ex; auto payload = ex.initRoot(); auto one = payload.initObjectNotExist(); auto proxy = one.initProxy(); proxy.setIdentity(c.id.c_str()); proxy.setEndpoint(c.adapter->endpoint().c_str()); proxy.setCategory(c.category.c_str()); one.setAdapter(c.adapter->name().c_str()); r.setStatus(capnproto::ResponseStatus::RUNTIME_EXCEPTION); r.getPayload().setAs(ex.getRoot()); } void marshal_operation_not_exist_exception(capnproto::Response::Builder& r, Current const& c) { capnp::MallocMessageBuilder ex; auto payload = ex.initRoot(); auto opne = payload.initOperationNotExist(); auto proxy = opne.initProxy(); proxy.setIdentity(c.id.c_str()); proxy.setEndpoint(c.adapter->endpoint().c_str()); proxy.setCategory(c.category.c_str()); opne.setAdapter(c.adapter->name().c_str()); opne.setOpName(c.op_name.c_str()); r.setStatus(capnproto::ResponseStatus::RUNTIME_EXCEPTION); r.getPayload().setAs(ex.getRoot()); } kj::ArrayPtr const> create_unknown_response(capnp::MessageBuilder& b, string const& s) { auto response = b.initRoot(); marshal_unknown_exception(response, s); return b.getSegmentsForOutput(); } kj::ArrayPtr const> create_object_not_exist_response(capnp::MessageBuilder& b, Current const& c) { auto response = b.initRoot(); marshal_object_not_exist_exception(response, c); return b.getSegmentsForOutput(); } void throw_if_runtime_exception(capnproto::Response::Reader const& response) { if (response.getStatus() != capnproto::ResponseStatus::RUNTIME_EXCEPTION) { return; } auto payload = response.getPayload().getAs(); switch (payload.which()) { case capnproto::RuntimeException::OPERATION_NOT_EXIST: { auto opne = payload.getOperationNotExist(); auto proxy = opne.getProxy(); string msg = string("Operation \"") + opne.getOpName().cStr() + "\" does not exist " "(adapter = " + opne.getAdapter().cStr() + ", endpoint = " + proxy.getEndpoint().cStr() + ", identity = " + proxy.getIdentity().cStr() + ")"; throw MiddlewareException(msg); } case capnproto::RuntimeException::OBJECT_NOT_EXIST: { auto one = payload.getObjectNotExist(); auto proxy = one.getProxy(); string msg = string("Object does not exist (adapter = ") + one.getAdapter().cStr() + ", endpoint = " + proxy.getEndpoint().cStr() + ", identity = " + proxy.getIdentity().cStr() + ")"; throw ObjectNotExistException(msg, proxy.getIdentity().cStr()); } case capnproto::RuntimeException::UNKNOWN: { throw MiddlewareException(payload.getUnknown().cStr()); } } } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ObjectAdapter.cpp0000644000015301777760000007060712320776161031463 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include #include // TODO: remove this once logging is added #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { ObjectAdapter::ObjectAdapter(ZmqMiddleware& mw, string const& name, string const& endpoint, RequestMode m, int pool_size) : mw_(mw), name_(name), endpoint_(endpoint), mode_(m), pool_size_(pool_size), state_(Inactive) { assert(!name.empty()); assert(!endpoint.empty()); assert(pool_size >= 1); throw_if_bad_endpoint(endpoint); } ObjectAdapter::~ObjectAdapter() { try { shutdown(); } catch (std::exception const& e) { // TODO: log error cerr << "~ObjectAdapter(): exception from shutdown(): " << e.what() << endl; } // LCOV_EXCL_START catch (...) { // TODO: log error cerr << "~ObjectAdapter(): unknown exception from shutdown()" << endl; } // LCOV_EXCL_STOP // We need to make sure that wait_for_shutdown() is always called because it joins // with any threads that may still be running. try { wait_for_shutdown(); } catch (std::exception const& e) { // TODO: log error cerr << "~ObjectAdapter(): exception from wait_for_shutdown(): " << e.what() << endl; } // LCOV_EXCL_START catch (...) { // TODO: log error cerr << "~ObjectAdapter(): unknown exception from wait_for_shutdown()" << endl; } // LCOV_EXCL_STOP } ZmqMiddleware* ObjectAdapter::mw() const { return &mw_; } string ObjectAdapter::name() const { return name_; } string ObjectAdapter::endpoint() const { return endpoint_; } ZmqProxy ObjectAdapter::add(std::string const& id, std::shared_ptr const& obj) { if (id.empty()) { throw InvalidArgumentException("ObjectAdapter::add(): invalid empty id (adapter: " + name_ + ")"); } if (!obj) { throw InvalidArgumentException("ObjectAdapter::add(): invalid nullptr object (adapter: " + name_ + ")"); } lock(map_mutex_, state_mutex_); lock_guard map_lock(map_mutex_, adopt_lock); { lock_guard state_lock(state_mutex_, adopt_lock); if (state_ == Destroyed || state_ == Failed) { throw_bad_state(state_); } } auto pair = servants_.insert(make_pair(id, obj)); if (!pair.second) { ostringstream s; s << "ObjectAdapter::add(): " << "cannot add id \"" << id << "\": id already in use (adapter: " << name_ << ")"; throw MiddlewareException(s.str()); } return ZmqProxy(new ZmqObjectProxy(&mw_, endpoint_, id, "", mode_)); } void ObjectAdapter::remove(std::string const& id) { shared_ptr servant; { lock(map_mutex_, state_mutex_); lock_guard map_lock(map_mutex_, adopt_lock); { lock_guard state_lock(state_mutex_, adopt_lock); if (state_ == Destroyed || state_ == Failed) { throw_bad_state(state_); } } auto it = servants_.find(id); if (it == servants_.end()) { ostringstream s; s << "ObjectAdapter::remove(): " << "cannot remove id \"" << id << "\": id not present (adapter: " << name_ << ")"; throw MiddlewareException(s.str()); } servant = it->second; servants_.erase(it); } // Lock released here, so we don't call servant destructor while holding a lock servant = nullptr; // This may trigger destructor call on the servant } shared_ptr ObjectAdapter::find(std::string const& id) const { lock(map_mutex_, state_mutex_); lock_guard map_lock(map_mutex_, adopt_lock); { lock_guard state_lock(state_mutex_, adopt_lock); if (state_ == Destroyed || state_ == Failed) { throw_bad_state(state_); } } auto it = servants_.find(id); if (it != servants_.end()) { return it->second; } return shared_ptr(); } void ObjectAdapter::add_dflt_servant(std::string const& category, std::shared_ptr const& obj) { if (!obj) { throw InvalidArgumentException("ObjectAdapter::add_dflt_servant(): invalid nullptr object (adapter: " + name_ + ")"); } lock(map_mutex_, state_mutex_); lock_guard map_lock(map_mutex_, adopt_lock); { lock_guard state_lock(state_mutex_, adopt_lock); if (state_ == Destroyed || state_ == Failed) { throw_bad_state(state_); } } auto pair = dflt_servants_.insert(make_pair(category, obj)); if (!pair.second) { ostringstream s; s << "ObjectAdapter::add_dflt_servant(): " << "cannot add category \"" << category << "\": category already in use (adapter: " << name_ << ")"; throw MiddlewareException(s.str()); } } void ObjectAdapter::remove_dflt_servant(std::string const& category) { shared_ptr servant; { lock(map_mutex_, state_mutex_); lock_guard map_lock(map_mutex_, adopt_lock); { lock_guard state_lock(state_mutex_, adopt_lock); if (state_ == Destroyed || state_ == Failed) { throw_bad_state(state_); } } auto it = dflt_servants_.find(category); if (it == dflt_servants_.end()) { ostringstream s; s << "ObjectAdapter::remove_dflt_servant(): " << "cannot remove category \"" << category << "\": category not present (adapter: " << name_ << ")"; throw MiddlewareException(s.str()); } servant = it->second; dflt_servants_.erase(it); } // Lock released here, so we don't call servant destructor while holding a lock servant = nullptr; // This may trigger destructor call on the servant } shared_ptr ObjectAdapter::find_dflt_servant(std::string const& category) const { lock(map_mutex_, state_mutex_); lock_guard map_lock(map_mutex_, adopt_lock); { lock_guard state_lock(state_mutex_, adopt_lock); if (state_ == Destroyed || state_ == Failed) { throw_bad_state(state_); } } auto it = dflt_servants_.find(category); if (it != dflt_servants_.end()) { return it->second; } return shared_ptr(); } void ObjectAdapter::activate() { unique_lock lock(state_mutex_); switch (state_) { case Inactive: { state_ = Activating; // No notify_all() here because no-one waits for this try { lock.unlock(); run_workers(); lock.lock(); } catch (...) { lock.lock(); state_ = Failed; state_changed_.notify_all(); throw; } state_ = Active; state_changed_.notify_all(); break; } case Activating: case Active: { break; // Already active, or about to become active, no-op } case Deactivating: case Destroyed: case Failed: { throw_bad_state(state_); } default: { assert(false); // LCOV_EXCL_LINE } } } void ObjectAdapter::shutdown() { unique_lock lock(state_mutex_); switch (state_) { case Deactivating: case Destroyed: { break; // Nothing to do } case Failed: { throw_bad_state(state_); } case Inactive: { state_ = Destroyed; state_changed_.notify_all(); break; } case Activating: { // LCOV_EXCL_START Too hard to hit with a test, the window is too small. // Wait until activation is complete or we reach a final state state_changed_.wait(lock, [this]{ return state_ != Activating; }); if (state_ == Deactivating || state_ == Destroyed) { return; // Another thread has finished the job in the mean time. } if (state_ == Failed) { throw_bad_state(state_); } // LCOV_EXCL_STOP // FALLTHROUGH } case Active: { state_ = Deactivating; stop_workers(); state_changed_.notify_all(); break; } default: { assert(false); // LCOV_EXCL_LINE } } } void ObjectAdapter::wait_for_shutdown() { AdapterState state; { unique_lock lock(state_mutex_); state_changed_.wait(lock, [this]{ return state_ == Deactivating || state_ == Destroyed || state_ == Failed; }); if (state_ == Deactivating) { state_ = Destroyed; } state_changed_.notify_all(); // Wake up everyone else asleep in here state = state_; } // We join with threads and call servant destructors outside synchronization. call_once(once_, [this](){ this->cleanup(); }); if (state == Failed) { throw_bad_state(state); } } void ObjectAdapter::throw_bad_state(AdapterState state) const { string bad_state; switch (state) { // LCOV_EXCL_START Too hard to hit with a test, the window is too short. case Deactivating: { bad_state = "Deactivating"; break; } // LCOV_EXCL_STOP case Destroyed: { bad_state = "Destroyed"; break; } case Failed: { bad_state = "Failed"; break; } default: { assert(false); // LCOV_EXCL_LINE break; } } MiddlewareException e("Object adapter in " + bad_state + " state (adapter: " + name_ + ")"); e.remember(exception_); // Remember any exception encountered by the broker thread or a worker thread. throw e; } void ObjectAdapter::run_workers() { // Start a broker thread to forward incoming messages to backend workers and // wait for the broker thread to finish its initialization. The broker // signals after it has connected to the ctrl socket. { lock_guard lock(ready_mutex_); ready_ = promise(); } broker_ = thread(&ObjectAdapter::broker_thread, this); { auto f = ready_.get_future(); try { f.get(); } catch (...) // LCOV_EXCL_LINE { throw MiddlewareException("ObjectAdapter::run_workers(): broker thread failure (adapter: " + name_ + ")"); // LCOV_EXCL_LINE } } // Create the appropriate number of worker threads. // The last worker thread to subscribe signals that the workers are ready. // This ensures that we won't send a stop from deactivate() until after // the workers can actually receive it. { lock_guard lock(ready_mutex_); ready_ = promise(); } { auto f = ready_.get_future(); num_workers_.store(pool_size_); for (auto i = 0; i < pool_size_; ++i) { workers_.push_back(thread(&ObjectAdapter::worker_thread, this)); } try { f.get(); } // LCOV_EXCL_START catch (...) // { stop_workers(); throw MiddlewareException("ObjectAdapter::run_workers(): worker thread failure (adapter: " + name_ + ")"); } // LCOV_EXCL_STOP } } void ObjectAdapter::init_ctrl_socket() { lock_guard lock(ctrl_mutex_); // PUB socket to let the broker and workers know when it is time to shut down. // Sending anything means the socket becomes ready for reading, which causes // the broker and worker threads to finish. ctrl_.reset(new zmqpp::socket(*mw_.context(), zmqpp::socket_type::publish)); ctrl_->set(zmqpp::socket_option::linger, 0); ctrl_->bind("inproc://" + name_ + "_adapter_ctrl"); } zmqpp::socket ObjectAdapter::subscribe_to_ctrl_socket() { zmqpp::socket ctrl(*mw_.context(), zmqpp::socket_type::subscribe); ctrl.set(zmqpp::socket_option::linger, 0); ctrl.connect("inproc://" + name_ + "_adapter_ctrl"); // Once a thread can read from here, that's the command to stop. ctrl.subscribe(""); return move(ctrl); } void ObjectAdapter::stop_workers() noexcept { lock_guard lock(ctrl_mutex_); try { ctrl_->send("stop"); } // LCOV_EXCL_START catch (std::exception const& e) { // TODO: log this instead cerr << "ObjectAdapter::stop_workers(): " << e.what() << endl; } catch (...) { // TODO: log this instead cerr << "ObjectAdapter::stop_workers(): unknown exception" << endl; } // LCOV_EXCL_STOP } // For the ipc transport, zmq permits more than one server to bind to the same endpoint. // If a server binds to an endpoint while another server is using that endpoint, the // second server silently "steals" the endpoint from the previous server, so all // connects after that point go to the new server, while connects that happened earlier // go to the old server. This is meant as a fail-over feature, and cannot be disabled. // // We don't want this and need an error if two servers try to use the same endpoint. // Hacky solution: we check whether it's possible to successfully connect to the // endpoint. If so, a server is still running there, and we throw. This has a // small race because a second server may connect after the check, but before // the bind. But, in practice, that's good enough for our purposes. void ObjectAdapter::safe_bind(zmqpp::socket& s, string const& endpoint) { const std::string transport_prefix = "ipc://"; if (endpoint.substr(0, transport_prefix.size()) == transport_prefix) { string path = endpoint.substr(transport_prefix.size()); struct sockaddr_un addr; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path) - 1); int fd = ::socket(AF_UNIX, SOCK_STREAM, 0); if (fd == -1) { // LCOV_EXCL_START throw MiddlewareException("ObjectAdapter: broker thread failure (adapter: " + name_ + "): " + "cannot create socket: " + strerror(errno)); // LCOV_EXCL_STOP } util::ResourcePtr close_guard(fd, ::close); if (::connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) { // Connect succeeded, so another server is using the socket already. throw MiddlewareException("ObjectAdapter: broker thread failure (adapter: " + name_ + "): " + "address in use: " + endpoint); } } s.bind(endpoint); } shared_ptr ObjectAdapter::find_servant(string const& id, string const& category) { shared_ptr servant = find(id); if (!servant) { servant = find_dflt_servant(category); } return servant; } void ObjectAdapter::broker_thread() { try { // Create the writing end of the ctrl socket. We need to do this before subscribing because, for inproc // pub-sub sockets, the bind must happen before the connect. init_ctrl_socket(); // Subscribe to ctrl socket. Once this socket becomes readable, that's the command to finish. auto ctrl = subscribe_to_ctrl_socket(); // Set up message pump. Router-dealer for twoway adapter, pull-push for oneway adapter. auto socket_type = mode_ == RequestMode::Twoway ? zmqpp::socket_type::router : zmqpp::socket_type::pull; zmqpp::socket frontend(*mw_.context(), socket_type); socket_type = mode_ == RequestMode::Twoway ? zmqpp::socket_type::dealer : zmqpp::socket_type::push; zmqpp::socket backend(*mw_.context(), socket_type); zmqpp::poller poller; try { poller.add(ctrl); frontend.set(zmqpp::socket_option::linger, 0); // "Safe" bind: prevents two servers from binding to the same endpoint. safe_bind(frontend, endpoint_); poller.add(frontend); backend.set(zmqpp::socket_option::linger, 0); backend.bind("inproc://" + name_ + "-worker"); poller.add(backend); // Tell parent that we are ready { lock_guard lock(ready_mutex_); ready_.set_value(); } } // LCOV_EXCL_START catch (...) // LCOV_EXCL_LINE { // TODO: log error lock_guard lock(ready_mutex_); ready_.set_exception(current_exception()); return; } // LCOV_EXCL_STOP int pending_requests = 0; bool shutting_down = false; for (;;) { zmqpp::message message; poller.poll(); if (poller.has_input(ctrl)) { // When the ctrl socket becomes ready, we need to get out of here. // We stop reading more requests from the router, but continue processing // while there are still replies outstanding. ctrl.receive(message); ctrl.close(); shutting_down = true; } if (!shutting_down && poller.has_input(frontend)) // Once shutting down, we no longer read incoming messages. { int flag; do { // This is the actual message pump. We read an incoming request and pass it to one of the workers // for processing. The dealer socket ensures fair sharing. frontend.receive(message); flag = frontend.has_more_parts() ? zmqpp::socket::send_more : zmqpp::socket::normal; backend.send(message, flag); } while (flag == zmqpp::socket::send_more); if (mode_ == RequestMode::Twoway) { ++pending_requests; // Only twoway requests require us to wait for replies } } if (pending_requests != 0 && poller.has_input(backend)) { // We need to read a reply for an earlier request. int flag; do { // Message pump in the opposite direction, for replies from server to client. backend.receive(message); flag = backend.has_more_parts() ? zmqpp::socket::send_more : zmqpp::socket::normal; frontend.send(message, flag); } while (flag == zmqpp::socket::send_more); assert(pending_requests > 0); --pending_requests; } if (shutting_down && pending_requests == 0) { frontend.close(); backend.close(); return; } } } catch (...) { MiddlewareException e("ObjectAdapter: broker thread failure (adapter: " + name_ + ")"); store_exception(e); // We may not have signaled the parent yet, depending on where things went wrong. try { lock_guard lock(ready_mutex_); ready_.set_exception(make_exception_ptr(e)); } catch (future_error) // LCOV_EXCL_LINE { } } } void ObjectAdapter::worker_thread() { try { zmqpp::poller poller; // Subscribe to ctrl socket. Once this socket becomes readable, that's the command to finish. auto ctrl = subscribe_to_ctrl_socket(); poller.add(ctrl); auto socket_type = mode_ == RequestMode::Twoway ? zmqpp::socket_type::reply : zmqpp::socket_type::pull; zmqpp::socket s(*mw_.context(), socket_type); s.set(zmqpp::socket_option::linger, 0); s.connect("inproc://" + name_ + "-worker"); poller.add(s); ZmqReceiver receiver(s); ZmqSender sender(s); // Sender is used only by twoway adapters (zero-cost, the class just remembers the passed socket). if (--num_workers_ == 0) // Last worker to reach this point notifies the parent that all workers are ready. { lock_guard lock(ready_mutex_); ready_.set_value(); } Current current; current.adapter = this; // Stays the same for all invocations, so we set this once only. bool finish = false; for (;;) { if (finish) { s.close(); return; } poller.poll(); if (poller.has_input(ctrl)) // Parent sent a stop message, so we are supposed to go away. { zmqpp::message message; ctrl.receive(message); ctrl.close(); finish = true; } if (!finish && poller.has_input(s)) // We stop reading new incoming messages once told to finish. { // Unmarshal the type-independent part of the message (id, category, operation name, mode). capnproto::Request::Reader req; unique_ptr message; try { // Unmarshal generic part of the message. auto segments = receiver.receive(); message.reset(new capnp::SegmentArrayMessageReader(segments)); req = message->getRoot(); current.id = req.getId().cStr(); current.category = req.getCat().cStr(); current.op_name = req.getOpName().cStr(); auto mode = req.getMode(); if (current.id.empty() || current.op_name.empty() || (mode != capnproto::RequestMode::TWOWAY && mode != capnproto::RequestMode::ONEWAY)) { if (mode_ == RequestMode::Twoway) { capnp::MallocMessageBuilder b; auto exr = create_unknown_response(b, "Invalid message header"); sender.send(exr); } else { // TODO: log error cerr << "ObjectAdapter: invalid oneway message header " << "(id: " << current.id << ", adapter: " << name_ << ", op: " << current.op_name << ")" << endl; } continue; } auto expected_mode = mode_ == RequestMode::Twoway ? capnproto::RequestMode::TWOWAY : capnproto::RequestMode::ONEWAY; if (mode != expected_mode) // Can't do oneway on a twoway adapter and vice-versa. { if (mode_ == RequestMode::Twoway) { ostringstream s; s << "ObjectAdapter: oneway invocation sent to twoway adapter " << "(id: " << current.id << ", adapter: " << name_ << ", op: " << current.op_name << ")"; capnp::MallocMessageBuilder b; auto exr = create_unknown_response(b, s.str()); sender.send(exr); } else { // TODO: log error cerr << "ObjectAdapter: twoway invocation sent to oneway adapter " << "(id: " << current.id << ", adapter: " << name_ << ", op: " << current.op_name << ")" << endl; } continue; } } catch (std::exception const& e) { // We get here if header unmarshaling failed. ostringstream s; s << "ObjectAdapter: error unmarshaling request header " << "(id: " << current.id << ", adapter: " << name_ << ", op: " << current.op_name << "): " << e.what(); if (mode_ == RequestMode::Twoway) { capnp::MallocMessageBuilder b; auto exr = create_unknown_response(b, s.str()); sender.send(exr); } else { // TODO: log error cerr << s.str() << endl; } continue; } // Look for a servant with matching id. auto servant = find_servant(current.id, current.category); if (!servant) { if (mode_ == RequestMode::Twoway) { capnp::MallocMessageBuilder b; auto exr = create_object_not_exist_response(b, current); sender.send(exr); } continue; } // We have a target object, so we can ask it to unmarshal the in-params, forward // the invocation to the application-provided method, and to marshal the results. auto in_params = req.getInParams(); capnp::MallocMessageBuilder b; auto r = b.initRoot(); servant->safe_dispatch_(current, in_params, r); // noexcept if (mode_ == RequestMode::Twoway) { sender.send(b.getSegmentsForOutput()); } } } } // LCOV_EXCL_START catch (...) { stop_workers(); // Fatal error, we need to stop all other workers and the broker. MiddlewareException e("ObjectAdapter: worker thread failure (adapter: " + name_ + ")"); store_exception(e); // We may not have signaled the parent yet, depending on where things went wrong. try { lock_guard lock(ready_mutex_); ready_.set_exception(make_exception_ptr(e)); } catch (future_error) { } } // LCOV_EXCL_STOP } void ObjectAdapter::cleanup() { join_with_all_threads(); servants_.clear(); dflt_servants_.clear(); } void ObjectAdapter::join_with_all_threads() { for (auto& w : workers_) { if (w.joinable()) { w.join(); } } if (broker_.joinable()) { broker_.join(); } } void ObjectAdapter::store_exception(MiddlewareException& ex) { lock_guard lock(state_mutex_); exception_ = ex.remember(exception_); state_ = Failed; state_changed_.notify_all(); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ZmqQueryCtrl.cpp0000644000015301777760000000352512320776161031371 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { /* interface QueryCtrl { void cancel(); // Oneway void destroy(); // Oneway }; */ ZmqQueryCtrl::ZmqQueryCtrl(ZmqMiddleware* mw_base, string const& endpoint, string const& identity, string const& category) : MWObjectProxy(mw_base), ZmqObjectProxy(mw_base, endpoint, identity, category, RequestMode::Oneway), MWQueryCtrl(mw_base) { } ZmqQueryCtrl::~ZmqQueryCtrl() { } void ZmqQueryCtrl::cancel() { capnp::MallocMessageBuilder request_builder; make_request_(request_builder, "cancel"); auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder); }); future.wait(); } void ZmqQueryCtrl::destroy() { capnp::MallocMessageBuilder request_builder; make_request_(request_builder, "destroy"); auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder); }); future.wait(); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/CMakeLists.txt0000644000015301777760000000256112320776161031002 0ustar pbusernogroup00000000000000add_subdirectory(capnproto) set(CAPNPROTO_FILES ${CAPNPROTO_FILES} PARENT_SCOPE) set(SRC ${CMAKE_CURRENT_SOURCE_DIR}/ConnectionPool.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Current.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ObjectAdapter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/QueryCtrlI.cpp ${CMAKE_CURRENT_SOURCE_DIR}/QueryI.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RegistryI.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ReplyI.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RequestMode.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RethrowException.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ScopeI.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ServantBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/StateReceiverI.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Util.cpp ${CMAKE_CURRENT_SOURCE_DIR}/VariantConverter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ZmqConfig.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ZmqMiddleware.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ZmqException.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ZmqObject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ZmqQuery.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ZmqQueryCtrl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ZmqReceiver.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ZmqRegistry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ZmqReply.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ZmqScope.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ZmqSender.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ZmqStateReceiver.cpp ) set(UNITY_SCOPES_LIB_SRC ${UNITY_SCOPES_LIB_SRC} ${SRC} PARENT_SCOPE) unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ZmqScope.cpp0000644000015301777760000002020512320776161030502 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { /* dictionary ValueDict; interface QueryCtrl; interface Reply; interface Scope { QueryCtrl* search(string query, ValueDict hints, Reply* replyProxy); QueryCtrl* activate(string query, ValueDict hints, Reply* replyProxy); QueryCtrl* perform_action(string query, ValueDict hints, string action_id, Reply* replyProxy); QueryCtrl* preview(string query, ValueDict hints, Reply* replyProxy); }; */ ZmqScope::ZmqScope(ZmqMiddleware* mw_base, string const& endpoint, string const& identity, string const& category, int64_t timeout) : MWObjectProxy(mw_base), ZmqObjectProxy(mw_base, endpoint, identity, category, RequestMode::Twoway, timeout), MWScope(mw_base) { } ZmqScope::~ZmqScope() { } QueryCtrlProxy ZmqScope::search(CannedQuery const& query, VariantMap const& hints, MWReplyProxy const& reply) { capnp::MallocMessageBuilder request_builder; auto reply_proxy = dynamic_pointer_cast(reply); { auto request = make_request_(request_builder, "search"); auto in_params = request.initInParams().getAs(); auto q = in_params.initQuery(); to_value_dict(query.serialize(), q); auto h = in_params.initHints(); to_value_dict(hints, h); auto p = in_params.initReplyProxy(); p.setEndpoint(reply_proxy->endpoint().c_str()); p.setIdentity(reply_proxy->identity().c_str()); p.setCategory(reply_proxy->category().c_str()); } auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder); }); auto receiver = future.get(); auto segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); throw_if_runtime_exception(response); auto proxy = response.getPayload().getAs().getReturnValue(); ZmqQueryCtrlProxy p(new ZmqQueryCtrl(mw_base(), proxy.getEndpoint().cStr(), proxy.getIdentity().cStr(), proxy.getCategory().cStr())); return make_shared(p, reply_proxy); } QueryCtrlProxy ZmqScope::activate(VariantMap const& result, VariantMap const& hints, MWReplyProxy const& reply) { capnp::MallocMessageBuilder request_builder; auto reply_proxy = dynamic_pointer_cast(reply); { auto request = make_request_(request_builder, "activate"); auto in_params = request.initInParams().getAs(); auto res = in_params.initResult(); to_value_dict(result, res); auto h = in_params.initHints(); to_value_dict(hints, h); auto p = in_params.initReplyProxy(); p.setEndpoint(reply_proxy->endpoint().c_str()); p.setIdentity(reply_proxy->identity().c_str()); } auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder); }); auto receiver = future.get(); auto segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); throw_if_runtime_exception(response); auto proxy = response.getPayload().getAs().getReturnValue(); ZmqQueryCtrlProxy p(new ZmqQueryCtrl(mw_base(), proxy.getEndpoint().cStr(), proxy.getIdentity().cStr(), proxy.getCategory().cStr())); return make_shared(p, reply_proxy); } QueryCtrlProxy ZmqScope::perform_action(VariantMap const& result, VariantMap const& hints, std::string const& widget_id, std::string const& action_id, MWReplyProxy const& reply) { capnp::MallocMessageBuilder request_builder; auto reply_proxy = dynamic_pointer_cast(reply); { auto request = make_request_(request_builder, "perform_action"); auto in_params = request.initInParams().getAs(); auto res = in_params.initResult(); to_value_dict(result, res); auto h = in_params.initHints(); to_value_dict(hints, h); in_params.setWidgetId(widget_id); in_params.setActionId(action_id); auto p = in_params.initReplyProxy(); p.setEndpoint(reply_proxy->endpoint().c_str()); p.setIdentity(reply_proxy->identity().c_str()); } auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder); }); future.wait(); auto receiver = future.get(); auto segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); throw_if_runtime_exception(response); auto proxy = response.getPayload().getAs().getReturnValue(); ZmqQueryCtrlProxy p(new ZmqQueryCtrl(mw_base(), proxy.getEndpoint().cStr(), proxy.getIdentity().cStr(), proxy.getCategory().cStr())); return make_shared(p, reply_proxy); } QueryCtrlProxy ZmqScope::preview(VariantMap const& result, VariantMap const& hints, MWReplyProxy const& reply) { capnp::MallocMessageBuilder request_builder; auto reply_proxy = dynamic_pointer_cast(reply); { auto request = make_request_(request_builder, "preview"); auto in_params = request.initInParams().getAs(); auto res = in_params.initResult(); to_value_dict(result, res); auto h = in_params.initHints(); to_value_dict(hints, h); auto p = in_params.initReplyProxy(); p.setEndpoint(reply_proxy->endpoint().c_str()); p.setIdentity(reply_proxy->identity().c_str()); } auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder); }); auto receiver = future.get(); auto segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); throw_if_runtime_exception(response); auto proxy = response.getPayload().getAs().getReturnValue(); ZmqQueryCtrlProxy p(new ZmqQueryCtrl(mw_base(), proxy.getEndpoint().cStr(), proxy.getIdentity().cStr(), proxy.getCategory().cStr())); return make_shared(p, reply_proxy); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/StateReceiverI.cpp0000644000015301777760000000444612320776161031630 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { /* interface StateReceiver { void push_state(std::string const& sender_id, StateReceiverObject::State state); // oneway }; */ using namespace std::placeholders; StateReceiverI::StateReceiverI(StateReceiverObject::SPtr const& sro) : ServantBase(sro, { { "push_state", bind(&StateReceiverI::push_state_, this, _1, _2, _3) } }) { } StateReceiverI::~StateReceiverI() { } void StateReceiverI::push_state_(Current const&, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder&) { auto delegate = std::dynamic_pointer_cast(del()); auto req = in_params.getAs(); auto sender_id = req.getSenderId(); auto s = req.getState(); StateReceiverObject::State state; switch (s) { case capnproto::StateReceiver::State::SCOPE_READY: { state = StateReceiverObject::ScopeReady; break; } case capnproto::StateReceiver::State::SCOPE_STOPPING: { state = StateReceiverObject::ScopeStopping; break; } default: { assert(false); } } delegate->push_state(sender_id, state); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/RequestMode.cpp0000644000015301777760000000207212320776161031200 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { string to_string(RequestMode m) { return m == RequestMode::Oneway ? "oneway" : "twoway"; } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/0000755000015301777760000000000012320776463030250 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/Reply.capnp0000644000015301777760000000332312320776161032362 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # @0xfdb6a0374075229f; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("unity::scopes::internal::zmq_middleware::capnproto::Reply"); using ValueDict = import "ValueDict.capnp"; # Reply interface # # Callback interface for the results returned by a query. We instantiate a separate reply object # for each query and pass a proxy to the reply object to createQuery(). In turn, the reply proxy # ends up inside the scope implementation, which uses it to push the results. This means that the # query identity is implicit in the reply object that is passed. The reply object is registered # on its object adapter with a UUID as the identity. # # Operations: # # void push(string result); # enum FinishedReason { Finished, Cancelled, Error }; # void finished(Reason r); struct PushRequest { result @0 : ValueDict.ValueDict; } enum FinishedReason { unused @0; finished @1; cancelled @2; error @3; } struct FinishedRequest { reason @0 : FinishedReason; error @1 : Text; # Present only if reason is error } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/Proxy.capnp0000644000015301777760000000305312320776161032410 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # @0x8fe122e718a84617; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("unity::scopes::internal::zmq_middleware::capnproto"); # Proxy definition. The endpoint must include # the protocol, which controls how to interpret the remainder of the string. For example: # # "tcp://localhost:5555" (TCP on loopback, port 5555 # # "ipc:///tmp/socket" (UNIX domain socket at /tmp/socket) # # The identity can be anything. It must be unique withing the corresponding endpoint. The identity # determines the target object of a message sent via the proxy. # # The category is normally empty. For default servants, the category is used to identify the type # of the target object, such as "Scope", "Reply", etc. struct Proxy { endpoint @0 : Text; identity @1 : Text; category @2 : Text; timeout @3 : Int64; # timeout for twoway proxies in milliseconds, -1 == wait forever } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/Query.capnp0000644000015301777760000000262512320776161032400 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # @0xa2f426b0db4141c5; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("unity::scopes::internal::zmq_middleware::capnproto::Query"); using Proxy = import "Proxy.capnp"; # Query interface # # The separate Query object solely exists so we can control a query # without the risk of blocking. The Scope::createQuery() method is on the -ctrl # endpoint, whereas the Query object is on the normal endpoint. This allows # createQuery() to start the query running by calling run(), which causes run() # to be dispatched in a thread from the normal endpoint, and createQuery() is guaranteed # to not block. # # Operations: # # void run(Proxy reply_proxy); struct RunRequest { replyProxy @0 : Proxy.Proxy; } struct RunResponse { } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/Scope.capnp0000644000015301777760000000450212320776161032340 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # @0xab8a5db476d65443; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("unity::scopes::internal::zmq_middleware::capnproto::Scope"); using Proxy = import "Proxy.capnp"; using ValueDict = import "ValueDict.capnp"; # Factory for queries. The Scope object runs on the ctrl-endpoint. # createQuery() creates a Query object on the normal endpoint, and a QueryCtrl object # on the ctrl-endpoint. It then calls run() on the Query object to set it executing in its own thread, before # returning the QueryCtrl proxy that permits cancellation. This guarantees that createQuery() will not block. # Scope interface # # Operations: # # Proxy createQuery(string query, ValueDict hints, Proxy reply_proxy); # The createQuery method instantiates a Query Object and its corresponding QueryCtrlObject. # The return value is the proxy to the QueryCtrl object. # The implementation of createQuery calls the Query's run() method to give a thread of control # to the application code. struct CreateQueryRequest { query @0 : ValueDict.ValueDict; hints @1 : ValueDict.ValueDict; replyProxy @2 : Proxy.Proxy; } struct CreateQueryResponse { returnValue @0 : Proxy.Proxy; } struct ActivationRequest { result @0 : ValueDict.ValueDict; hints @1 : ValueDict.ValueDict; replyProxy @2 : Proxy.Proxy; } struct ActionActivationRequest { result @0 : ValueDict.ValueDict; hints @1 : ValueDict.ValueDict; actionId @2 : Text; widgetId @3 : Text; replyProxy @4 : Proxy.Proxy; } struct PreviewRequest { result @0 : ValueDict.ValueDict; hints @1 : ValueDict.ValueDict; replyProxy @2 : Proxy.Proxy; } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/ValueDict.capnp0000644000015301777760000000252012320776161033145 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # @0x9514134742fa960f; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("unity::scopes::internal::zmq_middleware::capnproto"); struct NullVal { } # ValueDict definition. A dictionary of name/Value pairs, where each # Value can hold an int, bool, string, double, dict, array or null. struct Value { union { intVal @0 : Int32; doubleVal @1 : Float64; boolVal @2 : Bool; stringVal @3 : Text; dictVal @4 : ValueDict; arrayVal @5 : List(Value); nullVal @6 : NullVal; } } struct NVPair { name @0 : Text; value @1 : Value; } struct ValueDict { pairs @0 : List(NVPair); } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/StateReceiver.capnpunity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/StateReceiver.cap0000644000015301777760000000172312320776161033500 0ustar pbusernogroup00000000000000# # Copyright (C) 2014 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Marcus Tomlinson # @0xe6f283532b70ad20; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("unity::scopes::internal::zmq_middleware::capnproto::StateReceiver"); enum State { scopeReady @0; scopeStopping @1; } struct PushStateRequest { senderId @0 : Text; state @1 : State; } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/ScopeDict.capnp0000644000015301777760000000204212320776161033141 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # @0xffca41eb3c13387d; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("unity::scopes::internal::zmq_middleware::capnproto"); using Proxy = import "Proxy.capnp"; # ScopeDict definitions. A dictionary of name/scope proxy pairs. struct NSPair { name @0 : Text; scopeProxy @1 : Proxy.Proxy; } struct ScopeDict { pairs @0 : List(NSPair); } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/QueryCtrl.capnp0000644000015301777760000000245512320776161033226 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # @0x9903f9de544b6365; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("unity::scopes::internal::zmq_middleware::capnproto::QueryCtrl"); # The separate QueryCtrl object solely exists so we can cancel a query # without the risk of blocking. The QueryCtrl::cancel() method is on the -ctrl # endpoint, whereas the Query object is on the normal endpoint. This means # we always have a thread available to respond to an incoming cancel request. # QueryCtrl interface # # Operations: # # void cancel(); # void destroy(); struct CancelRequest { } struct CancelResponse { } struct DestroyRequest { } struct DestroyResponse { } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/Registry.capnp0000644000015301777760000000353612320776161033105 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # @0xb1b042af3cad4891; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("unity::scopes::internal::zmq_middleware::capnproto::Registry"); using ValueDict = import "ValueDict.capnp"; using Proxy = import "Proxy.capnp"; # Registry interface # # Operations: # # ValueDict get_metadata(string scope_id) throws NotFoundException; # map list(); # ObjectProxy locate(string identity) throws NotFoundException, RegistryException; struct NotFoundException { identity @0 : Text; } struct RegistryException { reason @0 : Text; } struct GetMetadataRequest { identity @0 : Text; } struct GetMetadataResponse { response : union { returnValue @0 : ValueDict.ValueDict; notFoundException @1 : NotFoundException; } } struct ListRequest { } struct ListResponse { returnValue @0 : ValueDict.ValueDict; # Dictionary of dictionaries: } struct LocateRequest { identity @0 : Text; } struct LocateResponse { response : union { returnValue @0 : Proxy.Proxy; notFoundException @1 : NotFoundException; registryException @2 : RegistryException; } } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/CMakeLists.txt0000644000015301777760000000111112320776161032775 0ustar pbusernogroup00000000000000set(CAPNPROTO_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Message.capnp ${CMAKE_CURRENT_SOURCE_DIR}/Object.capnp ${CMAKE_CURRENT_SOURCE_DIR}/Proxy.capnp ${CMAKE_CURRENT_SOURCE_DIR}/Query.capnp ${CMAKE_CURRENT_SOURCE_DIR}/QueryCtrl.capnp ${CMAKE_CURRENT_SOURCE_DIR}/Registry.capnp ${CMAKE_CURRENT_SOURCE_DIR}/Reply.capnp ${CMAKE_CURRENT_SOURCE_DIR}/Scope.capnp ${CMAKE_CURRENT_SOURCE_DIR}/ScopeDict.capnp ${CMAKE_CURRENT_SOURCE_DIR}/StateReceiver.capnp ${CMAKE_CURRENT_SOURCE_DIR}/ValueDict.capnp ) set(CAPNPROTO_FILES ${CAPNPROTO_FILES} PARENT_SCOPE) unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/Message.capnp0000644000015301777760000000622412320776161032656 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # @0x82174b92ecb836f7; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("unity::scopes::internal::zmq_middleware::capnproto"); # Message definitions (request and response). enum RequestMode { unused @0; # Prevents hasMode() from returning true if value wasn't sent oneway @1; twoway @2; } # A request contains the invocation mode, identity of the target object, an operation name, and the # in-parameters as a blob. struct Request { mode @0 : RequestMode; # Response required? id @1 : Text; # Identity of target object cat @2 : Text; # Category of target object opName @3 : Text; # Operation name inParams @4 : AnyPointer; # In-parameters for the operation } # Responses indicate success or an exception. All twoway invocations can raise run-time exceptions (such # as OperationNotExistException or ObjectNotExistException). # Operation can optionally raise one of a number of user-defined exceptions. enum ResponseStatus { unused @0; # Prevents hasStatus() from returning true if value wasn't set success @1; runtimeException @2; userException @3; } # A response is the response status, plus any payload. The payload is the out-parameters and return value (if any), # or it contains the details of the exception indicated by the status. struct Response { status @0 : ResponseStatus; payload @1 : AnyPointer; # Out-params followed by return value (if any), or exception data } # Run-time exceptions using Proxy = import "Proxy.capnp"; struct OperationNotExistException { proxy @0 : Proxy.Proxy; # The proxy for the request that raised the exception adapter @1 : Text; # Name of corresponding adapter opName @2 : Text; # Name of operation that wasn't found } struct ObjectNotExistException { proxy @0 : Proxy.Proxy; # The proxy for the request that raised the exception adapter @1 : Text; # Name of corresponding adapter } # Generic representation of a runtime exception. Holds the a union of all the exceptions that are possible. # The unknown exception deals with the servant throwing something we don't understand at all, # in which case the best we can do is marshal its type name. struct RuntimeException { union { operationNotExist @0 : OperationNotExistException; objectNotExist @1 : ObjectNotExistException; unknown @2 : Text; } } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/capnproto/Object.capnp0000644000015301777760000000171612320776161032501 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # @0xfdb6a03748b7779f; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("unity::api::scopes::internal::zmq_middleware::capnproto::Object"); # Object interface # # Operations: # # void ping(); # ping() has no parameters, so there is neither a Request nor a Response struct. unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/QueryI.cpp0000644000015301777760000000414312320776161030162 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { /* interface Query { void cancel(); void destroy(); }; */ using namespace std::placeholders; QueryI::QueryI(QueryObjectBase::SPtr const& qo) : ServantBase(qo, { { "run", bind(&QueryI::run_, this, _1, _2, _3) } }) { } QueryI::~QueryI() { } void QueryI::run_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder&) { auto req = in_params.getAs(); auto proxy = req.getReplyProxy(); ZmqReplyProxy reply_proxy(new ZmqReply(current.adapter->mw(), proxy.getEndpoint().cStr(), proxy.getIdentity().cStr(), proxy.getCategory().cStr())); assert(del()); auto delegate = dynamic_pointer_cast(del()); assert(delegate); delegate->run(reply_proxy, to_info(current)); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/RegistryI.cpp0000644000015301777760000001251612320776161030670 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { /* interface Scope; dictionary MetadataMap; exception NotFoundException { string identity; }; interface Registry { ScopeMetadata get_metadata(string scope_id) throws NotFoundException; MetadataMap list(); ObjectProxy locate(string identity) throws NotFoundException, RegistryException; }; */ using namespace std::placeholders; RegistryI::RegistryI(RegistryObjectBase::SPtr const& ro) : ServantBase(ro, { { "get_metadata", bind(&RegistryI::get_metadata_, this, _1, _2, _3) }, { "list", bind(&RegistryI::list_, this, _1, _2, _3) }, { "locate", bind(&RegistryI::locate_, this, _1, _2, _3) } }) { } RegistryI::~RegistryI() { } void RegistryI::get_metadata_(Current const&, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r) { auto req = in_params.getAs(); string scope_id = req.getIdentity().cStr(); auto delegate = dynamic_pointer_cast(del()); try { auto meta = delegate->get_metadata(scope_id); r.setStatus(capnproto::ResponseStatus::SUCCESS); auto get_metadata_response = r.initPayload().getAs().initResponse(); auto dict = get_metadata_response.initReturnValue(); to_value_dict(meta.serialize(), dict); } catch (NotFoundException const& e) { r.setStatus(capnproto::ResponseStatus::USER_EXCEPTION); auto get_metadata_response = r.initPayload().getAs().initResponse(); get_metadata_response.initNotFoundException().setIdentity(e.name().c_str()); } } void RegistryI::list_(Current const&, capnp::AnyPointer::Reader&, capnproto::Response::Builder& r) { auto delegate = dynamic_pointer_cast(del()); auto metadata_map = delegate->list(); r.setStatus(capnproto::ResponseStatus::SUCCESS); auto list_response = r.initPayload().getAs(); auto dict = list_response.initReturnValue().initPairs(metadata_map.size()); int i = 0; for (auto& pair : metadata_map) { dict[i].setName(pair.first.c_str()); // Scope ID auto md = dict[i].initValue().initDictVal(); to_value_dict(pair.second.serialize(), md); // Scope metadata ++i; } } void RegistryI::locate_(Current const&, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r) { auto req = in_params.getAs(); string identity = req.getIdentity().cStr(); auto delegate = dynamic_pointer_cast(del()); try { auto proxy = delegate->locate(identity); r.setStatus(capnproto::ResponseStatus::SUCCESS); auto locate_response = r.initPayload().getAs().initResponse(); auto return_proxy = locate_response.initReturnValue(); return_proxy.setIdentity(proxy->identity()); return_proxy.setCategory(proxy->category()); return_proxy.setEndpoint(proxy->endpoint()); return_proxy.setTimeout(proxy->timeout()); } catch (NotFoundException const& e) { r.setStatus(capnproto::ResponseStatus::USER_EXCEPTION); auto locate_response = r.initPayload().getAs().initResponse(); locate_response.initNotFoundException().setIdentity(e.name().c_str()); } catch (RegistryException const& e) { r.setStatus(capnproto::ResponseStatus::USER_EXCEPTION); auto locate_response = r.initPayload().getAs().initResponse(); locate_response.initRegistryException().setReason(e.reason().c_str()); } } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/VariantConverter.cpp0000644000015301777760000001007612320776161032242 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { void to_value(Variant const& v, capnproto::Value::Builder& b) { switch (v.which()) { case Variant::Int: { b.setIntVal(v.get_int()); break; } case Variant::Double: { b.setDoubleVal(v.get_double()); break; } case Variant::Bool: { b.setBoolVal(v.get_bool()); break; } case Variant::String: { b.setStringVal(v.get_string().c_str()); break; } case Variant::Dict: { auto vb = b.initDictVal(); to_value_dict(v.get_dict(), vb); break; } case Variant::Array: { auto vb = b.initArrayVal(v.get_array().size()); to_value_array(v.get_array(), vb); break; } case Variant::Null: { b.initNullVal(); break; } default: { assert(false); // LCOV_EXCL_LINE } } } Variant to_variant(capnproto::Value::Reader const& r) { switch (r.which()) { case capnproto::Value::INT_VAL: { return Variant(r.getIntVal()); } case capnproto::Value::DOUBLE_VAL: { return Variant(r.getDoubleVal()); } case capnproto::Value::BOOL_VAL: { return Variant(r.getBoolVal()); } case capnproto::Value::STRING_VAL: { return Variant(r.getStringVal().cStr()); } case capnproto::Value::DICT_VAL: { return Variant(to_variant_map(r.getDictVal())); } case capnproto::Value::ARRAY_VAL: { return Variant(to_variant_array(r.getArrayVal())); } case capnproto::Value::NULL_VAL: { return Variant::null(); } default: { assert(false); // LCOV_EXCL_LINE } } return Variant::null(); // LCOV_EXCL_LINE (stop compiler warning about not returning a value) } void to_value_dict(VariantMap const& vm, capnproto::ValueDict::Builder& b) { auto dict = b.initPairs(vm.size()); int i = 0; for (auto const& pair : vm) { dict[i].setName(pair.first.c_str()); auto val = dict[i].initValue(); to_value(pair.second, val); ++i; } } void to_value_array(VariantArray const& va, capnp::List::Builder& b) { assert(va.size() == b.size()); uint i = 0; for (auto const& el: va) { auto elm_bld = b[i]; to_value(el, elm_bld); ++i; } } VariantMap to_variant_map(capnproto::ValueDict::Reader const& r) { VariantMap vm; auto pairs = r.getPairs(); for (size_t i = 0; i < pairs.size(); ++i) { vm[pairs[i].getName().cStr()] = to_variant(pairs[i].getValue()); } return vm; } VariantArray to_variant_array(capnp::List::Reader const &r) { VariantArray va; for (auto const& el: r) { va.push_back(to_variant(el)); } return va; } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ZmqRegistry.cpp0000644000015301777760000001564112320776161031251 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { /* interface Scope; dictionary MetadataMap; exception NotFoundException { string identity; }; interface Registry { ScopeMetadata get_metadata(string scope_id) throws NotFoundException; MetadataMap list(); ObjectProxy locate(string identity) throws NotFoundException, RegistryException; }; */ ZmqRegistry::ZmqRegistry(ZmqMiddleware* mw_base, string const& endpoint, string const& identity, string const& category, int64_t timeout) : MWObjectProxy(mw_base), ZmqObjectProxy(mw_base, endpoint, identity, category, RequestMode::Twoway, timeout), MWRegistry(mw_base) { } ZmqRegistry::~ZmqRegistry() { } ScopeMetadata ZmqRegistry::get_metadata(std::string const& scope_id) { capnp::MallocMessageBuilder request_builder; auto request = make_request_(request_builder, "get_metadata"); auto in_params = request.initInParams().getAs(); in_params.setIdentity(scope_id.c_str()); auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder); }); auto receiver = future.get(); auto segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); throw_if_runtime_exception(response); auto get_metadata_response = response.getPayload().getAs().getResponse(); switch (get_metadata_response.which()) { case capnproto::Registry::GetMetadataResponse::Response::RETURN_VALUE: { auto md = get_metadata_response.getReturnValue(); VariantMap m = to_variant_map(md); unique_ptr smdi(new ScopeMetadataImpl(m, mw_base())); return ScopeMetadata(ScopeMetadataImpl::create(move(smdi))); } case capnproto::Registry::GetMetadataResponse::Response::NOT_FOUND_EXCEPTION: { auto ex = get_metadata_response.getNotFoundException(); throw NotFoundException("Registry::get_metadata(): no such scope", ex.getIdentity().cStr()); } default: { throw MiddlewareException("Registry::get_metadata(): unknown user exception"); } } } MetadataMap ZmqRegistry::list() { capnp::MallocMessageBuilder request_builder; make_request_(request_builder, "list"); auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder); }); auto receiver = future.get(); auto segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); throw_if_runtime_exception(response); auto list_response = response.getPayload().getAs(); auto list = list_response.getReturnValue().getPairs(); MetadataMap sm; for (size_t i = 0; i < list.size(); ++i) { string scope_id = list[i].getName(); VariantMap m = to_variant_map(list[i].getValue().getDictVal()); unique_ptr smdi(new ScopeMetadataImpl(m, mw_base())); ScopeMetadata d(ScopeMetadataImpl::create(move(smdi))); sm.emplace(make_pair(move(scope_id), move(d))); } return sm; } ObjectProxy ZmqRegistry::locate(std::string const& identity) { capnp::MallocMessageBuilder request_builder; auto request = make_request_(request_builder, "locate"); auto in_params = request.initInParams().getAs(); in_params.setIdentity(identity.c_str()); // locate uses a custom timeout because it needs to potentially fork/exec a scope. int64_t timeout = 1000; // TODO: get timeout from config auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder, timeout); }); auto receiver = future.get(); auto segments = receiver.receive(); capnp::SegmentArrayMessageReader reader(segments); auto response = reader.getRoot(); throw_if_runtime_exception(response); auto locate_response = response.getPayload().getAs().getResponse(); switch (locate_response.which()) { case capnproto::Registry::LocateResponse::Response::RETURN_VALUE: { auto proxy = locate_response.getReturnValue(); auto mw = dynamic_cast(mw_base()); assert(mw); auto zmq_proxy = make_shared(mw, proxy.getEndpoint(), proxy.getIdentity(), proxy.getCategory(), proxy.getTimeout()); return ScopeImpl::create(zmq_proxy, mw->runtime(), identity); } case capnproto::Registry::LocateResponse::Response::NOT_FOUND_EXCEPTION: { auto ex = locate_response.getNotFoundException(); throw NotFoundException("Registry::locate(): no such object", ex.getIdentity().cStr()); } case capnproto::Registry::LocateResponse::Response::REGISTRY_EXCEPTION: { auto ex = locate_response.getRegistryException(); throw RegistryException(ex.getReason().cStr()); } default: { throw MiddlewareException("Registry::locate(): unknown user exception"); } } } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ScopeI.cpp0000644000015301777760000002133712320776161030132 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { /* dictionary ValueDict; interface QueryCtrl; interface Reply; interface Scope { QueryCtrl* search(string query, ValueDict hints, Reply* replyProxy); QueryCtrl* preview(ValueDict result, ValueDict hints, Reply* replyProxy); QueryCtrl* perform_action(ValueDict result, ValueDict hints, string action_id, Reply* replyProxy); QueryCtrl* activate(ValueDict result, ValueDict hints, Reply* replyProxy); }; */ using namespace std::placeholders; ScopeI::ScopeI(ScopeObjectBase::SPtr const& so) : ServantBase(so, { { "search", bind(&ScopeI::search_, this, _1, _2, _3) }, { "preview", bind(&ScopeI::preview_, this, _1, _2, _3) }, { "activate", bind(&ScopeI::activate_, this, _1, _2, _3) }, { "perform_action", bind(&ScopeI::perform_action_, this, _1, _2, _3) } }) { } ScopeI::~ScopeI() { } void ScopeI::search_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r) { auto req = in_params.getAs(); auto query = internal::CannedQueryImpl::create(to_variant_map(req.getQuery())); auto metadata = SearchMetadataImpl::create(to_variant_map(req.getHints())); auto proxy = req.getReplyProxy(); ZmqReplyProxy reply_proxy(new ZmqReply(current.adapter->mw(), proxy.getEndpoint().cStr(), proxy.getIdentity().cStr(), proxy.getCategory().cStr())); auto delegate = dynamic_pointer_cast(del()); assert(delegate); auto ctrl_proxy = dynamic_pointer_cast(delegate->search(query, metadata, reply_proxy, to_info(current))); assert(ctrl_proxy); r.setStatus(capnproto::ResponseStatus::SUCCESS); auto search_response = r.initPayload().getAs(); auto p = search_response.initReturnValue(); p.setEndpoint(ctrl_proxy->endpoint().c_str()); p.setIdentity(ctrl_proxy->identity().c_str()); p.setCategory(ctrl_proxy->category().c_str()); } void ScopeI::activate_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r) { auto req = in_params.getAs(); auto result = ResultImpl::create_result(to_variant_map(req.getResult())); auto metadata = ActionMetadataImpl::create(to_variant_map(req.getHints())); auto proxy = req.getReplyProxy(); ZmqReplyProxy reply_proxy(new ZmqReply(current.adapter->mw(), proxy.getEndpoint().cStr(), proxy.getIdentity().cStr(), proxy.getCategory().cStr())); auto delegate = dynamic_pointer_cast(del()); assert(delegate); auto ctrl_proxy = dynamic_pointer_cast(delegate->activate(result, metadata, reply_proxy, to_info(current))); assert(ctrl_proxy); r.setStatus(capnproto::ResponseStatus::SUCCESS); auto search_response = r.initPayload().getAs(); auto p = search_response.initReturnValue(); p.setEndpoint(ctrl_proxy->endpoint().c_str()); p.setIdentity(ctrl_proxy->identity().c_str()); p.setCategory(ctrl_proxy->category().c_str()); } void ScopeI::perform_action_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r) { auto req = in_params.getAs(); auto result = ResultImpl::create_result(to_variant_map(req.getResult())); auto metadata = ActionMetadataImpl::create(to_variant_map(req.getHints())); auto proxy = req.getReplyProxy(); auto widget_id = req.getWidgetId().cStr(); auto action_id = req.getActionId().cStr(); ZmqReplyProxy reply_proxy(new ZmqReply(current.adapter->mw(), proxy.getEndpoint().cStr(), proxy.getIdentity().cStr(), proxy.getCategory().cStr())); auto delegate = dynamic_pointer_cast(del()); assert(delegate); auto ctrl_proxy = dynamic_pointer_cast(delegate->perform_action(result, metadata, widget_id, action_id, reply_proxy, to_info(current))); assert(ctrl_proxy); r.setStatus(capnproto::ResponseStatus::SUCCESS); auto search_response = r.initPayload().getAs(); auto p = search_response.initReturnValue(); p.setEndpoint(ctrl_proxy->endpoint().c_str()); p.setIdentity(ctrl_proxy->identity().c_str()); p.setCategory(ctrl_proxy->category().c_str()); } void ScopeI::preview_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r) { auto req = in_params.getAs(); auto result = ResultImpl::create_result(to_variant_map(req.getResult())); auto metadata = ActionMetadataImpl::create(to_variant_map(req.getHints())); auto proxy = req.getReplyProxy(); ZmqReplyProxy reply_proxy(new ZmqReply(current.adapter->mw(), proxy.getEndpoint().cStr(), proxy.getIdentity().cStr(), proxy.getCategory().cStr())); auto delegate = dynamic_pointer_cast(del()); assert(delegate); auto ctrl_proxy = dynamic_pointer_cast(delegate->preview(result, metadata, reply_proxy, to_info(current))); assert(ctrl_proxy); r.setStatus(capnproto::ResponseStatus::SUCCESS); auto search_response = r.initPayload().getAs(); auto p = search_response.initReturnValue(); p.setEndpoint(ctrl_proxy->endpoint().c_str()); p.setIdentity(ctrl_proxy->identity().c_str()); p.setCategory(ctrl_proxy->category().c_str()); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/zmq_middleware/ZmqReply.cpp0000644000015301777760000000576612320776161030543 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { /* interface Reply { void push(VariantMap result); // oneway void finished(ListenerBase::Reason reason, string error_message); // oneway }; */ ZmqReply::ZmqReply(ZmqMiddleware* mw_base, string const& endpoint, string const& identity, string const& category) : MWObjectProxy(mw_base), ZmqObjectProxy(mw_base, endpoint, identity, category, RequestMode::Oneway), MWReply(mw_base) { } ZmqReply::~ZmqReply() { } void ZmqReply::push(VariantMap const& result) { capnp::MallocMessageBuilder request_builder; auto request = make_request_(request_builder, "push"); auto in_params = request.initInParams().getAs(); auto resultBuilder = in_params.getResult(); to_value_dict(result, resultBuilder); auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder); }); future.wait(); } void ZmqReply::finished(ListenerBase::Reason reason, string const& error_message) { capnp::MallocMessageBuilder request_builder; auto request = make_request_(request_builder, "finished"); auto in_params = request.initInParams().getAs(); capnproto::Reply::FinishedReason r; switch (reason) { case ListenerBase::Finished: { r = capnproto::Reply::FinishedReason::FINISHED; break; } case ListenerBase::Cancelled: { r = capnproto::Reply::FinishedReason::CANCELLED; break; } case ListenerBase::Error: { r = capnproto::Reply::FinishedReason::ERROR; in_params.setError(error_message); break; } default: { assert(false); } } in_params.setReason(r); auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder); }); future.wait(); } } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ActivationQueryBaseImpl.cpp0000644000015301777760000000201412320776161030477 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include namespace unity { namespace scopes { namespace internal { ActivationResponse ActivationQueryBaseImpl::activate() { return ActivationResponse(ActivationResponse::Status::NotHandled); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ScopeBaseImpl.cpp0000644000015301777760000000207012320776161026423 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include namespace unity { namespace scopes { namespace internal { void ScopeBaseImpl::set_scope_directory(std::string const &path) { scope_directory_ = path; } std::string ScopeBaseImpl::scope_directory() const { return scope_directory_; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ActionMetadataImpl.cpp0000644000015301777760000000364612320776161027447 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { namespace internal { ActionMetadataImpl::ActionMetadataImpl(std::string const& locale, std::string const& form_factor) : QueryMetadataImpl(locale, form_factor) { } ActionMetadataImpl::ActionMetadataImpl(VariantMap const& var) : QueryMetadataImpl(var) { auto it = find_or_throw("ActionMetadataImpl()", var, "scope_data"); scope_data_ = it->second; } std::string ActionMetadataImpl::metadata_type() const { static const std::string t("action_metadata"); return t; } void ActionMetadataImpl::set_scope_data(Variant const& data) { scope_data_ = data; } Variant ActionMetadataImpl::scope_data() const { return scope_data_; } void ActionMetadataImpl::serialize(VariantMap &var) const { QueryMetadataImpl::serialize(var); var["scope_data"] = Variant(scope_data_); } VariantMap ActionMetadataImpl::serialize() const { VariantMap vm; serialize(vm); return vm; } ActionMetadata ActionMetadataImpl::create(VariantMap const& var) { return ActionMetadata(new ActionMetadataImpl(var)); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/PreviewReplyObject.cpp0000644000015301777760000000602612320776161027526 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include #include #include #include #include #include #include // TODO: remove this once logging is added using namespace std; using namespace unity::scopes::internal; namespace unity { namespace scopes { namespace internal { PreviewReplyObject::PreviewReplyObject(PreviewListenerBase::SPtr const& receiver, RuntimeImpl const* runtime, std::string const& scope_id) : ReplyObject(std::static_pointer_cast(receiver), runtime, scope_id), receiver_(receiver) { assert(receiver_); } PreviewReplyObject::~PreviewReplyObject() { } bool PreviewReplyObject::process_data(VariantMap const& data) { auto it = data.find("columns"); if (it != data.end()) { ColumnLayoutList list; const VariantArray arr = it->second.get_array(); for (auto const& pl: arr) { list.emplace_back(ColumnLayoutImpl::create(pl.get_dict())); } // basic check for consistency of layouts try { ColumnLayoutImpl::validate_layouts(list); } catch (unity::LogicException const &e) { throw unity::LogicException("PreviewReplyObject::process_data(): Failed to validate layouts"); } receiver_->push(list); } it = data.find("widgets"); if (it != data.end() && it->second.which() == Variant::Type::Array) { VariantArray arr = it->second.get_array(); PreviewWidgetList list; for (unsigned i = 0; i < arr.size(); i++) { list.emplace_back(PreviewWidgetImpl::create(arr[i].get_dict())); } receiver_->push(list); } auto data_it = data.find("preview-data"); if (data_it != data.end() && data_it->second.which() == Variant::Type::Dict) { VariantMap data = data_it->second.get_dict(); for (auto it = data.begin(); it != data.end(); ++it) { receiver_->push(it->first, it->second); } } return false; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/MWReply.cpp0000644000015301777760000000176112320776161025302 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include using namespace std; namespace unity { namespace scopes { namespace internal { MWReply::MWReply(MiddlewareBase* mw_base) : MWObjectProxy(mw_base) { } MWReply::~MWReply() { } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/MWStateReceiver.cpp0000644000015301777760000000201112320776161026741 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include namespace unity { namespace scopes { namespace internal { MWStateReceiver::MWStateReceiver(MiddlewareBase* mw_base) : MWObjectProxy(mw_base) { } MWStateReceiver::~MWStateReceiver() { } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/ConfigBase.cpp0000644000015301777760000000502712320776161025742 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { // If configfile is the empty string, we create a default instance that returns "Zmq" for the middleware // and throws for the other methods. ConfigBase::ConfigBase(string const& configfile) : parser_(nullptr), configfile_(configfile) { if (!configfile.empty()) { parser_ = make_shared(configfile.c_str()); } } ConfigBase::~ConfigBase() { } util::IniParser::SPtr ConfigBase::parser() const { if (!parser_) { throw LogicException("ConfigBase: no parser available with default config"); } return parser_; } string ConfigBase::get_string(string const& group, string const& key) const { string val = parser()->get_string(group, key); if (val.empty()) { throw_ex("Illegal empty value for " + key); } return val; } string ConfigBase::get_optional_string(string const& group, string const& key) const { try { return parser()->get_string(group, key); } catch (unity::LogicException const&) { return string(); } } string ConfigBase::get_middleware(string const& group, string const& key) const { if (!parser_) { return "Zmq"; } string val = get_string(group, key); if (val != "Zmq" && val != "REST") { throw_ex("Illegal value for " + key + ": \"" + val + "\": legal values are \"Zmq\" and \"REST\""); } return val; } void ConfigBase::throw_ex(string const& reason) const { string s = "\"" + configfile_ + "\": " + reason; throw ConfigException(s); } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/FilterOptionImpl.cpp0000644000015301777760000000220012320776161027170 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include namespace unity { namespace scopes { namespace internal { FilterOptionImpl::FilterOptionImpl(std::string const& id, std::string const& label) : id_(id), label_(label) { } std::string FilterOptionImpl::id() const { return id_; } std::string FilterOptionImpl::label() const { return label_; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/internal/MiddlewareBase.cpp0000644000015301777760000000220512320776161026605 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace std; namespace unity { namespace scopes { namespace internal { MiddlewareBase::MiddlewareBase(RuntimeImpl* runtime) : runtime_(runtime) { assert(runtime); } MiddlewareBase::~MiddlewareBase() { } RuntimeImpl* MiddlewareBase::runtime() const noexcept { return runtime_; } } // namespace internal } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/Scope.cpp0000644000015301777760000000157612320776161023204 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include namespace unity { namespace scopes { //! @cond Scope::Scope() { } Scope::~Scope() { } //! @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/ColumnLayout.cpp0000644000015301777760000000632412320776161024562 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { /*! \class ColumnLayout \brief Defines a layout for preview widgets with given column setup. ColumnLayout defines how widgets should be laid out on a display with a given number of columns. In typical use cases, a scope creates ColumnLayout instances for all supported displays (number of columns), and defines for every instance what widgets belong to which columns. The shell uses the layout that is most appropriate for the device in use. Column layout definitions are optional. However, we recommend that scopes define layouts for the best visual appearance. An example of creating two layouts, one for a screen with one column and and one for a screen with two columns. \code{.cpp} void MyPreview::run(PreviewReplyProxy const& reply) // layout definition for a screen with just 1 column ColumnLayout layout1col(1); layout1col.add_column({"art", "header", "actions"}); // all widgets in a single column // layout definition for a screen with 2 columns ColumnLayout layout2col(2); layout2col.add_column({"art"}); // widget in 1st column layout2col.add_column({"header", "actions"}); // widgets in 2nd column reply->register_layout({layout1col, layout2col}); // create widgets PreviewWidget w1("art", "image"); ... \endcode */ ColumnLayout::ColumnLayout(int num_of_columns) : p(new internal::ColumnLayoutImpl(num_of_columns)) { } /// @cond ColumnLayout::ColumnLayout(internal::ColumnLayoutImpl *impl) : p(impl) { } ColumnLayout::ColumnLayout(ColumnLayout const& other) : p(new internal::ColumnLayoutImpl(*(other.p))) { } ColumnLayout::ColumnLayout(ColumnLayout&&) = default; ColumnLayout& ColumnLayout::operator=(ColumnLayout const& other) { if (this != &other) { p.reset(new internal::ColumnLayoutImpl(*(other.p))); } return *this; } ColumnLayout::~ColumnLayout() = default; ColumnLayout& ColumnLayout::operator=(ColumnLayout&&) = default; VariantMap ColumnLayout::serialize() const { return p->serialize(); } /// @endcond void ColumnLayout::add_column(std::vector widget_ids) { return p->add_column(widget_ids); } int ColumnLayout::size() const noexcept { return p->size(); } int ColumnLayout::number_of_columns() const noexcept { return p->number_of_columns(); } std::vector ColumnLayout::column(int index) const { return p->column(index); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/QueryCtrl.cpp0000644000015301777760000000162212320776161024055 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include namespace unity { namespace scopes { //! @cond QueryCtrl::QueryCtrl() { } QueryCtrl::~QueryCtrl() { } //! @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/Registry.cpp0000644000015301777760000000163312320776161023735 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include namespace unity { namespace scopes { /// @cond Registry::Registry() = default; Registry::~Registry() = default; /// @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/ActivationResponse.cpp0000644000015301777760000000433712320776161025751 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include namespace unity { namespace scopes { ActivationResponse::ActivationResponse(Status status) : p(new internal::ActivationResponseImpl(status)) { } ActivationResponse::ActivationResponse(CannedQuery const& query) : p(new internal::ActivationResponseImpl(query)) { } /// @cond ActivationResponse::ActivationResponse(internal::ActivationResponseImpl* pimpl) : p(pimpl) { } ActivationResponse::~ActivationResponse() = default; ActivationResponse::ActivationResponse(ActivationResponse const& other) : p(new internal::ActivationResponseImpl(*other.p)) { } ActivationResponse::ActivationResponse(ActivationResponse&&) = default; ActivationResponse& ActivationResponse::operator=(ActivationResponse const& other) { if (this != &other) { p.reset(new internal::ActivationResponseImpl(*other.p)); } return *this; } ActivationResponse& ActivationResponse::operator=(ActivationResponse&&) = default; VariantMap ActivationResponse::serialize() const { return p->serialize(); } /// @endcond void ActivationResponse::set_scope_data(Variant const& data) { p->set_scope_data(data); } ActivationResponse::Status ActivationResponse::status() const { return p->status(); } Variant ActivationResponse::scope_data() const { return p->scope_data(); } CannedQuery ActivationResponse::query() const { return p->query(); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/CategorisedResult.cpp0000644000015301777760000000374512320776161025563 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include namespace unity { namespace scopes { //! @cond CategorisedResult::CategorisedResult(Category::SCPtr category) : Result(new internal::CategorisedResultImpl(category)) { } CategorisedResult::CategorisedResult(internal::ResultImpl* impl) : Result(impl) { } CategorisedResult::CategorisedResult(CategorisedResult&&) = default; CategorisedResult& CategorisedResult::operator=(CategorisedResult&&) = default; CategorisedResult::CategorisedResult(CategorisedResult const& other) : Result(new internal::CategorisedResultImpl(*(other.fwd()))) { } CategorisedResult& CategorisedResult::operator=(CategorisedResult const& other) { if (this != &other) { p.reset(new internal::CategorisedResultImpl(*(other.fwd()))); } return *this; } //! @endcond void CategorisedResult::set_category(Category::SCPtr category) { fwd()->set_category(category); } Category::SCPtr CategorisedResult::category() const { return fwd()->category(); } internal::CategorisedResultImpl* CategorisedResult::fwd() const { return dynamic_cast(p.get()); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/Link.cpp0000644000015301777760000000305512320776161023022 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { Link::Link(std::string const& label, CannedQuery const& query) : p(new internal::LinkImpl(label, query)) { } /// @cond Link::Link(VariantMap const& variant_map) : p(new internal::LinkImpl(variant_map)) { } Link::Link(Link&&) = default; Link::Link(Link const& other) : p(new internal::LinkImpl(*(other.p))) { } Link& Link::operator=(Link const& other) { if (this != &other) { p.reset(new internal::LinkImpl(*(other.p))); } return *this; } Link::~Link() = default; VariantMap Link::serialize() const { return p->serialize(); } /// @endcond std::string Link::label() const { return p->label(); } CannedQuery Link::query() const { return p->query(); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/PreviewReply.cpp0000644000015301777760000000165712320776161024570 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include namespace unity { namespace scopes { /// @cond PreviewReply::PreviewReply() = default; PreviewReply::~PreviewReply() = default; /// @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/ActivationQueryBase.cpp0000644000015301777760000000235112320776161026045 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { /// @cond ActivationQueryBase::ActivationQueryBase() : QueryBase(), p(new internal::ActivationQueryBaseImpl()) { } ActivationQueryBase::~ActivationQueryBase() { } /// @endcond void ActivationQueryBase::cancelled() { //default implementation does nothing } ActivationResponse ActivationQueryBase::activate() { return p->activate(); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/SearchQueryBase.cpp0000644000015301777760000000556612320776161025164 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; namespace unity { namespace scopes { /// @cond SearchQueryBase::SearchQueryBase() : QueryBase() { } SearchQueryBase::~SearchQueryBase() { } /// @endcond /// @cond // These methods are documented in the header. The @cond is here to suppress // a bogus warning from doxygen about undocumented methods. (Doxygen gets // confused by the typedef for ScopeProxy.) QueryCtrlProxy SearchQueryBase::subsearch(ScopeProxy const& scope, string const& query_string, SearchListenerBase::SPtr const& reply) { return p->subsearch(scope, query_string, reply); } QueryCtrlProxy SearchQueryBase::subsearch(ScopeProxy const& scope, std::string const& query_string, FilterState const& filter_state, SearchListenerBase::SPtr const& reply) { return p->subsearch(scope, query_string, filter_state, reply); } QueryCtrlProxy SearchQueryBase::subsearch(ScopeProxy const& scope, std::string const& query_string, std::string const& department_id, FilterState const& filter_state, SearchListenerBase::SPtr const& reply) { return p->subsearch(scope, query_string, department_id, filter_state, reply); } QueryCtrlProxy SearchQueryBase::subsearch(ScopeProxy const& scope, std::string const& query_string, std::string const& department_id, FilterState const& filter_state, SearchMetadata const& hints, SearchListenerBase::SPtr const& reply) { return p->subsearch(scope, query_string, department_id, filter_state, hints, reply); } /// @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/CannedQuery.cpp0000644000015301777760000000507712320776161024351 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { CannedQuery::CannedQuery(std::string const& scope_id) : p(new internal::CannedQueryImpl(scope_id)) { } CannedQuery::CannedQuery(std::string const& scope_id, std::string const& query_str, std::string const& department_id) : p(new internal::CannedQueryImpl(scope_id, query_str, department_id)) { } /// @cond CannedQuery::CannedQuery(CannedQuery const &other) : p(new internal::CannedQueryImpl(*(other.p))) { } CannedQuery::CannedQuery(internal::CannedQueryImpl *impl) : p(impl) { } CannedQuery::CannedQuery(CannedQuery&&) = default; CannedQuery::~CannedQuery() = default; CannedQuery& CannedQuery::operator=(CannedQuery const& other) { if (this != &other) { p.reset(new internal::CannedQueryImpl(*(other.p))); } return *this; } CannedQuery& CannedQuery::operator=(CannedQuery&&) = default; VariantMap CannedQuery::serialize() const { return p->serialize(); } /// @endcond void CannedQuery::set_department_id(std::string const& dep_id) { p->set_department_id(dep_id); } void CannedQuery::set_query_string(std::string const& query_str) { p->set_query_string(query_str); } void CannedQuery::set_filter_state(FilterState const& filter_state) { p->set_filter_state(filter_state); } std::string CannedQuery::scope_id() const { return p->scope_id(); } std::string CannedQuery::department_id() const { return p->department_id(); } std::string CannedQuery::query_string() const { return p->query_string(); } FilterState CannedQuery::filter_state() const { return p->filter_state(); } std::string CannedQuery::to_string() const { return p->to_string(); } CannedQuery CannedQuery::from_string() { return internal::CannedQueryImpl::from_string(); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/FilterState.cpp0000644000015301777760000000337012320776161024353 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include namespace unity { namespace scopes { FilterState::FilterState() : p(new internal::FilterStateImpl()) { } /// @cond FilterState::FilterState(FilterState const& other) : p(new internal::FilterStateImpl(*(other.p))) { } FilterState::FilterState(internal::FilterStateImpl *pimpl) : p(pimpl) { } FilterState::~FilterState() = default; FilterState::FilterState(FilterState &&) = default; FilterState& FilterState::operator=(FilterState &&) = default; FilterState& FilterState::operator=(FilterState const& other) { if (this != &other) { p.reset(new internal::FilterStateImpl(*(other.p))); } return *this; } VariantMap FilterState::serialize() const { return p->serialize(); } /// @endcond bool FilterState::has_filter(std::string const& id) const { return p->has_filter(id); } void FilterState::remove(std::string const& id) { p->remove(id); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/SearchReply.cpp0000644000015301777760000000165212320776161024347 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include namespace unity { namespace scopes { /// @cond SearchReply::SearchReply() = default; SearchReply::~SearchReply() = default; /// @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/Category.cpp0000644000015301777760000000310712320776161023700 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { //! @cond Category::Category(std::string const& id, std::string const& title, std::string const &icon, CategoryRenderer const& renderer_template) : p(new internal::CategoryImpl(id, title, icon, renderer_template)) { } Category::Category(VariantMap const& variant_map) : p(new internal::CategoryImpl(variant_map)) { } Category::~Category() { } std::string Category::id() const { return p->id(); } std::string Category::icon() const { return p->icon(); } CategoryRenderer const& Category::renderer_template() const { return p->renderer_template(); } std::string Category::title() const { return p->title(); } VariantMap Category::serialize() const { return p->serialize(); } //! @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/Object.cpp0000644000015301777760000000160312320776161023330 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include namespace unity { namespace scopes { //! @cond Object::Object() { } Object::~Object() { } //! @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/QueryBase.cpp0000644000015301777760000000235712320776161024031 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace std; namespace unity { namespace scopes { /// @cond QueryBase::QueryBase() : p(new internal::QueryBaseImpl) { } QueryBase::~QueryBase() { } void QueryBase::cancel() { p->cancel(); // Forward cancel to subqueries cancelled(); // Inform this query that it was cancelled } /// @endcond void QueryBase::set_metadata(SearchMetadata const& metadata) { p->set_metadata(metadata); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/ActionMetadata.cpp0000644000015301777760000000401212320776161024775 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { ActionMetadata::ActionMetadata(std::string const& locale, std::string const& form_factor) : p(new internal::ActionMetadataImpl(locale, form_factor)) { } /// @cond ActionMetadata::ActionMetadata(internal::ActionMetadataImpl *impl) : p(impl) { } ActionMetadata::ActionMetadata(ActionMetadata const& other) : p(new internal::ActionMetadataImpl(*(other.p.get()))) { } ActionMetadata::ActionMetadata(ActionMetadata&&) = default; ActionMetadata::~ActionMetadata() { } ActionMetadata& ActionMetadata::operator=(ActionMetadata const &other) { if (this != &other) { p.reset(new internal::ActionMetadataImpl(*(other.p.get()))); } return *this; } ActionMetadata& ActionMetadata::operator=(ActionMetadata&&) = default; VariantMap ActionMetadata::serialize() const { return p->serialize(); } /// @endcond std::string ActionMetadata::locale() const { return p->locale(); } std::string ActionMetadata::form_factor() const { return p->form_factor(); } void ActionMetadata::set_scope_data(Variant const& data) { p->set_scope_data(data); } Variant ActionMetadata::scope_data() const { return p->scope_data(); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/VariantBuilder.cpp0000644000015301777760000000335412320776161025042 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { VariantBuilder::VariantBuilder() : p(new internal::VariantBuilderImpl()) { } VariantBuilder::VariantBuilder(VariantBuilder const& other) : p(new internal::VariantBuilderImpl(*(other.p))) { } VariantBuilder::VariantBuilder(VariantBuilder&&) = default; VariantBuilder& VariantBuilder::operator=(VariantBuilder&&) = default; VariantBuilder& VariantBuilder::operator=(VariantBuilder const& other) { if (this != &other) { p.reset(new internal::VariantBuilderImpl(*(other.p))); } return *this; } VariantBuilder::~VariantBuilder() = default; void VariantBuilder::add_tuple(std::initializer_list> const& tuple) { p->add_tuple(tuple); } void VariantBuilder::add_tuple(std::vector> const& tuple) { p->add_tuple(tuple); } Variant VariantBuilder::end() { return p->end(); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/FilterBase.cpp0000644000015301777760000000232212320776161024141 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { /// @cond FilterBase::FilterBase(internal::FilterBaseImpl *pimpl) : p(pimpl) { } VariantMap FilterBase::serialize() const { return p->serialize(); } FilterBase::~FilterBase() = default; /// @endcond std::string FilterBase::id() const { return p->id(); } std::string FilterBase::filter_type() const { return p->filter_type(); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/Version.cpp0000644000015301777760000000211012320776161023541 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include namespace unity { namespace scopes { int major_version() { return UNITY_SCOPES_VERSION_MAJOR; } int minor_version() { return UNITY_SCOPES_VERSION_MINOR; } int micro_version() { return UNITY_SCOPES_VERSION_MICRO; } char const* version_string() { return UNITY_SCOPES_VERSION_STRING; } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/Result.cpp0000644000015301777760000000556612320776161023414 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { //! @cond Result::Result(internal::ResultImpl* impl) : p(impl) { } Result::Result(const VariantMap &variant_map) : p(new internal::ResultImpl(variant_map)) { } Result::Result(Result const& other) : p(new internal::ResultImpl(*(other.p))) { } Result::~Result() { } Result& Result::operator=(Result const& other) { if (this != &other) { p.reset(new internal::ResultImpl(*(other.p))); } return *this; } Result::Result(Result&&) = default; Result& Result::operator=(Result&&) = default; void Result::store(Result const& other, bool intercept_activation) { p->store(other, intercept_activation); } bool Result::has_stored_result() const { return p->has_stored_result(); } Result Result::retrieve() const { return p->retrieve(); } void Result::set_uri(std::string const& uri) { p->set_uri(uri); } void Result::set_title(std::string const& title) { p->set_title(title); } void Result::set_art(std::string const& image) { p->set_art(image); } void Result::set_dnd_uri(std::string const& dnd_uri) { p->set_dnd_uri(dnd_uri); } void Result::set_intercept_activation() { p->set_intercept_activation(); } bool Result::direct_activation() const { return p->direct_activation(); } ScopeProxy Result::target_scope_proxy() const { return p->target_scope_proxy(); } Variant& Result::operator[](std::string const& key) { return (*p)[key]; } Variant const& Result::operator[](std::string const& key) const { return p->value(key); } std::string Result::uri() const noexcept { return p->uri(); } std::string Result::title() const noexcept { return p->title(); } std::string Result::art() const noexcept { return p->art(); } std::string Result::dnd_uri() const noexcept { return p->dnd_uri(); } bool Result::contains(std::string const& key) const { return p->contains(key); } Variant const& Result::value(std::string const& key) const { return p->value(key); } VariantMap Result::serialize() const { return p->serialize(); } //! @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/ScopeMetadata.cpp0000644000015301777760000000554012320776161024640 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include using namespace std; namespace unity { namespace scopes { //! @cond ScopeMetadata::ScopeMetadata(unique_ptr impl) : p(move(impl)) { // The only way to create a ScopeMetadata instance is to first intialize // a ScopeMetadataImpl, fill it in, and then call this constructor. // We check here that all mandatory fields are present. If not // we have an internal logic error. assert(!p->scope_id().empty()); assert(p->proxy()); assert(!p->display_name().empty()); assert(!p->description().empty()); assert(!p->author().empty()); } ScopeMetadata::ScopeMetadata(ScopeMetadata const& other) : p(new internal::ScopeMetadataImpl(*(other.p))) { } ScopeMetadata::ScopeMetadata(ScopeMetadata&&) = default; ScopeMetadata::~ScopeMetadata() { } ScopeMetadata& ScopeMetadata::operator=(ScopeMetadata const& other) { if (this != &other) { p.reset(new internal::ScopeMetadataImpl(*(other.p))); } return *this; } ScopeMetadata& ScopeMetadata::operator=(ScopeMetadata&&) = default; string ScopeMetadata::scope_id() const { return p->scope_id(); } ScopeProxy ScopeMetadata::proxy() const { return p->proxy(); } string ScopeMetadata::display_name() const { return p->display_name(); } string ScopeMetadata::description() const { return p->description(); } string ScopeMetadata::author() const { return p->author(); } string ScopeMetadata::art() const { return p->art(); } string ScopeMetadata::icon() const { return p->icon(); } string ScopeMetadata::search_hint() const { return p->search_hint(); } string ScopeMetadata::hot_key() const { return p->hot_key(); } bool ScopeMetadata::invisible() const { return p->invisible(); } VariantMap ScopeMetadata::appearance_attributes() const { return p->appearance_attributes(); } std::string ScopeMetadata::scope_directory() const { return p->scope_directory(); } VariantMap ScopeMetadata::serialize() const { return p->serialize(); } //! @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/SearchMetadata.cpp0000644000015301777760000000536512320776161025001 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { SearchMetadata::SearchMetadata(std::string const& locale, std::string const& form_factor) : p(new internal::SearchMetadataImpl(locale, form_factor)) { } SearchMetadata::SearchMetadata(int cardinality, std::string const& locale, std::string const& form_factor) : p(new internal::SearchMetadataImpl(cardinality, locale, form_factor)) { } /// @cond SearchMetadata::SearchMetadata(internal::SearchMetadataImpl *impl) : p(impl) { } SearchMetadata::SearchMetadata(SearchMetadata const& other) : p(new internal::SearchMetadataImpl(*(other.p))) { } SearchMetadata::SearchMetadata(SearchMetadata&&) = default; SearchMetadata& SearchMetadata::operator=(SearchMetadata const &other) { if (this != &other) { p.reset(new internal::SearchMetadataImpl(*(other.p))); } return *this; } SearchMetadata& SearchMetadata::operator=(SearchMetadata&&) = default; SearchMetadata::~SearchMetadata() = default; VariantMap SearchMetadata::serialize() const { return p->serialize(); } /// @endcond std::string SearchMetadata::locale() const { return p->locale(); } std::string SearchMetadata::form_factor() const { return p->form_factor(); } void SearchMetadata::set_cardinality(int cardinality) { p->set_cardinality(cardinality); } int SearchMetadata::cardinality() const { return p->cardinality(); } void SearchMetadata::set_hint(std::string const& key, Variant const& value) { p->hint(key) = value; } VariantMap SearchMetadata::hints() const { return p->hints(); } Variant& SearchMetadata::operator[](std::string const& key) { return p->hint(key); } Variant const& SearchMetadata::operator[](std::string const& key) const { // force const hint() method return static_cast(p.get())->hint(key); } bool SearchMetadata::contains_hint(std::string const& key) const { return p->contains_hint(key); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/PreviewWidget.cpp0000644000015301777760000002734712320776161024724 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { /*! \class PreviewWidget \brief A widget for a preview. This class describes an individual widget used when constructing a preview for a result item. Note that the data that applies to particular widget types is likely to change with different major versions of Unity; therefore, attributes are of type Variant, that is, loosely typed. When Unity requests a preview for a particular result, the scope is expected to construct the preview by instantiating a PreviewWidget. Each widget has a free-form id, a type, and a number of attributes whose names and types depend on the specific widget type (see \link previewwidgets Preview Widgets\endlink). The attribute values can either be filled in directly before pushing the widget to Unity (using add_attribute_value()), or they can be mapped from a result field in a similar fashion to the components mapping when specifying a CategoryRenderer (see add_attribute_mapping()). When using add_attribute_mapping(), the corresponding attribute need not be present in the result; instead, its value can be pushed later using the PreviewReply::push() method, which accepts the name of the field and its value as a Variant. Here is an example that creates a preview and illustrates three ways to associate a preview widget attribute with its value: \code{.cpp} void MyPreview::run(PreviewReplyProxy const& reply) { PreviewWidget w1("img", "image"); // directly specify source URI for the image widget w1.add_attribute_value("source", Variant("http://www.example.org/graphics.png")); PreviewWidget w2("hdr", "header"); // the result associated with this preview already had a title specified, so we'll just map it to the preview widget w2.add_attribute_mapping("title", "title"); // description is not present in the result, but we'll push it later w2.add_attribute_mapping("summary", "description"); PreviewWidgetList widgets; widgets.push_back(w1); widgets.push_back(w2); reply->push(widgets); // do a costly database lookup for the description std::string description = fetch_description(result.uri()); reply->push("description", Variant(description)); } \endcode */ /** \page previewwidgets Preview widget types \section previewtypes Recognized preview widget types The following widget types are recognized by Unity: \arg \c audio \arg \c video \arg \c image \arg \c gallery \arg \c header \arg \c actions \arg \c progress \arg \c text \arg \c rating-input \arg \c reviews \subsection audio audio widget The audio widget displays a list of tracks with play/pause controls. List of attributes: \arg \c tracks A composite attribute containing an array of tuples, where each tuple has up to four fields: \c title (mandatory string), \c subtitle (optional string), \c source (mandatory URI), and \c length (optional integer specifying the track length in seconds) You can construct composite attributes with unity::scopes::VariantBuilder: \code{.cpp} { PreviewWidget w1("tracks", "audio"); VariantBuilder builder; builder.add_tuple({ {"title", Variant("Track #1")}, {"source", Variant("file:///tmp/song1.mp3")}, {"length", Variant(194)} }); builder.add_tuple({ {"title", Variant("Track #2")}, {"source", Variant("file:///tmp/song2.mp3")}, {"length", Variant(207)} }); w1.add_attribute_value("tracks", builder.end()); ... } \endcode \subsection video video widget The video widget displays a still from a video and allows playing the video. List of attributes: \arg \c source A URI pointing to the video \arg \c screenshot A URI pointing to a screenshot of the video (optional) \code{.cpp} { PreviewWidget w1("video1", "video"); w1.add_attribute_value("source", Variant("file:///tmp/video1.mp4")); ... } \endcode \subsection image image widget The image widget displays a single image. List of attributes: \arg \c source A URI pointing to the image \arg \c zoomable A boolean specifying whether the image is zoomable (default: \c false) \code{.cpp} { PreviewWidget w1("img1", "image"); w1.add_attribute_value("source", Variant("file:///tmp/image.jpg")); ... } \endcode \subsection gallery gallery widget The gallery widget displays a set of images. List of attributes: \arg \c sources An array of image URIs \code{.cpp} { PreviewWidget w1("gal", "gallery"); VariantArray arr; arr.push_back(Variant("file:///tmp/image1.jpg")); arr.push_back(Variant("file:///tmp/image2.jpg")); arr.push_back(Variant("file:///tmp/image3.jpg")); w1.add_attribute_value("sources", Variant(arr)); ... } \endcode \subsection header header widget The header widget displays basic infomation about the result. List of attributes: \arg \c title A string specifying the title \arg \c subtitle A string specifying the subtitle \arg \c mascot A URI specifying the mascot \arg \c emblem A URI specifying the emblem \code{.cpp} { PreviewWidget w1("hdr", "header"); w1.add_attribute_value("title", Variant("Result item")); w1.add_attribute_value("mascot", Variant("file:///tmp/mascot.png")); ... } \endcode \subsection actions actions widget The actions widget displays one or more buttons. List of attributes: \arg \c actions A composite attribute containing an array of tuples, where each tuple has at least these fields: \c id (a mandatory string that is passed to unity::scopes::ScopeBase::activate_preview_action()), \c label (mandatory string), and \c icon (optional URI). You can construct composite attributes with unity::scopes::VariantBuilder: \code{.cpp} { PreviewWidget w1("buttons", "actions"); VariantBuilder builder; builder.add_tuple({ {"id", Variant("open")}, {"label", Variant("Open")} }); builder.add_tuple({ {"id", Variant("download")}, {"label", Variant("Download")} }); w1.add_attribute_value("actions", builder.end()); ... } \endcode \subsection progress progress widget The progress widget displays the progress of an action, such as download progress. On completion, the scope receives a preview action activation with the id \c "finished" or \c "failed", depending on the outcome of the operation. List of attributes: \arg \c source A tuple with keys understood by a progress provider \code{.cpp} { PreviewWidget w1("download", "progress"); VariantMap tuple; tuple["dbus-name"] = "com.canonical.DownloadManager"; tuple["dbus-object"] = "/com/canonical/download/obj1"; w1.add_attribute_value("source", Variant(tuple)); ... } \endcode \subsection text text widget A text widget can be used for text of any length (without formatting). List of attributes: \arg \c title Optional string \arg \c text A string containing the text \code{.cpp} { PreviewWidget w1("summary", "text"); w1.add_attribute_value("text", Variant("Lorem Ipsum ...")); ... } \endcode \subsection rating-input rating-input widget The rating-input widget allows users to rate content. It consists of two types of widget: a star-based rating and an input field for the user to enter his/her review. It is possible to hide each widget as well as to require them to be filled in. When a user presses the "Send" button, the scope receives a preview action activation with the id \c "rated". List of attributes: \arg \c rating-label String for the star-based rating (default: "Rate this") \arg \c review-label String for the review input (default: "Add a review") \arg \c submit-label String for the confirmation button (default: "Send") \arg \c rating-icon-empty URI for an empty rating icon \arg \c rating-icon-full URI for a full rating icon \arg \c visible String specifying which of the two widgets are visible (\c "rating", \c "review" or default:\c "both") \arg \c required String specifying which of the two widgets are required to be filled in (\c "rating", \c "review" or default:\c "both") \code{.cpp} { PreviewWidget w1("rating", "rating-input"); w1.add_attribute_value("visible", Variant("rating")); w1.add_attribute_value("required", Variant("rating")); w1.add_attribute_value("rating-icon-empty", Variant("file:///tmp/star-empty.svg")); w1.add_attribute_value("rating-icon-full", Variant("file:///tmp/star-full.svg")); ... } \endcode \subsection reviews reviews widget The reviews widget is used to display previously-rated content. List of attributes: \arg \c rating-icon-empty URI for an empty rating icon \arg \c rating-icon-half URI for an half-full rating icon \arg \c rating-icon-full URI for a full rating icon \arg \c reviews A composite attribute containing an array of tuples, where each tuple has up to three fields: \c rating (optional integer specifying the number of stars), \c author (mandatory string) and \c review (optional string). You can construct composite attributes with unity::scopes::VariantBuilder: \code{.cpp} { PreviewWidget w1("summary", "reviews"); w1.add_attribute_value("rating-icon-empty", Variant("file:///tmp/star-empty.svg")); w1.add_attribute_value("rating-icon-full", Variant("file:///tmp/star-full.svg")); VariantBuilder builder; builder.add_tuple({ {"author", Variant("John Doe")}, {"rating", Variant(3)} }); builder.add_tuple({ {"author", Variant("Mr. Smith")}, {"rating", Variant(5)} }); w1.add_attribute_value("reviews", builder.end()); ... } \endcode */ //! @cond PreviewWidget::PreviewWidget(std::string const& definition) : p(new internal::PreviewWidgetImpl(definition)) { } PreviewWidget::PreviewWidget(std::string const& id, std::string const &widget_type) : p(new internal::PreviewWidgetImpl(id, widget_type)) { } PreviewWidget::PreviewWidget(internal::PreviewWidgetImpl *impl) : p(impl) { } PreviewWidget::PreviewWidget(PreviewWidget const& other) : p(new internal::PreviewWidgetImpl(*(other.p))) { } PreviewWidget::PreviewWidget(PreviewWidget&&) = default; PreviewWidget& PreviewWidget::operator=(PreviewWidget&&) = default; PreviewWidget::~PreviewWidget() = default; PreviewWidget& PreviewWidget::operator=(PreviewWidget const& other) { if (this != &other) { p.reset(new internal::PreviewWidgetImpl(*(other.p))); } return *this; } VariantMap PreviewWidget::serialize() const { return p->serialize(); } void PreviewWidget::add_attribute_value(std::string const& key, Variant const& value) { p->add_attribute_value(key, value); } void PreviewWidget::add_attribute_mapping(std::string const& key, std::string const& field_name) { p->add_attribute_mapping(key, field_name); } std::string PreviewWidget::id() const { return p->id(); } std::string PreviewWidget::widget_type() const { return p->widget_type(); } std::map PreviewWidget::attribute_mappings() const { return p->attribute_mappings(); } VariantMap PreviewWidget::attribute_values() const { return p->attribute_values(); } std::string PreviewWidget::data() const { return p->data(); } //! @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/Runtime.cpp0000644000015301777760000000341512320776161023550 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace std; namespace unity { namespace scopes { //! @cond Runtime::Runtime(string const& scope_id, string const& configfile) : p(internal::RuntimeImpl::create(scope_id, configfile)) { } Runtime::~Runtime() { } //! @endcond Runtime::UPtr Runtime::create(string const& configfile) { return UPtr(new Runtime("", configfile)); } Runtime::UPtr Runtime::create_scope_runtime(string const& scope_id, string const& configfile) { return UPtr(new Runtime(scope_id, configfile)); } void Runtime::destroy() { p->destroy(); } RegistryProxy Runtime::registry() const { return p->registry(); } void Runtime::run_scope(ScopeBase *const scope_base, std::string const& scope_ini_file) { p->run_scope(scope_base, scope_ini_file); } ObjectProxy Runtime::string_to_proxy(string const& s) const { return p->string_to_proxy(s); } string Runtime::proxy_to_string(ObjectProxy const& proxy) const { return p->proxy_to_string(proxy); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/PreviewListenerBase.cpp0000644000015301777760000000170412320776161026046 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include namespace unity { namespace scopes { //! @cond PreviewListenerBase::PreviewListenerBase() { } PreviewListenerBase::~PreviewListenerBase() { } //! @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/ScopeExceptions.cpp0000644000015301777760000000724512320776161025245 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include using namespace std; namespace unity { namespace scopes { MiddlewareException::MiddlewareException(std::string const& reason) : Exception("unity::scopes::MiddlewareException", reason) { } MiddlewareException::MiddlewareException(MiddlewareException const&) = default; //! @cond MiddlewareException& MiddlewareException::operator=(MiddlewareException const&) = default; MiddlewareException::~MiddlewareException() = default; //! @endcond exception_ptr MiddlewareException::self() const { return make_exception_ptr(*this); } ObjectNotExistException::ObjectNotExistException(std::string const& reason, std::string const& id) : Exception("unity::scopes::ObjectNotExistException", reason + (reason.empty() ? "" : " ") + "(id = " + id + ")"), MiddlewareException("unity::scopes::ObjectNotExistException" + reason + (reason.empty() ? "" : " ") + "(id = " + id + ")"), id_(id) { } ObjectNotExistException::ObjectNotExistException(ObjectNotExistException const&) = default; //! @cond ObjectNotExistException& ObjectNotExistException::operator=(ObjectNotExistException const&) = default; ObjectNotExistException::~ObjectNotExistException() noexcept = default; //! @endcond exception_ptr ObjectNotExistException::self() const { return make_exception_ptr(*this); } string ObjectNotExistException::id() const { return id_; } TimeoutException::TimeoutException(std::string const& reason) : Exception("unity::scopes::TimeoutException", reason), MiddlewareException(reason) { } TimeoutException::TimeoutException(TimeoutException const&) = default; //! @cond TimeoutException& TimeoutException::operator=(TimeoutException const&) = default; TimeoutException::~TimeoutException() noexcept = default; //! @endcond exception_ptr TimeoutException::self() const { return make_exception_ptr(*this); } ConfigException::ConfigException(std::string const& reason) : Exception("unity::scopes::ConfigException", reason) { } ConfigException::ConfigException(ConfigException const&) = default; //! @cond ConfigException& ConfigException::operator=(ConfigException const&) = default; ConfigException::~ConfigException() = default; //! @endcond exception_ptr ConfigException:: self() const { return make_exception_ptr(*this); } NotFoundException::NotFoundException(std::string const& reason, std::string const& name) : Exception("unity::scopes::NotFoundException", reason + (reason.empty() ? "" : " ") + "(name = " + name + ")"), name_(name) { } NotFoundException::NotFoundException(NotFoundException const&) = default; //! @cond NotFoundException& NotFoundException::operator=(NotFoundException const&) = default; NotFoundException::~NotFoundException() = default; //! @endcond exception_ptr NotFoundException::self() const { return make_exception_ptr(*this); } string NotFoundException::name() const { return name_; } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/ActivationListenerBase.cpp0000644000015301777760000000241712320776161026530 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include namespace unity { namespace scopes { /// @cond ActivationListenerBase::ActivationListenerBase() { } ActivationListenerBase::~ActivationListenerBase() { } /// @endcond void ActivationListenerBase::activated(ActivationResponse const& /* response */) { // Intentionally empty: "do nothing" default implementation. } void ActivationListenerBase::finished(Reason /* r */, std::string const& /* error_message */) { // Intentionally empty: "do nothing" default implementation. } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/OptionSelectorFilter.cpp0000644000015301777760000000505512320776161026246 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { OptionSelectorFilter::OptionSelectorFilter(std::string const& id, std::string const& label, bool multi_select) : FilterBase(new internal::OptionSelectorFilterImpl(id, label, multi_select)) { } OptionSelectorFilter::OptionSelectorFilter(VariantMap const& var) : FilterBase(new internal::OptionSelectorFilterImpl(var)) { } OptionSelectorFilter::SPtr OptionSelectorFilter::create(std::string const& id, std::string const& label, bool multi_select) { return std::shared_ptr(new OptionSelectorFilter(id, label, multi_select)); } std::string OptionSelectorFilter::label() const { return fwd()->label(); } bool OptionSelectorFilter::multi_select() const { return fwd()->multi_select(); } FilterOption::SCPtr OptionSelectorFilter::add_option(std::string const& id, std::string const& label) { return fwd()->add_option(id, label); } std::list OptionSelectorFilter::options() const { return fwd()->options(); } std::set OptionSelectorFilter::active_options(FilterState const& filter_state) const { return fwd()->active_options(filter_state); } void OptionSelectorFilter::update_state(FilterState& filter_state, FilterOption::SCPtr option, bool active) const { fwd()->update_state(filter_state, option, active); } void OptionSelectorFilter::update_state(FilterState& filter_state, std::string const& filter_id, std::string const& option_id, bool value) { internal::OptionSelectorFilterImpl::update_state(filter_state, filter_id, option_id, value); } internal::OptionSelectorFilterImpl* OptionSelectorFilter::fwd() const { return dynamic_cast(p.get()); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/CategoryRenderer.cpp0000644000015301777760000001635212320776161025375 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { /*! \class CategoryRenderer This class specifies how is a particular category rendered by Unity. Note that the data is likely to change between major versions of Unity, and therefore the definition isn't strongly typed and provided by a scope author as a JSON string. A Category contains all the information needed by Unity to render results provided by a scope author (by handling unity::scopes::SearchQueryBase::run()) in a way that gives the user as much useful information as possible. When pushing results to the query originator (unity::scopes::SearchReply::push()), each result needs to have a category associated, and this association determines what will the result look like. The most important part of a category definition is the unity::scopes::CategoryRenderer instance. If you use the default constructor CategoryRenderer(), the renderer will use the following definition: \verbatim { "schema-version" : 1, "template" : { "category-layout" : "grid" }, "components" : { "title" : "title", "art" : "art" } } \endverbatim As specified by the \c "category-layout" key of the \c "template" dictionary, Unity will render results associated with this category in a grid layout. The \c "components" dictionary specifies which result fields are used by Unity. In case of this definition, each tile of the grid will map the "title" field from the result (set also by the call to unity::scopes::Result::set_title()) as title for the grid tile, and "art" field from the result (see unity::scopes::Result::set_art()) as the icon for the grid tile. To sum up, the \c "template" dictionary contains information to determine the correct renderer and its parameters, and the \c "components" dictionary contains mapping specifying which fields of the results are used by the renderer, where keys of the dictionary are understood by Unity and values specify either field name of the results directly ({"title": "album_name"} would mean that Unity will use result["album_name"] as a title for the grid tile), or the value can specify extra hints for the renderer as well as the result field name ({"art": {"field": "icon", "aspect-ratio": 1.3}}). \section jsonschema1 JSON structure (v1) When using {"schema-version": 1}, the following keys are understood: \subsection template1 template keys \arg \c category-layout Specifies renderer type; possible values: \c "grid" (default), \c "carousel", \c "organic-grid", \c "journal", \c "vertical-journal" \arg \c card-layout Specifies layout of the individual result cards; possible values: \c "vertical" (default), \c "horizontal" \arg \c card-size Size of the result cards; possible values: \c "small", \c "medium" (default), \c "large"; when using "category-layout": "vertical-journal" any integer between 12 and 38 \arg \c overlay Overlay text data on top of the art; boolean, default false \arg \c collapsed-rows Number of result rows displayed while the category is collapsed; possible values: 1 or 2 (only affects grid and journal) \arg \c card-background Background color for the cards; string; URI in the format \verbatim color:///#rrggbb \endverbatim or \verbatim color:///color_name \endverbatim or \verbatim gradient:///#rrggbb/#rrggbb \endverbatim or an image URI (will be stretched) \subsection components1 components keys \arg \c title Card title, string \arg \c art Card art (primary graphics), uri; can contain subkeys: \c "aspect-ratio" (double specifying the aspect ratio of the graphics, default: 1.0) and \c "fill-mode" (\c "crop" (default), or \c "fit") \arg \c subtitle Subtitle of a card, string \arg \c mascot Mascot (secondary graphics), uri \arg \c emblem Emblem, uri \arg \c summary Text summary, string \arg \c background Card background, can override the default specified in the card-background field of the template section, string (same URI format as for card-background) \arg \c attribute-1 string \arg \c attribute-2 string \arg \c attribute-3 string \section example Example In the following example a category named "Recommended" containing three components is created (title, art and subtitle), and a result providing values for these components is pushed. Note that the scope is free to set any other extra result fields even if they are not used by the renderer (and therefore not specified in the \c "components" dictionary), such fields will be preserved and available to the scope when handling result-specific methods (for example unity::scopes::ScopeBase::preview()). \code{.cpp} // use raw string literal, so we don't have to escape all the quotes std::string CATEGORY_DEFINITION = R"( { "schema-version" : 1, "template" : { "category-layout" : "carousel", "card-size": "small" }, "components" : { "title" : "title", "art" : { "field": "art", "aspect-ratio": 1.3 }, "subtitle": "publisher" } } )"; void MyQuery::run(SearchReplyProxy const& reply) { auto category = reply->register_category("recommended", "Recommended", icon, CategoryRenderer(CATEGORY_DEFINITION)); // push a sample result CategorisedResult result(category); // create a result item in "recommended" category result.set_uri("http://www.example.org"); result.set_title("Example Result"); result.set_art("http://www.example.org/graphics.png"); result.set_dnd_uri("http://www.example.org"); result["publisher"] = "Example.org"; reply->push(result); // send result to the client } \endcode */ //! @cond CategoryRenderer::CategoryRenderer(std::string const& json_text) : p(new internal::CategoryRendererImpl(json_text)) { } CategoryRenderer::~CategoryRenderer() = default; CategoryRenderer::CategoryRenderer(CategoryRenderer const& other) : p(new internal::CategoryRendererImpl(*(other.p))) { } CategoryRenderer& CategoryRenderer::operator=(CategoryRenderer const& other) { if (this != &other) { p.reset(new internal::CategoryRendererImpl(*(other.p))); } return *this; } CategoryRenderer::CategoryRenderer(CategoryRenderer&&) = default; CategoryRenderer& CategoryRenderer::operator=(CategoryRenderer&&) = default; CategoryRenderer CategoryRenderer::from_file(std::string const& path) { return internal::CategoryRendererImpl::from_file(path); } std::string CategoryRenderer::data() const { return p->data(); } bool operator==(const CategoryRenderer& lhs, const CategoryRenderer& rhs) { return lhs.data() == rhs.data(); } //! @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/Variant.cpp0000644000015301777760000001216112320776161023527 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include #include using namespace std; namespace unity { namespace scopes { namespace internal { struct NullVariant { bool operator<(NullVariant const&) const { return false; } bool operator==(NullVariant const&) const { return true; } }; struct VariantImpl { boost::variant v; }; } // namespace internal Variant::Variant() noexcept : p(new internal::VariantImpl { internal::NullVariant() }) { } Variant::Variant(int val) noexcept : p(new internal::VariantImpl { val }) { } Variant::Variant(double val) noexcept : p(new internal::VariantImpl { val }) { } Variant::Variant(bool val) noexcept : p(new internal::VariantImpl { val }) { } Variant::Variant(std::string const& val) : p(new internal::VariantImpl { val }) { } Variant::Variant(VariantMap const& val) : p(new internal::VariantImpl { val }) { } Variant::Variant(VariantArray const& val) : p(new internal::VariantImpl { val }) { } Variant::Variant(internal::NullVariant const& val) : p(new internal::VariantImpl { val }) { } Variant::Variant(char const* val) : p(new internal::VariantImpl { string(val) }) { } Variant::~Variant() { } Variant const& Variant::null() { static const Variant var = internal::NullVariant(); return var; } Variant::Variant(Variant const& other) : p(new internal::VariantImpl(*other.p)) { } Variant::Variant(Variant&&) = default; Variant& Variant::operator=(Variant const& rhs) { p->v = rhs.p->v; return *this; } Variant& Variant::operator=(Variant&&) = default; Variant& Variant::operator=(int val) noexcept { p->v = val; return *this; } Variant& Variant::operator=(double val) noexcept { p->v = val; return *this; } Variant& Variant::operator=(bool val) noexcept { p->v = val; return *this; } Variant& Variant::operator=(std::string const& val) { p->v = val; return *this; } Variant& Variant::operator=(VariantMap const& val) { p->v = val; return *this; } Variant& Variant::operator=(VariantArray const& val) { p->v = val; return *this; } Variant& Variant::operator=(char const* val) { p->v = string(val); return *this; } bool Variant::operator==(Variant const& rhs) const noexcept { return p->v == rhs.p->v; } bool Variant::operator<(Variant const& rhs) const noexcept { return p->v < rhs.p->v; } int Variant::get_int() const { try { return boost::get(p->v); } catch (std::exception const&) { throw LogicException("Variant does not contain an int value"); } } double Variant::get_double() const { try { return boost::get(p->v); } catch (std::exception const&) { throw LogicException("Variant does not contain a double value"); } } bool Variant::get_bool() const { try { return boost::get(p->v); } catch (std::exception const&) { throw LogicException("Variant does not contain a bool value"); } } string Variant::get_string() const { try { return boost::get(p->v); } catch (std::exception const&) { throw LogicException("Variant does not contain a string value"); } } VariantMap Variant::get_dict() const { try { return boost::get(p->v); } catch (std::exception const&) { throw LogicException("Variant does not contain a dictionary"); } } VariantArray Variant::get_array() const { try { return boost::get(p->v); } catch (std::exception const&) { throw LogicException("Variant does not contain an array"); } } bool Variant::is_null() const { return p->v.which() == Type::Null; } Variant::Type Variant::which() const noexcept { auto w = p->v.which(); return static_cast(w); } void Variant::swap(Variant& other) noexcept { p.swap(other.p); } void swap(Variant& lhs, Variant& rhs) noexcept { lhs.swap(rhs); } std::string Variant::serialize_json() const { internal::JsonCppNode node(*this); return node.to_json_string(); } Variant Variant::deserialize_json(std::string const& json_string) { internal::JsonCppNode node(json_string); return node.to_variant(); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/testing/0000755000015301777760000000000012320776463023100 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/src/scopes/testing/OutOfProcessBenchmark.cpp0000644000015301777760000001471612320776161030016 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include /// @cond unity::scopes::testing::Benchmark::Result unity::scopes::testing::OutOfProcessBenchmark::for_query( const std::shared_ptr& scope, unity::scopes::testing::Benchmark::QueryConfiguration config) { auto child = core::posix::fork([this, config, scope]() { InProcessBenchmark::for_query(scope, config).save_to(std::cout); return core::posix::exit::Status::success; }, core::posix::StandardStream::stdout); unity::scopes::testing::Benchmark::Result result; result.load_from(child.cout()); auto wait_result = child.wait_for(core::posix::wait::Flags::untraced); switch(wait_result.status) { case core::posix::wait::Result::Status::signaled: case core::posix::wait::Result::Status::stopped: throw std::runtime_error("unity::scopes::testing::Benchmark::for_query: " "Trial terminated with error, bailing out now. " "Please see the detailed error output and backtrace."); default: break; } if (wait_result.detail.if_exited.status != core::posix::exit::Status::success) throw std::runtime_error("unity::scopes::testing::Benchmark::for_query: " "Trial exited with failure, bailing out now. " "Please see the detailed error output and backtrace."); return result; } unity::scopes::testing::Benchmark::Result unity::scopes::testing::OutOfProcessBenchmark::for_preview( const std::shared_ptr& scope, unity::scopes::testing::Benchmark::PreviewConfiguration config) { auto child = core::posix::fork([this, config, scope]() { InProcessBenchmark::for_preview(scope, config).save_to(std::cout); return core::posix::exit::Status::success; }, core::posix::StandardStream::stdout); unity::scopes::testing::Benchmark::Result result; result.load_from(child.cout()); auto wait_result = child.wait_for(core::posix::wait::Flags::untraced); switch(wait_result.status) { case core::posix::wait::Result::Status::signaled: case core::posix::wait::Result::Status::stopped: throw std::runtime_error("unity::scopes::testing::Benchmark::for_query: " "Trial terminated with error, bailing out now. " "Please see the detailed error output and backtrace."); default: break; } if (wait_result.detail.if_exited.status != core::posix::exit::Status::success) throw std::runtime_error("unity::scopes::testing::Benchmark::for_query: " "Trial exited with failure, bailing out now. " "Please see the detailed error output and backtrace."); return result; } unity::scopes::testing::Benchmark::Result unity::scopes::testing::OutOfProcessBenchmark::for_activation( const std::shared_ptr& scope, unity::scopes::testing::Benchmark::ActivationConfiguration config) { auto child = core::posix::fork([this, config, scope]() { InProcessBenchmark::for_activation(scope, config).save_to(std::cout); return core::posix::exit::Status::success; }, core::posix::StandardStream::stdout); unity::scopes::testing::Benchmark::Result result; result.load_from(child.cout()); auto wait_result = child.wait_for(core::posix::wait::Flags::untraced); switch(wait_result.status) { case core::posix::wait::Result::Status::signaled: case core::posix::wait::Result::Status::stopped: throw std::runtime_error("unity::scopes::testing::Benchmark::for_query: " "Trial terminated with error, bailing out now. " "Please see the detailed error output and backtrace."); default: break; } if (wait_result.detail.if_exited.status != core::posix::exit::Status::success) throw std::runtime_error("unity::scopes::testing::Benchmark::for_query: " "Trial exited with failure, bailing out now. " "Please see the detailed error output and backtrace."); return result; } unity::scopes::testing::Benchmark::Result unity::scopes::testing::OutOfProcessBenchmark::for_action( const std::shared_ptr& scope, unity::scopes::testing::Benchmark::ActionConfiguration config) { auto child = core::posix::fork([this, config, scope]() { InProcessBenchmark::for_action(scope, config).save_to(std::cout); return core::posix::exit::Status::success; }, core::posix::StandardStream::stdout); unity::scopes::testing::Benchmark::Result result; result.load_from(child.cout()); auto wait_result = child.wait_for(core::posix::wait::Flags::untraced); switch(wait_result.status) { case core::posix::wait::Result::Status::signaled: case core::posix::wait::Result::Status::stopped: throw std::runtime_error("unity::scopes::testing::Benchmark::for_query: " "Trial terminated with error, bailing out now. " "Please see the detailed error output and backtrace."); default: break; } if (wait_result.detail.if_exited.status != core::posix::exit::Status::success) throw std::runtime_error("unity::scopes::testing::Benchmark::for_query: " "Trial exited with failure, bailing out now. " "Please see the detailed error output and backtrace."); return result; } /// @endcond unity-scopes-api-0.4.2+14.04.20140408/src/scopes/testing/ScopeMetadataBuilder.cpp0000644000015301777760000000713112320776161027622 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the Lesser GNU General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include namespace internal = unity::scopes::internal; namespace testing = unity::scopes::testing; /// @cond struct testing::ScopeMetadataBuilder::Private { constexpr static unity::scopes::internal::MiddlewareBase* invalid_middleware = nullptr; std::string scope_id; ScopeProxy proxy; std::string display_name; std::string description; Optional art; Optional icon; Optional search_hint; Optional hot_key; Optional invisible; }; testing::ScopeMetadataBuilder::ScopeMetadataBuilder() : p(new Private()) { } testing::ScopeMetadataBuilder::~ScopeMetadataBuilder() { } testing::ScopeMetadataBuilder& testing::ScopeMetadataBuilder::scope_id(std::string const& value) { p->scope_id = value; return *this; } testing::ScopeMetadataBuilder& testing::ScopeMetadataBuilder::proxy(ScopeProxy const& value) { p->proxy = value; return *this; } testing::ScopeMetadataBuilder& testing::ScopeMetadataBuilder::display_name(std::string const& value) { p->display_name = value; return *this; } testing::ScopeMetadataBuilder& testing::ScopeMetadataBuilder::description(std::string const& value) { p->description = value; return *this; } testing::ScopeMetadataBuilder& testing::ScopeMetadataBuilder::art(Optional const& value) { p->art = value; return *this; } testing::ScopeMetadataBuilder& testing::ScopeMetadataBuilder::icon(Optional const& value) { p->icon = value; return *this; } testing::ScopeMetadataBuilder& testing::ScopeMetadataBuilder::search_hint(Optional const& value) { p->search_hint = value; return *this; } testing::ScopeMetadataBuilder& testing::ScopeMetadataBuilder::hot_key(Optional const& value) { p->hot_key = value; return *this; } testing::ScopeMetadataBuilder& testing::ScopeMetadataBuilder::invisible(Optional value) { p->invisible = value; return *this; } unity::scopes::ScopeMetadata testing::ScopeMetadataBuilder::operator()() const { auto impl = new unity::scopes::internal::ScopeMetadataImpl(Private::invalid_middleware); impl->set_scope_id(p->scope_id); impl->set_proxy(p->proxy); impl->set_display_name(p->display_name); impl->set_description(p->description); if (p->art) impl->set_art(*p->art); if (p->icon) impl->set_icon(*p->icon); if (p->search_hint) impl->set_search_hint(*p->search_hint); if (p->hot_key) impl->set_hot_key(*p->hot_key); if (p->invisible) impl->set_invisible(*p->invisible); return unity::scopes::internal::ScopeMetadataImpl::create( std::move( std::unique_ptr{impl})); } /// @endcond unity-scopes-api-0.4.2+14.04.20140408/src/scopes/testing/Statistics.cpp0000644000015301777760000001325412320776161025736 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include namespace math = boost::math; // We are considering the procedure presented in: // http://en.wikipedia.org/wiki/Anderson%E2%80%93Darling_test // section "Test for normality". More specifically, case 4, unknown mean and // unknown variance. unity::scopes::testing::AndersonDarlingTest::Result unity::scopes::testing::AndersonDarlingTest::for_normality( const unity::scopes::testing::Sample& result) { double n = result.get_size(); // Consider the empirical mean & std. dev. here. double mean = result.get_mean(); double std_dev = std::sqrt(result.get_variance()); std::vector y; result.enumerate([&](double value) { y.push_back((value - mean) / std_dev); }); std::sort(y.begin(), y.end()); math::normal_distribution<> normal; double s = 0.f; for (std::size_t i = 1; i <= y.size(); i++) { auto cdf = math::cdf(normal, y[i-1]); s += (2*i-1) * std::log(cdf) + (2*(n-i)+1)*std::log(1-cdf); } double a2 = -n - 1.f/n * s; // We correct for the case that we are considering empirical mean and variance here. // See: // Ralph B. D'Agostino (1986). "Tests for the Normal Distribution". // In D'Agostino, R.B. and Stephens, M.A. Goodness-of-Fit Techniques. // New York: Marcel Dekker. a2 = a2 * (1 + .75/n - 2.25/math::pow<2>(n)); return unity::scopes::testing::AndersonDarlingTest::Result { [a2](Confidence alpha) { static const std::map lut { {Confidence::zero_point_five_percent, 1.159}, {Confidence::one_percent, 1.035}, {Confidence::two_point_five_percent, 0.873}, {Confidence::five_percent, 0.752}, {Confidence::ten_percent, 0.631} }; return a2 < lut.at(alpha) ? HypothesisStatus::not_rejected : HypothesisStatus::rejected; } }; } unity::scopes::testing::StudentsTTest::Result unity::scopes::testing::StudentsTTest::one_sample( const unity::scopes::testing::Sample& sample, unity::scopes::testing::Sample::ValueType mean, unity::scopes::testing::Sample::ValueType std_dev) { double t = (sample.get_mean() - mean) * std::sqrt(sample.get_size()) / std_dev; std::size_t df = sample.get_size() - 1; math::students_t_distribution<> dist(df); return unity::scopes::testing::StudentsTTest::Result { t, [=](double alpha) { return math::cdf(math::complement(dist, std::fabs(t))) < alpha / 2. ? unity::scopes::testing::HypothesisStatus::rejected : unity::scopes::testing::HypothesisStatus::not_rejected; }, [=](double alpha) { return math::cdf(dist, t) < alpha ? unity::scopes::testing::HypothesisStatus::not_rejected : unity::scopes::testing::HypothesisStatus::rejected; }, [=](double alpha) { return math::cdf(math::complement(dist, t)) < alpha ? unity::scopes::testing::HypothesisStatus::not_rejected : unity::scopes::testing::HypothesisStatus::rejected; }, }; } unity::scopes::testing::StudentsTTest::Result unity::scopes::testing::StudentsTTest::two_independent_samples( const unity::scopes::testing::Sample& reference, const unity::scopes::testing::Sample& sample) { double s1 = reference.get_variance(); double s2 = sample.get_variance(); std::size_t n1 = reference.get_size(); std::size_t n2 = sample.get_size(); double d = reference.get_mean() - sample.get_mean(); double s12 = std::sqrt( ((n1-1.)*s1 + (n2-1)*s2)/(n1 + n2 - 2)); double t = d / (s12 * std::sqrt(1./n1 + 1./n2)); std::size_t df = n1 + n2 - 2; math::students_t_distribution<> dist(df); return unity::scopes::testing::StudentsTTest::Result { t, [=](double alpha) { return math::cdf(math::complement(dist, std::fabs(t))) < alpha / 2. ? unity::scopes::testing::HypothesisStatus::rejected : unity::scopes::testing::HypothesisStatus::not_rejected; }, [=](double alpha) { return math::cdf(dist, t) < alpha ? unity::scopes::testing::HypothesisStatus::not_rejected : unity::scopes::testing::HypothesisStatus::rejected; }, [=](double alpha) { return math::cdf(math::complement(dist, t)) < alpha ? unity::scopes::testing::HypothesisStatus::not_rejected : unity::scopes::testing::HypothesisStatus::rejected; }, }; } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/testing/Benchmark.cpp0000644000015301777760000002415412320776161025477 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include #include #include namespace { constexpr const char* name_for_seconds{"seconds"}; } namespace boost { namespace serialization { template void load( Archive & ar, unity::scopes::testing::Benchmark::Result::Timing::Seconds& duration, const unsigned int) { unity::scopes::testing::Benchmark::Result::Timing::Seconds::rep value; ar & boost::serialization::make_nvp(name_for_seconds, value); duration = unity::scopes::testing::Benchmark::Result::Timing::Seconds{value}; } template void save( Archive & ar, const unity::scopes::testing::Benchmark::Result::Timing::Seconds& duration, const unsigned int) { unity::scopes::testing::Benchmark::Result::Timing::Seconds::rep value = duration.count(); ar & boost::serialization::make_nvp(name_for_seconds, value); } template void serialize( Archive & ar, unity::scopes::testing::Benchmark::Result::Timing::Seconds& duration, const unsigned int version) { boost::serialization::split_free(ar, duration, version); } template void serialize( Archive & ar, std::pair< unity::scopes::testing::Benchmark::Result::Timing::Seconds, double >& pair, const unsigned int) { ar & boost::serialization::make_nvp("first", pair.first); ar & boost::serialization::make_nvp("second", pair.second); } template void serialize(Archive & ar, unity::scopes::testing::Benchmark::Result& result, const unsigned int) { ar & boost::serialization::make_nvp("sample_size", result.sample_size); ar & boost::serialization::make_nvp("timing.min", result.timing.min); ar & boost::serialization::make_nvp("timing.max", result.timing.max); ar & boost::serialization::make_nvp("timing.mean", result.timing.mean); ar & boost::serialization::make_nvp("timing.std_dev", result.timing.std_dev); ar & boost::serialization::make_nvp("timing.kurtosis", result.timing.kurtosis); ar & boost::serialization::make_nvp("timing.skewness", result.timing.skewness); ar & boost::serialization::make_nvp("timing.sample", result.timing.sample); ar & boost::serialization::make_nvp("timing.histogram", result.timing.histogram); } } // namespace boost } // namespace serialization void unity::scopes::testing::Benchmark::Result::load_from_xml(std::istream& in) { try { boost::archive::xml_iarchive ia(in); ia >> boost::serialization::make_nvp("result", *this); } catch(const boost::archive::archive_exception& e) { throw std::runtime_error(std::string{"Benchmark::Result::write_to: "}+ e.what()); } } void unity::scopes::testing::Benchmark::Result::save_to_xml(std::ostream& out) { try { boost::archive::xml_oarchive oa(out); oa << boost::serialization::make_nvp("result", *this); } catch(const boost::archive::archive_exception& e) { throw std::runtime_error(std::string{"Benchmark::Result::write_to: "} + e.what()); } } void unity::scopes::testing::Benchmark::Result::load_from(std::istream& in) { try { boost::archive::text_iarchive ia(in); ia >> boost::serialization::make_nvp("result", *this); } catch(const boost::archive::archive_exception& e) { throw std::runtime_error(std::string{"Benchmark::Result::write_to: "}+ e.what()); } } void unity::scopes::testing::Benchmark::Result::save_to(std::ostream& out) { try { boost::archive::text_oarchive oa(out); oa << boost::serialization::make_nvp("result", *this); } catch(const boost::archive::archive_exception& e) { throw std::runtime_error(std::string{"Benchmark::Result::write_to: "} + e.what()); } } unity::scopes::testing::Sample::SizeType unity::scopes::testing::Benchmark::Result::Timing::get_size() const { return sample.size(); } unity::scopes::testing::Sample::ValueType unity::scopes::testing::Benchmark::Result::Timing::get_mean() const { return mean.count(); } unity::scopes::testing::Sample::ValueType unity::scopes::testing::Benchmark::Result::Timing::get_variance() const { return std_dev.count() * std_dev.count(); } void unity::scopes::testing::Benchmark::Result::Timing::enumerate(const unity::scopes::testing::Sample::Enumerator& enumerator) const { for (const auto& observation : sample) enumerator(observation.count()); } bool unity::scopes::testing::Benchmark::Result::Timing::is_significantly_faster_than_reference( const unity::scopes::testing::Benchmark::Result::Timing& reference, double alpha) const { if (unity::scopes::testing::HypothesisStatus::rejected == unity::scopes::testing::AndersonDarlingTest() .for_normality(*this) .data_fits_normal_distribution( unity::scopes::testing::Confidence::zero_point_five_percent)) throw std::runtime_error{"Timing sample is not normally distributed."}; if (unity::scopes::testing::HypothesisStatus::rejected == unity::scopes::testing::AndersonDarlingTest() .for_normality(reference) .data_fits_normal_distribution( unity::scopes::testing::Confidence::zero_point_five_percent)) throw std::runtime_error{"Reference timing sample is not normally distributed."}; auto test_result = unity::scopes::testing::StudentsTTest() .two_independent_samples( reference, *this); return unity::scopes::testing::HypothesisStatus::not_rejected == test_result.sample1_mean_gt_sample2_mean(alpha); } bool unity::scopes::testing::Benchmark::Result::Timing::is_significantly_faster_than_reference( double mean, double std_dev, double alpha) const { if (unity::scopes::testing::HypothesisStatus::rejected == unity::scopes::testing::AndersonDarlingTest() .for_normality(*this) .data_fits_normal_distribution( unity::scopes::testing::Confidence::zero_point_five_percent)) throw std::runtime_error{"Timing sample is not normally distributed."}; auto test_result = unity::scopes::testing::StudentsTTest() .one_sample(*this, mean, std_dev); return unity::scopes::testing::HypothesisStatus::not_rejected == test_result.sample1_mean_lt_sample2_mean(alpha); } bool unity::scopes::testing::Benchmark::Result::Timing::is_significantly_slower_than_reference( const unity::scopes::testing::Benchmark::Result::Timing& reference, double alpha) const { if (unity::scopes::testing::HypothesisStatus::rejected == unity::scopes::testing::AndersonDarlingTest() .for_normality(*this) .data_fits_normal_distribution( unity::scopes::testing::Confidence::zero_point_five_percent)) throw std::runtime_error{"Timing sample is not normally distributed."}; if (unity::scopes::testing::HypothesisStatus::rejected == unity::scopes::testing::AndersonDarlingTest() .for_normality(reference) .data_fits_normal_distribution( unity::scopes::testing::Confidence::zero_point_five_percent)) throw std::runtime_error{"Reference timing sample is not normally distributed."}; auto test_result = unity::scopes::testing::StudentsTTest() .two_independent_samples( reference, *this); return unity::scopes::testing::HypothesisStatus::not_rejected == test_result.sample1_mean_lt_sample2_mean(alpha); } bool unity::scopes::testing::Benchmark::Result::Timing::is_significantly_slower_than_reference( double mean, double std_dev, double alpha) const { if (unity::scopes::testing::HypothesisStatus::rejected == unity::scopes::testing::AndersonDarlingTest() .for_normality(*this) .data_fits_normal_distribution( unity::scopes::testing::Confidence::zero_point_five_percent)) throw std::runtime_error{"Timing sample is not normally distributed."}; auto test_result = unity::scopes::testing::StudentsTTest() .one_sample(*this, mean, std_dev); return unity::scopes::testing::HypothesisStatus::not_rejected == test_result.sample1_mean_gt_sample2_mean(alpha); } bool unity::scopes::testing::operator==(const unity::scopes::testing::Benchmark::Result& lhs, const unity::scopes::testing::Benchmark::Result& rhs) { return lhs.sample_size == rhs.sample_size && lhs.timing.mean == rhs.timing.mean && lhs.timing.std_dev == rhs.timing.std_dev && lhs.timing.sample == rhs.timing.sample && lhs.timing.histogram == rhs.timing.histogram; } std::ostream& unity::scopes::testing::operator<<(std::ostream& out, const unity::scopes::testing::Benchmark::Result& result) { out << "{" << "sample_size: " << result.sample_size << ", " << "timing: {" << "µ: " << result.timing.mean.count() << " [µs], " << "σ: " << result.timing.std_dev.count() << " [µs]" << "}}"; return out; } unity-scopes-api-0.4.2+14.04.20140408/src/scopes/testing/InProcessBenchmark.cpp0000644000015301777760000003056312320776161027326 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace acc = boost::accumulators; namespace { constexpr static const int result_idx = 0; constexpr static const int metadata_idx = 1; constexpr static const int widget_idx = 2; constexpr static const int action_idx = 3; struct ObjectImpl : public virtual unity::scopes::Object { std::string endpoint() override { return ""; } std::string identity() override { return ""; } std::string category() override { return ""; } int64_t timeout() override { return -1; } std::string to_string() override { return ""; } }; struct WaitableReply : public virtual unity::scopes::Reply, public ObjectImpl { enum class State { idle, running, finished_with_success, finished_with_error }; std::mutex guard; mutable std::condition_variable wait_condition; mutable std::atomic state{State::idle}; bool is_finished() { return state.load() == State::finished_with_success || state.load() == State::finished_with_error; } bool is_finished_with_error() { return state.load() == State::finished_with_error; } bool is_finished_with_success() { return state.load() == State::finished_with_success; } bool wait_for_finished_for(const std::chrono::microseconds& duration) { if (is_finished()) return true; std::unique_lock ul(guard); return wait_condition.wait_for(ul, duration, [this]() { return is_finished(); }); } void finished() override { state.store(State::finished_with_success); wait_condition.notify_all(); } void error(std::exception_ptr) override { state.store(State::finished_with_error); wait_condition.notify_all(); } }; struct DevNullPreviewReply : public unity::scopes::PreviewReply, public WaitableReply { bool register_layout(unity::scopes::ColumnLayoutList const&) override { return true; } bool push(unity::scopes::PreviewWidgetList const&) override { return true; } bool push(std::string const&, unity::scopes::Variant const&) override { return true; } }; struct DevNullSearchReply : public unity::scopes::SearchReply, public WaitableReply { unity::scopes::internal::CategoryRegistry category_registry; void register_departments(unity::scopes::DepartmentList const&, std::string) override { } unity::scopes::Category::SCPtr register_category( std::string const& id, std::string const& title, std::string const& icon, unity::scopes::CategoryRenderer const& renderer) override { return category_registry.register_category(id, title, icon, renderer); } void register_category(unity::scopes::Category::SCPtr category) override { category_registry.register_category(category); } unity::scopes::Category::SCPtr lookup_category(std::string const& id) override { return category_registry.lookup_category(id); } bool push(unity::scopes::CategorisedResult const&) override { return true; } bool push(unity::scopes::Filters const&, unity::scopes::FilterState const&) override { return true; } bool register_annotation(unity::scopes::Annotation const&) override { return true; } }; typedef std::chrono::high_resolution_clock Clock; typedef unity::scopes::testing::Benchmark::Result::Timing::Seconds Resolution; typedef acc::accumulator_set< Resolution::rep, acc::stats< acc::tag::count, acc::tag::density, acc::tag::min, acc::tag::max, acc::tag::mean, acc::tag::kurtosis, acc::tag::skewness, acc::tag::variance > > Statistics; void fill_results_from_statistics(unity::scopes::testing::Benchmark::Result& result, const Statistics& stats) { result.sample_size = acc::count(stats); auto histogram = acc::density(stats); for (const auto& bin : histogram) { result.timing.histogram.push_back( std::make_pair( Resolution(bin.first), bin.second)); } result.timing.min = Resolution { static_cast(acc::min(stats)) }; result.timing.max = Resolution { static_cast(acc::max(stats)) }; result.timing.kurtosis = Resolution { static_cast(acc::kurtosis(stats)) }; result.timing.skewness = Resolution { static_cast(acc::skewness(stats)) }; result.timing.mean = Resolution { static_cast(acc::mean(stats)) }; result.timing.std_dev = Resolution { static_cast(std::sqrt(acc::variance(stats))) }; } } /// @cond unity::scopes::testing::Benchmark::Result unity::scopes::testing::InProcessBenchmark::for_query( const std::shared_ptr& scope, unity::scopes::testing::Benchmark::QueryConfiguration config) { Statistics stats( acc::tag::density::num_bins = config.trial_configuration.statistics_configuration.histogram_bin_count, acc::tag::density::cache_size = 10); unity::scopes::testing::Benchmark::Result benchmark_result; benchmark_result.timing.sample.resize(config.trial_configuration.trial_count); for (unsigned int i = 0; i < config.trial_configuration.trial_count; i++) { DevNullSearchReply search_reply; auto before = Clock::now(); { auto sample = config.sampler(); auto q = scope->search(sample.first, sample.second); q->run(unity::scopes::SearchReplyProxy { &search_reply, [](unity::scopes::SearchReply* r) { r->finished(); } }); if (!search_reply.wait_for_finished_for(config.trial_configuration.per_trial_timeout)) throw std::runtime_error("Query did not complete within the specified timeout interval."); } auto after = Clock::now(); auto duration = std::chrono::duration_cast(after - before); stats(duration.count()); benchmark_result.timing.sample[i] = duration; } fill_results_from_statistics(benchmark_result, stats); return benchmark_result; } unity::scopes::testing::Benchmark::Result unity::scopes::testing::InProcessBenchmark::for_preview( const std::shared_ptr& scope, unity::scopes::testing::Benchmark::PreviewConfiguration config) { Statistics stats( acc::tag::density::num_bins = config.trial_configuration.statistics_configuration.histogram_bin_count, acc::tag::density::cache_size = 10); unity::scopes::testing::Benchmark::Result benchmark_result; benchmark_result.timing.sample.resize(config.trial_configuration.trial_count); for (unsigned int i = 0; i < config.trial_configuration.trial_count; i++) { DevNullPreviewReply preview_reply; auto before = Clock::now(); { auto sample = config.sampler(); auto q = scope->preview(sample.first, sample.second); q->run(unity::scopes::PreviewReplyProxy { &preview_reply, [](unity::scopes::PreviewReply* r) { r->finished(); } }); if (!preview_reply.wait_for_finished_for(config.trial_configuration.per_trial_timeout)) throw std::runtime_error("Preview did not complete within the specified timeout interval."); } auto after = Clock::now(); auto duration = std::chrono::duration_cast(after - before); stats(duration.count()); benchmark_result.timing.sample[i] = duration; } fill_results_from_statistics(benchmark_result, stats); return benchmark_result; } unity::scopes::testing::Benchmark::Result unity::scopes::testing::InProcessBenchmark::for_activation( const std::shared_ptr& scope, unity::scopes::testing::Benchmark::ActivationConfiguration config) { Statistics stats( acc::tag::density::num_bins = config.trial_configuration.statistics_configuration.histogram_bin_count, acc::tag::density::cache_size = 10); unity::scopes::testing::Benchmark::Result benchmark_result; benchmark_result.timing.sample.resize(config.trial_configuration.trial_count); for (unsigned int i = 0; i < config.trial_configuration.trial_count; i++) { auto before = Clock::now(); { auto sample = config.sampler(); auto a = scope->activate(sample.first, sample.second); (void) a->activate(); } auto after = Clock::now(); auto duration = std::chrono::duration_cast(after - before); stats(duration.count()); benchmark_result.timing.sample[i] = duration; } fill_results_from_statistics(benchmark_result, stats); return benchmark_result; } unity::scopes::testing::Benchmark::Result unity::scopes::testing::InProcessBenchmark::for_action( const std::shared_ptr& scope, unity::scopes::testing::Benchmark::ActionConfiguration config) { Statistics stats( acc::tag::density::num_bins = config.trial_configuration.statistics_configuration.histogram_bin_count, acc::tag::density::cache_size = 10); unity::scopes::testing::Benchmark::Result benchmark_result; benchmark_result.timing.sample.resize(config.trial_configuration.trial_count); for (unsigned int i = 0; i < config.trial_configuration.trial_count; i++) { auto before = Clock::now(); { auto sample = config.sampler(); auto a = scope->perform_action(std::get(sample), std::get(sample), std::get(sample), std::get(sample)); (void) a->activate(); } auto after = Clock::now(); auto duration = std::chrono::duration_cast(after - before); stats(duration.count()); benchmark_result.timing.sample[i] = duration; } fill_results_from_statistics(benchmark_result, stats); return benchmark_result; } /// @endcond unity-scopes-api-0.4.2+14.04.20140408/src/scopes/testing/Result.cpp0000644000015301777760000000165212320776161025061 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #include #include /// @cond unity::scopes::testing::Result::Result() : unity::scopes::Result(new unity::scopes::internal::ResultImpl()) { } /// @endcond unity-scopes-api-0.4.2+14.04.20140408/src/scopes/testing/CMakeLists.txt0000644000015301777760000000060312320776161025632 0ustar pbusernogroup00000000000000set(SRC ${CMAKE_CURRENT_SOURCE_DIR}/Benchmark.cpp ${CMAKE_CURRENT_SOURCE_DIR}/InProcessBenchmark.cpp ${CMAKE_CURRENT_SOURCE_DIR}/OutOfProcessBenchmark.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Result.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Statistics.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ScopeMetadataBuilder.cpp ) set(UNITY_SCOPES_LIB_SRC ${UNITY_SCOPES_LIB_SRC} ${SRC} PARENT_SCOPE) unity-scopes-api-0.4.2+14.04.20140408/src/scopes/PreviewQueryBase.cpp0000644000015301777760000000201112320776161025356 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include using namespace std; namespace unity { namespace scopes { /// @cond PreviewQueryBase::PreviewQueryBase() : QueryBase() { } PreviewQueryBase::~PreviewQueryBase() { } /// @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/CMakeLists.txt0000644000015301777760000000405712320776161024164 0ustar pbusernogroup00000000000000add_subdirectory(internal) add_subdirectory(testing) set(CAPNPROTO_FILES ${CAPNPROTO_FILES} PARENT_SCOPE) set(SRC ${CMAKE_CURRENT_SOURCE_DIR}/ActionMetadata.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ActivationListenerBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ActivationQueryBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ActivationResponse.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Annotation.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CannedQuery.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CategorisedResult.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Category.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CategoryRenderer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ColumnLayout.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Department.cpp ${CMAKE_CURRENT_SOURCE_DIR}/FilterBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/FilterOption.cpp ${CMAKE_CURRENT_SOURCE_DIR}/FilterState.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Link.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ListenerBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Object.cpp ${CMAKE_CURRENT_SOURCE_DIR}/OptionSelectorFilter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PreviewListenerBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PreviewQueryBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PreviewReply.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PreviewWidget.cpp ${CMAKE_CURRENT_SOURCE_DIR}/QueryBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/QueryCtrl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Registry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Reply.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Result.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Runtime.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ScopeBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Scope.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ScopeExceptions.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ScopeMetadata.cpp ${CMAKE_CURRENT_SOURCE_DIR}/SearchListenerBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/SearchMetadata.cpp ${CMAKE_CURRENT_SOURCE_DIR}/SearchQueryBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/SearchReply.cpp ${CMAKE_CURRENT_SOURCE_DIR}/VariantBuilder.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Variant.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Version.cpp ) set(UNITY_SCOPES_LIB_SRC ${UNITY_SCOPES_LIB_SRC} ${SRC} PARENT_SCOPE) unity-scopes-api-0.4.2+14.04.20140408/src/scopes/ScopeBase.cpp0000644000015301777760000000365312320776161023775 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include #include #include namespace unity { namespace scopes { //! @cond ScopeBase::ScopeBase() : p(new internal::ScopeBaseImpl()) { } ScopeBase::~ScopeBase() { } //! @endcond void ScopeBase::run() { // Intentionally empty: default "do nothing" implementation. } ActivationQueryBase::UPtr ScopeBase::activate(Result const& /* result */, ActionMetadata const& /* metadata */) { return ActivationQueryBase::UPtr(new ActivationQueryBase()); // default impl returns NotHandled } ActivationQueryBase::UPtr ScopeBase::perform_action(Result const& /* result */, ActionMetadata const& /* metadata */, std::string const& /* widget_id */, std::string const& /* action_id */) { return ActivationQueryBase::UPtr(new ActivationQueryBase()); // default impl returns NotHandled } void ScopeBase::runtime_version(int& v_major, int& v_minor, int& v_micro) noexcept { v_major = unity::scopes::major_version(); v_minor = unity::scopes::minor_version(); v_micro = unity::scopes::micro_version(); } std::string ScopeBase::scope_directory() const { return p->scope_directory(); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/Annotation.cpp0000644000015301777760000000417612320776161024244 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include #include namespace unity { namespace scopes { Annotation::Annotation(Type atype) : p(new internal::AnnotationImpl(atype)) { } /// @cond Annotation::Annotation(Annotation const &other) : p(new internal::AnnotationImpl(*(other.p))) { } Annotation::Annotation(internal::AnnotationImpl* impl) : p(impl) { } Annotation::Annotation(Annotation&&) = default; Annotation& Annotation::operator=(Annotation const& other) { if (this != &other) { p.reset(new internal::AnnotationImpl(*(other.p))); } return *this; } Annotation& Annotation::operator=(Annotation&&) = default; Annotation::~Annotation() { } VariantMap Annotation::serialize() const { return p->serialize(); } /// @endcond void Annotation::set_label(std::string const& label) { p->set_label(label); } void Annotation::set_icon(std::string const& icon) { p->set_icon(icon); } void Annotation::add_link(std::string const& label, CannedQuery const& query) { p->add_link(label, query); } std::string Annotation::label() const { return p->label(); } std::string Annotation::icon() const { return p->icon(); } std::list Annotation::links() const { return p->links(); } Annotation::Type Annotation::annotation_type() const { return p->annotation_type(); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/Reply.cpp0000644000015301777760000000161412320776161023217 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include namespace unity { namespace scopes { /// @cond Reply::Reply() = default; Reply::~Reply() = default; /// @endcond } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/scopes/FilterOption.cpp0000644000015301777760000000230112320776161024534 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #include #include namespace unity { namespace scopes { FilterOption::FilterOption(std::string const& id, std::string const& label) : p(new internal::FilterOptionImpl(id, label)) { } /// @cond FilterOption::~FilterOption() = default; /// @endcond std::string FilterOption::id() const { return p->id(); } std::string FilterOption::label() const { return p->label(); } } // namespace scopes } // namespace unity unity-scopes-api-0.4.2+14.04.20140408/src/CMakeLists.txt0000644000015301777760000000022412320776161022660 0ustar pbusernogroup00000000000000add_subdirectory(scopes) set(CAPNPROTO_FILES ${CAPNPROTO_FILES} PARENT_SCOPE) set(UNITY_SCOPES_LIB_SRC ${UNITY_SCOPES_LIB_SRC} ${SRC} PARENT_SCOPE) unity-scopes-api-0.4.2+14.04.20140408/include/0000755000015301777760000000000012320776463020763 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/0000755000015301777760000000000012320776463022133 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/0000755000015301777760000000000012320776463023427 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/Registry.h0000644000015301777760000000432012320776161025402 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_REGISTRY_H #define UNITY_SCOPES_REGISTRY_H #include #include #include #include namespace unity { namespace scopes { namespace internal { class RegistryImpl; } /** \brief Map for scope ID and metadata pairs. */ typedef std::map MetadataMap; /** \brief White pages service for available scopes. You can obtain a proxy to the registry by calling Runtime::registry(). */ class Registry : public virtual Object { public: /// @cond virtual ~Registry(); /// @endcond /** \brief Returns the metadata for the scope with the given ID. \return The metadata for the scope. \throws NotFoundException if no scope with the given name exists. */ virtual ScopeMetadata get_metadata(std::string const& scope_id) = 0; /** \brief Returns a map containing the metadata for all scopes. \return The metadata for all scopes. */ virtual MetadataMap list() = 0; /** \brief Returns a map containing only those scopes for which `predicate` returns true. \param predicate a function object that must return true for each metadata item to be included in the map. \return The metadata items for which the predicate returned true. */ virtual MetadataMap list_if(std::function predicate) = 0; protected: /// @cond Registry(); /// @endcond }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/QueryBase.h0000644000015301777760000000505112320776161025474 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_QUERYBASE_H #define UNITY_SCOPES_QUERYBASE_H #include #include #include #include #include #include namespace unity { namespace scopes { class SearchMetadata; namespace internal { class QueryBaseImpl; class QueryObject; class ScopeObject; namespace smartscopes { class SSQueryObject; } // namespace smartscopes } // namespace internal /** \brief Abstract server-side base interface for a query that is executed inside a scope. \see SearchQueryBase, PreviewQueryBase, ActivationQueryBase */ class QueryBase { public: /// @cond NONCOPYABLE(QueryBase); UNITY_DEFINES_PTRS(QueryBase); /// @endcond /** \brief Called by the scopes run time when the query originator cancels a query. Your implementation of this method should ensure that the scope stops processing the current query as soon as possible. Any calls to a `push()` method once a query is cancelled are ignored, so continuing to push after cancellation only wastes CPU cycles. */ virtual void cancelled() = 0; // Originator cancelled the query /// @cond virtual ~QueryBase(); /// @endcond protected: /// @cond QueryBase(); void cancel(); std::unique_ptr p; /// @endcond private: void set_metadata(SearchMetadata const& metadata); friend class internal::QueryObject; // So QueryObject can call cancel() friend class internal::smartscopes::SSQueryObject; // So SSQueryObject can call cancel() friend class internal::ScopeObject; // So ScopeObject can call set_metadata() }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/0000755000015301777760000000000012320776463025243 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/RegistryImpl.h0000644000015301777760000000321612320776161030043 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_REGISTRYIMPL_H #define UNITY_SCOPES_INTERNAL_REGISTRYIMPL_H #include #include #include namespace unity { namespace scopes { namespace internal { class RuntimeImpl; class RegistryImpl : public virtual unity::scopes::Registry, public virtual ObjectImpl { public: RegistryImpl(MWRegistryProxy const& mw_proxy, RuntimeImpl* runtime); ~RegistryImpl(); virtual ScopeMetadata get_metadata(std::string const& scope_id) override; virtual MetadataMap list() override; virtual MetadataMap list_if(std::function predicate) override; // Remote operation. Not part of public API, hence not override. ObjectProxy locate(std::string const& identity); private: MWRegistryProxy fwd() const; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/Reaper.h0000644000015301777760000001633012320776161026630 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_REAPER_H #define UNITY_SCOPES_INTERNAL_REAPER_H #include #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { typedef std::function ReaperCallback; namespace reaper_private { struct Item { Item(ReaperCallback cb) : cb(cb), timestamp(std::chrono::steady_clock::now()) { } Item(Item const&) = default; Item& operator=(Item const&) = default; ReaperCallback cb; // Called if timeout expires (application-supplied callback) std::chrono::steady_clock::time_point timestamp; // Last add() or refresh() std::function disable_reap_item; // Disables corresponding ReapItem if timeout expires }; typedef std::list Reaplist; } // namespace reaper_private class Reaper; // Simple refresh class returned from Reaper::add(). // refresh() renews the timestamp of an entry. // destroy() removes the entry from the reaper's list *without* invoking the callback. // Calls to refresh() or destroy() after destroy() do nothing. // // It is safe to continue to call methods on a ReapItem even its reaper has gone out of scope. // In that case, refresh() and destroy() do nothing. // // Letting a ReapItem go out of scope automatically calls destroy(), meaning that the item's callback // is *not* invoked when a ReapItem is destroyed. class ReapItem final { public: NONCOPYABLE(ReapItem); UNITY_DEFINES_PTRS(ReapItem); void refresh() noexcept; // Update time stamp on item to keep it alive. O(1) performance. void destroy() noexcept; // Removes this item from the reaper *without* invoking the callback. O(1) performance. ~ReapItem(); private: ReapItem(std::weak_ptr const& reaper, reaper_private::Reaplist::iterator it); // Only Reaper can instantiate std::weak_ptr reaper_; // The reaper this item belongs with static std::mutex mutex_; // Protects weak_ptr reaper_private::Reaplist::iterator it_; // Position in reap list std::atomic_bool destroyed_; friend class Reaper; }; // Simple reaper class. It maintains a list of items in LRU order. The caller adds items to the // list by calling add(), which returns a ReapItem. If the caller calls refresh() on the returned // ReapItem within the expiry interval, the item remains in the list. If no refresh() was sent // for the item within the expiry interval, the reaper removes the item and calls the callback // function that was passed to add(). This lets the caller know that the item expired. // // It is safe to let a reaper go out of scope while there are still ReapItems for it. The methods // on the ReapItem do nothing if they are called after the reaper is gone. class Reaper final : public std::enable_shared_from_this { public: NONCOPYABLE(Reaper); UNITY_DEFINES_PTRS(Reaper); ~Reaper(); enum DestroyPolicy { NoCallbackOnDestroy, CallbackOnDestroy }; // Creates a new reaper. Intervals are in seconds. By default, if the reaper is destroyed while // there are entries in its list, the reaper will *not* invoke the callback from the destructor. // If CallbackOnDestroy is set, the destructor will call the callback of all entries that are // still on the list, whether they have expired or not. // // The reaper thread runs (at most) once every reap_interval seconds. Entries are reaped once // they are at least expiry_interval seconds old. Actual life time is in the range // [expiry_interval, expiry_interval + reap_interval]. // For example, a reap interval of 1 second and expiry interval of 5 seconds means that the // callback for an entry will be made once the entry has not been refreshed for at least 5 seconds // and at most 6 seconds. // The reap interval must be less than or equal to the expiry interval. Otherwise, we would allow // entries to not be refreshed for longer than their expiry interval, then be refreshed again, and // not be reaped on the next pass. // // Reaping passes are O(m) complexity, where m is the number of expired items (not // the total number of items). static SPtr create(int reap_interval, int expiry_interval, DestroyPolicy p = NoCallbackOnDestroy); // Destroys the reaper and returns once any remaining items have been reaped (depending on the // destroy policy). The destructor implicitly calls destroy(). void destroy(); // Adds a new item to the reaper. The reaper calls cb once the item has not been refreshed for at // least expiry_interval seconds. O(1) performance. // The callback passed to add() must not block for any length of time. We have only one reaper // thread, which invokes the callback synchronously. (Invoking the callback asynchronously would be // too expensive because, in the worst case, we would use as many threads as there are expired // entries.) ReapItem::SPtr add(ReaperCallback const& cb); // Returns the number of items in the reaper list. // O(1) performance. size_t size() const noexcept; private: Reaper(int reap_interval, int expiry_interval, DestroyPolicy p); void set_self() noexcept; void start(); void reap_func(); // Start function for reaper thread void remove_zombies(reaper_private::Reaplist const&) noexcept; // Invokes callbacks for expired entries std::weak_ptr self_; // We keep a weak reference to ourselves, to pass to each ReapItem. std::chrono::seconds reap_interval_; // How frequently we look for entries to reap std::chrono::seconds expiry_interval_; // How long before an entry times out DestroyPolicy policy_; // Whether to invoke callback on entries still present when reaper is destroyed reaper_private::Reaplist list_; // Items in LRU order, most recently refreshed one at the front. mutable std::mutex mutex_; // Protects list_. Also used by ReapItem to serialize updates to list_. std::thread reap_thread_; // Reaper thread scans list_ and issues callbacks for timed-out entries std::condition_variable do_work_; // Reaper thread waits on this bool finish_; // Set when reaper thread needs to terminate friend class ReapItem; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/InvokeInfo.h0000644000015301777760000000254212320776161027461 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_INVOKEINFO_H #define UNITY_SCOPES_INTERNAL_INVOKEINFO_H #include namespace unity { namespace scopes { namespace internal { class MiddlewareBase; // InvokeInfo is passed to all server-side implementation objects. It is intended // mainly for the implementation of default servants, which need to incarnate // different middleware object (that is, conceptual object) on a per-request basis. struct InvokeInfo { std::string const& id; // Identity of invocation target MiddlewareBase* mw; // Middleware for this request }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/QueryObject.h0000644000015301777760000000555512320776161027655 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_QUERYOBJECT_H #define UNITY_SCOPES_INTERNAL_QUERYOBJECT_H #include #include #include #include #include namespace unity { namespace scopes { class QueryBase; namespace internal { // A QueryObject sits in between the incoming requests from the middleware layer and the // QueryBase-derived implementation. This allows us to receive cancel requests. In turn, // the implementation of this object ensures that the corresponding ReplyObject is disabled. // TODO: Probably need to flesh out this comment. class QueryObject : public QueryObjectBase { public: UNITY_DEFINES_PTRS(QueryObject); QueryObject(std::shared_ptr const& query_base, MWReplyProxy const& reply, MWQueryCtrlProxy const& ctrl); QueryObject(std::shared_ptr const& query_base, int cardinality, MWReplyProxy const& reply, MWQueryCtrlProxy const& ctrl); virtual ~QueryObject(); // Remote operation implementations virtual void run(MWReplyProxy const& reply, InvokeInfo const& info) noexcept override; // Local methods virtual void cancel(InvokeInfo const& info) override; // Called locally, by QueryCtrlObject. virtual bool pushable(InvokeInfo const& info) const noexcept override; // Called locally, by ReplyImpl virtual int cardinality(InvokeInfo const& info) const noexcept override; // Called locally, by ReplyImpl // Called by create_query(), to hold the reference count high until the run call arrives via the middleware, // and we can pass the shared_ptr to the ReplyImpl. void set_self(QueryObjectBase::SPtr const& self) noexcept override; protected: std::shared_ptr query_base_; MWReplyProxy reply_; std::weak_ptr reply_proxy_; MWQueryCtrlProxy const ctrl_; std::atomic_bool pushable_; QueryObjectBase::SPtr self_; std::atomic_int cardinality_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/JsonNodeInterface.h0000644000015301777760000000431212320776161030747 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_JSONNODEINTERFACE_H #define UNITY_SCOPES_INTERNAL_JSONNODEINTERFACE_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class JsonNodeInterface { public: NONCOPYABLE(JsonNodeInterface); UNITY_DEFINES_PTRS(JsonNodeInterface); enum NodeType { Null, Array, Object, String, Int, UInt, Real, Bool }; JsonNodeInterface() = default; virtual ~JsonNodeInterface() = default; virtual void clear() = 0; virtual void read_json(std::string const& json_string) = 0; virtual std::string to_json_string() const = 0; virtual Variant to_variant() const = 0; virtual int size() const = 0; virtual std::vector member_names() const = 0; virtual NodeType type() const = 0; virtual std::string as_string() const = 0; virtual int as_int() const = 0; virtual uint as_uint() const = 0; virtual double as_double() const = 0; virtual bool as_bool() const = 0; virtual bool has_node(std::string const& node_name) const = 0; virtual JsonNodeInterface::SPtr get_node() const = 0; virtual JsonNodeInterface::SPtr get_node(std::string const& node_name) const = 0; virtual JsonNodeInterface::SPtr get_node(uint node_index) const = 0; }; } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_JSONNODEINTERFACE_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/SearchReplyImpl.h0000644000015301777760000000521212320776161030452 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_SEARCHREPLYIMPL_H #define UNITY_SCOPES_INTERNAL_SEARCHREPLYIMPL_H #include #include #include #include #include #include #include #include #include namespace unity { namespace scopes { class CategorisedResult; class CategoryRenderer; class Annotation; namespace internal { class QueryObjectBase; class SearchReplyImpl : public virtual unity::scopes::SearchReply, public virtual ReplyImpl { public: SearchReplyImpl(MWReplyProxy const& mw_proxy, std::shared_ptrconst & qo); virtual ~SearchReplyImpl(); virtual void register_departments(DepartmentList const& departments, std::string current_department_id) override; virtual Category::SCPtr register_category(std::string const& id, std::string const& title, std::string const &icon, CategoryRenderer const& renderer_template) override; virtual void register_category(Category::SCPtr category) override; virtual Category::SCPtr lookup_category(std::string const& id) override; virtual bool register_annotation(unity::scopes::Annotation const& annotation) override; virtual bool push(unity::scopes::CategorisedResult const& result) override; virtual bool push(unity::scopes::Filters const& filters, unity::scopes::FilterState const& filter_state) override; private: bool push(Category::SCPtr category); std::shared_ptr cat_registry_; std::atomic_int cardinality_; std::atomic_int num_pushes_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/smartscopes/0000755000015301777760000000000012320776463027606 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/smartscopes/SSQueryCtrlObject.h0000644000015301777760000000337612320776161033312 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_SMARTSCOPES_SSQUERYCTRLOBJECT_H #define UNITY_SCOPES_INTERNAL_SMARTSCOPES_SSQUERYCTRLOBJECT_H #include #include namespace unity { namespace scopes { namespace internal { class QueryObjectBase; namespace smartscopes { class SSQueryCtrlObject final : public QueryCtrlObjectBase { public: UNITY_DEFINES_PTRS(SSQueryCtrlObject); SSQueryCtrlObject(); virtual ~SSQueryCtrlObject(); // Remote operation implementations virtual void cancel(InvokeInfo const& info) override; virtual void destroy(InvokeInfo const& info) override; // Called by create_query() after instantiation to tell this ctrl what its corresponding // query facade is. void set_query(std::shared_ptr const& qo); private: std::weak_ptr qo_; std::atomic_bool destroyed_; }; } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_SMARTSCOPES_SSQUERYCTRLOBJECT_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/smartscopes/SSRegistryObject.h0000644000015301777760000000524512320776161033165 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_SMARTSCOPES_SSREGISTRYOBJECT_H #define UNITY_SCOPES_INTERNAL_SMARTSCOPES_SSREGISTRYOBJECT_H #include #include #include #include namespace unity { namespace scopes { namespace internal { namespace smartscopes { class SSRegistryObject final : public RegistryObjectBase { public: UNITY_DEFINES_PTRS(SSRegistryObject); SSRegistryObject(MiddlewareBase::SPtr middleware, std::string const& ss_scope_endpoint, uint http_reply_timeout, uint refresh_rate_in_sec, std::string const& sss_url = "", bool caching_enabled = true); virtual ~SSRegistryObject() noexcept; ScopeMetadata get_metadata(std::string const& scope_id) const override; MetadataMap list() const override; ObjectProxy locate(std::string const& identity) override; bool has_scope(std::string const& scope_id) const; std::string get_base_url(std::string const& scope_id) const; SmartScopesClient::SPtr get_ssclient() const; private: void refresh_thread(); void get_remote_scopes(); static bool add(RemoteScope const& remotedata, ScopeMetadata const& scope, MetadataMap& scopes, std::map& urls); private: SmartScopesClient::SPtr ssclient_; MetadataMap scopes_; std::map base_urls_; mutable std::mutex scopes_mutex_; std::thread refresh_thread_; std::mutex refresh_mutex_; std::condition_variable_any refresh_cond_; bool refresh_stopped_; MiddlewareBase::SPtr middleware_; std::string ss_scope_endpoint_; uint const regular_refresh_timeout_; uint next_refresh_timeout_; bool caching_enabled_; }; } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_SMARTSCOPES_SSREGISTRYOBJECT_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/smartscopes/SmartScopesClient.h0000644000015301777760000001221712320776161033357 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_SMARTSCOPES_SMARTSCOPESCLIENT_H #define UNITY_SCOPES_INTERNAL_SMARTSCOPES_SMARTSCOPESCLIENT_H #include #include #include #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { namespace smartscopes { class SmartScopesClient; struct RemoteScope { std::string id; std::string name; std::string description; std::string author; std::string base_url; std::shared_ptr icon; // optional std::shared_ptr art; // optional bool invisible = false; }; struct SearchCategory { std::string id; std::string title; std::string icon; std::string renderer_template; }; struct SearchResult { std::string json; std::string uri; std::map other_params; std::shared_ptr category; }; class SearchHandle { public: NONCOPYABLE(SearchHandle); UNITY_DEFINES_PTRS(SearchHandle); ~SearchHandle(); std::vector get_search_results(); void cancel_search(); private: friend class SmartScopesClient; SearchHandle(uint search_id, std::shared_ptr ssc); private: uint search_id_; std::shared_ptr ssc_; }; class PreviewHandle { public: NONCOPYABLE(PreviewHandle); UNITY_DEFINES_PTRS(PreviewHandle); ~PreviewHandle(); using Columns = std::vector>>; using Widgets = std::vector; std::pair get_preview_results(); void cancel_preview(); private: friend class SmartScopesClient; PreviewHandle(uint preview_id, std::shared_ptr ssc); private: uint preview_id_; std::shared_ptr ssc_; }; class SmartScopesClient : public std::enable_shared_from_this { public: NONCOPYABLE(SmartScopesClient); UNITY_DEFINES_PTRS(SmartScopesClient); SmartScopesClient(HttpClientInterface::SPtr http_client, JsonNodeInterface::SPtr json_node, std::string const& url = ""); // detect url virtual ~SmartScopesClient(); void reset_url(std::string const& url = ""); std::string url(); bool get_remote_scopes(std::vector& scopes, std::string const& locale = "", bool caching_enabled = true); SearchHandle::UPtr search(std::string const& base_url, std::string const& query, std::string const& department_id, std::string const& session_id, uint query_id, std::string const& platform, std::string const& locale = "", std::string const& country = "", const uint limit = 0); PreviewHandle::UPtr preview(std::string const& base_url, std::string const& result, std::string const& session_id, std::string const& platform, const uint widgets_api_version, std::string const& locale = "", std::string const& country = ""); private: friend class SearchHandle; friend class PreviewHandle; std::vector get_search_results(uint search_id); std::pair get_preview_results(uint preview_id); std::vector extract_json_stream(std::string const& json_stream); void cancel_query(uint query_id); void write_cache(std::string const& scopes_json); std::string read_cache(); private: HttpClientInterface::SPtr http_client_; JsonNodeInterface::SPtr json_node_; std::string url_; std::map query_results_; std::mutex json_node_mutex_; std::mutex query_results_mutex_; std::string cached_scopes_; bool have_latest_cache_; uint query_counter_; }; } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_SMARTSCOPES_SMARTSCOPESCLIENT_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/smartscopes/HttpClientQtThread.h0000644000015301777760000000401712320776161033467 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_SMARTSCOPES_HTTPCLIENTQTTHREAD_H #define UNITY_SCOPES_INTERNAL_SMARTSCOPES_HTTPCLIENTQTTHREAD_H // This hack allows unity-scopes-api to be built with // clang-3.4+ and versions of Qt before v5.1.1. #if QT_VERSION < 0x050101 #define register #include #define qHash(x,y) qHash(const QUrl &url, uint seed) #include #undef qHash #undef register #else #include #include #endif #include #include class QNetworkReply; class QNetworkAccessManager; namespace unity { namespace scopes { namespace internal { namespace smartscopes { class Q_DECL_EXPORT HttpClientQtThread : public QThread { Q_OBJECT public: NONCOPYABLE(HttpClientQtThread); HttpClientQtThread(const QUrl& url, uint timeout); ~HttpClientQtThread(); bool get_reply(std::string& reply); private: void run(); public Q_SLOTS: void cancel(); void timeout(); void got_reply(QNetworkReply* reply); Q_SIGNALS: void abort(); private: QUrl url_; uint timeout_; std::mutex reply_mutex_; bool success_; std::string reply_; }; } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_SMARTSCOPES_HTTPCLIENTQTTHREAD_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/smartscopes/HttpClientQt.h0000644000015301777760000000433612320776161032343 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_SMARTSCOPES_HTTPCLIENTQT_H #define UNITY_SCOPES_INTERNAL_SMARTSCOPES_HTTPCLIENTQT_H #include #include class QCoreApplication; namespace unity { namespace scopes { namespace internal { namespace smartscopes { class HttpClientQtThread; class HttpClientQt : public HttpClientInterface { public: explicit HttpClientQt(uint no_reply_timeout); ~HttpClientQt(); HttpResponseHandle::SPtr get(std::string const& request_url) override; std::string to_percent_encoding(std::string const& string) override; private: void cancel_get(uint session_id) override; private: class HttpSession { public: HttpSession(std::string const& request_url, uint timeout); ~HttpSession(); std::future get_future(); void cancel_session(); void wait_for_session(); private: std::shared_ptr> promise_; std::thread get_thread_; std::unique_ptr qt_thread_; std::mutex qt_thread_mutex_; std::promise qt_thread_ready_; }; private: uint session_index_; std::map> sessions_; std::mutex sessions_mutex_; uint const no_reply_timeout_; std::unique_ptr app_; }; } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_SMARTSCOPES_HTTPCLIENTQT_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/smartscopes/SSQueryObject.h0000644000015301777760000000630112320776161032454 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_SMARTSCOPES_SSQUERYOBJECT_H #define UNITY_SCOPES_INTERNAL_SMARTSCOPES_SSQUERYOBJECT_H #include #include #include #include #include namespace unity { namespace scopes { class QueryBase; namespace internal { namespace smartscopes { struct SSQuery { UNITY_DEFINES_PTRS(SSQuery); enum QueryType { Query, Activation, Preview }; SSQuery(QueryType type, std::shared_ptr base, int cardinality, MWReplyProxy reply) : q_type(type), q_base(base), q_cardinality(cardinality), q_reply(reply) {} QueryType q_type; std::shared_ptr q_base; int q_cardinality; MWReplyProxy q_reply; std::weak_ptr q_reply_proxy; bool q_pushable = true; }; class SSQueryObject : public QueryObjectBase, public std::enable_shared_from_this { public: UNITY_DEFINES_PTRS(SSQueryObject); SSQueryObject(); virtual ~SSQueryObject() noexcept; // Remote operation implementations virtual void run(MWReplyProxy const& reply, InvokeInfo const& info) noexcept override; // Local methods virtual void cancel(InvokeInfo const& info) override; // Called locally, by QueryCtrlObject. virtual bool pushable(InvokeInfo const& info) const noexcept override; // Called locally, by ReplyImpl virtual int cardinality(InvokeInfo const& info) const noexcept override; // Called locally, by ReplyImpl void set_self(QueryObjectBase::SPtr const& self) noexcept override; void add_query(SSQuery::QueryType query_type, std::shared_ptr const& query_base, int cardinality, MWReplyProxy const& reply); void add_query(SSQuery::QueryType query_type, std::shared_ptr const& query_base, MWReplyProxy const& reply); private: void run_query(SSQuery::SPtr query, MWReplyProxy const& reply); void run_preview(SSQuery::SPtr query, MWReplyProxy const& reply); void run_activation(SSQuery::SPtr query, MWReplyProxy const& reply); private: mutable std::mutex queries_mutex_; std::map queries_; // reply ID : query }; } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_SMARTSCOPES_SSQUERYOBJECT_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/smartscopes/CMakeLists.txt0000644000015301777760000000020212320776161032333 0ustar pbusernogroup00000000000000file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h") set(UNITY_SCOPES_LIB_HDRS ${UNITY_SCOPES_LIB_HDRS} ${headers} PARENT_SCOPE) unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/smartscopes/SSScopeObject.h0000644000015301777760000000636012320776161032425 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_SMARTSCOPES_SSSCOPEOBJECT_H #define UNITY_SCOPES_INTERNAL_SMARTSCOPES_SSSCOPEOBJECT_H #include #include #include #include #include #include namespace unity { namespace scopes { class ActionMetadata; namespace internal { namespace smartscopes { class SmartScope; class SSScopeObject final : public ScopeObjectBase { public: UNITY_DEFINES_PTRS(SSScopeObject); SSScopeObject(std::string const& ss_scope_id, MiddlewareBase::SPtr middleware, SSRegistryObject::SPtr ss_registry); virtual ~SSScopeObject() noexcept; // Remote operation implementations MWQueryCtrlProxy search(CannedQuery const& q, SearchMetadata const& hints, MWReplyProxy const& reply, InvokeInfo const& info) override; MWQueryCtrlProxy activate(Result const& result, ActionMetadata const& hints, MWReplyProxy const& reply, InvokeInfo const& info) override; MWQueryCtrlProxy perform_action(Result const& result, ActionMetadata const& hints, std::string const& widget_id, std::string const& action_id, MWReplyProxy const& reply, InvokeInfo const& info) override; MWQueryCtrlProxy preview(Result const& result, ActionMetadata const& hints, MWReplyProxy const& reply, InvokeInfo const& info) override; private: MWQueryCtrlProxy query(InvokeInfo const& info, MWReplyProxy const& reply, std::function const& query_factory_fun, std::function const& query_object_fun); private: std::string ss_scope_id_; SSQueryCtrlObject::SPtr co_; SSQueryObject::SPtr qo_; std::unique_ptr const smartscope_; SSRegistryObject::SPtr ss_registry_; }; } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_SMARTSCOPES_SSSCOPEOBJECT_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/smartscopes/SmartScope.h0000644000015301777760000001766412320776200032042 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include #include #include #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { namespace smartscopes { class SmartQuery : public SearchQueryBase { public: SmartQuery(std::string const& scope_id, SSRegistryObject::SPtr reg, CannedQuery const& query, SearchMetadata const& hints) : scope_id_(scope_id) , query_(query) { static const std::string no_net_hint("no-internet"); if (hints.contains_hint(no_net_hint)) { auto var = hints[no_net_hint]; if (var.which() == Variant::Type::Bool && var.get_bool()) { std::cout << "SmartQuery(): networking disabled for remote scope " << scope_id << ", skipping" << std::endl; return; } } SmartScopesClient::SPtr ss_client = reg->get_ssclient(); std::string base_url = reg->get_base_url(scope_id_); ///! TODO: session_id, query_id, locale, country search_handle_ = ss_client->search(base_url, query_.query_string(), query.department_id(), "session_id", 0, hints.form_factor(), "", "", hints.cardinality()); } ~SmartQuery() noexcept { } virtual void cancelled() override { if (search_handle_ != nullptr) { search_handle_->cancel_search(); } } virtual void run(SearchReplyProxy const& reply) override { if (search_handle_ == nullptr) { // this can happen if networking is disabled return; } std::vector results = search_handle_->get_search_results(); std::map categories; for (auto& result : results) { if (!result.category) { std::cerr << "SmartScope: result for query: \"" << scope_id_ << "\": \"" << query_.query_string() << "\" returned an invalid cat_id. Skipping result." << std::endl; continue; } Category::SCPtr cat; auto cat_it = categories.find(result.category->id); if (cat_it == end(categories)) { CategoryRenderer rdr(result.category->renderer_template); cat = reply->register_category(result.category->id, result.category->title, result.category->icon, rdr); categories[result.category->id] = cat; } else { cat = cat_it->second; } CategorisedResult res(cat); res.set_uri(result.uri); res["result_json"] = result.json; auto other_params = result.other_params; for (auto& param : other_params) { res[param.first] = param.second->to_variant(); } reply->push(res); } std::cout << "SmartScope: query for \"" << scope_id_ << "\": \"" << query_.query_string() << "\" complete" << std::endl; } private: std::string scope_id_; CannedQuery query_; SearchHandle::UPtr search_handle_; }; class SmartPreview : public PreviewQueryBase { public: SmartPreview(std::string const& scope_id, SSRegistryObject::SPtr reg, Result const& result, ActionMetadata const& hints) : scope_id_(scope_id) , result_(result) { SmartScopesClient::SPtr ss_client = reg->get_ssclient(); std::string base_url = reg->get_base_url(scope_id_); ///! TODO: session_id, widgets_api_version, locale, country preview_handle_ = ss_client->preview(base_url, result_["result_json"].get_string(), "session_id", hints.form_factor(), 0, "", ""); } ~SmartPreview() { } virtual void cancelled() override { preview_handle_->cancel_preview(); } virtual void run(PreviewReplyProxy const& reply) override { auto results = preview_handle_->get_preview_results(); PreviewHandle::Columns columns = results.first; PreviewHandle::Widgets widgets = results.second; // register layout if (columns.size() > 0) { ColumnLayoutList layout_list; for (auto& column : columns) { ColumnLayout layout(column.size()); for (auto& widget_lo : column) { layout.add_column(widget_lo); } layout_list.emplace_back(layout); } reply->register_layout(layout_list); } // push wigdets PreviewWidgetList widget_list; for (auto& widget_json : widgets) { widget_list.emplace_back(PreviewWidget(widget_json)); } reply->push(widget_list); std::cout << "SmartScope: preview for \"" << scope_id_ << "\": \"" << result_.uri() << "\" complete" << std::endl; } private: std::string scope_id_; Result result_; PreviewHandle::UPtr preview_handle_; }; class NullActivation : public ActivationQueryBase { ActivationResponse activate() override { return ActivationResponse(ActivationResponse::Status::NotHandled); } }; class SmartActivation : public ActivationQueryBase { ActivationResponse activate() override { ///! TODO: need SSS endpoint for this return ActivationResponse(ActivationResponse::Status::NotHandled); } }; class SmartScope { public: SmartScope(SSRegistryObject::SPtr reg) : reg_(reg) { } QueryBase::UPtr search(std::string const& scope_id, CannedQuery const& q, SearchMetadata const& hints) { QueryBase::UPtr query(new SmartQuery(scope_id, reg_, q, hints)); std::cout << "SmartScope: created query for \"" << scope_id << "\": \"" << q.query_string() << "\"" << std::endl; return query; } QueryBase::UPtr preview(std::string const& scope_id, Result const& result, ActionMetadata const& hints) { QueryBase::UPtr preview(new SmartPreview(scope_id, reg_, result, hints)); std::cout << "SmartScope: created preview for \"" << scope_id << "\": \"" << result.uri() << "\"" << std::endl; return preview; } ActivationQueryBase::UPtr activate(std::string const&, Result const&, ActionMetadata const&) { ActivationQueryBase::UPtr activation(new NullActivation()); return activation; } ActivationQueryBase::UPtr perform_action(std::string const& scope_id, Result const& result, ActionMetadata const& /*hints*/, std::string const& /*widget_id*/, std::string const& /*action_id*/) { ActivationQueryBase::UPtr activation(new SmartActivation()); std::cout << "SmartScope: created activation for \"" << scope_id << "\": \"" << result.uri() << "\"" << std::endl; return activation; } private: SSRegistryObject::SPtr reg_; }; } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/smartscopes/HttpClientInterface.hunity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/smartscopes/HttpClientInterface.0000644000015301777760000000463412320776161033510 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_SMARTSCOPES_HTTPCLIENTINTERFACE_H #define UNITY_SCOPES_INTERNAL_SMARTSCOPES_HTTPCLIENTINTERFACE_H #include #include #include namespace unity { namespace scopes { namespace internal { namespace smartscopes { class HttpResponseHandle; class HttpClientInterface : public std::enable_shared_from_this { public: NONCOPYABLE(HttpClientInterface); UNITY_DEFINES_PTRS(HttpClientInterface); HttpClientInterface() = default; virtual ~HttpClientInterface() = default; virtual std::shared_ptr get(std::string const& request_url) = 0; virtual std::string to_percent_encoding(std::string const& string) = 0; private: friend class HttpResponseHandle; virtual void cancel_get(uint session_id) = 0; }; class HttpResponseHandle { public: NONCOPYABLE(HttpResponseHandle); UNITY_DEFINES_PTRS(HttpResponseHandle); HttpResponseHandle(HttpClientInterface::SPtr client, uint session_id, std::shared_future future) : client_(client) , session_id_(session_id) , future_(future) { } ~HttpResponseHandle() { cancel(); } void wait() { future_.wait(); } std::string get() { return future_.get(); } void cancel() { client_->cancel_get(session_id_); } private: std::shared_ptr client_; uint session_id_; std::shared_future future_; }; } // namespace smartscopes } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_SMARTSCOPES_HTTPCLIENTINTERFACE_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ReplyImpl.h0000644000015301777760000000343012320776161027324 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_REPLYIMPL_H #define UNITY_SCOPES_INTERNAL_REPLYIMPL_H #include #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class QueryObjectBase; class ReplyImpl : public virtual unity::scopes::Reply, public virtual ObjectImpl { public: ReplyImpl(MWReplyProxy const& mw_proxy, std::shared_ptrconst & qo); virtual ~ReplyImpl(); virtual void finished() override; void finished(unity::scopes::ListenerBase::Reason reason); virtual void error(std::exception_ptr ex) override; typedef std::function CleanupFunc; protected: bool push(VariantMap const& variant_map); MWReplyProxy fwd() const; private: std::shared_ptr qo_; std::atomic_bool finished_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/DynamicLoader.h0000644000015301777760000000745412320776161030134 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_DYNAMICLOADER_H #define UNITY_SCOPES_INTERNAL_DYNAMICLOADER_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { // // Simple helper class that wraps dlopen(), dlsym() and dlclose(). // // To use it, call create() with a path. If the supplied path contains a slash, the library will be loaded // from the specified location; otherwise, the usual lookup performed by dlopen() applies. // // The Binding flag determines whether unresolved external functions are diagnosed only when a function // requiring an unresolved symbol is looked for (lazy binding) or whether all functions are bound // immediately on loading. (References to variables are always bound immediately, regardless of the flag.) // // By default, the destructor calls dlclose(). If you don't want the destructor to call dlclose(), pass // Unload::noclose to create(). This will leave the library loaded in memory, even after this instance is destroyed. // Note that, if a thread is still executing inside the library when it is unloaded, or if the code elsewhere // still holds a reference to something in the library and uses the reference once the library is unloaded, // the behavior is undefined. // // To resolve a symbol in the library, call find_function() or find_variable(). // If the symbol can't be located, these calls throw unity::ResourceException. // // find_function() returns a pointer to a function returning void and accepting no arguments. // find_variable() returns a void*. // You are responsible for casting the return value to the correct type. Dereferencing the returned pointer // after casting it to the wrong type has undefined behavior. // // Any other errors from the underlying dlopen(), dlsym(), and dlclose() functions throw unity::ResourceException. // // Typical use pattern: // // DynamicLoader::UPtr dl = DynamicLoader::create("libexample.so"); // // ... // DynamicLoader::VoidFunc f = dl->find_function("some_function"); // void (*int_func)(int) = reinterpret_cast(f); // int_func(5); // class DynamicLoader { public: NONCOPYABLE(DynamicLoader); UNITY_DEFINES_PTRS(DynamicLoader); enum class Binding { lazy, now }; enum class Unload { automatic, noclose }; static UPtr create(std::string const& path, Binding b = Binding::lazy, Unload ul = Unload::automatic); typedef void (*VoidFunc)(); VoidFunc find_function(std::string const& symbol); void* find_variable(std::string const& symbol); std::string path() const; ~DynamicLoader(); private: DynamicLoader(std::string const& path, Binding b, Unload ul); std::string path_; void* handle_; Unload unload_; typedef std::map LibraryHandles; static LibraryHandles handles_; // Handles of libraries that will not be unloaded static std::mutex mutex_; // Protects m_handle_map }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWObjectProxyFwd.h0000644000015301777760000000201612320776161030563 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MWOBJECTPROXYFWD_H #define UNITY_SCOPES_INTERNAL_MWOBJECTPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { class MWObjectProxy; typedef std::shared_ptr MWProxy; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/LinkImpl.h0000644000015301777760000000251512320776161027131 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_HYPERLINKIMPL_H #define UNITY_SCOPES_INTERNAL_HYPERLINKIMPL_H #include #include #include #include namespace unity { namespace scopes { namespace internal { class LinkImpl { public: LinkImpl(std::string const& label, CannedQuery const& query); LinkImpl(VariantMap const& variant_map); std::string label() const; CannedQuery query() const; VariantMap serialize() const; private: std::string label_; CannedQuery::SCPtr query_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ScopeMetadataImpl.h0000644000015301777760000000665412320776161030756 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the Lesser GNU General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_SCOPEMETADATAIMPL_H #define UNITY_SCOPES_INTERNAL_SCOPEMETADATAIMPL_H #include #include #include namespace unity { namespace scopes { namespace internal { class ScopeMetadataImpl { public: ScopeMetadataImpl(MiddlewareBase* mw); ScopeMetadataImpl(VariantMap const& variant_map, MiddlewareBase* mw); ScopeMetadataImpl(ScopeMetadataImpl const&); ScopeMetadataImpl(ScopeMetadataImpl&&) = default; ScopeMetadataImpl& operator=(ScopeMetadataImpl const&); ScopeMetadataImpl& operator=(ScopeMetadataImpl&&) = default; std::string scope_id() const; ScopeProxy proxy() const; std::string display_name() const; // localized std::string description() const; // localized std::string author() const; std::string art() const; // optional std::string icon() const; // optional std::string search_hint() const; // localized, optional std::string hot_key() const; // localized, optional bool invisible() const; // optional (default = false) VariantMap appearance_attributes() const; // optional (default: empty map) std::string scope_directory() const; void set_scope_id(std::string const& scope_id); void set_proxy(ScopeProxy const& proxy); void set_display_name(std::string const& display_name); void set_description(std::string const& description); void set_author(std::string const& author); void set_art(std::string const& art); void set_icon(std::string const& icon); void set_search_hint(std::string const& search_hint); void set_hot_key(std::string const& hot_key); void set_invisible(bool invisible); void set_appearance_attributes(VariantMap const& appearance_attributes); void set_scope_directory(std::string const& path); VariantMap serialize() const; void deserialize(VariantMap const& var); static ScopeMetadata create(std::unique_ptr impl); private: MiddlewareBase* mw_; std::string scope_id_; ScopeProxy proxy_; std::string display_name_; std::string description_; std::string author_; std::unique_ptr art_; // Optional, hence a pointer std::unique_ptr icon_; // Optional, hence a pointer std::unique_ptr search_hint_; // Optional, hence a pointer std::unique_ptr hot_key_; // Optional, hence a pointer std::unique_ptr invisible_; // Optional, hence a pointer std::unique_ptr scope_directory_; VariantMap appearance_attributes_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/StateReceiverObject.h0000644000015301777760000000321512320776161031304 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_STATERECEIVEROBJECT_H #define UNITY_SCOPES_INTERNAL_STATERECEIVEROBJECT_H #include #include #include #include namespace unity { namespace scopes { namespace internal { class StateReceiverObject : public AbstractObject { public: UNITY_DEFINES_PTRS(StateReceiverObject); enum State { ScopeReady, ScopeStopping }; StateReceiverObject(); virtual ~StateReceiverObject(); // Remote operation implementations void push_state(std::string const& sender_id, State const& state); // Local methods core::Signal const& state_received() const; private: core::Signal state_received_; }; } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_STATERECEIVEROBJECT_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/RegistryConfig.h0000644000015301777760000000414512320776161030351 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_REGISTRYCONFIG_H #define UNITY_SCOPES_INTERNAL_REGISTRYCONFIG_H #include namespace unity { namespace scopes { namespace internal { class RegistryConfig : public ConfigBase { public: static constexpr char const* REGISTRY_CONFIG_GROUP = "Registry"; RegistryConfig(std::string const& identity, std::string const& configfile); ~RegistryConfig(); std::string identity() const; std::string mw_kind() const; std::string endpointdir() const; std::string endpoint() const; std::string mw_configfile() const; std::string scope_installdir() const; // Directory for Canonical scopes std::string oem_installdir() const; // Directory for OEM scope config files std::string scoperunner_path() const; // Path to scoperunner binary std::string ss_registry_identity() const; // Identity of smart scopes registry std::string ss_registry_endpoint() const; // Endpoint of smart scopes registry private: std::string identity_; std::string mw_kind_; std::string endpointdir_; std::string endpoint_; std::string mw_configfile_; std::string scope_installdir_; std::string oem_installdir_; std::string scoperunner_path_; std::string ss_registry_identity_; std::string ss_registry_endpoint_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/UniqueID.h0000644000015301777760000000321412320776161027072 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_UNIQUEID_H #define UNITY_SCOPES_INTERNAL_UNIQUEID_H #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { // Poor man's thread-safe unique ID generator. // Generates a random number concatenated with a counter. // Return value is a string of 16 hex digits. class UniqueID { public: NONCOPYABLE(UniqueID); UniqueID(); // Gets seed from std::random_device explicit UniqueID(std::mt19937::result_type seed); // Uses specified seed std::string gen(); // Returns a unique id private: std::mt19937 engine; std::uniform_int_distribution uniform_dist; int counter; std::ostringstream s; std::mutex m; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/VariantBuilderImpl.h0000644000015301777760000000313612320776161031147 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_VARIANTBUILDER_H #define UNITY_SCOPES_INTERNAL_VARIANTBUILDER_H #include #include #include namespace unity { namespace scopes { namespace internal { class VariantBuilderImpl final { public: VariantBuilderImpl() = default; VariantBuilderImpl(VariantBuilderImpl const& other); VariantBuilderImpl(VariantBuilderImpl&&) = default; ~VariantBuilderImpl() = default; VariantBuilderImpl& operator=(VariantBuilderImpl const& other) = delete; VariantBuilderImpl& operator=(VariantBuilderImpl&&) = default; void add_tuple(std::initializer_list> const& tuple); void add_tuple(std::vector> const& tuple); Variant end(); private: std::unique_ptr variant_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/JsonCppNode.h0000644000015301777760000000432012320776161027570 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_JSONCPPNODE_H #define UNITY_SCOPES_INTERNAL_JSONCPPNODE_H #include #include #include namespace unity { namespace scopes { namespace internal { class JsonCppNode : public JsonNodeInterface { public: explicit JsonCppNode(std::string const& json_string = ""); explicit JsonCppNode(const Json::Value& root); explicit JsonCppNode(const Variant& var); ~JsonCppNode(); void clear() override; void read_json(std::string const& json_string) override; std::string to_json_string() const override; Variant to_variant() const override; int size() const override; std::vector member_names() const override; NodeType type() const override; std::string as_string() const override; int as_int() const override; uint as_uint() const override; double as_double() const override; bool as_bool() const override; bool has_node(std::string const& node_name) const override; JsonNodeInterface::SPtr get_node() const override; JsonNodeInterface::SPtr get_node(std::string const& node_name) const override; JsonNodeInterface::SPtr get_node(uint node_index) const override; private: static Json::Value from_variant(Variant const& var); static Variant to_variant(Json::Value const &val); Json::Value root_; }; } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_JSONCPPNODE_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/QueryCtrlObject.h0000644000015301777760000000314512320776161030473 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_QUERYCTRLOBJECT_H #define UNITY_SCOPES_INTERNAL_QUERYCTRLOBJECT_H #include #include namespace unity { namespace scopes { namespace internal { class QueryObjectBase; class QueryCtrlObject final : public QueryCtrlObjectBase { public: UNITY_DEFINES_PTRS(QueryCtrlObject); QueryCtrlObject(); virtual ~QueryCtrlObject(); // Remote operation implementations virtual void cancel(InvokeInfo const& info) override; virtual void destroy(InvokeInfo const& info) override; // Called by create_query() after instantiation to tell this ctrl what its corresponding // query facade is. void set_query(std::shared_ptr const& qo); private: std::weak_ptr qo_; std::atomic_bool destroyed_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ScopeBaseImpl.h0000644000015301777760000000227112320776161030077 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_SCOPEBASEIMPL_H #define UNITY_SCOPES_INTERNAL_SCOPEBASEIMPL_H #include namespace unity { namespace scopes { namespace internal { class ScopeBaseImpl final { public: ScopeBaseImpl() = default; ~ScopeBaseImpl() = default; void set_scope_directory(std::string const &path); std::string scope_directory() const; private: std::string scope_directory_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/DfltConfig.h.in0000644000015301777760000000236012320776161030034 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michal Hruby */ #ifndef UNITY_SCOPES_DFLTCONFIG_H #define UNITY_SCOPES_DFLTCONFIG_H namespace unity { namespace scopes { namespace internal { static constexpr const char* DFLT_RUNTIME_INI = "@CMAKE_INSTALL_PREFIX@/@SCOPES_DEFAULT_CONFIGDIR@/Runtime.ini"; static constexpr const char* DFLT_SS_RUNTIME_INI = "@CMAKE_INSTALL_PREFIX@/@SCOPES_DEFAULT_CONFIGDIR@/SSRuntime.ini"; static constexpr const char* DFLT_REGISTRY_INI = "@CMAKE_INSTALL_PREFIX@/@SCOPES_DEFAULT_CONFIGDIR@/Registry.ini"; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWQueryProxyFwd.h0000644000015301777760000000200512320776161030460 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MWQUERYPROXYFWD_H #define UNITY_SCOPES_INTERNAL_MWQUERYPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { class MWQuery; typedef std::shared_ptr MWQueryProxy; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MiddlewareBase.h0000644000015301777760000000771712320776161030273 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MIDDLEWAREBASE_H #define UNITY_SCOPES_INTERNAL_MIDDLEWAREBASE_H #include #include #include #include #include #include #include #include #include #include #include #include namespace unity { namespace scopes { class ScopeBase; namespace internal { class RuntimeImpl; // Abstract base class for our middleware transport. Any control functions we need can be added here // as pure virtual functions. This is used by the remainder of the code to do things to the middleware // without knowing which middleware it actually is. class MiddlewareBase { public: NONCOPYABLE(MiddlewareBase); UNITY_DEFINES_PTRS(MiddlewareBase); MiddlewareBase(RuntimeImpl* runtime); virtual ~MiddlewareBase(); virtual void start() = 0; virtual void stop() = 0; virtual void wait_for_shutdown() = 0; virtual ObjectProxy string_to_proxy(std::string const& s) = 0; virtual std::string proxy_to_string(MWProxy const& proxy) = 0; virtual MWRegistryProxy create_registry_proxy(std::string const& identity, std::string const& endpoint) = 0; virtual MWScopeProxy create_scope_proxy(std::string const& identity) = 0; virtual MWScopeProxy create_scope_proxy(std::string const& identity, std::string const& endpoint) = 0; virtual MWQueryProxy create_query_proxy(std::string const& identity, std::string const& endpoint) = 0; virtual MWQueryCtrlProxy create_query_ctrl_proxy(std::string const& identity, std::string const& endpoint) = 0; virtual MWStateReceiverProxy create_state_receiver_proxy(std::string const& identity) = 0; virtual MWQueryCtrlProxy add_query_ctrl_object(QueryCtrlObjectBase::SPtr const& ctrl) = 0; virtual void add_dflt_query_ctrl_object(QueryCtrlObjectBase::SPtr const& ctrl) = 0; virtual MWQueryProxy add_query_object(QueryObjectBase::SPtr const& query) = 0; virtual void add_dflt_query_object(QueryObjectBase::SPtr const& query) = 0; virtual MWRegistryProxy add_registry_object(std::string const& identity, RegistryObjectBase::SPtr const& registry) = 0; virtual MWReplyProxy add_reply_object(ReplyObjectBase::SPtr const& reply) = 0; virtual MWScopeProxy add_scope_object(std::string const& identity, ScopeObjectBase::SPtr const& scope) = 0; virtual void add_dflt_scope_object(ScopeObjectBase::SPtr const& scope) = 0; virtual MWStateReceiverProxy add_state_receiver_object(std::string const& identity, StateReceiverObject::SPtr const& state_receiver) = 0; virtual std::string get_scope_endpoint() = 0; virtual std::string get_query_endpoint() = 0; virtual std::string get_query_ctrl_endpoint() = 0; RuntimeImpl* runtime() const noexcept; private: RuntimeImpl* const runtime_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/QueryCtrlObjectBase.h0000644000015301777760000000236512320776161031271 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_QUERYCTRLOBJECTBASE_H #define UNITY_SCOPES_INTERNAL_QUERYCTRLOBJECTBASE_H #include #include namespace unity { namespace scopes { namespace internal { class QueryCtrlObjectBase : public AbstractObject { public: UNITY_DEFINES_PTRS(QueryCtrlObjectBase); virtual void cancel(InvokeInfo const& info) = 0; virtual void destroy(InvokeInfo const& info) = 0; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ScopeImpl.h0000644000015301777760000000706612320776161027313 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_SCOPEIMPL_H #define UNITY_SCOPES_INTERNAL_SCOPEIMPL_H #include #include #include #include #include #include #include namespace unity { namespace scopes { class Result; class FilterState; class ActionMetadata; class SearchMetadata; namespace internal { class RuntimeImpl; class ScopeImpl : public virtual unity::scopes::Scope, public virtual ObjectImpl { public: ScopeImpl(MWScopeProxy const& mw_proxy, RuntimeImpl* runtime, std::string const& scope_id); virtual ~ScopeImpl(); virtual QueryCtrlProxy search(std::string const& q, SearchMetadata const& metadata, SearchListenerBase::SPtr const& reply) override; virtual QueryCtrlProxy search(std::string const& query_string, FilterState const& filter_state, SearchMetadata const& metadata, SearchListenerBase::SPtr const& reply) override; virtual QueryCtrlProxy search(std::string const& query_string, std::string const& department_id, FilterState const& filter_state, SearchMetadata const& metadata, SearchListenerBase::SPtr const& reply) override; QueryCtrlProxy search(CannedQuery const& query, SearchMetadata const& metadata, SearchListenerBase::SPtr const& reply); // Not remote operation, hence not override virtual QueryCtrlProxy activate(Result const& result, ActionMetadata const& metadata, ActivationListenerBase::SPtr const& reply) override; virtual QueryCtrlProxy perform_action(Result const& result, ActionMetadata const& hints, std::string const& widget_id, std::string const& action_id, ActivationListenerBase::SPtr const& reply) override; virtual QueryCtrlProxy preview(Result const& result, ActionMetadata const& hints, PreviewListenerBase::SPtr const& reply) override; static ScopeProxy create(MWScopeProxy const& mw_proxy, RuntimeImpl* runtime, std::string const& scope_id); private: MWScopeProxy fwd() const; RuntimeImpl* const runtime_; std::string scope_id_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/DepartmentImpl.h0000644000015301777760000000445512320776161030344 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_INTERNAL_DEPARTMENTIMPL_H #define UNITY_INTERNAL_DEPARTMENTIMPL_H #include #include #include namespace unity { namespace scopes { namespace internal { class DepartmentImpl { public: DepartmentImpl(CannedQuery const& query, std::string const& label); DepartmentImpl(std::string const& department_id, CannedQuery const& query, std::string const& label); DepartmentImpl(std::string const& department_id, CannedQuery const& query, std::string const& label, DepartmentList const& subdepartments); DepartmentImpl(DepartmentImpl const&) = default; ~DepartmentImpl() = default; DepartmentImpl& operator=(DepartmentImpl const&) = default; void set_subdepartments(DepartmentList const& departments); std::string id() const; std::string label() const; CannedQuery query() const; DepartmentList subdepartments() const; VariantMap serialize() const; static Department create(VariantMap const& var); static void validate_departments(DepartmentList const& departments, std::string const ¤t_department_id); static VariantMap serialize_departments(DepartmentList const& departments, std::string const& current_department_id); static DepartmentList deserialize_departments(VariantArray const& var); private: static void validate_departments(DepartmentList const& departments, std::unordered_set& lookup); CannedQuery query_; std::string label_; DepartmentList departments_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ActionMetadataImpl.h0000644000015301777760000000354212320776161031113 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_INTERNAL_ACTIONMETADATAIMPL_H #define UNITY_INTERNAL_ACTIONMETADATAIMPL_H #include #include namespace unity { namespace scopes { namespace internal { class ActionMetadataImpl : public QueryMetadataImpl { public: ActionMetadataImpl(std::string const& locale, std::string const& form_factor); ActionMetadataImpl(VariantMap const& var); ActionMetadataImpl(ActionMetadataImpl const&) = default; ActionMetadataImpl(ActionMetadataImpl&&) = default; ActionMetadataImpl& operator=(ActionMetadataImpl const&) = default; ActionMetadataImpl& operator=(ActionMetadataImpl&&) = default; virtual ~ActionMetadataImpl() = default; void set_scope_data(Variant const& data); Variant scope_data() const; virtual VariantMap serialize() const override; static ActionMetadata create(VariantMap const& var); protected: virtual void serialize(VariantMap &var) const override; virtual std::string metadata_type() const override; private: Variant scope_data_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/RegistryException.h0000644000015301777760000000242612320776161031102 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_REGISTRYEXCEPTION_H #define UNITY_SCOPES_INTERNAL_REGISTRYEXCEPTION_H #include namespace unity { namespace scopes { namespace internal { class RegistryException : public unity::Exception { public: explicit RegistryException(std::string const& reason); RegistryException(RegistryException const&); RegistryException& operator=(RegistryException const&); virtual ~RegistryException(); virtual std::exception_ptr self() const override; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/PreviewReplyObject.h0000644000015301777760000000266412320776161031203 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_PREVIEWREPLYOBJECT_H #define UNITY_SCOPES_INTERNAL_PREVIEWREPLYOBJECT_H #include #include #include namespace unity { namespace scopes { namespace internal { class RuntimeImpl; class PreviewReplyObject : public ReplyObject { public: PreviewReplyObject(PreviewListenerBase::SPtr const& receiver, RuntimeImpl const* runtime, std::string const& scope_id); virtual ~PreviewReplyObject(); virtual bool process_data(VariantMap const& data) override; private: PreviewListenerBase::SPtr const receiver_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWScope.h0000644000015301777760000000352012320776161026724 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MWSCOPE_H #define UNITY_SCOPES_INTERNAL_MWSCOPE_H #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class MWScope : public virtual MWObjectProxy { public: virtual ~MWScope(); virtual QueryCtrlProxy search(CannedQuery const& query, VariantMap const& hints, MWReplyProxy const& reply) = 0; virtual QueryCtrlProxy activate(VariantMap const& result, VariantMap const& hints, MWReplyProxy const& reply) = 0; virtual QueryCtrlProxy perform_action(VariantMap const& result, VariantMap const& hints, std::string const& widget_id, std::string const& action_id, MWReplyProxy const& reply) = 0; virtual QueryCtrlProxy preview(VariantMap const& result, VariantMap const& hints, MWReplyProxy const& reply) = 0; protected: MWScope(MiddlewareBase* mw_base); }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWReplyProxyFwd.h0000644000015301777760000000200512320776161030446 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MWREPLYPROXYFWD_H #define UNITY_SCOPES_INTERNAL_MWREPLYPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { class MWReply; typedef std::shared_ptr MWReplyProxy; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/RegistryObjectBase.h0000644000015301777760000000246512320776161031150 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_REGISTRYOBJECTBASE_H #define UNITY_SCOPES_INTERNAL_REGISTRYOBJECTBASE_H #include #include namespace unity { namespace scopes { namespace internal { class RegistryObjectBase : public AbstractObject { public: UNITY_DEFINES_PTRS(RegistryObjectBase); virtual ScopeMetadata get_metadata(std::string const& scope_id) const = 0; virtual MetadataMap list() const = 0; virtual ObjectProxy locate(std::string const& identity) = 0; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ScopeObject.h0000644000015301777760000000631712320776161027616 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_SCOPEOBJECT_H #define UNITY_SCOPES_INTERNAL_SCOPEOBJECT_H #include #include #include #include #include namespace unity { namespace scopes { class ScopeBase; class ActionMetadata; class SearchMetadata; class Result; namespace internal { class MiddlewareBase; class RuntimeImpl; // A ScopeObject sits in between the incoming requests from the middleware layer and the // ScopeBase-derived implementation provided by the scope. It forwards incoming // queries to the actual scope. This allows us to intercept all queries for a scope. class ScopeObject final : public ScopeObjectBase { public: UNITY_DEFINES_PTRS(ScopeObject); ScopeObject(RuntimeImpl* runtime, ScopeBase* scope_base_); virtual ~ScopeObject(); // Remote operation implementations virtual MWQueryCtrlProxy search(CannedQuery const& q, SearchMetadata const& hints, MWReplyProxy const& reply, InvokeInfo const& info) override; virtual MWQueryCtrlProxy activate(Result const& result, ActionMetadata const& hints, MWReplyProxy const &reply, InvokeInfo const& info) override; virtual MWQueryCtrlProxy perform_action(Result const& result, ActionMetadata const& hints, std::string const& widget_id, std::string const& action_id, MWReplyProxy const &reply, InvokeInfo const& info) override; virtual MWQueryCtrlProxy preview(Result const& result, ActionMetadata const& hints, MWReplyProxy const& reply, InvokeInfo const& info) override; private: MWQueryCtrlProxy query(MWReplyProxy const& reply, MiddlewareBase* mw_base, std::function const& query_factory_fun, std::function const& query_object_factory_fun); RuntimeImpl* const runtime_; ScopeBase* const scope_base_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/CategoryRendererImpl.h0000644000015301777760000000234012320776161031474 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_CATEGORYRENDERERIMPL_H #define UNITY_SCOPES_INTERNAL_CATEGORYRENDERERIMPL_H #include #include namespace unity { namespace scopes { namespace internal { class CategoryRendererImpl { public: CategoryRendererImpl(std::string const& json_text); static CategoryRenderer from_file(std::string const& path); std::string data() const; private: std::string data_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ResultImpl.h0000644000015301777760000000733312320776161027515 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_RESULTITEMIMPL_H #define UNITY_SCOPES_INTERNAL_RESULTITEMIMPL_H #include #include #include #include #include #include namespace unity { namespace scopes { class Result; namespace internal { class ResultImpl { public: // activation and preview flags, used internally only. // some of them can potentially be OR'ed if we add more, so let's make them powers of 2 enum Flags { ActivationNotHandled = 0, // direct activation InterceptActivation = 1 }; ResultImpl(); ResultImpl(VariantMap const& variant_map); ResultImpl(ResultImpl const& other); ResultImpl& operator=(ResultImpl const& other); virtual ~ResultImpl() = default; void store(Result const& other, bool intercept_activation); bool has_stored_result() const; Result retrieve() const; void set_runtime(RuntimeImpl const* runtime); void set_origin(std::string const& scope_id); void set_uri(std::string const& uri); void set_title(std::string const& title); void set_art(std::string const& image); void set_dnd_uri(std::string const& dnd_uri); void set_intercept_activation(); bool direct_activation() const; int flags() const; ScopeProxy target_scope_proxy() const; VariantMap activation_target() const; Variant& operator[](std::string const& key); Variant const& operator[](std::string const& key) const; std::string uri() const noexcept; std::string title() const noexcept; std::string art() const noexcept; std::string dnd_uri() const noexcept; std::string origin() const noexcept; bool contains(std::string const& key) const; Variant const& value(std::string const& key) const; VariantMap serialize() const; // a public static method, so there's access to the private constructor // without the need to define too many classes as friends static Result create_result(VariantMap const&); protected: virtual void serialize_internal(VariantMap& var) const; // find stored result whose flags give true in cmp_func, pass it to found_func and return; // non-matching results are passed to not_found_func. // this is done recursively as stored result can be nested. // return true if found, otherwise false. bool find_stored_result(std::function const& cmp_func, std::function const& found_func, std::function const& not_found_func) const; private: void deserialize(VariantMap const& var); void throw_on_non_string(std::string const& name, Variant::Type vtype) const; void throw_on_empty(std::string const& name) const; VariantMap attrs_; std::shared_ptr stored_result_; std::string origin_; int flags_; RuntimeImpl const* runtime_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/QueryBaseImpl.h0000644000015301777760000000510212320776161030127 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_QUERYBASEIMPL_H #define UNITY_SCOPES_INTERNAL_QUERYBASEIMPL_H #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class QueryBaseImpl final { public: QueryBaseImpl(); ~QueryBaseImpl(); QueryCtrlProxy subsearch(ScopeProxy const& scope, std::string const& query_string, SearchListenerBase::SPtr const& reply); QueryCtrlProxy subsearch(ScopeProxy const& scope, std::string const& query_string, FilterState const& filter_state, SearchListenerBase::SPtr const& reply); QueryCtrlProxy subsearch(ScopeProxy const& scope, std::string const& query_string, std::string const& department_id, FilterState const& filter_state, SearchListenerBase::SPtr const& reply); QueryCtrlProxy subsearch(ScopeProxy const& scope, std::string const& query_string, std::string const& department_id, FilterState const& filter_state, SearchMetadata const& metadata, SearchListenerBase::SPtr const& reply); void cancel(); void set_metadata(SearchMetadata const& metadata); private: SearchMetadata::UPtr search_metadata_; std::vector subqueries_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/TaskWrapper.h0000644000015301777760000000432312320776161027654 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_TASKWRAPPER_H #define UNITY_SCOPES_INTERNAL_TASKWRAPPER_H #include namespace unity { namespace scopes { namespace internal { // Simple wrapper for tasks. Allows us to use a std::packaged_task as the functor // for a task in a thread pool, without having to know the task's return type in advance. class TaskWrapper final { public: TaskWrapper() = default; ~TaskWrapper() = default; template TaskWrapper(F&& f) : task_(new WrapperType(std::move(f))) { } TaskWrapper(TaskWrapper&&) = default; TaskWrapper& operator=(TaskWrapper&&) = default; TaskWrapper(TaskWrapper&) = delete; TaskWrapper(TaskWrapper const&) = delete; TaskWrapper& operator=(TaskWrapper const&) = delete; void operator()() { task_->call(); } bool valid() const { return task_ ? task_->valid() : false; } private: struct WrapperBase { virtual void call() = 0; virtual bool valid() const = 0; virtual ~WrapperBase() {}; }; template struct WrapperType : WrapperBase { F f_; WrapperType(F&& f) : f_(std::move(f)) { } virtual ~WrapperType() {}; void call() { f_(); } bool valid() const { return f_.valid(); } }; std::unique_ptr task_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/QueryCtrlImpl.h0000644000015301777760000000341312320776161030164 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_QUERYCTRLIMPL_H #define UNITY_SCOPES_INTERNAL_QUERYCTRLIMPL_H #include #include #include #include namespace unity { namespace scopes { namespace internal { // Proxy used by a scope to push results for a query. // To indicate that it has sent the last result, the scope must call finished(). // Subsequent calls to finished() are ignored. // Calls to push() after finished() was called are ignored. // If the proxy goes out of scope before finished was called, it implicitly calls finished(). class QueryCtrlImpl : public virtual unity::scopes::QueryCtrl, public virtual ObjectImpl { public: QueryCtrlImpl(MWQueryCtrlProxy const& ctrl_proxy, MWReplyProxy const& reply_proxy); virtual ~QueryCtrlImpl(); virtual void cancel() override; private: MWQueryCtrlProxy fwd() const; MWReplyProxy reply_proxy_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ColumnLayoutImpl.h0000644000015301777760000000332712320776161030671 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_COLUMNLAYOUTIMPL_H #define UNITY_SCOPES_INTERNAL_COLUMNLAYOUTIMPL_H #include #include #include #include namespace unity { namespace scopes { namespace internal { class ColumnLayoutImpl { public: explicit ColumnLayoutImpl(int num_of_columns); explicit ColumnLayoutImpl(VariantMap const& var); ColumnLayoutImpl(ColumnLayoutImpl const& other) = default; void add_column(std::vector widget_ids); int size() const noexcept; int number_of_columns() const noexcept; std::vector column(int index) const; VariantMap serialize() const; static ColumnLayout create(VariantMap const& var); static void validate_layouts(ColumnLayoutList const& layouts); private: int num_of_columns_; std::vector> columns_; static const int max_number_of_columns_ = 1024; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ActivationResponseImpl.h0000644000015301777760000000367512320776161032064 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_ACTIVATIONRESPONSEIMPL_H #define UNITY_SCOPES_INTERNAL_ACTIVATIONRESPONSEIMPL_H #include #include namespace unity { namespace scopes { namespace internal { class ActivationResponseImpl final { public: ActivationResponseImpl(ActivationResponse::Status status); ActivationResponseImpl(CannedQuery const& query); ActivationResponseImpl(VariantMap const& var); ~ActivationResponseImpl() = default; ActivationResponseImpl(ActivationResponseImpl const& other) = default; ActivationResponseImpl(ActivationResponseImpl&& other) = default; ActivationResponseImpl& operator=(ActivationResponseImpl const& other) = default; ActivationResponseImpl& operator=(ActivationResponseImpl && other) = default; ActivationResponse::Status status() const; void set_scope_data(Variant const& hints); Variant scope_data() const; CannedQuery query() const; VariantMap serialize() const; static ActivationResponse create(VariantMap const& var); private: ActivationResponse::Status status_; CannedQuery::SPtr query_; Variant scope_data_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ThreadPool.h0000644000015301777760000000403712320776161027454 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_THREADPOOL_H #define UNITY_SCOPES_INTERNAL_THREADPOOL_H #include #include #include #include namespace unity { namespace scopes { namespace internal { // Simple thread pool that runs tasks on a number of worker threads. // submit() accepts an arbitrary functor and returns a future that // the calling thread can use to wait for the task to complete. class ThreadPool final { public: NONCOPYABLE(ThreadPool); ThreadPool(int size); ~ThreadPool(); template std::future::type> submit(F f); void run(); private: typedef ThreadSafeQueue TaskQueue; std::unique_ptr queue_; std::vector threads_; std::mutex mutex_; std::promise threads_ready_; int num_threads_; }; template std::future::type> ThreadPool::submit(F f) { typedef typename std::result_of::type ResultType; std::packaged_task task(std::move(f)); std::future result(task.get_future()); queue_->push(move(task)); return result; } } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/RuntimeImpl.h0000644000015301777760000000502012320776161027651 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_RUNTIMEIMPL_H #define UNITY_SCOPES_INTERNAL_RUNTIMEIMPL_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class RuntimeImpl final { public: NONCOPYABLE(RuntimeImpl); UNITY_DEFINES_PTRS(RuntimeImpl); static UPtr create(std::string const& scope_id, std::string const& configfile = ""); void destroy(); std::string scope_id() const; std::string configfile() const; MiddlewareFactory const* factory() const; RegistryProxy registry() const; std::string registry_configfile() const; std::string registry_identity() const; std::string registry_endpointdir() const; std::string registry_endpoint() const; Reaper::SPtr reply_reaper() const; void run_scope(ScopeBase *const scope_base, std::string const &scope_ini_file); ObjectProxy string_to_proxy(std::string const& s) const; std::string proxy_to_string(ObjectProxy const& proxy) const; ~RuntimeImpl(); private: RuntimeImpl(std::string const& scope_id, std::string const& configfile); std::atomic_bool destroyed_; std::string scope_id_; std::string configfile_; MiddlewareFactory::UPtr middleware_factory_; MiddlewareBase::SPtr middleware_; mutable RegistryProxy registry_; mutable std::string registry_configfile_; mutable std::string registry_identity_; mutable std::string registry_endpointdir_; mutable std::string registry_endpoint_; mutable Reaper::SPtr reply_reaper_; mutable std::mutex mutex_; // For lazy initialization of reply_reaper_ }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/AnnotationImpl.h0000644000015301777760000000341212320776161030343 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_ANNOTATIONIMPL_H #define UNITY_SCOPES_INTERNAL_ANNOTATIONIMPL_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class AnnotationImpl { public: explicit AnnotationImpl(Annotation::Type annotation_type); AnnotationImpl(const VariantMap &variant_map); virtual ~AnnotationImpl(); void set_label(std::string const& label); void set_icon(std::string const& icon); void add_link(std::string const& label, CannedQuery const& query); std::string label() const; std::string icon() const; std::list links() const; Annotation::Type annotation_type() const; VariantMap serialize() const; private: void throw_if_inconsistent() const; Annotation::Type annotation_type_; std::string label_; std::string icon_; std::list links_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWScopeProxyFwd.h0000644000015301777760000000200512320776161030424 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MWSCOPEPROXYFWD_H #define UNITY_SCOPES_INTERNAL_MWSCOPEPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { class MWScope; typedef std::shared_ptr MWScopeProxy; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ScopeLoader.h0000644000015301777760000000517012320776161027612 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_SCOPELOADER_H #define UNITY_SCOPES_INTERNAL_SCOPELOADER_H #include #include #include namespace unity { namespace scopes { namespace internal { // ScopeLoader loads the .so for a scope and TODO: complete this and updated comments below. class ScopeLoader final { public: NONCOPYABLE(ScopeLoader); UNITY_DEFINES_PTRS(ScopeLoader); // Creates a ScopeLoader for a scope with the given ID and library. We pass in the registry proxy // so we can pass it to the scope's start method. static UPtr load(std::string const& scope_id, std::string const& libpath, RegistryProxy const& registry); // unload() explicitly finalizes the scope. This is called by the destructor too, but calling it explicity // allows the caller to receive any exceptions that may have been produced by the scope thread. void unload(); // These methods start or stop a scope, that is, call through to the scope-provided versions in the dynamic library. void start(); void stop(); // Returns the scope ID std::string scope_id() const noexcept; // Returns the library path for the scope std::string libpath() const noexcept; // Returns the actual implementation provided by the scope. unity::scopes::ScopeBase* scope_base() const; ~ScopeLoader(); private: ScopeLoader(std::string const& scope_id, std::string const& path, RegistryProxy const& registry); std::string scope_id_; unity::scopes::internal::DynamicLoader::UPtr dyn_loader_; unity::scopes::RegistryProxy registry_; std::exception_ptr exception_; std::thread scope_thread_; std::unique_ptr scope_base_; enum class ScopeState { Stopped, Started, Failed, Finished }; ScopeState scope_state_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/CategoryImpl.h0000644000015301777760000000326412320776161030013 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_CATEGORYIMPL_H #define UNITY_SCOPES_INTERNAL_CATEGORYIMPL_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class CategoryImpl { public: NONCOPYABLE(CategoryImpl); CategoryImpl(VariantMap const& variant_map); CategoryImpl(std::string const& id, std::string const& title, std::string const &icon, CategoryRenderer const& renderer_template); std::string const& id() const; std::string const& title() const; std::string const& icon() const; CategoryRenderer const& renderer_template() const; VariantMap serialize() const; private: void deserialize(VariantMap const& variant_map); std::string id_; std::string title_; std::string icon_; CategoryRenderer renderer_template_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ObjectImpl.h0000644000015301777760000000345312320776161027444 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_OBJECTIMPL_H #define UNITY_SCOPES_INTERNAL_OBJECTIMPL_H #include #include namespace unity { namespace scopes { namespace internal { class ObjectImpl : public virtual Object { public: ObjectImpl(MWProxy const& mw_proxy); virtual ~ObjectImpl(); virtual std::string identity() override; virtual std::string category() override; virtual std::string endpoint() override; virtual int64_t timeout() override; virtual std::string to_string() override; // Remote operation. Not part of the public API, hence not override. virtual void ping(); protected: MWProxy proxy() const; // Non-virtual because we cannot use covariance with incomplete types. // Each derived proxy implements a non-virtual fwd() method // that is called from within each operation to down-cast the MWProxy. MWProxy mw_proxy_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/Utils.h0000644000015301777760000000210012320776161026500 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_INTERNAL_UTILS_H #define UNITY_INTERNAL_UTILS_H #include #include namespace unity { namespace scopes { namespace internal { VariantMap::const_iterator find_or_throw(std::string const& context, VariantMap const& var, std::string const& key); } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ReplyObject.h0000644000015301777760000000413112320776161027630 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_REPLYOBJECT_H #define UNITY_SCOPES_INTERNAL_REPLYOBJECT_H #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class RuntimeImpl; // A ReplyObject sits in between the incoming requests from the middleware layer and the // ListenerBase-derived implementation provided by the scope. // This allows us to intercept all replies. class ReplyObject : public ReplyObjectBase { public: UNITY_DEFINES_PTRS(ReplyObject); ReplyObject(ListenerBase::SPtr const& receiver_base, RuntimeImpl const* runtime, std::string const& scope_proxy); virtual ~ReplyObject(); virtual bool process_data(VariantMap const& data) = 0; std::string origin_proxy() const; // Remote operation implementations void push(VariantMap const& result) noexcept override; void finished(ListenerBase::Reason reason, std::string const& error_message) noexcept override; private: ListenerBase::SPtr const listener_base_; ReapItem::SPtr reap_item_; std::atomic_bool finished_; std::mutex mutex_; std::condition_variable idle_; std::string origin_proxy_; int num_push_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ResultReplyObject.h0000644000015301777760000000323012320776161031026 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_RESULTREPLYOBJECT_H #define UNITY_SCOPES_INTERNAL_RESULTREPLYOBJECT_H #include #include #include namespace unity { namespace scopes { namespace internal { class RuntimeImpl; class ResultReplyObject : public ReplyObject { public: ResultReplyObject(SearchListenerBase::SPtr const& receiver, RuntimeImpl const* runtime, std::string const& scope_id, int cardinality); virtual ~ResultReplyObject(); virtual bool process_data(VariantMap const& data) override; private: SearchListenerBase::SPtr const receiver_; std::shared_ptr cat_registry_; RuntimeImpl const* runtime_; std::atomic_int cardinality_; std::atomic_int num_pushes_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWRegistry.h0000644000015301777760000000257412320776161027473 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MWREGISTRY_H #define UNITY_SCOPES_INTERNAL_MWREGISTRY_H #include #include #include namespace unity { namespace scopes { namespace internal { class MWRegistry : public virtual MWObjectProxy { public: // Remote operations virtual ScopeMetadata get_metadata(std::string const& scope_id) = 0; virtual MetadataMap list() = 0; virtual ObjectProxy locate(std::string const& identity) = 0; virtual ~MWRegistry(); protected: MWRegistry(MiddlewareBase* mw_base); }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWQuery.h0000644000015301777760000000227712320776161026770 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MWQUERY_H #define UNITY_SCOPES_INTERNAL_MWQUERY_H #include #include namespace unity { namespace scopes { namespace internal { class MWQuery : public virtual MWObjectProxy { public: virtual ~MWQuery(); virtual void run(MWReplyProxy const& r) = 0; protected: MWQuery(MiddlewareBase* mw_base); }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/PreviewReplyImpl.h0000644000015301777760000000330512320776161030667 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_PREVIEWREPLYIMPL_H #define UNITY_SCOPES_INTERNAL_PREVIEWREPLYIMPL_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class QueryObjectBase; class PreviewReplyImpl : public virtual unity::scopes::PreviewReply, public virtual ReplyImpl { public: PreviewReplyImpl(MWReplyProxy const& mw_proxy, std::shared_ptrconst & qo); virtual ~PreviewReplyImpl(); virtual bool register_layout(unity::scopes::ColumnLayoutList const& layouts) override; virtual bool push(unity::scopes::PreviewWidgetList const& widgets) override; virtual bool push(std::string const& key, Variant const& value) override; private: std::atomic_bool layouts_push_disallowed_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/FilterOptionImpl.h0000644000015301777760000000225212320776161030650 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_FILTEROPTIONIMPL_H #define UNITY_SCOPES_INTERNAL_FILTEROPTIONIMPL_H #include namespace unity { namespace scopes { namespace internal { class FilterOptionImpl { public: FilterOptionImpl(std::string const& id, std::string const& label); std::string id() const; std::string label() const; private: std::string id_; std::string label_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/lttng/0000755000015301777760000000000012320776463026373 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/lttng/SimpleTracepoint.h0000644000015301777760000001301712320776161032023 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef SIMPLETRACEPOINT_H_ #define SIMPLETRACEPOINT_H_ #include /* simple_tracepoint */ /* * The STAP_PROBEV() macro from sdt.h (SystemTap) used by * the tracepoint() macro from lttng/tracepoint.h fails to * build with clang at the moment. Disable tracepoints * when building with clang until this is resolved. * * See: http://sourceware.org/bugzilla/show_bug.cgi?id=13974 */ #ifdef __clang__ /* template< typename... T > void simple_tracepoint_unused_args( T&&... ) {} */ #define simple_tracepoint( c, e, ... ) simple_tracepoint_unused_args( __VA_ARGS__ ) #else #define simple_tracepoint( c, e, ... ) tracepoint( c, e, __VA_ARGS__ ) #endif /* SIMPLE_TRACEPOINT */ #define SIMPLE_TRACEPOINT( name, loglevel, ... )\ TRACEPOINT_EVENT(\ TRACEPOINT_PROVIDER,\ name,\ TP_ARGS( _STP_ARGS( __VA_ARGS__ ) ),\ TP_FIELDS(\ _STP_FIELDS( __VA_ARGS__ )\ )\ )\ TRACEPOINT_LOGLEVEL( TRACEPOINT_PROVIDER, name, loglevel ) /* stp argument definitions */ #define stp_integer( arg_type, arg_name ) (\ ( arg_type, arg_name ),\ ctf_integer, ( arg_type, arg_name, arg_name ) ) #define stp_integer_hex( arg_type, arg_name ) (\ ( arg_type, arg_name ),\ ctf_integer_hex, ( arg_type, arg_name, arg_name ) ) #define stp_integer_network( arg_type, arg_name ) (\ ( arg_type, arg_name ),\ ctf_integer_network, ( arg_type, arg_name, arg_name ) ) #define stp_integer_network_hex( arg_type, arg_name ) (\ ( arg_type, arg_name ),\ ctf_integer_network_hex, ( arg_type, arg_name, arg_name ) ) #define stp_array( arg_type, elem_type, arg_name, arg_size ) (\ ( arg_type, arg_name ),\ ctf_array, ( elem_type, arg_name, arg_name, arg_size ) ) #define stp_array_text( arg_type, elem_type, arg_name, arg_size ) (\ ( arg_type, arg_name ),\ ctf_array_text, ( elem_type, arg_name, arg_name, arg_size ) ) #define stp_sequence( arg_type, elem_type, arg_name, arg_size ) (\ ( arg_type, arg_name ),\ ctf_sequence, ( elem_type, arg_name, arg_name, size_t, arg_size ) ) #define stp_sequence_text( arg_type, elem_type, arg_name, arg_size ) (\ ( arg_type, arg_name ),\ ctf_sequence_text, ( elem_type, arg_name, arg_name, size_t, arg_size ) ) #define stp_string( arg_name ) (\ ( const char*, arg_name ),\ ctf_string, ( arg_name, arg_name ) ) #define stp_float( arg_type, arg_name ) (\ ( arg_type, arg_name ),\ ctf_float, ( arg_type, arg_name, arg_name ) ) /* Internal */ #define _STP_ARGS( ... )\ _TP_COMBINE_TOKENS( _STP_ARGS_, _TP_NARGS( 0, __VA_ARGS__ ) ) ( __VA_ARGS__ ) #define _STP_FIELDS( ... )\ _TP_COMBINE_TOKENS( _STP_FIELDS_, _TP_NARGS( 0, __VA_ARGS__ ) ) ( __VA_ARGS__ ) #define ___TPA( arg, arg2 ) arg, arg2 #define __TPA( args, ctf, fields ) ___TPA args #define _TPA( args_ctf_fields ) __TPA args_ctf_fields #define __TPF( args, ctf, fields ) ctf fields #define _TPF( args_ctf_fields ) __TPF args_ctf_fields #define _STP_ARGS_1( a )\ _TPA( a ) #define _STP_ARGS_2( a, b )\ _TPA( a ), _TPA( b ) #define _STP_ARGS_3( a, b, c )\ _TPA( a ), _TPA( b ), _TPA( c ) #define _STP_ARGS_4( a, b, c, d )\ _TPA( a ), _TPA( b ), _TPA( c ), _TPA( d ) #define _STP_ARGS_5( a, b, c, d, e )\ _TPA( a ), _TPA( b ), _TPA( c ), _TPA( d ), _TPA( e ) #define _STP_ARGS_6( a, b, c, d, e, f )\ _TPA( a ), _TPA( b ), _TPA( c ), _TPA( d ), _TPA( e ), _TPA( f ) #define _STP_ARGS_7( a, b, c, d, e, f, g )\ _TPA( a ), _TPA( b ), _TPA( c ), _TPA( d ), _TPA( e ), _TPA( f ), _TPA( g ) #define _STP_ARGS_8( a, b, c, d, e, f, g, h )\ _TPA( a ), _TPA( b ), _TPA( c ), _TPA( d ), _TPA( e ), _TPA( f ), _TPA( g ), _TPA( h ) #define _STP_ARGS_9( a, b, c, d, e, f, g, h, i )\ _TPA( a ), _TPA( b ), _TPA( c ), _TPA( d ), _TPA( e ), _TPA( f ), _TPA( g ), _TPA( h ), _TPA( i ) #define _STP_ARGS_10( a, b, c, d, e, f, g, h, i, j )\ _TPA( a ), _TPA( b ), _TPA( c ), _TPA( d ), _TPA( e ), _TPA( f ), _TPA( g ), _TPA( h ), _TPA( i ), _TPA( j ) #define _STP_FIELDS_1( a )\ _TPF( a ) #define _STP_FIELDS_2( a, b )\ _TPF( a ) _TPF( b ) #define _STP_FIELDS_3( a, b, c )\ _TPF( a ) _TPF( b ) _TPF( c ) #define _STP_FIELDS_4( a, b, c, d )\ _TPF( a ) _TPF( b ) _TPF( c ) _TPF( d ) #define _STP_FIELDS_5( a, b, c, d, e )\ _TPF( a ) _TPF( b ) _TPF( c ) _TPF( d ) _TPF( e ) #define _STP_FIELDS_6( a, b, c, d, e, f )\ _TPF( a ) _TPF( b ) _TPF( c ) _TPF( d ) _TPF( e ) _TPF( f ) #define _STP_FIELDS_7( a, b, c, d, e, f, g )\ _TPF( a ) _TPF( b ) _TPF( c ) _TPF( d ) _TPF( e ) _TPF( f ) _TPF( g ) #define _STP_FIELDS_8( a, b, c, d, e, f, g, h )\ _TPF( a ) _TPF( b ) _TPF( c ) _TPF( d ) _TPF( e ) _TPF( f ) _TPF( g ) _TPF( h ) #define _STP_FIELDS_9( a, b, c, d, e, f, g, h, i )\ _TPF( a ) _TPF( b ) _TPF( c ) _TPF( d ) _TPF( e ) _TPF( f ) _TPF( g ) _TPF( h ) _TPF( i ) #define _STP_FIELDS_10( a, b, c, d, e, f, g, h, i, j )\ _TPF( a ) _TPF( b ) _TPF( c ) _TPF( d ) _TPF( e ) _TPF( f ) _TPF( g ) _TPF( h ) _TPF( i ) _TPF( j ) #endif /* SIMPLETRACEPOINT_H_ */ unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/lttng/CMakeLists.txt0000644000015301777760000000020212320776161031120 0ustar pbusernogroup00000000000000file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h") set(UNITY_SCOPES_LIB_HDRS ${UNITY_SCOPES_LIB_HDRS} ${headers} PARENT_SCOPE) unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/lttng/UnityScopes_tp.h0000644000015301777760000000267512320776161031541 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #if !defined(UNITY_SCOPES_INTERNAL_LTTNG_UNITYSCOPESTP_H) || defined(TRACEPOINT_HEADER_MULTI_READ) #define UNITY_SCOPES_INTERNAL_LTTNG_UNITYSCOPESTP_H #undef TRACEPOINT_PROVIDER #undef TRACEPOINT_INCLUDE #define TRACEPOINT_PROVIDER unity_scopes #define TRACEPOINT_INCLUDE #include #include #if __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-function" #pragma clang diagnostic ignored "-Wmissing-field-initializers" #endif SIMPLE_TRACEPOINT( trace, TRACE_DEBUG, stp_integer(int, value) ) #if __clang__ #pragma clang diagnostic pop #endif #endif /* UNITY_SCOPES_INTERNAL_LTTNG_UNITYSCOPES_TP_H */ unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWRegistryProxyFwd.h0000644000015301777760000000202412320776161031164 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MWREGISTRYPROXYFWD_H #define UNITY_SCOPES_INTERNAL_MWREGISTRYPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { class MWRegistry; typedef std::shared_ptr MWRegistryProxy; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/FilterStateImpl.h0000644000015301777760000000301512320776161030456 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_FILTERSTATEIMPL_H #define UNITY_SCOPES_INTERNAL_FILTERSTATEIMPL_H #include #include #include namespace unity { namespace scopes { namespace internal { class FilterStateImpl final { public: FilterStateImpl() = default; FilterStateImpl(VariantMap const& var); ~FilterStateImpl() = default; FilterStateImpl(FilterStateImpl const& other) = default; bool has_filter(std::string const& id) const; void remove(std::string const& id); Variant get(std::string const& filter_id) const; VariantMap& get(); VariantMap serialize() const; static FilterState deserialize(VariantMap const& var); private: VariantMap state_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/FilterBaseImpl.h0000644000015301777760000000334412320776161030255 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_FILTERBASEIMPL_H #define UNITY_SCOPES_INTERNAL_FILTERBASEIMPL_H #include #include #include namespace unity { namespace scopes { class FilterState; namespace internal { class FilterBaseImpl { public: FilterBaseImpl(std::string const& id); FilterBaseImpl(VariantMap const& var); virtual ~FilterBaseImpl(); std::string id() const; VariantMap serialize() const; virtual std::string filter_type() const = 0; static FilterBase::SCPtr deserialize(VariantMap const& var); static VariantArray serialize_filters(Filters const& filters); static Filters deserialize_filters(VariantArray const& var); protected: virtual void serialize(VariantMap& var) const = 0; static Variant get(FilterState const& filter_state, std::string const& filter_id); static VariantMap& get(FilterState const& filter_state); private: std::string id_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ScopeObjectBase.h0000644000015301777760000000514712320776161030411 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_SCOPEOBJECTBASE_H #define UNITY_SCOPES_INTERNAL_SCOPEOBJECTBASE_H #include #include #include #include #include #include namespace unity { namespace scopes { class ScopeBase; class ActionMetadata; class SearchMetadata; class CannedQuery; namespace internal { class MiddlewareBase; class RuntimeImpl; class ScopeObjectBase : public AbstractObject { public: UNITY_DEFINES_PTRS(ScopeObjectBase); virtual MWQueryCtrlProxy search(CannedQuery const& query, SearchMetadata const& hints, MWReplyProxy const& reply, InvokeInfo const& info) = 0; virtual MWQueryCtrlProxy activate(Result const& result, ActionMetadata const& hints, MWReplyProxy const &reply, InvokeInfo const& info) = 0; virtual MWQueryCtrlProxy perform_action(Result const& result, ActionMetadata const& hints, std::string const& widget_id, std::string const& action_id, MWReplyProxy const &reply, InvokeInfo const& info) = 0; virtual MWQueryCtrlProxy preview(Result const& result, ActionMetadata const& hints, MWReplyProxy const& reply, InvokeInfo const& info) = 0; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/RegistryObject.h0000644000015301777760000001005112320776161030343 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_REGISTRYOBJECT_H #define UNITY_SCOPES_INTERNAL_REGISTRYOBJECT_H #include #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class RegistryObject : public RegistryObjectBase { public: struct ScopeExecData { ScopeExecData() = default; ScopeExecData(std::initializer_list) = delete; std::string scope_id; std::string scoperunner_path; std::string runtime_config; std::string scope_config; }; public: UNITY_DEFINES_PTRS(RegistryObject); RegistryObject(core::posix::ChildProcess::DeathObserver& death_observer); virtual ~RegistryObject(); // Remote operation implementations virtual ScopeMetadata get_metadata(std::string const& scope_id) const override; virtual MetadataMap list() const override; virtual ObjectProxy locate(std::string const& identity) override; // Local methods bool add_local_scope(std::string const& scope_id, ScopeMetadata const& scope, ScopeExecData const& scope_exec_data); bool remove_local_scope(std::string const& scope_id); void set_remote_registry(MWRegistryProxy const& remote_registry); bool is_scope_running(std::string const& scope_id); StateReceiverObject::SPtr state_receiver(); private: void on_process_death(core::posix::Process const& process); void on_state_received(std::string const& scope_id, StateReceiverObject::State const& state); class ScopeProcess { public: enum ProcessState { Stopped, Starting, Running, Stopping }; ScopeProcess(ScopeExecData exec_data); ScopeProcess(ScopeProcess const& other); ~ScopeProcess(); ProcessState state() const; void update_state(ProcessState state); bool wait_for_state(ProcessState state, int timeout_ms) const; void exec(core::posix::ChildProcess::DeathObserver& death_observer); void kill(); bool on_process_death(pid_t pid); private: // the following methods must be called with process_mutex_ locked void clear_handle_unlocked(); void update_state_unlocked(ProcessState state); bool wait_for_state(std::unique_lock& lock, ProcessState state, int timeout_ms) const; void kill(std::unique_lock& lock); private: const ScopeExecData exec_data_; ProcessState state_ = Stopped; mutable std::mutex process_mutex_; mutable std::condition_variable state_change_cond_; core::posix::ChildProcess process_ = core::posix::ChildProcess::invalid(); }; private: core::posix::ChildProcess::DeathObserver& death_observer_; core::ScopedConnection death_observer_connection_; StateReceiverObject::SPtr state_receiver_; core::ScopedConnection state_receiver_connection_; mutable std::mutex mutex_; MetadataMap scopes_; std::map scope_processes_; MWRegistryProxy remote_registry_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/SearchMetadataImpl.h0000644000015301777760000000443012320776161031100 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_INTERNAL_SEARCHMETADATAIMPL_H #define UNITY_INTERNAL_SEARCHMETADATAIMPL_H #include #include namespace unity { namespace scopes { namespace internal { class SearchMetadataImpl : public QueryMetadataImpl { public: SearchMetadataImpl(std::string const& locale, std::string const& form_factor); SearchMetadataImpl(int cardinality, std::string const& locale, std::string const& form_factor); SearchMetadataImpl(VariantMap const& var); SearchMetadataImpl(SearchMetadataImpl const&) = default; SearchMetadataImpl(SearchMetadataImpl&&) = default; SearchMetadataImpl& operator=(SearchMetadataImpl const&) = default; SearchMetadataImpl& operator=(SearchMetadataImpl&&) = default; virtual ~SearchMetadataImpl() = default; void set_cardinality(int cardinality); int cardinality() const; bool contains_hint(std::string const& key) const; void set_hint(std::string const& key, Variant const& value); VariantMap hints() const; Variant& hint(std::string const& key); Variant const& hint(std::string const& key) const; virtual VariantMap serialize() const override; static SearchMetadata create(VariantMap const& var); protected: virtual std::string metadata_type() const override; virtual void serialize(VariantMap &var) const override; void check_cardinality(std::string const& func_name, int cardinality); private: int cardinality_; VariantMap hints_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/RuntimeConfig.h0000644000015301777760000000302112320776161030154 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_RUNTIMECONFIG_H #define UNITY_SCOPES_INTERNAL_RUNTIMECONFIG_H #include #include namespace unity { namespace scopes { namespace internal { class RuntimeConfig : public ConfigBase { public: static const char* RUNTIME_CONFIG_GROUP; RuntimeConfig(std::string const& configfile); ~RuntimeConfig(); std::string registry_identity() const; std::string registry_configfile() const; std::string default_middleware() const; std::string default_middleware_configfile() const; private: std::string registry_identity_; std::string registry_configfile_; std::string default_middleware_; std::string default_middleware_configfile_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWReply.h0000644000015301777760000000257512320776161026757 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MWREPLY_H #define UNITY_SCOPES_INTERNAL_MWREPLY_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class MWReply : public virtual MWObjectProxy { public: virtual ~MWReply(); virtual void push(VariantMap const& result) = 0; virtual void finished(ListenerBase::Reason reason, std::string const& error_message) = 0; protected: MWReply(MiddlewareBase* mw_base); }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/CannedQueryImpl.h0000644000015301777760000000422412320776161030451 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_CANNEDQUERYIMPL_H #define UNITY_SCOPES_INTERNAL_CANNEDQUERYIMPL_H #include #include #include namespace unity { namespace scopes { class CannedQuery; class FilterState; namespace internal { class CannedQueryImpl { public: explicit CannedQueryImpl(std::string const& scope_id); CannedQueryImpl(std::string const& scope_id, std::string const& query_str, std::string const& department_id); CannedQueryImpl(VariantMap const& variant); CannedQueryImpl(CannedQueryImpl const &other) = default; CannedQueryImpl(CannedQueryImpl&&) = default; CannedQueryImpl& operator=(CannedQueryImpl const& other) = default; CannedQueryImpl& operator=(CannedQueryImpl&&) = default; void set_department_id(std::string const& dep_id); void set_query_string(std::string const& query_str); void set_filter_state(FilterState const& filter_state); std::string scope_id() const; std::string department_id() const; std::string query_string() const; FilterState filter_state() const; VariantMap serialize() const; std::string to_string() const; static CannedQuery from_string(); static CannedQuery create(VariantMap const& var); private: std::string scope_id_; std::string query_string_; std::string department_id_; FilterState filter_state_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ActivationQueryObject.h0000644000015301777760000000300312320776161031661 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_ACTIVATIONQUERYOBJECT_H #define UNITY_SCOPES_INTERNAL_ACTIVATIONQUERYOBJECT_H #include #include namespace unity { namespace scopes { class ActivationQueryBase; namespace internal { class ActivationQueryObject final : public QueryObject { public: UNITY_DEFINES_PTRS(ActivationQueryObject); ActivationQueryObject(std::shared_ptr const& act_base, MWReplyProxy const& reply, MWQueryCtrlProxy const& ctrl); virtual ~ActivationQueryObject(); virtual void run(MWReplyProxy const& reply, InvokeInfo const& info) noexcept override; private: std::shared_ptr act_base_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWQueryCtrl.h0000644000015301777760000000234512320776161027611 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MWQUERYCTRL_H #define UNITY_SCOPES_INTERNAL_MWQUERYCTRL_H #include #include namespace unity { namespace scopes { namespace internal { class MWQueryCtrl : public virtual MWObjectProxy { public: virtual ~MWQueryCtrl(); virtual void cancel() = 0; virtual void destroy() = 0; protected: MWQueryCtrl(MiddlewareBase* mw_base); }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MiddlewareFactory.h0000644000015301777760000000530512320776161031017 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MIDDLEWAREFACTORY_H #define UNITY_SCOPES_INTERNAL_MIDDLEWAREFACTORY_H #include #include namespace unity { namespace scopes { namespace internal { class RuntimeImpl; // Factory to make middleware instances available. // // This class is thread-safe. class MiddlewareFactory final { public: NONCOPYABLE(MiddlewareFactory); UNITY_DEFINES_PTRS(MiddlewareFactory); MiddlewareFactory(RuntimeImpl* runtime); ~MiddlewareFactory(); // Returns the middleware with the given name and kind. If that middleware hasn't been created yet, // it is created first. MiddlewareBase::SPtr create(std::string const& server_name, std::string const& kind, std::string const& configfile) const; // Find the middleware with the given name and kind. Returns nullptr if that middleware doesn't exist. MiddlewareBase::SPtr find(std::string const& server_name, std::string const& kind) const; // Find any middleware that understands the scheme of the stringified proxy. MiddlewareBase::SPtr find(std::string const& proxy_string) const; private: MiddlewareBase::SPtr find_unlocked(std::string const& server_name, std::string const& kind) const; enum Kind { Kind_Zmq, Kind_REST }; static Kind to_kind(::std::string const& kind); struct MiddlewareData { std::string server_name; std::string kind; bool operator<(MiddlewareData const& rhs) const { if (server_name < rhs.server_name) { return true; } if (server_name > rhs.server_name) { return false; } return kind < rhs.kind; } }; RuntimeImpl* const runtime_; mutable std::map mw_map_; mutable std::mutex mutex_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWStateReceiverProxyFwd.h0000644000015301777760000000214612320776161032126 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_MWSTATERECEIVERPROXYFWD_H #define UNITY_SCOPES_INTERNAL_MWSTATERECEIVERPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { class MWStateReceiver; typedef std::shared_ptr MWStateReceiverProxy; } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_MWSTATERECEIVERPROXYFWD_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ReplyObjectBase.h0000644000015301777760000000247212320776161030431 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_REPLYOBJECTBASE_H #define UNITY_SCOPES_INTERNAL_REPLYOBJECTBASE_H #include #include #include namespace unity { namespace scopes { namespace internal { class ReplyObjectBase : public AbstractObject { public: UNITY_DEFINES_PTRS(ReplyObjectBase); virtual void push(VariantMap const& result) noexcept = 0; virtual void finished(ListenerBase::Reason reason, std::string const& error_message) noexcept = 0; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/CMakeLists.txt0000644000015301777760000000051112320776161027773 0ustar pbusernogroup00000000000000add_subdirectory(lttng) add_subdirectory(smartscopes) add_subdirectory(zmq_middleware) file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h") configure_file(DfltConfig.h.in DfltConfig.h) set(headers ${headers} ${CMAKE_CURRENT_BINARY_DIR}/DfltConfig.h) set(UNITY_SCOPES_LIB_HDRS ${UNITY_SCOPES_LIB_HDRS} ${headers} PARENT_SCOPE) unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWStateReceiver.h0000644000015301777760000000252312320776161030422 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_MWSTATERECEIVER_H #define UNITY_SCOPES_INTERNAL_MWSTATERECEIVER_H #include #include namespace unity { namespace scopes { namespace internal { class MWStateReceiver : public virtual MWObjectProxy { public: virtual void push_state(std::string const& sender_id, StateReceiverObject::State const& state) = 0; virtual ~MWStateReceiver(); protected: MWStateReceiver(MiddlewareBase* mw_base); }; } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_MWSTATERECEIVER_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWQueryCtrlProxyFwd.h0000644000015301777760000000203112320776161031304 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MWQUERYCTRLPROXYFWD_H #define UNITY_SCOPES_INTERNAL_MWQUERYCTRLPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { class MWQueryCtrl; typedef std::shared_ptr MWQueryCtrlProxy; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ActivationQueryBaseImpl.h0000644000015301777760000000235412320776161032157 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_ACTIVATIONQUERYBASEIMPL_H #define UNITY_SCOPES_INTERNAL_ACTIVATIONQUERYBASEIMPL_H #include #include namespace unity { namespace scopes { namespace internal { class ActivationQueryBaseImpl final { public: NONCOPYABLE(ActivationQueryBaseImpl); ActivationQueryBaseImpl() = default; ~ActivationQueryBaseImpl() = default; ActivationResponse activate(); }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/MWObjectProxy.h0000644000015301777760000000330712320776161030126 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_MWOBJECTPROXY_H #define UNITY_SCOPES_INTERNAL_MWOBJECTPROXY_H #include namespace unity { namespace scopes { namespace internal { class MiddlewareBase; // Base class for the MWProxy hierarchy. We store the pointer to the middleware here, // which is needed to, for example, register callback objects (such as a Reply object) with the middleware. class MWObjectProxy { public: virtual ~MWObjectProxy(); virtual MiddlewareBase* mw_base() const noexcept = 0; virtual std::string identity() const = 0; virtual std::string category() const = 0; virtual std::string endpoint() const = 0; virtual int64_t timeout() const noexcept = 0; virtual std::string to_string() const = 0; // Remote operation virtual void ping() = 0; protected: MWObjectProxy(MiddlewareBase* mw_base); private: MiddlewareBase* mw_base_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/QueryMetadataImpl.h0000644000015301777760000000333212320776161031000 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_INTERNAL_QUERYMETADATAIMPL_H #define UNITY_INTERNAL_QUERYMETADATAIMPL_H #include #include namespace unity { namespace scopes { namespace internal { class QueryMetadataImpl { public: QueryMetadataImpl(std::string const& locale, std::string const& form_factor); QueryMetadataImpl(VariantMap const& var); QueryMetadataImpl(QueryMetadataImpl const&) = default; QueryMetadataImpl(QueryMetadataImpl&&) = default; QueryMetadataImpl& operator=(QueryMetadataImpl const&) = default; QueryMetadataImpl& operator=(QueryMetadataImpl&&) = default; virtual ~QueryMetadataImpl() = default; std::string locale() const; std::string form_factor() const; protected: virtual VariantMap serialize() const = 0; virtual void serialize(VariantMap &var) const = 0; virtual std::string metadata_type() const = 0; private: std::string locale_; std::string form_factor_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ScopeConfig.h0000644000015301777760000000475612320776161027622 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_SCOPECONFIG_H #define UNITY_SCOPES_INTERNAL_SCOPECONFIG_H #include #include namespace unity { namespace scopes { namespace internal { class ScopeConfig : public ConfigBase { public: static constexpr const char* SCOPE_CONFIG_GROUP = "ScopeConfig"; static constexpr const char* SCOPE_DISPLAY_GROUP = "Appearance"; ScopeConfig(std::string const& configfile); ~ScopeConfig(); bool overrideable() const; // Optional, returns false if not present std::string display_name() const; std::string description() const; std::string author() const; std::string art() const; // Optional, throws NotFoundException if not present std::string icon() const; // Optional, throws NotFoundException if not present std::string search_hint() const; // Optional, throws NotFoundException if not present std::string hot_key() const; // Optional, throws NotFoundException if not present bool invisible() const; // Optional, returns false if not present std::string scope_runner() const; // Optional, throws NotFoundException if not present VariantMap appearance_attributes() const; // Optional, return empty map if no attributes are present private: bool overrideable_; std::string display_name_; std::string description_; std::string author_; std::unique_ptr art_; std::unique_ptr icon_; std::unique_ptr search_hint_; std::unique_ptr hot_key_; std::unique_ptr invisible_; std::unique_ptr scope_runner_; VariantMap appearance_attributes_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/CategoryRegistry.h0000644000015301777760000000456012320776161030722 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_CATEGORYREGISTRY_H #define UNITY_SCOPES_INTERNAL_CATEGORYREGISTRY_H #include #include #include #include #include namespace unity { namespace scopes { class CategoryRenderer; namespace internal { /** \brief Provides factory method for creating Category instances and keeping track of them. This class is for internal use, most of its functionality is exposed via register_category and find_category method of Reply class. */ class CategoryRegistry { public: CategoryRegistry() = default; /** \brief Deserializes category from a variant_map and registers it. Throws if category with same id exists. \return category instance */ Category::SCPtr register_category(VariantMap const& variant_map); /** \brief Creates category from supplied parameters. Throws if category with same id exists. \return category instance */ Category::SCPtr register_category(std::string const& id, std::string const& title, std::string const& icon, CategoryRenderer const& renderer_template); /** \brief Finds category instance with give id. \return category instance or nullptr if no such category has been registered */ Category::SCPtr lookup_category(std::string const& id) const; /** \brief Register an existing category instance with this registry. Throws if category with sane id exists. */ void register_category(Category::SCPtr category); private: mutable std::mutex mutex_; std::map categories_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/OptionSelectorFilterImpl.h0000644000015301777760000000431212320776161032350 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_OPTIONSELECTORFILTERIMPL_H #define UNITY_SCOPES_INTERNAL_OPTIONSELECTORFILTERIMPL_H #include #include #include #include #include namespace unity { namespace scopes { class FilterState; namespace internal { class OptionSelectorFilterImpl : public FilterBaseImpl { public: OptionSelectorFilterImpl(std::string const& id, std::string const& label, bool multi_select); OptionSelectorFilterImpl(VariantMap const& var); std::string label() const; bool multi_select() const; FilterOption::SCPtr add_option(std::string const& id, std::string const& label); std::list options() const; std::set active_options(FilterState const& filter_state) const; void update_state(FilterState& filter_state, FilterOption::SCPtr option, bool active) const; static void update_state(FilterState& filter_state, std::string const& filter_id, std::string const& option_id, bool value); protected: void serialize(VariantMap& var) const override; void deserialize(VariantMap const& var); std::string filter_type() const override; private: void throw_on_missing(VariantMap::const_iterator const& it, VariantMap::const_iterator const& endit, std::string const& name); std::string label_; bool multi_select_; std::list options_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/CategorisedResultImpl.h0000644000015301777760000000332412320776161031663 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_RESULTIMPL_H #define UNITY_SCOPES_INTERNAL_RESULTIMPL_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class CategorisedResultImpl : public ResultImpl { public: explicit CategorisedResultImpl(Category::SCPtr category); CategorisedResultImpl(CategorisedResultImpl const& other); CategorisedResultImpl(Category::SCPtr category, VariantMap const& variant_map); CategorisedResultImpl(internal::CategoryRegistry const& reg, const VariantMap &variant_map); void set_category(Category::SCPtr category); Category::SCPtr category() const; static CategorisedResult create_result(CategorisedResultImpl* impl); protected: void serialize_internal(VariantMap& var) const override; private: Category::SCPtr category_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/0000755000015301777760000000000012320776463030247 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqQuery.h0000644000015301777760000000277112320776161032217 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQQUERY_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQQUERY_H #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ZmqQuery : public virtual ZmqObjectProxy, public virtual MWQuery { public: ZmqQuery(ZmqMiddleware* mw_base, std::string const& endpoint, std::string const& identity, std::string const& category); virtual ~ZmqQuery(); virtual void run(MWReplyProxy const& reply) override; }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqObjectProxy.h0000644000015301777760000000517212320776161033360 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQOBJECTPROXY_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQOBJECTPROXY_H #include #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ZmqReceiver; // A Zmq proxy that points at some Zmq object, but without a specific type. class ZmqObjectProxy : public virtual MWObjectProxy { public: ZmqObjectProxy(ZmqMiddleware* mw_base, std::string const& endpoint, std::string const& identity, std::string const& category, RequestMode mode, int64_t timeout = -1); virtual ~ZmqObjectProxy(); virtual ZmqMiddleware* mw_base() const noexcept; virtual std::string endpoint() const override; virtual std::string identity() const override; std::string category() const; RequestMode mode() const; virtual int64_t timeout() const noexcept override; virtual std::string to_string() const override; // Remote operation virtual void ping() override; protected: capnproto::Request::Builder make_request_(capnp::MessageBuilder& b, std::string const& operation_name) const; ZmqReceiver invoke_(capnp::MessageBuilder& out_params); ZmqReceiver invoke_(capnp::MessageBuilder& out_params, int64_t timeout); private: std::string endpoint_; std::string identity_; std::string category_; RequestMode mode_; int64_t timeout_; }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ScopeI.h0000644000015301777760000000374012320776161031601 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_SCOPEI_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_SCOPEI_H #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ScopeI : public ServantBase { public: ScopeI(ScopeObjectBase::SPtr const& so); virtual ~ScopeI(); private: virtual void search_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); virtual void activate_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); virtual void perform_action_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); virtual void preview_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/RequestMode.h0000644000015301777760000000215112320776161032647 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_REQUESTMODE_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_REQUESTMODE_H #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { enum RequestMode { Unknown, Oneway, Twoway }; std::string to_string(RequestMode); } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ObjectAdapter.h0000644000015301777760000001065312320776161033127 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_OBJECTADAPTER_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_OBJECTADAPTER_H #include #include #include #include #include #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ServantBase; class ZmqMiddleware; class ObjectAdapter final { public: NONCOPYABLE(ObjectAdapter); ObjectAdapter(ZmqMiddleware& mw, std::string const& name, std::string const& endpoint, RequestMode m, int pool_size); ~ObjectAdapter(); ZmqMiddleware* mw() const; std::string name() const; std::string endpoint() const; ZmqProxy add(std::string const& id, std::shared_ptr const& obj); void remove(std::string const& id); std::shared_ptr find(std::string const& id) const; void add_dflt_servant(std::string const& category, std::shared_ptr const& obj); void remove_dflt_servant(std::string const& category); std::shared_ptr find_dflt_servant(std::string const& id) const; void activate(); void shutdown(); void wait_for_shutdown(); private: // An adapter transitions through these states in order: // // Inactive -> Activating -> Active -> Deactivating -> Destroyed. // // If the adapter is destroyed without ever having been activated, the transitions are // // Inactive -> Deactivating -> Destroyed. // // A deactivated adapter cannot be reactivated. // The Failed state is reachable from any of the other states and indicates // a fatal error condition. enum AdapterState { Inactive, Activating, Active, Deactivating, Destroyed, Failed }; void throw_bad_state(AdapterState state) const; void run_workers(); void init_ctrl_socket(); zmqpp::socket subscribe_to_ctrl_socket(); void stop_workers() noexcept; void safe_bind(zmqpp::socket& s, std::string const& endpoint); std::shared_ptr find_servant(std::string const& id, std::string const& category); // Thread start functions void broker_thread(); void worker_thread(); void cleanup(); void join_with_all_threads(); void store_exception(scopes::MiddlewareException& ex); ZmqMiddleware& mw_; std::string name_; std::string endpoint_; RequestMode mode_; int pool_size_; std::unique_ptr ctrl_; // PUB socket to signal when to deactivate std::mutex ctrl_mutex_; // Synchronizes access to ctrl_ when sending std::thread broker_; // Connects router with dealer std::vector workers_; // Threads for incoming invocations std::atomic_int num_workers_; // For handshake with parent std::promise ready_; // For handshake with child threads std::mutex ready_mutex_; // Protects ready_ std::once_flag once_; std::exception_ptr exception_; // Failed threads deposit their exception here AdapterState state_; std::condition_variable state_changed_; mutable std::mutex state_mutex_; // Map of object identity and servant pairs typedef std::unordered_map> ServantMap; ServantMap servants_; ServantMap dflt_servants_; mutable std::mutex map_mutex_; }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/Current.h0000644000015301777760000000241212320776161032034 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_CURRENT_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_CURRENT_H #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ObjectAdapter; struct Current { std::string id; std::string category; std::string op_name; ObjectAdapter* adapter; }; unity::scopes::internal::InvokeInfo to_info(Current const& c); } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/Util.h0000644000015301777760000000210112320776161031322 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_UTIL_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_UTIL_H #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { void throw_if_bad_endpoint(std::string const& endpoint); } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqScope.h0000644000015301777760000000462512320776161032163 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSCOPE_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSCOPE_H #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ZmqScope : public virtual ZmqObjectProxy, public virtual MWScope { public: ZmqScope(ZmqMiddleware* mw_base, std::string const& endpoint, std::string const& identity, std::string const& category, int64_t timeout); virtual ~ZmqScope(); virtual QueryCtrlProxy search(CannedQuery const& query, VariantMap const& hints, MWReplyProxy const& reply) override; virtual QueryCtrlProxy activate(VariantMap const& result, VariantMap const& hints, MWReplyProxy const& reply) override; virtual QueryCtrlProxy perform_action(VariantMap const& result, VariantMap const& hints, std::string const& widget_id, std::string const& action_id, MWReplyProxy const& reply) override; virtual QueryCtrlProxy preview(VariantMap const& result, VariantMap const& hints, MWReplyProxy const& reply) override; }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqRegistry.h0000644000015301777760000000362312320776161032717 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQREGISTRY_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQREGISTRY_H #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { // Client-side registry proxy for Zmq. The implementation forwards the invocations via Zmq, // and translates the parameters and return value between the Zmq types and the public types. class ZmqRegistry : public virtual ZmqObjectProxy, public virtual MWRegistry { public: ZmqRegistry(ZmqMiddleware* mw_base, std::string const& endpoint, std::string const& identity, std::string const& category, int64_t timeout); virtual ~ZmqRegistry(); // Remote operations. virtual ScopeMetadata get_metadata(std::string const& scope_id) override; virtual MetadataMap list() override; virtual ObjectProxy locate(std::string const& identity) override; }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ServantBase.h0000644000015301777760000000430312320776161032630 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_SERVANTBASE_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_SERVANTBASE_H #include #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class AbstractObject; namespace zmq_middleware { class ServantBase { public: NONCOPYABLE(ServantBase); void safe_dispatch_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r) noexcept; virtual ~ServantBase(); protected: typedef std::function DispatchFunc; typedef std::unordered_map DispatchTable; ServantBase(std::shared_ptr const& delegate, DispatchTable funcs); void dispatch_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); std::shared_ptr del() const noexcept; private: std::shared_ptr delegate_; DispatchTable dispatch_table_; }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqConfig.h0000644000015301777760000000240112320776161032305 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQCONFIG_H #define UNITY_SCOPES_INTERNAL_ZMQCONFIG_H #include namespace unity { namespace scopes { namespace internal { class ZmqConfig : public ConfigBase { public: static const char* ZMQ_CONFIG_GROUP; ZmqConfig(std::string const& configfile); ~ZmqConfig(); std::string public_dir() const; std::string private_dir() const; private: std::string public_dir_; std::string private_dir_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/StateReceiverI.h0000644000015301777760000000301612320776161033271 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_STATERECEIVERI_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_STATERECEIVERI_H #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class StateReceiverI : public ServantBase { public: StateReceiverI(StateReceiverObject::SPtr const& sro); virtual ~StateReceiverI(); private: virtual void push_state_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_STATERECEIVERI_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ReplyI.h0000644000015301777760000000315112320776161031617 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_REPLYI_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_REPLYI_H #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ReplyI : public ServantBase { public: ReplyI(ReplyObjectBase::SPtr const& ro); virtual ~ReplyI(); private: virtual void push_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); virtual void finished_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/RethrowException.hunity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/RethrowException.0000644000015301777760000000224712320776161033561 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_RETHROWEXCEPTION_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_RETHROWEXCEPTION_H #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { // Convert a zmq exception to a unity::MiddlewareException and throw it. void rethrow_zmq_ex(zmqpp::exception const& e); } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqQueryCtrl.h0000644000015301777760000000306412320776161033040 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQQUERYCTRL_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQQUERYCTRL_H #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ZmqQueryCtrl : public virtual ZmqObjectProxy, public virtual MWQueryCtrl { public: ZmqQueryCtrl(ZmqMiddleware* mw_base, std::string const& endpoint, std::string const& identity, std::string const& category); virtual ~ZmqQueryCtrl(); virtual void cancel() override; virtual void destroy() override; }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqException.h0000644000015301777760000000367712320776161033056 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQEXCEPTION_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQEXCEPTION_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { struct Current; void marshal_unknown_exception(capnproto::Response::Builder& r, std::string const& s); void marshal_object_not_exist_exception(capnproto::Response::Builder& r, Current const& c); void marshal_operation_not_exist_exception(capnproto::Response::Builder& r, Current const& c); kj::ArrayPtr const> create_unknown_response(capnp::MessageBuilder& b, std::string const& s); kj::ArrayPtr const> create_object_not_exist_response(capnp::MessageBuilder& b, Current const& c); void throw_if_runtime_exception(capnproto::Response::Reader const& reader); } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/RegistryI.h0000644000015301777760000000417312320776161032341 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_REGISTRYI_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_REGISTRYI_H #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { // Server-side implementation of a Registry object, which maps scope IDs to scope proxies. // It provides remote lookup and listing of the map contents, and local methods to manipulate the map. // // This class is thread-safe: differnt threads can concurrently update the map while lookup operations // are in progress. class RegistryI : public ServantBase { public: RegistryI(RegistryObjectBase::SPtr const& ro); virtual ~RegistryI(); private: virtual void get_metadata_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); virtual void list_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); virtual void locate_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqQueryProxyFwd.hunity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqQueryProxyFwd.0000644000015301777760000000214112320776161033541 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQQUERYPROXYFWD_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQQUERYPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ZmqQuery; typedef std::shared_ptr ZmqQueryProxy; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqRegistryProxyFwd.hunity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqRegistryProxyF0000644000015301777760000000216012320776161033634 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQREGISTRYPROXYFWD_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQREGISTRYPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ZmqRegistry; typedef std::shared_ptr ZmqRegistryProxy; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqReceiver.h0000644000015301777760000000351512320776161032653 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQRECEIVER_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQRECEIVER_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { // Simple message receiver. Converts a message received from zmq (either as a single message or in parts) // to a Cap'n Proto segment list, taking care of any alignment issues. The receiver instance must stay // in scope until unmarshaling is complete. class ZmqReceiver final { public: NONCOPYABLE(ZmqReceiver); ZmqReceiver(ZmqReceiver&&) = default; ZmqReceiver& operator=(ZmqReceiver&&) = default; ZmqReceiver(zmqpp::socket& s); kj::ArrayPtr const> receive(); private: zmqpp::socket& s_; std::vector parts_; std::vector> copied_parts_; std::vector> segments_; }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/VariantConverter.hunity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/VariantConverter.0000644000015301777760000000341012320776161033535 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_VARIANTCONVERTER_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_VARIANTCONVERTER_H #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { // Utility functions to convert to/from Variant and VariantMap. void to_value(Variant const& v, unity::scopes::internal::zmq_middleware::capnproto::Value::Builder& b); Variant to_variant(unity::scopes::internal::zmq_middleware::capnproto::Value::Reader const& r); void to_value_dict(VariantMap const& vm, unity::scopes::internal::zmq_middleware::capnproto::ValueDict::Builder& b); VariantMap to_variant_map(unity::scopes::internal::zmq_middleware::capnproto::ValueDict::Reader const& r); void to_value_array(VariantArray const& va, capnp::List::Builder& b); VariantArray to_variant_array(capnp::List::Reader const &r); } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqReplyProxyFwd.hunity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqReplyProxyFwd.0000644000015301777760000000214112320776161033527 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQREPLYPROXYFWD_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQREPLYPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ZmqReply; typedef std::shared_ptr ZmqReplyProxy; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqScopeProxyFwd.hunity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqScopeProxyFwd.0000644000015301777760000000214112320776161033505 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSCOPEPROXYFWD_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSCOPEPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ZmqScope; typedef std::shared_ptr ZmqScopeProxy; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/CMakeLists.txt0000644000015301777760000000020212320776161032774 0ustar pbusernogroup00000000000000file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h") set(UNITY_SCOPES_LIB_HDRS ${UNITY_SCOPES_LIB_HDRS} ${headers} PARENT_SCOPE) ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqObjectProxyFwd.hunity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqObjectProxyFwd0000644000015301777760000000215212320776161033566 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQOBJECTPROXYFWD_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQOBJECTPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ZmqObjectProxy; typedef std::shared_ptr ZmqProxy; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqReply.h0000644000015301777760000000313412320776161032177 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQREPLY_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQREPLY_H #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ZmqReply : public virtual ZmqObjectProxy, public virtual MWReply { public: ZmqReply(ZmqMiddleware* mw_base, std::string const& endpoint, std::string const& identity, std::string const& category); virtual ~ZmqReply(); virtual void push(VariantMap const& result) override; virtual void finished(ListenerBase::Reason reason, std::string const& error_message) override; }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/QueryCtrlI.h0000644000015301777760000000321512320776161032457 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_QUERYCTRLI_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_QUERYCTRLI_H #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class QueryCtrlI : public ServantBase { public: QueryCtrlI(QueryCtrlObjectBase::SPtr const& qo); virtual ~QueryCtrlI(); private: virtual void cancel_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); virtual void destroy_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ConnectionPool.h0000644000015301777760000000422712320776161033351 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_CONNECTIONPOOL_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_CONNECTIONPOOL_H #include #include #include #include #include #include // Simple connection pool for invocation threads. Zmq sockets are not thread-safe, which means // that a proxy cannot directly contain a socket because that would cause invocations on the same proxy by // different threads to crash. // So, we maintain a pool of invocation threads, with each thread keeping its own cache of sockets. // Sockets are indexed by adapter name and created lazily. namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ConnectionPool final { public: NONCOPYABLE(ConnectionPool); ConnectionPool(zmqpp::context& context); ~ConnectionPool(); zmqpp::socket& find(std::string const& endpoint, RequestMode m); void remove(std::string const& endpoint); void register_socket(std::string const& endpoint, zmqpp::socket socket, RequestMode m); private: struct Connection { zmqpp::socket socket; RequestMode mode; }; typedef std::unordered_map CPool; zmqpp::context& context_; CPool pool_; std::mutex mutex_; }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqMiddleware.h0000644000015301777760000001260112320776161033160 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQMIDDLEWARE_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQMIDDLEWARE_H #include #include #include #include #include #include #include #include #include #include namespace unity { namespace scopes { class ScopeBase; namespace internal { class RuntimeImpl; namespace zmq_middleware { class ObjectAdapter; class ServantBase; class ZmqMiddleware final : public MiddlewareBase { public: ZmqMiddleware(std::string const& server_name, std::string const& configfile, RuntimeImpl* runtime); virtual ~ZmqMiddleware(); virtual void start() override; virtual void stop() override; virtual void wait_for_shutdown() override; virtual ObjectProxy string_to_proxy(std::string const& s) override; virtual std::string proxy_to_string(MWProxy const& proxy) override; virtual MWRegistryProxy create_registry_proxy(std::string const& identity, std::string const& endpoint) override; virtual MWScopeProxy create_scope_proxy(std::string const& identity) override; virtual MWScopeProxy create_scope_proxy(std::string const& identity, std::string const& endpoint) override; virtual MWQueryProxy create_query_proxy(std::string const& identity, std::string const& endpoint) override; virtual MWQueryCtrlProxy create_query_ctrl_proxy(std::string const& identity, std::string const& endpoint) override; virtual MWStateReceiverProxy create_state_receiver_proxy(std::string const& identity) override; virtual MWQueryCtrlProxy add_query_ctrl_object(QueryCtrlObjectBase::SPtr const& ctrl) override; virtual void add_dflt_query_ctrl_object(QueryCtrlObjectBase::SPtr const& ctrl) override; virtual MWQueryProxy add_query_object(QueryObjectBase::SPtr const& query) override; virtual void add_dflt_query_object(QueryObjectBase::SPtr const& query) override; virtual MWRegistryProxy add_registry_object(std::string const& identity, RegistryObjectBase::SPtr const& registry) override; virtual MWReplyProxy add_reply_object(ReplyObjectBase::SPtr const& reply) override; virtual MWScopeProxy add_scope_object(std::string const& identity, ScopeObjectBase::SPtr const& scope) override; virtual void add_dflt_scope_object(ScopeObjectBase::SPtr const& scope) override; virtual MWStateReceiverProxy add_state_receiver_object(std::string const& identity, StateReceiverObject::SPtr const& state_receiver) override; virtual std::string get_scope_endpoint() override; virtual std::string get_query_endpoint() override; virtual std::string get_query_ctrl_endpoint() override; zmqpp::context* context() const noexcept; ThreadPool* invoke_pool(); int64_t locate_timeout() const noexcept; private: ObjectProxy make_typed_proxy(std::string const& endpoint, std::string const& identity, std::string const& category, RequestMode mode, int64_t timeout); std::shared_ptr find_adapter(std::string const& name, std::string const& endpoint_dir); ZmqProxy safe_add(std::function& disconnect_func, std::shared_ptr const& adapter, std::string const& identity, std::shared_ptr const& servant); std::function safe_dflt_add(std::shared_ptr const& adapter, std::string const& category, std::shared_ptr const& servant); std::string server_name_; zmqpp::context context_; typedef std::map> AdapterMap; AdapterMap am_; std::unique_ptr invokers_; mutable std::mutex data_mutex_; // Protects am_ and invokers_ UniqueID unique_id_; enum State { Stopped, Starting, Started }; State state_; std::condition_variable state_changed_; mutable std::mutex state_mutex_; // Protects state_ ZmqConfig config_; const int64_t twoway_timeout_; // Default timeout for twoway invocations int64_t locate_timeout_; // Timeout for registry locate() }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqStateReceiverProxyFwd.hunity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqStateReceiverP0000644000015301777760000000232112320776161033540 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSTATERECEIVERPROXYFWD_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSTATERECEIVERPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ZmqStateReceiver; typedef std::shared_ptr ZmqStateReceiverProxy; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSTATERECEIVERPROXYFWD_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqSender.h0000644000015301777760000000266712320776161032336 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSENDER_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSENDER_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { // Simple message sender. Sends a Cap'n Proto segment list sending each segment as a zmq message part. class ZmqSender final { public: NONCOPYABLE(ZmqSender); ZmqSender(zmqpp::socket& s); void send(kj::ArrayPtr const> segments); private: zmqpp::socket& s_; }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/QueryI.h0000644000015301777760000000266512320776161031642 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_QUERYI_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_QUERYI_H #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class QueryI : public ServantBase { public: QueryI(QueryObjectBase::SPtr const& qo); virtual ~QueryI(); private: virtual void run_(Current const& current, capnp::AnyPointer::Reader& in_params, capnproto::Response::Builder& r); }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqQueryCtrlProxyFwd.hunity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqQueryCtrlProxy0000644000015301777760000000216512320776161033655 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQQUERYCTRLPROXYFWD_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQQUERYCTRLPROXYFWD_H #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ZmqQueryCtrl; typedef std::shared_ptr ZmqQueryCtrlProxy; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqStateReceiver.hunity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/zmq_middleware/ZmqStateReceiver.0000644000015301777760000000327412320776161033506 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSTATERECEIVER_H #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSTATERECEIVER_H #include #include #include namespace unity { namespace scopes { namespace internal { namespace zmq_middleware { class ZmqStateReceiver : public virtual ZmqObjectProxy, public virtual MWStateReceiver { public: ZmqStateReceiver(ZmqMiddleware* mw_base, std::string const& endpoint, std::string const& identity, std::string const& category); virtual ~ZmqStateReceiver(); void push_state(std::string const& sender_id, StateReceiverObject::State const& state) override; }; } // namespace zmq_middleware } // namespace internal } // namespace scopes } // namespace unity #endif // UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSTATERECEIVER_H unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ActivationReplyObject.h0000644000015301777760000000254112320776161031655 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_ACTIVATIONREPLYOBJECT_H #define UNITY_SCOPES_INTERNAL_ACTIVATIONREPLYOBJECT_H #include #include namespace unity { namespace scopes { namespace internal { class ActivationReplyObject : public ReplyObject { public: ActivationReplyObject(ActivationListenerBase::SPtr const& receiver, RuntimeImpl const* runtime, std::string const& scope_id); virtual bool process_data(VariantMap const& data) override; private: ActivationListenerBase::SPtr const receiver_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/AbstractObject.h0000644000015301777760000000300712320776161030301 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_ABSTRACTOBJECT_H #define UNITY_SCOPES_INTERNAL_ABSTRACTOBJECT_H #include #include #include namespace unity { namespace scopes { namespace internal { class AbstractObject { public: NONCOPYABLE(AbstractObject); UNITY_DEFINES_PTRS(AbstractObject); virtual ~AbstractObject(); // Sets callback to allow this facade to disconnect itself from the middleware. // Called by disconnect(). void set_disconnect_function(std::function func) noexcept; protected: AbstractObject(); void disconnect() noexcept; // Disconnect self from middleware private: std::function disconnect_func_; std::mutex mutex_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/PreviewWidgetImpl.h0000644000015301777760000000407012320776161031017 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_PREVIEWWIDGETIMPL_H #define UNITY_SCOPES_INTERNAL_PREVIEWWIDGETIMPL_H #include #include namespace unity { namespace scopes { namespace internal { class PreviewWidgetImpl { public: PreviewWidgetImpl(std::string const& json_text); PreviewWidgetImpl(std::string const& id, std::string const& widget_type); PreviewWidgetImpl(VariantMap const& var); PreviewWidgetImpl(PreviewWidgetImpl const& other) = default; ~PreviewWidgetImpl() = default; void set_id(std::string const& id); void set_widget_type(std::string const &widget_type); void add_attribute_value(std::string const& key, Variant const& value); void add_attribute_mapping(std::string const& key, std::string const& field_name); std::string id() const; std::string widget_type() const; std::map attribute_mappings() const; VariantMap attribute_values() const; std::string data() const; VariantMap serialize() const; static PreviewWidget create(VariantMap const& var); private: static void throw_on_empty(std::string const& name, std::string const& value); std::string id_; std::string type_; VariantMap attributes_; std::map components_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ThreadSafeQueue.h0000644000015301777760000000747312320776161030435 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_THREADSAFEQUEUE_H #define UNITY_SCOPES_INTERNAL_THREADSAFEQUEUE_H #include #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { // Simple thread-safe queue of items. // If the queue is destroyed while threads are blocked in wait_and_pop(), wait_and_pop() throws std::runtime_error. template class ThreadSafeQueue final { public: NONCOPYABLE(ThreadSafeQueue); typedef T value_type; ThreadSafeQueue(); ~ThreadSafeQueue(); void destroy() noexcept; void push(T const& item); void push(T&& item); T wait_and_pop(); bool try_pop(T& item); bool empty() const noexcept; size_t size() const noexcept; private: std::queue queue_; mutable std::mutex mutex_; std::condition_variable cond_; bool done_; std::atomic num_waiters_; }; template ThreadSafeQueue::ThreadSafeQueue() : done_(false), num_waiters_(0) { } template ThreadSafeQueue::~ThreadSafeQueue() { destroy(); // Don't destroy the object while there are still threads in wait_and_pop(), otherwise // a thread that wakes up in wait_and_pop() will try to re-lock the already-destroyed // mutex. while (num_waiters_.load() > 0) std::this_thread::yield(); // LCOV_EXCL_LINE (impossible to reliably hit with a test) } template void ThreadSafeQueue::destroy() noexcept { std::lock_guard lock(mutex_); if (done_) { return; } done_ = true; cond_.notify_all(); // Wake up anyone asleep in wait_and_pop() } template void ThreadSafeQueue::push(T const& item) { std::lock_guard lock(mutex_); queue_.push(item); cond_.notify_one(); } template void ThreadSafeQueue::push(T&& item) { std::lock_guard lock(mutex_); queue_.emplace(std::move(item)); cond_.notify_one(); } template T ThreadSafeQueue::wait_and_pop() { std::unique_lock lock(mutex_); ++num_waiters_; cond_.wait(lock, [this] { return done_ || queue_.size() != 0; }); if (done_) { lock.unlock(); --num_waiters_; throw std::runtime_error("ThreadSafeQueue: queue destroyed while thread was blocked in wait_and_pop()"); } T item = std::move(queue_.front()); queue_.pop(); --num_waiters_; return item; } template bool ThreadSafeQueue::try_pop(T& item) { std::lock_guard lock(mutex_); if (queue_.empty()) { return false; } item = std::move(queue_.front()); queue_.pop(); return true; } template bool ThreadSafeQueue::empty() const noexcept { std::lock_guard lock(mutex_); return queue_.empty(); } template size_t ThreadSafeQueue::size() const noexcept { std::lock_guard lock(mutex_); return queue_.size(); } } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/ConfigBase.h0000644000015301777760000000312012320776161027403 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_INTERNAL_CONFIGBASE_H #define UNITY_SCOPES_INTERNAL_CONFIGBASE_H #include namespace unity { namespace util { class IniParser; } namespace scopes { namespace internal { class ConfigBase { public: ConfigBase(); ConfigBase(std::string const& configfile); virtual ~ConfigBase(); unity::util::IniParser::SPtr parser() const; virtual std::string get_string(std::string const& group, std::string const& key) const; virtual std::string get_optional_string(std::string const& group, std::string const& key) const; virtual std::string get_middleware(std::string const& group, std::string const& key) const; virtual void throw_ex(::std::string const& reason) const; private: unity::util::IniParser::SPtr parser_; std::string configfile_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/QueryObjectBase.h0000644000015301777760000000353712320776161030446 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_INTERNAL_QUERYOBJECTBASE_H #define UNITY_SCOPES_INTERNAL_QUERYOBJECTBASE_H #include #include #include #include namespace unity { namespace scopes { namespace internal { class QueryObjectBase : public AbstractObject { public: UNITY_DEFINES_PTRS(QueryObjectBase); // Remote operation implementation virtual void run(MWReplyProxy const& reply, InvokeInfo const& info) noexcept = 0; virtual void cancel(InvokeInfo const& info) = 0; // Called locally, by QueryCtrlObject virtual bool pushable(InvokeInfo const& info) const noexcept = 0; // Called locally, by ReplyImpl virtual int cardinality(InvokeInfo const& info) const noexcept = 0; // Called locally, by ReplyImpl // Used to hold the reference count high until the run call arrives via the middleware, // and we can pass the shared_ptr to the ReplyImpl. virtual void set_self(SPtr const& self) noexcept = 0; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/internal/PreviewQueryObject.h0000644000015301777760000000301512320776161031204 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michal Hruby */ #ifndef UNITY_SCOPES_INTERNAL_PREVIEWQUERYOBJECT_H #define UNITY_SCOPES_INTERNAL_PREVIEWQUERYOBJECT_H #include #include #include namespace unity { namespace scopes { class PreviewQueryBase; namespace internal { class PreviewQueryObject final : public QueryObject { public: UNITY_DEFINES_PTRS(PreviewQueryObject); PreviewQueryObject(std::shared_ptr const& preview_base, MWReplyProxy const& reply, MWQueryCtrlProxy const& ctrl); virtual ~PreviewQueryObject(); void run(MWReplyProxy const& reply, InvokeInfo const& info) noexcept override; private: std::shared_ptr preview_base_; }; } // namespace internal } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/CannedQuery.h0000644000015301777760000000736312320776161026022 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_CANNEDQUERY_H #define UNITY_SCOPES_CANNEDQUERY_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class CannedQueryImpl; } /** \brief Parameters of a search query. Holds all parameters of a search query: the target scope id, query string, department id, and state of the filters. Can be converted to/from scope:// uri schema string. */ class CannedQuery final { public: /// @cond UNITY_DEFINES_PTRS(CannedQuery); /// @endcond /** \brief Creates a query for given scope with empty query string. */ explicit CannedQuery(std::string const& scope_id); /** \brief Creates a query for given scope with specific query string and in given department. */ CannedQuery(std::string const& scope_id, std::string const& query_str, std::string const& department_id); /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ CannedQuery(CannedQuery const &other); CannedQuery(CannedQuery&&); CannedQuery& operator=(CannedQuery const& other); CannedQuery& operator=(CannedQuery&&); //@} /// @cond ~CannedQuery(); /// @endcond /** \brief Sets or updates the department. */ void set_department_id(std::string const& dep_id); /** \brief Sets or updates the query string. */ void set_query_string(std::string const& query_str); /** \brief Sets filter state. */ void set_filter_state(FilterState const& filter_state); /** \brief Returns the scope identifier of this CannedQuery. \return The scope identifier. */ std::string scope_id() const; /** \brief Returns the department id of this CannedQuery. \return The department id. */ std::string department_id() const; /** \brief Returns the query string of this CannedQuery. \return The query string. */ std::string query_string() const; /// @cond VariantMap serialize() const; /// @endcond /** \brief Returns a string representation of this CannedQuery object as a URI using scope:// schema. \return The URI for the query. */ std::string to_string() const; /** \brief Get state of the filters for this CannedQuery. Pass this state to methods of specific filter instances (such as unity::scopes::OptionSelectorFilter::active_options())to examine filter state. \return The state of the filters. */ FilterState filter_state() const; /** \brief Recreates a CannedQuery object from a scope:// URI. \return a CannedQuery instance \throws InvalidArgumentException if the URI cannot be parsed. */ static CannedQuery from_string(); private: CannedQuery(internal::CannedQueryImpl *impl); std::unique_ptr p; friend class internal::CannedQueryImpl; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/Scope.h0000644000015301777760000001306512320776161024651 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_SCOPE_H #define UNITY_SCOPES_SCOPE_H #include #include #include #include #include #include #include namespace unity { namespace scopes { class Result; class FilterState; class ActionMetadata; class SearchMetadata; /** \brief Allows queries, preview requests, and activation requests to be sent to a scope. */ class Scope : public virtual Object { public: /** \brief Initiates a search query. The search() method expects a SearchListenerBase, which it uses to return the results for the query. search() may block for some time, for example, if the target scope is not running and needs to be started first. Results for the query may begin to arrive only after search() completes (but may also arrive while search() is still running). \param query_string search string \param metadata additional data to pass to scope \param reply The callback object to receive replies \return A proxy that permits cancellation of this request */ virtual QueryCtrlProxy search(std::string const& query_string, SearchMetadata const& metadata, SearchListenerBase::SPtr const& reply) = 0; /** \brief Initiates a search query (overloaded method). This method has same synopsis as previous method, but it takes additional unity::scopes::FilterState argument. \param query_string search string \param filter_state state of filters \param metadata additional data to pass to scope \param reply The callback object to receive replies \return A proxy that permits cancellation of this request */ virtual QueryCtrlProxy search(std::string const& query_string, FilterState const& filter_state, SearchMetadata const& metadata, SearchListenerBase::SPtr const& reply) = 0; /** \brief Initiates a search query (overloaded method). This method has same synopsis as previous method, but it takes additional department identifier argument. \param query_string search string \param department_id identifier of a department to search \param filter_state state of filters \param metadata additional data to pass to scope \param reply The callback object to receive replies \return query handler */ virtual QueryCtrlProxy search(std::string const& query_string, std::string const& department_id, FilterState const& filter_state, SearchMetadata const& metadata, SearchListenerBase::SPtr const& reply) = 0; /** \brief Initiates activation of a search result. \param result activated result \param metadata additional data to pass to scope \param reply The callback object to receive replies \return A proxy that permits cancellation of this request */ virtual QueryCtrlProxy activate(Result const& result, ActionMetadata const& metadata, ActivationListenerBase::SPtr const& reply) = 0; /** \brief Initiates activation of a preview action. \param result Result that was previewed. \param metadata additional data to pass to scope \param widget_id identifier of 'actions' widget of activated action \param action_id identifier of an action to activate \param reply The callback object to receive replies \return A proxy that permits cancellation of this request */ virtual QueryCtrlProxy perform_action(Result const& result, ActionMetadata const& metadata, std::string const& widget_id, std::string const& action_id, ActivationListenerBase::SPtr const& reply) = 0; /** \brief Initiates preview request. \param result Result to be previewed \param metadata additional data to pass to scope \param reply The callback object to receive replies \return A proxy that permits cancellation of this request */ virtual QueryCtrlProxy preview(Result const& result, ActionMetadata const& metadata, PreviewListenerBase::SPtr const& reply) = 0; /** \brief Destroys a Scope. Destroying a Scope has no effect on any query that might still be in progress. */ virtual ~Scope(); protected: /// @cond Scope(); /// @endcond }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/Variant.h0000644000015301777760000001276312320776161025210 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_VARIANT_H #define UNITY_SCOPES_VARIANT_H #include #include #include #include namespace unity { namespace scopes { class Variant; /** \typedef VariantMap \brief A dictionary of (string, Variant) pairs. */ typedef std::map VariantMap; /** \brief An array of variants */ typedef std::vector VariantArray; namespace internal { struct VariantImpl; struct NullVariant; } // namespace internal /** \brief Simple variant class that can hold an integer, boolean, string, double, dictionary, array or null value. */ class Variant final // LCOV_EXCL_LINE // lcov incorrectly reports this line as uncovered { public: /** \brief Type of value held by a Variant instance. */ enum Type { Null, Int, Bool, String, Double, Dict, Array }; /**@name Constructors and destructor */ /** \brief The default constructor creates a Variant instance containing a null. */ Variant() noexcept; /** \brief Creates a Variant instance that stores the supplied integer. */ explicit Variant(int val) noexcept; /** \brief Creates a Variant instance that stores the supplied double. */ explicit Variant(double val) noexcept; /** \brief Creates a Variant instance that stores the supplied boolean. */ explicit Variant(bool val) noexcept; /** \brief Creates a Variant instance that stores the supplied string. */ explicit Variant(std::string const& val); /** \brief Converts the supplied pointer to a string and stores the string in the Variant instance. */ explicit Variant(char const* val); // Required to prevent Variant("Hello") from storing a bool explicit Variant(VariantMap const& val); explicit Variant(VariantArray const& val); /** \brief Construct a null variant. */ static Variant const& null(); /** \brief Destructor. */ ~Variant(); /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ Variant(Variant const&); Variant(Variant&&); Variant& operator=(Variant const&); Variant& operator=(Variant&&); //@} /**@name Value assignment The assignment operators replace the value currently held by a Variant with the supplied value, potentially changing the type of the value held by the Variant. Assigning a `const char*` to a Variant stores the corresponding `std::string` value. */ //{@ Variant& operator=(int val) noexcept; Variant& operator=(double val) noexcept; Variant& operator=(bool val) noexcept; Variant& operator=(std::string const& val); Variant& operator=(char const* val); // Required to prevent v = "Hello" from storing a bool Variant& operator=(VariantMap const& val); Variant& operator=(VariantArray const& val); //@} /**@name Comparison operators Two variants are considered equal if they both store values of the same type and equal value. For Variants storing values of different type, ordering follows the types defined in the Type enum. For example, any integer value compares less than any boolean value. For Variants of the same type, the stored values determine order as usual. */ //{@ bool operator==(Variant const&) const noexcept; bool operator<(Variant const&) const noexcept; //@} /**@name Value accessors The accessor methods retrieve a value of the specified type. If a Variant currently stores a value of different type, these methods throw `unity::LogicException`. */ //{@ int get_int() const; double get_double() const; bool get_bool() const; std::string get_string() const; VariantMap get_dict() const; VariantArray get_array() const; /** \brief Test if variant holds null value. \return True if variant holds null. */ bool is_null() const; //@} /**@name Observers */ /** \brief Returns the type of value currently stored by this Variant. */ Type which() const noexcept; /**@name Modifiers */ /** \brief Swaps the contents of this Variant with `other`. */ void swap(Variant& other) noexcept; /**@name Serialization */ //@{ /** \brief Serializes the variant to a JSON encoded string. */ std::string serialize_json() const; /** \brief Deserializes a JSON encoded string to a `Variant`. */ static Variant deserialize_json(std::string const& json_string); //@} private: Variant(internal::NullVariant const&); std::unique_ptr p; friend class VariantImpl; }; /** \brief Swaps the contents of two Variants. */ void swap(Variant&, Variant&) noexcept; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/VariantBuilder.h0000644000015301777760000000634312320776161026514 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_VARIANTBUILDER_H #define UNITY_SCOPES_VARIANTBUILDER_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class VariantBuilderImpl; } /** \brief Helper class for creating and populating Variant containers. The main purpose of this class is to ease creation of variant containers needed for PreviewWidget instances or any other classes that require non-trivial variant definitions. For example, the value of the "rating" key of the following JSON template \code { "type": "reviews", ... "reviews": [{"rating": null, "review": null, "author": null}] } \endcode can be created with VariantBuilder as follows: \code VariantBuilder builder; builder.add_tuple({{"rating", Variant::null())}, {"review", Variant::null()}, {"author", Variant::null()}}); \endcode */ class VariantBuilder { public: VariantBuilder(); virtual ~VariantBuilder(); /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ VariantBuilder(VariantBuilder const& other); VariantBuilder(VariantBuilder&& other); VariantBuilder& operator=(VariantBuilder const& other); VariantBuilder& operator=(VariantBuilder&& other); //@} /** \brief Adds a tuple of key-value pairs to an array. It can be used multiple times to create an array of tuples, for example: \code [{"a": 1, "b": 2}, {"c": 2, "d" : 3}] \endcode can be created with: \code VariantBuilder builder; builder.add_tuple({{"a", Variant(1)}, {"b", Variant(2)}}); builder.add_tuple({{"c", Variant(2)}, {"d", Variant(3)}}); \endcode */ void add_tuple(std::initializer_list> const& tuple); /** \brief Adds a tuple of key-value pairs to an array. This is an overloaded version of add_tuple that accepts `std::vector` instead of `std::initializer_list`, making it more convenient for language bindings. */ void add_tuple(std::vector> const& tuple); /** \brief Retrieves a completed variant. Returns the completed variant and resets this builder, so the builder can be re-used. \return The completed variant. \throws unity::LogicException if the builder does not hold a variant. */ Variant end(); private: std::unique_ptr p; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/ScopeBase.h0000644000015301777760000002752612320776161025453 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_SCOPEBASE_H #define UNITY_SCOPES_SCOPEBASE_H #include #include #include #include #include #include #include #include /** \brief Expands to the identifier of the scope create function. @hideinitializer */ #define UNITY_SCOPE_CREATE_FUNCTION unity_scope_create /** \brief Expands to the identifier of the scope destroy function. @hideinitializer */ #define UNITY_SCOPE_DESTROY_FUNCTION unity_scope_destroy // Convenience definitions for looking up the create and destroy functions in the symbol table // of a dynamically loaded scope. // UNITY_SCOPE_CREATE_SYMSTR and UNITY_SCOPE_DESTROY_SYMSTR expand to a string literal containing the name // of the create and destroy function, respectively. #ifndef DOXYGEN_SKIP # define UNITY_SCOPE_STR(sym) #sym # define UNITY_SCOPE_XSTR(sym) UNITY_SCOPE_STR(sym) #endif /** \brief Expands to the identifier of the scope create function as a string literal. @hideinitializer */ #define UNITY_SCOPE_CREATE_SYMSTR UNITY_SCOPE_XSTR(UNITY_SCOPE_CREATE_FUNCTION) /** \brief Expands to the identifier of the scope destroy function as a string literal. @hideinitializer */ #define UNITY_SCOPE_DESTROY_SYMSTR UNITY_SCOPE_XSTR(UNITY_SCOPE_DESTROY_FUNCTION) namespace unity { namespace scopes { class CannedQuery; namespace internal { class ScopeBaseImpl; class ScopeLoader; class RuntimeImpl; } /** \file ScopeBase.h \class ScopeBase \brief Base class for a scope implementation. Scopes are accessed by the scopes run time as a shared library (one library per scope). Each scope must implement a class that derives from ScopeBase, for example: ~~~ #include class MyScope : public unity::scopes::ScopeBase { public: MyScope(); virtual ~MyScope(); virtual int start(); // Mandatory virtual void stop(); // Mandatory virtual void run(); // Optional }; ~~~ The derived class must provide implementations of the pure virtual methods start() and stop(). In addition, the library must provide two functions with "C" linkage: - a create function that must return a pointer to the derived instance - a destroy function that is passed the pointer returned by the create function Typically, the create and destroy functions will simply call `new` and `delete`, respectively. (However, there is no requirement that the derived class instance must be heap-allocated.) If the create function throws an exception, the destroy function will not be called. If the create function returns NULL, the destroy function _will_ be called with NULL as its argument. Rather than hard-coding the names of the functions, use the #UNITY_SCOPE_CREATE_FUNCTION and #UNITY_SCOPE_DESTROY_FUNCTION macros, for example: ~~~ unity::scopes::ScopeBase* UNITY_SCOPE_CREATE_FUNCTION() { return new MyScope; // Example only, heap-allocation is not mandatory } void UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope) { delete scope; // Example only, heap-allocation is not mandatory } ~~~ After the scopes run time has obtained a pointer to the class instance from the create function, it calls start(), which allows the scope to intialize itself. This is followed by call to run(). The call to run() is made by a separate thread; its only purpose is to pass a thread of control to the scope, for example, to run an event loop. When the scope should complete its activities, the run time calls stop(). The calls to the create function, start(), stop(), and the destroy function) are made by the same thread. The scope implementation, if it does not return from run(), is expected to return from run() in response to a call to stop() in a timely manner. */ class ScopeBase { public: /// @cond NONCOPYABLE(ScopeBase); virtual ~ScopeBase(); /// @endcond /** \brief This value must be returned from the start() method. */ static constexpr int VERSION = UNITY_SCOPES_VERSION_MAJOR; /** \brief Called by the scopes run time after the create function completes. If start() throws an exception, stop() will _not_ be called. The call to start() is made by the same thread that calls the create function. \param scope_id The name of the scope as defined by the scope's configuration file. \param registry A proxy to the scope registry. This parameter is provided for aggregating scopes that need to retrieve proxies to their child scopes. \return Any return value other than ScopeBase::VERSION will cause the scopes run time to refuse to load the scope. The return value is used to ensure that the shared library containing the scope is ABI compatible with the scopes run time. */ virtual int start(std::string const& scope_id, RegistryProxy const& registry) = 0; /** \brief Called by the scopes run time when the scope should shut down. A scope should deallocate as many resources as possible when stop() is called, for example, deallocate any caches and close network connections. In addition, if the scope implements run() and did not return from run(), it must return from run() in response to the call to stop(). Exceptions from stop() are ignored. The call to stop() is made by the same thread that calls the create function and start(). */ virtual void stop() = 0; /** \brief Called by the scopes run time after it has called start() to hand a thread of control to the scope. run() passes a thread of control to the scope to do with as it sees fit, for example, to run an event loop. During finalization, the scopes run time joins with the thread that called run(). This means that, if the scope implementation does not return from run(), it is expected to arrange for run() to complete in timely manner in response to a call to stop(). Failure to do so will cause deadlock during finalization. If run() throws an exception, the run time handles the exception and calls stop() in response. */ virtual void run(); /** \brief Called by the scopes run time when a scope needs to instantiate a query. This method must return an instance that is derived from QueryBase. The implementation of this method must return in a timely manner, that is, it should perform only minimal initialization that is guaranteed to complete quickly. The call to search() is made by an arbitrary thread. \param query The query string to be executed by the returned object instance. \param metadata additional data sent by the client. \return The query instance. */ virtual SearchQueryBase::UPtr search(CannedQuery const& query, SearchMetadata const& metadata) = 0; /** \brief Called by the scopes run time when a scope needs to respond to a result activation request. This method must return an instance that is derived from ActivationQueryBase. The implementation of this method must return in a timely manner, that is, it should perform only minimal initialization that is guaranteed to complete quickly. The call to activate() is made by an arbitrary thread. The default implementation returns an instance of ActivationQueryBase that responds with ActivationResponse::Status::NotHandled. \param result The result that should be activated. \param metadata additional data sent by the client. \return The activation instance. */ virtual ActivationQueryBase::UPtr activate(Result const& result, ActionMetadata const& metadata); /** \brief Invoked when a scope is requested to handle a preview action. This method must return an instance that is derived from ActivationQueryBase. The implementation of this method must return in a timely manner, that is, it should perform only minimal initialization that is guaranteed to complete quickly. The call to activate() is made by an arbitrary thread. The default implementation returns an instance of ActivationQueryBase that responds with ActivationResponse::Status::NotHandled. \param result The result that was previewed. \param metadata Additional data sent by client. \param widget_id The identifier of the 'actions' widget of the activated action. \param action_id The identifier of the action that was activated. \return The activation instance. */ virtual ActivationQueryBase::UPtr perform_action(Result const& result, ActionMetadata const& metadata, std::string const& widget_id, std::string const& action_id); /** \brief Invoked when a scope is requested to create a preview for a particular result. This method must return an instance that is derived from PreviewQueryBase. The implementation of this method must return in a timely manner, that is, it should perform only minimal initialization that is guaranteed to complete quickly. The call to activate() is made by an arbitrary thread. \param result The result that should be previewed. \param metadata Additional data sent by the client. \return The preview instance. */ virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const& metadata) = 0; /** \brief Returns the version information for the scopes API that the scope was linked with. */ static void runtime_version(int& v_major, int& v_minor, int& v_micro) noexcept; /** \brief Returns directory where the scope files are. Note, scope directory is only known after the scope has been instantantiated, e.g. it's not available in the constructor. */ std::string scope_directory() const; protected: /// @cond ScopeBase(); private: std::unique_ptr p; friend class internal::ScopeLoader; friend class internal::RuntimeImpl; /// @endcond }; } // namespace scopes } // namespace unity /** \brief The function called by the scopes run time to initialize the scope. It must return a pointer to an instance derived from ScopeBase. The returned instance need not be heap-allocated, but must remain in scope until the destroy function is called by the scopes run time. If this function throws an exception, the destroy function will _not_ be called. If this function returns NULL, the destroy function _will_ be called with NULL as its argument. \return The pointer to the ScopeBase instance. */ extern "C" unity::scopes::ScopeBase* UNITY_SCOPE_CREATE_FUNCTION(); /** \brief The function called by the scopes run time to finalize the scope. The passed pointer is the pointer that was returned by the create function. Exceptions thrown by the destroy function are ignored. \param p The pointer to the instance to be destroyed (previously returned by the create function). */ extern "C" void UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* p); namespace unity { namespace scopes { /** \brief Convenience typedef for the create function pointer. */ typedef decltype(&UNITY_SCOPE_CREATE_FUNCTION) CreateFunction; /** \brief Convenience typedef for the destroy function pointer. */ typedef decltype(&UNITY_SCOPE_DESTROY_FUNCTION) DestroyFunction; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/ScopeExceptions.h0000644000015301777760000001335112320776161026711 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_SCOPEEXCEPTIONS_H #define UNITY_SCOPES_SCOPEEXCEPTIONS_H #include namespace unity { namespace scopes { /** \brief Exception to indicate that something went wrong with the middleware layer. */ class MiddlewareException : public virtual unity::Exception { public: /** \brief Constructs the exception. \param reason Further details about the cause of the exception. */ explicit MiddlewareException(std::string const& reason); /**@name Copy and assignment Copy constructor and assignment operator have the usual value semantics. */ //{@ MiddlewareException(MiddlewareException const&); MiddlewareException& operator=(MiddlewareException const&); //@} /// @cond virtual ~MiddlewareException(); /// @endcond /** \brief Returns a std::exception_ptr to this. \return std::exception_ptr to this. */ virtual std::exception_ptr self() const override; }; /** \brief Exception to indicate that a (twoway) request was sent to an object with an unknown identity. */ class ObjectNotExistException : public virtual MiddlewareException { public: /** \brief Constructs the exception. \param reason Further details about the cause of the exception. \param id The identity of the unknown object. */ explicit ObjectNotExistException(std::string const& reason, std::string const& id); /**@name Copy and assignment Copy constructor and assignment operator have the usual value semantics. */ //{@ ObjectNotExistException(ObjectNotExistException const&); ObjectNotExistException& operator=(ObjectNotExistException const&); //@} /// @cond virtual ~ObjectNotExistException() noexcept; /// @endcond /** \brief Returns a std::exception_ptr to this. \return std::exception_ptr to this. */ virtual std::exception_ptr self() const override; /** \brief Returns the identity of the non-existent object. \return The identity of the non-existent object. */ virtual std::string id() const; private: std::string id_; }; /** \brief Exception to indicate that a twoway request timed out. */ class TimeoutException : public virtual MiddlewareException { public: /** \brief Constructs the exception. \param reason Further details about the cause of the exception. */ explicit TimeoutException(std::string const& reason); /**@name Copy and assignment Copy constructor and assignment operator have the usual value semantics. */ //{@ TimeoutException(TimeoutException const&); TimeoutException& operator=(TimeoutException const&); //@} /// @cond virtual ~TimeoutException() noexcept; /// @endcond /** \brief Returns a std::exception_ptr to this. \return std::exception_ptr to this. */ virtual std::exception_ptr self() const override; }; /** \brief Exception to indicate that something went wrong with the contents of configuration files. */ class ConfigException : public virtual unity::Exception { public: /** \brief Constructs the exception. \param reason Further details about the cause of the exception. */ explicit ConfigException(std::string const& reason); /**@name Copy and assignment Copy constructor and assignment operator have the usual value semantics. */ //{@ ConfigException(ConfigException const&); ConfigException& operator=(ConfigException const&); //@} /// @cond virtual ~ConfigException(); /// @endcond /** \brief Returns a std::exception_ptr to this. \return std::exception_ptr to this. */ virtual std::exception_ptr self() const override; }; /** \brief Exception to indicate that an object wasn't found by a lookup function. */ class NotFoundException : public virtual unity::Exception { public: /** \brief Constructs the exception. \param reason Further details about the cause of the exception. \param name The name of the object that was not found. */ explicit NotFoundException(std::string const& reason, std::string const& name); /**@name Copy and assignment Copy constructor and assignment operator have the usual value semantics. */ //{@ NotFoundException(NotFoundException const&); NotFoundException& operator=(NotFoundException const&); //@} /// @cond virtual ~NotFoundException(); /// @endcond /** \brief Returns a std::exception_ptr to this. \return std::exception_ptr to this. */ virtual std::exception_ptr self() const override; /** \brief Returns the name that was passed to the constructor. \return The name that was passed to the constructor. */ virtual std::string name() const; private: std::string name_; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/Category.h0000644000015301777760000000451412320776161025354 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_CATEGORY_H #define UNITY_SCOPES_CATEGORY_H #include #include #include #include #include namespace unity { namespace scopes { class CategoryRenderer; namespace internal { class CategoryImpl; class CategoryRegistry; } /** \brief A set of related results returned by a scope and displayed within a single pane in the Unity dash. To create a Category, use ReplyProxy::register_category. \see ResultItem */ class Category { public: /// @cond NONCOPYABLE(Category); UNITY_DEFINES_PTRS(Category); virtual ~Category(); /// @endcond /** \brief Get identifier of this Category \return The category identifier. */ std::string id() const; /** \brief Get title of this Category \return The category title. */ std::string title() const; /** \brief Get icon of this Category \return The category icon. */ std::string icon() const; /** \brief Get renderer template of this Category \return The category renderer template. */ CategoryRenderer const& renderer_template() const; // @cond VariantMap serialize() const; // @endcond protected: /// @cond Category(std::string const& id, std::string const& title, std::string const &icon, CategoryRenderer const& renderer_template); Category(VariantMap const& variant_map); /// @endcond friend class internal::CategoryRegistry; private: std::unique_ptr p; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/SearchReply.h0000644000015301777760000001050612320776161026016 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_SEARCHREPLY_H #define UNITY_SCOPES_SEARCHREPLY_H #include #include #include #include #include #include namespace unity { namespace scopes { class CategorisedResult; class Annotation; /** \brief Allows the results of a search query to be sent to the query source. */ class SearchReply : public virtual Reply { public: /** \brief Register departments for the current search reply and provide the current department. current_department_id should in most cases be the department returned by Query::department_id(). Pass an empty string for current_department_id to indicate no active department. \param departments A list of departments. \param current_department_id A department id that should be considered current. */ virtual void register_departments(DepartmentList const& departments, std::string current_department_id = "") = 0; /** \brief Register an existing category instance and send it to the source of the query. The purpose of this call is to register a category obtained via ReplyBase::push(Category::SCPtr) when aggregating results and categories from other scope(s). */ virtual Category::SCPtr register_category(std::string const& id, std::string const& title, std::string const &icon, CategoryRenderer const& renderer_template = CategoryRenderer()) = 0; /** \brief Returns a previously registered category. \return The category instance or `nullptr` if the category does not exist registered. */ virtual void register_category(Category::SCPtr category) = 0; /** \brief Returns a previously registered category. \return The category instance or `nullptr` if the category does not exist. */ virtual Category::SCPtr lookup_category(std::string const& id) = 0; /** \brief Sends a single result to the source of a query. Any calls to push() after finished() was called are ignored. \return The return value is true if the result was accepted, false otherwise. A false return value can be due to finished() having been called earlier, or the client that sent the query having cancelled that query. The return value is false also if the query has a cardinality limit and is reached or exceeded. (The return value is false for the last valid push and subsequent pushes.) */ virtual bool push(CategorisedResult const& result) = 0; /** \brief Register an annotation. The annotation will be rendered at a next available spot below any category registered earlier. To render annotations in the top annotation area, call register_annotation() before registering any categories. \note The Unity shell can ignore some or all annotations, depending on available screen real estate. */ virtual bool register_annotation(Annotation const& annotation) = 0; /** \brief Sends all filters and their state to the source of a query. \return True if the filters were accepted, false otherwise. */ virtual bool push(Filters const& filters, FilterState const& filter_state) = 0; /** \brief Destroys a Reply. If a Reply goes out of scope without a prior call to finished(), the destructor implicitly calls finished(). */ virtual ~SearchReply(); protected: /// @cond SearchReply(); /// @endcond }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/SearchListenerBase.h0000644000015301777760000000613212320776161027303 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_SEARCHLISTENERBASE_H #define UNITY_SCOPES_SEARCHLISTENERBASE_H #include #include #include #include #include #include #include #include namespace unity { namespace scopes { class CategorisedResult; class FilterState; /** \brief Abstract base interface that a scope specializes to receive the results of a query. An instance of this interface must be passed to Scope::create_query(). Results for the query are delivered to the instance by the scopes run time by invoking the appropriate push method. If a scope throw an exception from one of the push() methods, the scopes run time calls ListenerBase::finished() with an 'Error' reason. */ class SearchListenerBase : public ListenerBase { public: /// @cond NONCOPYABLE(SearchListenerBase); UNITY_DEFINES_PTRS(SearchListenerBase); virtual ~SearchListenerBase(); /// @endcond /** \brief Called at most once by the scopes run time for a list of departments returned by a query. The default implementation does nothing. */ virtual void push(DepartmentList const& departments, std::string const& current_department_id); /** \brief Called once by the scopes run time for each result that is returned by a query(). */ virtual void push(CategorisedResult result) = 0; /** \brief Called once by the scopes run time for each annotation that is returned by a query(). The default implementation does nothing. */ virtual void push(Annotation annotation); /** \brief Called once by the scopes run time for each category that is returned by a query(). The default implementation does nothing. Receipt of categories may be interleaved with the receipt of results, that is, there is no guarantee that the complete set of categories will be provided before the first query result. */ virtual void push(Category::SCPtr category); /** \brief Called once by the scopes to send all the filters and their state. The default implementation does nothing. */ virtual void push(Filters const& filters, FilterState const& filter_state); protected: /// @cond SearchListenerBase(); /// @endcond }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/Result.h0000644000015301777760000002022412320776161025051 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_RESULT_H #define UNITY_SCOPES_RESULT_H #include #include #include #include #include namespace unity { namespace scopes { class CategorisedResult; namespace internal { class ResultImpl; class ScopeImpl; } /** \brief The attributes of a result returned by a Scope. The Result API provides convenience methods for some typical attributes (title, art), but scopes are free to add and use any custom attributes with `operator[]`. The only required attribute is 'uri' and it must not be empty before calling Reply::push(). */ class Result { public: /// @cond UNITY_DEFINES_PTRS(Result); /// @endcond /**@name Copy and assignment Copy and assignment (move and non-move versions) have the usual value semantics. */ //{@ Result(Result const& other); Result(Result&&); Result& operator=(Result const& other); Result& operator=(Result&&); //@} /** Destructor. */ virtual ~Result(); /** \brief Stores a Result inside this Result instance. This method is meant to be used by aggregator scopes which want to modify results they receive, but want to keep a copy of the original result so that they can be correctly handled by the original scopes who created them when it comes to activation or previews. Scopes middleware will automatically pass the correct inner stored result to the activation or preview request handler of a scope which created it. \param other The original result to store within this result. \param intercept_activation True if this scope should receive activation and preview requests. */ void store(Result const& other, bool intercept_activation = false); /** \brief Check if this Result instance has a stored result. \return True if there is a stored result */ bool has_stored_result() const; /** \brief Get a stored result. \return stored result \throws unity::InvalidArgumentException if no result was stored in this Result instance. */ Result retrieve() const; /** \brief Set the "uri" attribute of this result. */ void set_uri(std::string const& uri); /** \brief Set the "title" attribute of this result. Equivalent to calling `result["title"] = title;` */ void set_title(std::string const& title); /** \brief Set the "art" attribute of this result. Equivalent to calling `result["art"] = image;` */ void set_art(std::string const& image); /** \brief Set the "dnd_uri" attribute of this result. Equivalent to calling `result["dnd_uri"] = dnd_uri;` */ void set_dnd_uri(std::string const& dnd_uri); /** \brief Indicates to the receiver that this scope should intercept activation requests for this result. By default, a scope receives preview requests for the results it creates, but does not receive activation requests (they are handled directly by the shell). Intercepting activation implies intercepting preview requests as well; this is important for scopes that forward results from other scopes and call set_intercept_activation() on these scopes. A scope that sets intercept activation flag for a result should re-implement ScopeBase::activate() and provide an implementation of ActivationQueryBase that handles the actual activation. If not called, the result will be activated directly by the Unity shell whithout involving the scope, assuming an appropriate URI schema handler is present on the system. */ void set_intercept_activation(); /** \brief Check if this result should be activated directly by the shell because the scope doesn't handle activation of this result. \return True if this result needs to be activated directly. */ bool direct_activation() const; /** \brief Get the proxy of a scope that handles activation and preview of this result. The proxy is only available when receiving this result from a scope, otherwise this method throws LogicException. Activation requests should only be sent to a scope returned by this method only if direct_activation() is false. \return The scope proxy. */ ScopeProxy target_scope_proxy() const; /** \brief Returns reference of a Result attribute. This method can be used to read or initialize both standard ("uri", "title", "art", "dnd_uri") and custom metadata attributes. Referencing a non-existing attribute automatically creates it with a default value of Variant::Type::Null. \param key The name of the attribute. \return A reference to the attribute. \throws unity::Invalidargument if no attribute with the given name exists. */ Variant& operator[](std::string const& key); /** \brief Returns a const reference to a Result attribute. This method can be used for read-only access to both standard ("uri", "title", "art", "dnd_uri") and custom metadata attributes. Referencing a non-existing attribute throws unity::InvalidArgumentException. \param key The name of the attribute. \return A const reference to the attribute. \throws unity::Invalidargument if no attribute with the given name exists. */ Variant const& operator[](std::string const& key) const; /** \brief Get the "uri" property of this Result. This method returns an empty string if this attribute is not of type Variant::Type::String (e.g. it was set with operator[]). \return The value of "uri" or the empty string. */ std::string uri() const noexcept; /** \brief Get the "title" property of this Result. This method returns an empty string if this attribute is not of type Variant::Type::String (e.g. it was set with operator[]). \return The value of "title" or the empty string. */ std::string title() const noexcept; /** \brief Get the "art" property of this Result. This method returns an empty string if this attribute is not of type Variant::Type::String (e.g. it was set with operator[]). \return The value of "art" or the empty string. */ std::string art() const noexcept; /** \brief Get the "dnd_uri" property of this Result. This method returns an empty string if this attribute is not of type Variant::Type::String type (e.g. it was set with operator[]). \return The value of "dnd_uri" or the empty string. */ std::string dnd_uri() const noexcept; /** \brief Check if this Result has an attribute. \param key The attribute name. \return True if the attribute is set. */ bool contains(std::string const& key) const; /** \brief Get the value of an attribute. \param key The attribute name. \return The attribute value. \throws unity::InvalidArgumentException if given attribute hasn't been set. */ Variant const& value(std::string const& key) const; /** \brief Returns a dictionary of all attributes of this Result instance. \return All base attributes and custom attributes set with add_metadata(). */ VariantMap serialize() const; protected: /// @cond explicit Result(const VariantMap &variant_map); explicit Result(internal::ResultImpl* impl); /// @endcond private: std::unique_ptr p; friend class internal::ResultImpl; friend class internal::ScopeImpl; friend class CategorisedResult; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/Version.h.in0000644000015301777760000000647212320776161025636 0ustar pbusernogroup00000000000000// // DO NOT EDIT Version.h (this file)! It is generated from Version.h.in. // /* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_VERSION_H #define UNITY_SCOPES_VERSION_H #ifndef UNITY_SCOPES_VERSION_MAJOR # define UNITY_SCOPES_VERSION_MAJOR @UNITY_SCOPES_MAJOR@ #endif #ifndef UNITY_SCOPES_VERSION_MINOR # define UNITY_SCOPES_VERSION_MINOR @UNITY_SCOPES_MINOR@ #endif #ifndef UNITY_SCOPES_VERSION_MICRO # define UNITY_SCOPES_VERSION_MICRO @UNITY_SCOPES_MICRO@ #endif #define UNITY_SCOPES_VERSION_STR(s) #s #define UNITY_SCOPES_VERSION_XSTR(s) UNITY_SCOPES_VERSION_STR(s) #define UNITY_SCOPES_VERSION_STRING UNITY_SCOPES_VERSION_XSTR(UNITY_SCOPES_VERSION_MAJOR) "." \ UNITY_SCOPES_VERSION_XSTR(UNITY_SCOPES_VERSION_MINOR) "." \ UNITY_SCOPES_VERSION_XSTR(UNITY_SCOPES_VERSION_MICRO) /** \brief Top-level namespace for all things Unity-related. */ namespace unity { /** \brief Top-level namespace for public functionality of the Unity scopes API. */ namespace scopes { /** @name Version information Version information is represented as <major>.<minor>.<micro>. Releases that differ in the major version number are binary incompatible. Releases of the library that differ in the minor or micro version number are binary compatible with older releases, so client code does not need to be recompiled to use the newer library version. Changes in the micro version number indicate bug fixes. Changes in the minor version number indicate feature additions that are binary compatible. */ /** \brief Returns the major version number of the Unity scopes library. The major version number is also available as the macro UNITY_SCOPES_VERSION_MAJOR. */ int major_version(); /** \brief Returns the minor version number of the Unity scopes library. The minor version number is also available as the macro UNITY_SCOPES_VERSION_MINOR. */ int minor_version(); /** \brief Returns the micro version number of the Unity scopes library. The micro version number is also available as the macro UNITY_SCOPES_VERSION_MICRO. */ int micro_version(); /** \brief Returns the Unity scopes version as a string in the format <major>.<minor>.<micro>. The version string is also available as the macro UNITY_SCOPES_VERSION_STRING. */ const char* version_string(); // Returns "major.minor.micro" /// }@ // TODO: Add methods to report compiler version and compiler flags } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/Reply.h0000644000015301777760000000522312320776161024670 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_REPLY_H #define UNITY_SCOPES_REPLY_H #include #include #include namespace unity { namespace scopes { /** \brief Allows query termination to be sent to the source of a query. */ class Reply : public virtual Object { public: /** \brief Informs the source of a query that the query results are complete. Calling finished() informs the source of a query that the final result for the query was sent, that is, that the query is complete. Multiple calls to finished() and calls to error() after finished() was called are ignored. The destructor implicitly calls finished() if a Reply goes out of scope without a prior call to finished(). Similarly, QueryBase::run() implicitly calls finished() when it returns, provided there are no more reply proxies in scope. In other words, calling finished() is optional. The scopes run time ensures that the call happens automatically, either when the last reply proxy goes out of scope, or when QueryBase::run() returns (whichever happens last). */ virtual void finished() = 0; /** \brief Informs the source of a query that the query was terminated due to an error. Multiple calls to error() and calls to finished() after error() was called are ignored. \param ex An exception_ptr indicating the cause of the error. If ex is a `std::exception`, the return value of `what()` is made available to the query source. Otherwise, the query source receives `"unknown exception"`. */ virtual void error(std::exception_ptr ex) = 0; /** \brief Destroys a Reply. If a Reply goes out of scope without a prior call to finished(), the destructor implicitly calls finished(), provided QueryBase::run() has returned. */ virtual ~Reply(); protected: /// @cond Reply(); /// @endcond }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/PreviewListenerBase.h0000644000015301777760000000403712320776161027521 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_PREVIEWLISTENERBASE_H #define UNITY_SCOPES_PREVIEWLISTENERBASE_H #include #include #include #include #include #include #include namespace unity { namespace scopes { /** \brief Abstract base class for a scope to respond to preview requests. An instance of this class must be returned from Scope::preview(). */ class PreviewListenerBase : public ListenerBase { public: /// @cond NONCOPYABLE(PreviewListenerBase); UNITY_DEFINES_PTRS(PreviewListenerBase); virtual ~PreviewListenerBase(); /// @endcond /** \brief Called by the scopes runtime for each column layout definition returned by preview(). */ virtual void push(ColumnLayoutList const& layouts) = 0; /** \brief Called by the scopes runtime for each preview chunk that is returned by preview(). */ virtual void push(PreviewWidgetList const&) = 0; /** \brief Called by the scopes runtime for each data field that is returned by preview(). */ virtual void push(std::string const& key, Variant const& value) = 0; protected: /// @cond PreviewListenerBase(); /// @endcond }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/ListenerBase.h0000644000015301777760000000457512320776161026166 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_LISTENERBASE_H #define UNITY_SCOPES_LISTENERBASE_H #include #include #include namespace unity { namespace scopes { //TODO: fix doc /** \brief Abstract base class to be notified of query completion. Once a query is complete, the run time calls the finished() method once, to inform the caller that the query is complete. */ class ListenerBase { public: /// @cond NONCOPYABLE(ListenerBase); UNITY_DEFINES_PTRS(ListenerBase); virtual ~ListenerBase(); /// @endcond /** \brief Indicates the cause of a call to finished(). The `Error` enumerator indicates that a query terminated abnormally, for example, because a scope could not be reached over the network or explicitly reported an error. */ enum Reason { Finished, Cancelled, Error }; /** \brief Called once by the scopes run time after the final result for a query() was sent. Calls to finished() are made by an arbitrary thread. Exceptions thrown from finished() are ignored. \param r Indicates the cause for the call to finished(). \param error_message If `r` is set to `Error`, `error_message` contains further details. Otherwise, `error_message` is the empty string. */ virtual void finished(Reason r, std::string const& error_message) = 0; protected: /// @cond ListenerBase(); /// @endcond }; /** \brief Convenience function to convert a ListenerBase::Reason enumerator to a string. \return Possible return values are "finished", "cancelled", and "error". */ char const* to_string(ListenerBase::Reason reason); } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/PreviewReplyProxyFwd.h0000644000015301777760000000204412320776161027733 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_PREVIEWREPLYPROXYFWD_H #define UNITY_SCOPES_PREVIEWREPLYPROXYFWD_H #include namespace unity { namespace scopes { class PreviewReply; /** \typedef PreviewReplyProxy \brief Convenience type definition. */ typedef std::shared_ptr PreviewReplyProxy; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/Annotation.h0000644000015301777760000000732012320776161025707 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_ANNOTATION_H #define UNITY_SCOPES_ANNOTATION_H #include #include #include #include #include namespace unity { namespace scopes { class CannedQuery; namespace internal { class AnnotationImpl; class ResultReplyObject; } /** * \brief Query link(s) that result in a new search query when clicked by the user. */ class Annotation final { public: /// @cond UNITY_DEFINES_PTRS(Annotation); /// @endcond /*! \brief Enumeration of supported Annotation types */ enum Type { Link, /**< A simple link with just a label and/or an icon */ GroupedLink /**< A group of links, with a label for the group name and labels for all links inside it */ }; /** * \brief Creates annotation of given type. The Type imposes attributes that are * supported or required by that annotation. */ explicit Annotation(Type atype); /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ Annotation(Annotation const &other); Annotation(Annotation&&); Annotation& operator=(Annotation const& other); Annotation& operator=(Annotation&&); //@} /// @cond virtual ~Annotation(); /// @endcond /** * \brief Sets a label for an annotation. This currently makes sense for Type::GroupedLink only. */ void set_label(std::string const& label); /** * \brief Sets an icon for an annotation. This currently makes sense for Type::Link. */ void set_icon(std::string const& icon); /** * \brief Adds a link to the annotation. There needs to be exactly one link * added for the annotations of type Type::Link * and at least one for Type::GroupedLink. This method * throws InvalidArgumentException if these constraints are violated. */ void add_link(std::string const& label, CannedQuery const& query); /** * \brief Returns label assigned to this annotation. This currently makes sense for Type::GroupedLink only. * \return label The label associated with this annotation. */ std::string label() const; /** * \brief Returns icon assigned to this annotation. This currently only makes sense for Type::Link. * \return The icon associated with this annotation. */ std::string icon() const; /** * \brief Returns all links assigned to given position of this annotation. * \return The link at the given position. */ std::list links() const; /** * \brief Returns the type of this annotation. * \return The type of the annotation. */ Type annotation_type() const; /// @cond VariantMap serialize() const; /// @endcond private: Annotation(internal::AnnotationImpl* impl); std::unique_ptr p; friend class internal::ResultReplyObject; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/ColumnLayout.h0000644000015301777760000000656212320776161026237 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_COLUMNLAYOUT_H #define UNITY_SCOPES_COLUMNLAYOUT_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class ColumnLayoutImpl; } class ColumnLayout final { public: /// @cond UNITY_DEFINES_PTRS(ColumnLayout); /// @endcond /** \brief Creates a layout definition that expects num_of_columns columns to be added with ColumnLayout::add_column. \param num_of_columns The number of columns for the layout. \throws unity::InvalidArgumentException for an invalid number of columns. */ explicit ColumnLayout(int num_of_columns); /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ ColumnLayout(ColumnLayout const& other); ColumnLayout(ColumnLayout&&); ColumnLayout& operator=(ColumnLayout const& other); ColumnLayout& operator=(ColumnLayout&&); //@} /// @cond ~ColumnLayout(); /// @endcond /** \brief Adds a new column and assigns widgets to it. ColumnLayout expects exactly the number of columns passed to the constructor to be created with the add_column method. \throws unity::LogicException if an attempt is made to add more columns than specified in the constructor. \throws unity::LogicException from \link unity::scopes::PreviewReply::register_layout\endlink if a layout has fewer columns than specified in the constructor. */ void add_column(std::vector widget_ids); /** \brief Get the current number of columns in this layout. \return The number of columns added with add_column(). */ int size() const noexcept; /** \brief Get the number of columns expected by this layout as specified in the constructor. \return The number of columns expected by this layout. */ int number_of_columns() const noexcept; /** \brief Retrieve the list of widgets for given column. \param index The index of a column. \return The widget identifiers for the given column index. \throws unity::InvalidArgumentException if the index is invalid. */ std::vector column(int index) const; /// @cond VariantMap serialize() const; /// @endcond private: ColumnLayout(internal::ColumnLayoutImpl *impl); std::unique_ptr p; friend class internal::ColumnLayoutImpl; }; /*! \typedef ColumnLayoutList \brief List of column layouts (see unity::scopes::ColumnLayout) */ typedef std::list ColumnLayoutList; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/ActionMetadata.h0000644000015301777760000000530112320776161026450 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_ACTIONMETADATA_H #define UNITY_SCOPES_ACTIONMETADATA_H #include #include namespace unity { namespace scopes { namespace internal { class ActionMetadataImpl; } /** \brief Metadata passed to scopes for preview and activation. \see unity::scopes::ScopeBase::preview, unity::scopes::ScopeBase::activate, unity::scopes::ScopeBase::perform_action */ class ActionMetadata final { public: /// @cond UNITY_DEFINES_PTRS(ActionMetadata); ~ActionMetadata(); /// @endcond /** \brief Create ActionMetadata with given locale and form factor \param locale locale string, eg. en_EN \param form_factor form factor name, e.g. phone, desktop, phone-version etc. */ ActionMetadata(std::string const& locale, std::string const& form_factor); /** \brief Get the locale string. \return The locale string */ std::string locale() const; /** \brief Get the form factor string. \return The form factor string */ std::string form_factor() const; /** \brief Attach arbitrary data to this ActionMetadata. \param data The data value to attach. */ void set_scope_data(Variant const& data); /** \brief Get data attached to this ActionMetadata. \return The attached data, or Variant::null. */ Variant scope_data() const; /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ ActionMetadata(ActionMetadata const& other); ActionMetadata(ActionMetadata&&); ActionMetadata& operator=(ActionMetadata const &other); ActionMetadata& operator=(ActionMetadata&&); //@} /// @cond VariantMap serialize() const; /// @endcond private: std::unique_ptr p; ActionMetadata(internal::ActionMetadataImpl *impl); friend class internal::ActionMetadataImpl; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/ObjectProxyFwd.h0000644000015301777760000000203612320776161026505 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_OBJECTPROXYFWD_H #define UNITY_SCOPES_OBJECTPROXYFWD_H #include namespace unity { namespace scopes { class Object; /** \typedef ObjectProxy \brief Convenience type definition for the proxy inheritance root. */ typedef std::shared_ptr ObjectProxy; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/QueryCtrlProxyFwd.h0000644000015301777760000000202112320776161027223 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_QUERYCTRLPROXYFWD_H #define UNITY_SCOPES_QUERYCTRLPROXYFWD_H #include namespace unity { namespace scopes { class QueryCtrl; /** \typedef QueryCtrlProxy \brief Convenience type definition. */ typedef std::shared_ptr QueryCtrlProxy; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/ActivationQueryBase.h0000644000015301777760000000405312320776161027517 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_ACTIVATIONQUERYBASE_H #define UNITY_SCOPES_ACTIVATIONQUERYBASE_H #include #include #include namespace unity { namespace scopes { namespace internal { class ActivationQueryBaseImpl; } /** \brief Base class for an activation request that is executed inside a scope. The default implementation responds with ActivationResponse(ActivationResponse::Status::NotHandled). Reimplement this class and return an instance in ScopeBase::activate method for custom activation handling. */ class ActivationQueryBase : public QueryBase { public: /// @cond UNITY_DEFINES_PTRS(ActivationQueryBase); ActivationQueryBase(); virtual ~ActivationQueryBase(); /// @endcond /** \brief Called when the originator of the activation request cancelled it. */ virtual void cancelled() override; /** \brief Return response to the activation request. The response is received by the originator of the request. Default implementation returns ActivationResponse(ActivationResponse::Status::NotHandled. \return The response to the activation request. */ virtual ActivationResponse activate(); private: std::unique_ptr p; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/Object.h0000644000015301777760000000434712320776161025011 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_OBJECT_H #define UNITY_SCOPES_OBJECT_H #include #include namespace unity { namespace scopes { /** \brief The root base class for all proxies. */ class Object { public: /// @cond NONCOPYABLE(Object); virtual ~Object(); /// @endcond /** \brief Returns the endpoint this proxy connects to. \return The endpoint of the proxy. */ virtual std::string endpoint() = 0; /** \brief Returns the identity of the target object of this proxy. \return The identity of the target of the proxy. */ virtual std::string identity() = 0; /** \brief Returns the category of the target object of this proxy. \return The category of the target of the proxy. */ virtual std::string category() = 0; /** \brief Returns the timeout in milliseconds if this proxy is a twoway proxy. For oneway proxies and twoway proxies without a timeout, the return value is -1. \return The timeout value in milliseconds (-1 if none or timeout does not apply). */ virtual int64_t timeout() = 0; // Timeout in milliseconds, -1 == no timeout /** \brief converts a proxy into its string representation. A proxy string can be converted back into a proxy by calling Runtime::string_to_proxy(). \return The string representation of the proxy. */ virtual std::string to_string() = 0; protected: /// @cond Object(); /// @endcond }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/SearchMetadata.h0000644000015301777760000001031712320776161026443 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_SEARCHMETADATA_H #define UNITY_SCOPES_SEARCHMETADATA_H #include #include namespace unity { namespace scopes { namespace internal { class SearchMetadataImpl; class ScopeObject; } /** \brief Metadata passed with search requests. */ class SearchMetadata final { public: /// @cond UNITY_DEFINES_PTRS(SearchMetadata); /// @endcond /** \brief Create SearchMetadata with given locale and form factor. \param locale locale string, eg. en_EN \param form_factor form factor name, e.g. phone, desktop, phone-version etc. */ SearchMetadata(std::string const& locale, std::string const& form_factor); /** \brief Create SearchMetadata with given cardinality, locale and form factor. \param cardinality maximum number of search results \param locale locale string, eg. en_EN \param form_factor form factor name, e.g. phone, desktop, phone-version etc. */ SearchMetadata(int cardinality, std::string const& locale, std::string const& form_factor); /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ SearchMetadata(SearchMetadata const& other); SearchMetadata(SearchMetadata&&); SearchMetadata& operator=(SearchMetadata const &other); SearchMetadata& operator=(SearchMetadata&&); //@} /// @cond ~SearchMetadata(); /// @endcond /** \brief Get the locale string. \return The locale string */ std::string locale() const; /** \brief Get the form factor string. \return The form factor string */ std::string form_factor() const; /** \brief Set cardinality. \param cardinality The maximum number of search results. */ void set_cardinality(int cardinality); /** \brief Get cardinality. \return The maxmium number of search results, or 0 for no limit. */ int cardinality() const; /** \brief Sets a hint. \param key The name of the hint. \param value Hint value */ void set_hint(std::string const& key, Variant const& value); /** \brief Get all hints. \return Hints dictionary. */ VariantMap hints() const; /** \brief Check if this SearchMetadata has a hint. \param key The hint name. \return True if the hint is set. */ bool contains_hint(std::string const& key) const; /** \brief Returns a reference to a hint. This method can be used to read or set hints. Setting a value of an existing hint overwrites its previous value. Referencing a non-existing hint automatically creates it with a default value of Variant::Type::Null. \param key The name of the hint. \return A reference to the hint. */ Variant& operator[](std::string const& key); /** \brief Returns a const reference to a hint. This method can be used for read-only access to hints. Referencing a non-existing hint throws unity::InvalidArgumentException. \param key The name of the hint. \return A const reference to the hint. \throws unity::LogicException if no hint with the given name exists. */ Variant const& operator[](std::string const& key) const; /// @cond VariantMap serialize() const; /// @endcond private: std::unique_ptr p; SearchMetadata(internal::SearchMetadataImpl *impl); friend class internal::SearchMetadataImpl; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/CategorisedResult.h0000644000015301777760000000453212320776161027227 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_CATEGORISEDRESULT_H #define UNITY_SCOPES_CATEGORISEDRESULT_H #include #include namespace unity { namespace scopes { namespace internal { class CategorisedResultImpl; class ResultReplyObject; } /** \brief A result, including the category it belongs to. */ class CategorisedResult: public Result { public: /// @cond UNITY_DEFINES_PTRS(CategorisedResult); /// @endcond /** \brief Creates a CategorisedResult with given category, with all base attributes initially empty. \param category The category for the result. */ explicit CategorisedResult(Category::SCPtr category); /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ CategorisedResult(CategorisedResult const& other); CategorisedResult& operator=(CategorisedResult const& other); CategorisedResult(CategorisedResult&&); CategorisedResult& operator=(CategorisedResult&&); //@} /** \brief Updates the category of this result. \param category The category for the result. */ void set_category(Category::SCPtr category); /** \brief Return category of this result. Get the category instance this result belongs to. \return The category instance. */ Category::SCPtr category() const; private: CategorisedResult(internal::ResultImpl* impl); internal::CategorisedResultImpl* fwd() const; friend class internal::CategorisedResultImpl; friend class internal::ResultReplyObject; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/FilterOption.h0000644000015301777760000000336312320776161026216 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_FILTEROPTION_H #define UNITY_SCOPES_FILTEROPTION_H #include #include #include #include namespace unity { namespace scopes { namespace internal { class FilterOptionImpl; class OptionSelectorFilterImpl; } /** \brief Holds definition of filter option for OptionSelectorFilter. */ class FilterOption final { public: /// @cond UNITY_DEFINES_PTRS(FilterOption); NONCOPYABLE(FilterOption); /// @endcond /** \brief Get the identifier of this filter option. \return The option identifier. */ std::string id() const; /** \brief Get the label of this filter option. \return The option label. */ std::string label() const; /// @cond ~FilterOption(); /// @endcond private: FilterOption(std::string const& id, std::string const& label); std::unique_ptr p; friend class internal::OptionSelectorFilterImpl; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/Link.h0000644000015301777760000000401512320776161024470 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_LINK_H #define UNITY_SCOPES_LINK_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class LinkImpl; class AnnotationImpl; } /** * \brief A hyperlink (label and canned query). */ class Link final { public: /// @cond UNITY_DEFINES_PTRS(Link); /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ Link(Link const& other); Link(Link&&); Link& operator=(Link const& other); Link& operator=(Link&&); //@} /// @cond ~Link(); /// @endcond /** * \brief Returns the label of this Link instance. * \return The label of this link instance. */ std::string label() const; /** * \brief Returns a CannedQuery instance. * \return The canned query. */ CannedQuery query() const; /// @cond VariantMap serialize() const; /// @endcond private: Link(std::string const& label, CannedQuery const& query); Link(VariantMap const& variant_map); std::unique_ptr p; friend class internal::AnnotationImpl; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/Runtime.h0000644000015301777760000001323512320776161025222 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_RUNTIME_H #define UNITY_SCOPES_RUNTIME_H #include #include #include #include #include namespace unity { namespace scopes { class ScopeBase; namespace internal { class RuntimeImpl; } /** \brief The main object for query originators to access the scopes run time. All interactions with the scopes run time require a Runtime object to be instantiated first. The Runtime instance controls the overall life cycle; once a Runtime instance goes out of scope, the application must not make further calls on any instance obtained via the destroyed Runtime. The application must instantiate a Runtime object only after `main()` is entered, and it must destroy the instance before leaving `main()`; failure to do so results in undefined behavior. Note that scope implementations do not need to instantiate a Runtime instance. */ class Runtime { public: /// @cond NONCOPYABLE(Runtime); UNITY_DEFINES_PTRS(Runtime); /// @endcond /** \brief Instantiates the scopes run time for a client with the given (optional) configuration file. The life time of the run time is under control of the caller. Letting the returned `unique_ptr` go out of scope shuts down the run time. You _must not_ create a Runtime instance until after `main()` is entered, and you _must_ destroy it before leaving `main()` (either by explicitly calling destroy(), or by letting the returned `unique_ptr` go out of scope). Failure to do so causes undefined behavior. \param configfile The path name of the configuration file to use. If configfile is the empty string, a default configuration is used. */ // TODO: Update above to state what the default configuration is exactly static UPtr create(std::string const& configfile = ""); static UPtr create_scope_runtime(std::string const& scope_id, std::string const& configfile = ""); /** \brief Shuts down the run time, reclaiming all associated resources. Calling destroy() is optional; the destructor implicitly calls destroy() if it was not called explicitly. However, no exceptions are thrown by the destructor. If you want to log or handle any exceptions during shutdown, call destroy() explicitly before letting the `unique_ptr` returned by create() go out of scope. */ void destroy(); /** \brief Returns a proxy to the Registry object. The returned proxy allows application code to interact with the registry, which provides access to the available scopes. */ RegistryProxy registry() const; /** \brief Run a scope without going through the scope runner. This method is intended to run a scope that can not be loaded via the scope runner, such as those written in languages that can not be dynamically loaded. \param scope_base The scope implementation \param scope_ini_file The full path of scope configuration file */ void run_scope(ScopeBase *const scope_base, std::string const& scope_ini_file); // TODO: Flesh out documentation for this, especially syntax. /** \brief Convert a string to a proxy. This method is intended for testing purposes. Do not use string_to_proxy() in production code! string_to_proxy() converts a string to a proxy. The returned proxy must be down-cast using `dynamic_pointer_cast` to the correct type before it can be used. \param s The string to convert into a proxy. \return The converted proxy. It is possible for the return value to be `nullptr`, but only if the passed string represents a null proxy. Otherwise, the return value is a non-null proxy, or an exception (for example, if the proxy string did not parse correctly, or if the proxy could not be instantiated due to incorrect values inside the string). */ ObjectProxy string_to_proxy(std::string const& s) const; /** \brief Converts a proxy to a string. proxy_to_string() converts the passed proxy to a string. Note that it is typically easier to call the ObjectProxy::to_string() method to achieve the same thing. However, proxy_to_string() is needed in order to obtain a string for a null proxy (because it is not possible to invoke a member function on a null proxy). \param proxy The proxy to convert to a string. \return The string representation of the proxy. */ std::string proxy_to_string(ObjectProxy const& proxy) const; /** \brief Destroys a Runtime instance. The destructor implicitly calls destroy() if the application code does not explicitly destroy the instance. You _must not_ permit a Runtime instance to persist beyond the end of `main()`; doing so has undefined behavior. */ ~Runtime(); private: Runtime(std::string const& scope_id, std::string const& configfile); // Instantiation only via create() std::unique_ptr p; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/PreviewQueryBase.h0000644000015301777760000000526512320776161027045 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_PREVIEWQUERYBASE_H #define UNITY_SCOPES_PREVIEWQUERYBASE_H #include #include #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class QueryBaseImpl; class QueryObject; } // namespace internal /** \brief Abstract base class to represent a particular preview. A scope must return an instance of this class from its implementation of ScopeBase::preview(). \note The constructor of the instance must complete in a timely manner. Do not perform anything in the constructor that might block. */ class PreviewQueryBase : public QueryBase { public: /// @cond NONCOPYABLE(PreviewQueryBase); UNITY_DEFINES_PTRS(PreviewQueryBase); /// @endcond /** \brief Called by scopes run time to start the preview. Your implementation of run() can use the reply proxy to push results for the preview. You can push results from within run(), in which case the preview implicitly completes when run() returns. Alternatively, run() can store the reply proxy and return immediately. In this case, you can use the stored proxy to push results from another thread. It is safe to call `push()` from multiple threads without synchronization. The preview completes either when run() returns, or when the last stored reply proxy goes out of scope (whichever happens last). \param reply The proxy on which to push results for the preview. */ virtual void run(PreviewReplyProxy const& reply) = 0; // Called by the run time to start this query // TODO: Add a method for subpreview request? /// @cond virtual ~PreviewQueryBase(); /// @endcond protected: /// @cond PreviewQueryBase(); /// @endcond }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/0000755000015301777760000000000012320776463025104 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/TypedScopeFixture.h0000644000015301777760000000370212320776161030700 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef UNITY_SCOPES_TESTING_TYPED_SCOPE_FIXTURE_H #define UNITY_SCOPES_TESTING_TYPED_SCOPE_FIXTURE_H #include #include #include #include namespace unity { namespace scopes { namespace testing { /// @cond template struct ScopeTraits { inline static const char* name() { return "unknown"; } inline static std::shared_ptr construct() { return std::make_shared(); } }; template class TypedScopeFixture : public ::testing::Test { public: TypedScopeFixture() : scope(ScopeTraits::construct()), registry_proxy(®istry, [](unity::scopes::Registry*) {}) { } void SetUp() { EXPECT_EQ(UNITY_SCOPES_VERSION_MAJOR, scope->start(ScopeTraits::name(), registry_proxy)); EXPECT_NO_THROW(scope->run()); } void TearDown() { EXPECT_NO_THROW(scope->stop()); } protected: std::shared_ptr scope; unity::scopes::testing::MockRegistry registry; unity::scopes::RegistryProxy registry_proxy; }; /// @endcond } // namespace testing } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/Statistics.h0000644000015301777760000001520612320776161027406 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef UNITY_SCOPES_TESTING_STATISTICS_H #define UNITY_SCOPES_TESTING_STATISTICS_H #include namespace unity { namespace scopes { class ScopeBase; namespace testing { /** * \brief The Sample class models the interface to a sample of raw observations * and their statistical properties. */ class Sample { public: /** Unsigned type describing the size of the sample. */ typedef std::size_t SizeType; /** Floating point type describing an individual observation. */ typedef double ValueType; /** Function signature for enumerating all raw observations. */ typedef std::function Enumerator; /** \cond */ virtual ~Sample() = default; Sample& operator=(const Sample&) = delete; Sample& operator=(Sample&&) = delete; bool operator==(const Sample&) const = delete; /** \endcond */ /** Query the size of the sample. */ virtual SizeType get_size() const = 0; /** Query the empirical mean of the sample. */ virtual ValueType get_mean() const = 0; /** Query the empirical variance of the sample. */ virtual ValueType get_variance() const = 0; /** Enumerate all raw observations from the sample. */ virtual void enumerate(const Enumerator& enumerator) const = 0; protected: /** \cond */ Sample() = default; Sample(const Sample&) = default; Sample(Sample&&) = default; /** \endcond */ }; /** * \brief Summarizes the different outcomes of evaluating a hypothesis at a * given confidence level. * * Please note that in statistical testing, !(rejected) != not_rejected. That is, * whenever a hypothesis is rejected, further investigations are required and the * conclusion that a hypothesis does not hold is not valid. * */ enum class HypothesisStatus { rejected, ///< The hypothesis holds at the given confidence level not_rejected ///< The hypothesis does not hold at the given confidence level }; /** \brief We model a hypothesis as a function that can be evaluated for a given confidence value. */ typedef std::function Hypothesis; /** * \brief The Confidence enum contains well-known confidence levels and is * used in cases where only tabulated critical values are available. */ enum class Confidence { zero_point_five_percent, ///< alpha = 0.5% one_percent, ///< alpha = 1% two_point_five_percent, ///< alpha = 2.5% five_percent, ///< alpha = 5% ten_percent ///< alpha = 10% }; /** \brief Specialized hypothesis that can only be evaluated at well-known confidence levels. */ typedef std::function HypothesisForWellKnownConfidence; /** \brief Implements the Anderson-Darling test for normality for the case of empirical mean and variance.*/ struct AndersonDarlingTest { /** * \brief Executing the test returns a set of hypothesis that have to be evaluated * at the desired confidence level. */ struct Result { HypothesisForWellKnownConfidence data_fits_normal_distribution; ///< H0, data is normally distributed }; /** * \brief for_normality evaluates a given sample to check if its underlying distribution is normal. * \param sample The sample to check. * \return A hypothesis containing the test statistics, can be evaluated at different confidence levels. */ Result for_normality(const Sample& sample); }; /** * \brief Implements different variants of the Student's T-test (see http://en.wikipedia.org/wiki/Student's_t-test) * * \code * * unity::scopes::testing::OutOfProcessBenchmark benchmark; * * unity::scopes::testing::Result search_result; * unity::scopes::ActionMetadata meta_data{default_locale, default_form_factor}; * * static const std::size_t sample_size{10}; * static const std::chrono::seconds per_trial_timeout{1}; * * unity::scopes::testing::Benchmark::PreviewConfiguration config * { * [search_result, meta_data]() { return std::make_pair(search_result, meta_data); }, * { * sample_size, * per_trial_timeout * } * }; * * auto result = benchmark.for_preview(scope, config); * * auto test_result = unity::scopes::testing::StudentsTTest().one_sample( * reference_preview_performance, * result); * * EXPECT_EQ(unity::scopes::testing::HypothesisStatus::not_rejected, * test_result.sample_mean_is_eq_to_reference(0.05)); * EXPECT_EQ(unity::scopes::testing::HypothesisStatus::not_rejected, * test_result.sample_mean_is_ge_than_reference(0.05)); * EXPECT_EQ(unity::scopes::testing::HypothesisStatus::rejected, * test_result.sample_mean_is_le_than_reference(0.05)); * \endcode * */ struct StudentsTTest { /** * \brief Executing the test returns a set of hypothesis that have to be evaluated * at the desired confidence level. */ struct Result { double t; ///< The t value of the test. Hypothesis both_means_are_equal; ///< H0, both means are equal. Hypothesis sample1_mean_lt_sample2_mean; ///< H1, sample1 mean < sample2 mean. Hypothesis sample1_mean_gt_sample2_mean; ///< H2, sample1 mean > sample2 mean. }; /** * \brief one_sample calculates the Student's T test for one sample and a known mean and std. dev.. * \param sample Sample of values. * \param mean The known mean of the underlying distribution * \param std_dev The known std. dev. of the underlying distribution * \return */ Result one_sample( const Sample& sample, Sample::ValueType mean, Sample::ValueType std_dev); /** * \brief two_independent_samples calculates the Student's T test for two samples * \param sample1 The first sample * \param sample2 The second sample * \return An instance of Result. */ Result two_independent_samples( const Sample& sample1, const Sample& sample2); }; } // namespace testing } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/Category.h0000644000015301777760000000372112320776161027030 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef UNITY_SCOPES_TESTING_CATEGORY_H #define UNITY_SCOPES_TESTING_CATEGORY_H #include namespace unity { namespace scopes { class CategoryRenderer; namespace testing { /** \brief Implementation of Category class for testing. This class inherits from the unity::scopes::Category and provides a public constructor that allows for creating categories with no need to register them via a real instance of unity::scopes::SearchReply. */ class Category : public unity::scopes::Category { public: /** \brief Creates category instance. \param id The identifier of this category \param title The title of this category \param icon The icon of this category \param renderer_template The renderer template */ inline Category(std::string const& id, std::string const& title, std::string const &icon, CategoryRenderer const& renderer_template) : unity::scopes::Category(id, title, icon, renderer_template) { } /** \brief Deserializes category from a variant data. \param variant_map Serialized category */ inline Category(VariantMap const& variant_map) : unity::scopes::Category(variant_map) { } }; } // namespace testing } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/ScopeMetadataBuilder.h0000644000015301777760000000513112320776161031271 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef UNITY_SCOPES_TESTING_SCOPEMETADATA_BUILDER_H #define UNITY_SCOPES_TESTING_SCOPEMETADATA_BUILDER_H #include namespace unity { namespace scopes { namespace testing { /// @cond class ScopeMetadataBuilder { public: template class Optional { public: inline Optional() = default; inline Optional(const T& t) : value(new T{t}) { } inline operator bool() const { return value.get() != nullptr; } inline Optional& operator=(const T& rhs) { if (*this) *value = rhs; else value.reset(new T{rhs}); return *this; } inline Optional& operator=(const Optional& rhs) { if (rhs) *this = *rhs; else value.reset(); return *this; } inline const T& operator*() const { return *value; } private: std::unique_ptr value; }; ScopeMetadataBuilder(); ~ScopeMetadataBuilder(); ScopeMetadataBuilder& scope_id(std::string const& value); ScopeMetadataBuilder& proxy(ScopeProxy const& value); ScopeMetadataBuilder& display_name(std::string const& value); ScopeMetadataBuilder& description(std::string const& value); ScopeMetadataBuilder& art(Optional const& value); ScopeMetadataBuilder& icon(Optional const& value); ScopeMetadataBuilder& search_hint(Optional const& value); ScopeMetadataBuilder& hot_key(Optional const& value); ScopeMetadataBuilder& invisible(Optional value); ScopeMetadata operator()() const; private: struct Private; std::unique_ptr p; }; /// @endcond } // namespace testing } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/MockPreviewReply.h0000644000015301777760000000266712320776161030532 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef UNITY_SCOPES_TESTING_MOCK_PREVIEW_REPLY_H #define UNITY_SCOPES_TESTING_MOCK_PREVIEW_REPLY_H #include #include namespace unity { namespace scopes { namespace testing { /// @cond class MockPreviewReply : public unity::scopes::PreviewReply { public: MockPreviewReply() = default; // From Reply MOCK_METHOD0(finished, void()); MOCK_METHOD1(error, void(std::exception_ptr)); // From SearchReply MOCK_METHOD1(register_layout, bool(ColumnLayoutList const&)); MOCK_METHOD1(push, bool(PreviewWidgetList const&)); MOCK_METHOD2(push, bool(std::string const&, Variant const&)); }; /// @endcond } // namespace testing } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/Result.h0000644000015301777760000000245412320776161026533 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef UNITY_SCOPES_TESTING_RESULT_H #define UNITY_SCOPES_TESTING_RESULT_H #include namespace unity { namespace scopes { namespace testing { /** \brief A simple class implementation of unity::scopes::Result that provides a default constructor. This class makes it possible to create dummy results with no attributes, for testing purposes. */ class Result : public unity::scopes::Result { public: /** \brief Default constructor, creates Result instance with no attributes. */ Result(); }; } // namespace testing } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/InProcessBenchmark.h0000644000015301777760000000461012320776161030771 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef UNITY_SCOPES_TESTING_IN_PROCESS_BENCHMARK_H #define UNITY_SCOPES_TESTING_IN_PROCESS_BENCHMARK_H #include namespace unity { namespace scopes { class ScopeBase; namespace testing { /** * \brief The InProcessBenchmark class provides scope authors * with runtime benchmarking capabilities. The actual runs are executed in the same process. * * \code * unity::scopes::testing::InProcessBenchmark benchmark; * * unity::scopes::Query query{scope_id}; * query.set_query_string(scope_query_string); * * unity::scopes::SearchMetadata meta_data{default_locale, default_form_factor}; * * unity::scopes::testing::Benchmark::QueryConfiguration config; * config.sampler = [query, meta_data]() * { * return std::make_pair(query, meta_data); * }; * * auto result = benchmark.for_query(scope, config); * \endcode * */ class InProcessBenchmark : public Benchmark { public: InProcessBenchmark() = default; virtual Result for_query(const std::shared_ptr& scope, QueryConfiguration configuration) override; virtual Result for_preview(const std::shared_ptr& scope, PreviewConfiguration preview_configuration) override; virtual Result for_activation(const std::shared_ptr& scope, ActivationConfiguration activation_configuration) override; virtual Result for_action(const std::shared_ptr& scope, ActionConfiguration activation_configuration) override; }; } // namespace testing } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/CMakeLists.txt0000644000015301777760000000020212320776161027631 0ustar pbusernogroup00000000000000file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h") set(UNITY_SCOPES_LIB_HDRS ${UNITY_SCOPES_LIB_HDRS} ${headers} PARENT_SCOPE) unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/OutOfProcessBenchmark.h0000644000015301777760000000530612320776161031462 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef UNITY_SCOPES_TESTING_OUT_OF_PROCESS_BENCHMARK_H #define UNITY_SCOPES_TESTING_OUT_OF_PROCESS_BENCHMARK_H #include namespace unity { namespace scopes { class ScopeBase; namespace testing { /** * \brief The OutOfProcessBenchmark class provides scope authors * with runtime benchmarking capabilities. The actual runs are executed in another process. * * Please note that this class provides better test isolation than the class InProcessBenchmark * and we promote use of this implementation due to this feature. However, as the internal * implementation relies on fork(), the results in case of multi-threaded environments that exist * before the execution of the benchmark are undefined. * * \code * unity::scopes::testing::OutOfProcessBenchmark benchmark; * * unity::scopes::Query query{scope_id}; * query.set_query_string(scope_query_string); * * unity::scopes::SearchMetadata meta_data{default_locale, default_form_factor}; * * unity::scopes::testing::Benchmark::QueryConfiguration config; * config.sampler = [query, meta_data]() * { * return std::make_pair(query, meta_data); * }; * * auto result = benchmark.for_query(scope, config); * \endcode * */ class OutOfProcessBenchmark : public InProcessBenchmark { public: OutOfProcessBenchmark() = default; Result for_query(const std::shared_ptr& scope, QueryConfiguration configuration) override; Result for_preview(const std::shared_ptr& scope, PreviewConfiguration preview_configuration) override; Result for_activation(const std::shared_ptr& scope, ActivationConfiguration activation_configuration) override; Result for_action(const std::shared_ptr& scope, ActionConfiguration activation_configuration) override; }; } // namespace testing } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/MockRegistry.h0000644000015301777760000000252512320776161027676 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef UNITY_SCOPES_TESTING_MOCK_REGISTRY_H #define UNITY_SCOPES_TESTING_MOCK_REGISTRY_H #include #include #include namespace unity { namespace scopes { namespace testing { /// @cond class MockRegistry : public Registry, public virtual MockObject { public: MockRegistry() = default; MOCK_METHOD1(get_metadata, ScopeMetadata(std::string const&)); MOCK_METHOD0(list, MetadataMap()); MOCK_METHOD1(list_if, MetadataMap(std::function)); }; /// @endcond } // namespace testing } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/MockSearchReply.h0000644000015301777760000000401412320776161030302 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef UNITY_SCOPES_TESTING_MOCK_SEARCHREPLY_H #define UNITY_SCOPES_TESTING_MOCK_SEARCHREPLY_H #include #include #include #include namespace unity { namespace scopes { namespace testing { /// @cond class MockSearchReply : public unity::scopes::SearchReply, public virtual MockObject { public: MockSearchReply() = default; // From Reply MOCK_METHOD0(finished, void()); MOCK_METHOD1(error, void(std::exception_ptr)); // From SearchReply MOCK_METHOD2(register_departments, void(DepartmentList const&, std::string )); MOCK_METHOD4(register_category, Category::SCPtr(std::string const&, std::string const&, std::string const&, CategoryRenderer const&)); MOCK_METHOD1(register_category, void(Category::SCPtr category)); MOCK_METHOD1(lookup_category, Category::SCPtr(std::string const&)); MOCK_METHOD1(push, bool(CategorisedResult const&)); MOCK_METHOD2(push, bool(Filters const&, FilterState const&)); MOCK_METHOD1(register_annotation, bool(Annotation const& annotation)); }; /// @endcond } // namespace testing } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/MockObject.h0000644000015301777760000000244312320776161027273 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_TESTING_MOCK_OBJECT_H #define UNITY_SCOPES_TESTING_MOCK_OBJECT_H #include #include namespace unity { namespace scopes { namespace testing { /// @cond class MockObject : public virtual Object { public: MockObject() = default; MOCK_METHOD0(endpoint, std::string()); MOCK_METHOD0(identity, std::string()); MOCK_METHOD0(category, std::string()); MOCK_METHOD0(timeout, int64_t()); MOCK_METHOD0(to_string, std::string()); }; /// @endcond } // namespace testing } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/testing/Benchmark.h0000644000015301777760000003355412320776161027154 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef UNITY_SCOPES_TESTING_BENCHMARK_H #define UNITY_SCOPES_TESTING_BENCHMARK_H #include #include #include #include #include #include #include #include #include namespace unity { namespace scopes { class ScopeBase; namespace testing { /** * \brief The Benchmark class defines an interface to provide scope authors with runtime benchmarking capabilities * to be used in their own testing. */ class Benchmark { public: /** * \brief The Result struct encapsulates all of the result gathered from one * individual benchmark run consisting of multiple independent trials. */ struct Result { /** Size of the sample, corresponds to number of trials. */ std::size_t sample_size{0}; /** Timing characteristics captured during the benchmark run. */ struct Timing : public Sample { /** All timing-based results are measures in fractional seconds. */ typedef std::chrono::duration Seconds; /** \cond */ Timing() = default; Timing(const Timing&) = default; Timing(Timing&&) = default; /** \endcond */ /** Query the size of the sample. */ Sample::SizeType get_size() const; /** Query the empirical mean of the sample. */ Sample::ValueType get_mean() const; /** Query the empirical variance of the sample. */ Sample::ValueType get_variance() const; /** Enumerate all raw observations from the sample. */ void enumerate(const Sample::Enumerator& enumerator) const; /** * \brief Checks if a timing sample is statistically significantly * faster than a reference timing sample. * \throw std::runtime_error if either this sample or the reference sample is not normally distributed. * \param reference The reference timing sample to compare to. * \param alpha The critical value of the statistical test. The lower, the higher the relevance of the test. * \return true iff this timing sample is significantly faster than the reference sample. */ bool is_significantly_faster_than_reference(const Timing& reference, double alpha = 0.05) const; /** * \brief Checks if a timing sample is statistically significantly * faster than a reference timing with mean 'mean and std. dev. 'std_dev' * \throw std::runtime_error if this sample is not normally distributed. * \param mean The reference mean to compare to. * \param std_dev The reference std. dev. to compare to. * \param alpha The critical value of the statistical test. The lower, the higher the relevance of the test. * \return true iff this timing sample is significantly faster than the reference sample. */ bool is_significantly_faster_than_reference( double mean, double std_dev, double alpha = 0.05) const; /** * \brief Checks if a timing sample is statistically significantly * slower than a reference timing sample. * \throw std::runtime_error if either this sample or the reference sample is not normally distributed. * \param reference The reference timing sample to compare to. * \param alpha The critical value of the statistical test. The lower, the higher the relevance of the test. * \return true iff this timing sample is significantly slower than the reference. */ bool is_significantly_slower_than_reference(const Timing& reference, double alpha = 0.05) const; /** * \brief Checks if a timing sample is statistically significantly * slower than a reference timing with mean 'mean and std. dev. 'std_dev' * \throw std::runtime_error if this sample is not normally distributed. * \param mean The reference mean to compare to. * \param std_dev The reference std. dev. to compare to. * \param alpha The critical value of the statistical test. The lower, the higher the relevance of the test. * \return true iff this timing sample is significantly slower than the reference. */ bool is_significantly_slower_than_reference( double mean, double std_dev, double alpha = 0.05) const; /** Minimum execution time for the benchmarked operation. */ Seconds min{Seconds::min()}; /** Maximum execution time for the benchmarked operation. */ Seconds max{Seconds::min()}; /** Mean execution time for the benchmarked operation. */ Seconds mean{Seconds::min()}; /** Std. deviation in execution time for the benchmarked operation. */ Seconds std_dev{Seconds::min()}; /** Kurtosis in execution time for the benchmarked operation. */ Seconds kurtosis{Seconds::min()}; /** Skewness in execution time for the benchmarked operation. */ Seconds skewness{Seconds::min()}; /** Histogram of measured execution times for the benchmarked operation. */ std::vector> histogram{}; /** Raw sample vector, with sample.size() == sample_size */ std::vector sample{}; } timing{}; ///< Runtime-specific sample data. /** * \brief load_from restores a result from the given input stream. * \throw std::runtime_error in case of issues. * \param in The stream to read from. */ void load_from(std::istream& in); /** * \brief save_to stores a result to the given output stream. * \throw std::runtime_error in case of issues. * \param out The stream to write to. */ void save_to(std::ostream& out); /** * \brief load_from_xml restores a result stored as xml from the given input stream. * \throw std::runtime_error in case of issues. * \param in The stream to read from. */ void load_from_xml(std::istream& in); /** * \brief save_to_xml stores a result as xml to the given output stream. * \throw std::runtime_error in case of issues. * \param out The stream to write to. */ void save_to_xml(std::ostream& out); }; /** * \brief The StatisticsConfiguration struct contains options controlling * the calculation of benchmark result statistics. */ struct StatisticsConfiguration { /** Number of bins in the final histogram. */ std::size_t histogram_bin_count{10}; }; /** * \brief The TrialConfiguration struct contains options controlling * the execution of individual trials. */ struct TrialConfiguration { /** The number of independent trials. Please note that the number should not be << 10 */ std::size_t trial_count{25}; /** Wait at most this time for one trial to finish or throw if a timeout is encountered. */ std::chrono::microseconds per_trial_timeout{std::chrono::seconds{10}}; /** Fold in statistics configuration into the overall trial setup. */ StatisticsConfiguration statistics_configuration{}; }; /** * \brief The QueryConfiguration struct constains all options controlling the * benchmark of scope query operations. */ struct QueryConfiguration { /** Function signature for choosing a query configuration. */ typedef std::function< std::pair< unity::scopes::CannedQuery, unity::scopes::SearchMetadata>() > Sampler; /** * The sampling function instance for choosing a query configuration. * Has to be set to an actual instance. */ Sampler sampler{}; /** fold in trial configuration options into the overall setup. */ TrialConfiguration trial_configuration{}; }; /** * \brief The PreviewConfiguration struct constains all options controlling the * benchmark of scope preview operations. */ struct PreviewConfiguration { /** Function signature for choosing a preview configuration. */ typedef std::function< std::pair< unity::scopes::Result, unity::scopes::ActionMetadata >() > Sampler; /** * The sampling function instance for choosing a preview configuration. * Has to be set to an actual instance. */ Sampler sampler{}; /** fold in trial configuration options into the overall setup. */ TrialConfiguration trial_configuration{}; }; /** * \brief The ActivationConfiguration struct constains all options controlling the * benchmark of scope activation operations. */ struct ActivationConfiguration { /** Function signature for choosing an activation configuration. */ typedef std::function< std::pair< unity::scopes::Result, unity::scopes::ActionMetadata>() > Sampler; /** * The sampling function instance for choosing a preview configuration. * Has to be set to an actual instance. */ Sampler sampler{}; /** fold in trial configuration options into the overall setup. */ TrialConfiguration trial_configuration{}; }; /** * \brief The ActionConfiguration struct constains all options controlling the * benchmark of scope action activation operations. */ struct ActionConfiguration { /** Function signature for choosing an action invocation configuration. */ typedef std::function< std::tuple< unity::scopes::Result, unity::scopes::ActionMetadata, std::string, std::string >() > Sampler; /** * The sampling function instance for choosing an action activation configuration. * Has to be set to an actual instance. */ Sampler sampler{}; /** fold in trial configuration options into the overall setup. */ TrialConfiguration trial_configuration; }; /** \cond */ virtual ~Benchmark() = default; Benchmark(const Benchmark&) = delete; Benchmark(Benchmark&&) = delete; Benchmark& operator=(const Benchmark&) = delete; Benchmark& operator=(Benchmark&&) = delete; /** \endcond */ /** * \brief for_query executes a benchmark to measure the scope's query performance. * \throw std::runtime_error in case of timeouts. * \throw std::logic_error in case of misconfiguration. * \param scope The scope instance to benchmark. * \param configuration Options controlling the experiment. * \return An instance of Result. */ virtual Result for_query(const std::shared_ptr& scope, QueryConfiguration configuration) = 0; /** * \brief for_preview executes a benchmark to measure the scope's preview performance. * \throw std::runtime_error in case of timeouts. * \throw std::logic_error in case of misconfiguration. * \param scope The scope instance to benchmark. * \param configuration Options controlling the experiment. * \return An instance of Result. */ virtual Result for_preview(const std::shared_ptr& scope, PreviewConfiguration configuration) = 0; /** * \brief for_preview executes a benchmark to measure the scope's activation performance. * \throw std::runtime_error in case of timeouts. * \throw std::logic_error in case of misconfiguration. * \param scope The scope instance to benchmark. * \param configuration Options controlling the experiment. * \return An instance of Result. */ virtual Result for_activation(const std::shared_ptr& scope, ActivationConfiguration configuration) = 0; /** * \brief for_preview executes a benchmark to measure the scope's action activation performance. * \throw std::runtime_error in case of timeouts. * \throw std::logic_error in case of misconfiguration. * \param scope The scope instance to benchmark. * \param configuration Options controlling the experiment. * \return An instance of Result. */ virtual Result for_action(const std::shared_ptr& scope, ActionConfiguration configuration) = 0; protected: Benchmark() = default; }; bool operator==(const Benchmark::Result& lhs, const Benchmark::Result& rhs); std::ostream& operator<<(std::ostream&, const Benchmark::Result&); } // namespace testing } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/FilterState.h0000644000015301777760000000452612320776161026030 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_FILTERSTATE_H #define UNITY_SCOPES_FILTERSTATE_H #include #include #include namespace unity { namespace scopes { class FilterBase; namespace internal { class FilterStateImpl; class FilterBaseImpl; } /** \brief Captures state of multiple filters. State can be examined by passing an instance of FilterState to appropriate methods of filters (FilterBase implementations). */ class FilterState final { public: /// @cond UNITY_DEFINES_PTRS(FilterState); ~FilterState(); VariantMap serialize() const; /// @endcond /** \brief Constructs a an empty filter state instance. */ FilterState(); /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ FilterState(FilterState const& other); FilterState(FilterState &&); FilterState& operator=(FilterState const& other); FilterState& operator=(FilterState&& other); //@} /** \brief Check if state for the given filter has been stored. \return True if state for a filter with the given ID is present; false otherwise. */ bool has_filter(std::string const& id) const; /** \brief Removes the state for a specific filter. \param id The identity of the filter to remove. */ void remove(std::string const& id); private: FilterState(internal::FilterStateImpl *pimpl); std::unique_ptr p; friend class internal::FilterBaseImpl; friend class internal::FilterStateImpl; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/ActivationResponse.h0000644000015301777760000000742612320776161027424 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_ACTIVATIONRESPONSE_H #define UNITY_SCOPES_ACTIVATIONRESPONSE_H #include #include #include namespace unity { namespace scopes { namespace internal { class ActivationResponseImpl; } /** \brief Response to a result activation. */ class ActivationResponse final { public: /** \brief Status of a unity::scopes::ScopeBase::activate or unity::scopes::ScopeBase::perform_action request. */ enum Status { NotHandled, /**< Activation of this result wasn't handled by the scope */ ShowDash, /**< Activation of this result was handled, show the Dash */ HideDash, /**< Activation of this result was handled, hide the Dash */ ShowPreview, /**< Preview should be requested for this result */ PerformQuery /**< Perform new search. This state is implied if creating ActivationResponse with CannedQuery object and is invalid otherwise */ }; /** \brief Creates ActivationResponse with given status. \param status The activation status. \throws unity::InvalidArgumentException if status is Status::PerformQuery. To create an ActivationResponse of that type, use the ActivationResponse(CannedQuery const&) constructor. */ ActivationResponse(Status status); /** \brief Creates an ActivationResponse with status Status::PerformQuery and a search query to be executed. \param query The search query to be executed by the client. */ ActivationResponse(CannedQuery const& query); /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ ActivationResponse(ActivationResponse const& other); ActivationResponse(ActivationResponse&& other); ActivationResponse& operator=(ActivationResponse const& other); ActivationResponse& operator=(ActivationResponse&& other); //@} /** \brief Get activation status. \return The activation status. */ ActivationResponse::Status status() const; /** \brief Attach arbitrary data to this response. The attached data is sent back to the scope if the status of this response is Status::ShowPreview. \param data arbitrary value attached to response */ void set_scope_data(Variant const& data); /** \brief Get data attached to this response object. \return The data attached to response. */ Variant scope_data() const; /** \brief A query to be executed if status is Status::PerformQuery. \throws unity::LogicException if the status of this ActivationResponse is anything other than Status::PerformQuery. \return The query to be executed by the client. */ CannedQuery query() const; /// @cond VariantMap serialize() const; ~ActivationResponse(); /// @endcond private: std::unique_ptr p; ActivationResponse(internal::ActivationResponseImpl* pimpl); friend class internal::ActivationResponseImpl; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/CMakeLists.txt0000644000015301777760000000057512320776161026171 0ustar pbusernogroup00000000000000add_subdirectory(internal) add_subdirectory(testing) file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h") # # Generated headers # configure_file(Version.h.in Version.h) set(headers ${headers} ${CMAKE_CURRENT_BINARY_DIR}/Version.h) install(FILES ${headers} DESTINATION ${HDR_INSTALL_DIR}/unity/scopes) set(UNITY_SCOPES_LIB_HDRS ${UNITY_SCOPES_LIB_HDRS} ${headers} PARENT_SCOPE) unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/RegistryProxyFwd.h0000644000015301777760000000201312320776161027102 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_REGISTRYPROXYFWD_H #define UNITY_SCOPES_REGISTRYPROXYFWD_H #include namespace unity { namespace scopes { class Registry; /** \typedef RegistryProxy \brief Convenience type definition. */ typedef std::shared_ptr RegistryProxy; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/ActivationListenerBase.h0000644000015301777760000000427612320776161030206 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_ACTIVATIONLISTENERBASE_H #define UNITY_SCOPES_ACTIVATIONLISTENERBASE_H #include #include namespace unity { namespace scopes { class ActivationResponse; /** \brief Base class to receive a response to a result activation request. */ class ActivationListenerBase: public ListenerBase { public: /// @cond NONCOPYABLE(ActivationListenerBase); UNITY_DEFINES_PTRS(ActivationListenerBase); ~ActivationListenerBase(); /// @endcond /** \brief Called once by the scopes run time with the activation response. The default implementation does nothing. \param response The response to the activation request, returned by a scope from ActivationQueryBase::activate(). */ virtual void activated(ActivationResponse const& response); /** \brief Called once by the scopes run time after receiving an activation response. Default implementation does nothing. Calls to finished() are made by an arbitrary thread. Exceptions thrown from finished() are ignored. \param r Indicates the cause for the call to finished(). \param error_message If r is set to Reason::Error, error_message contains further details. Otherwise, error_message is the empty string. */ virtual void finished(Reason r, std::string const& error_message) override; protected: /// @cond ActivationListenerBase(); /// @endcond }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/ReplyProxyFwd.h0000644000015301777760000000177212320776161026400 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_REPLYPROXYFWD_H #define UNITY_SCOPES_REPLYPROXYFWD_H #include namespace unity { namespace scopes { class Reply; /** \typedef ReplyProxy \brief Convenience type definition. */ typedef std::shared_ptr ReplyProxy; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/FilterBase.h0000644000015301777760000000371612320776161025622 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_FILTERBASE_H #define UNITY_SCOPES_FILTERBASE_H #include #include #include #include #include namespace unity { namespace scopes { namespace internal { class FilterBaseImpl; } /** \brief Base class for all implementations of filters. All implementations of FilterBase define the "look" of a filter in the UI and do not hold any state information. The actual state of a filters is kept by a FilterState object. */ class FilterBase { public: /// @cond UNITY_DEFINES_PTRS(FilterBase); NONCOPYABLE(FilterBase); /// @endcond /** \brief Get the identifier of this filter. \return The filter id. */ std::string id() const; /// @cond VariantMap serialize() const; /// @endcond /** \brief Get the type name of this filter. \return The filter type string. */ std::string filter_type() const; /// @cond virtual ~FilterBase(); protected: FilterBase(internal::FilterBaseImpl *pimpl); std::unique_ptr p; /// @endcond }; /** \brief List of filters */ typedef std::list Filters; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/CategoryRenderer.h0000644000015301777760000000626712320776161027052 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_CATEGORYRENDERER_H #define UNITY_SCOPES_CATEGORYRENDERER_H #include #include #include namespace unity { namespace scopes { namespace internal { class CategoryRendererImpl; } /** \brief A default template for generic use. */ constexpr const char* DEFAULT_RENDERER { R"( { "schema-version":1, "template": { "category-layout":"grid" }, "components": { "title":"title", "art":"art" } } )" }; /** \brief A template suitable for displaying music results. */ constexpr const char* MUSIC_GRID_RENDERER { R"( { "schema-version":1, "template": { "category-layout":"grid" }, "components": { "title":"title", "subtitle":"subtitle", "art":"art" } } )" }; /** \brief A category renderer template in JSON format. */ class CategoryRenderer { public: /// @cond UNITY_DEFINES_PTRS(CategoryRenderer); /// @endcond /** \brief Creates a CategoryRenderer from a JSON string. \param json_text Renderer template in JSON format \throws unity::InvalidArgumentException if json_text cannot be parsed */ explicit CategoryRenderer(std::string const& json_text = DEFAULT_RENDERER); /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ CategoryRenderer(CategoryRenderer const&); CategoryRenderer& operator=(CategoryRenderer const&); CategoryRenderer(CategoryRenderer&&); CategoryRenderer& operator=(CategoryRenderer&&); virtual ~CategoryRenderer(); //@} /** \brief Creates a CategoryRenderer from a text file. \return The CategoryRenderer corresponding to the information in the file. */ // TODO: document exception thrown for invalid string. static CategoryRenderer from_file(std::string const& path); /** \brief Returns complete renderer template definition in JSON format. \return The renderer template (JSON). */ std::string data() const; private: std::unique_ptr p; friend class internal::CategoryRendererImpl; }; /// @cond bool operator==(const CategoryRenderer&, const CategoryRenderer&); /// @endcond } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/PreviewWidget.h0000644000015301777760000001000412320776161026353 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_PREVIEW_WIDGET_H #define UNITY_SCOPES_PREVIEW_WIDGET_H #include #include #include #include #include #include namespace unity { namespace scopes { class VariantMapBuilder; namespace internal { class PreviewWidgetImpl; } class PreviewWidget { public: /// @cond UNITY_DEFINES_PTRS(PreviewWidget); /// @endcond /** \brief Create an empty widget definition with a specific id and type. \param id The unique widget identifier. \param widget_type The type of the widget. */ PreviewWidget(std::string const& id, std::string const &widget_type); /** \brief Create a widget from a JSON definition. \param definition The JSON definition. */ PreviewWidget(std::string const& definition); /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ PreviewWidget(PreviewWidget const& other); PreviewWidget(PreviewWidget&& other); virtual ~PreviewWidget(); PreviewWidget& operator=(PreviewWidget const& other); PreviewWidget& operator=(PreviewWidget&& other); //@} /** \brief Adds an attribute definition and its value. \param key The name of the attribute. \param value The value of the attribute. */ void add_attribute_value(std::string const& key, Variant const& value); /** \brief Adds an attribute definition using a component mapping. If an attribute value is either not known, or the value is already present in a result field, this method creates a mapping between the attribute name and given the field name. If an attribute value is not known, the scope is expected to push the attribute value using unity::scopes::PreviewReply::push(); otherwise, the value is automatically mapped from the result. */ void add_attribute_mapping(std::string const& key, std::string const& field_name); /** \brief Get the identifier of this widget. \return The widget identifier. */ std::string id() const; /** \brief Get type name of this widget. \return The widget type. */ std::string widget_type() const; /** \brief Get the components of this widget. The returned map is a dictionary of (key, field name) pairs, as defined by calls to add_attribute_mapping(). \return The components map. */ std::map attribute_mappings() const; /** \brief Get the attributes of this widget. The returned map is a dictionary of (key, value) pairs, as defined by calls to add_attribute_value(). \return The attribute map. */ VariantMap attribute_values() const; /** \brief Get a JSON representation of this widget. \return The JSON string. */ std::string data() const; /// @cond VariantMap serialize() const; /// @endcond private: std::unique_ptr p; PreviewWidget(internal::PreviewWidgetImpl *impl); friend class internal::PreviewWidgetImpl; }; /*! \typedef PreviewWidgetList \brief List of preview widgets (see unity::scopes::PreviewWidget) */ typedef std::list PreviewWidgetList; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/OptionSelectorFilter.h0000644000015301777760000000745412320776161027724 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_OPTIONSELECTOR_H #define UNITY_SCOPES_OPTIONSELECTOR_H #include #include #include #include #include #include namespace unity { namespace scopes { class FilterState; namespace internal { class OptionSelectorFilterImpl; class FilterBaseImpl; } /** \brief A selection filter that displays a list of choices and allows one or more of them to be selected. */ class OptionSelectorFilter : public FilterBase { public: /// @cond UNITY_DEFINES_PTRS(OptionSelectorFilter); /// @endcond /** \brief Creates an OpionSelectorFilter. \param id A unique identifier for the filter that can be used to identify it later among several filters. \param label A display label for the filter. \param multi_select If true, the filter permits more than option to be selected; otherwise, only a single option can be selected. */ static OptionSelectorFilter::SPtr create(std::string const& id, std::string const& label, bool multi_select = false); /** \brief Get the label of this filter. \return The filter label. */ std::string label() const; /** \brief Check if this filter supports multiple options to be selected. \return True if multi-selection is enabled. */ bool multi_select() const; /** \brief Add a new option to this filter. \return The new option instance. */ FilterOption::SCPtr add_option(std::string const& id, std::string const& label); /** \brief Get all options of this filter, in the order they were added. \return The list of options. */ std::list options() const; /** \brief Get active options from an instance of FilterState for this filter. \return The set of selected filter options. */ std::set active_options(FilterState const& filter_state) const; /** \brief Marks given FilterOption of this filter instance as active (or not active) in a FilterState object. Records the given FilterOption as "selected" in the FilterState. This is meant to be used to modify a FilterState received with a search request before sending it back to the client (UI shell). */ void update_state(FilterState& filter_state, FilterOption::SCPtr option, bool active) const; /** \brief Marks an option of a filter active/inactive in a FilterState object, without having an instance of OptionSelectorFilter. Updates an instance of FilterState, without the need for an OptionSelectorFilter instance. This is meant to be used when creating a canned Query that references another scope. */ static void update_state(FilterState& filter_state, std::string const& filter_id, std::string const& option_id, bool value); private: OptionSelectorFilter(std::string const& id, std::string const& label, bool multi_select = false); OptionSelectorFilter(VariantMap const& var); internal::OptionSelectorFilterImpl* fwd() const; friend class internal::FilterBaseImpl; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/PreviewReply.h0000644000015301777760000000441012320776161026227 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_PREVIEW_REPLY_H #define UNITY_SCOPES_PREVIEW_REPLY_H #include #include #include #include #include namespace unity { namespace scopes { /** \brief Allows the results of a preview to be sent to the preview requester. */ class PreviewReply : public virtual Reply { public: /** \brief Registers a list of column layouts for the current preview. Layouts must be registered before pushing a unity::scopes::PreviewWidgetList, and must be registered only once. \return True if the query is still alive, false if the query failed or was cancelled. \throws unity::LogicException register_layout() is called more than once. */ virtual bool register_layout(ColumnLayoutList const& layouts) = 0; /** \brief Sends widget definitions to the sender of the preview query. This method can be called mutiple times to send widgets in stages. \return True if the query is still alive, false if the query failed or was cancelled. */ virtual bool push(PreviewWidgetList const& widget_list) = 0; /** \brief Sends data for a preview widget attribute. \return True if the query is still alive, false if the query failed or was cancelled. */ virtual bool push(std::string const& key, Variant const& value) = 0; /// @cond virtual ~PreviewReply(); /// @endcond protected: /// @cond PreviewReply(); /// @endcond }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/QueryCtrl.h0000644000015301777760000000313712320776161025531 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_QUERYCTRL_H #define UNITY_SCOPES_QUERYCTRL_H #include #include namespace unity { namespace scopes { /** \brief QueryCtrl allows a query to be cancelled. */ class QueryCtrl : public virtual Object { public: /** \brief Cancels an executing query. Calling cancel() informs the scope to which a query was sent that the query should be cancelled. Calling cancel() on a query that is complete has no effect. cancel() is guaranteed to not block the caller. */ virtual void cancel() = 0; /** \brief Destroys a QueryCtrl. Letting a QueryCtrl go out of scope has no effect on the query, that is, the destructor does _not_ implicitly call cancel(). */ virtual ~QueryCtrl(); protected: /// @cond QueryCtrl(); /// @endcond }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/SearchReplyProxyFwd.h0000644000015301777760000000203612320776161027520 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_SEARCHREPLYPROXYFWD_H #define UNITY_SCOPES_SEARCHREPLYPROXYFWD_H #include namespace unity { namespace scopes { class SearchReply; /** \typedef SearchReplyProxy \brief Convenience type definition. */ typedef std::shared_ptr SearchReplyProxy; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/SearchQueryBase.h0000644000015301777760000001055012320776161026622 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_SEARCHQUERYBASE_H #define UNITY_SCOPES_SEARCHQUERYBASE_H #include #include #include #include #include #include #include #include namespace unity { namespace scopes { class SearchMetadata; namespace internal { class QueryBaseImpl; class QueryObject; } // namespace internal /** \brief Abstract base class to represent a particular query. A scope must return an instance of this class from its implementation of ScopeBase::create_query(). \note The constructor of the instance must complete in a timely manner. Do not perform anything in the constructor that might block. */ class SearchQueryBase : public QueryBase { public: /// @cond NONCOPYABLE(SearchQueryBase); UNITY_DEFINES_PTRS(SearchQueryBase); /// @endcond /** \brief Called by scopes run time to start the query. Your implementation of run() can use the reply proxy to push results for the query. You can push results from within run(), in which case the query implicitly completes when run() returns. Alternatively, run() can store the reply proxy and return immediately. In this case, you can use the stored proxy to push results from another thread. It is safe to call `push()` from multiple threads without synchronization. The query completes either when run() returns, or when the last stored reply proxy goes out of scope (whichever happens last). \param reply The proxy on which to push results for the query. */ virtual void run(SearchReplyProxy const& reply) = 0; /** @name Subquery methods The subsearch() methods are for use by aggregating scopes. When an aggregator passes a query to its child scopes, it should use subsearch() instead of the normal Scope::search() that would be called by a client. subsearch() takes care of automatically forwarding query cancellation to child scopes. This means that there is no need for an aggregating scope to explicitly forward cancellation to child scopes when its QueryBase::cancelled() method is called by the scopes run time. */ //{@ QueryCtrlProxy subsearch(ScopeProxy const& scope, std::string const& query_string, SearchListenerBase::SPtr const& reply); QueryCtrlProxy subsearch(ScopeProxy const& scope, std::string const& query_string, FilterState const& filter_state, SearchListenerBase::SPtr const& reply); QueryCtrlProxy subsearch(ScopeProxy const& scope, std::string const& query_string, std::string const& department_id, FilterState const& filter_state, SearchListenerBase::SPtr const& reply); QueryCtrlProxy subsearch(ScopeProxy const& scope, std::string const& query_string, std::string const& department_id, FilterState const& filter_state, SearchMetadata const& hints, SearchListenerBase::SPtr const& reply); //@} /// @cond virtual ~SearchQueryBase(); /// @endcond protected: /// @cond SearchQueryBase(); /// @endcond }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/Department.h0000644000015301777760000001077712320776161025712 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pawel Stolowski */ #ifndef UNITY_SCOPES_DEPARTMENT_H #define UNITY_SCOPES_DEPARTMENT_H #include #include #include #include #include namespace unity { namespace scopes { class CannedQuery; class Department; /*! \typedef DepartmentList \brief List of departments (see unity::scopes::Department) */ typedef std::list DepartmentList; namespace internal { class DepartmentImpl; } /** \brief A department with optional sub-departments. */ class Department final { public: /// @cond UNITY_DEFINES_PTRS(Department); /// @endcond /** \brief Create a department with the given canned query and name. The identifier of this department instance is that of the `query` instance (\link CannedQuery::department_id()\endlink). \param query The query (and associated parameters, such as filter state) to be executed when the user selects this department. \param label The display name of this department. */ Department(CannedQuery const& query, std::string const& label); /** \brief Create a department with the given department identifier, canned query, and name. The canned query's target department identifier is updated with department_id. This constructor is convenient for creating multiple departments that use the same query and only need a different department identifier. \param department_id The department identifier. \param query The canned query (and associated parameters, such as filter state) to be executed when the user selects this department. \param label The display name of this department. */ Department(std::string const& department_id, CannedQuery const& query, std::string const& label); /** \brief Create a department with the given department identifier, canned query, name, and sub-departments. The canned query's target department identifier is updated with department_id. This constructor is convenient for creating multiple departments that use the same query and only need a different department identifier. \param department_id The department identifier. \param query The canned query (and associated parameters, such as filter state) to be executed when the user selects this department. \param label The display name of this department. \param subdepartments The sub-departments of this department. */ Department(std::string const& department_id, CannedQuery const& query, std::string const& label, DepartmentList const& subdepartments); /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ Department(Department const& other); Department(Department&&); Department& operator=(Department const& other); Department& operator=(Department&&); //@} /// @cond ~Department(); /// @endcond /** \brief Set sub-departments of this department. \param departments The list of sub-departments. */ void set_subdepartments(DepartmentList const& departments); /** \brief Get the identifier of this department. \return The department identifier. */ std::string id() const; /** \brief Get the label of this department. \return The department label. */ std::string label() const; /** \brief Get the canned query associated with this department. \return The canned query for this department. */ CannedQuery query() const; /** \brief Get list of sub-departments of this department. \return The list of sub-departments. */ DepartmentList subdepartments() const; /// @cond VariantMap serialize() const; /// @endcond private: std::unique_ptr p; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/ScopeProxyFwd.h0000644000015301777760000000177212320776161026356 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_SCOPEPROXYFWD_H #define UNITY_SCOPES_SCOPEPROXYFWD_H #include namespace unity { namespace scopes { class Scope; /** \typedef ScopeProxy \brief Convenience type definition. */ typedef std::shared_ptr ScopeProxy; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/scopes/ScopeMetadata.h0000644000015301777760000001025512320776161026310 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef UNITY_SCOPES_SCOPEMETADATA_H #define UNITY_SCOPES_SCOPEMETADATA_H #include namespace unity { namespace scopes { namespace internal { class ScopeMetadataImpl; } // namespace internal namespace testing { class ScopeMetadataBuilder; } // namespace testing /** \brief Holds scope attributes such as name, description, icon etc. The information stored by ScopeMetadata comes from the .ini file for the given scope (for local scopes) or is fetched from the remote server (for scopes running on Smart Scopes Server). Use unity::scopes::Registry to get the metadata for a specific scope or all scopes. */ class ScopeMetadata final { public: /// @cond UNITY_DEFINES_PTRS(ScopeMetadata); ~ScopeMetadata(); /// @endcond /**@name Copy and assignment Copy and assignment operators (move and non-move versions) have the usual value semantics. */ //{@ ScopeMetadata(ScopeMetadata const& other); ScopeMetadata(ScopeMetadata&&); ScopeMetadata& operator=(ScopeMetadata const& other); ScopeMetadata& operator=(ScopeMetadata&&); //@} /** \brief Get the scope identifier. \return The ID of the scope. */ std::string scope_id() const; /** \brief Get the proxy object for this scope. \return The scope proxy. */ ScopeProxy proxy() const; /** \brief Get the display name for this scope. \return The scope display name. */ std::string display_name() const; // localized /** \brief Get the description for this scope. \return The scope description. */ std::string description() const; // localized /** \brief Get the author for this scope. \return The scope author. */ std::string author() const; /** \brief Get the art for this scope. \return The scope art. */ std::string art() const; // optional /** \brief Get the icon for this scope. \return The scope icon. */ std::string icon() const; // optional /** \brief Get the search hint for this scope. \return The search hint. */ std::string search_hint() const; // localized, optional /** \brief Get the hot key for this scope. \return The hot key. */ std::string hot_key() const; // localized, optional /** \brief Check if this scope should be hidden in the Dash. \return True if this scope is invisible. */ bool invisible() const; // optional (default = false) /** \brief Get optional display attributes. Appearance attributes define customized look of the scope in Scopes Scope. \return Map of attributes (may be empty) */ VariantMap appearance_attributes() const; /** \brief Get directory where scope config files and .so file lives. Note that the directory is not set for remote scopes; in such case this method throws unity::scopes::NotFoundException. \throws unity::scopes::NotFoundException if directory is not set \return path string */ std::string scope_directory() const; /** \brief Return a dictionary of all metadata attributes. \return Dictionary of all metadata attributes. */ VariantMap serialize() const; private: ScopeMetadata(std::unique_ptr); // Instantiable only by ScopeMetadataImpl std::unique_ptr p; friend class internal::ScopeMetadataImpl; }; } // namespace scopes } // namespace unity #endif unity-scopes-api-0.4.2+14.04.20140408/include/unity/CMakeLists.txt0000644000015301777760000000023412320776161024665 0ustar pbusernogroup00000000000000add_subdirectory(scopes) file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h") set(UNITY_SCOPES_LIB_HDRS ${UNITY_SCOPES_LIB_HDRS} ${headers} PARENT_SCOPE) unity-scopes-api-0.4.2+14.04.20140408/include/CMakeLists.txt0000644000015301777760000000077612320776161023530 0ustar pbusernogroup00000000000000add_subdirectory(unity) set(UNITY_SCOPES_LIB_HDRS ${UNITY_SCOPES_LIB_HDRS} ${headers} PARENT_SCOPE) add_custom_command(OUTPUT unity-scopes.h COMMAND ${CMAKE_SOURCE_DIR}/tools/create_globalheader.py ${CMAKE_CURRENT_BINARY_DIR}/unity-scopes.h ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${UNITY_SCOPES_LIB_HDRS}) add_custom_target(globalheader ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/unity-scopes.h) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/unity-scopes.h DESTINATION ${HDR_INSTALL_DIR}) unity-scopes-api-0.4.2+14.04.20140408/scoperegistry/0000755000015301777760000000000012320776463022242 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/scoperegistry/FindFiles.cpp0000644000015301777760000000753412320776161024615 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "FindFiles.h" #include #include #include #include #include using namespace std; using namespace unity; namespace scoperegistry { namespace { bool has_suffix(string const& s, string const& suffix) { auto s_len = s.length(); auto suffix_len = suffix.length(); if (s_len >= suffix_len) { return s.compare(s_len - suffix_len, suffix_len, suffix) == 0; } return false; } // Return all paths underneath the given dir that are of the given type // or are a symbolic link. enum EntryType { File, Directory }; vector find_entries(string const& install_dir, EntryType type) { DIR* d = opendir(install_dir.c_str()); if (d == NULL) { throw ResourceException("cannot open scope installation directory \"" + install_dir + "\": " + strerror(errno)); } util::ResourcePtr dir_ptr(d, closedir); // Clean up automatically vector entries; struct dirent* entry; while ((entry = readdir(dir_ptr.get())) != NULL) { string name = entry->d_name; if (name == "." || name == "..") { continue; // Ignore current and parent dir } struct stat st; int rc = lstat((install_dir + "/" + name).c_str(), &st); if (rc == -1) { continue; // We ignore errors, such as a file having been unlinked in the mean time. } if (type == File && !S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) { continue; // Not a regular file or symbolic link } else if (type == Directory && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode)) { continue; // Not a directory or symbolic link } entries.emplace_back(install_dir + "/" + name); } return entries; } } // namespace // Return all files of the form dir//.ini that are regular files or // symbolic links and have the specified suffix. // The empty suffix is legal and causes all regular files and symlinks to be returned. vector find_scope_config_files(string const& install_dir, string const& suffix) { vector files; auto subdirs = find_entries(install_dir, Directory); for (auto subdir : subdirs) { string scope_id = basename(const_cast(subdir.c_str())); // basename() modifies its argument auto candidates = find_entries(subdir, File); for (auto c : candidates) { string config_name = basename(const_cast(c.c_str())); // basename() modifies its argument if (config_name == scope_id + suffix) { files.emplace_back(c); } } } return files; } // Return all files with the given suffix in dir. vector find_files(string const& dir, string const& suffix) { vector files; auto candidates = find_entries(dir, File); for (auto c : candidates) { if (has_suffix(c, suffix)) { files.emplace_back(c); } } return files; } } // namespace scoperegistry unity-scopes-api-0.4.2+14.04.20140408/scoperegistry/scoperegistry.cpp0000644000015301777760000003760512320776161025656 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #include "FindFiles.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace scoperegistry; using namespace std; using namespace unity; using namespace unity::scopes; using namespace unity::scopes::internal; using namespace unity::util; char const* prog_name; namespace { void error(string const& msg) { assert(!msg.empty()); cerr << prog_name << ": " << msg << endl; } string strip_suffix(string const& s, string const& suffix) { auto s_len = s.length(); auto suffix_len = suffix.length(); if (s_len >= suffix_len) { if (s.compare(s_len - suffix_len, suffix_len, suffix) == 0) { return string(s, 0, s_len - suffix_len); } } return s; } // if path is an absolute path, just return it. otherwise, append it to scopedir. string relative_scope_path_to_abs_path(string const& path, string const& scopedir) { if (path.size() > 0 && path[0] != '/') { return scopedir + "/" + path; } return path; } // Return a map of pairs for all scopes (Canonical and OEM scopes). // If a Canonical scope is overrideable and the OEM has configured a scope with the // same id, the OEM scope overrides the Canonical one. map find_local_scopes(string const& scope_installdir, string const& oem_installdir) { // Look in scope_installdir for scope configuration files. // Scopes that do not permit themselves to be overridden are collected in fixed_scopes. // Scopes that can be overridden are collected in overrideable_scopes. // Each set contains file names (including the ".ini" suffix). map fixed_scopes; // Scopes that the OEM cannot override map overrideable_scopes; // Scopes that the OEM can override auto config_files = find_scope_config_files(scope_installdir, ".ini"); for (auto&& path : config_files) { string file_name = basename(const_cast(string(path).c_str())); // basename() modifies its argument string scope_id = strip_suffix(file_name, ".ini"); try { ScopeConfig config(path); if (config.overrideable()) { overrideable_scopes[scope_id] = path; } else { fixed_scopes[scope_id] = path; } } catch (unity::Exception const& e) { error("ignoring scope \"" + scope_id + "\": configuration error:\n" + e.what()); } } if (!oem_installdir.empty()) { try { auto oem_paths = find_scope_config_files(oem_installdir, ".ini"); for (auto&& path : oem_paths) { string file_name = basename(const_cast(string(path).c_str())); // basename() modifies its argument string scope_id = strip_suffix(file_name, ".ini"); if (fixed_scopes.find(scope_id) == fixed_scopes.end()) { overrideable_scopes[scope_id] = path; // Replaces scope if it was present already } else { error("ignoring non-overrideable scope config \"" + file_name + "\" in OEM directory " + oem_installdir); } } } catch (ResourceException const& e) { error(e.what()); error("could not open OEM installation directory, ignoring OEM scopes"); } } // Combine fixed_scopes and overrideable_scopes now. fixed_scopes.insert(overrideable_scopes.begin(), overrideable_scopes.end()); return fixed_scopes; } // For each scope, open the config file for the scope, create the metadata info from the config, // and add an entry to the RegistryObject. void add_local_scopes(RegistryObject::SPtr const& registry, map const& all_scopes, MiddlewareBase::SPtr const& mw, string const& scoperunner_path, string const& config_file) { for (auto&& pair : all_scopes) { try { unique_ptr mi(new ScopeMetadataImpl(mw.get())); ScopeConfig sc(pair.second); // dirname modifies its argument, so we need a copy of scope ini path. std::vector scope_ini(pair.second.c_str(), pair.second.c_str() + pair.second.size() + 1); const std::string scope_dir(dirname(&scope_ini[0])); mi->set_scope_id(pair.first); mi->set_display_name(sc.display_name()); mi->set_description(sc.description()); mi->set_author(sc.author()); mi->set_invisible(sc.invisible()); mi->set_appearance_attributes(sc.appearance_attributes()); mi->set_scope_directory(scope_dir); try { mi->set_art(relative_scope_path_to_abs_path(sc.art(), scope_dir)); } catch (NotFoundException const&) { } try { mi->set_icon(relative_scope_path_to_abs_path(sc.icon(), scope_dir)); } catch (NotFoundException const&) { } try { mi->set_search_hint(sc.search_hint()); } catch (NotFoundException const&) { } try { mi->set_hot_key(sc.hot_key()); } catch (NotFoundException const&) { } ScopeProxy proxy = ScopeImpl::create(mw->create_scope_proxy(pair.first), mw->runtime(), pair.first); mi->set_proxy(proxy); auto meta = ScopeMetadataImpl::create(move(mi)); RegistryObject::ScopeExecData exec_data; exec_data.scope_id = pair.first; // get custom scope runner executable, if not set use default scoperunner exec_data.scoperunner_path = scoperunner_path; try { auto custom_exec = sc.scope_runner(); if (custom_exec.empty()) { throw unity::InvalidArgumentException("Invalid scope runner executable for scope: " + pair.first); } exec_data.scoperunner_path = relative_scope_path_to_abs_path(custom_exec, scope_dir); } catch (NotFoundException const&) { } exec_data.runtime_config = config_file; exec_data.scope_config = pair.second; registry->add_local_scope(pair.first, move(meta), exec_data); } catch (unity::Exception const& e) { error("ignoring scope \"" + pair.first + "\": cannot create metadata: " + e.what()); } } } // Overwrite any remote scopes loaded previously with the current ones. void load_remote_scopes(RegistryObject::SPtr const& registry, MiddlewareBase::SPtr const& mw, string const& ss_reg_id, string const& ss_reg_endpoint) { auto ss_reg = mw->create_registry_proxy(ss_reg_id, ss_reg_endpoint); registry->set_remote_registry(ss_reg); } } // namespace // Usage: scoperegistry [runtime.ini] [scope.ini]... // // If no runtime config file is specified, the default location (/usr/share/unity-scopes-api/Runtime.ini) // is assumed. // If additional scope configuration files are specified, the corresponding scopes will be added // to the registry (overriding any scopes that are found via config files reached via Runtime.ini). void usage(ostream& s = cerr) { s << "usage: " << prog_name << " [runtime.ini] [scope.ini]..." << endl; } int main(int argc, char* argv[]) { prog_name = basename(argv[0]); if (argc > 1 && (string("-h") == argv[1] || string("--help") == argv[1])) { usage(cout); exit(0); } char const* const config_file = argc > 1 ? argv[1] : ""; int exit_status = 1; try { // We shutdown the runtime whenever these signals happen. auto termination_trap = core::posix::trap_signals_for_all_subsequent_threads( { core::posix::Signal::sig_int, core::posix::Signal::sig_hup, core::posix::Signal::sig_term }); // And we maintain our list of processes with the help of sig_chld. auto child_trap = core::posix::trap_signals_for_all_subsequent_threads( { core::posix::Signal::sig_chld }); // The death observer is required to make sure that we reap all child processes // whenever multiple sigchld's are compressed together. auto death_observer = core::posix::ChildProcess::DeathObserver::create_once_with_signal_trap( child_trap); // Starting up both traps. std::thread termination_trap_worker([termination_trap]() { termination_trap->run(); }); std::thread child_trap_worker([child_trap]() { child_trap->run(); }); // And finally creating our runtime. RuntimeConfig rt_config(config_file); RuntimeImpl::UPtr runtime = RuntimeImpl::create(rt_config.registry_identity(), config_file); string identity = runtime->registry_identity(); // Collect the registry config data. string mw_kind; string mw_endpoint; string mw_configfile; string scope_installdir; string oem_installdir; string scoperunner_path; string ss_reg_id; string ss_reg_endpoint; { RegistryConfig c(identity, runtime->registry_configfile()); mw_kind = c.mw_kind(); mw_endpoint = c.endpoint(); mw_configfile = c.mw_configfile(); scope_installdir = c.scope_installdir(); oem_installdir = c.oem_installdir(); scoperunner_path = c.scoperunner_path(); ss_reg_id = c.ss_registry_identity(); ss_reg_endpoint = c.ss_registry_endpoint(); } // Release memory for config parser MiddlewareBase::SPtr middleware = runtime->factory()->find(identity, mw_kind); // Inform the signal thread that it should shutdown the middleware // if we get a termination signal. termination_trap->signal_raised().connect([middleware](core::posix::Signal signal) { switch(signal) { case core::posix::Signal::sig_int: case core::posix::Signal::sig_hup: case core::posix::Signal::sig_term: middleware->stop(); break; default: break; } }); // The registry object stores the local and remote scopes RegistryObject::SPtr registry(new RegistryObject(*death_observer)); // Add the metadata for each scope to the lookup table. // We do this before starting any of the scopes, so aggregating scopes don't get a lookup failure if // they look for another scope in the registry. auto local_scopes = find_local_scopes(scope_installdir, oem_installdir); // Before we add the local scopes, we check whether any scopes were explicitly specified // on the command line. If so, scopes on the command line override scopes in // configuration files. for (auto i = 2; i < argc; ++i) { string file_name = basename(const_cast(string(argv[i]).c_str())); // basename() modifies its argument string scope_id = strip_suffix(file_name, ".ini"); local_scopes[scope_id] = argv[i]; // operator[] overwrites pre-existing entries } add_local_scopes(registry, local_scopes, middleware, scoperunner_path, runtime->configfile()); if (ss_reg_id.empty() || ss_reg_endpoint.empty()) { error("no remote registry configured, only local scopes will be available"); } else { load_remote_scopes(registry, middleware, ss_reg_id, ss_reg_endpoint); } // Now that the registry table is populated, we can add the registry to the middleware, so // it starts processing incoming requests. middleware->add_registry_object(runtime->registry_identity(), registry); // We also add the registry's state receiver to the middleware so that scopes can inform // the registry of state changes. middleware->add_state_receiver_object("StateReceiver", registry->state_receiver()); // FIXME, HACK HACK HACK HACK // The middleware should spawn scope processes with lookup() on demand. // Because it currently does not have the plumbing, we start every scope immediately. // When the plumbing appears, remove this. for (auto&& pair : local_scopes) { try { registry->locate(pair.first); } catch (NotFoundException const&) { // We ignore this. If the scope config couldn't be found, add_local_scopes() // has already printed an error message. } catch (std::exception const& e) { error("could not start scope " + pair.first + ": " + e.what()); } } // Drop our shared_ptr to the RegistryObject. This means that the registry object // is kept alive only via the shared_ptr held by the middleware. If the middleware // shuts down, it clears out the active servant map, which destroys the registry // object. The registry object kills all its child processes as part of its clean-up. registry = nullptr; // Wait until we are done, which happens if we receive a termination signal. middleware->wait_for_shutdown(); // Stop termination_trap termination_trap->stop(); if (termination_trap_worker.joinable()) termination_trap_worker.join(); // Please note that the child_trap must only be stopped once the // termination_trap thread has been joined. We otherwise will encounter // a race between the middleware shutting down and not receiving sigchld anymore. child_trap->stop(); if (child_trap_worker.joinable()) child_trap_worker.join(); exit_status = 0; } catch (std::exception const& e) { error(e.what()); } catch (string const& e) { error("fatal error: " + e); } catch (char const* e) { error(string("fatal error: ") + e); } catch (...) { error("terminated due to unknown exception"); } return exit_status; } unity-scopes-api-0.4.2+14.04.20140408/scoperegistry/CMakeLists.txt0000644000015301777760000000051012320776161024771 0ustar pbusernogroup00000000000000set(SRC FindFiles.cpp scoperegistry.cpp ScopeSet.cpp ) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_executable(scoperegistry ${SRC}) target_link_libraries(scoperegistry ${UNITY_SCOPES_LIB} ${OTHER_LIBS}) install(TARGETS scoperegistry RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/scoperegistry) unity-scopes-api-0.4.2+14.04.20140408/scoperegistry/ScopeSet.cpp0000644000015301777760000000666212320776161024500 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Jussi Pakkanen */ #include"FindFiles.h" #include"ScopeSet.h" #include #include #include #include #include #include #include #include using namespace std; using namespace unity::scopes; using namespace unity::scopes::internal; namespace scoperegistry { static string strip_suffix(string const& s, string const& suffix) { auto s_len = s.length(); auto suffix_len = suffix.length(); if (s_len >= suffix_len) { if (s.compare(s_len - suffix_len, suffix_len, suffix) == 0) { return string(s, 0, s_len - suffix_len); } } return s; } struct ScopeSetPrivate { std::set overridable_scopes; std::map> scopes; }; ScopeSet::ScopeSet(const RegistryConfig& c) : p(new ScopeSetPrivate()) { string canonical_dir = c.scope_installdir(); string oem_dir = c.oem_installdir(); auto canonical_files = find_scope_config_files(canonical_dir, ".ini"); auto oem_files = find_scope_config_files(oem_dir, ".ini"); for (const auto &path : canonical_files) { unique_ptr sc(new ScopeConfig(path)); // basename() modifies its argument string file_name = basename(const_cast(string(path).c_str())); string scope_id = strip_suffix(file_name, ".ini"); if (sc->overrideable()) { p->overridable_scopes.insert(path); } p->scopes[scope_id] = move(sc); } for (const auto &path : oem_files) { unique_ptr sc(new ScopeConfig(path)); string file_name = basename(const_cast(string(path).c_str())); string scope_id = strip_suffix(file_name, ".ini"); if (p->scopes.find(scope_id) != p->scopes.end()) { if (p->overridable_scopes.find(scope_id) != p->overridable_scopes.end()) { p->scopes[scope_id] = move(sc); } else { // print error about trying to override a non-overridable scope. } } else { p->scopes[scope_id] = move(sc); } } // Add click scope parsing here. } ScopeSet::~ScopeSet() { delete p; } std::vector ScopeSet::list() const { vector list; for (auto &i : p->scopes) { list.push_back(i.first); } return list; } const unity::scopes::internal::ScopeConfig& ScopeSet::get(const std::string& name) { if (p->scopes.find(name) == p->scopes.end()) { throw NotFoundException("Scope does not exist", name); } return *p->scopes[name].get(); } } unity-scopes-api-0.4.2+14.04.20140408/scoperegistry/ScopeSet.h0000644000015301777760000000250312320776161024133 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Jussi Pakkanen */ #ifndef SCOPEREGISTRY_SCOPESET_H_ #define SCOPEREGISTRY_SCOPESET_H_ #include #include #include #include namespace scoperegistry { struct ScopeSetPrivate; class ScopeSet final { public: ScopeSet(const ::unity::scopes::internal::RegistryConfig& c); ~ScopeSet(); ScopeSet(const ScopeSet&) = delete; ScopeSet& operator=(const ScopeSet&) = delete; std::vector list() const; const unity::scopes::internal::ScopeConfig& get(const std::string& name); private: ScopeSetPrivate* p; }; } #endif unity-scopes-api-0.4.2+14.04.20140408/scoperegistry/FindFiles.h0000644000015301777760000000276212320776161024260 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Michi Henning */ #ifndef SCOPEREGISTRY_FINDFILES_H #define SCOPEREGISTRY_FINDFILES_H #include #include namespace scoperegistry { // Return a vector of file names underneath a scope root install dir that have the given suffix. // Files are searched for exactly "one level down", that is, if we have a directory structure. // // canonical/scopeA/myconfig.ini // canonical/someScope/someScope.ini // // we get those two .ini files, but no .ini files in canonical or underneath // further-nested directories. std::vector find_scope_config_files(std::string const& install_dir, std::string const& suffix); // Return a vector of file names in dir with the given suffix. std::vector find_files(std::string const& dir, std::string const& suffix); } // namespace scoperegistry #endif unity-scopes-api-0.4.2+14.04.20140408/smartscopesproxy/0000755000015301777760000000000012320776463023005 5ustar pbusernogroup00000000000000unity-scopes-api-0.4.2+14.04.20140408/smartscopesproxy/smartscopesproxy.cpp0000644000015301777760000001145512320776161027157 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Marcus Tomlinson */ #include #include #include #include #include #include #include #include #include #include #include using namespace unity::scopes; using namespace unity::scopes::internal; using namespace unity::scopes::internal::smartscopes; static void error(std::string const& msg) { assert(!msg.empty()); std::cerr << "smartscopesproxy: " << msg << std::endl; } int main(int argc, char* argv[]) { if (argc > 1 && (std::string("-h") == argv[1] || std::string("--help") == argv[1])) { char const* prog_name = basename(argv[0]); std::cout << "usage: " << prog_name << " [sss_url] [runtime.ini]" << std::endl; return 0; } int exit_status = 1; bool sig_upstart = false; std::string server_url_env; std::string config_file; // check for "upstart" as first arg if (argc > 1 && std::string(argv[1]) == "upstart") { sig_upstart = true; } else { // argv[1]: server_url_env if (argc > 1) { server_url_env = "SMART_SCOPES_SERVER=" + std::string(argv[1]); ::putenv(const_cast(server_url_env.c_str())); } // argv[2]: config_file config_file = argc > 2 ? argv[2] : ""; } try { auto trap = core::posix::trap_signals_for_all_subsequent_threads( { core::posix::Signal::sig_int, core::posix::Signal::sig_hup, core::posix::Signal::sig_term }); ///! TODO: get these from config std::string ss_reg_id = "SSRegistry"; std::string ss_scope_id = "SmartScope"; uint const http_reply_timeout = 20000; uint const ss_reg_refresh_rate = 60 * 60 * 24; // 24 hour refresh (in seconds) // Instantiate SS registry and scopes runtimes RuntimeImpl::UPtr reg_rt = RuntimeImpl::create(ss_reg_id, DFLT_SS_RUNTIME_INI); RuntimeImpl::UPtr scope_rt = RuntimeImpl::create(ss_scope_id, config_file); // Get registry config RegistryConfig reg_conf(ss_reg_id, reg_rt->registry_configfile()); std::string mw_kind = reg_conf.mw_kind(); std::string mw_configfile = reg_conf.mw_configfile(); // Get middleware handles from runtimes MiddlewareBase::SPtr reg_mw = reg_rt->factory()->find(ss_reg_id, mw_kind); MiddlewareBase::SPtr scope_mw = scope_rt->factory()->create(ss_scope_id, mw_kind, mw_configfile); trap->signal_raised().connect([reg_mw, scope_mw](core::posix::Signal) { scope_mw->stop(); reg_mw->stop(); }); std::thread trap_worker([trap]() { trap->run(); }); // Instantiate a SS registry object SSRegistryObject::SPtr reg(new SSRegistryObject(reg_mw, scope_mw->get_scope_endpoint(), http_reply_timeout, ss_reg_refresh_rate)); // Instantiate a SS scope object SSScopeObject::UPtr scope(new SSScopeObject(ss_scope_id, scope_mw, reg)); // Add objects to the middlewares reg_mw->add_registry_object(reg_rt->registry_identity(), reg); scope_mw->add_dflt_scope_object(std::move(scope)); if (sig_upstart) { // signal to upstart that we are ready kill(getpid(), SIGSTOP); } // Wait until shutdown scope_mw->wait_for_shutdown(); reg_mw->wait_for_shutdown(); trap->stop(); if (trap_worker.joinable()) trap_worker.join(); exit_status = 0; } catch (std::exception const& e) { error(e.what()); } catch (std::string const& e) { error("fatal error: " + e); } catch (char const* e) { error(std::string("fatal error: ") + e); } catch (...) { error("terminated due to unknown exception"); } return exit_status; } unity-scopes-api-0.4.2+14.04.20140408/smartscopesproxy/CMakeLists.txt0000644000015301777760000000036112320776161025540 0ustar pbusernogroup00000000000000set(SRC smartscopesproxy.cpp) add_executable(smartscopesproxy ${SRC}) target_link_libraries(smartscopesproxy ${UNITY_SCOPES_LIB} ${OTHER_LIBS}) install(TARGETS smartscopesproxy RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/smartscopesproxy) unity-scopes-api-0.4.2+14.04.20140408/README0000644000015301777760000004432112320776161020217 0ustar pbusernogroup00000000000000# # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 as # published by the Free Software Foundation. # # 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Authored by: Michi Henning # This is an explanation of the layout of the source tree, and the conventions used by this library. Please read this before making changes to the source! For instructions on how to build the code, see the INSTALL file. Build targets ------------- The build produces the Unity scopes library (libunity-scopes). TODO: Flesh this out Source tree layout ------------------ At the top level, we have src, include, and test, which contain what they suggest. Underneath src and include, we have subdirectories that correspond to namespaces, that is, if we have src/internal, that automatically means that there is a namespace unity::scopes::internal. This one-to-one correspondence makes it easier to work out what is defined where. Namespaces ---------- The library maintains a compilation firewall, strictly separating external API and internal implementation. This reduces the chance of breaking the API, and it makes it clear what parts of the API are for public consumption. Anything that is not public is implemented in a namespace called "internal". TODO: More explanation of the namespaces used and for what. Header file conventions ----------------------- All header files are underneath include/scopes. Source code always includes headers using the full pathname, for example: #include All source code uses angle brackets (<...>) for #include directives. Double quotes ("...") are never used because the lookup semantics can be surprising if there are any headers with the same name in the tree. (Not that this should happen, but it's better to be safe. If there are no duplicate names, inclusion with angle brackets behaves the same way as inclusion with double quotes.) All headers that are for public consumption appear in include/scopes/* (provided the path does not include "internal"). Public header directories contain a private header directory called "internal". This directory contains all the headers that are private and specific to the implementation. No public header file is allowed to include any header from one of the internal directories. (Doing so would break the compilation firewall and also prevent API clients from compiling because the internal headers are not installed when unity is deployed. (This is enforced by the tests.) All header files, whether public or internal, compile stand-alone, that is, no header relies on another header being included first in order to compile. (This is enforced by the tests.) Compilation firewall -------------------- Public classes use the pimpl (pointer-to-implemtation) idiom, also known as "envelope-letter idiom", "Cheshire Cat", or "Compiler firewall idiom". This makes it less likely that an update to the code will break the ABI. Many classes that are part of the public API contain only one private data member, namely the pimpl. No other data members (public, protected, or private) are permitted. For public classes with shallow-copy semantics (classes that are immutable after instantiation), the code uses std::shared_ptr as the pimpl type because std::shared_ptr provides the correct semantics. (See unity::Exception and its derived classes for an example.) For classes that are non-copyable, std::unique_ptr is used as the pimpl type. If classes form derivation hierarchies, by convention, the pimpl is a private data member of the root base class. Derived classes can access the pimpl by calling the protected pimpl() method of the root base class. This avoids redundantly storing a separated pimpl to the derived type in each derived class. Instead, polymorphic dispatch to virtual methods in the derived classes is achieved by using a dynamic_cast to the derived type to forward an invocation to the corresponding virtual method in the derived implementation class. Error handling -------------- No error codes, period. All errors are reported via exceptions. All exceptions thrown by the library are derived from unity::Exception (which is abstract). unity::Exception provides a to_string() method. This method returns the exception history and prints all exceptions that were raised along a particular throw path, even if a low-level exception was caught and translated into a higher level exception. This works for exceptions derived from std::nested_exception. (The exception chaining ends when it encounters an exception that does not derive from std::nested_exception.) If API clients intercept unity exceptions and rethrow their own exceptions, it is recommended that API clients derive their exceptions from unity::Exception or, alternatively, derive them from std::nested_exception and implement a similar to_string() operation that, if it encounters a unity::Exception while following a chain, calls the to_string() method on unity::Exception. That way, the entire exception history will be returned from to_string(). Functions that throw exceptions should, if at all possible, provide the strong exception guarantee. Otherwise, they must provide the basic (weak) exception guarantee. If it is impossible to maintain even the basic guarantee, the code must call abort() instead of throwing an exception. Resource management ------------------- The code uses the RAII (resource acquisition is initialization) idiom extensively. If you find yourself writing free, delete, Xfree, XCloseResource, or any other kind of clean-up function, your code has a problem. Instead of explictly cleaning up in destructors, *immediately* assign the resource to a unique_ptr or shared_ptr with a custom deleter. This guarantees that the resource will be released without having to remember anything. In particular, it guarantees that the resource will be released even if allocated in a constructor near the beginning and something called by the constructor throws before the constructor completes. For resources that cannot be managed by unique_ptr or shared_ptr (because the allocator does not return a pointer or returns a pointer to an opaque type), use the RAII helper class in ResourcePtr.h. It does much the same thing as unique_ptr, but is more permissive in the types it can manage. Note the naming convention established by util/DefinesPtrs.h. All classes that return or accept smart pointers derive from DefinesPtrs, which is a code injection template that creates typedefs for Ptr and UPtr (shared_ptr and unique_ptr, respectively) as well as CPtr and UCPtr (shared_ptr and unique_ptr to constant instances). Ideally, classes are fully initialized by their constructor so it is impossible for a class to exist but not being in a usable state. For some classes, it is unavoidable to provide a default constructor (for example, if we want to put instances into an array). It is also sometimes impossible to fully construct an instance immediately, for example if the instance is member variable and the necessary initialization data is not available until some time afterwards. In this case, the default constructor must initialize the class to a fail-safe state, that is, it must behave sanely in the face of methods being invoked on it. This means that calling a method on a default-constructed instance should throw a logic exception to indicate to the caller that the instance is not fully initialized yet. Note that turning method calls on not-yet-initialized instances into no-ops is usually a bad idea: the caller thinks that everything worked fine when, in fact, it did nothing. If such no-op methods do something sensible (that is, they can do their job even on an incompletely initialized instance), this begs the question of why the instance wasn't default-constructible in the first place... To sum it up: try to enforce complete initialization from the constructor wherever possible. If it is impossible to do that, follow the principle of least surprise for the caller if a method is called on a not-yet-initialized instance. Code structure -------------------------------- The code is arranged in three layers: - scopes (top level) This level contains everything that is part of the public API. No source file in this level includes any header from the internal namespace (or below the internal namespace). - internal This level contains the implementation logic for the scopes run time, independent of the particular middleware. - zmq_middleware This level contains the middleware-specific parts of the code. No internal header file (except for MiddlewareFactory) includes any header in zmq_middleware. Client invocation classes ------------------------- The call chain for an outgoing invocation is like this (using Scope as an example): ScopeProxy -> Scope -> ScopeImpl -> MWScopeProxy -> ZmqScope Clients invoke remote operations via a proxy. The *Proxy types (such as ScopeProxy) are shared_ptrs to the corresponding proxy class (such as Proxy). Each proxy class provides a method that corresponds to a remote operation in the server. The proxy class stores a pimpl, which bridges the gap into the internal namespace. In the internal namespace, the actual proxy implementation is called *Impl, for example, ScopeImpl. The *Impl classes contain any additional methods and data members that might be needed by the run time during remote method invocation. In effect, they provide an interception point where we can do things behind the scenes during an invocation (such as sending metrics and transparently forwarding query cancellation.) Each *Impl class provides access to the actual middleware-specific proxy as a shared_ptr to a base class. The accessor for this proxy is called fwd() and returns an instance of MW*Proxy, for example, MWScopeProxy. This actually is a shared_ptr. In other words, the MWScopeProxy pointer does for our implementation what ScopeProxy does for our API clients: it shields our implementation from the specifics of the middleware that is in use. MWScope is an abstract base interface. It contains a pure virtual method for each remote operation. The signature of each method is the same as the signature of the corresponding method on the public proxy. The concrete implementation of the MWScope interface is provided by ZmqScope.h. ZmqScope.h provides the client-side implementation of each remote operation. The job of the implementation is to convert the middleware-independent input parameters into their middleware-specific counterparts, invoke the operation, wait for any return values, and convert the middleware-specific return values into their middleware-independent counterparts. For Zmq, the proxy implementation also drives the capnproto marshaling and unmarshaling. Server dispatch classes ----------------------- The call chain for an incoming invocation is like this (using Scope as an example): ObjectAdapter -> ScopeI -> ScopeObject On the server side, when a method invocation arrives over the wire, it ends up in an instance of ObjectAdapter. Each network endpoint has one adapter. The job of the adapter is to listen for incoming requests, map each request to the correct C++ target object, and invoke a callback that corresponds to the operation on that target object. The endpoint to which a request is sent by a client implicitly identifies which adapter handles the incoming request. Each request that arrives over the wire carries an object identity and an operation name. The adapter unmarshals this information and then looks for a C++ object (called a "servant") that was registered for that identity with the middleware to receive requests of a particular type. Each adapter can have multiple C++ servants, each of which handles requests for a particular identity. The different servants can implement objects of different types. Each adapter contains a table that maps the incoming identity to the corresponding servant. The key to the table is the identity, and the lookup value is a shared_ptr to the servant. The table is populated by the add_*_object() methods on MiddlewareBase. If the adapter cannot find a servant with an identity that matches the request, it marshals an exception back to the client. Otherwise, it dispatches the request. The concrete servants are of type *I, for example, ScopeI. (The "I" is short for Implementation.) The ScopeI class is the middleware-specific server-side equivalent of the ZmqScope client-side proxy. All servants derive from a base ServantBase. ServantBase provides a generic dispatch_() method. The job of dispatch_() is to check whether the servant can actually handle an incoming operation. For example, if the incoming operation name is "foo", but the servant does not provide a method called "foo", it sends an OperationNotExistException back to the client. Otherwise, dispatch_() calls the corresponding method on the servant and waits for the method to complete. The invocation to the servant is made in a try-catch block; if the servant throws an exception, dispatch_() takes care of returning an exception to the client. The concrete servant method called by dispatch_ (such as ScopeI::create_query) now unmarshals any in-parameters, translates them to the middleware-independent equivalents, forwards the invocation to the middleware-independent servant, and translates and marshals any return values or exceptions. Each servant class stores a pointer to a delegate. The delegate implementation lives in the internal namespace and does not know by which middleware it is called. The delegates are middleware-independent servants, called *Object, for example, ScopeObject. Each *Object class implements a method for the middleware-specific servant to call, with parameters that correspond to the operation that was invoked by the client. In other words, the *Object classes implement the server-side behavior of the operations that clients call, and the servant classes forward an incoming request to their corresponding *Object instance. This allows the middleware-independent part of run time to implement operations without having to include and middleware-specific header files. If you think of ScopeProxy as a pointer that can point at an object in a remote address space, then ScopeObject is the corresponding server-side target that implements the methods that the client can invoke on the proxy. Capnproto definitions --------------------- The capnproto definitions live in zmq_middleware/capnproto and define what is marshaled over the wire. (As far as zmq is concerned, things that go over the wire are just opaque messages, that is, blobs of bytes. Zmq knows about message boundaries, but knows nothing about what's inside them.) Message.capnp defines the message headers. A request contains the request mode (oneway or twoway), the identity of the servant, the operation name, followed by the in-parameters as a blob (a capnproto Object). A response (sent only for twoway invocations) contains a status that indicates success, run-time exception, or user exception, plus any return values as a blob. Success means the invocation was successful, and the return values are inside the payload blob. If the invocation failed, it can be for a variety of reasons, some unexpected, some not. Unexpected reasons are things such as general failures during dispatch, failure to locate the identity for a servant or the operation within the servant, and any unexpected exceptions that the operation implementation might throw. Unexpected errors are indicated as a runtimeException. At the moment, there are two special runtime exceptions (ObjectNotExist and OperationNotExist), which indicate failure to find a servant or the correct operation. All other error conditions (such as an operation implementation throwing 42), the client gets an UnknownUserException with an error string. Expected exceptions are exceptions that an operation is expected to produce. (Think of Java exception specifications.) For example, NotFoundException can be thrown by the Registry::get_metadata() method. To deal with these, the servant implementation (ZmqRegistry) calls get_metadata() on the delegate in a try-catch block that handles NotFoundException separately. If that exception is thrown, ZmqRegistry::get_metadata() populates the payload that is marshaled with the response with the exception details and sets the error status in the response accordingly. The renaming capnp definitions, such as Scope.capnp, each define the operations and parameters for the corresponding interface. There is a definition for each operation, Request, that lists all the in-parameters and, for twoway methods, and Response (for twoway operations), that contains a union of the return values and exceptions that the operation can raise. (Oneway operations do not marshal anything in the return direction and so do not have any Response definitions.) Loose ends ---------- Things that need fixing or checking are marked with a TODO comment in the code. Things that are work-arounds for bugs in the compiler or libraries are marked with a BUGFIX comment. Things that are dubious in some way with no better solution available are marked with a HACK comment. Style ----- Consider running astyle over the code before checking it in. See astyle-config for more details. Test suite ---------- The test suite lives underneath the test directory. test/headers contains tests relating to header file integrity. test/gtest contains the C++ tests (which use Google test). The Google gtest authors are adamant that it is a bad idea to just link with a pre-installed version of libgtest.a. Therefore, libgtest.a (and libgtest_main.a) are created as part of the build and can be found in test/gtest/libgtest. See the INSTALL file for how to run the tests, particularly the caveat about "make test" not rebuilding the tests! Building and installing the code -------------------------------- See the INSTALL file. Development hints and tricks ---------------------------- See the HACKING file.