#if !UCONFIG_NO_FORMATTING
+#include "charstr.h"
+#include "cstr.h"
+#include "measunit_impl.h"
#include "unicode/decimfmt.h"
#include "unicode/measfmt.h"
#include "unicode/measure.h"
#include "unicode/tmunit.h"
#include "unicode/plurrule.h"
#include "unicode/ustring.h"
-#include "charstr.h"
-#include "cstr.h"
#include "unicode/reldatefmt.h"
#include "unicode/rbnf.h"
void TestDimensionlessBehaviour();
void Test21060_AddressSanitizerProblem();
void Test21223_FrenchDuration();
+ void TestInternalMeasureUnitImpl();
void verifyFormat(
const char *description,
TESTCASE_AUTO(TestDimensionlessBehaviour);
TESTCASE_AUTO(Test21060_AddressSanitizerProblem);
TESTCASE_AUTO(Test21223_FrenchDuration);
+ TESTCASE_AUTO(TestInternalMeasureUnitImpl);
TESTCASE_AUTO_END;
}
// }
}
+void MeasureFormatTest::TestInternalMeasureUnitImpl() {
+ IcuTestErrorCode status(*this, "TestInternalMeasureUnitImpl");
+ MeasureUnitImpl mu1 = MeasureUnitImpl::forIdentifier("meter", status);
+ status.assertSuccess();
+ assertEquals("mu1 initial identifier", "", mu1.identifier.data());
+ assertEquals("mu1 initial complexity", UMEASURE_UNIT_SINGLE, mu1.complexity);
+ assertEquals("mu1 initial units length", 1, mu1.units.length());
+ assertEquals("mu1 initial units[0]", "meter", mu1.units[0]->getSimpleUnitID());
+
+ // Producing identifier via build(): the std::move() means mu1 gets modified
+ // while it also gets assigned to tmp's internal fImpl.
+ MeasureUnit tmp = std::move(mu1).build(status);
+ status.assertSuccess();
+ assertEquals("mu1 post-move-build identifier", "meter", mu1.identifier.data());
+ assertEquals("mu1 post-move-build complexity", UMEASURE_UNIT_SINGLE, mu1.complexity);
+ assertEquals("mu1 post-move-build units length", 1, mu1.units.length());
+ assertEquals("mu1 post-move-build units[0]", "meter", mu1.units[0]->getSimpleUnitID());
+ assertEquals("MeasureUnit tmp identifier", "meter", tmp.getIdentifier());
+
+ // This temporary variable is used when forMeasureUnit's first parameter
+ // lacks an fImpl instance:
+ MeasureUnitImpl tmpMemory;
+ const MeasureUnitImpl &tmpImplRef = MeasureUnitImpl::forMeasureUnit(tmp, tmpMemory, status);
+ status.assertSuccess();
+ assertEquals("tmpMemory identifier", "", tmpMemory.identifier.data());
+ assertEquals("tmpMemory complexity", UMEASURE_UNIT_SINGLE, tmpMemory.complexity);
+ assertEquals("tmpMemory units length", 1, tmpMemory.units.length());
+ assertEquals("tmpMemory units[0]", "meter", tmpMemory.units[0]->getSimpleUnitID());
+ assertEquals("tmpImplRef identifier", "", tmpImplRef.identifier.data());
+ assertEquals("tmpImplRef complexity", UMEASURE_UNIT_SINGLE, tmpImplRef.complexity);
+
+ MeasureUnitImpl mu2 = MeasureUnitImpl::forIdentifier("newton-meter", status);
+ status.assertSuccess();
+ mu1 = std::move(mu2);
+ assertEquals("mu1 = move(mu2): identifier", "", mu1.identifier.data());
+ assertEquals("mu1 = move(mu2): complexity", UMEASURE_UNIT_COMPOUND, mu1.complexity);
+ assertEquals("mu1 = move(mu2): units length", 2, mu1.units.length());
+ assertEquals("mu1 = move(mu2): units[0]", "newton", mu1.units[0]->getSimpleUnitID());
+ assertEquals("mu1 = move(mu2): units[1]", "meter", mu1.units[1]->getSimpleUnitID());
+
+ mu1 = MeasureUnitImpl::forIdentifier("hour-and-minute-and-second", status);
+ status.assertSuccess();
+ assertEquals("mu1 = HMS: identifier", "", mu1.identifier.data());
+ assertEquals("mu1 = HMS: complexity", UMEASURE_UNIT_MIXED, mu1.complexity);
+ assertEquals("mu1 = HMS: units length", 3, mu1.units.length());
+ assertEquals("mu1 = HMS: units[0]", "hour", mu1.units[0]->getSimpleUnitID());
+ assertEquals("mu1 = HMS: units[1]", "minute", mu1.units[1]->getSimpleUnitID());
+ assertEquals("mu1 = HMS: units[2]", "second", mu1.units[2]->getSimpleUnitID());
+}
+
void MeasureFormatTest::verifyFieldPosition(
const char *description,
assertEquals("1.9999: measures[0] value", 1.0, measures[0]->getNumber().getDouble(status));
assertEquals("1.9999: measures[0] unit", MeasureUnit::getFoot().getIdentifier(),
measures[0]->getUnit().getIdentifier());
- assertEqualsNear("1.9999: measures[1] value", 11.9988, measures[1]->getNumber().getDouble(status), 0.0001);
+ assertEqualsNear("1.9999: measures[1] value", 11.9988,
+ measures[1]->getNumber().getDouble(status), 0.0001);
assertEquals("1.9999: measures[1] unit", MeasureUnit::getInch().getIdentifier(),
measures[1]->getUnit().getIdentifier());
}
// TODO(icu-units#100): consider factoring out the set of tests to make this function more
- // data-driven, *after* dealing appropriately with the memory leaks that can
- // be demonstrated by this code.
+ // data-driven.
- // TODO(icu-units#100): reusing measures results in a leak.
// A minimal nudge under 2.0.
- MaybeStackVector<Measure> measures2 = converter.convert((2.0 - DBL_EPSILON), nullptr, status);
- assertEquals("measures length", 2, measures2.length());
- if (2 == measures2.length()) {
- assertEquals("1 - eps: measures[0] value", 2.0, measures2[0]->getNumber().getDouble(status));
+ measures = converter.convert((2.0 - DBL_EPSILON), nullptr, status);
+ assertEquals("measures length", 2, measures.length());
+ if (2 == measures.length()) {
+ assertEquals("1 - eps: measures[0] value", 2.0, measures[0]->getNumber().getDouble(status));
assertEquals("1 - eps: measures[0] unit", MeasureUnit::getFoot().getIdentifier(),
- measures2[0]->getUnit().getIdentifier());
- assertEquals("1 - eps: measures[1] value", 0.0, measures2[1]->getNumber().getDouble(status));
+ measures[0]->getUnit().getIdentifier());
+ assertEquals("1 - eps: measures[1] value", 0.0, measures[1]->getNumber().getDouble(status));
assertEquals("1 - eps: measures[1] unit", MeasureUnit::getInch().getIdentifier(),
- measures2[1]->getUnit().getIdentifier());
+ measures[1]->getUnit().getIdentifier());
}
// Testing precision with meter and light-year. 1e-16 light years is
// An epsilon's nudge under one light-year: should give 1 ly, 0 m.
input = MeasureUnit::getLightYear();
output = MeasureUnit::forIdentifier("light-year-and-meter", status);
- // TODO(icu-units#100): reusing tempInput and tempOutput results in a leak.
- MeasureUnitImpl tempInput3, tempOutput3;
- const MeasureUnitImpl &inputImpl3 = MeasureUnitImpl::forMeasureUnit(input, tempInput3, status);
- const MeasureUnitImpl &outputImpl3 = MeasureUnitImpl::forMeasureUnit(output, tempOutput3, status);
- // TODO(icu-units#100): reusing converter results in a leak.
- ComplexUnitsConverter converter3 = ComplexUnitsConverter(inputImpl3, outputImpl3, rates, status);
- // TODO(icu-units#100): reusing measures results in a leak.
- MaybeStackVector<Measure> measures3 = converter3.convert((2.0 - DBL_EPSILON), nullptr, status);
- assertEquals("measures length", 2, measures3.length());
- if (2 == measures3.length()) {
- assertEquals("light-year test: measures[0] value", 2.0, measures3[0]->getNumber().getDouble(status));
+ const MeasureUnitImpl &inputImpl3 = MeasureUnitImpl::forMeasureUnit(input, tempInput, status);
+ const MeasureUnitImpl &outputImpl3 = MeasureUnitImpl::forMeasureUnit(output, tempOutput, status);
+ converter = ComplexUnitsConverter(inputImpl3, outputImpl3, rates, status);
+ measures = converter.convert((2.0 - DBL_EPSILON), nullptr, status);
+ assertEquals("measures length", 2, measures.length());
+ if (2 == measures.length()) {
+ assertEquals("light-year test: measures[0] value", 2.0,
+ measures[0]->getNumber().getDouble(status));
assertEquals("light-year test: measures[0] unit", MeasureUnit::getLightYear().getIdentifier(),
- measures3[0]->getUnit().getIdentifier());
- assertEquals("light-year test: measures[1] value", 0.0, measures3[1]->getNumber().getDouble(status));
+ measures[0]->getUnit().getIdentifier());
+ assertEquals("light-year test: measures[1] value", 0.0,
+ measures[1]->getNumber().getDouble(status));
assertEquals("light-year test: measures[1] unit", MeasureUnit::getMeter().getIdentifier(),
- measures3[1]->getUnit().getIdentifier());
+ measures[1]->getUnit().getIdentifier());
}
// 1e-15 light years is 9.46073 meters (calculated using "bc" and the CLDR
// conversion factor). With double-precision maths, we get 10.5. In this
// case, we're off by almost 1 meter.
- MaybeStackVector<Measure> measures4 = converter3.convert((1.0 + 1e-15), nullptr, status);
- assertEquals("measures length", 2, measures4.length());
- if (2 == measures4.length()) {
- assertEquals("light-year test: measures[0] value", 1.0, measures4[0]->getNumber().getDouble(status));
+ measures = converter.convert((1.0 + 1e-15), nullptr, status);
+ assertEquals("measures length", 2, measures.length());
+ if (2 == measures.length()) {
+ assertEquals("light-year test: measures[0] value", 1.0,
+ measures[0]->getNumber().getDouble(status));
assertEquals("light-year test: measures[0] unit", MeasureUnit::getLightYear().getIdentifier(),
- measures4[0]->getUnit().getIdentifier());
+ measures[0]->getUnit().getIdentifier());
assertEqualsNear("light-year test: measures[1] value", 10,
- measures4[1]->getNumber().getDouble(status), 1);
+ measures[1]->getNumber().getDouble(status), 1);
assertEquals("light-year test: measures[1] unit", MeasureUnit::getMeter().getIdentifier(),
- measures4[1]->getUnit().getIdentifier());
+ measures[1]->getUnit().getIdentifier());
}
// 2e-16 light years is 1.892146 meters. We consider this in the noise, and
// thus expect a 0. (This test fails when 2e-16 is increased to 4e-16.)
- MaybeStackVector<Measure> measures5 = converter3.convert((1.0 + 2e-16), nullptr, status);
- assertEquals("measures length", 2, measures5.length());
- if (2 == measures5.length()) {
- assertEquals("light-year test: measures[0] value", 1.0, measures5[0]->getNumber().getDouble(status));
+ measures = converter.convert((1.0 + 2e-16), nullptr, status);
+ assertEquals("measures length", 2, measures.length());
+ if (2 == measures.length()) {
+ assertEquals("light-year test: measures[0] value", 1.0,
+ measures[0]->getNumber().getDouble(status));
assertEquals("light-year test: measures[0] unit", MeasureUnit::getLightYear().getIdentifier(),
- measures5[0]->getUnit().getIdentifier());
+ measures[0]->getUnit().getIdentifier());
assertEquals("light-year test: measures[1] value", 0.0,
- measures5[1]->getNumber().getDouble(status));
+ measures[1]->getNumber().getDouble(status));
assertEquals("light-year test: measures[1] unit", MeasureUnit::getMeter().getIdentifier(),
- measures5[1]->getUnit().getIdentifier());
+ measures[1]->getUnit().getIdentifier());
}
// TODO(icu-units#63): test negative numbers!