[knx] Increase test coverage (#16511)

Signed-off-by: Holger Friedrich <mail@holger-friedrich.de>
Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
Holger Friedrich 2024-03-16 11:51:53 +01:00 committed by Ciprian Pascu
parent ff0e2293aa
commit f7aa3fea52
4 changed files with 96 additions and 17 deletions

View File

@ -231,7 +231,8 @@ public class ValueDecoder {
} catch (NumberFormatException | KNXFormatException | KNXIllegalArgumentException | ParseException e) {
LOGGER.info("Translator couldn't parse data '{}' for datapoint type '{}' ({}).", data, dptId, e.getClass());
} catch (KNXException e) {
LOGGER.warn("Failed creating a translator for datapoint type '{}'.", dptId, e);
// should never happen unless Calimero changes
LOGGER.warn("Failed creating a translator for datapoint type '{}'. Please open an issue.", dptId, e);
}
return null;
@ -280,7 +281,8 @@ public class ValueDecoder {
case "008":
return translator3BitControlled.getControlBit() ? UpDownType.DOWN : UpDownType.UP;
default:
LOGGER.warn("DPT3, subtype '{}' is unknown.", subType);
// should never happen unless Calimero introduces new subtypes
LOGGER.warn("DPT3, subtype '{}' is unknown. Please open an issue.", subType);
return null;
}
}
@ -324,7 +326,12 @@ public class ValueDecoder {
if (translatorDateTime.isValidField(DPTXlatorDateTime.YEAR)
&& !translatorDateTime.isValidField(DPTXlatorDateTime.TIME)) {
// Pure date format, no time information
cal.setTimeInMillis(translatorDateTime.getValueMilliseconds());
try {
cal.setTimeInMillis(translatorDateTime.getValueMilliseconds());
} catch (KNXFormatException e) {
LOGGER.debug("KNX clock msg ignored: {}", e.getMessage());
throw e;
}
String value = new SimpleDateFormat(DateTimeType.DATE_PATTERN).format(cal.getTime());
return DateTimeType.valueOf(value);
} else if (!translatorDateTime.isValidField(DPTXlatorDateTime.YEAR)

View File

@ -26,14 +26,18 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.openhab.binding.knx.internal.itests.Back2BackTest;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.library.unit.Units;
import org.openhab.core.util.ColorUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tuwien.auto.calimero.dptxlator.DPTXlator2ByteUnsigned;
import tuwien.auto.calimero.dptxlator.DPTXlator4ByteFloat;
@ -50,6 +54,13 @@ import tuwien.auto.calimero.dptxlator.DptXlator2ByteSigned;
*/
@NonNullByDefault
class DPTTest {
public static final Logger LOGGER = LoggerFactory.getLogger(Back2BackTest.class);
@Test
void testDptBroken() {
assertNull(ValueEncoder.encode(new DecimalType(), "9.042.1"));
assertNotNull(DPTUtil.getAllowedTypes("9.042.1"));
}
@Test
void testToDPTValueTrailingZeroesStrippedOff() {
@ -62,6 +73,21 @@ class DPTTest {
assertEquals("23.1", ValueEncoder.encode(new DecimalType("23.1"), "9.001"));
}
@Test
public void dpt1Value() {
// unknown subtype
assertNull(ValueDecoder.decode("1.091", new byte[] { 0 }, DecimalType.class));
assertNotNull(ValueEncoder.encode(new DecimalType(), "1.001"));
}
@Test
public void dpt3Value() {
// unknown subtype
assertNull(ValueDecoder.decode("3.042", new byte[] { 0 }, IncreaseDecreaseType.class));
assertNotNull(ValueEncoder.encode(new HSBType(), "5.003"));
assertNotNull(ValueEncoder.encode(new HSBType(), "5.001"));
}
@Test
void testToDPT5ValueFromQuantityType() {
assertEquals("80", ValueEncoder.encode(new QuantityType<>("80 %"), "5.001"));
@ -72,6 +98,22 @@ class DPTTest {
assertEquals("80", ValueEncoder.encode(new QuantityType<>("80 %"), "5.004"));
}
@Test
public void dpt6Value() {
assertEquals("42", ValueEncoder.encode(new DecimalType(42), "6.001"));
assertEquals("42", ValueEncoder.encode(new DecimalType(42), "6.010"));
assertEquals("0/0/0/0/1 0", Objects.toString(ValueDecoder.decode("6.020", new byte[] { 9 }, StringType.class)));
assertEquals("0/0/0/0/0 1", Objects.toString(ValueDecoder.decode("6.020", new byte[] { 2 }, StringType.class)));
assertEquals("1/1/1/1/1 2",
Objects.toString(ValueDecoder.decode("6.020", new byte[] { (byte) 0xfc }, StringType.class)));
assertEquals("0/0/0/0/1 0", ValueEncoder.encode(StringType.valueOf("0/0/0/0/1 0"), "6.020"));
// unknown subtype
assertNull(ValueDecoder.decode("6.200", new byte[] { 0 }, IncreaseDecreaseType.class));
}
@Test
void testToDPT7ValueFromQuantityType() {
assertEquals("1000", ValueEncoder.encode(new QuantityType<>("1000 ms"), "7.002"));
@ -155,6 +197,11 @@ class DPTTest {
assertEquals("10", ValueEncoder.encode(new QuantityType<>("10 km/h"), "9.028"));
assertEquals("1", ValueEncoder.encode(new QuantityType<>("1 g/m³"), "9.029"));
assertEquals("1", ValueEncoder.encode(new QuantityType<>("1 µg/m³"), "9.030"));
// w/o unit
ValueEncoder.encode(new QuantityType<>("1"), "9.030");
// wrong unit
ValueEncoder.encode(new QuantityType<>("1 kg"), "9.030");
}
@Test
@ -297,6 +344,30 @@ class DPTTest {
void testToDPT19ValueFromQuantityType() {
// DateTimeType, not QuantityType
assertEquals("2019-06-12 17:30:00", ValueEncoder.encode(new DateTimeType("2019-06-12T17:30:00Z"), "19.001"));
// special: clock fault
assertNull(ValueDecoder.decode("19.001", new byte[] { (byte) (2019 - 1900), 1, 15, 17, 30, 0, (byte) 0x80, 0 },
DateTimeType.class));
// special: no year, but month/day
assertNull(ValueDecoder.decode("19.001", new byte[] { (byte) (2019 - 1900), 1, 15, 17, 30, 0, (byte) 0x10, 0 },
DateTimeType.class));
// special: no day, but year
assertNull(ValueDecoder.decode("19.001", new byte[] { (byte) (2019 - 1900), 1, 15, 17, 30, 0, (byte) 0x08, 0 },
DateTimeType.class));
// special: no date, no time, no year
assertNull(ValueDecoder.decode("19.001", new byte[] { (byte) (2019 - 1900), 1, 15, 17, 30, 0, (byte) 0x1A, 0 },
DateTimeType.class));
// special: no time, but year etc. -> works if weekday is matching
assertNotNull(ValueDecoder.decode("19.001",
new byte[] { (byte) (2019 - 1900), 1, 15, 0x51, 30, 0, (byte) 0x02, 0 }, DateTimeType.class));
// special: no time, but year etc. -> weekday is not matching
assertNull(ValueDecoder.decode("19.001", new byte[] { (byte) (2019 - 1900), 1, 15, 17, 30, 0, (byte) 0x02, 0 },
DateTimeType.class));
// special: no time, no year
assertNull(ValueDecoder.decode("19.001", new byte[] { (byte) (2019 - 1900), 1, 15, 17, 30, 0, (byte) 0x12, 0 },
DateTimeType.class));
// special: no date, no year
assertNotNull(ValueDecoder.decode("19.001",
new byte[] { (byte) (2019 - 1900), 1, 15, 17, 30, 0, (byte) 0x18, 0 }, DateTimeType.class));
}
@Test
@ -306,19 +377,6 @@ class DPTTest {
assertEquals("42", ValueEncoder.encode(new QuantityType<>("42 varh"), "29.012"));
}
@Test
public void dpt6Value() {
assertEquals("42", ValueEncoder.encode(new DecimalType(42), "6.001"));
assertEquals("42", ValueEncoder.encode(new DecimalType(42), "6.010"));
assertEquals("0/0/0/0/1 0", Objects.toString(ValueDecoder.decode("6.020", new byte[] { 9 }, StringType.class)));
assertEquals("0/0/0/0/0 1", Objects.toString(ValueDecoder.decode("6.020", new byte[] { 2 }, StringType.class)));
assertEquals("1/1/1/1/1 2",
Objects.toString(ValueDecoder.decode("6.020", new byte[] { (byte) 0xfc }, StringType.class)));
assertEquals("0/0/0/0/1 0", ValueEncoder.encode(StringType.valueOf("0/0/0/0/1 0"), "6.020"));
}
@Test
public void dpt232RgbValue() {
// input data
@ -374,6 +432,18 @@ class DPTTest {
byte[] negativeEnergy = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
(byte) 0x02 };
assertEquals(new QuantityType<>("-1 Wh"), ValueDecoder.decode("235.001", negativeEnergy, QuantityType.class));
// invalid frame size
byte[] frameSizeTooSmall = new byte[] {};
assertNull(ValueDecoder.decode("235.001", frameSizeTooSmall, DecimalType.class));
assertNull(ValueDecoder.decode("235.001", frameSizeTooSmall, QuantityType.class));
assertNull(ValueDecoder.decode("235.61001", frameSizeTooSmall, DecimalType.class));
assertNull(ValueDecoder.decode("235.61001", frameSizeTooSmall, QuantityType.class));
byte[] frameSizeTooLong = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
assertNull(ValueDecoder.decode("235.001", frameSizeTooLong, DecimalType.class));
assertNull(ValueDecoder.decode("235.001", frameSizeTooLong, QuantityType.class));
assertNull(ValueDecoder.decode("235.61001", frameSizeTooLong, DecimalType.class));
assertNull(ValueDecoder.decode("235.61001", frameSizeTooLong, QuantityType.class));
}
@Test

View File

@ -97,6 +97,7 @@ class KNXTranslationProviderTest {
final Exception se = new KNXLinkClosedException("connection closed", e);
assertNotNull(KNXTranslationProvider.I18N.getLocalizedException(e));
assertNotNull(KNXTranslationProvider.I18N.getLocalizedException(se));
assertNotNull(KNXTranslationProvider.I18N.getLocalizedException(new Exception()));
assertEquals("KNXException, error 1", KNXTranslationProvider.I18N.getLocalizedException(e));
// use mockup classes with known dictionary

View File

@ -301,7 +301,8 @@ public class Back2BackTest {
@Test
void testDpt2() {
for (int subType = 1; subType <= 12; subType++) {
helper("2." + String.format("%03d", subType), new byte[] { 3 }, new DecimalType(3));
helper("2." + String.format("%03d", subType), new byte[] { (byte) (subType % 4) },
new DecimalType(subType % 4));
}
}