mirror of
https://github.com/danieldemus/openhab-core.git
synced 2025-01-25 19:55:48 +01:00
Fix decimal separator issues when creating QuantityType from String (#2362)
* Fix decimal separator issues when creating QuantityType from String Fixes #2360 Signed-off-by: Wouter Born <github@maindrain.net>
This commit is contained in:
parent
a8f469e5e7
commit
568881a678
@ -15,6 +15,7 @@ package org.openhab.core.library.types;
|
||||
import static org.eclipse.jdt.annotation.DefaultLocation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
@ -58,6 +59,7 @@ public class QuantityType<T extends Quantity<T>> extends Number
|
||||
implements PrimitiveType, State, Command, Comparable<QuantityType<T>> {
|
||||
|
||||
private static final long serialVersionUID = 8828949721938234629L;
|
||||
private static final char DOT_DECIMAL_SEPARATOR = '.';
|
||||
private static final BigDecimal HUNDRED = BigDecimal.valueOf(100);
|
||||
|
||||
public static final QuantityType<Dimensionless> ZERO = new QuantityType<>(0, AbstractUnit.ONE);
|
||||
@ -102,6 +104,14 @@ public class QuantityType<T extends Quantity<T>> extends Number
|
||||
BigDecimal bd = new BigDecimal(value);
|
||||
quantity = (Quantity<T>) Quantities.getQuantity(bd, AbstractUnit.ONE, Scale.RELATIVE);
|
||||
} else {
|
||||
char defaultDecimalSeparator = DecimalFormatSymbols.getInstance().getDecimalSeparator();
|
||||
// The quantity is parsed using a NumberFormat based on the default locale.
|
||||
// To prevent issues, any dot decimal separators are replaced by the default locale decimal separator.
|
||||
if (DOT_DECIMAL_SEPARATOR != defaultDecimalSeparator
|
||||
&& formatted.contains(String.valueOf(DOT_DECIMAL_SEPARATOR))) {
|
||||
formatted = formatted.replace(DOT_DECIMAL_SEPARATOR, defaultDecimalSeparator);
|
||||
}
|
||||
|
||||
Quantity<T> absoluteQuantity = (Quantity<T>) Quantities.getQuantity(formatted);
|
||||
quantity = Quantities.getQuantity(absoluteQuantity.getValue(), absoluteQuantity.getUnit(), Scale.RELATIVE);
|
||||
}
|
||||
|
@ -17,12 +17,16 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.measure.quantity.Length;
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.openhab.core.i18n.UnitProvider;
|
||||
import org.openhab.core.items.Item;
|
||||
import org.openhab.core.library.items.NumberItem;
|
||||
@ -44,6 +48,19 @@ public class ItemStateConverterImplTest {
|
||||
|
||||
private @NonNullByDefault({}) ItemStateConverterImpl itemStateConverter;
|
||||
|
||||
/**
|
||||
* Locales having a different decimal separator to test string parsing and generation.
|
||||
*/
|
||||
static Stream<Locale> locales() {
|
||||
return Stream.of(
|
||||
// ٫ (Arabic, Egypt)
|
||||
Locale.forLanguageTag("ar-EG"),
|
||||
// , (German, Germany)
|
||||
Locale.forLanguageTag("de-DE"),
|
||||
// . (English, United States)
|
||||
Locale.forLanguageTag("en-US"));
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
UnitProvider unitProvider = mock(UnitProvider.class);
|
||||
@ -51,16 +68,22 @@ public class ItemStateConverterImplTest {
|
||||
itemStateConverter = new ItemStateConverterImpl(unitProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullState() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testNullState(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
State undef = itemStateConverter.convertToAcceptedState(null, null);
|
||||
|
||||
assertThat(undef, is(UnDefType.NULL));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
@SuppressWarnings("PMD.CompareObjectsWithEquals")
|
||||
public void testNoConversion() {
|
||||
public void testNoConversion(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Item item = new NumberItem("number");
|
||||
State originalState = new DecimalType(12.34);
|
||||
State state = itemStateConverter.convertToAcceptedState(originalState, item);
|
||||
@ -68,8 +91,11 @@ public class ItemStateConverterImplTest {
|
||||
assertTrue(originalState == state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStateConversion() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testStateConversion(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Item item = new NumberItem("number");
|
||||
State originalState = new PercentType("42");
|
||||
State convertedState = itemStateConverter.convertToAcceptedState(originalState, item);
|
||||
@ -77,8 +103,11 @@ public class ItemStateConverterImplTest {
|
||||
assertThat(convertedState, is(new DecimalType("0.42")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void numberItemWithoutDimensionShouldConvertToDecimalType() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void numberItemWithoutDimensionShouldConvertToDecimalType(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Item item = new NumberItem("number");
|
||||
State originalState = new QuantityType<>("12.34 °C");
|
||||
State convertedState = itemStateConverter.convertToAcceptedState(originalState, item);
|
||||
@ -86,8 +115,11 @@ public class ItemStateConverterImplTest {
|
||||
assertThat(convertedState, is(new DecimalType("12.34")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void numberItemWitDimensionShouldConvertToItemStateDescriptionUnit() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void numberItemWitDimensionShouldConvertToItemStateDescriptionUnit(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
NumberItem item = mock(NumberItem.class);
|
||||
StateDescription stateDescription = mock(StateDescription.class);
|
||||
when(item.getStateDescription()).thenReturn(stateDescription);
|
||||
@ -100,8 +132,11 @@ public class ItemStateConverterImplTest {
|
||||
assertThat(convertedState, is(new QuantityType<>("285.49 K")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void numberItemWitDimensionShouldConvertToLocaleBasedUnit() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void numberItemWitDimensionShouldConvertToLocaleBasedUnit(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
NumberItem item = mock(NumberItem.class);
|
||||
doReturn(Temperature.class).when(item).getDimension();
|
||||
|
||||
@ -111,8 +146,11 @@ public class ItemStateConverterImplTest {
|
||||
assertThat(convertedState, is(new QuantityType<>("54.212 °F")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void numberItemShouldNotConvertUnitsWhereMeasurmentSystemEquals() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void numberItemShouldNotConvertUnitsWhereMeasurmentSystemEquals(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
NumberItem item = mock(NumberItem.class);
|
||||
doReturn(Length.class).when(item).getDimension();
|
||||
|
||||
|
@ -15,7 +15,9 @@ package org.openhab.core.library.types;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.measure.Quantity;
|
||||
import javax.measure.quantity.Dimensionless;
|
||||
@ -23,9 +25,10 @@ import javax.measure.quantity.Power;
|
||||
import javax.measure.quantity.Pressure;
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.openhab.core.i18n.UnitProvider;
|
||||
@ -41,155 +44,204 @@ import org.openhab.core.types.UnDefType;
|
||||
* @author Henning Treu - Initial contribution
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@NonNullByDefault
|
||||
public class QuantityTypeArithmeticGroupFunctionTest {
|
||||
|
||||
private GroupFunction function;
|
||||
private Set<Item> items;
|
||||
private @NonNullByDefault({}) @Mock UnitProvider unitProvider;
|
||||
|
||||
private @Mock UnitProvider unitProvider;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
items = new LinkedHashSet<>();
|
||||
/**
|
||||
* Locales having a different decimal separator to test string parsing and generation.
|
||||
*/
|
||||
static Stream<Locale> locales() {
|
||||
return Stream.of(
|
||||
// ٫ (Arabic, Egypt)
|
||||
Locale.forLanguageTag("ar-EG"),
|
||||
// , (German, Germany)
|
||||
Locale.forLanguageTag("de-DE"),
|
||||
// . (English, United States)
|
||||
Locale.forLanguageTag("en-US"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSumFunctionQuantityType() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testSumFunctionQuantityType(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>();
|
||||
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("23.54 °C")));
|
||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||
items.add(createNumberItem("TestItem3", Temperature.class, new QuantityType<>("89 °C")));
|
||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("122.41 °C")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Sum(Temperature.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(Temperature.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("234.95 °C"), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSumFunctionQuantityTypeDifferentUnits() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testSumFunctionQuantityTypeDifferentUnits(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>();
|
||||
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("23.54 °C")));
|
||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||
items.add(createNumberItem("TestItem3", Temperature.class, new QuantityType<>("192.2 °F")));
|
||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("395.56 K")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Sum(Temperature.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(Temperature.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("234.95 °C"), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSumFunctionQuantityTypeIncompatibleUnits() {
|
||||
items = new LinkedHashSet<>(); // we need an ordered set to guarantee the Unit of the first entry
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testSumFunctionQuantityTypeIncompatibleUnits(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>(); // we need an ordered set to guarantee the Unit of the first entry
|
||||
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("23.54 °C")));
|
||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||
items.add(createNumberItem("TestItem3", Pressure.class, new QuantityType<>("192.2 hPa")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Sum(Temperature.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(Temperature.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("23.54 °C"), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAvgFunctionQuantityType() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testAvgFunctionQuantityType(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>();
|
||||
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("100 °C")));
|
||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||
items.add(createNumberItem("TestItem3", Temperature.class, new QuantityType<>("200 °C")));
|
||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("300 °C")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Avg(Temperature.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Avg(Temperature.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("200 °C"), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAvgFunctionQuantityTypeDifferentUnits() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testAvgFunctionQuantityTypeDifferentUnits(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>();
|
||||
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("100 °C")));
|
||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||
items.add(createNumberItem("TestItem3", Temperature.class, new QuantityType<>("113 °F")));
|
||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("294.15 K")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Avg(Temperature.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Avg(Temperature.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("55.33333333333333333333333333333334 °C"), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAvgFunctionQuantityTypeIncompatibleUnits() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testAvgFunctionQuantityTypeIncompatibleUnits(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>();
|
||||
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("23.54 °C")));
|
||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||
items.add(createNumberItem("TestItem3", Pressure.class, new QuantityType<>("192.2 hPa")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Avg(Temperature.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Avg(Temperature.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("23.54 °C"), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxFunctionQuantityType() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testMaxFunctionQuantityType(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>();
|
||||
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("100 °C")));
|
||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||
items.add(createNumberItem("TestItem3", Temperature.class, new QuantityType<>("200 °C")));
|
||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("300 °C")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Max(Temperature.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(Temperature.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("300 °C"), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxFunctionQuantityTypeDifferentUnits() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testMaxFunctionQuantityTypeDifferentUnits(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>();
|
||||
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("100 °C")));
|
||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||
items.add(createNumberItem("TestItem3", Temperature.class, new QuantityType<>("113 °F")));
|
||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("294.15 K")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Max(Temperature.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(Temperature.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("100 °C"), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxFunctionQuantityTypeIncompatibleUnits() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testMaxFunctionQuantityTypeIncompatibleUnits(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>();
|
||||
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("23.54 °C")));
|
||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||
items.add(createNumberItem("TestItem3", Pressure.class, new QuantityType<>("192.2 hPa")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Max(Temperature.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(Temperature.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("23.54 °C"), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinFunctionQuantityType() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testMinFunctionQuantityType(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>();
|
||||
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("100 °C")));
|
||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||
items.add(createNumberItem("TestItem3", Temperature.class, new QuantityType<>("200 °C")));
|
||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("300 °C")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Min(Temperature.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Min(Temperature.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("100 °C"), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxFunctionQuantityTypeOnDimensionless() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testMaxFunctionQuantityTypeOnDimensionless(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>();
|
||||
items.add(createNumberItem("TestItem1", Dimensionless.class, new QuantityType<>("48 %")));
|
||||
items.add(createNumberItem("TestItem2", Dimensionless.class, new QuantityType<>("36 %")));
|
||||
items.add(createNumberItem("TestItem3", Dimensionless.class, new QuantityType<>("0 %")));
|
||||
@ -197,44 +249,56 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
||||
items.add(createNumberItem("TestItem5", Dimensionless.class, new QuantityType<>("0 %")));
|
||||
items.add(createNumberItem("TestItem6", Dimensionless.class, new QuantityType<>("0 %")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Max(Dimensionless.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(Dimensionless.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("48 %"), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinFunctionQuantityTypeDifferentUnits() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testMinFunctionQuantityTypeDifferentUnits(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>();
|
||||
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("100 °C")));
|
||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||
items.add(createNumberItem("TestItem3", Temperature.class, new QuantityType<>("113 °F")));
|
||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("294.15 K")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Min(Temperature.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Min(Temperature.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("294.15 K"), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinFunctionQuantityTypeIncompatibleUnits() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testMinFunctionQuantityTypeIncompatibleUnits(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>();
|
||||
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("23.54 °C")));
|
||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||
items.add(createNumberItem("TestItem3", Pressure.class, new QuantityType<>("192.2 hPa")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Min(Temperature.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Min(Temperature.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("23.54 °C"), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSumFunctionQuantityTypeWithGroups() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testSumFunctionQuantityTypeWithGroups(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Set<Item> items = new LinkedHashSet<>();
|
||||
items.add(createNumberItem("TestItem1", Power.class, new QuantityType<>("5 W")));
|
||||
items.add(createGroupItem("TestGroup1", Power.class, new QuantityType<>("5 W")));
|
||||
|
||||
function = new QuantityTypeArithmeticGroupFunction.Sum(Power.class);
|
||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(Power.class);
|
||||
State state = function.calculate(items);
|
||||
|
||||
assertEquals(new QuantityType<>("10 W"), state);
|
||||
|
@ -20,6 +20,8 @@ import static org.openhab.core.library.unit.MetricPrefix.CENTI;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.measure.format.MeasurementParseException;
|
||||
import javax.measure.quantity.Dimensionless;
|
||||
@ -31,6 +33,8 @@ import javax.measure.quantity.Temperature;
|
||||
import javax.measure.quantity.Time;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.openhab.core.library.dimension.DataAmount;
|
||||
import org.openhab.core.library.dimension.DataTransferRate;
|
||||
import org.openhab.core.library.dimension.Density;
|
||||
@ -49,8 +53,18 @@ import tech.units.indriya.unit.UnitDimension;
|
||||
@SuppressWarnings("null")
|
||||
public class QuantityTypeTest {
|
||||
|
||||
// we need to get the decimal separator of the default locale for our tests
|
||||
private static final char SEP = new DecimalFormatSymbols().getDecimalSeparator();
|
||||
/**
|
||||
* Locales having a different decimal separator to test string parsing and generation.
|
||||
*/
|
||||
static Stream<Locale> locales() {
|
||||
return Stream.of(
|
||||
// ٫ (Arabic, Egypt)
|
||||
Locale.forLanguageTag("ar-EG"),
|
||||
// , (German, Germany)
|
||||
Locale.forLanguageTag("de-DE"),
|
||||
// . (English, United States)
|
||||
Locale.forLanguageTag("en-US"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDimensionless() {
|
||||
@ -128,12 +142,14 @@ public class QuantityTypeTest {
|
||||
QuantityType<Time> millis = seconds.toUnit(MetricPrefix.MILLI(Units.SECOND));
|
||||
QuantityType<Time> minutes = seconds.toUnit(Units.MINUTE);
|
||||
|
||||
assertThat(seconds.format("%.1f " + UnitUtils.UNIT_PLACEHOLDER), is("80" + SEP + "0 s"));
|
||||
assertThat(millis.format("%.1f " + UnitUtils.UNIT_PLACEHOLDER), is("80000" + SEP + "0 ms"));
|
||||
assertThat(minutes.format("%.1f " + UnitUtils.UNIT_PLACEHOLDER), is("1" + SEP + "3 min"));
|
||||
char sep = new DecimalFormatSymbols().getDecimalSeparator();
|
||||
|
||||
assertThat(seconds.format("%.1f"), is("80" + SEP + "0"));
|
||||
assertThat(minutes.format("%.1f"), is("1" + SEP + "3"));
|
||||
assertThat(seconds.format("%.1f " + UnitUtils.UNIT_PLACEHOLDER), is("80" + sep + "0 s"));
|
||||
assertThat(millis.format("%.1f " + UnitUtils.UNIT_PLACEHOLDER), is("80000" + sep + "0 ms"));
|
||||
assertThat(minutes.format("%.1f " + UnitUtils.UNIT_PLACEHOLDER), is("1" + sep + "3 min"));
|
||||
|
||||
assertThat(seconds.format("%.1f"), is("80" + sep + "0"));
|
||||
assertThat(minutes.format("%.1f"), is("1" + sep + "3"));
|
||||
|
||||
assertThat(seconds.format("%1$tH:%1$tM:%1$tS"), is("00:01:20"));
|
||||
assertThat(millis.format("%1$tHh %1$tMm %1$tSs"), is("00h 01m 20s"));
|
||||
@ -196,28 +212,41 @@ public class QuantityTypeTest {
|
||||
assertNull(new QuantityType<>("0.5").as(OpenClosedType.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConversionToHSBType() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testConversionToHSBType(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
assertEquals(new HSBType("0,0,0"), new QuantityType<>("0.0").as(HSBType.class));
|
||||
assertEquals(new HSBType("0,0,100"), new QuantityType<>("1.0").as(HSBType.class));
|
||||
assertEquals(new HSBType("0,0,50"), new QuantityType<>("0.5").as(HSBType.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConversionToPercentType() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testConversionToPercentType(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
assertEquals(PercentType.HUNDRED, new QuantityType<>("100 %").as(PercentType.class));
|
||||
assertEquals(PercentType.ZERO, new QuantityType<>("0 %").as(PercentType.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toFullStringShouldParseToEqualState() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void toFullStringShouldParseToEqualState(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
QuantityType<Temperature> temp = new QuantityType<>("20 °C");
|
||||
|
||||
assertThat(temp.toFullString(), is("20 °C"));
|
||||
assertThat(QuantityType.valueOf(temp.toFullString()), is(temp));
|
||||
}
|
||||
|
||||
public void testAdd() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testAdd(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
QuantityType<?> result = new QuantityType<>("20 m").add(new QuantityType<>("20cm"));
|
||||
assertThat(result, is(new QuantityType<>("20.20 m")));
|
||||
}
|
||||
@ -227,8 +256,11 @@ public class QuantityTypeTest {
|
||||
assertThat(new QuantityType<>("20 °C").negate(), is(new QuantityType<>("-20 °C")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubtract() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testSubtract(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
QuantityType<?> result = new QuantityType<>("20 m").subtract(new QuantityType<>("20cm"));
|
||||
assertThat(result, is(new QuantityType<>("19.80 m")));
|
||||
}
|
||||
@ -243,18 +275,27 @@ public class QuantityTypeTest {
|
||||
assertThat(new QuantityType<>("2 m").multiply(new QuantityType<>("4 cm")), is(new QuantityType<>("8 m·cm")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDivideNumber() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testDivideNumber(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
assertThat(new QuantityType<>("4 m").divide(BigDecimal.valueOf(2)), is(new QuantityType<>("2 m")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDivideQuantityType() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testDivideQuantityType(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
assertThat(new QuantityType<>("4 m").divide(new QuantityType<>("2 cm")), is(new QuantityType<>("2 m/cm")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDivideZero() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("locales")
|
||||
public void testDivideZero(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> new QuantityType<>("4 m").divide(QuantityType.ZERO));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user