[tests] Fix distance formatting tests using system locale #6470
|
@ -10,6 +10,7 @@ set(SRC
|
|||
jansson_test.cpp
|
||||
language_test.cpp
|
||||
local_country_file_tests.cpp
|
||||
locale_utils.cpp
|
||||
location_test.cpp
|
||||
measurement_tests.cpp
|
||||
platform_test.cpp
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
|
||||
#include "platform/distance.hpp"
|
||||
#include "platform/measurement_utils.hpp"
|
||||
#include "platform/platform_tests/locale_utils.hpp"
|
||||
#include "platform/settings.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace platform
|
||||
{
|
||||
std::string MakeDistanceStr(std::string const & value, std::string const & unit)
|
||||
|
@ -65,6 +69,8 @@ UNIT_TEST(Distance_CreateFormatted)
|
|||
|
||||
UNIT_TEST(Distance_CreateAltitudeFormatted)
|
||||
{
|
||||
std::string groupSep = GetSystemGroupSeparator();
|
||||
|
||||
{
|
||||
ScopedSettings const guard(measurement_utils::Units::Metric);
|
||||
|
||||
|
@ -78,12 +84,12 @@ UNIT_TEST(Distance_CreateAltitudeFormatted)
|
|||
{
|
||||
ScopedSettings const guard(measurement_utils::Units::Metric);
|
||||
|
||||
TEST_EQUAL(Distance::FormatAltitude(12345), MakeDistanceStr("12,345", "m"), ());
|
||||
TEST_EQUAL(Distance::FormatAltitude(12345), MakeDistanceStr("12" + groupSep + "345", "m"), ());
|
||||
}
|
||||
{
|
||||
ScopedSettings const guard(measurement_utils::Units::Imperial);
|
||||
|
||||
gpesquero
commented
Hi @biodranik: I'm afraid that with the current implementation, we may not be able to test the The main reason is that this function calls the We could change the behavior of the Hi @biodranik: I'm afraid that with the current implementation, we may not be able to test the `Distance::FormatAltitude()` function for different locales.
The main reason is that this function calls the `measurement_utils::ToStringPrecision()` function, which uses a static variable to store the locale to use. This locale is therefore updated only in the first iteration, so if we change the locale during the tests, it won't have any effect.
We could change the behavior of the `measurement_utils::ToStringPrecision()` function by removing this static variable, but that would lead to a worse runtime performance.
gpesquero
commented
@biodranik , @vng: PTAL @biodranik , @vng: PTAL
|
||||
TEST_EQUAL(Distance::FormatAltitude(10000), MakeDistanceStr("32,808", "ft"), ());
|
||||
TEST_EQUAL(Distance::FormatAltitude(10000), MakeDistanceStr("32" + groupSep + "808", "ft"), ());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,6 +177,8 @@ UNIT_TEST(Distance_To)
|
|||
|
||||
UNIT_TEST(Distance_ToPlatformUnitsFormatted)
|
||||
{
|
||||
std::string decSep = GetSystemDecimalSeparator();
|
||||
|
||||
{
|
||||
ScopedSettings const guard(measurement_utils::Units::Metric);
|
||||
|
||||
|
@ -207,8 +215,8 @@ UNIT_TEST(Distance_ToPlatformUnitsFormatted)
|
|||
|
||||
TEST_EQUAL(newDistance.GetUnits(), Distance::Units::Miles, (d.ToString()));
|
||||
TEST_ALMOST_EQUAL_ULPS(newDistance.GetDistance(), 6.8, (d.ToString()));
|
||||
TEST_EQUAL(newDistance.GetDistanceString(), "6.8", (d.ToString()));
|
||||
TEST_EQUAL(newDistance.ToString(), MakeDistanceStr("6.8", "mi"), (d.ToString()));
|
||||
TEST_EQUAL(newDistance.GetDistanceString(), "6" + decSep + "8", (d.ToString()));
|
||||
TEST_EQUAL(newDistance.ToString(), MakeDistanceStr("6" + decSep + "8", "mi"), (d.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,6 +348,8 @@ UNIT_TEST(Distance_FormattedDistance)
|
|||
{Distance(999'999, Units::Feet), 189, Units::Miles, "189", MakeDistanceStr("189", "mi")},
|
||||
};
|
||||
|
||||
Locale loc = GetCurrentLocale();
|
||||
|
||||
// clang-format on
|
||||
for (TestData const & data : testData)
|
||||
{
|
||||
|
@ -349,8 +359,8 @@ UNIT_TEST(Distance_FormattedDistance)
|
|||
{
|
||||
TEST_ALMOST_EQUAL_ULPS(d.GetDistance(), data.formattedDistance, (data.distance));
|
||||
TEST_EQUAL(d.GetUnits(), data.formattedUnits, (data.distance));
|
||||
TEST_EQUAL(d.GetDistanceString(), data.formattedDistanceString, (data.distance));
|
||||
TEST_EQUAL(d.ToString(), data.formattedString, (data.distance));
|
||||
TEST_EQUAL(d.GetDistanceString(), LocalizeValueString(data.formattedDistanceString, loc), (data.distance));
|
||||
TEST_EQUAL(d.ToString(), LocalizeValueString(data.formattedString, loc), (data.distance));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
72
platform/platform_tests/locale_utils.cpp
Normal file
|
@ -0,0 +1,72 @@
|
|||
#include "platform/locale.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace platform;
|
||||
|
||||
namespace platform
|
||||
{
|
||||
std::string GetSystemDecimalSeparator()
|
||||
{
|
||||
Locale loc = GetCurrentLocale();
|
||||
|
||||
return loc.m_decimalSeparator;
|
||||
}
|
||||
|
||||
std::string GetSystemGroupSeparator()
|
||||
{
|
||||
Locale loc = GetCurrentLocale();
|
||||
|
||||
return loc.m_groupingSeparator;
|
||||
}
|
||||
|
||||
std::string ReplaceGroupingSeparators(std::string const & valueString, std::string const & groupingSeparator)
|
||||
{
|
||||
std::string out(valueString);
|
||||
|
||||
if (groupingSeparator == ",")
|
||||
return out;
|
||||
|
||||
size_t pos;
|
||||
|
||||
while((pos = out.find(",")) != std::string::npos)
|
||||
out.replace(pos, 1, groupingSeparator);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string ReplaceDecimalSeparator(std::string const & valueString, std::string const & decimalSeparator)
|
||||
{
|
||||
std::string out(valueString);
|
||||
|
||||
if (decimalSeparator == ".")
|
||||
return out;
|
||||
|
||||
size_t pos = valueString.find(".");
|
||||
|
||||
if (pos != std::string::npos)
|
||||
out.replace(pos, 1, decimalSeparator);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string LocalizeValueString(std::string const & valueString, Locale const & loc)
|
||||
{
|
||||
std::string out;
|
||||
|
||||
if (valueString.find(".") != std::string::npos)
|
||||
![]() This looks hacky. Why is the decimal point always replaced? Is the input always in the US locale? Generally, can the code be simplified? This looks hacky. Why is the decimal point always replaced? Is the input always in the US locale?
Generally, can the code be simplified?
|
||||
{
|
||||
// String contains a value with decimal separator.
|
||||
out = ReplaceDecimalSeparator(valueString, loc.m_decimalSeparator);
|
||||
}
|
||||
else if (valueString.find(",") != std::string::npos)
|
||||
{
|
||||
// String contains a value with grouping separator.
|
||||
out = ReplaceGroupingSeparators(valueString, loc.m_groupingSeparator);
|
||||
}
|
||||
else
|
||||
out = valueString;
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
9
platform/platform_tests/locale_utils.hpp
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace platform
|
||||
{
|
||||
std::string GetSystemDecimalSeparator();
|
||||
std::string GetSystemGroupSeparator();
|
||||
std::string ReplaceGroupingSeparators(std::string const & valueString, std::string const & groupingSeparator);
|
||||
std::string ReplaceDecimalSeparator(std::string const & valueString, std::string const & decimalSeparator);
|
||||
std::string LocalizeValueString(std::string const & valueString, Locale const & loc);
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "platform/measurement_utils.hpp"
|
||||
#include "platform/platform_tests/locale_utils.hpp"
|
||||
|
||||
#include "base/math.hpp"
|
||||
|
||||
|
@ -10,17 +11,6 @@
|
|||
using namespace measurement_utils;
|
||||
using namespace platform;
|
||||
|
||||
std::string AddGroupingSeparators(std::string const & valueString, std::string const & groupingSeparator)
|
||||
{
|
||||
std::string out(valueString);
|
||||
|
||||
if (out.size() > 4 && !groupingSeparator.empty())
|
||||
for (int pos = out.size() - 3; pos > 0; pos -= 3)
|
||||
out.insert(pos, groupingSeparator);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
UNIT_TEST(LatLonToDMS_Origin)
|
||||
{
|
||||
TEST_EQUAL(FormatLatLonAsDMS(0, 0, false), "00°00′00″ 00°00′00″", ());
|
||||
|
@ -66,11 +56,13 @@ UNIT_TEST(FormatOsmLink)
|
|||
|
||||
UNIT_TEST(FormatSpeedNumeric)
|
||||
{
|
||||
std::string decSep = GetSystemDecimalSeparator();
|
||||
|
||||
TEST_EQUAL(FormatSpeedNumeric(10, Units::Metric), "36", ());
|
||||
TEST_EQUAL(FormatSpeedNumeric(1, Units::Metric), "3.6", ());
|
||||
TEST_EQUAL(FormatSpeedNumeric(1, Units::Metric), "3" + decSep + "6", ());
|
||||
|
||||
TEST_EQUAL(FormatSpeedNumeric(10, Units::Imperial), "22", ());
|
||||
TEST_EQUAL(FormatSpeedNumeric(1, Units::Imperial), "2.2", ());
|
||||
TEST_EQUAL(FormatSpeedNumeric(1, Units::Imperial), "2" + decSep + "2", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(OSMDistanceToMetersString)
|
||||
|
@ -152,7 +144,7 @@ UNIT_TEST(ToStringPrecisionLocale)
|
|||
|
||||
double d2 = 12345.0;
|
||||
int pr2 = 0;
|
||||
std::string d2String("12345");
|
||||
std::string d2String("12,345");
|
||||
|
||||
struct TestData
|
||||
{
|
||||
|
@ -180,6 +172,6 @@ UNIT_TEST(ToStringPrecisionLocale)
|
|||
|
||||
TEST_EQUAL(measurement_utils::ToStringPrecisionLocale(loc, d1, pr1), data.d1String, ());
|
||||
TEST_EQUAL(measurement_utils::ToStringPrecisionLocale(loc, d2, pr2),
|
||||
AddGroupingSeparators(d2String, loc.m_groupingSeparator), ());
|
||||
ReplaceGroupingSeparators(d2String, loc.m_groupingSeparator), ());
|
||||
}
|
||||
}
|
||||
|
|
Is there an option to set/override the locale from the test, so we can check different separators for different locales explicitly?