From c2b211fef2a0335c2c7b418738e5dc7aa1ba7522 Mon Sep 17 00:00:00 2001 From: Khlopkova Olga Date: Thu, 9 Nov 2023 17:01:39 +0300 Subject: [PATCH] Minor fixes --- README.md | 20 +-- include/just_gtfs/just_gtfs.h | 53 +++--- tests/unit_tests.cpp | 300 ++++++++++++++++++---------------- 3 files changed, 191 insertions(+), 182 deletions(-) diff --git a/README.md b/README.md index e997f63..3e3bc07 100644 --- a/README.md +++ b/README.md @@ -33,26 +33,20 @@ Its main features: Library provides main class for working with GTFS feeds: `gtfs::Feed`. It also provides classes for each of the 17 GTFS entities: `Route`, `Stop`, `Pathway`, `Translation` and others. GTFS csv files are mapped to the corresponding C++ classes. Every GTFS entity can be accessed through `gtfs::Feed` corresponding getters & setters. -:pushpin: All GTFS entities are managed in the same way. So here is the example for working with `agencies`. - -Method of the `Feed` class for reading `agency.txt`: +Method for reading GTFS feed. Path to the feed is specified in the `Feed` constructor: ```c++ -Result read_agencies() -``` - -Method for reading reading not only agencies but all GTFS entities. Path to the feed is specified in the `Feed` constructor: -```c++ -Result read_feed() +Result read_feed(strict=true) ``` +Flag `strict` is used to interrupt feed parsing in case of absence or errors in required GTFS files. If you want to read incomplete feed, set it to `false`. Method for getting reference to the `Agencies` - `std::vector` of all `Agency` objects of the feed: ```c++ const Agencies & get_agencies() ``` -Method for finding agency by its id. Returns `std::optional` so you should check if the result is `std::nullopt`: +Method for finding agency by its id. Returns `Agency` so you should check if the result struct is empty: ```c++ -std::optional get_agency(const Id & agency_id) +const & Agency get_agency(const Id & agency_id) ``` Method for adding agency to the feed: @@ -79,7 +73,7 @@ StopTimes get_stop_times_for_stop(const Id & stop_id) Or you can find stop times for the particular trip: ```c++ -StopTimes get_stop_times_for_trip(const Id & trip_id, bool sort_by_sequence = true) +StopTimesRange get_stop_times_for_trip(const Id & trip_id, bool sort_by_sequence = true) ``` ### Example of reading GTFS feed and working with its stops and routes @@ -110,7 +104,7 @@ GTFS feed can be wholly read from directory as in the example above or you can r :pushpin: Read only `shapes.txt` from the feed and work with shapes: ```c++ Feed feed("~/data/SFMTA/"); -if (feed.read_shapes() == ResultCode::OK) +if (feed.read_feed() == ResultCode::OK) { Shapes all_shapes = feed.get_shapes(); Shape shape = feed.get_shape("9367"); diff --git a/include/just_gtfs/just_gtfs.h b/include/just_gtfs/just_gtfs.h index 06aec45..4bcc216 100644 --- a/include/just_gtfs/just_gtfs.h +++ b/include/just_gtfs/just_gtfs.h @@ -1261,38 +1261,35 @@ class Feed inline Feed() = default; inline explicit Feed(const std::string & gtfs_path); - inline Result read_feed(); + // 'strict' flag is used to interrupt feed parsing in case of absence or errors in + // required files. If you want to read incomplete feed, set it to false. + inline Result read_feed(bool strict=true); inline Result write_feed(const std::string & gtfs_path) const; - inline Result read_agencies(); inline Result write_agencies(const std::string & gtfs_path) const; inline const Agencies & get_agencies() const; inline const Agency & get_agency(const Id & agency_id) const; inline void add_agency(const Agency & agency); - inline Result read_stops(); inline Result write_stops(const std::string & gtfs_path) const; inline const Stops & get_stops() const; inline const Stop & get_stop(const Id & stop_id) const; inline void add_stop(const Stop & stop); - inline Result read_routes(); inline Result write_routes(const std::string & gtfs_path) const; inline const Routes & get_routes() const; inline const Route & get_route(const Id & route_id) const; inline void add_route(const Route & route); - inline Result read_trips(); inline Result write_trips(const std::string & gtfs_path) const; inline const Trips & get_trips() const; inline const Trip & get_trip(const Id & trip_id) const; inline void add_trip(const Trip & trip); - inline Result read_stop_times(); inline Result write_stop_times(const std::string & gtfs_path) const; inline const StopTimes & get_stop_times() const; @@ -1300,56 +1297,48 @@ class Feed inline StopTimesRange get_stop_times_for_trip(const Id & trip_id) const; inline void add_stop_time(const StopTime & stop_time); - inline Result read_calendar(); inline Result write_calendar(const std::string & gtfs_path) const; inline const Calendar & get_calendar() const; inline const CalendarItem & get_calendar_item(const Id & service_id) const; inline void add_calendar_item(const CalendarItem & calendar_item); - inline Result read_calendar_dates(); inline Result write_calendar_dates(const std::string & gtfs_path) const; inline const CalendarDates & get_calendar_dates() const; inline CalendarDatesRange get_calendar_dates(const Id & service_id) const; inline void add_calendar_date(const CalendarDate & calendar_date); - inline Result read_fare_rules(); inline Result write_fare_rules(const std::string & gtfs_path) const; inline const FareRules & get_fare_rules() const; inline FareRulesRange get_fare_rules(const Id & fare_id) const; inline void add_fare_rule(const FareRule & fare_rule); - inline Result read_fare_attributes(); inline Result write_fare_attributes(const std::string & gtfs_path) const; inline const FareAttributes & get_fare_attributes() const; inline FareAttributesRange get_fare_attributes(const Id & fare_id) const; inline void add_fare_attributes(const FareAttributesItem & fare_attributes_item); - inline Result read_shapes(); inline Result write_shapes(const std::string & gtfs_path) const; inline const Shapes & get_shapes() const; inline ShapeRange get_shape(const Id & shape_id) const; inline void add_shape(const ShapePoint & shape); - inline Result read_frequencies(); inline Result write_frequencies(const std::string & gtfs_path) const; inline const Frequencies & get_frequencies() const; inline FrequenciesRange get_frequencies(const Id & trip_id) const; inline void add_frequency(const Frequency & frequency); - inline Result read_transfers(); inline Result write_transfers(const std::string & gtfs_path) const; inline const Transfers & get_transfers() const; inline const Transfer & get_transfer(const Id & from_stop_id, const Id & to_stop_id) const; inline void add_transfer(const Transfer & transfer); - inline Result read_pathways(); inline Result write_pathways(const std::string & gtfs_path) const; inline const Pathways & get_pathways() const; @@ -1357,27 +1346,23 @@ class Feed inline Pathways get_pathways(const Id & from_stop_id, const Id & to_stop_id) const; inline void add_pathway(const Pathway & pathway); - inline Result read_levels(); inline Result write_levels(const std::string & gtfs_path) const; inline const Levels & get_levels() const; inline const Level & get_level(const Id & level_id) const; inline void add_level(const Level & level); - inline Result read_feed_info(); inline Result write_feed_info(const std::string & gtfs_path) const; inline FeedInfo get_feed_info() const; inline void set_feed_info(const FeedInfo & feed_info); - inline Result read_translations(); inline Result write_translations(const std::string & gtfs_path) const; inline const Translations & get_translations() const; inline TranslationsRange get_translations(const Text & table_name) const; inline void add_translation(const Translation & translation); - inline Result read_attributions(); inline Result write_attributions(const std::string & gtfs_path) const; inline const Attributions & get_attributions() const; @@ -1409,6 +1394,24 @@ class Feed inline Result add_translation(const ParsedCsvRow & row); inline Result add_attribution(const ParsedCsvRow & row); + inline Result read_agencies(); + inline Result read_stops(); + inline Result read_routes(); + inline Result read_trips(); + inline Result read_stop_times(); + inline Result read_calendar(); + inline Result read_calendar_dates(); + inline Result read_fare_rules(); + inline Result read_fare_attributes(); + inline Result read_shapes(); + inline Result read_frequencies(); + inline Result read_transfers(); + inline Result read_pathways(); + inline Result read_levels(); + inline Result read_feed_info(); + inline Result read_translations(); + inline Result read_attributions(); + inline void write_agencies(std::ofstream & out) const; inline void write_routes(std::ofstream & out) const; inline void write_shapes(std::ofstream & out) const; @@ -1457,22 +1460,22 @@ inline bool ErrorParsingOptionalFile(const Result & res) return res != ResultCode::OK && res != ResultCode::ERROR_FILE_ABSENT; } -inline Result Feed::read_feed() +inline Result Feed::read_feed(bool strict) { // Read required files: - if (auto res = read_agencies(); res != ResultCode::OK) + if (auto res = read_agencies(); strict && res != ResultCode::OK) return res; - if (auto res = read_stops(); res != ResultCode::OK) + if (auto res = read_stops(); strict && res != ResultCode::OK) return res; - if (auto res = read_routes(); res != ResultCode::OK) + if (auto res = read_routes(); strict && res != ResultCode::OK) return res; - if (auto res = read_trips(); res != ResultCode::OK) + if (auto res = read_trips(); strict && res != ResultCode::OK) return res; - if (auto res = read_stop_times(); res != ResultCode::OK) + if (auto res = read_stop_times(); strict && res != ResultCode::OK) return res; // Read conditionally required files: @@ -2601,7 +2604,7 @@ inline const Transfer & Feed::get_transfer(const Id & from_stop_id, { const auto it = std::lower_bound(transfers.begin(), transfers.end(), "", - [&](const auto & a, const Id & i) + [&](const auto & a, const Id & ) { return a.from_stop_id < from_stop_id || (a.from_stop_id == from_stop_id && a.to_stop_id < to_stop_id); }); if (it == transfers.end() || it->from_stop_id != it->from_stop_id || it->to_stop_id != to_stop_id) diff --git a/tests/unit_tests.cpp b/tests/unit_tests.cpp index a6ec8c0..09570a7 100644 --- a/tests/unit_tests.cpp +++ b/tests/unit_tests.cpp @@ -3,7 +3,11 @@ #include "just_gtfs/just_gtfs.h" +#include + using namespace gtfs; +const std::string test_feed = "data/sample_feed"; +const std::string test_output_feed = "data/output_feed"; TEST_SUITE_BEGIN("Handling time GTFS fields"); TEST_CASE("Time in H:MM:SS format") @@ -230,20 +234,21 @@ TEST_CASE("Empty container before parsing") Feed feed("data/non_existing_dir"); REQUIRE(feed.get_agencies().empty()); auto agency = feed.get_agency("agency_10"); - CHECK(!agency); + const Agency non_existing_agency; + CHECK_EQ(agency, non_existing_agency); } -TEST_CASE("Non existend directory") +TEST_CASE("Non existing directory") { Feed feed("data/non_existing_dir"); - REQUIRE_EQ(feed.read_transfers(), ResultCode::ERROR_FILE_ABSENT); + REQUIRE_EQ(feed.read_feed(), ResultCode::ERROR_FILE_ABSENT); CHECK_EQ(feed.get_transfers().size(), 0); } TEST_CASE("Transfers") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_transfers(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & transfers = feed.get_transfers(); CHECK_EQ(transfers.size(), 4); @@ -253,50 +258,48 @@ TEST_CASE("Transfers") CHECK_EQ(transfers[0].min_transfer_time, 70); const auto & transfer = feed.get_transfer("314", "11"); - REQUIRE(transfer); - CHECK_EQ(transfer.value().transfer_type, TransferType::Timed); - CHECK_EQ(transfer.value().min_transfer_time, 0); + + CHECK_EQ(transfer.transfer_type, TransferType::Timed); + CHECK_EQ(transfer.min_transfer_time, 0); } TEST_CASE("Calendar") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_calendar(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & calendar = feed.get_calendar(); REQUIRE_EQ(calendar.size(), 2); - const auto & calendar_record = feed.get_calendar("WE"); - REQUIRE(calendar_record); + const auto & calendar_record = feed.get_calendar_item("WE"); - CHECK_EQ(calendar_record->start_date, Date(2007, 01, 01)); - CHECK_EQ(calendar_record->end_date, Date(2010, 12, 31)); + CHECK_EQ(calendar_record.start_date, Date(2007, 01, 01)); + CHECK_EQ(calendar_record.end_date, Date(2010, 12, 31)); - CHECK_EQ(calendar_record->monday, CalendarAvailability::NotAvailable); - CHECK_EQ(calendar_record->tuesday, CalendarAvailability::NotAvailable); - CHECK_EQ(calendar_record->wednesday, CalendarAvailability::NotAvailable); - CHECK_EQ(calendar_record->thursday, CalendarAvailability::NotAvailable); - CHECK_EQ(calendar_record->friday, CalendarAvailability::NotAvailable); - CHECK_EQ(calendar_record->saturday, CalendarAvailability::Available); - CHECK_EQ(calendar_record->sunday, CalendarAvailability::Available); + CHECK_EQ(calendar_record.monday, CalendarAvailability::NotAvailable); + CHECK_EQ(calendar_record.tuesday, CalendarAvailability::NotAvailable); + CHECK_EQ(calendar_record.wednesday, CalendarAvailability::NotAvailable); + CHECK_EQ(calendar_record.thursday, CalendarAvailability::NotAvailable); + CHECK_EQ(calendar_record.friday, CalendarAvailability::NotAvailable); + CHECK_EQ(calendar_record.saturday, CalendarAvailability::Available); + CHECK_EQ(calendar_record.sunday, CalendarAvailability::Available); } TEST_CASE("Calendar dates") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_calendar_dates(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & calendar_dates = feed.get_calendar_dates(); REQUIRE_EQ(calendar_dates.size(), 1); - const auto & calendar_record = feed.get_calendar_dates("FULLW"); - REQUIRE(!calendar_record.empty()); + const auto & calendar_records_range = feed.get_calendar_dates("FULLW"); - CHECK_EQ(calendar_record[0].date, Date(2007, 06, 04)); - CHECK_EQ(calendar_record[0].exception_type, CalendarDateException::Removed); + CHECK_EQ(calendar_records_range.first->date, Date(2007, 06, 04)); + CHECK_EQ(calendar_records_range.first->exception_type, CalendarDateException::Removed); } TEST_CASE("Read GTFS feed") { - Feed feed("data/sample_feed"); + Feed feed(test_feed); REQUIRE_EQ(feed.read_feed(), ResultCode::OK); CHECK_EQ(feed.get_agencies().size(), 1); @@ -320,8 +323,8 @@ TEST_CASE("Read GTFS feed") TEST_CASE("Agency") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_agencies(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & agencies = feed.get_agencies(); REQUIRE_EQ(agencies.size(), 1); @@ -332,101 +335,108 @@ TEST_CASE("Agency") CHECK_EQ(agencies[0].agency_timezone, "America/Los_Angeles"); const auto agency = feed.get_agency("DTA"); - CHECK(agency); + CHECK_EQ(agency.agency_name, "Demo Transit Authority"); - REQUIRE_EQ(feed.write_agencies("data/output_feed"), ResultCode::OK); - Feed feed_copy("data/output_feed"); - REQUIRE_EQ(feed_copy.read_agencies(), ResultCode::OK); + REQUIRE_EQ(feed.write_agencies(test_output_feed), ResultCode::OK); + Feed feed_copy(test_output_feed); + REQUIRE_EQ(feed_copy.read_feed(false), ResultCode::OK); CHECK_EQ(agencies, feed_copy.get_agencies()); } TEST_CASE("Routes") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_routes(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & routes = feed.get_routes(); REQUIRE_EQ(routes.size(), 5); - CHECK_EQ(routes[0].route_id, "AB"); - CHECK_EQ(routes[0].agency_id, "DTA"); - CHECK_EQ(routes[0].route_short_name, "10"); - CHECK_EQ(routes[0].route_long_name, "Airport - Bullfrog"); - CHECK_EQ(routes[0].route_type, RouteType::Bus); - CHECK(routes[0].route_text_color.empty()); - CHECK(routes[0].route_color.empty()); - CHECK(routes[0].route_desc.empty()); + const size_t i = 1; + CHECK_EQ(routes[i].route_id, "AB"); + CHECK_EQ(routes[i].agency_id, "DTA"); + CHECK_EQ(routes[i].route_short_name, "10"); + CHECK_EQ(routes[i].route_long_name, "Airport - Bullfrog"); + CHECK_EQ(routes[i].route_type, RouteType::Bus); + CHECK(routes[i].route_text_color.empty()); + CHECK(routes[i].route_color.empty()); + CHECK(routes[i].route_desc.empty()); const auto & route = feed.get_route("AB"); - CHECK(route); + CHECK_EQ(route.agency_id, "DTA"); + CHECK_EQ(route.route_type, RouteType::Bus); } TEST_CASE("Trips") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_trips(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & trips = feed.get_trips(); REQUIRE_EQ(trips.size(), 11); - CHECK_EQ(trips[0].block_id, "1"); - CHECK_EQ(trips[0].route_id, "AB"); - CHECK_EQ(trips[0].direction_id, TripDirectionId::DefaultDirection); - CHECK_EQ(trips[0].trip_headsign, "to Bullfrog"); - CHECK(trips[0].shape_id.empty()); - CHECK_EQ(trips[0].service_id, "FULLW"); - CHECK_EQ(trips[0].trip_id, "AB1"); + const size_t i = 4; + CHECK_EQ(trips[i].block_id, "1"); + CHECK_EQ(trips[i].route_id, "AB"); + CHECK_EQ(trips[i].direction_id, TripDirectionId::DefaultDirection); + CHECK_EQ(trips[i].trip_headsign, "to Bullfrog"); + CHECK(trips[i].shape_id.empty()); + CHECK_EQ(trips[i].service_id, "FULLW"); + CHECK_EQ(trips[i].trip_id, "AB1"); const auto & trip = feed.get_trip("AB1"); - REQUIRE(trip); - CHECK(trip.value().trip_short_name.empty()); + CHECK(trip.trip_short_name.empty()); } TEST_CASE("Stops") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_stops(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & stops = feed.get_stops(); REQUIRE_EQ(stops.size(), 9); - CHECK_EQ(stops[0].stop_lat, 36.425288); - CHECK_EQ(stops[0].stop_lon, -117.133162); - CHECK(stops[0].stop_code.empty()); - CHECK(stops[0].stop_url.empty()); - CHECK_EQ(stops[0].stop_id, "FUR_CREEK_RES"); - CHECK(stops[0].stop_desc.empty()); - CHECK_EQ(stops[0].stop_name, "Furnace Creek Resort (Demo)"); - CHECK_EQ(stops[0].location_type, StopLocationType::StopOrPlatform); - CHECK(stops[0].zone_id.empty()); + size_t i = 5; + CHECK_EQ(stops[i].stop_lat, 36.425288); + CHECK_EQ(stops[i].stop_lon, -117.133162); + CHECK(stops[i].stop_code.empty()); + CHECK(stops[i].stop_url.empty()); + CHECK_EQ(stops[i].stop_id, "FUR_CREEK_RES"); + CHECK(stops[i].stop_desc.empty()); + CHECK_EQ(stops[i].stop_name, "Furnace Creek Resort (Demo)"); + CHECK_EQ(stops[i].location_type, StopLocationType::StopOrPlatform); + CHECK(stops[i].zone_id.empty()); auto const & stop = feed.get_stop("FUR_CREEK_RES"); - REQUIRE(stop); + CHECK_EQ(stop.stop_name, "Furnace Creek Resort (Demo)"); } TEST_CASE("StopTimes") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_stop_times(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & stop_times = feed.get_stop_times(); REQUIRE_EQ(stop_times.size(), 28); - CHECK_EQ(stop_times[0].trip_id, "STBA"); - CHECK_EQ(stop_times[0].arrival_time, Time(06, 00, 00)); - CHECK_EQ(stop_times[0].departure_time, Time(06, 00, 00)); - CHECK_EQ(stop_times[0].stop_id, "STAGECOACH"); - CHECK_EQ(stop_times[0].stop_sequence, 1); - CHECK(stop_times[0].stop_headsign.empty()); - CHECK_EQ(stop_times[0].pickup_type, StopTimeBoarding::RegularlyScheduled); - CHECK_EQ(stop_times[0].drop_off_type, StopTimeBoarding::RegularlyScheduled); + const size_t i = 26; + CHECK_EQ(stop_times[i].trip_id, "STBA"); + CHECK_EQ(stop_times[i].arrival_time, Time(06, 00, 00)); + CHECK_EQ(stop_times[i].departure_time, Time(06, 00, 00)); + CHECK_EQ(stop_times[i].stop_id, "STAGECOACH"); + CHECK_EQ(stop_times[i].stop_sequence, 1); + CHECK(stop_times[i].stop_headsign.empty()); + CHECK_EQ(stop_times[i].pickup_type, StopTimeBoarding::RegularlyScheduled); + CHECK_EQ(stop_times[i].drop_off_type, StopTimeBoarding::RegularlyScheduled); CHECK_EQ(feed.get_stop_times_for_stop("STAGECOACH").size(), 3); - CHECK_EQ(feed.get_stop_times_for_trip("STBA").size(), 2); + + CHECK_EQ(std::distance(feed.get_stop_times_for_trip("STBA").first, + feed.get_stop_times_for_trip("STBA").second), + 2); } TEST_CASE("Shapes") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_shapes(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & shapes = feed.get_shapes(); REQUIRE_EQ(shapes.size(), 8); @@ -437,13 +447,13 @@ TEST_CASE("Shapes") CHECK_EQ(shapes[0].shape_dist_traveled, 12669); const auto & shape = feed.get_shape("10237"); - CHECK_EQ(shape.size(), 4); + CHECK_EQ(std::distance(shape.first, shape.second), 4); } TEST_CASE("Calendar") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_calendar(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & calendar = feed.get_calendar(); REQUIRE_EQ(calendar.size(), 2); @@ -453,14 +463,14 @@ TEST_CASE("Calendar") CHECK_EQ(calendar[0].monday, CalendarAvailability::Available); CHECK_EQ(calendar[0].sunday, CalendarAvailability::Available); - const auto & calendar_for_service = feed.get_calendar("FULLW"); - CHECK(calendar_for_service); + const auto & calendar_for_service = feed.get_calendar_dates("FULLW"); + CHECK_EQ(std::distance(calendar_for_service.first, calendar_for_service.second), 1); } TEST_CASE("Calendar dates") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_calendar_dates(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & calendar_dates = feed.get_calendar_dates(); REQUIRE_EQ(calendar_dates.size(), 1); @@ -468,45 +478,47 @@ TEST_CASE("Calendar dates") CHECK_EQ(calendar_dates[0].date, Date(2007, 06, 04)); CHECK_EQ(calendar_dates[0].exception_type, CalendarDateException::Removed); - const auto & calendar_dates_for_service = feed.get_calendar_dates("FULLW"); - CHECK_EQ(calendar_dates_for_service.size(), 1); + const auto & d = feed.get_calendar_dates("FULLW"); + CHECK_EQ(std::distance(d.first, d.second), 1); } TEST_CASE("Frequencies") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_frequencies(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & frequencies = feed.get_frequencies(); REQUIRE_EQ(frequencies.size(), 11); - CHECK_EQ(frequencies[0].trip_id, "STBA"); - CHECK_EQ(frequencies[0].start_time, Time(6, 00, 00)); - CHECK_EQ(frequencies[0].end_time, Time(22, 00, 00)); - CHECK_EQ(frequencies[0].headway_secs, 1800); + const size_t i = 10; + CHECK_EQ(frequencies[i].trip_id, "STBA"); + CHECK_EQ(frequencies[i].start_time, Time(6, 00, 00)); + CHECK_EQ(frequencies[i].end_time, Time(22, 00, 00)); + CHECK_EQ(frequencies[i].headway_secs, 1800); - const auto & frequencies_for_trip = feed.get_frequencies("CITY1"); - CHECK_EQ(frequencies_for_trip.size(), 5); + const auto & f = feed.get_frequencies("CITY1"); + CHECK_EQ(std::distance(f.first, f.second), 5); } TEST_CASE("Fare attributes") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_fare_attributes(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & attributes = feed.get_fare_attributes(); REQUIRE_EQ(attributes.size(), 3); - CHECK_EQ(attributes[0].fare_id, "p"); - CHECK_EQ(attributes[0].price, 1.25); + + CHECK_EQ(attributes[0].fare_id, "a"); + CHECK_EQ(attributes[0].price, 5.25); CHECK_EQ(attributes[0].currency_type, "USD"); - CHECK_EQ(attributes[0].payment_method, FarePayment::OnBoard); - CHECK_EQ(attributes[0].transfers, FareTransfers::No); + CHECK_EQ(attributes[0].payment_method, FarePayment::BeforeBoarding); + CHECK_EQ(attributes[0].transfers, FareTransfers::Once); CHECK_EQ(attributes[0].transfer_duration, 0); - CHECK_EQ(attributes[1].fare_id, "a"); - CHECK_EQ(attributes[1].price, 5.25); + CHECK_EQ(attributes[1].fare_id, "p"); + CHECK_EQ(attributes[1].price, 1.25); CHECK_EQ(attributes[1].currency_type, "USD"); - CHECK_EQ(attributes[1].payment_method, FarePayment::BeforeBoarding); - CHECK_EQ(attributes[1].transfers, FareTransfers::Once); + CHECK_EQ(attributes[1].payment_method, FarePayment::OnBoard); + CHECK_EQ(attributes[1].transfers, FareTransfers::No); CHECK_EQ(attributes[1].transfer_duration, 0); CHECK_EQ(attributes[2].fare_id, "x"); @@ -517,51 +529,49 @@ TEST_CASE("Fare attributes") CHECK_EQ(attributes[2].transfer_duration, 60); const auto & attributes_for_id = feed.get_fare_attributes("a"); - REQUIRE_EQ(attributes_for_id.size(), 1); - CHECK_EQ(attributes_for_id[0].price, 5.25); + REQUIRE_EQ(std::distance(attributes_for_id.first, attributes_for_id.second), 1); + CHECK_EQ(attributes_for_id.first->price, 5.25); - REQUIRE_EQ(feed.write_fare_attributes("data/output_feed"), ResultCode::OK); - Feed feed_copy("data/output_feed"); - REQUIRE_EQ(feed_copy.read_fare_attributes(), ResultCode::OK); + REQUIRE_EQ(feed.write_fare_attributes(test_output_feed), ResultCode::OK); + Feed feed_copy(test_output_feed); + REQUIRE_EQ(feed_copy.read_feed(false), ResultCode::OK); CHECK_EQ(attributes, feed_copy.get_fare_attributes()); } TEST_CASE("Fare rules") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_fare_rules(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & fare_rules = feed.get_fare_rules(); REQUIRE_EQ(fare_rules.size(), 4); - CHECK_EQ(fare_rules[0].fare_id, "p"); - CHECK_EQ(fare_rules[0].route_id, "AB"); + CHECK_EQ(fare_rules[1].fare_id, "p"); + CHECK_EQ(fare_rules[1].route_id, "AB"); const auto & rules_for_id = feed.get_fare_rules("p"); - REQUIRE_EQ(rules_for_id.size(), 3); - CHECK_EQ(rules_for_id[1].route_id, "STBA"); + CHECK_EQ(std::distance(rules_for_id.first, rules_for_id.second), 3); } TEST_CASE("Levels") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_levels(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & levels = feed.get_levels(); REQUIRE_EQ(levels.size(), 3); - CHECK_EQ(levels[0].level_id, "U321L1"); - CHECK_EQ(levels[0].level_index, -1.5); + CHECK_EQ(levels[1].level_id, "U321L1"); + CHECK_EQ(levels[1].level_index, -1.5); const auto & level = feed.get_level("U321L2"); - REQUIRE(level); - CHECK_EQ(level.value().level_index, -2); - CHECK_EQ(level.value().level_name, "Vestibul2"); + CHECK_EQ(level.level_index, -2); + CHECK_EQ(level.level_name, "Vestibul2"); } TEST_CASE("Pathways") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_pathways(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & pathways = feed.get_pathways(); REQUIRE_EQ(pathways.size(), 3); @@ -574,15 +584,16 @@ TEST_CASE("Pathways") CHECK_EQ(pathways[0].is_bidirectional, PathwayDirection::Bidirectional); const auto & pathways_by_id = feed.get_pathways("T-A01D01"); - REQUIRE_EQ(pathways_by_id.size(), 2); - CHECK_EQ(pathways_by_id[0].is_bidirectional, PathwayDirection::Unidirectional); - CHECK(pathways_by_id[0].reversed_signposted_as.empty()); + + CHECK_EQ(std::distance(pathways_by_id.first, pathways_by_id.second), 2); + CHECK_EQ(pathways_by_id.first->is_bidirectional, PathwayDirection::Unidirectional); + CHECK(pathways_by_id.first->reversed_signposted_as.empty()); } TEST_CASE("Translations") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_translations(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & translations = feed.get_translations(); REQUIRE_EQ(translations.size(), 1); @@ -594,13 +605,14 @@ TEST_CASE("Translations") CHECK(translations[0].record_sub_id.empty()); CHECK(translations[0].field_value.empty()); - CHECK_EQ(feed.get_translations("stop_times").size(), 1); + auto const & t = feed.get_translations("stop_times"); + CHECK_EQ(std::distance(t.first, t.second), 1); } TEST_CASE("Attributions") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_attributions(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & attributions = feed.get_attributions(); REQUIRE_EQ(attributions.size(), 1); @@ -616,8 +628,8 @@ TEST_CASE("Attributions") TEST_CASE("Feed info") { - Feed feed("data/sample_feed"); - REQUIRE_EQ(feed.read_feed_info(), ResultCode::OK); + Feed feed(test_feed); + REQUIRE_EQ(feed.read_feed(), ResultCode::OK); const auto & info = feed.get_feed_info(); @@ -651,10 +663,10 @@ TEST_CASE("Agencies create & save") feed_for_writing.add_agency(agency1); feed_for_writing.add_agency(agency2); - REQUIRE_EQ(feed_for_writing.write_agencies("data/output_feed"), ResultCode::OK); - Feed feed_for_testing("data/output_feed"); + REQUIRE_EQ(feed_for_writing.write_agencies(test_output_feed), ResultCode::OK); + Feed feed_for_testing(test_output_feed); - REQUIRE_EQ(feed_for_testing.read_agencies(), ResultCode::OK); + REQUIRE_EQ(feed_for_testing.read_feed(false), ResultCode::OK); CHECK_EQ(feed_for_writing.get_agencies(), feed_for_testing.get_agencies()); } @@ -666,10 +678,10 @@ TEST_CASE("Shapes create & save") feed_for_writing.add_shape(ShapePoint{"id1", 61.199419, -149.867680, 1, 178}); feed_for_writing.add_shape(ShapePoint{"id2", 61.199972, -149.867731, 2, 416}); - REQUIRE_EQ(feed_for_writing.write_shapes("data/output_feed"), ResultCode::OK); - Feed feed_for_testing("data/output_feed"); + REQUIRE_EQ(feed_for_writing.write_shapes(test_output_feed), ResultCode::OK); + Feed feed_for_testing(test_output_feed); - REQUIRE_EQ(feed_for_testing.read_shapes(), ResultCode::OK); + REQUIRE_EQ(feed_for_testing.read_feed(false), ResultCode::OK); CHECK_EQ(feed_for_testing.get_shapes().size(), 3); } TEST_SUITE_END();