11// Include the C library into this C++ test file.
22extern " C" {
3- #include " src/olc.h"
3+ #include " src/olc.h"
44}
55
6+ #include < stdio.h>
7+ #include < stdlib.h>
68#include < chrono>
7- #include < cstring>
89#include < cmath>
10+ #include < cstring>
911#include < fstream>
10- #include < stdio.h>
11- #include < stdlib.h>
1212#include < string>
1313
1414#include " gtest/gtest.h"
@@ -72,14 +72,12 @@ std::vector<DecodingTestData> GetDecodingDataFromCsv() {
7272
7373TEST_P (DecodingChecks, Decode) {
7474 DecodingTestData test_data = GetParam ();
75- OLC_CodeArea expected_area =
76- OLC_CodeArea{
77- OLC_LatLon{test_data.lo_lat_deg , test_data.lo_lng_deg },
78- OLC_LatLon{test_data.hi_lat_deg , test_data.hi_lng_deg },
79- test_data.length };
80- OLC_LatLon expected_center = OLC_LatLon{
81- (test_data.lo_lat_deg + test_data.hi_lat_deg )/2 ,
82- (test_data.lo_lng_deg + test_data.hi_lng_deg )/2 };
75+ OLC_CodeArea expected_area = OLC_CodeArea{
76+ OLC_LatLon{test_data.lo_lat_deg , test_data.lo_lng_deg },
77+ OLC_LatLon{test_data.hi_lat_deg , test_data.hi_lng_deg }, test_data.length };
78+ OLC_LatLon expected_center =
79+ OLC_LatLon{(test_data.lo_lat_deg + test_data.hi_lat_deg ) / 2 ,
80+ (test_data.lo_lng_deg + test_data.hi_lng_deg ) / 2 };
8381 OLC_CodeArea got_area;
8482 OLC_LatLon got_center;
8583 OLC_Decode (test_data.code .c_str (), 0 , &got_area);
@@ -99,12 +97,12 @@ INSTANTIATE_TEST_SUITE_P(OLC_Tests, DecodingChecks,
9997struct EncodingTestData {
10098 double lat_deg;
10199 double lng_deg;
100+ long long int lat_int;
101+ long long int lng_int;
102102 size_t length;
103103 std::string code;
104104};
105105
106- class EncodingChecks : public ::testing::TestWithParam<EncodingTestData> {};
107-
108106const std::string kEncodingTestsFile = " test_data/encoding.csv" ;
109107
110108std::vector<EncodingTestData> GetEncodingDataFromCsv () {
@@ -115,22 +113,72 @@ std::vector<EncodingTestData> GetEncodingDataFromCsv() {
115113 EncodingTestData test_data = {};
116114 test_data.lat_deg = strtod (csv_records[i][0 ].c_str (), nullptr );
117115 test_data.lng_deg = strtod (csv_records[i][1 ].c_str (), nullptr );
118- test_data.length = atoi (csv_records[i][2 ].c_str ());
119- test_data.code = csv_records[i][3 ];
116+ test_data.lat_int = strtoll (csv_records[i][2 ].c_str (), nullptr , 10 );
117+ test_data.lng_int = strtoll (csv_records[i][3 ].c_str (), nullptr , 10 );
118+ test_data.length = atoi (csv_records[i][4 ].c_str ());
119+ test_data.code = csv_records[i][5 ];
120120 data_results.push_back (test_data);
121121 }
122122 return data_results;
123123}
124124
125- TEST_P (EncodingChecks, Encode) {
125+ // TolerantTestParams runs a test with the
126+ struct TolerantTestParams {
127+ double allowed_failure_rate;
128+ std::vector<EncodingTestData> test_data;
129+ };
130+
131+ class TolerantEncodingChecks
132+ : public ::testing::TestWithParam<TolerantTestParams> {};
133+
134+ TEST_P (TolerantEncodingChecks, EncodeDegrees) {
135+ const TolerantTestParams& test_params = GetParam ();
136+ int failure_count = 0 ;
137+
138+ for (EncodingTestData tc : test_params.test_data ) {
139+ OLC_LatLon loc = OLC_LatLon{tc.lat_deg , tc.lng_deg };
140+ char got_code[18 ];
141+ // Encode the test location and make sure we get the expected code.
142+ OLC_Encode (&loc, tc.length , got_code, 18 );
143+ if (tc.code .compare (got_code) != 0 ) {
144+ failure_count ++;
145+ printf (" ENCODING FAILURE: Got: '%s', expected: '%s'\n " , got_code, tc.code .c_str ());
146+ }
147+ }
148+ double actual_failure_rate = double (failure_count) / test_params.test_data .size ();
149+ EXPECT_LE (actual_failure_rate, test_params.allowed_failure_rate )
150+ << " Failure rate " << actual_failure_rate << " exceeds allowed rate " << test_params.allowed_failure_rate ;
151+ }
152+
153+ // Allow a 5% error rate encoding from degree coordinates (because of floating point precision).
154+ INSTANTIATE_TEST_SUITE_P (OLC_Tests, TolerantEncodingChecks,
155+ ::testing::Values (TolerantTestParams{0.05 , GetEncodingDataFromCsv ()}));
156+
157+ class EncodingChecks : public ::testing::TestWithParam<EncodingTestData> {};
158+
159+ TEST_P (EncodingChecks, OLC_EncodeIntegers) {
126160 EncodingTestData test_data = GetParam ();
127- OLC_LatLon loc = OLC_LatLon{test_data.lat_deg , test_data.lng_deg };
161+ OLC_LatLonIntegers loc =
162+ OLC_LatLonIntegers{test_data.lat_int , test_data.lng_int };
128163 char got_code[18 ];
129164 // Encode the test location and make sure we get the expected code.
130- OLC_Encode (&loc, test_data.length , got_code, 18 );
165+ OLC_EncodeIntegers (&loc, test_data.length , got_code, 18 );
131166 EXPECT_EQ (test_data.code , got_code);
132167}
133168
169+ TEST_P (EncodingChecks, OLC_LocationToIntegers) {
170+ EncodingTestData test_data = GetParam ();
171+ OLC_LatLon loc = OLC_LatLon{test_data.lat_deg , test_data.lng_deg };
172+ OLC_LatLonIntegers got;
173+ OLC_LocationToIntegers (&loc, &got);
174+ // Due to floating point precision limitations, we may get values 1 less than
175+ // expected.
176+ EXPECT_LE (got.lat , test_data.lat_int );
177+ EXPECT_GE (got.lat + 1 , test_data.lat_int );
178+ EXPECT_LE (got.lon , test_data.lng_int );
179+ EXPECT_GE (got.lon + 1 , test_data.lng_int );
180+ }
181+
134182INSTANTIATE_TEST_SUITE_P (OLC_Tests, EncodingChecks,
135183 ::testing::ValuesIn (GetEncodingDataFromCsv()));
136184
@@ -211,7 +259,8 @@ TEST_P(ShortCodeChecks, ShortCode) {
211259 // Now extend the code using the reference location and check.
212260 if (test_data.test_type == " B" || test_data.test_type == " R" ) {
213261 char got[18 ];
214- OLC_RecoverNearest (test_data.short_code .c_str (), 0 , &reference_loc, got, 18 );
262+ OLC_RecoverNearest (test_data.short_code .c_str (), 0 , &reference_loc, got,
263+ 18 );
215264 EXPECT_EQ (test_data.full_code , got);
216265 }
217266}
0 commit comments