bool MatchResults(DataSource const & dataSource, vector<shared_ptr<MatchingRule>> rules, vector<search::Result> const & actual) { vector<FeatureID> resultIds; for (auto const & a : actual) resultIds.push_back(a.GetFeatureID()); sort(resultIds.begin(), resultIds.end()); vector<string> unexpected; auto removeMatched = [&rules, &unexpected](FeatureType & feature) { for (auto it = rules.begin(); it != rules.end(); ++it) { if ((*it)->Matches(feature)) { rules.erase(it); return; } } unexpected.push_back(feature.DebugString(FeatureType::BEST_GEOMETRY) + " from " + DebugPrint(feature.GetID().m_mwmId)); }; dataSource.ReadFeatures(removeMatched, resultIds); if (rules.empty() && unexpected.empty()) return true; ostringstream os; os << "Unsatisfied rules:" << endl; for (auto const & e : rules) os << " " << DebugPrint(*e) << endl; os << "Unexpected retrieved features:" << endl; for (auto const & u : unexpected) os << " " << u << endl; LOG(LWARNING, (os.str())); return false; }