1 #include <boost/test/unit_test.hpp>
2 
3 #include <cmath>
4 
5 #include "coordinates.hpp"
6 #include "equal_json.hpp"
7 #include "fixture.hpp"
8 
9 #include "engine/api/flatbuffers/fbresult_generated.h"
10 #include "osrm/coordinate.hpp"
11 #include "osrm/engine_config.hpp"
12 #include "osrm/exception.hpp"
13 #include "osrm/json_container.hpp"
14 #include "osrm/osrm.hpp"
15 #include "osrm/route_parameters.hpp"
16 #include "osrm/status.hpp"
17 
run_route_json(const osrm::OSRM & osrm,const osrm::RouteParameters & params,osrm::json::Object & json_result,bool use_json_only_api)18 osrm::Status run_route_json(const osrm::OSRM &osrm,
19                             const osrm::RouteParameters &params,
20                             osrm::json::Object &json_result,
21                             bool use_json_only_api)
22 {
23     if (use_json_only_api)
24     {
25         return osrm.Route(params, json_result);
26     }
27     osrm::engine::api::ResultT result = osrm::json::Object();
28     auto rc = osrm.Route(params, result);
29     json_result = result.get<osrm::json::Object>();
30     return rc;
31 }
32 
BOOST_AUTO_TEST_SUITE(route)33 BOOST_AUTO_TEST_SUITE(route)
34 
35 void test_route_same_coordinates_fixture(bool use_json_only_api)
36 {
37     auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");
38 
39     using namespace osrm;
40 
41     RouteParameters params;
42     params.steps = true;
43     params.coordinates.push_back(get_dummy_location());
44     params.coordinates.push_back(get_dummy_location());
45 
46     json::Object json_result;
47     const auto rc = run_route_json(osrm, params, json_result, use_json_only_api);
48     BOOST_CHECK(rc == Status::Ok);
49 
50     // unset snapping dependent hint
51     for (auto &itr : json_result.values["waypoints"].get<json::Array>().values)
52     {
53         // Hint values aren't stable, so blank it out
54         itr.get<json::Object>().values["hint"] = "";
55 
56         // Round value to 6 decimal places for double comparison later
57         itr.get<json::Object>().values["distance"] =
58             round(itr.get<json::Object>().values["distance"].get<json::Number>().value * 1000000);
59     }
60 
61     const auto location = json::Array{{{7.437070}, {43.749248}}};
62 
63     json::Object reference{
64         {{"code", "Ok"},
65          {"waypoints",
66           json::Array{{json::Object{{{"name", "Boulevard du Larvotto"},
67                                      {"location", location},
68                                      {"distance", round(0.137249 * 1000000)},
69                                      {"hint", ""}}},
70                        json::Object{{{"name", "Boulevard du Larvotto"},
71                                      {"location", location},
72                                      {"distance", round(0.137249 * 1000000)},
73                                      {"hint", ""}}}}}},
74          {"routes",
75           json::Array{{json::Object{
76               {{"distance", 0.},
77                {"duration", 0.},
78                {"weight", 0.},
79                {"weight_name", "routability"},
80                {"geometry", "yw_jGupkl@??"},
81                {"legs",
82                 json::Array{{json::Object{
83                     {{"distance", 0.},
84                      {"duration", 0.},
85                      {"weight", 0.},
86                      {"summary", "Boulevard du Larvotto"},
87                      {"steps",
88                       json::Array{{{json::Object{{{"duration", 0.},
89                                                   {"distance", 0.},
90                                                   {"weight", 0.},
91                                                   {"geometry", "yw_jGupkl@??"},
92                                                   {"name", "Boulevard du Larvotto"},
93                                                   {"mode", "driving"},
94                                                   {"driving_side", "right"},
95                                                   {"maneuver",
96                                                    json::Object{{
97                                                        {"location", location},
98                                                        {"bearing_before", 0},
99                                                        {"bearing_after", 238},
100                                                        {"type", "depart"},
101                                                    }}},
102                                                   {"intersections",
103                                                    json::Array{{json::Object{
104                                                        {{"location", location},
105                                                         {"bearings", json::Array{{238}}},
106                                                         {"entry", json::Array{{json::True()}}},
107                                                         {"out", 0}}}}}}}}},
108 
109                                    json::Object{{{"duration", 0.},
110                                                  {"distance", 0.},
111                                                  {"weight", 0.},
112                                                  {"geometry", "yw_jGupkl@"},
113                                                  {"name", "Boulevard du Larvotto"},
114                                                  {"mode", "driving"},
115                                                  {"driving_side", "right"},
116                                                  {"maneuver",
117                                                   json::Object{{{"location", location},
118                                                                 {"bearing_before", 238},
119                                                                 {"bearing_after", 0},
120                                                                 {"type", "arrive"}}}},
121                                                  {"intersections",
122                                                   json::Array{{json::Object{
123                                                       {{"location", location},
124                                                        {"bearings", json::Array{{58}}},
125                                                        {"entry", json::Array{{json::True()}}},
126                                                        {"in", 0}}}}}}
127 
128                                    }}}}}}}}}}}}}}}}};
129 
130     CHECK_EQUAL_JSON(reference, json_result);
131 }
BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture_old_api)132 BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture_old_api)
133 {
134     test_route_same_coordinates_fixture(true);
135 }
BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture_new_api)136 BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture_new_api)
137 {
138     test_route_same_coordinates_fixture(false);
139 }
140 
test_route_same_coordinates(bool use_json_only_api)141 void test_route_same_coordinates(bool use_json_only_api)
142 {
143     auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");
144 
145     using namespace osrm;
146 
147     RouteParameters params;
148     params.steps = true;
149     params.coordinates.push_back(get_dummy_location());
150     params.coordinates.push_back(get_dummy_location());
151     params.coordinates.push_back(get_dummy_location());
152 
153     json::Object json_result;
154     const auto rc = run_route_json(osrm, params, json_result, use_json_only_api);
155     BOOST_CHECK(rc == Status::Ok);
156 
157     const auto code = json_result.values.at("code").get<json::String>().value;
158     BOOST_CHECK_EQUAL(code, "Ok");
159 
160     const auto &waypoints = json_result.values.at("waypoints").get<json::Array>().values;
161     BOOST_CHECK(waypoints.size() == params.coordinates.size());
162 
163     for (const auto &waypoint : waypoints)
164     {
165         const auto &waypoint_object = waypoint.get<json::Object>();
166 
167         // nothing can be said about name, empty or contains name of the street
168         const auto name = waypoint_object.values.at("name").get<json::String>().value;
169         BOOST_CHECK(((void)name, true));
170 
171         const auto location = waypoint_object.values.at("location").get<json::Array>().values;
172         const auto longitude = location[0].get<json::Number>().value;
173         const auto latitude = location[1].get<json::Number>().value;
174         BOOST_CHECK(longitude >= -180. && longitude <= 180.);
175         BOOST_CHECK(latitude >= -90. && latitude <= 90.);
176 
177         const auto hint = waypoint_object.values.at("hint").get<json::String>().value;
178         BOOST_CHECK(!hint.empty());
179     }
180 
181     const auto &routes = json_result.values.at("routes").get<json::Array>().values;
182     BOOST_REQUIRE_GT(routes.size(), 0);
183 
184     for (const auto &route : routes)
185     {
186         const auto &route_object = route.get<json::Object>();
187 
188         const auto distance = route_object.values.at("distance").get<json::Number>().value;
189         BOOST_CHECK_EQUAL(distance, 0);
190 
191         const auto duration = route_object.values.at("duration").get<json::Number>().value;
192         BOOST_CHECK_EQUAL(duration, 0);
193 
194         // geometries=polyline by default
195         const auto geometry = route_object.values.at("geometry").get<json::String>().value;
196         BOOST_CHECK(!geometry.empty());
197 
198         const auto &legs = route_object.values.at("legs").get<json::Array>().values;
199         BOOST_CHECK(!legs.empty());
200 
201         for (const auto &leg : legs)
202         {
203             const auto &leg_object = leg.get<json::Object>();
204 
205             const auto distance = leg_object.values.at("distance").get<json::Number>().value;
206             BOOST_CHECK_EQUAL(distance, 0);
207 
208             const auto duration = leg_object.values.at("duration").get<json::Number>().value;
209             BOOST_CHECK_EQUAL(duration, 0);
210 
211             // nothing can be said about summary, empty or contains human readable summary
212             const auto summary = leg_object.values.at("summary").get<json::String>().value;
213             BOOST_CHECK(((void)summary, true));
214 
215             const auto &steps = leg_object.values.at("steps").get<json::Array>().values;
216             BOOST_CHECK(!steps.empty());
217 
218             std::size_t step_count = 0;
219 
220             for (const auto &step : steps)
221             {
222                 const auto &step_object = step.get<json::Object>();
223 
224                 const auto distance = step_object.values.at("distance").get<json::Number>().value;
225                 BOOST_CHECK_EQUAL(distance, 0);
226 
227                 const auto duration = step_object.values.at("duration").get<json::Number>().value;
228                 BOOST_CHECK_EQUAL(duration, 0);
229 
230                 // geometries=polyline by default
231                 const auto geometry = step_object.values.at("geometry").get<json::String>().value;
232                 BOOST_CHECK(!geometry.empty());
233 
234                 // nothing can be said about name, empty or contains way name
235                 const auto name = step_object.values.at("name").get<json::String>().value;
236                 BOOST_CHECK(((void)name, true));
237 
238                 // nothing can be said about mode, contains mode of transportation
239                 const auto mode = step_object.values.at("mode").get<json::String>().value;
240                 BOOST_CHECK(!name.empty());
241 
242                 const auto &maneuver = step_object.values.at("maneuver").get<json::Object>().values;
243 
244                 const auto type = maneuver.at("type").get<json::String>().value;
245                 BOOST_CHECK(!type.empty());
246 
247                 const auto &intersections =
248                     step_object.values.at("intersections").get<json::Array>().values;
249 
250                 for (auto &intersection : intersections)
251                 {
252                     const auto &intersection_object = intersection.get<json::Object>().values;
253                     const auto location =
254                         intersection_object.at("location").get<json::Array>().values;
255                     const auto longitude = location[0].get<json::Number>().value;
256                     const auto latitude = location[1].get<json::Number>().value;
257                     BOOST_CHECK(longitude >= -180. && longitude <= 180.);
258                     BOOST_CHECK(latitude >= -90. && latitude <= 90.);
259 
260                     const auto &bearings =
261                         intersection_object.at("bearings").get<json::Array>().values;
262                     BOOST_CHECK(!bearings.empty());
263                     const auto &entries = intersection_object.at("entry").get<json::Array>().values;
264                     BOOST_CHECK(bearings.size() == entries.size());
265 
266                     for (const auto &bearing : bearings)
267                         BOOST_CHECK(0. <= bearing.get<json::Number>().value &&
268                                     bearing.get<json::Number>().value <= 360.);
269 
270                     if (step_count > 0)
271                     {
272                         const auto in = intersection_object.at("in").get<json::Number>().value;
273                         BOOST_CHECK(in < bearings.size());
274                     }
275                     if (step_count + 1 < steps.size())
276                     {
277                         const auto out = intersection_object.at("out").get<json::Number>().value;
278                         BOOST_CHECK(out < bearings.size());
279                     }
280                 }
281 
282                 // modifier is optional
283                 // TODO(daniel-j-h):
284 
285                 // exit is optional
286                 // TODO(daniel-j-h):
287                 ++step_count;
288             }
289         }
290     }
291 }
BOOST_AUTO_TEST_CASE(test_route_same_coordinates_old_api)292 BOOST_AUTO_TEST_CASE(test_route_same_coordinates_old_api) { test_route_same_coordinates(true); }
BOOST_AUTO_TEST_CASE(test_route_same_coordinates_new_api)293 BOOST_AUTO_TEST_CASE(test_route_same_coordinates_new_api) { test_route_same_coordinates(false); }
294 
test_route_same_coordinates_no_waypoints(bool use_json_only_api)295 void test_route_same_coordinates_no_waypoints(bool use_json_only_api)
296 {
297     auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");
298 
299     using namespace osrm;
300 
301     RouteParameters params;
302     params.skip_waypoints = true;
303     params.steps = true;
304     params.coordinates.push_back(get_dummy_location());
305     params.coordinates.push_back(get_dummy_location());
306     params.coordinates.push_back(get_dummy_location());
307 
308     json::Object json_result;
309     const auto rc = run_route_json(osrm, params, json_result, use_json_only_api);
310     BOOST_CHECK(rc == Status::Ok);
311 
312     const auto code = json_result.values.at("code").get<json::String>().value;
313     BOOST_CHECK_EQUAL(code, "Ok");
314 
315     BOOST_CHECK(json_result.values.find("waypoints") == json_result.values.end());
316 
317     const auto &routes = json_result.values.at("routes").get<json::Array>().values;
318     BOOST_REQUIRE_GT(routes.size(), 0);
319 
320     for (const auto &route : routes)
321     {
322         const auto &route_object = route.get<json::Object>();
323 
324         const auto distance = route_object.values.at("distance").get<json::Number>().value;
325         BOOST_CHECK_EQUAL(distance, 0);
326 
327         const auto duration = route_object.values.at("duration").get<json::Number>().value;
328         BOOST_CHECK_EQUAL(duration, 0);
329 
330         // geometries=polyline by default
331         const auto geometry = route_object.values.at("geometry").get<json::String>().value;
332         BOOST_CHECK(!geometry.empty());
333 
334         const auto &legs = route_object.values.at("legs").get<json::Array>().values;
335         BOOST_CHECK(!legs.empty());
336 
337         // The rest of legs contents is verified by test_route_same_coordinates
338     }
339 }
BOOST_AUTO_TEST_CASE(test_route_same_coordinates_no_waypoints_old_api)340 BOOST_AUTO_TEST_CASE(test_route_same_coordinates_no_waypoints_old_api)
341 {
342     test_route_same_coordinates_no_waypoints(true);
343 }
BOOST_AUTO_TEST_CASE(test_route_same_coordinates_no_waypoints_new_api)344 BOOST_AUTO_TEST_CASE(test_route_same_coordinates_no_waypoints_new_api)
345 {
346     test_route_same_coordinates_no_waypoints(false);
347 }
348 
test_route_response_for_locations_in_small_component(bool use_json_only_api)349 void test_route_response_for_locations_in_small_component(bool use_json_only_api)
350 {
351     auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");
352 
353     using namespace osrm;
354 
355     const auto locations = get_locations_in_small_component();
356 
357     RouteParameters params;
358     params.coordinates.push_back(locations.at(0));
359     params.coordinates.push_back(locations.at(1));
360     params.coordinates.push_back(locations.at(2));
361 
362     json::Object json_result;
363     const auto rc = run_route_json(osrm, params, json_result, use_json_only_api);
364     BOOST_CHECK(rc == Status::Ok);
365 
366     const auto code = json_result.values.at("code").get<json::String>().value;
367     BOOST_CHECK_EQUAL(code, "Ok");
368 
369     const auto &waypoints = json_result.values.at("waypoints").get<json::Array>().values;
370     BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());
371 
372     for (const auto &waypoint : waypoints)
373     {
374         const auto &waypoint_object = waypoint.get<json::Object>();
375 
376         const auto location = waypoint_object.values.at("location").get<json::Array>().values;
377         const auto longitude = location[0].get<json::Number>().value;
378         const auto latitude = location[1].get<json::Number>().value;
379         BOOST_CHECK(longitude >= -180. && longitude <= 180.);
380         BOOST_CHECK(latitude >= -90. && latitude <= 90.);
381     }
382 }
BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_small_component_old_api)383 BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_small_component_old_api)
384 {
385     test_route_response_for_locations_in_small_component(true);
386 }
BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_small_component_new_api)387 BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_small_component_new_api)
388 {
389     test_route_response_for_locations_in_small_component(false);
390 }
391 
test_route_response_for_locations_in_big_component(bool use_json_only_api)392 void test_route_response_for_locations_in_big_component(bool use_json_only_api)
393 {
394     auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");
395 
396     using namespace osrm;
397 
398     const auto locations = get_locations_in_big_component();
399 
400     RouteParameters params;
401     params.coordinates.push_back(locations.at(0));
402     params.coordinates.push_back(locations.at(1));
403     params.coordinates.push_back(locations.at(2));
404 
405     json::Object json_result;
406     const auto rc = run_route_json(osrm, params, json_result, use_json_only_api);
407     BOOST_CHECK(rc == Status::Ok);
408 
409     const auto code = json_result.values.at("code").get<json::String>().value;
410     BOOST_CHECK_EQUAL(code, "Ok");
411 
412     const auto &waypoints = json_result.values.at("waypoints").get<json::Array>().values;
413     BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());
414 
415     for (const auto &waypoint : waypoints)
416     {
417         const auto &waypoint_object = waypoint.get<json::Object>();
418 
419         const auto location = waypoint_object.values.at("location").get<json::Array>().values;
420         const auto longitude = location[0].get<json::Number>().value;
421         const auto latitude = location[1].get<json::Number>().value;
422         BOOST_CHECK(longitude >= -180. && longitude <= 180.);
423         BOOST_CHECK(latitude >= -90. && latitude <= 90.);
424     }
425 }
BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_big_component_old_api)426 BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_big_component_old_api)
427 {
428     test_route_response_for_locations_in_big_component(true);
429 }
BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_big_component_new_api)430 BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_big_component_new_api)
431 {
432     test_route_response_for_locations_in_big_component(false);
433 }
434 
test_route_response_for_locations_across_components(bool use_json_only_api)435 void test_route_response_for_locations_across_components(bool use_json_only_api)
436 {
437     auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");
438 
439     using namespace osrm;
440 
441     const auto big_component = get_locations_in_big_component();
442     const auto small_component = get_locations_in_small_component();
443 
444     RouteParameters params;
445     params.coordinates.push_back(small_component.at(0));
446     params.coordinates.push_back(big_component.at(0));
447     params.coordinates.push_back(small_component.at(1));
448     params.coordinates.push_back(big_component.at(1));
449 
450     json::Object json_result;
451     const auto rc = run_route_json(osrm, params, json_result, use_json_only_api);
452     BOOST_CHECK(rc == Status::Ok);
453 
454     const auto code = json_result.values.at("code").get<json::String>().value;
455     BOOST_CHECK_EQUAL(code, "Ok");
456 
457     const auto &waypoints = json_result.values.at("waypoints").get<json::Array>().values;
458     BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());
459 
460     for (const auto &waypoint : waypoints)
461     {
462         const auto &waypoint_object = waypoint.get<json::Object>();
463 
464         const auto location = waypoint_object.values.at("location").get<json::Array>().values;
465         const auto longitude = location[0].get<json::Number>().value;
466         const auto latitude = location[1].get<json::Number>().value;
467         BOOST_CHECK(longitude >= -180. && longitude <= 180.);
468         BOOST_CHECK(latitude >= -90. && latitude <= 90.);
469     }
470 }
BOOST_AUTO_TEST_CASE(test_route_response_for_locations_across_components_old_api)471 BOOST_AUTO_TEST_CASE(test_route_response_for_locations_across_components_old_api)
472 {
473     test_route_response_for_locations_across_components(true);
474 }
BOOST_AUTO_TEST_CASE(test_route_response_for_locations_across_components_new_api)475 BOOST_AUTO_TEST_CASE(test_route_response_for_locations_across_components_new_api)
476 {
477     test_route_response_for_locations_across_components(false);
478 }
479 
test_route_user_disables_generating_hints(bool use_json_only_api)480 void test_route_user_disables_generating_hints(bool use_json_only_api)
481 {
482     auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");
483 
484     using namespace osrm;
485 
486     RouteParameters params;
487     params.steps = true;
488     params.coordinates.push_back(get_dummy_location());
489     params.coordinates.push_back(get_dummy_location());
490     params.generate_hints = false;
491 
492     json::Object json_result;
493     const auto rc = run_route_json(osrm, params, json_result, use_json_only_api);
494     BOOST_CHECK(rc == Status::Ok);
495 
496     for (auto waypoint : json_result.values["waypoints"].get<json::Array>().values)
497         BOOST_CHECK_EQUAL(waypoint.get<json::Object>().values.count("hint"), 0);
498 }
BOOST_AUTO_TEST_CASE(test_route_user_disables_generating_hints_old_api)499 BOOST_AUTO_TEST_CASE(test_route_user_disables_generating_hints_old_api)
500 {
501     test_route_user_disables_generating_hints(true);
502 }
BOOST_AUTO_TEST_CASE(test_route_user_disables_generating_hints_new_api)503 BOOST_AUTO_TEST_CASE(test_route_user_disables_generating_hints_new_api)
504 {
505     test_route_user_disables_generating_hints(false);
506 }
507 
speed_annotation_matches_duration_and_distance(bool use_json_only_api)508 void speed_annotation_matches_duration_and_distance(bool use_json_only_api)
509 {
510     auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");
511 
512     using namespace osrm;
513 
514     RouteParameters params;
515     params.annotations_type = RouteParameters::AnnotationsType::Duration |
516                               RouteParameters::AnnotationsType::Distance |
517                               RouteParameters::AnnotationsType::Speed;
518     params.coordinates.push_back(get_dummy_location());
519     params.coordinates.push_back(get_dummy_location());
520 
521     json::Object json_result;
522     const auto rc = run_route_json(osrm, params, json_result, use_json_only_api);
523     BOOST_CHECK(rc == Status::Ok);
524 
525     const auto &routes = json_result.values["routes"].get<json::Array>().values;
526     const auto &legs = routes[0].get<json::Object>().values.at("legs").get<json::Array>().values;
527     const auto &annotation =
528         legs[0].get<json::Object>().values.at("annotation").get<json::Object>();
529     const auto &speeds = annotation.values.at("speed").get<json::Array>().values;
530     const auto &durations = annotation.values.at("duration").get<json::Array>().values;
531     const auto &distances = annotation.values.at("distance").get<json::Array>().values;
532     int length = speeds.size();
533 
534     BOOST_CHECK_EQUAL(length, 1);
535     for (int i = 0; i < length; i++)
536     {
537         auto speed = speeds[i].get<json::Number>().value;
538         auto duration = durations[i].get<json::Number>().value;
539         auto distance = distances[i].get<json::Number>().value;
540         auto calc = std::round(distance / duration * 10.) / 10.;
541         BOOST_CHECK_EQUAL(speed, std::isnan(calc) ? 0 : calc);
542 
543         // Because we route from/to the same location, all annotations should be 0;
544         BOOST_CHECK_EQUAL(speed, 0);
545         BOOST_CHECK_EQUAL(distance, 0);
546         BOOST_CHECK_EQUAL(duration, 0);
547     }
548 }
BOOST_AUTO_TEST_CASE(speed_annotation_matches_duration_and_distance_old_api)549 BOOST_AUTO_TEST_CASE(speed_annotation_matches_duration_and_distance_old_api)
550 {
551     speed_annotation_matches_duration_and_distance(true);
552 }
BOOST_AUTO_TEST_CASE(speed_annotation_matches_duration_and_distance_new_api)553 BOOST_AUTO_TEST_CASE(speed_annotation_matches_duration_and_distance_new_api)
554 {
555     speed_annotation_matches_duration_and_distance(false);
556 }
557 
test_manual_setting_of_annotations_property(bool use_json_only_api)558 void test_manual_setting_of_annotations_property(bool use_json_only_api)
559 {
560     auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");
561 
562     using namespace osrm;
563 
564     RouteParameters params{};
565     params.annotations = true;
566     params.coordinates.push_back(get_dummy_location());
567     params.coordinates.push_back(get_dummy_location());
568 
569     json::Object json_result;
570     const auto rc = run_route_json(osrm, params, json_result, use_json_only_api);
571     BOOST_CHECK(rc == Status::Ok);
572 
573     const auto code = json_result.values.at("code").get<json::String>().value;
574     BOOST_CHECK_EQUAL(code, "Ok");
575 
576     auto annotations = json_result.values["routes"]
577                            .get<json::Array>()
578                            .values[0]
579                            .get<json::Object>()
580                            .values["legs"]
581                            .get<json::Array>()
582                            .values[0]
583                            .get<json::Object>()
584                            .values["annotation"]
585                            .get<json::Object>()
586                            .values;
587     BOOST_CHECK_EQUAL(annotations.size(), 6);
588 }
BOOST_AUTO_TEST_CASE(test_manual_setting_of_annotations_property_old_api)589 BOOST_AUTO_TEST_CASE(test_manual_setting_of_annotations_property_old_api)
590 {
591     test_manual_setting_of_annotations_property(true);
592 }
BOOST_AUTO_TEST_CASE(test_manual_setting_of_annotations_property_new_api)593 BOOST_AUTO_TEST_CASE(test_manual_setting_of_annotations_property_new_api)
594 {
595     test_manual_setting_of_annotations_property(false);
596 }
597 
BOOST_AUTO_TEST_CASE(test_route_serialize_fb)598 BOOST_AUTO_TEST_CASE(test_route_serialize_fb)
599 {
600     auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");
601 
602     using namespace osrm;
603 
604     RouteParameters params;
605     params.steps = true;
606     params.coordinates.push_back(get_dummy_location());
607     params.coordinates.push_back(get_dummy_location());
608     params.coordinates.push_back(get_dummy_location());
609 
610     engine::api::ResultT result = flatbuffers::FlatBufferBuilder();
611     const auto rc = osrm.Route(params, result);
612     BOOST_CHECK(rc == Status::Ok);
613 
614     auto &fb_result = result.get<flatbuffers::FlatBufferBuilder>();
615     auto fb = engine::api::fbresult::GetFBResult(fb_result.GetBufferPointer());
616     BOOST_CHECK(!fb->error());
617 
618     BOOST_CHECK(fb->waypoints() != nullptr);
619     const auto waypoints = fb->waypoints();
620     BOOST_CHECK(waypoints->size() == params.coordinates.size());
621 
622     for (const auto waypoint : *waypoints)
623     {
624         const auto longitude = waypoint->location()->longitude();
625         const auto latitude = waypoint->location()->latitude();
626         BOOST_CHECK(longitude >= -180. && longitude <= 180.);
627         BOOST_CHECK(latitude >= -90. && latitude <= 90.);
628 
629         BOOST_CHECK(!waypoint->hint()->str().empty());
630     }
631 
632     BOOST_CHECK(fb->routes() != nullptr);
633     const auto routes = fb->routes();
634     BOOST_REQUIRE_GT(routes->size(), 0);
635 
636     for (const auto route : *routes)
637     {
638         BOOST_CHECK_EQUAL(route->distance(), 0);
639         BOOST_CHECK_EQUAL(route->duration(), 0);
640 
641         const auto &legs = route->legs();
642         BOOST_CHECK(legs->size() > 0);
643 
644         for (const auto leg : *legs)
645         {
646             BOOST_CHECK_EQUAL(leg->distance(), 0);
647 
648             BOOST_CHECK_EQUAL(leg->duration(), 0);
649 
650             BOOST_CHECK(leg->steps() != nullptr);
651             const auto steps = leg->steps();
652             BOOST_CHECK(steps->size() > 0);
653 
654             std::size_t step_count = 0;
655 
656             for (const auto step : *steps)
657             {
658                 BOOST_CHECK_EQUAL(step->distance(), 0);
659 
660                 BOOST_CHECK_EQUAL(step->duration(), 0);
661 
662                 BOOST_CHECK(step->maneuver() != nullptr);
663 
664                 BOOST_CHECK(step->intersections() != nullptr);
665                 const auto intersections = step->intersections();
666 
667                 for (auto intersection : *intersections)
668                 {
669                     const auto longitude = intersection->location()->longitude();
670                     const auto latitude = intersection->location()->latitude();
671                     BOOST_CHECK(longitude >= -180. && longitude <= 180.);
672                     BOOST_CHECK(latitude >= -90. && latitude <= 90.);
673 
674                     BOOST_CHECK(intersection->bearings() != nullptr);
675                     const auto bearings = intersection->bearings();
676                     BOOST_CHECK(bearings->size() > 0);
677 
678                     for (const auto bearing : *bearings)
679                         BOOST_CHECK(0. <= bearing && bearing <= 360.);
680 
681                     if (step_count > 0)
682                     {
683                         BOOST_CHECK(intersection->in_bearing() < bearings->size());
684                     }
685                     if (step_count + 1 < steps->size())
686                     {
687                         BOOST_CHECK(intersection->out_bearing() < bearings->size());
688                     }
689                 }
690                 ++step_count;
691             }
692         }
693     }
694 }
695 
BOOST_AUTO_TEST_CASE(test_route_serialize_fb_skip_waypoints)696 BOOST_AUTO_TEST_CASE(test_route_serialize_fb_skip_waypoints)
697 {
698     auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");
699 
700     using namespace osrm;
701 
702     RouteParameters params;
703     params.skip_waypoints = true;
704     params.steps = true;
705     params.coordinates.push_back(get_dummy_location());
706     params.coordinates.push_back(get_dummy_location());
707     params.coordinates.push_back(get_dummy_location());
708 
709     engine::api::ResultT result = flatbuffers::FlatBufferBuilder();
710     const auto rc = osrm.Route(params, result);
711     BOOST_CHECK(rc == Status::Ok);
712 
713     auto &fb_result = result.get<flatbuffers::FlatBufferBuilder>();
714     auto fb = engine::api::fbresult::GetFBResult(fb_result.GetBufferPointer());
715     BOOST_CHECK(!fb->error());
716 
717     BOOST_CHECK(fb->waypoints() == nullptr);
718 
719     BOOST_CHECK(fb->routes() != nullptr);
720     const auto routes = fb->routes();
721     BOOST_REQUIRE_GT(routes->size(), 0);
722 
723     for (const auto route : *routes)
724     {
725         BOOST_CHECK_EQUAL(route->distance(), 0);
726         BOOST_CHECK_EQUAL(route->duration(), 0);
727 
728         const auto &legs = route->legs();
729         BOOST_CHECK(legs->size() > 0);
730 
731         // Rest of the content is verified by test_route_serialize_fb
732     }
733 }
734 
735 BOOST_AUTO_TEST_SUITE_END()
736