};
Monitor<ContextInfo> contextInfo;
std::unordered_map<std::string, EvaluationValue> variables;
- std::unordered_map<std::pair<detail::Kind, std::string>, std::function<EvaluationValue(const EvaluationValue &, EvaluationValue)>> setters;
- std::unordered_map<std::pair<detail::Kind, std::string>, std::function<EvaluationValue(const EvaluationValue &)>> getters;
+ std::unordered_map<std::pair<detail::Kind, std::string>, EvaluationValue> setters;
+ std::unordered_map<std::pair<detail::Kind, std::string>, EvaluationValue> getters;
std::ostream &output;
+ EvaluationContext ec;
// 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)
+ TestExecutor(std::ostream &output) : output(output), ec(*this)
{
insertRoleConstants();
insertStateConstants();
[&](EvaluationContext & ec, std::string name) -> EvaluationValue {
auto h = contextInfo.lock();
auto untilMoment = std::chrono::high_resolution_clock::now() + 3000ms;
- AtspiAccessiblePtr previousRoot = nullptr;
- auto success = h.waitForCondition(untilMoment, [&]()
- {
+ if (!h.waitForCondition(untilMoment, [&]() {
return h->rootName == name;
- });
-
- if (!success)
- {
+ }))
throw EvaluationFailure{} << "wait_for_application('" << name << "'): operation timeouted";
- }
return {};
}
};
}, monitor);
}
};
- getters[ { detail::Kind::UIELEMENT, "name" }] = [&](const EvaluationValue & self) -> EvaluationValue {
- auto uiElem = self.as<std::shared_ptr<UIElement>>();
- ASSERT(uiElem->getObject());
- return executeOnMainThread([&]()
- {
- auto root = getVisibleRoot();
- 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)";
- });
- };
- getters[ { detail::Kind::UIELEMENT, "middle_point" }] = [&](const EvaluationValue & self) -> EvaluationValue {
- auto uiElem = self.as<std::shared_ptr<UIElement>>();
- ASSERT(uiElem->getObject());
- return executeOnMainThread([&]()
+ getters[ { detail::Kind::UIELEMENT, "name" }] = detail::UserFunctionType<std::shared_ptr<UIElement>> {
+ [&](EvaluationContext & ec, std::shared_ptr<UIElement> uiElem)
{
- auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
- auto comp = atspi->getComponentInterface(uiElem->getObject());
- if (comp) {
- auto found = atspi->getScreenPosition(comp);
+ ASSERT(uiElem->getObject());
+ return executeOnMainThread([&]() {
+ auto root = getVisibleRoot();
+ auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+ auto found = atspi->getName(uiElem->getObject());
if (found)
- return std::move(*found).getCenterPoint();
- }
- throw EvaluationFailure{} << "failed to get at-spi object's screen position (use dlogutil to get at-spi error message)";
- });
+ return std::move(*found);
+ throw EvaluationFailure{} << "failed to get at-spi object's name (use dlogutil to get at-spi error message)";
+ });
+ }
+ };
+ getters[ { detail::Kind::POINT, "x" }] = detail::UserFunctionType<Point> {
+ [&](EvaluationContext & ec, Point p) -> EvaluationValue {
+ return p.x;
+ }
+ };
+ getters[ { detail::Kind::POINT, "y" }] = detail::UserFunctionType<Point> {
+ [&](EvaluationContext & ec, Point p) -> EvaluationValue {
+ return p.y;
+ }
+ };
+ getters[ { detail::Kind::UIELEMENT, "middle_point" }] = detail::UserFunctionType<std::shared_ptr<UIElement>> {
+ [&](EvaluationContext & ec, std::shared_ptr<UIElement> uiElem) -> EvaluationValue {
+ ASSERT(uiElem->getObject());
+ Optional<Rectangle> result;
+ return executeOnMainThread([&]()
+ {
+ auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+ auto comp = atspi->getComponentInterface(uiElem->getObject());
+ if (comp) {
+ auto found = atspi->getScreenPosition(comp);
+ if (found)
+ return (*found).getCenterPoint();
+ }
+ throw EvaluationFailure{} << "failed to get at-spi object's screen position (use dlogutil to get at-spi error message)";
+ });
+ }
};
for (auto activityName : ActivityFactory::getInstance()->getAllActivityTypes()) {
variables[activityName] = detail::FunctionType::Type{
throw EvaluationFailure{} << "unknown variable '" << name << "'";
}
- EvaluationValue setAttribute(const EvaluationValue &self, const std::string &name, EvaluationValue value)
+ EvaluationValue setAttribute(const EvaluationValue &self, const std::string &name, EvaluationValue value) override
{
auto it = setters.find({ self.kind(), name });
if (it != setters.end()) {
- return it->second(self, std::move(value));
+ return it->second.as<detail::FunctionType>()(ec, self, std::move(value));
}
return ExecutorInterface::setAttribute(self, name, std::move(value));
}
- EvaluationValue getAttribute(const EvaluationValue &self, const std::string &name)
+ EvaluationValue getAttribute(const EvaluationValue &self, const std::string &name) override
{
auto it = getters.find({ self.kind(), name });
if (it != getters.end()) {
- return it->second(self);
+ return it->second.as<detail::FunctionType>()(ec, self);
}
return ExecutorInterface::getAttribute(self, name);
}
auto exec = std::make_unique<TestExecutor>(*outputPtr);
std::thread { [result, exec = std::move(exec), outputPtr = std::move(outputPtr)]()
{
- EvaluationContext ec { *exec };
+ EvaluationContext &ec = exec->ec;
exec->outputStream() << "waiting for context change...\n";
auto until = std::chrono::high_resolution_clock::now() + std::chrono::seconds{ 2 };
while (true) {