Rename TestExecutor to BatchExecutor, move definition to header 77/168977/4
authorPaweł Stawicki <p.stawicki@samsung.com>
Thu, 1 Feb 2018 12:42:11 +0000 (13:42 +0100)
committerPaweł Stawicki <p.stawicki@samsung.com>
Tue, 6 Feb 2018 11:20:37 +0000 (12:20 +0100)
Change-Id: I77e3af59358f7ed17ec1b9475fd0da5a50e5d864

src/batch/BatchRunner.cpp
src/batch/BatchRunner.hpp

index b5e8408..be6c2ce 100644 (file)
 #include "../UniversalSwitchLog.hpp"
 #include "Lexer.hpp"
 #include "Parser.hpp"
-#include "EvaluationContext.hpp"
 #include "EvaluationValue.hpp"
-#include "Evaluator.hpp"
 #include "../ActivityFactory.hpp"
 #include "../Observer.hpp"
 #include "../UIElement.hpp"
 #include "../UIActivity.hpp"
-#include "../NavigationInterface.hpp"
 #include "Monitor.hpp"
 #include "../DoneCallback.hpp"
 #include "../DBus.hpp"
 #include "Dlog.hpp"
 
 #include <mutex>
+#include <chrono>
 #include <thread>
 #include <fstream>
 #include <cmath>
 #include <type_traits>
-#include <regex>
 
 
 namespace WrapDetails
@@ -194,645 +191,630 @@ template <typename T, typename MONITORED_TYPE> MONITORED_TYPE executeOnMainThrea
        return h->takeValue();
 }
 
-struct TestExecutor : ExecutorInterface {
-       NavigationInterface::CallbackHandle contextChangedHandle;
-       struct ContextInfo {
-               std::shared_ptr<UIElement> root;
-               std::shared_ptr<NavigationElement> navigation;
-               std::string rootName;
-       };
-       Monitor<ContextInfo> contextInfo;
-       struct TTSInfo {
-               Optional<std::regex> searchLine;
-               enum class Mode { ignore, search, found };
-               Mode mode;
+BatchExecutor::BatchExecutor(std::ostream &output) : output(output)
+{
+       insertRoleConstants();
+       insertStateConstants();
+       insertMethods();
+       insertWaits();
+       insertActivities();
+       registerContextChangeCallback();
+}
+
+void BatchExecutor::registerContextChangeCallback()
+{
+       auto updateContextInfo = [this](std::shared_ptr<UIElement> root, std::shared_ptr<NavigationElement> navigationContext) {
+               std::string name;
+               if (root && root->getObject()) {
+                       auto r = Singleton<UniversalSwitch>::instance().getAtspi()->getName(root->getObject());
+                       if (r)
+                               name = std::move(*r);
+               }
+               DEBUG("context changed to root %s (%s)", root ? Atspi::getUniqueId(root->getObject()).c_str() : "", name.c_str());
+               auto h = contextInfo.lock();
+               h->navigation = std::move(navigationContext);
+               h->root = std::move(root);
+               h->rootName = std::move(name);
        };
-       Monitor<TTSInfo> ttsInfo;
-       std::unordered_map<std::string, EvaluationValue> variables;
-       std::ostream &output;
-
-       // NOTE: constructor of TestExecutor must be called on main thread
-       // constructor calls NavigationInterface object, which might be
-       // in progress of updating itself (context change) on main thread
-       TestExecutor(std::ostream &output) : output(output)
-       {
-               insertRoleConstants();
-               insertStateConstants();
-               insertMethods();
-               insertWaits();
-               insertActivities();
-               registerContextChangeCallback();
-       }
-       ~TestExecutor() = default;
+       auto nav = Singleton<UniversalSwitch>::instance().getNavigationInterface();
+       updateContextInfo(nav->getCurrentVisibleRoot(), nav->getCurrentNavigationContext());
+       contextChangedHandle = Singleton<UniversalSwitch>::instance().getNavigationInterface()->
+                                                  registerCb<NavigationCallbackType::ContextChanged>(std::move(updateContextInfo));
+}
 
-       void registerContextChangeCallback()
-       {
-               auto updateContextInfo = [this](std::shared_ptr<UIElement> root, std::shared_ptr<NavigationElement> navigationContext) {
-                       std::string name;
-                       if (root && root->getObject()) {
-                               auto r = Singleton<UniversalSwitch>::instance().getAtspi()->getName(root->getObject());
-                               if (r)
-                                       name = std::move(*r);
-                       }
-                       DEBUG("context changed to root %s (%s)", root ? Atspi::getUniqueId(root->getObject()).c_str() : "", name.c_str());
-                       auto h = contextInfo.lock();
-                       h->navigation = std::move(navigationContext);
-                       h->root = std::move(root);
-                       h->rootName = std::move(name);
-               };
-               auto nav = Singleton<UniversalSwitch>::instance().getNavigationInterface();
-               updateContextInfo(nav->getCurrentVisibleRoot(), nav->getCurrentNavigationContext());
-               contextChangedHandle = Singleton<UniversalSwitch>::instance().getNavigationInterface()->
-                                                          registerCb<NavigationCallbackType::ContextChanged>(std::move(updateContextInfo));
-       }
+EvaluationValue BatchExecutor::getVariableByName(const std::string &name)
+{
+       auto it = variables.find(name);
+       if (it != variables.end())
+               return it->second;
+       throw EvaluationFailure{} << "unknown variable '" << name << "'";
+}
 
-       EvaluationValue getVariableByName(const std::string &name) override
-       {
-               auto it = variables.find(name);
-               if (it != variables.end())
-                       return it->second;
-               throw EvaluationFailure{} << "unknown variable '" << name << "'";
-       }
+std::shared_ptr<UIElement> BatchExecutor::getVisibleRoot()
+{
+       auto h = contextInfo.lock();
+       return h->root;
+}
 
-       std::shared_ptr<UIElement> getVisibleRoot() override
-       {
-               auto h = contextInfo.lock();
-               return h->root;
-       }
+std::ostream &BatchExecutor::outputStream()
+{
+       return output;
+}
 
-       std::ostream &outputStream() override
-       {
-               return output;
-       }
-       std::shared_ptr<UIElement> convertToUIElement(Point pt) override
-       {
-               return executeOnMainThread([&]() {
-                       auto root = getVisibleRoot();
-                       auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
-                       auto found = atspi->getAtPoint(pt, Atspi::CoordType::Screen, root->getObject());
-                       if (!found) throw EvaluationFailure{} << "no at-spi object found at position <" <<
-                                                                                                         pt.x << ", " << pt.y << ">";
-                       return std::make_shared<UIElement>(std::move(found), pt, root->getApplicationCategory());
-               });
-       }
+std::shared_ptr<UIElement> BatchExecutor::convertToUIElement(Point pt)
+{
+       return executeOnMainThread([&]() {
+               auto root = getVisibleRoot();
+               auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+               auto found = atspi->getAtPoint(pt, Atspi::CoordType::Screen, root->getObject());
+               if (!found) throw EvaluationFailure{} << "no at-spi object found at position <" <<
+                                                                                                 pt.x << ", " << pt.y << ">";
+               return std::make_shared<UIElement>(std::move(found), pt, root->getApplicationCategory());
+       });
+}
 
-       std::string getUIElementName(const std::shared_ptr<UIElement> &uiElem) override
-       {
-               return executeOnMainThread([&]() {
-                       auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
-                       auto found = atspi->getName(uiElem->getObject());
-                       if (found)
-                               return std::move(*found);
-                       throw EvaluationFailure{} << "failed to get at-spi object's name (use dlogutil to get at-spi error message)";
+std::string BatchExecutor::getUIElementName(const std::shared_ptr<UIElement> &uiElem)
+{
+       return executeOnMainThread([&]() {
+               auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+               auto found = atspi->getName(uiElem->getObject());
+               if (found)
+                       return std::move(*found);
+               throw EvaluationFailure{} << "failed to get at-spi object's name (use dlogutil to get at-spi error message)";
+       });
+}
+
+std::string BatchExecutor::getUIElementUniqueId(const std::shared_ptr<UIElement> &uiElem)
+{
+       return executeOnMainThread([&]() {
+               return Atspi::getUniqueId(uiElem->getObject());
+       });
+}
+
+void BatchExecutor::findByName(const std::vector<AtspiAccessiblePtr> &elems, std::string requestedName, std::function<void(DBus::ValueOrError<std::vector<AtspiAccessiblePtr>>)> callback)
+{
+       struct Exec {
+               std::function<void(DBus::ValueOrError<std::vector<AtspiAccessiblePtr>>)> callback;
+               std::string requestedName;
+               std::vector<AtspiAccessiblePtr> foundElements;
+               Optional<DBus::Error> error;
+
+               ~Exec()
+               {
+                       if (error) callback(*error);
+                       else callback(std::move(foundElements));
+               }
+       };
+       auto exec = std::make_shared<Exec>();
+       exec->callback = std::move(callback);
+       exec->requestedName = std::move(requestedName);
+       auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+       for (auto &e : elems) {
+               atspi->getName(e, [e, exec](DBus::ValueOrError<std::string> name) {
+                       if (!name) {
+                               if (!exec->error)
+                                       exec->error = name.getError();
+                       } else if (std::get<0>(name) == exec->requestedName) {
+                               exec->foundElements.push_back(e);
+                       }
                });
        }
-       std::string getUIElementUniqueId(const std::shared_ptr<UIElement> &uiElem) override
-       {
-               return executeOnMainThread([&]() {
-                       return Atspi::getUniqueId(uiElem->getObject());
-               });
+}
+
+void BatchExecutor::getAllObjects(AtspiAccessiblePtr root, std::function<void(DBus::ValueOrError<std::vector<AtspiAccessiblePtr>>)> callback,
+                                                                 std::vector<int> roles, std::vector<int> states)
+{
+       auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+       auto col = atspi->getCollectionInterface(root);
+       if (!col) {
+               callback(DBus::Error{ "root '" + Atspi::getUniqueId(root) + "' doesn't have collection interface" });
+       } else {
+               auto m = Atspi::Matcher();
+               if (!states.empty()) m.states(states.begin(), states.end(), ATSPI_Collection_MATCH_ALL);
+               if (!roles.empty()) m.roles(roles.begin(), roles.end(), ATSPI_Collection_MATCH_ANY);
+               atspi->getMatchedElements(col, ATSPI_Collection_SORT_ORDER_CANONICAL, 0,
+                                                                 m, false, std::move(callback));
        }
-       void findByName(const std::vector<AtspiAccessiblePtr> &elems, std::string requestedName, std::function<void(DBus::ValueOrError<std::vector<AtspiAccessiblePtr>>)> callback)
-       {
-               struct Exec {
-                       std::function<void(DBus::ValueOrError<std::vector<AtspiAccessiblePtr>>)> callback;
-                       std::string requestedName;
-                       std::vector<AtspiAccessiblePtr> foundElements;
-                       Optional<DBus::Error> error;
+}
 
-                       ~Exec()
-                       {
-                               if (error) callback(*error);
-                               else callback(std::move(foundElements));
-                       }
-               };
-               auto exec = std::make_shared<Exec>();
-               exec->callback = std::move(callback);
-               exec->requestedName = std::move(requestedName);
-               auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
-               for (auto &e : elems) {
-                       atspi->getName(e, [e, exec](DBus::ValueOrError<std::string> name) {
-                               if (!name) {
-                                       if (!exec->error)
-                                               exec->error = name.getError();
-                               } else if (std::get<0>(name) == exec->requestedName) {
-                                       exec->foundElements.push_back(e);
-                               }
-                       });
+void BatchExecutor::makeUIElement(AtspiAccessiblePtr src, std::function<void(DBus::ValueOrError<std::shared_ptr<UIElement>>)> callback)
+{
+       auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+       atspi->getComponentInterface(src, [src, callback = std::move(callback)](DBus::ValueOrError<AtspiComponentPtr> comp) {
+               if (!comp) {
+                       callback(comp.getError());
+                       return;
                }
-       }
-       void getAllObjects(AtspiAccessiblePtr root, std::function<void(DBus::ValueOrError<std::vector<AtspiAccessiblePtr>>)> callback,
-                                          std::vector<int> roles = {}, std::vector<int> states = {})
-       {
                auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
-               auto col = atspi->getCollectionInterface(root);
-               if (!col) {
-                       callback(DBus::Error{ "root '" + Atspi::getUniqueId(root) + "' doesn't have collection interface" });
-               } else {
-                       auto m = Atspi::Matcher();
-                       if (!states.empty()) m.states(states.begin(), states.end(), ATSPI_Collection_MATCH_ALL);
-                       if (!roles.empty()) m.roles(roles.begin(), roles.end(), ATSPI_Collection_MATCH_ANY);
-                       atspi->getMatchedElements(col, ATSPI_Collection_SORT_ORDER_CANONICAL, 0,
-                                                                         m, false, std::move(callback));
+               atspi->getScreenPosition(std::get<0>(comp), [src, callback = std::move(callback)](DBus::ValueOrError<Rectangle> pos) {
+                       if (!pos) {
+                               callback(pos.getError());
+                               return;
+                       }
+                       callback(std::make_shared<UIElement>(src, std::get<0>(pos).getCenterPoint(), UIElement::ApplicationCategory::OTHER));
+               });
+       });
+}
+
+void BatchExecutor::makeUIElements(std::vector<AtspiAccessiblePtr> sources,
+                                                                  std::function<void(DBus::ValueOrError<std::vector<std::shared_ptr<UIElement>>>)> callback)
+{
+       struct Exec {
+               std::function<void(DBus::ValueOrError<std::vector<std::shared_ptr<UIElement>>>)> callback;
+               std::vector<std::shared_ptr<UIElement>> results;
+               Optional<DBus::Error> error;
+
+               ~Exec()
+               {
+                       if (error) {
+                               callback(*error);
+                       } else {
+                               for (auto e : results)
+                                       ASSERT(e && e->getObject());
+                               callback(std::move(results));
+                       }
                }
-       }
-       void makeUIElement(AtspiAccessiblePtr src, std::function<void(DBus::ValueOrError<std::shared_ptr<UIElement>>)> callback)
-       {
-               auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
-               atspi->getComponentInterface(src, [src, callback = std::move(callback)](DBus::ValueOrError<AtspiComponentPtr> comp) {
-                       if (!comp) {
-                               callback(comp.getError());
+       };
+       auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+       auto exec = std::make_shared<Exec>();
+       exec->callback = std::move(callback);
+       exec->results.resize(sources.size());
+       for (auto i = 0u; i < sources.size(); ++i) {
+               makeUIElement(sources[i], [i, exec](DBus::ValueOrError<std::shared_ptr<UIElement>> ui) {
+                       if (!ui) {
+                               if (!exec->error)
+                                       exec->error = std::move(ui.getError());
                                return;
                        }
-                       auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
-                       atspi->getScreenPosition(std::get<0>(comp), [src, callback = std::move(callback)](DBus::ValueOrError<Rectangle> pos) {
-                               if (!pos) {
-                                       callback(pos.getError());
-                                       return;
-                               }
-                               callback(std::make_shared<UIElement>(src, std::get<0>(pos).getCenterPoint(), UIElement::ApplicationCategory::OTHER));
-                       });
+                       if (!exec->error) {
+                               exec->results[i] = std::move(std::get<0>(ui));
+                       }
                });
        }
-       void makeUIElements(std::vector<AtspiAccessiblePtr> sources,
-                                               std::function<void(DBus::ValueOrError<std::vector<std::shared_ptr<UIElement>>>)> callback)
-       {
-               struct Exec {
-                       std::function<void(DBus::ValueOrError<std::vector<std::shared_ptr<UIElement>>>)> callback;
-                       std::vector<std::shared_ptr<UIElement>> results;
-                       Optional<DBus::Error> error;
+}
 
-                       ~Exec()
+std::shared_ptr<UIElement> BatchExecutor::convertToUIElement(const std::string &requestedName)
+{
+       Monitor<BatchValueOrError<std::shared_ptr<UIElement>>> monitor;
+
+       return executeOnMainThread([&]() {
+               auto uiRoot = getVisibleRoot();
+               if (!uiRoot) throw EvaluationFailure{} << "no visible root (context change didn't happen)";
+               auto root = uiRoot->getObject();
+               ASSERT(root);
+               getAllObjects(root, wrap(monitor, [ = ](DBus::ValueOrError<std::vector<AtspiAccessiblePtr>> elems) mutable {
+                       findByName(std::get<0>(elems), requestedName,
+                                          wrap(monitor, [ = ](DBus::ValueOrError<std::vector<AtspiAccessiblePtr>> elements)
                        {
-                               if (error) {
-                                       callback(*error);
-                               } else {
-                                       for (auto e : results)
-                                               ASSERT(e && e->getObject());
-                                       callback(std::move(results));
+                               auto &e = std::get<0>(elements);
+                               if (e.empty()) {
+                                       throw EvaluationFailure{} << "no at-spi object found with name '" << requestedName << "'";
                                }
-                       }
-               };
-               auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
-               auto exec = std::make_shared<Exec>();
-               exec->callback = std::move(callback);
-               exec->results.resize(sources.size());
-               for (auto i = 0u; i < sources.size(); ++i) {
-                       makeUIElement(sources[i], [i, exec](DBus::ValueOrError<std::shared_ptr<UIElement>> ui) {
-                               if (!ui) {
-                                       if (!exec->error)
-                                               exec->error = std::move(ui.getError());
-                                       return;
+                               if (e.size() > 1) {
+                                       std::ostringstream names;
+                                       for (auto &elem : e) names << " " << Atspi::getUniqueId(elem);
+                                       throw EvaluationFailure{} << "found more, than one at-spi object with name '" <<
+                                                                                         requestedName << "' (see" << names.str() << ")";
                                }
-                               if (!exec->error) {
-                                       exec->results[i] = std::move(std::get<0>(ui));
-                               }
-                       });
-               }
-       }
-
-       std::shared_ptr<UIElement> convertToUIElement(const std::string &requestedName) override
-       {
-               Monitor<BatchValueOrError<std::shared_ptr<UIElement>>> monitor;
-
-               return executeOnMainThread([&]() {
-                       auto uiRoot = getVisibleRoot();
-                       if (!uiRoot) throw EvaluationFailure{} << "no visible root (context change didn't happen)";
-                       auto root = uiRoot->getObject();
-                       ASSERT(root);
-                       getAllObjects(root, wrap(monitor, [ = ](DBus::ValueOrError<std::vector<AtspiAccessiblePtr>> elems) mutable {
-                               findByName(std::get<0>(elems), requestedName,
-                                                  wrap(monitor, [ = ](DBus::ValueOrError<std::vector<AtspiAccessiblePtr>> elements)
-                               {
-                                       auto &e = std::get<0>(elements);
-                                       if (e.empty()) {
-                                               throw EvaluationFailure{} << "no at-spi object found with name '" << requestedName << "'";
-                                       }
-                                       if (e.size() > 1) {
-                                               std::ostringstream names;
-                                               for (auto &elem : e) names << " " << Atspi::getUniqueId(elem);
-                                               throw EvaluationFailure{} << "found more, than one at-spi object with name '" <<
-                                                                                                 requestedName << "' (see" << names.str() << ")";
-                                       }
-                                       makeUIElement(e[0], wrap(monitor, [ = ](DBus::ValueOrError<std::shared_ptr<UIElement>> elem) {
-                                               auto h = monitor.lock();
-                                               h->setValue(std::move(std::get<0>(elem)));
-                                       }));
+                               makeUIElement(e[0], wrap(monitor, [ = ](DBus::ValueOrError<std::shared_ptr<UIElement>> elem) {
+                                       auto h = monitor.lock();
+                                       h->setValue(std::move(std::get<0>(elem)));
                                }));
                        }));
-               }, monitor);
-       }
+               }));
+       }, monitor);
+}
 
-       void insertMethods()
-       {
-               variables["sleep"] = [&](double tm) -> EvaluationValue {
-                       if (tm > 0)
-                       {
-                               auto sleepTime = std::chrono::milliseconds{ static_cast<int>(std::floor(1000.0 * tm + 0.5)) };
-                               std::this_thread::sleep_for(sleepTime);
-                       }
-                       return {};
-               };
-               variables["print"] = [&](std::string txt) -> EvaluationValue {
-                       output << txt << "\n";
-                       return {};
-               };
-               variables["get_at_point"] = [&](Point pt) -> EvaluationValue {
-                       return convertToUIElement(pt);
-               };
-               variables["assert"] = [&](bool condition) -> EvaluationValue {
-                       if (!condition) throw EvaluationFailure{} << "assertion failed";
-                       return {};
-               };
-               variables["find_by_name"] = EvaluationValueFunction{ [&](std::string name, std::vector<int> roles, std::vector<int> states) -> EvaluationValue {
-                               auto root = getVisibleRoot();
-                               if (!root) throw EvaluationFailure{} << "no visible root (context changed didn't happen)";
-                               ASSERT(root->getObject());
-                               Monitor<BatchValueOrError<std::vector<std::shared_ptr<UIElement>>>> monitor;
+void BatchExecutor::insertMethods()
+{
+       variables["sleep"] = [&](double tm) -> EvaluationValue {
+               if (tm > 0)
+               {
+                       auto sleepTime = std::chrono::milliseconds{ static_cast<int>(std::floor(1000.0 * tm + 0.5)) };
+                       std::this_thread::sleep_for(sleepTime);
+               }
+               return {};
+       };
+       variables["print"] = [&](std::string txt) -> EvaluationValue {
+               output << txt << "\n";
+               return {};
+       };
+       variables["get_at_point"] = [&](Point pt) -> EvaluationValue {
+               return convertToUIElement(pt);
+       };
+       variables["assert"] = [&](bool condition) -> EvaluationValue {
+               if (!condition) throw EvaluationFailure{} << "assertion failed";
+               return {};
+       };
+       variables["find_by_name"] = EvaluationValueFunction{ [&](std::string name, std::vector<int> roles, std::vector<int> states) -> EvaluationValue {
+                       auto root = getVisibleRoot();
+                       if (!root) throw EvaluationFailure{} << "no visible root (context changed didn't happen)";
+                       ASSERT(root->getObject());
+                       Monitor<BatchValueOrError<std::vector<std::shared_ptr<UIElement>>>> monitor;
 
-                               return executeOnMainThread([&]()
-                               {
-                                       getAllObjects(root->getObject(), wrap(monitor, [ = ](DBus::ValueOrError<std::vector<AtspiAccessiblePtr>> allElements) {
-                                               findByName(std::get<0>(allElements), name, wrap(monitor, [ = ](DBus::ValueOrError<std::vector<AtspiAccessiblePtr>> elements) {
-                                                       auto &elems = std::get<0>(elements);
-                                                       makeUIElements(std::move(elems), wrap(monitor, [ = ](DBus::ValueOrError<std::vector<std::shared_ptr<UIElement>>> uiElems) {
-                                                               auto h = monitor.lock();
-                                                               h->setValue(std::move(std::get<0>(uiElems)));
-                                                       }));
+                       return executeOnMainThread([&]()
+                       {
+                               getAllObjects(root->getObject(), wrap(monitor, [ = ](DBus::ValueOrError<std::vector<AtspiAccessiblePtr>> allElements) {
+                                       findByName(std::get<0>(allElements), name, wrap(monitor, [ = ](DBus::ValueOrError<std::vector<AtspiAccessiblePtr>> elements) {
+                                               auto &elems = std::get<0>(elements);
+                                               makeUIElements(std::move(elems), wrap(monitor, [ = ](DBus::ValueOrError<std::vector<std::shared_ptr<UIElement>>> uiElems) {
+                                                       auto h = monitor.lock();
+                                                       h->setValue(std::move(std::get<0>(uiElems)));
                                                }));
-                                       }), std::move(roles), std::move(states));
-                               }, monitor);
-                       }, { { "name" }, { "roles", EvaluationValueSet() }, { "states", EvaluationValueSet() } } };
-       }
+                                       }));
+                               }), std::move(roles), std::move(states));
+                       }, monitor);
+               }, { { "name" }, { "roles", EvaluationValueSet() }, { "states", EvaluationValueSet() } } };
+}
 
-       class EvaluationValueWaitImpl : public EvaluationValueWaitInterface
-       {
-       public:
-               EvaluationValueWaitImpl(TestExecutor *executor, std::chrono::milliseconds timeout)
-                       : self(executor), timeout(std::chrono::high_resolution_clock::now() + timeout)
-               {}
+class PredicateWaitInterface : public EvaluationValueWaitInterface
+{
+public:
+       PredicateWaitInterface(BatchExecutor *executor, std::chrono::milliseconds timeout)
+               : self(executor), timeout(std::chrono::high_resolution_clock::now() + timeout)
+       {}
 
-               void join() override
-               {
-                       if (success) return;
+       void join() override
+       {
+               if (success) return;
 
-                       success = waitForPredicate();
-               }
+               success = predicate();
+       }
 
-       protected:
-               virtual bool waitForPredicate() = 0;
+protected:
+       virtual bool predicate() = 0;
 
-               TestExecutor *self;
-               std::chrono::high_resolution_clock::time_point timeout;
-               bool success = false;
-       };
+       BatchExecutor *self;
+       std::chrono::high_resolution_clock::time_point timeout;
+       bool success = false;
+};
 
-       class WaitTTS : public EvaluationValueWaitImpl
+class WaitTTS : public PredicateWaitInterface
+{
+public:
+       WaitTTS(BatchExecutor *executor, std::chrono::milliseconds timeout, std::string pattern)
+               : PredicateWaitInterface(executor, timeout)
        {
-       public:
-               WaitTTS(TestExecutor *executor, std::chrono::milliseconds timeout, std::string pattern)
-                       : EvaluationValueWaitImpl(executor, timeout)
-               {
-                       std::regex regex;
-                       if (!pattern.empty()) {
-                               try {
-                                       regex = std::regex {
-                                               pattern,
-                                               std::regex_constants::nosubs |
-                                               std::regex_constants::optimize |
-                                               std::regex_constants::ECMAScript
-                                       };
-                               } catch (...) {
-                                       throw EvaluationFailure{} << "invalid regex pattern '" << pattern << "'";
-                               }
-                       }
-                       {
-                               auto h = self->ttsInfo.lock();
-                               if (!pattern.empty())
-                                       h->searchLine = std::move(regex);
-                               h->mode = TTSInfo::Mode::search;
+               std::regex regex;
+               if (!pattern.empty()) {
+                       try {
+                               regex = std::regex {
+                                       pattern,
+                                       std::regex_constants::nosubs |
+                                       std::regex_constants::optimize |
+                                       std::regex_constants::ECMAScript
+                               };
+                       } catch (...) {
+                               throw EvaluationFailure{} << "invalid regex pattern '" << pattern << "'";
                        }
-                       this->pattern = std::move(pattern);
                }
-
-       private:
-               bool waitForPredicate() override
                {
                        auto h = self->ttsInfo.lock();
-                       auto res = h.waitForCondition(timeout, [&]() {
-                               return h->mode == TTSInfo::Mode::found;
-                       });
+                       if (!pattern.empty())
+                               h->searchLine = std::move(regex);
+                       h->mode = BatchExecutor::TTSInfo::Mode::search;
+               }
+               this->pattern = std::move(pattern);
+       }
 
-                       if (!res) {
-                               h->mode = TTSInfo::Mode::ignore;
-                               throw EvaluationFailure{} << "wait for dlog ('" << pattern << "'): operation timeouted";
-                       }
-                       h->mode = TTSInfo::Mode::ignore;
+private:
+       bool predicate() override
+       {
+               auto h = self->ttsInfo.lock();
+               auto res = h.waitForCondition(timeout, [&]() {
+                       return h->mode == BatchExecutor::TTSInfo::Mode::found;
+               });
 
-                       return res;
+               if (!res) {
+                       h->mode = BatchExecutor::TTSInfo::Mode::ignore;
+                       throw EvaluationFailure{} << "wait for dlog ('" << pattern << "'): operation timeouted";
                }
+               h->mode = BatchExecutor::TTSInfo::Mode::ignore;
 
-               std::string pattern;
-       };
+               return res;
+       }
 
-       class WaitGui : public EvaluationValueWaitImpl
-       {
-       public:
-               WaitGui(TestExecutor *executor, std::chrono::milliseconds timeout, std::string name)
-                       : EvaluationValueWaitImpl(executor, timeout)
-               {
-                       if (name.empty()) {
-                               auto h = self->contextInfo.lock();
-                               name = h->rootName;
-                               searchForAnyChange = true;
-                       } else {
-                               this->name = std::move(name);
-                       }
-               }
+       std::string pattern;
+};
 
-       private:
-               bool waitForPredicate() override
-               {
+class WaitGui : public PredicateWaitInterface
+{
+public:
+       WaitGui(BatchExecutor *executor, std::chrono::milliseconds timeout, std::string name)
+               : PredicateWaitInterface(executor, timeout)
+       {
+               if (name.empty()) {
                        auto h = self->contextInfo.lock();
-                       auto res = h.waitForCondition(timeout, [&]() {
-                               return (searchForAnyChange && name != h->rootName) || (!searchForAnyChange && name == h->rootName);
-                       });
+                       name = h->rootName;
+                       searchForAnyChange = true;
+               } else {
+                       this->name = std::move(name);
+               }
+       }
 
-                       if (!res) {
-                               throw EvaluationFailure{} << "wait for gui ('" << name << "'): operation timeouted, " <<
-                                                                                 "current root name is '" << h->rootName << "'";
-                       }
+private:
+       bool predicate() override
+       {
+               auto h = self->contextInfo.lock();
+               auto res = h.waitForCondition(timeout, [&]() {
+                       return (searchForAnyChange && name != h->rootName) || (!searchForAnyChange && name == h->rootName);
+               });
 
-                       return res;
+               if (!res) {
+                       throw EvaluationFailure{} << "wait for gui ('" << name << "'): operation timeouted, " <<
+                                                                         "current root name is '" << h->rootName << "'";
                }
 
-               std::string name;
-               bool searchForAnyChange = false;
-       };
+               return res;
+       }
 
-       void insertWaits()
-       {
-               auto waitTTS = [&](std::string pattern, double timeout) -> EvaluationValue {
-                       auto impl = std::make_shared<WaitTTS>(this, std::chrono::milliseconds{ static_cast<size_t>(timeout * 1000) }, std::move(pattern));
-                       return EvaluationValue{ impl };
-               };
-               variables["tts"] = EvaluationValueFunction{ std::move(waitTTS), { { "pattern", "" }, { "timeout", 3.0 } } };
+       std::string name;
+       bool searchForAnyChange = false;
+};
 
-               auto waitGui = [&](std::string name, double timeout) -> EvaluationValue {
-                       auto impl = std::make_shared<WaitGui>(this, std::chrono::milliseconds{ static_cast<size_t>(timeout * 1000) }, std::move(name));
-                       return EvaluationValue{ impl };
-               };
-               variables["gui"] = EvaluationValueFunction{ std::move(waitGui), { { "name", "" }, { "timeout", 3.0 } } };
-       }
+void BatchExecutor::insertWaits()
+{
+       auto waitTTS = [&](std::string pattern, double timeout) -> EvaluationValue {
+               auto impl = std::make_shared<WaitTTS>(this, std::chrono::milliseconds{ static_cast<size_t>(timeout * 1000) }, std::move(pattern));
+               return EvaluationValue{ impl };
+       };
+       variables["tts"] = EvaluationValueFunction{ std::move(waitTTS), { { "pattern", "" }, { "timeout", 3.0 } } };
 
-       void insertActivities()
-       {
-               for (auto activityName : ActivityFactory::getInstance()->getAllActivityTypes()) {
-                       variables[activityName] = [ = ](EvaluationValueFunction::Args args) -> EvaluationValue {
-                               auto activity = executeOnMainThread([&]()
-                               {
-                                       return ActivityFactory::getInstance()->createActivity(activityName);
-                               });
-                               if (!activity)
-                                       throw EvaluationFailure{} << "failed to construct '" << activityName << "' activity";
-                               auto numOfArgs = activity->getRequiredNumberOfArgumentsIfAllowedInBatchProcessing();
-                               if (!numOfArgs)
-                                       throw EvaluationFailure{} << "activity '" << activityName << "' is not supported";
-                               if (*numOfArgs != args.size())
-                                       throw EvaluationFailure{} << "invalid number of arguments for activity '" << activityName <<
-                                                                                 "', got " << args.size() << ", expected " << *numOfArgs;
-                               auto uiActivity = std::dynamic_pointer_cast<UIActivity>(activity);
-
-                               // activity must inherit from UIActivity if it returns non zero expected arguments
-                               ASSERT(args.empty() || uiActivity);
-
-                               std::vector<std::shared_ptr<UIElement>> uiArgs(args.size());
-                               for (size_t i = 0; i < args.size(); ++i)
-                               {
-                                       ASSERT(uiActivity);
-                                       uiArgs[i] = args[i].convertToUIElement();
-                                       if (!uiArgs[i])
-                                               throw EvaluationFailure{} << "can't convert argument " << (i + 1) <<
-                                                                                         " of kind " << args[i].typeName() << " to UIElement";
-                               }
-                               Monitor<BatchValueOrError<bool>> monitor;
+       auto waitGui = [&](std::string name, double timeout) -> EvaluationValue {
+               auto impl = std::make_shared<WaitGui>(this, std::chrono::milliseconds{ static_cast<size_t>(timeout * 1000) }, std::move(name));
+               return EvaluationValue{ impl };
+       };
+       variables["gui"] = EvaluationValueFunction{ std::move(waitGui), { { "name", "" }, { "timeout", 3.0 } } };
+}
+
+void BatchExecutor::insertActivities()
+{
+       for (auto activityName : ActivityFactory::getInstance()->getAllActivityTypes()) {
+               variables[activityName] = [ = ](EvaluationValueFunction::Args args) -> EvaluationValue {
+                       auto activity = executeOnMainThread([&]()
+                       {
+                               return ActivityFactory::getInstance()->createActivity(activityName);
+                       });
+                       if (!activity)
+                               throw EvaluationFailure{} << "failed to construct '" << activityName << "' activity";
+                       auto numOfArgs = activity->getRequiredNumberOfArgumentsIfAllowedInBatchProcessing();
+                       if (!numOfArgs)
+                               throw EvaluationFailure{} << "activity '" << activityName << "' is not supported";
+                       if (*numOfArgs != args.size())
+                               throw EvaluationFailure{} << "invalid number of arguments for activity '" << activityName <<
+                                                                         "', got " << args.size() << ", expected " << *numOfArgs;
+                       auto uiActivity = std::dynamic_pointer_cast<UIActivity>(activity);
+
+                       // activity must inherit from UIActivity if it returns non zero expected arguments
+                       ASSERT(args.empty() || uiActivity);
+
+                       std::vector<std::shared_ptr<UIElement>> uiArgs(args.size());
+                       for (size_t i = 0; i < args.size(); ++i)
+                       {
+                               ASSERT(uiActivity);
+                               uiArgs[i] = args[i].convertToUIElement();
+                               if (!uiArgs[i])
+                                       throw EvaluationFailure{} << "can't convert argument " << (i + 1) <<
+                                                                                 " of kind " << args[i].typeName() << " to UIElement";
+                       }
+                       Monitor<BatchValueOrError<bool>> monitor;
+                       {
+                               executeOnMainThread([&]()
                                {
-                                       executeOnMainThread([&]()
-                                       {
-                                               DEBUG("calling activity %s", activityName.c_str());
-                                               for (auto &arg : uiArgs) {
-                                                       ASSERT(uiActivity);
-                                                       uiActivity->update(std::move(arg));
-                                               }
-                                               activity->process(DoneCallback{ [ = ] {
-                                                               auto h = monitor.lock();
-                                                               h->setValue(true);
-                                                       } });
-                                               DEBUG("calling activity %s done", activityName.c_str());
-                                       }, monitor);
-                                       if (!activity->isCompleted())
-                                               throw EvaluationFailure{} << "activity '" << activityName << "' is not marked as completed!";
-                                       auto h = monitor.lock();
-                                       ASSERT(*h); // sanity check, must be set, otherwise an exception was thrown
-                               }
-                               return {};
-                       };
-               }
+                                       DEBUG("calling activity %s", activityName.c_str());
+                                       for (auto &arg : uiArgs) {
+                                               ASSERT(uiActivity);
+                                               uiActivity->update(std::move(arg));
+                                       }
+                                       activity->process(DoneCallback{ [ = ] {
+                                                       auto h = monitor.lock();
+                                                       h->setValue(true);
+                                               } });
+                                       DEBUG("calling activity %s done", activityName.c_str());
+                               }, monitor);
+                               if (!activity->isCompleted())
+                                       throw EvaluationFailure{} << "activity '" << activityName << "' is not marked as completed!";
+                               auto h = monitor.lock();
+                               ASSERT(*h); // sanity check, must be set, otherwise an exception was thrown
+                       }
+                       return {};
+               };
        }
+}
 
-       void insertStateConstants()
-       {
-               // from at-spi2-core v. 2.16.0
-               for (auto pair : std::initializer_list<std::pair<std::string, int>> {
+void BatchExecutor::insertStateConstants()
+{
+       // from at-spi2-core v. 2.16.0
+       for (auto pair : std::initializer_list<std::pair<std::string, int>> {
 #define Q(a) { #a, a }
-               Q(ATSPI_STATE_INVALID),
-                       Q(ATSPI_STATE_ACTIVE),
-                       Q(ATSPI_STATE_ARMED),
-                       Q(ATSPI_STATE_BUSY),
-                       Q(ATSPI_STATE_CHECKED),
-                       Q(ATSPI_STATE_COLLAPSED),
-                       Q(ATSPI_STATE_DEFUNCT),
-                       Q(ATSPI_STATE_EDITABLE),
-                       Q(ATSPI_STATE_ENABLED),
-                       Q(ATSPI_STATE_EXPANDABLE),
-                       Q(ATSPI_STATE_EXPANDED),
-                       Q(ATSPI_STATE_FOCUSABLE),
-                       Q(ATSPI_STATE_FOCUSED),
-                       Q(ATSPI_STATE_HAS_TOOLTIP),
-                       Q(ATSPI_STATE_HORIZONTAL),
-                       Q(ATSPI_STATE_ICONIFIED),
-                       Q(ATSPI_STATE_MODAL),
-                       Q(ATSPI_STATE_MULTI_LINE),
-                       Q(ATSPI_STATE_MULTISELECTABLE),
-                       Q(ATSPI_STATE_OPAQUE),
-                       Q(ATSPI_STATE_PRESSED),
-                       Q(ATSPI_STATE_RESIZABLE),
-                       Q(ATSPI_STATE_SELECTABLE),
-                       Q(ATSPI_STATE_SELECTED),
-                       Q(ATSPI_STATE_SENSITIVE),
-                       Q(ATSPI_STATE_SHOWING),
-                       Q(ATSPI_STATE_SINGLE_LINE),
-                       Q(ATSPI_STATE_STALE),
-                       Q(ATSPI_STATE_TRANSIENT),
-                       Q(ATSPI_STATE_VERTICAL),
-                       Q(ATSPI_STATE_VISIBLE),
-                       Q(ATSPI_STATE_MANAGES_DESCENDANTS),
-                       Q(ATSPI_STATE_INDETERMINATE),
-                       Q(ATSPI_STATE_REQUIRED),
-                       Q(ATSPI_STATE_TRUNCATED),
-                       Q(ATSPI_STATE_ANIMATED),
-                       Q(ATSPI_STATE_INVALID_ENTRY),
-                       Q(ATSPI_STATE_SUPPORTS_AUTOCOMPLETION),
-                       Q(ATSPI_STATE_SELECTABLE_TEXT),
-                       Q(ATSPI_STATE_IS_DEFAULT),
-                       Q(ATSPI_STATE_VISITED),
-                       Q(ATSPI_STATE_CHECKABLE),
-                       Q(ATSPI_STATE_HAS_POPUP),
-                       Q(ATSPI_STATE_READ_ONLY),
-                       Q(ATSPI_STATE_HIGHLIGHTED),
-                       Q(ATSPI_STATE_HIGHLIGHTABLE),
-                       Q(ATSPI_STATE_LAST_DEFINED),
+       Q(ATSPI_STATE_INVALID),
+               Q(ATSPI_STATE_ACTIVE),
+               Q(ATSPI_STATE_ARMED),
+               Q(ATSPI_STATE_BUSY),
+               Q(ATSPI_STATE_CHECKED),
+               Q(ATSPI_STATE_COLLAPSED),
+               Q(ATSPI_STATE_DEFUNCT),
+               Q(ATSPI_STATE_EDITABLE),
+               Q(ATSPI_STATE_ENABLED),
+               Q(ATSPI_STATE_EXPANDABLE),
+               Q(ATSPI_STATE_EXPANDED),
+               Q(ATSPI_STATE_FOCUSABLE),
+               Q(ATSPI_STATE_FOCUSED),
+               Q(ATSPI_STATE_HAS_TOOLTIP),
+               Q(ATSPI_STATE_HORIZONTAL),
+               Q(ATSPI_STATE_ICONIFIED),
+               Q(ATSPI_STATE_MODAL),
+               Q(ATSPI_STATE_MULTI_LINE),
+               Q(ATSPI_STATE_MULTISELECTABLE),
+               Q(ATSPI_STATE_OPAQUE),
+               Q(ATSPI_STATE_PRESSED),
+               Q(ATSPI_STATE_RESIZABLE),
+               Q(ATSPI_STATE_SELECTABLE),
+               Q(ATSPI_STATE_SELECTED),
+               Q(ATSPI_STATE_SENSITIVE),
+               Q(ATSPI_STATE_SHOWING),
+               Q(ATSPI_STATE_SINGLE_LINE),
+               Q(ATSPI_STATE_STALE),
+               Q(ATSPI_STATE_TRANSIENT),
+               Q(ATSPI_STATE_VERTICAL),
+               Q(ATSPI_STATE_VISIBLE),
+               Q(ATSPI_STATE_MANAGES_DESCENDANTS),
+               Q(ATSPI_STATE_INDETERMINATE),
+               Q(ATSPI_STATE_REQUIRED),
+               Q(ATSPI_STATE_TRUNCATED),
+               Q(ATSPI_STATE_ANIMATED),
+               Q(ATSPI_STATE_INVALID_ENTRY),
+               Q(ATSPI_STATE_SUPPORTS_AUTOCOMPLETION),
+               Q(ATSPI_STATE_SELECTABLE_TEXT),
+               Q(ATSPI_STATE_IS_DEFAULT),
+               Q(ATSPI_STATE_VISITED),
+               Q(ATSPI_STATE_CHECKABLE),
+               Q(ATSPI_STATE_HAS_POPUP),
+               Q(ATSPI_STATE_READ_ONLY),
+               Q(ATSPI_STATE_HIGHLIGHTED),
+               Q(ATSPI_STATE_HIGHLIGHTABLE),
+               Q(ATSPI_STATE_LAST_DEFINED),
 #undef Q
-               }) {
-                       ASSERT(pair.first.substr(0, 6) == "ATSPI_");
-                       variables[pair.first.substr(6)] = pair.second;
-               }
+       }) {
+               ASSERT(pair.first.substr(0, 6) == "ATSPI_");
+               variables[pair.first.substr(6)] = pair.second;
        }
-       void insertRoleConstants()
-       {
-               // from at-spi2-core v. 2.16.0
-               for (auto pair : std::initializer_list<std::pair<std::string, int>> {
+}
+
+void BatchExecutor::insertRoleConstants()
+{
+       // from at-spi2-core v. 2.16.0
+       for (auto pair : std::initializer_list<std::pair<std::string, int>> {
 #define Q(a) { #a, a }
-               Q(ATSPI_ROLE_INVALID),
-                       Q(ATSPI_ROLE_ACCELERATOR_LABEL),
-                       Q(ATSPI_ROLE_ALERT),
-                       Q(ATSPI_ROLE_ANIMATION),
-                       Q(ATSPI_ROLE_ARROW),
-                       Q(ATSPI_ROLE_CALENDAR),
-                       Q(ATSPI_ROLE_CANVAS),
-                       Q(ATSPI_ROLE_CHECK_BOX),
-                       Q(ATSPI_ROLE_CHECK_MENU_ITEM),
-                       Q(ATSPI_ROLE_COLOR_CHOOSER),
-                       Q(ATSPI_ROLE_COLUMN_HEADER),
-                       Q(ATSPI_ROLE_COMBO_BOX),
-                       Q(ATSPI_ROLE_DATE_EDITOR),
-                       Q(ATSPI_ROLE_DESKTOP_ICON),
-                       Q(ATSPI_ROLE_DESKTOP_FRAME),
-                       Q(ATSPI_ROLE_DIAL),
-                       Q(ATSPI_ROLE_DIALOG),
-                       Q(ATSPI_ROLE_DIRECTORY_PANE),
-                       Q(ATSPI_ROLE_DRAWING_AREA),
-                       Q(ATSPI_ROLE_FILE_CHOOSER),
-                       Q(ATSPI_ROLE_FILLER),
-                       Q(ATSPI_ROLE_FOCUS_TRAVERSABLE),
-                       Q(ATSPI_ROLE_FONT_CHOOSER),
-                       Q(ATSPI_ROLE_FRAME),
-                       Q(ATSPI_ROLE_GLASS_PANE),
-                       Q(ATSPI_ROLE_HTML_CONTAINER),
-                       Q(ATSPI_ROLE_ICON),
-                       Q(ATSPI_ROLE_IMAGE),
-                       Q(ATSPI_ROLE_INTERNAL_FRAME),
-                       Q(ATSPI_ROLE_LABEL),
-                       Q(ATSPI_ROLE_LAYERED_PANE),
-                       Q(ATSPI_ROLE_LIST),
-                       Q(ATSPI_ROLE_LIST_ITEM),
-                       Q(ATSPI_ROLE_MENU),
-                       Q(ATSPI_ROLE_MENU_BAR),
-                       Q(ATSPI_ROLE_MENU_ITEM),
-                       Q(ATSPI_ROLE_OPTION_PANE),
-                       Q(ATSPI_ROLE_PAGE_TAB),
-                       Q(ATSPI_ROLE_PAGE_TAB_LIST),
-                       Q(ATSPI_ROLE_PANEL),
-                       Q(ATSPI_ROLE_PASSWORD_TEXT),
-                       Q(ATSPI_ROLE_POPUP_MENU),
-                       Q(ATSPI_ROLE_PROGRESS_BAR),
-                       Q(ATSPI_ROLE_PUSH_BUTTON),
-                       Q(ATSPI_ROLE_RADIO_BUTTON),
-                       Q(ATSPI_ROLE_RADIO_MENU_ITEM),
-                       Q(ATSPI_ROLE_ROOT_PANE),
-                       Q(ATSPI_ROLE_ROW_HEADER),
-                       Q(ATSPI_ROLE_SCROLL_BAR),
-                       Q(ATSPI_ROLE_SCROLL_PANE),
-                       Q(ATSPI_ROLE_SEPARATOR),
-                       Q(ATSPI_ROLE_SLIDER),
-                       Q(ATSPI_ROLE_SPIN_BUTTON),
-                       Q(ATSPI_ROLE_SPLIT_PANE),
-                       Q(ATSPI_ROLE_STATUS_BAR),
-                       Q(ATSPI_ROLE_TABLE),
-                       Q(ATSPI_ROLE_TABLE_CELL),
-                       Q(ATSPI_ROLE_TABLE_COLUMN_HEADER),
-                       Q(ATSPI_ROLE_TABLE_ROW_HEADER),
-                       Q(ATSPI_ROLE_TEAROFF_MENU_ITEM),
-                       Q(ATSPI_ROLE_TERMINAL),
-                       Q(ATSPI_ROLE_TEXT),
-                       Q(ATSPI_ROLE_TOGGLE_BUTTON),
-                       Q(ATSPI_ROLE_TOOL_BAR),
-                       Q(ATSPI_ROLE_TOOL_TIP),
-                       Q(ATSPI_ROLE_TREE),
-                       Q(ATSPI_ROLE_TREE_TABLE),
-                       Q(ATSPI_ROLE_UNKNOWN),
-                       Q(ATSPI_ROLE_VIEWPORT),
-                       Q(ATSPI_ROLE_WINDOW),
-                       Q(ATSPI_ROLE_EXTENDED),
-                       Q(ATSPI_ROLE_HEADER),
-                       Q(ATSPI_ROLE_FOOTER),
-                       Q(ATSPI_ROLE_PARAGRAPH),
-                       Q(ATSPI_ROLE_RULER),
-                       Q(ATSPI_ROLE_APPLICATION),
-                       Q(ATSPI_ROLE_AUTOCOMPLETE),
-                       Q(ATSPI_ROLE_EDITBAR),
-                       Q(ATSPI_ROLE_EMBEDDED),
-                       Q(ATSPI_ROLE_ENTRY),
-                       Q(ATSPI_ROLE_CHART),
-                       Q(ATSPI_ROLE_CAPTION),
-                       Q(ATSPI_ROLE_DOCUMENT_FRAME),
-                       Q(ATSPI_ROLE_HEADING),
-                       Q(ATSPI_ROLE_PAGE),
-                       Q(ATSPI_ROLE_SECTION),
-                       Q(ATSPI_ROLE_REDUNDANT_OBJECT),
-                       Q(ATSPI_ROLE_FORM),
-                       Q(ATSPI_ROLE_LINK),
-                       Q(ATSPI_ROLE_INPUT_METHOD_WINDOW),
-                       Q(ATSPI_ROLE_TABLE_ROW),
-                       Q(ATSPI_ROLE_TREE_ITEM),
-                       Q(ATSPI_ROLE_DOCUMENT_SPREADSHEET),
-                       Q(ATSPI_ROLE_DOCUMENT_PRESENTATION),
-                       Q(ATSPI_ROLE_DOCUMENT_TEXT),
-                       Q(ATSPI_ROLE_DOCUMENT_WEB),
-                       Q(ATSPI_ROLE_DOCUMENT_EMAIL),
-                       Q(ATSPI_ROLE_COMMENT),
-                       Q(ATSPI_ROLE_LIST_BOX),
-                       Q(ATSPI_ROLE_GROUPING),
-                       Q(ATSPI_ROLE_IMAGE_MAP),
-                       Q(ATSPI_ROLE_NOTIFICATION),
-                       Q(ATSPI_ROLE_INFO_BAR),
-                       Q(ATSPI_ROLE_LEVEL_BAR),
-                       Q(ATSPI_ROLE_TITLE_BAR),
-                       Q(ATSPI_ROLE_BLOCK_QUOTE),
-                       Q(ATSPI_ROLE_AUDIO),
-                       Q(ATSPI_ROLE_VIDEO),
-                       Q(ATSPI_ROLE_DEFINITION),
-                       Q(ATSPI_ROLE_ARTICLE),
-                       Q(ATSPI_ROLE_LANDMARK),
-                       Q(ATSPI_ROLE_LOG),
-                       Q(ATSPI_ROLE_MARQUEE),
-                       Q(ATSPI_ROLE_MATH),
-                       Q(ATSPI_ROLE_RATING),
-                       Q(ATSPI_ROLE_TIMER),
-                       Q(ATSPI_ROLE_STATIC),
-                       Q(ATSPI_ROLE_MATH_FRACTION),
-                       Q(ATSPI_ROLE_MATH_ROOT),
-                       Q(ATSPI_ROLE_SUBSCRIPT),
-                       Q(ATSPI_ROLE_SUPERSCRIPT),
-                       Q(ATSPI_ROLE_LAST_DEFINED),
-               }) {
-                       ASSERT(pair.first.substr(0, 6) == "ATSPI_");
-                       variables[pair.first.substr(6)] = pair.second;
-               }
+       Q(ATSPI_ROLE_INVALID),
+               Q(ATSPI_ROLE_ACCELERATOR_LABEL),
+               Q(ATSPI_ROLE_ALERT),
+               Q(ATSPI_ROLE_ANIMATION),
+               Q(ATSPI_ROLE_ARROW),
+               Q(ATSPI_ROLE_CALENDAR),
+               Q(ATSPI_ROLE_CANVAS),
+               Q(ATSPI_ROLE_CHECK_BOX),
+               Q(ATSPI_ROLE_CHECK_MENU_ITEM),
+               Q(ATSPI_ROLE_COLOR_CHOOSER),
+               Q(ATSPI_ROLE_COLUMN_HEADER),
+               Q(ATSPI_ROLE_COMBO_BOX),
+               Q(ATSPI_ROLE_DATE_EDITOR),
+               Q(ATSPI_ROLE_DESKTOP_ICON),
+               Q(ATSPI_ROLE_DESKTOP_FRAME),
+               Q(ATSPI_ROLE_DIAL),
+               Q(ATSPI_ROLE_DIALOG),
+               Q(ATSPI_ROLE_DIRECTORY_PANE),
+               Q(ATSPI_ROLE_DRAWING_AREA),
+               Q(ATSPI_ROLE_FILE_CHOOSER),
+               Q(ATSPI_ROLE_FILLER),
+               Q(ATSPI_ROLE_FOCUS_TRAVERSABLE),
+               Q(ATSPI_ROLE_FONT_CHOOSER),
+               Q(ATSPI_ROLE_FRAME),
+               Q(ATSPI_ROLE_GLASS_PANE),
+               Q(ATSPI_ROLE_HTML_CONTAINER),
+               Q(ATSPI_ROLE_ICON),
+               Q(ATSPI_ROLE_IMAGE),
+               Q(ATSPI_ROLE_INTERNAL_FRAME),
+               Q(ATSPI_ROLE_LABEL),
+               Q(ATSPI_ROLE_LAYERED_PANE),
+               Q(ATSPI_ROLE_LIST),
+               Q(ATSPI_ROLE_LIST_ITEM),
+               Q(ATSPI_ROLE_MENU),
+               Q(ATSPI_ROLE_MENU_BAR),
+               Q(ATSPI_ROLE_MENU_ITEM),
+               Q(ATSPI_ROLE_OPTION_PANE),
+               Q(ATSPI_ROLE_PAGE_TAB),
+               Q(ATSPI_ROLE_PAGE_TAB_LIST),
+               Q(ATSPI_ROLE_PANEL),
+               Q(ATSPI_ROLE_PASSWORD_TEXT),
+               Q(ATSPI_ROLE_POPUP_MENU),
+               Q(ATSPI_ROLE_PROGRESS_BAR),
+               Q(ATSPI_ROLE_PUSH_BUTTON),
+               Q(ATSPI_ROLE_RADIO_BUTTON),
+               Q(ATSPI_ROLE_RADIO_MENU_ITEM),
+               Q(ATSPI_ROLE_ROOT_PANE),
+               Q(ATSPI_ROLE_ROW_HEADER),
+               Q(ATSPI_ROLE_SCROLL_BAR),
+               Q(ATSPI_ROLE_SCROLL_PANE),
+               Q(ATSPI_ROLE_SEPARATOR),
+               Q(ATSPI_ROLE_SLIDER),
+               Q(ATSPI_ROLE_SPIN_BUTTON),
+               Q(ATSPI_ROLE_SPLIT_PANE),
+               Q(ATSPI_ROLE_STATUS_BAR),
+               Q(ATSPI_ROLE_TABLE),
+               Q(ATSPI_ROLE_TABLE_CELL),
+               Q(ATSPI_ROLE_TABLE_COLUMN_HEADER),
+               Q(ATSPI_ROLE_TABLE_ROW_HEADER),
+               Q(ATSPI_ROLE_TEAROFF_MENU_ITEM),
+               Q(ATSPI_ROLE_TERMINAL),
+               Q(ATSPI_ROLE_TEXT),
+               Q(ATSPI_ROLE_TOGGLE_BUTTON),
+               Q(ATSPI_ROLE_TOOL_BAR),
+               Q(ATSPI_ROLE_TOOL_TIP),
+               Q(ATSPI_ROLE_TREE),
+               Q(ATSPI_ROLE_TREE_TABLE),
+               Q(ATSPI_ROLE_UNKNOWN),
+               Q(ATSPI_ROLE_VIEWPORT),
+               Q(ATSPI_ROLE_WINDOW),
+               Q(ATSPI_ROLE_EXTENDED),
+               Q(ATSPI_ROLE_HEADER),
+               Q(ATSPI_ROLE_FOOTER),
+               Q(ATSPI_ROLE_PARAGRAPH),
+               Q(ATSPI_ROLE_RULER),
+               Q(ATSPI_ROLE_APPLICATION),
+               Q(ATSPI_ROLE_AUTOCOMPLETE),
+               Q(ATSPI_ROLE_EDITBAR),
+               Q(ATSPI_ROLE_EMBEDDED),
+               Q(ATSPI_ROLE_ENTRY),
+               Q(ATSPI_ROLE_CHART),
+               Q(ATSPI_ROLE_CAPTION),
+               Q(ATSPI_ROLE_DOCUMENT_FRAME),
+               Q(ATSPI_ROLE_HEADING),
+               Q(ATSPI_ROLE_PAGE),
+               Q(ATSPI_ROLE_SECTION),
+               Q(ATSPI_ROLE_REDUNDANT_OBJECT),
+               Q(ATSPI_ROLE_FORM),
+               Q(ATSPI_ROLE_LINK),
+               Q(ATSPI_ROLE_INPUT_METHOD_WINDOW),
+               Q(ATSPI_ROLE_TABLE_ROW),
+               Q(ATSPI_ROLE_TREE_ITEM),
+               Q(ATSPI_ROLE_DOCUMENT_SPREADSHEET),
+               Q(ATSPI_ROLE_DOCUMENT_PRESENTATION),
+               Q(ATSPI_ROLE_DOCUMENT_TEXT),
+               Q(ATSPI_ROLE_DOCUMENT_WEB),
+               Q(ATSPI_ROLE_DOCUMENT_EMAIL),
+               Q(ATSPI_ROLE_COMMENT),
+               Q(ATSPI_ROLE_LIST_BOX),
+               Q(ATSPI_ROLE_GROUPING),
+               Q(ATSPI_ROLE_IMAGE_MAP),
+               Q(ATSPI_ROLE_NOTIFICATION),
+               Q(ATSPI_ROLE_INFO_BAR),
+               Q(ATSPI_ROLE_LEVEL_BAR),
+               Q(ATSPI_ROLE_TITLE_BAR),
+               Q(ATSPI_ROLE_BLOCK_QUOTE),
+               Q(ATSPI_ROLE_AUDIO),
+               Q(ATSPI_ROLE_VIDEO),
+               Q(ATSPI_ROLE_DEFINITION),
+               Q(ATSPI_ROLE_ARTICLE),
+               Q(ATSPI_ROLE_LANDMARK),
+               Q(ATSPI_ROLE_LOG),
+               Q(ATSPI_ROLE_MARQUEE),
+               Q(ATSPI_ROLE_MATH),
+               Q(ATSPI_ROLE_RATING),
+               Q(ATSPI_ROLE_TIMER),
+               Q(ATSPI_ROLE_STATIC),
+               Q(ATSPI_ROLE_MATH_FRACTION),
+               Q(ATSPI_ROLE_MATH_ROOT),
+               Q(ATSPI_ROLE_SUBSCRIPT),
+               Q(ATSPI_ROLE_SUPERSCRIPT),
+               Q(ATSPI_ROLE_LAST_DEFINED),
+       }) {
+               ASSERT(pair.first.substr(0, 6) == "ATSPI_");
+               variables[pair.first.substr(6)] = pair.second;
        }
-};
+}
 
-void threadFunc(StatPtr result, std::unique_ptr<TestExecutor> exec, std::unique_ptr<std::ostream> outputPtr, Dlog dlog)
+static void threadFunc(StatPtr result, std::unique_ptr<BatchExecutor> exec, std::unique_ptr<std::ostream> outputPtr, Dlog dlog)
 {
        EvaluationContext ec(*exec);
        exec->outputStream() << "waiting for context change...\n";
@@ -856,15 +838,15 @@ void threadFunc(StatPtr result, std::unique_ptr<TestExecutor> exec, std::unique_
                };
                auto ttsDlogHandler = dlog.registerCallback([&exec, ttsMainRegex = std::move(ttsMainRegex)](const std::string & txt) {
                        auto h = exec->ttsInfo.lock();
-                       if (h->mode == TestExecutor::TTSInfo::Mode::search) {
+                       if (h->mode == BatchExecutor::TTSInfo::Mode::search) {
                                if (!h->searchLine) {
-                                       h->mode = TestExecutor::TTSInfo::Mode::found;
+                                       h->mode = BatchExecutor::TTSInfo::Mode::found;
                                } else {
                                        std::smatch result;
                                        if (std::regex_search(txt, result, ttsMainRegex)) {
                                                auto sub = result[1].str();
                                                if (std::regex_search(sub, *h->searchLine))
-                                                       h->mode = TestExecutor::TTSInfo::Mode::found;
+                                                       h->mode = BatchExecutor::TTSInfo::Mode::found;
                                        }
                                }
                        }
@@ -958,6 +940,6 @@ Optional<std::thread> runBatch(const std::array<Optional<std::string>, (size_t)u
                *outputPtr << "Parsed source code:\n";
                *outputPtr << os.str() << "\n\n";
        }
-       auto exec = std::make_unique<TestExecutor>(*outputPtr);
+       auto exec = std::make_unique<BatchExecutor>(*outputPtr);
        return std::thread { threadFunc, std::move(result), std::move(exec), std::move(outputPtr), std::move(dlog) };
 }
index e5343e5..66ba870 100644 (file)
 
 #include <string>
 #include <thread>
+#include <regex>
+
 #include "../utils.hpp"
-#include "EvaluationValue.hpp"
 #include "../Optional.hpp"
+#include "../NavigationInterface.hpp"
+#include "EvaluationValue.hpp"
+#include "EvaluationContext.hpp"
+#include "Evaluator.hpp"
 
 template <typename T> class BatchValueOrError
 {
@@ -51,4 +56,60 @@ public:
 
 Optional<std::thread> runBatch(const std::array<Optional<std::string>, (size_t)utils::Argument::_count> &arguments);
 
+class BatchExecutor : public ExecutorInterface
+{
+public:
+       struct ContextInfo {
+               std::shared_ptr<UIElement> root;
+               std::shared_ptr<NavigationElement> navigation;
+               std::string rootName;
+       };
+       struct TTSInfo {
+               Optional<std::regex> searchLine;
+               enum class Mode { ignore, search, found };
+               Mode mode;
+       };
+
+       // NOTE: constructor of TestExecutor must be called on main thread
+       // constructor calls NavigationInterface object, which might be
+       // in progress of updating itself (context change) on main thread
+       BatchExecutor(std::ostream &output);
+       ~BatchExecutor() = default;
+
+       EvaluationValue getVariableByName(const std::string &name) override;
+       std::ostream &outputStream() override;
+
+       std::shared_ptr<UIElement> getVisibleRoot() override;
+       std::shared_ptr<UIElement> convertToUIElement(Point pt) override;
+       std::string getUIElementName(const std::shared_ptr<UIElement> &uiElem) override;
+       std::string getUIElementUniqueId(const std::shared_ptr<UIElement> &uiElem) override;
+       std::shared_ptr<UIElement> convertToUIElement(const std::string &requestedName) override;
+
+       Monitor<TTSInfo> ttsInfo;
+       Monitor<ContextInfo> contextInfo;
+       std::unordered_map<std::string, EvaluationValue> variables;
+
+protected:
+       void registerContextChangeCallback();
+
+       void insertMethods();
+       void insertWaits();
+       void insertActivities();
+       void insertStateConstants();
+       void insertRoleConstants();
+
+       void findByName(const std::vector<AtspiAccessiblePtr> &elems, std::string requestedName, std::function<void(DBus::ValueOrError<std::vector<AtspiAccessiblePtr>>)> callback);
+       void getAllObjects(AtspiAccessiblePtr root, std::function<void(DBus::ValueOrError<std::vector<AtspiAccessiblePtr>>)> callback,
+                                          std::vector<int> roles = {}, std::vector<int> states = {});
+       void makeUIElement(AtspiAccessiblePtr src, std::function<void(DBus::ValueOrError<std::shared_ptr<UIElement>>)> callback);
+       void makeUIElements(std::vector<AtspiAccessiblePtr> sources,
+                                               std::function<void(DBus::ValueOrError<std::vector<std::shared_ptr<UIElement>>>)> callback);
+
+       NavigationInterface::CallbackHandle contextChangedHandle;
+       std::unordered_map<std::string, StatPtr> imports;
+       std::ostream &output;
+};
+
+
+
 #endif