Compare commits

..

16 commits

Author SHA1 Message Date
github-actions[bot]
ab59bd57fb
@Osyotr has signed the CLA from Pull Request #21 2024-05-02 00:14:11 +00:00
github-actions[bot]
65cab1b379
@nilsnolde has signed the CLA from Pull Request #18 2023-02-23 12:23:48 +00:00
github-actions[bot]
ebe9cf219c
Creating file for storing CLA Signatures 2023-02-23 12:20:58 +00:00
Khlopkova Olga
b7f7abaaca Fixed yml allowlist 2021-02-10 13:15:41 +03:00
Khlopkova Olga
e833ae1d35 Yml for CLA assistant lite GitHub action. 2021-02-10 13:15:41 +03:00
Khlopkova Olga
c0f696fc52 Added CLA file. 2021-02-10 13:15:41 +03:00
Olga Khlopkova
661b9dc43b
Merge pull request #14 from BaqablH/just_gtfs-improvements
Just gtfs improvements
2021-02-09 09:51:58 +03:00
Victor
ef0c8946b1 Added constructor for Time 2021-02-05 18:38:51 +01:00
Victor
c43b6032d8 Made attributes of Feed protected in order to be able to use inheritance 2021-02-05 18:37:00 +01:00
Victor
574da01e12 Changed underlying types of enum classes 2021-02-05 18:34:46 +01:00
Khlopkova Olga
646bb13f39 Fixed unit-test 2021-02-05 17:57:22 +03:00
Khlopkova Olga
b07393991a Changed default StopLocationType. 2021-02-05 17:57:22 +03:00
Tatiana Yan
f0b74c210e
Merge pull request #11 from mapsme/fix-fare-attributes
Fixed fare attributes.
2021-02-01 15:25:52 +03:00
Khlopkova Olga
a74b71af50 clang-format 2021-02-01 14:37:20 +03:00
Khlopkova Olga
5a6590533c Test for fare attribetes read & write. 2021-02-01 14:37:02 +03:00
Khlopkova Olga
d93723861e Fixed fare attributes 2021-02-01 14:27:31 +03:00
9 changed files with 269 additions and 153 deletions

View file

@ -2,9 +2,9 @@ name: C/C++ CI
on:
push:
branches: [ cpp14, add-* ]
branches: [ master, add-* ]
pull_request:
branches: [ cpp14 ]
branches: [ master ]
jobs:
build:
@ -13,9 +13,6 @@ jobs:
steps:
- uses: actions/checkout@v2
# install dependencies
- name: boost
run: sudo apt-get update && sudo apt-get install -yq libboost1.65-dev
- name: git_actions
run: git submodule update --init --recursive
- name: cmake

34
.github/workflows/cla.yml vendored Normal file
View file

@ -0,0 +1,34 @@
name: "CLA Assistant"
on:
issue_comment:
types: [created]
pull_request_target:
types: [opened,closed,synchronize]
jobs:
CLAssistant:
runs-on: ubuntu-latest
steps:
- name: "CLA Assistant"
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
# Alpha Release
uses: cla-assistant/github-action@v2.1.0-alpha
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PERSONAL_ACCESS_TOKEN : ${{ secrets.PERSONAL_ACCESS_TOKEN }}
with:
path-to-signatures: 'signatures/version1/cla.json'
path-to-document: 'https://github.com/mapsme/just_gtfs/blob/master/MIT_CLA.md'
# branch should not be protected
branch: 'master'
allowlist: mesozoic-drones,tatiana-yan,bot*
#below are the optional inputs - If the optional inputs are not given, then default values will be taken
#remote-organization-name: enter the remote organization name where the signatures should be stored (Default is storing the signatures in the same repository)
#remote-repository-name: enter the remote repository name where the signatures should be stored (Default is storing the signatures in the same repository)
#create-file-commit-message: 'For example: Creating file for storing CLA Signatures'
#signed-commit-message: 'For example: $contributorName has signed the CLA in #$pullRequestNo'
#custom-notsigned-prcomment: 'pull request comment with Introductory message to ask new contributors to sign'
#custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA'
#custom-allsigned-prcomment: 'pull request comment when all contributors has signed, defaults to **CLA Assistant Lite bot** All Contributors have signed the CLA.'

View file

@ -5,13 +5,10 @@ project(just_gtfs LANGUAGES CXX VERSION 0.1)
include_directories(include)
include_directories(doctest/doctest)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED on)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror")
find_package(Boost 1.65 COMPONENTS program_options)
include_directories( ${Boost_INCLUDE_DIR} )
enable_testing()
add_library(just_gtfs INTERFACE)

59
MIT_CLA.md Normal file
View file

@ -0,0 +1,59 @@
## Individual Contributor License Agreement (CLA)
**Thank you for submitting your contributions to this project.**
By signing this CLA, you agree that the following terms apply to all of your past, present and future contributions
to the project.
### License.
You hereby represent that all present, past and future contributions are governed by the
[MIT License](https://opensource.org/licenses/MIT)
copyright statement.
This entails that to the extent possible under law, you transfer all copyright and related or neighboring rights
of the code or documents you contribute to the project itself or its maintainers.
Furthermore you also represent that you have the authority to perform the above waiver
with respect to the entirety of you contributions.
### Moral Rights.
To the fullest extent permitted under applicable law, you hereby waive, and agree not to
assert, all of your “moral rights” in or relating to your contributions for the benefit of the project.
### Third Party Content.
If your Contribution includes or is based on any source code, object code, bug fixes, configuration changes, tools,
specifications, documentation, data, materials, feedback, information or other works of authorship that were not
authored by you (“Third Party Content”) or if you are aware of any third party intellectual property or proprietary
rights associated with your Contribution (“Third Party Rights”),
then you agree to include with the submission of your Contribution full details respecting such Third Party
Content and Third Party Rights, including, without limitation, identification of which aspects of your
Contribution contain Third Party Content or are associated with Third Party Rights, the owner/author of the
Third Party Content and Third Party Rights, where you obtained the Third Party Content, and any applicable
third party license terms or restrictions respecting the Third Party Content and Third Party Rights. For greater
certainty, the foregoing obligations respecting the identification of Third Party Content and Third Party Rights
do not apply to any portion of a Project that is incorporated into your Contribution to that same Project.
### Representations.
You represent that, other than the Third Party Content and Third Party Rights identified by
you in accordance with this Agreement, you are the sole author of your Contributions and are legally entitled
to grant the foregoing licenses and waivers in respect of your Contributions. If your Contributions were
created in the course of your employment with your past or present employer(s), you represent that such
employer(s) has authorized you to make your Contributions on behalf of such employer(s) or such employer
(s) has waived all of their right, title or interest in or to your Contributions.
### Disclaimer.
To the fullest extent permitted under applicable law, your Contributions are provided on an "as is"
basis, without any warranties or conditions, express or implied, including, without limitation, any implied
warranties or conditions of non-infringement, merchantability or fitness for a particular purpose. You are not
required to provide support for your Contributions, except to the extent you desire to provide support.
### No Obligation.
You acknowledge that the maintainers of this project are under no obligation to use or incorporate your contributions
into the project. The decision to use or incorporate your contributions into the project will be made at the
sole discretion of the maintainers or their authorized delegates.

View file

@ -21,32 +21,29 @@
#include <utility>
#include <vector>
#include <boost/optional.hpp>
#include <boost/optional/optional_io.hpp>
namespace gtfs
{
// File names and other entities defined in GTFS----------------------------------------------------
const std::string file_agency = "agency.txt";
const std::string file_stops = "stops.txt";
const std::string file_routes = "routes.txt";
const std::string file_trips = "trips.txt";
const std::string file_stop_times = "stop_times.txt";
const std::string file_calendar = "calendar.txt";
const std::string file_calendar_dates = "calendar_dates.txt";
const std::string file_fare_attributes = "fare_attributes.txt";
const std::string file_fare_rules = "fare_rules.txt";
const std::string file_shapes = "shapes.txt";
const std::string file_frequencies = "frequencies.txt";
const std::string file_transfers = "transfers.txt";
const std::string file_pathways = "pathways.txt";
const std::string file_levels = "levels.txt";
const std::string file_feed_info = "feed_info.txt";
const std::string file_translations = "translations.txt";
const std::string file_attributions = "attributions.txt";
inline const std::string file_agency = "agency.txt";
inline const std::string file_stops = "stops.txt";
inline const std::string file_routes = "routes.txt";
inline const std::string file_trips = "trips.txt";
inline const std::string file_stop_times = "stop_times.txt";
inline const std::string file_calendar = "calendar.txt";
inline const std::string file_calendar_dates = "calendar_dates.txt";
inline const std::string file_fare_attributes = "fare_attributes.txt";
inline const std::string file_fare_rules = "fare_rules.txt";
inline const std::string file_shapes = "shapes.txt";
inline const std::string file_frequencies = "frequencies.txt";
inline const std::string file_transfers = "transfers.txt";
inline const std::string file_pathways = "pathways.txt";
inline const std::string file_levels = "levels.txt";
inline const std::string file_feed_info = "feed_info.txt";
inline const std::string file_translations = "translations.txt";
inline const std::string file_attributions = "attributions.txt";
constexpr char csv_separator = ',';
constexpr char quote = '"';
inline constexpr char csv_separator = ',';
inline constexpr char quote = '"';
// Helper classes and functions---------------------------------------------------------------------
struct InvalidFieldFormat : public std::exception
@ -458,6 +455,7 @@ public:
inline Time() = default;
inline explicit Time(const std::string & raw_time_str);
inline Time(uint16_t hours, uint16_t minutes, uint16_t seconds);
inline Time(size_t seconds);
inline bool is_provided() const;
inline size_t get_total_seconds() const;
inline std::tuple<uint16_t, uint16_t, uint16_t> get_hh_mm_ss() const;
@ -546,6 +544,13 @@ inline Time::Time(uint16_t hours, uint16_t minutes, uint16_t seconds)
time_is_provided = true;
}
inline Time::Time(size_t seconds)
: time_is_provided(true), total_seconds(seconds),
hh(seconds / 3600), mm((seconds % 3600) / 60), ss(seconds % 3600)
{
set_raw_time();
}
inline bool Time::is_provided() const { return time_is_provided; }
inline size_t Time::get_total_seconds() const { return total_seconds; }
@ -647,7 +652,7 @@ using CurrencyCode = std::string;
using LanguageCode = std::string;
// Helper enums for some GTFS fields ---------------------------------------------------------------
enum class StopLocationType
enum class StopLocationType : int8_t
{
StopOrPlatform = 0,
Station = 1,
@ -657,7 +662,7 @@ enum class StopLocationType
};
// The type of transportation used on a route.
enum class RouteType
enum class RouteType : int16_t
{
// GTFS route types
Tram = 0, // Tram, Streetcar, Light rail
@ -755,20 +760,20 @@ enum class RouteType
HorseDrawnCarriage = 1702
};
enum class TripDirectionId
enum class TripDirectionId : bool
{
DefaultDirection = 0, // e.g. outbound
OppositeDirection = 1 // e.g. inbound
};
enum class TripAccess
enum class TripAccess : int8_t
{
NoInfo = 0,
Yes = 1,
No = 2
};
enum class StopTimeBoarding
enum class StopTimeBoarding : int8_t
{
RegularlyScheduled = 0,
No = 1, // Not available
@ -776,31 +781,31 @@ enum class StopTimeBoarding
CoordinateWithDriver = 3 // Must coordinate with driver to arrange
};
enum class StopTimePoint
enum class StopTimePoint : bool
{
Approximate = 0,
Exact = 1
};
enum class CalendarAvailability
enum class CalendarAvailability : bool
{
NotAvailable = 0,
Available = 1
};
enum class CalendarDateException
enum class CalendarDateException : int8_t
{
Added = 1, // Service has been added for the specified date
Removed = 2
};
enum class FarePayment
enum class FarePayment : bool
{
OnBoard = 0,
BeforeBoarding = 1 // Fare must be paid before boarding
};
enum class FareTransfers
enum class FareTransfers : int8_t
{
No = 0, // No transfers permitted on this fare
Once = 1,
@ -808,13 +813,13 @@ enum class FareTransfers
Unlimited = 3
};
enum class FrequencyTripService
enum class FrequencyTripService : bool
{
FrequencyBased = 0, // Frequency-based trips
ScheduleBased = 1 // Schedule-based trips with the exact same headway throughout the day
};
enum class TransferType
enum class TransferType : int8_t
{
Recommended = 0,
Timed = 1,
@ -822,7 +827,7 @@ enum class TransferType
NotPossible = 3
};
enum class PathwayMode
enum class PathwayMode : int8_t
{
Walkway = 1,
Stairs = 2,
@ -833,13 +838,13 @@ enum class PathwayMode
ExitGate = 7
};
enum class PathwayDirection
enum class PathwayDirection : bool
{
Unidirectional = 0,
Bidirectional = 1
};
enum class AttributionRole
enum class AttributionRole : bool
{
No = 0, // Organization doesnt have this role
Yes = 1 // Organization does have this role
@ -1002,6 +1007,14 @@ struct FareAttributesItem
size_t transfer_duration = 0; // Length of time in seconds before a transfer expires
};
inline bool operator==(const FareAttributesItem & lhs, const FareAttributesItem & rhs)
{
return std::tie(lhs.fare_id, lhs.price, lhs.currency_type, lhs.payment_method, lhs.transfers,
lhs.agency_id, lhs.transfer_duration) ==
std::tie(rhs.fare_id, rhs.price, rhs.currency_type, rhs.payment_method, rhs.transfers,
rhs.agency_id, rhs.transfer_duration);
}
// Optional dataset file
struct FareRule
{
@ -1184,28 +1197,28 @@ public:
inline Result write_agencies(const std::string & gtfs_path) const;
inline const Agencies & get_agencies() const;
inline boost::optional<Agency> get_agency(const Id & agency_id) const;
inline std::optional<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 boost::optional<Stop> get_stop(const Id & stop_id) const;
inline std::optional<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 boost::optional<Route> get_route(const Id & route_id) const;
inline std::optional<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 boost::optional<Trip> get_trip(const Id & trip_id) const;
inline std::optional<Trip> get_trip(const Id & trip_id) const;
inline void add_trip(const Trip & trip);
inline Result read_stop_times();
@ -1220,7 +1233,7 @@ public:
inline Result write_calendar(const std::string & gtfs_path) const;
inline const Calendar & get_calendar() const;
inline boost::optional<CalendarItem> get_calendar(const Id & service_id) const;
inline std::optional<CalendarItem> get_calendar(const Id & service_id) const;
inline void add_calendar_item(const CalendarItem & calendar_item);
inline Result read_calendar_dates();
@ -1262,7 +1275,7 @@ public:
inline Result write_transfers(const std::string & gtfs_path) const;
inline const Transfers & get_transfers() const;
inline boost::optional<Transfer> get_transfer(const Id & from_stop_id, const Id & to_stop_id) const;
inline std::optional<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();
@ -1277,7 +1290,7 @@ public:
inline Result write_levels(const std::string & gtfs_path) const;
inline const Levels & get_levels() const;
inline boost::optional<Level> get_level(const Id & level_id) const;
inline std::optional<Level> get_level(const Id & level_id) const;
inline void add_level(const Level & level);
inline Result read_feed_info();
@ -1343,6 +1356,7 @@ private:
inline void write_translations(std::ofstream & out) const;
inline void write_attributions(std::ofstream & out) const;
protected:
std::string gtfs_directory;
Agencies agencies;
@ -1375,74 +1389,57 @@ inline bool ErrorParsingOptionalFile(const Result & res)
inline Result Feed::read_feed()
{
// Read required files:
auto res = read_agencies();
if (res != ResultCode::OK)
return res;
res = read_stops();
if (res != ResultCode::OK)
if (auto res = read_agencies(); res != ResultCode::OK)
return res;
res = read_routes();
if (res != ResultCode::OK)
if (auto res = read_stops(); res != ResultCode::OK)
return res;
res = read_trips();
if (res != ResultCode::OK)
if (auto res = read_routes(); res != ResultCode::OK)
return res;
res = read_stop_times();
if (res != ResultCode::OK)
if (auto res = read_trips(); res != ResultCode::OK)
return res;
if (auto res = read_stop_times(); res != ResultCode::OK)
return res;
// Read conditionally required files:
res = read_calendar();
if (ErrorParsingOptionalFile(res))
if (auto res = read_calendar(); ErrorParsingOptionalFile(res))
return res;
res = read_calendar_dates();
if (ErrorParsingOptionalFile(res))
if (auto res = read_calendar_dates(); ErrorParsingOptionalFile(res))
return res;
// Read optional files:
res = read_shapes();
if (ErrorParsingOptionalFile(res))
if (auto res = read_shapes(); ErrorParsingOptionalFile(res))
return res;
res = read_transfers();
if (ErrorParsingOptionalFile(res))
if (auto res = read_transfers(); ErrorParsingOptionalFile(res))
return res;
res = read_frequencies();
if (ErrorParsingOptionalFile(res))
if (auto res = read_frequencies(); ErrorParsingOptionalFile(res))
return res;
res = read_fare_attributes();
if (ErrorParsingOptionalFile(res))
if (auto res = read_fare_attributes(); ErrorParsingOptionalFile(res))
return res;
res = read_fare_rules();
if (ErrorParsingOptionalFile(res))
if (auto res = read_fare_rules(); ErrorParsingOptionalFile(res))
return res;
res = read_pathways();
if (ErrorParsingOptionalFile(res))
if (auto res = read_pathways(); ErrorParsingOptionalFile(res))
return res;
res = read_levels();
if (ErrorParsingOptionalFile(res))
if (auto res = read_levels(); ErrorParsingOptionalFile(res))
return res;
res = read_attributions();
if (ErrorParsingOptionalFile(res))
if (auto res = read_attributions(); ErrorParsingOptionalFile(res))
return res;
res = read_feed_info();
if (ErrorParsingOptionalFile(res))
if (auto res = read_feed_info(); ErrorParsingOptionalFile(res))
return res;
res = read_translations();
if (ErrorParsingOptionalFile(res))
if (auto res = read_translations(); ErrorParsingOptionalFile(res))
return res;
return ResultCode::OK;
@ -1860,7 +1857,7 @@ inline Result Feed::add_fare_attributes(const ParsedCsvRow & row)
item.currency_type = row.at("currency_type");
set_field(item.payment_method, row, "payment_method", false);
set_field(item.transfers, row, "transfers", false);
set_field(item.transfers, row, "transfers");
// Conditionally optional:
item.agency_id = get_value_or_default(row, "agency_id");
@ -2162,7 +2159,7 @@ inline Result Feed::write_agencies(const std::string & gtfs_path) const
inline const Agencies & Feed::get_agencies() const { return agencies; }
inline boost::optional<Agency> Feed::get_agency(const Id & agency_id) const
inline std::optional<Agency> Feed::get_agency(const Id & agency_id) const
{
// agency id is required when the dataset contains data for multiple agencies,
// otherwise it is optional:
@ -2174,7 +2171,7 @@ inline boost::optional<Agency> Feed::get_agency(const Id & agency_id) const
[&agency_id](const Agency & agency) { return agency.agency_id == agency_id; });
if (it == agencies.end())
return boost::none;
return std::nullopt;
return *it;
}
@ -2195,13 +2192,13 @@ inline Result Feed::write_stops(const std::string & gtfs_path) const
inline const Stops & Feed::get_stops() const { return stops; }
inline boost::optional<Stop> Feed::get_stop(const Id & stop_id) const
inline std::optional<Stop> Feed::get_stop(const Id & stop_id) const
{
const auto it = std::find_if(stops.begin(), stops.end(),
[&stop_id](const Stop & stop) { return stop.stop_id == stop_id; });
if (it == stops.end())
return boost::none;
return std::nullopt;
return *it;
}
@ -2222,14 +2219,14 @@ inline Result Feed::write_routes(const std::string & gtfs_path) const
inline const Routes & Feed::get_routes() const { return routes; }
inline boost::optional<Route> Feed::get_route(const Id & route_id) const
inline std::optional<Route> Feed::get_route(const Id & route_id) const
{
const auto it = std::find_if(routes.begin(), routes.end(), [&route_id](const Route & route) {
return route.route_id == route_id;
});
if (it == routes.end())
return boost::none;
return std::nullopt;
return *it;
}
@ -2250,13 +2247,13 @@ inline Result Feed::write_trips(const std::string & gtfs_path) const
inline const Trips & Feed::get_trips() const { return trips; }
inline boost::optional<Trip> Feed::get_trip(const Id & trip_id) const
inline std::optional<Trip> Feed::get_trip(const Id & trip_id) const
{
const auto it = std::find_if(trips.begin(), trips.end(),
[&trip_id](const Trip & trip) { return trip.trip_id == trip_id; });
if (it == trips.end())
return boost::none;
return std::nullopt;
return *it;
}
@ -2321,7 +2318,7 @@ inline Result Feed::write_calendar(const std::string & gtfs_path) const
inline const Calendar & Feed::get_calendar() const { return calendar; }
inline boost::optional<CalendarItem> Feed::get_calendar(const Id & service_id) const
inline std::optional<CalendarItem> Feed::get_calendar(const Id & service_id) const
{
const auto it = std::find_if(calendar.begin(), calendar.end(),
[&service_id](const CalendarItem & calendar_item) {
@ -2329,7 +2326,7 @@ inline boost::optional<CalendarItem> Feed::get_calendar(const Id & service_id) c
});
if (it == calendar.end())
return boost::none;
return std::nullopt;
return *it;
}
@ -2510,7 +2507,7 @@ inline Result Feed::write_transfers(const std::string & gtfs_path) const
inline const Transfers & Feed::get_transfers() const { return transfers; }
inline boost::optional<Transfer> Feed::get_transfer(const Id & from_stop_id,
inline std::optional<Transfer> Feed::get_transfer(const Id & from_stop_id,
const Id & to_stop_id) const
{
const auto it = std::find_if(
@ -2519,7 +2516,7 @@ inline boost::optional<Transfer> Feed::get_transfer(const Id & from_stop_id,
});
if (it == transfers.end())
return boost::none;
return std::nullopt;
return *it;
}
@ -2578,14 +2575,14 @@ inline Result Feed::write_levels(const std::string & gtfs_path) const
inline const Levels & Feed::get_levels() const { return levels; }
inline boost::optional<Level> Feed::get_level(const Id & level_id) const
inline std::optional<Level> Feed::get_level(const Id & level_id) const
{
const auto it = std::find_if(levels.begin(), levels.end(), [&level_id](const Level & level) {
return level.level_id == level_id;
});
if (it == levels.end())
return boost::none;
return std::nullopt;
return *it;
}
@ -2798,9 +2795,12 @@ inline void Feed::write_fare_attributes(std::ofstream & out) const
for (const auto & attribute : fare_attributes)
{
std::vector<std::string> fields{
wrap(attribute.fare_id), wrap(attribute.price), attribute.currency_type,
wrap(attribute.payment_method), wrap(attribute.transfers), wrap(attribute.agency_id),
wrap(attribute.transfer_duration)};
wrap(attribute.fare_id), wrap(attribute.price), attribute.currency_type,
wrap(attribute.payment_method),
// Here we handle GTFS specification corner case: "The fact that this field can be left
// empty is an exception to the requirement that a Required field must not be empty.":
attribute.transfers == FareTransfers::Unlimited ? "" : wrap(attribute.transfers),
wrap(attribute.agency_id), wrap(attribute.transfer_duration)};
write_joined(out, std::move(fields));
}
}

View file

@ -0,0 +1,20 @@
{
"signedContributors": [
{
"name": "nilsnolde",
"id": 25637358,
"comment_id": 1441674396,
"created_at": "2023-02-23T12:23:33Z",
"repoId": 250751634,
"pullRequestNo": 18
},
{
"name": "Osyotr",
"id": 8740768,
"comment_id": 2089322842,
"created_at": "2024-05-02T00:13:58Z",
"repoId": 250751634,
"pullRequestNo": 21
}
]
}

View file

@ -5,6 +5,6 @@ message(STATUS "CMAKE_CURRENT_BINARY_DIR=" ${CMAKE_CURRENT_BINARY_DIR})
foreach(TEST_SOURCE ${TESTS})
string(REPLACE ".cpp" "" TEST_TARGET "${TEST_SOURCE}")
add_executable(${TEST_TARGET} ${TEST_SOURCE})
target_compile_features(${TEST_TARGET} PRIVATE cxx_std_14)
target_compile_features(${TEST_TARGET} PRIVATE cxx_std_17)
add_test("${TEST_TARGET}" "${TEST_TARGET}" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} --verbose)
endforeach()

View file

@ -1,3 +1,4 @@
fare_id,price,currency_type,payment_method,transfers,transfer_duration
p,1.25,USD,0,0,
a,5.25,USD,0,0,
a,5.25,USD,1,1,
x,20,USD,0,,60

View file

@ -230,11 +230,10 @@ TEST_CASE("Empty container before parsing")
Feed feed("data/non_existing_dir");
REQUIRE(feed.get_agencies().empty());
auto agency = feed.get_agency("agency_10");
const bool no_agency = agency == boost::none;
CHECK_EQ(no_agency, true);
CHECK(!agency);
}
TEST_CASE("Non existing directory")
TEST_CASE("Non existend directory")
{
Feed feed("data/non_existing_dir");
REQUIRE_EQ(feed.read_transfers(), ResultCode::ERROR_FILE_ABSENT);
@ -244,8 +243,7 @@ TEST_CASE("Non existing directory")
TEST_CASE("Transfers")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_transfers().code, ResultCode::OK);
REQUIRE_EQ(feed.read_transfers(), ResultCode::OK);
const auto & transfers = feed.get_transfers();
CHECK_EQ(transfers.size(), 4);
@ -255,8 +253,7 @@ TEST_CASE("Transfers")
CHECK_EQ(transfers[0].min_transfer_time, 70);
const auto & transfer = feed.get_transfer("314", "11");
const bool transfer_exists = transfer != boost::none;
REQUIRE_EQ(transfer_exists, true);
REQUIRE(transfer);
CHECK_EQ(transfer.value().transfer_type, TransferType::Timed);
CHECK_EQ(transfer.value().min_transfer_time, 0);
}
@ -264,14 +261,12 @@ TEST_CASE("Transfers")
TEST_CASE("Calendar")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_calendar().code, ResultCode::OK);
REQUIRE_EQ(feed.read_calendar(), ResultCode::OK);
const auto & calendar = feed.get_calendar();
REQUIRE_EQ(calendar.size(), 2);
const auto & calendar_record = feed.get_calendar("WE");
const bool calendar_exists = calendar_record != boost::none;
REQUIRE_EQ(calendar_exists, true);
REQUIRE(calendar_record);
CHECK_EQ(calendar_record->start_date, Date(2007, 01, 01));
CHECK_EQ(calendar_record->end_date, Date(2010, 12, 31));
@ -288,7 +283,7 @@ TEST_CASE("Calendar")
TEST_CASE("Calendar dates")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_calendar_dates().code, ResultCode::OK);
REQUIRE_EQ(feed.read_calendar_dates(), ResultCode::OK);
const auto & calendar_dates = feed.get_calendar_dates();
REQUIRE_EQ(calendar_dates.size(), 1);
@ -302,7 +297,7 @@ TEST_CASE("Calendar dates")
TEST_CASE("Read GTFS feed")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_feed().code, ResultCode::OK);
REQUIRE_EQ(feed.read_feed(), ResultCode::OK);
CHECK_EQ(feed.get_agencies().size(), 1);
CHECK_EQ(feed.get_routes().size(), 5);
@ -315,7 +310,7 @@ TEST_CASE("Read GTFS feed")
CHECK_EQ(feed.get_attributions().size(), 1);
CHECK_EQ(feed.get_calendar().size(), 2);
CHECK_EQ(feed.get_calendar_dates().size(), 1);
CHECK_EQ(feed.get_fare_attributes().size(), 2);
CHECK_EQ(feed.get_fare_attributes().size(), 3);
CHECK_EQ(feed.get_fare_rules().size(), 4);
CHECK(!feed.get_feed_info().feed_publisher_name.empty());
CHECK_EQ(feed.get_levels().size(), 3);
@ -326,7 +321,7 @@ TEST_CASE("Read GTFS feed")
TEST_CASE("Agency")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_agencies().code, ResultCode::OK);
REQUIRE_EQ(feed.read_agencies(), ResultCode::OK);
const auto & agencies = feed.get_agencies();
REQUIRE_EQ(agencies.size(), 1);
@ -337,8 +332,7 @@ TEST_CASE("Agency")
CHECK_EQ(agencies[0].agency_timezone, "America/Los_Angeles");
const auto agency = feed.get_agency("DTA");
const bool agency_exists = agency != boost::none;
CHECK_EQ(agency_exists, true);
CHECK(agency);
REQUIRE_EQ(feed.write_agencies("data/output_feed"), ResultCode::OK);
Feed feed_copy("data/output_feed");
@ -349,7 +343,7 @@ TEST_CASE("Agency")
TEST_CASE("Routes")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_routes().code, ResultCode::OK);
REQUIRE_EQ(feed.read_routes(), ResultCode::OK);
const auto & routes = feed.get_routes();
REQUIRE_EQ(routes.size(), 5);
@ -363,14 +357,13 @@ TEST_CASE("Routes")
CHECK(routes[0].route_desc.empty());
const auto & route = feed.get_route("AB");
const bool route_exists = route != boost::none;
CHECK_EQ(route_exists, true);
CHECK(route);
}
TEST_CASE("Trips")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_trips().code, ResultCode::OK);
REQUIRE_EQ(feed.read_trips(), ResultCode::OK);
const auto & trips = feed.get_trips();
REQUIRE_EQ(trips.size(), 11);
@ -384,15 +377,14 @@ TEST_CASE("Trips")
CHECK_EQ(trips[0].trip_id, "AB1");
const auto & trip = feed.get_trip("AB1");
const bool trip_exists = trip != boost::none;
REQUIRE_EQ(trip_exists, true);
REQUIRE(trip);
CHECK(trip.value().trip_short_name.empty());
}
TEST_CASE("Stops")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_stops().code, ResultCode::OK);
REQUIRE_EQ(feed.read_stops(), ResultCode::OK);
const auto & stops = feed.get_stops();
REQUIRE_EQ(stops.size(), 9);
@ -407,14 +399,13 @@ TEST_CASE("Stops")
CHECK(stops[0].zone_id.empty());
auto const & stop = feed.get_stop("FUR_CREEK_RES");
const bool stop_exists = stop != boost::none;
REQUIRE_EQ(stop_exists, true);
REQUIRE(stop);
}
TEST_CASE("StopTimes")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_stop_times().code, ResultCode::OK);
REQUIRE_EQ(feed.read_stop_times(), ResultCode::OK);
const auto & stop_times = feed.get_stop_times();
REQUIRE_EQ(stop_times.size(), 28);
@ -435,7 +426,7 @@ TEST_CASE("StopTimes")
TEST_CASE("Shapes")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_shapes().code, ResultCode::OK);
REQUIRE_EQ(feed.read_shapes(), ResultCode::OK);
const auto & shapes = feed.get_shapes();
REQUIRE_EQ(shapes.size(), 8);
@ -452,7 +443,7 @@ TEST_CASE("Shapes")
TEST_CASE("Calendar")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_calendar().code, ResultCode::OK);
REQUIRE_EQ(feed.read_calendar(), ResultCode::OK);
const auto & calendar = feed.get_calendar();
REQUIRE_EQ(calendar.size(), 2);
@ -463,14 +454,13 @@ TEST_CASE("Calendar")
CHECK_EQ(calendar[0].sunday, CalendarAvailability::Available);
const auto & calendar_for_service = feed.get_calendar("FULLW");
const bool calendar_exists = calendar_for_service != boost::none;
CHECK_EQ(calendar_exists, true);
CHECK(calendar_for_service);
}
TEST_CASE("Calendar dates")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_calendar_dates().code, ResultCode::OK);
REQUIRE_EQ(feed.read_calendar_dates(), ResultCode::OK);
const auto & calendar_dates = feed.get_calendar_dates();
REQUIRE_EQ(calendar_dates.size(), 1);
@ -485,7 +475,7 @@ TEST_CASE("Calendar dates")
TEST_CASE("Frequencies")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_frequencies().code, ResultCode::OK);
REQUIRE_EQ(feed.read_frequencies(), ResultCode::OK);
const auto & frequencies = feed.get_frequencies();
REQUIRE_EQ(frequencies.size(), 11);
@ -501,10 +491,10 @@ TEST_CASE("Frequencies")
TEST_CASE("Fare attributes")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_fare_attributes().code, ResultCode::OK);
REQUIRE_EQ(feed.read_fare_attributes(), ResultCode::OK);
const auto & attributes = feed.get_fare_attributes();
REQUIRE_EQ(attributes.size(), 2);
REQUIRE_EQ(attributes.size(), 3);
CHECK_EQ(attributes[0].fare_id, "p");
CHECK_EQ(attributes[0].price, 1.25);
CHECK_EQ(attributes[0].currency_type, "USD");
@ -512,15 +502,34 @@ TEST_CASE("Fare attributes")
CHECK_EQ(attributes[0].transfers, FareTransfers::No);
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].currency_type, "USD");
CHECK_EQ(attributes[1].payment_method, FarePayment::BeforeBoarding);
CHECK_EQ(attributes[1].transfers, FareTransfers::Once);
CHECK_EQ(attributes[1].transfer_duration, 0);
CHECK_EQ(attributes[2].fare_id, "x");
CHECK_EQ(attributes[2].price, 20);
CHECK_EQ(attributes[2].currency_type, "USD");
CHECK_EQ(attributes[2].payment_method, FarePayment::OnBoard);
CHECK_EQ(attributes[2].transfers, FareTransfers::Unlimited);
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(feed.write_fare_attributes("data/output_feed"), ResultCode::OK);
Feed feed_copy("data/output_feed");
REQUIRE_EQ(feed_copy.read_fare_attributes(), 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().code, ResultCode::OK);
REQUIRE_EQ(feed.read_fare_rules(), ResultCode::OK);
const auto & fare_rules = feed.get_fare_rules();
REQUIRE_EQ(fare_rules.size(), 4);
@ -535,7 +544,7 @@ TEST_CASE("Fare rules")
TEST_CASE("Levels")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_levels().code, ResultCode::OK);
REQUIRE_EQ(feed.read_levels(), ResultCode::OK);
const auto & levels = feed.get_levels();
REQUIRE_EQ(levels.size(), 3);
@ -543,8 +552,7 @@ TEST_CASE("Levels")
CHECK_EQ(levels[0].level_index, -1.5);
const auto & level = feed.get_level("U321L2");
const bool level_exists = level != boost::none;
REQUIRE_EQ(level_exists, true);
REQUIRE(level);
CHECK_EQ(level.value().level_index, -2);
CHECK_EQ(level.value().level_name, "Vestibul2");
@ -553,7 +561,7 @@ TEST_CASE("Levels")
TEST_CASE("Pathways")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_pathways().code, ResultCode::OK);
REQUIRE_EQ(feed.read_pathways(), ResultCode::OK);
const auto & pathways = feed.get_pathways();
REQUIRE_EQ(pathways.size(), 3);
@ -574,7 +582,7 @@ TEST_CASE("Pathways")
TEST_CASE("Translations")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_translations().code, ResultCode::OK);
REQUIRE_EQ(feed.read_translations(), ResultCode::OK);
const auto & translations = feed.get_translations();
REQUIRE_EQ(translations.size(), 1);
@ -592,7 +600,7 @@ TEST_CASE("Translations")
TEST_CASE("Attributions")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_attributions().code, ResultCode::OK);
REQUIRE_EQ(feed.read_attributions(), ResultCode::OK);
const auto & attributions = feed.get_attributions();
REQUIRE_EQ(attributions.size(), 1);
@ -609,7 +617,7 @@ TEST_CASE("Attributions")
TEST_CASE("Feed info")
{
Feed feed("data/sample_feed");
REQUIRE_EQ(feed.read_feed_info().code, ResultCode::OK);
REQUIRE_EQ(feed.read_feed_info(), ResultCode::OK);
const auto & info = feed.get_feed_info();
@ -643,7 +651,7 @@ 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").code, ResultCode::OK);
REQUIRE_EQ(feed_for_writing.write_agencies("data/output_feed"), ResultCode::OK);
Feed feed_for_testing("data/output_feed");
REQUIRE_EQ(feed_for_testing.read_agencies(), ResultCode::OK);