From c69889d177d7523e4205fcf03c02a7d287520dd9 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sun, 11 Dec 2016 23:29:22 +0100 Subject: [PATCH] Simplified + fixed ArrayUtils.equals() + added lots of testcases --- .../miband/AbstractMi1FirmwareInfo.java | 2 +- .../devices/miband/Mi1SFirmwareInfo.java | 2 +- .../devices/miband2/Mi2FirmwareInfo.java | 2 +- .../operations/FetchActivityOperation.java | 2 +- .../gadgetbridge/util/ArrayUtils.java | 32 +++-- .../gadgetbridge/test/ArrayUtilsTest.java | 117 ++++++++++++++++++ 6 files changed, 135 insertions(+), 22 deletions(-) create mode 100644 app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/ArrayUtilsTest.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/AbstractMi1FirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/AbstractMi1FirmwareInfo.java index 627ea19f..a1a622b6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/AbstractMi1FirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/AbstractMi1FirmwareInfo.java @@ -94,7 +94,7 @@ public abstract class AbstractMi1FirmwareInfo extends AbstractMiFirmwareInfo { @Override protected boolean isHeaderValid() { // TODO: not sure if this is a correct check! - return ArrayUtils.equals(SINGLE_FW_HEADER, wholeFirmwareBytes, SINGLE_FW_HEADER_OFFSET, SINGLE_FW_HEADER_OFFSET + SINGLE_FW_HEADER.length); + return ArrayUtils.equals(wholeFirmwareBytes, SINGLE_FW_HEADER, SINGLE_FW_HEADER_OFFSET); } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/Mi1SFirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/Mi1SFirmwareInfo.java index 8de13acd..9a5a80ff 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/Mi1SFirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/Mi1SFirmwareInfo.java @@ -41,7 +41,7 @@ public class Mi1SFirmwareInfo extends CompositeMiFirmwareInfo { @Override protected boolean isHeaderValid() { // TODO: not sure if this is a correct check! - return ArrayUtils.equals(DOUBLE_FW_HEADER, wholeFirmwareBytes, DOUBLE_FW_HEADER_OFFSET, DOUBLE_FW_HEADER_OFFSET + DOUBLE_FW_HEADER.length); + return ArrayUtils.equals(wholeFirmwareBytes, DOUBLE_FW_HEADER, DOUBLE_FW_HEADER_OFFSET); } @Nullable diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java index 6e9cb0a0..4dbf595e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java @@ -59,7 +59,7 @@ public class Mi2FirmwareInfo { public boolean isHeaderValid() { // TODO: this is certainly not a correct validation, but it works for now - return ArrayUtils.equals(FW_HEADER, bytes, FW_HEADER_OFFSET, FW_HEADER_OFFSET + FW_HEADER.length); + return ArrayUtils.equals(bytes, FW_HEADER, FW_HEADER_OFFSET); } public void checkValid() throws IllegalArgumentException { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/FetchActivityOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/FetchActivityOperation.java index 85200a63..c83e6104 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/FetchActivityOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/FetchActivityOperation.java @@ -218,7 +218,7 @@ public class FetchActivityOperation extends AbstractMiBand2Operation { private void handleActivityMetadata(byte[] value) { if (value.length == 15) { // first two bytes are whether our request was accepted - if (ArrayUtils.equals(MiBand2Service.RESPONSE_ACTIVITY_DATA_START_DATE_SUCCESS, value, 0, 3)) { + if (ArrayUtils.equals(value, MiBand2Service.RESPONSE_ACTIVITY_DATA_START_DATE_SUCCESS, 0)) { // the third byte (0x01 on success) = ? // the 4th - 7th bytes probably somehow represent the number of bytes/packets to expect diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/ArrayUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/ArrayUtils.java index a7fbbf3e..d0bee577 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/ArrayUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/ArrayUtils.java @@ -4,35 +4,31 @@ import java.util.Collection; public class ArrayUtils { /** - * Checks the two given arrays for equality, but comparing only a subset of the second - * array with the whole first array. + * Checks the two given arrays for equality, but comparing the second array with a specified + * subset of the first array. * - * @param first the whole array to compare against - * @param second the array, of which a subset shall be compared against the whole first array - * @param secondStartIndex the start index (inclusive) of the second array from which to start the comparison - * @param secondEndIndex the end index (exclusive) of the second array until which to compare - * @return whether the first byte array is equal to the specified subset of the second byte array - * @throws IllegalArgumentException when one of the arrays is null or start and end index are wrong + * @param first the array in which to look for the second array + * @param second the data to look for inside the first array + * @param startIndex the start index (inclusive) inside the first array from which to start the comparison + * @return whether the second byte array is equal to the specified subset of the first byte array + * @throws IllegalArgumentException when one of the arrays is null or start index/length are wrong */ - public static boolean equals(byte[] first, byte[] second, int secondStartIndex, int secondEndIndex) { + public static boolean equals(byte[] first, byte[] second, int startIndex) { if (first == null) { throw new IllegalArgumentException("first must not be null"); } if (second == null) { throw new IllegalArgumentException("second must not be null"); } - if (secondStartIndex >= secondEndIndex) { - throw new IllegalArgumentException("secondStartIndex must be smaller than secondEndIndex"); + if (startIndex < 0) { + throw new IllegalArgumentException("startIndex must be >= 0"); } - if (second.length < secondEndIndex) { - throw new IllegalArgumentException("secondStartIndex must be smaller than secondEndIndex"); - } - int len = secondEndIndex - secondStartIndex; - if (first.length != len) { + + if (second.length + startIndex > first.length) { return false; } - for (int i = 0; i < len; i++) { - if (first[i] != second[secondStartIndex + i]) { + for (int i = 0; i < second.length; i++) { + if (first[startIndex + i] != second[i]) { return false; } } diff --git a/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/ArrayUtilsTest.java b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/ArrayUtilsTest.java new file mode 100644 index 00000000..d6bc5bca --- /dev/null +++ b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/ArrayUtilsTest.java @@ -0,0 +1,117 @@ +package nodomain.freeyourgadget.gadgetbridge.test; + +import org.junit.Test; + +import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Tests ArrayUtils + */ +public class ArrayUtilsTest extends TestBase { + + private static final byte[] EMPTY = new byte[0]; + private static final byte[] DATA_5 = new byte[] { 1, 2, 3, 4, 5}; + + public ArrayUtilsTest() throws Exception { + } + + @Test + public void testEqualsException1() throws Exception { + try { + ArrayUtils.equals(null, EMPTY, 0); + fail("equals should throw on bad argument"); + } catch (IllegalArgumentException ex) { + // expected + } + } + + @Test + public void testEqualsException2() throws Exception { + try { + ArrayUtils.equals(EMPTY, null, 0); + fail("equals should throw on bad argument"); + } catch (IllegalArgumentException ex) { + // expected + } + } + + @Test + public void testEqualsException5() throws Exception { + try { + ArrayUtils.equals(EMPTY, EMPTY, -1); + fail("equals should throw on bad argument"); + } catch (IllegalArgumentException ex) { + // expected + } + } + + @Test + public void testEqualsEmptyData() throws Exception { + assertFalse(ArrayUtils.equals(EMPTY, DATA_5, 0)); + } + + @Test + public void testEqualsEmptyTest() throws Exception { + // testing for 0 equal bytes may be senseless, but always true + assertTrue(ArrayUtils.equals(EMPTY, EMPTY, 0)); + assertTrue(ArrayUtils.equals(DATA_5, EMPTY, 0)); + } + + @Test + public void testEquals1() throws Exception { + assertTrue(ArrayUtils.equals(DATA_5, b(1), 0)); + } + + @Test + public void testEquals2() throws Exception { + assertTrue(ArrayUtils.equals(DATA_5, b(2), 1)); + } + + @Test + public void testEquals5() throws Exception { + assertTrue(ArrayUtils.equals(DATA_5, b(5), 4)); + } + + @Test + public void testEqualsOutOfRange() throws Exception { + assertFalse(ArrayUtils.equals(DATA_5, b(5), 5)); + } + + @Test + public void testEquals123() throws Exception { + assertTrue(ArrayUtils.equals(DATA_5, new byte[] {1, 2, 3}, 0)); + } + + @Test + public void testEquals234() throws Exception { + assertTrue(ArrayUtils.equals(DATA_5, new byte[] {2, 3, 4}, 1)); + } + + @Test + public void testEquals345() throws Exception { + assertTrue(ArrayUtils.equals(DATA_5, new byte[] {3, 4, 5}, 2)); + } + + @Test + public void testEquals12345() throws Exception { + assertTrue(ArrayUtils.equals(DATA_5, DATA_5, 0)); + } + + @Test + public void testEqualsWrongStart() throws Exception { + assertFalse(ArrayUtils.equals(DATA_5, new byte[] {0, 2, 3}, 0)); + } + + @Test + public void testEqualsWrongEnd() throws Exception { + assertFalse(ArrayUtils.equals(DATA_5, new byte[] {3, 4, 6}, 2)); + } + + private byte[] b(int b) { + return new byte[] {(byte) b}; + } +}