- Defines Network, StopArea, StopPoints and JourneySections - Loads them from json using the build_from_json method
675 lines
16 KiB
C++
675 lines
16 KiB
C++
#include <gtest/gtest.h>
|
|
#include <gmock/gmock.h>
|
|
|
|
#include "trenesis/network/graph.h"
|
|
#include "trenesis/network/graph_assets.h"
|
|
|
|
using namespace testing;
|
|
|
|
namespace trenesis {
|
|
using stop_area_pair = decltype(trenesis::Network::stop_areas)::value_type;
|
|
using stop_point_pair = decltype(trenesis::StopArea::stop_points)::value_type;
|
|
|
|
namespace matchers {
|
|
template<class... StopPoints>
|
|
auto StopArea(const char* stop_area_id, StopPoints... stop_points) {
|
|
return AllOf(
|
|
Field(
|
|
"key", &stop_area_pair::first, stop_area_id
|
|
),
|
|
Field(
|
|
"value",
|
|
&stop_area_pair::second,
|
|
Pointee(Field("stop_points", &StopArea::stop_points, UnorderedElementsAre(
|
|
Field(
|
|
"key", &stop_point_pair::first, stop_points // Dijon
|
|
)...
|
|
)
|
|
))
|
|
)
|
|
);
|
|
}
|
|
|
|
auto Departure(
|
|
const Network& graph,
|
|
const char* origin_stop_area,
|
|
const char* origin_stop_point,
|
|
const char* destination_stop_area,
|
|
const char* destination_stop_point,
|
|
const char* departure_time,
|
|
const char* arrival_time
|
|
) {
|
|
return AllOf(
|
|
Field(
|
|
"origin", &JourneySection::origin,
|
|
graph.stop_areas.at(origin_stop_area)->stop_points.at(origin_stop_point).get()
|
|
),
|
|
Field(
|
|
"destination", &JourneySection::destination,
|
|
graph.stop_areas.at(destination_stop_area)->stop_points.at(destination_stop_point).get()
|
|
),
|
|
Field(
|
|
"departure_time", &JourneySection::departure_time, departure_time
|
|
),
|
|
Field(
|
|
"arrival_time", &JourneySection::arrival_time, arrival_time
|
|
)
|
|
);
|
|
}
|
|
|
|
template<class... Departures>
|
|
auto DeparturesFromStopPoint(Departures... departures) {
|
|
return Field(
|
|
"value",
|
|
&stop_point_pair::second,
|
|
Pointee(
|
|
Field(
|
|
"departures", &StopPoint::departures, UnorderedElementsAre(
|
|
departures...
|
|
)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
template<class... DeparturesFromStopPoint>
|
|
auto DeparturesFromStopArea(
|
|
DeparturesFromStopPoint... departures_from_stop_point
|
|
) {
|
|
return Pointer(
|
|
Field("stop_points", &StopArea::stop_points, UnorderedElementsAre(
|
|
departures_from_stop_point...
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
using namespace trenesis;
|
|
|
|
/*
|
|
* Builds a graph with a single node to test node parsing.
|
|
*/
|
|
TEST(Network, build_simple_node) {
|
|
const auto graph = trenesis::Network::build_from_json(
|
|
json::parse(single_node_journey),
|
|
json::parse(single_node_stop_points)
|
|
);
|
|
|
|
// Complete stop areas matching is only performed in this test. For the
|
|
// rest of the test, only the structure of the network (i.e. stop points and
|
|
// departures) are tested.
|
|
EXPECT_THAT(graph.stop_areas, UnorderedElementsAre(
|
|
AllOf(
|
|
Field(
|
|
"key",
|
|
&stop_area_pair::first,
|
|
"stop_area:SNCF:87713040"
|
|
),
|
|
Field(
|
|
"value",
|
|
&stop_area_pair::second,
|
|
Pointer(AllOf(
|
|
Field(&trenesis::StopArea::id, "stop_area:SNCF:87713040"),
|
|
Field(&trenesis::StopArea::name, "Dijon"),
|
|
Field(&trenesis::StopArea::label, "Dijon (Dijon)"),
|
|
Field(
|
|
&trenesis::StopArea::coord,
|
|
AllOf(
|
|
Field(&trenesis::Point::longitude, 5.027256),
|
|
Field(&trenesis::Point::latitude, 47.323411)
|
|
)
|
|
),
|
|
Field(&trenesis::StopArea::stop_points, UnorderedElementsAre(
|
|
AllOf(
|
|
Field("key", &stop_point_pair::first, "stop_point:SNCF:87713040:Train"),
|
|
Field(
|
|
"value",
|
|
&stop_point_pair::second,
|
|
Pointer(AllOf(
|
|
Field(&trenesis::StopPoint::id, "stop_point:SNCF:87713040:Train"),
|
|
Field(&trenesis::StopPoint::name, "Dijon"),
|
|
Field(&trenesis::StopPoint::label, "Dijon (Dijon)"),
|
|
Field(
|
|
&trenesis::StopPoint::coord,
|
|
AllOf(
|
|
Field(&trenesis::Point::longitude, 5.027256),
|
|
Field(&trenesis::Point::latitude, 47.323411)
|
|
)
|
|
)
|
|
))
|
|
)
|
|
)
|
|
))
|
|
))
|
|
)
|
|
)
|
|
));
|
|
}
|
|
|
|
/*
|
|
* Builds a linear graph with 3 nodes
|
|
*/
|
|
TEST(Network, build_simple_graph) {
|
|
const auto graph = trenesis::Network::build_from_json(
|
|
json::parse(dijon_cercy_nevers_journey),
|
|
json::parse(dijon_cercy_nevers_stop_points)
|
|
);
|
|
|
|
// Check stop_areas
|
|
EXPECT_THAT(graph.stop_areas, UnorderedElementsAre(
|
|
matchers::StopArea(
|
|
// Dijon
|
|
"stop_area:SNCF:87713040", "stop_point:SNCF:87713040:Train"
|
|
),
|
|
matchers::StopArea(
|
|
// Cercy
|
|
"stop_area:SNCF:87696492", "stop_point:SNCF:87696492:Train"
|
|
),
|
|
matchers::StopArea(
|
|
// Nevers
|
|
"stop_area:SNCF:87696005", "stop_point:SNCF:87696005:Train"
|
|
)
|
|
));
|
|
|
|
// Check departures
|
|
|
|
// Dijon
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87713040"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
matchers::Departure(
|
|
graph,
|
|
// Dijon
|
|
"stop_area:SNCF:87713040",
|
|
"stop_point:SNCF:87713040:Train",
|
|
// Cercy
|
|
"stop_area:SNCF:87696492",
|
|
"stop_point:SNCF:87696492:Train",
|
|
// Departure
|
|
"081200",
|
|
// Arrival
|
|
"095300")
|
|
)
|
|
)
|
|
);
|
|
|
|
// Cercy
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87696492"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
matchers::Departure(
|
|
graph,
|
|
// Cercy
|
|
"stop_area:SNCF:87696492",
|
|
"stop_point:SNCF:87696492:Train",
|
|
// Nevers
|
|
"stop_area:SNCF:87696005",
|
|
"stop_point:SNCF:87696005:Train",
|
|
// Departure
|
|
"095400",
|
|
// Arrival
|
|
"102900"
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
// Nevers
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87696005"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
// None
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
/*
|
|
* Builds a graph with 4 nodes and the following shape:
|
|
*
|
|
* Besançon -- Dole -- Dijon
|
|
* \ /
|
|
* Arc-et-Senans
|
|
* |
|
|
* --Mouchard
|
|
* / |
|
|
* / Pontarlier
|
|
* |
|
|
* Lons-le-Saunier
|
|
*/
|
|
TEST(Network, build_complex_graph) {
|
|
const auto graph = trenesis::Network::build_from_json(
|
|
// This is a simplified extract from /coverage/sncf/vehicle_journeys
|
|
json::parse(besancon_dijon_lons_train_only_journeys),
|
|
json::parse(besancon_dijon_lons_train_only_stop_points)
|
|
);
|
|
|
|
// Check stop_areas
|
|
EXPECT_THAT(graph.stop_areas, UnorderedElementsAre(
|
|
matchers::StopArea(
|
|
// Besançon Viotte
|
|
"stop_area:SNCF:87718007","stop_point:SNCF:87718007:Train"
|
|
),
|
|
matchers::StopArea(
|
|
// Dole
|
|
"stop_area:SNCF:87713412", "stop_point:SNCF:87713412:Train"
|
|
),
|
|
matchers::StopArea(
|
|
// Dijon
|
|
"stop_area:SNCF:87713040", "stop_point:SNCF:87713040:Train"
|
|
),
|
|
matchers::StopArea(
|
|
// Arc-et-senans
|
|
"stop_area:SNCF:87718841", "stop_point:SNCF:87718841:Train"
|
|
),
|
|
matchers::StopArea(
|
|
// Mouchard
|
|
"stop_area:SNCF:87718833", "stop_point:SNCF:87718833:Train"
|
|
),
|
|
matchers::StopArea(
|
|
// Pontarlier
|
|
"stop_area:SNCF:87715003","stop_point:SNCF:87715003:Train"
|
|
),
|
|
matchers::StopArea(
|
|
// Lons-le-Saunier
|
|
"stop_area:SNCF:87718239", "stop_point:SNCF:87718239:Train"
|
|
)
|
|
)
|
|
);
|
|
|
|
// Check departures
|
|
|
|
// Besançon Viotte
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87718007"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
matchers::Departure(
|
|
graph,
|
|
// Besançon
|
|
"stop_area:SNCF:87718007",
|
|
"stop_point:SNCF:87718007:Train",
|
|
// Dole
|
|
"stop_area:SNCF:87713412",
|
|
"stop_point:SNCF:87713412:Train",
|
|
// Departure
|
|
"105600",
|
|
// Arrival
|
|
"112000"
|
|
),
|
|
matchers::Departure(
|
|
graph,
|
|
// Besançon
|
|
"stop_area:SNCF:87718007",
|
|
"stop_point:SNCF:87718007:Train",
|
|
// Arc-et-Senans
|
|
"stop_area:SNCF:87718841",
|
|
"stop_point:SNCF:87718841:Train",
|
|
// Departure
|
|
"165200",
|
|
// Arrival
|
|
"171500"
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
// Dole
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87713412"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
matchers::Departure(
|
|
graph,
|
|
// Dole
|
|
"stop_area:SNCF:87713412",
|
|
"stop_point:SNCF:87713412:Train",
|
|
// Dijon
|
|
"stop_area:SNCF:87713040",
|
|
"stop_point:SNCF:87713040:Train",
|
|
// Departure
|
|
"112200",
|
|
// Arrival
|
|
"115200"
|
|
),
|
|
matchers::Departure(
|
|
graph,
|
|
// Dole
|
|
"stop_area:SNCF:87713412",
|
|
"stop_point:SNCF:87713412:Train",
|
|
// Arc-et-Senans
|
|
"stop_area:SNCF:87718841",
|
|
"stop_point:SNCF:87718841:Train",
|
|
// Departure
|
|
"111400",
|
|
// Arrival
|
|
"113200"
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
// Dijon
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87713040"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
// None
|
|
)
|
|
)
|
|
);
|
|
|
|
// Arc-et-Senans
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87718841"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
matchers::Departure(
|
|
graph,
|
|
// Arc-et-Senans
|
|
"stop_area:SNCF:87718841",
|
|
"stop_point:SNCF:87718841:Train",
|
|
// Mouchard
|
|
"stop_area:SNCF:87718833",
|
|
"stop_point:SNCF:87718833:Train",
|
|
// Departure
|
|
"113300",
|
|
// Arrival
|
|
"113900"
|
|
),
|
|
matchers::Departure(
|
|
graph,
|
|
// Arc-et-Senans
|
|
"stop_area:SNCF:87718841",
|
|
"stop_point:SNCF:87718841:Train",
|
|
// Mouchard
|
|
"stop_area:SNCF:87718833",
|
|
"stop_point:SNCF:87718833:Train",
|
|
// Departure
|
|
"171600",
|
|
// Arrival
|
|
"172100"
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
// Mouchard
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87718833"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
matchers::Departure(
|
|
graph,
|
|
// Mouchard
|
|
"stop_area:SNCF:87718833",
|
|
"stop_point:SNCF:87718833:Train",
|
|
// Pontarlier
|
|
"stop_area:SNCF:87715003",
|
|
"stop_point:SNCF:87715003:Train",
|
|
// Departure
|
|
"114200",
|
|
// Arrival
|
|
"123700"
|
|
),
|
|
matchers::Departure(
|
|
graph,
|
|
// Mouchard
|
|
"stop_area:SNCF:87718833",
|
|
"stop_point:SNCF:87718833:Train",
|
|
// Lons-le-Saunier
|
|
"stop_area:SNCF:87718239",
|
|
"stop_point:SNCF:87718239:Train",
|
|
// Departure
|
|
"172200",
|
|
// Arrival
|
|
"175900"
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
// Pontarlier
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87715003"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
// None
|
|
)
|
|
)
|
|
);
|
|
|
|
// Lons-le-Saunier
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87718239"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
// None
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
/*
|
|
* Builds a graph with 4 nodes and the following shape:
|
|
*
|
|
* Besançon -- Dole -- Dijon
|
|
* \ /
|
|
* Arc-et-Senans
|
|
* | |
|
|
* --Mouchard
|
|
* / |
|
|
* / Pontarlier
|
|
* |
|
|
* Lons-le-Saunier
|
|
*/
|
|
TEST(Network, build_complex_graph_with_long_distance_train) {
|
|
const auto graph = trenesis::Network::build_from_json(
|
|
json::parse(besancon_dijon_lons_journeys),
|
|
json::parse(besancon_dijon_lons_stop_points)
|
|
);
|
|
|
|
// Check stop_areas
|
|
EXPECT_THAT(graph.stop_areas, UnorderedElementsAre(
|
|
matchers::StopArea(
|
|
// Besançon Viotte
|
|
"stop_area:SNCF:87718007",
|
|
"stop_point:SNCF:87718007:Train", "stop_point:SNCF:87718007:LongDistanceTrain"
|
|
),
|
|
matchers::StopArea(
|
|
// Dole
|
|
"stop_area:SNCF:87713412", "stop_point:SNCF:87713412:Train"
|
|
),
|
|
matchers::StopArea(
|
|
// Dijon
|
|
"stop_area:SNCF:87713040", "stop_point:SNCF:87713040:Train"
|
|
),
|
|
matchers::StopArea(
|
|
// Arc-et-senans
|
|
"stop_area:SNCF:87718841",
|
|
"stop_point:SNCF:87718841:Train", "stop_point:SNCF:87718841:LongDistanceTrain"
|
|
),
|
|
matchers::StopArea(
|
|
// Mouchard
|
|
"stop_area:SNCF:87718833",
|
|
"stop_point:SNCF:87718833:Train", "stop_point:SNCF:87718833:LongDistanceTrain"
|
|
),
|
|
matchers::StopArea(
|
|
// Pontarlier
|
|
"stop_area:SNCF:87715003","stop_point:SNCF:87715003:Train"
|
|
),
|
|
matchers::StopArea(
|
|
// Lons-le-Saunier
|
|
"stop_area:SNCF:87718239",
|
|
"stop_point:SNCF:87718239:LongDistanceTrain"
|
|
)
|
|
)
|
|
);
|
|
|
|
// Check departures
|
|
|
|
// Besançon Viotte
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87718007"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
matchers::Departure(
|
|
graph,
|
|
// Besançon
|
|
"stop_area:SNCF:87718007",
|
|
"stop_point:SNCF:87718007:Train",
|
|
// Dole
|
|
"stop_area:SNCF:87713412",
|
|
"stop_point:SNCF:87713412:Train",
|
|
// Departure
|
|
"105600",
|
|
// Arrival
|
|
"112000"
|
|
)
|
|
),
|
|
matchers::DeparturesFromStopPoint(
|
|
matchers::Departure(
|
|
graph,
|
|
// Besançon
|
|
"stop_area:SNCF:87718007",
|
|
"stop_point:SNCF:87718007:LongDistanceTrain",
|
|
// Arc-et-Senans
|
|
"stop_area:SNCF:87718841",
|
|
"stop_point:SNCF:87718841:LongDistanceTrain",
|
|
// Departure
|
|
"165200",
|
|
// Arrival
|
|
"171500"
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
// Dole
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87713412"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
matchers::Departure(
|
|
graph,
|
|
// Dole
|
|
"stop_area:SNCF:87713412",
|
|
"stop_point:SNCF:87713412:Train",
|
|
// Dijon
|
|
"stop_area:SNCF:87713040",
|
|
"stop_point:SNCF:87713040:Train",
|
|
// Departure
|
|
"112200",
|
|
// Arrival
|
|
"115200"
|
|
),
|
|
matchers::Departure(
|
|
graph,
|
|
// Dole
|
|
"stop_area:SNCF:87713412",
|
|
"stop_point:SNCF:87713412:Train",
|
|
// Arc-et-Senans
|
|
"stop_area:SNCF:87718841",
|
|
"stop_point:SNCF:87718841:Train",
|
|
// Departure
|
|
"111400",
|
|
// Arrival
|
|
"113200"
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
// Dijon
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87713040"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
// None
|
|
)
|
|
)
|
|
);
|
|
|
|
// Arc-et-Senans
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87718841"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
matchers::Departure(
|
|
graph,
|
|
// Arc-et-Senans
|
|
"stop_area:SNCF:87718841",
|
|
"stop_point:SNCF:87718841:Train",
|
|
// Mouchard
|
|
"stop_area:SNCF:87718833",
|
|
"stop_point:SNCF:87718833:Train",
|
|
// Departure
|
|
"113300",
|
|
// Arrival
|
|
"113900"
|
|
)
|
|
),
|
|
matchers::DeparturesFromStopPoint(
|
|
matchers::Departure(
|
|
graph,
|
|
// Arc-et-Senans
|
|
"stop_area:SNCF:87718841",
|
|
"stop_point:SNCF:87718841:LongDistanceTrain",
|
|
// Mouchard
|
|
"stop_area:SNCF:87718833",
|
|
"stop_point:SNCF:87718833:LongDistanceTrain",
|
|
// Departure
|
|
"171600",
|
|
// Arrival
|
|
"172100"
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
// Mouchard
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87718833"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
matchers::Departure(
|
|
graph,
|
|
// Mouchard
|
|
"stop_area:SNCF:87718833",
|
|
"stop_point:SNCF:87718833:Train",
|
|
// Pontarlier
|
|
"stop_area:SNCF:87715003",
|
|
"stop_point:SNCF:87715003:Train",
|
|
// Departure
|
|
"114200",
|
|
// Arrival
|
|
"123700"
|
|
)
|
|
),
|
|
matchers::DeparturesFromStopPoint(
|
|
matchers::Departure(
|
|
graph,
|
|
// Mouchard
|
|
"stop_area:SNCF:87718833",
|
|
"stop_point:SNCF:87718833:LongDistanceTrain",
|
|
// Lons-le-Saunier
|
|
"stop_area:SNCF:87718239",
|
|
"stop_point:SNCF:87718239:LongDistanceTrain",
|
|
// Departure
|
|
"172200",
|
|
// Arrival
|
|
"175900"
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
// Pontarlier
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87715003"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
// None
|
|
)
|
|
)
|
|
);
|
|
|
|
// Lons-le-Saunier
|
|
EXPECT_THAT(graph.stop_areas.at("stop_area:SNCF:87718239"),
|
|
matchers::DeparturesFromStopArea(
|
|
matchers::DeparturesFromStopPoint(
|
|
// None
|
|
)
|
|
)
|
|
);
|
|
}
|