From 6d8d6d5bc810139c2d1f0d12ab664503ebb316ba Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Thu, 17 Mar 2016 23:41:41 +0100 Subject: [PATCH] Testcases for firmware checking --- app/build.gradle | 2 + .../service/devices/miband/Mi1SInfo.java | 20 ++-- .../service/devices/miband/FirmwareTest.java | 110 ++++++++++++++++++ 3 files changed, 123 insertions(+), 9 deletions(-) create mode 100644 app/src/test/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/FirmwareTest.java diff --git a/app/build.gradle b/app/build.gradle index 3746bc49..191981db 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,6 +4,8 @@ apply plugin: 'pmd' def ABORT_ON_CHECK_FAILURE=false +tasks.withType(Test) { systemProperty 'MiFirmwareDir', System.getProperty('MiFirmwareDir', null) } + android { compileSdkVersion 23 buildToolsVersion "23.0.2" diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/Mi1SInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/Mi1SInfo.java index ea27e6eb..7a1448e1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/Mi1SInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/Mi1SInfo.java @@ -1,12 +1,14 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.miband; +import android.support.annotation.NonNull; + /** * FW1 is Mi Band firmware * FW2 is heartrate firmware */ public class Mi1SInfo { - public static int getFirmware2OffsetIn(byte[] wholeFirmwareBytes) + public static int getFirmware2OffsetIn(@NonNull byte[] wholeFirmwareBytes) { return (wholeFirmwareBytes[26] & 255) << 24 | (wholeFirmwareBytes[27] & 255) << 16 @@ -14,7 +16,7 @@ public class Mi1SInfo { | (wholeFirmwareBytes[29] & 255); } - public static int getFirmware2LengthIn(byte[] wholeFirmwareBytes) + public static int getFirmware2LengthIn(@NonNull byte[] wholeFirmwareBytes) { return (wholeFirmwareBytes[30] & 255) << 24 | (wholeFirmwareBytes[31] & 255) << 16 @@ -22,7 +24,7 @@ public class Mi1SInfo { | (wholeFirmwareBytes[33] & 255); } - public static int getFirmware1OffsetIn(byte[] wholeFirmwareBytes) + public static int getFirmware1OffsetIn(@NonNull byte[] wholeFirmwareBytes) { return (wholeFirmwareBytes[12] & 255) << 24 | (wholeFirmwareBytes[13] & 255) << 16 @@ -30,7 +32,7 @@ public class Mi1SInfo { | (wholeFirmwareBytes[15] & 255); } - public static int getFirmware1LengthIn(byte[] wholeFirmwareBytes) + public static int getFirmware1LengthIn(@NonNull byte[] wholeFirmwareBytes) { return (wholeFirmwareBytes[16] & 255) << 24 | (wholeFirmwareBytes[17] & 255) << 16 @@ -38,7 +40,7 @@ public class Mi1SInfo { | (wholeFirmwareBytes[19] & 255); } - public static int getFirmware1VersionFrom(byte[] wholeFirmwareBytes) + public static int getFirmware1VersionFrom(@NonNull byte[] wholeFirmwareBytes) { return (wholeFirmwareBytes[8] & 255) << 24 | (wholeFirmwareBytes[9] & 255) << 16 @@ -46,7 +48,7 @@ public class Mi1SInfo { | wholeFirmwareBytes[11] & 255; } - public static int getFirmware2VersionFrom(byte[] wholeFirmwareBytes) + public static int getFirmware2VersionFrom(@NonNull byte[] wholeFirmwareBytes) { return (wholeFirmwareBytes[22] & 255) << 24 | (wholeFirmwareBytes[23] & 255) << 16 @@ -56,11 +58,11 @@ public class Mi1SInfo { // FIXME: this method is wrong. We don't know a way to check if a firmware file // contains one or more firmwares. - public static boolean isSingleMiBandFirmware(byte[] wholeFirmwareBytes) { + public static boolean isSingleMiBandFirmware(@NonNull byte[] wholeFirmwareBytes) { if ((wholeFirmwareBytes[7] & 255) != 1) { - return false; + return true; } - return true; + return false; } } diff --git a/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/FirmwareTest.java b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/FirmwareTest.java new file mode 100644 index 00000000..b842ec1e --- /dev/null +++ b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/FirmwareTest.java @@ -0,0 +1,110 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.miband; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandFWHelper; +import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; + +public class FirmwareTest { + + private static final long MAX_FILE_SIZE_BYTES = 1024 * 1024; // 1MB + private static final int MI_FW_VERSION = 0; // FIXME + private static final int MI1A_FW_VERSION = 0; // FIXME + private static final int MI1S_FW1_VERSION = 0; + private static final int MI1S_FW2_VERSION = 0; + + @Test + public void testFirmwareMi() throws Exception{ + byte[] wholeFw = getFirmwareMi(); + Assert.assertNotNull(wholeFw); + + Assert.assertTrue(Mi1SInfo.isSingleMiBandFirmware(wholeFw)); + int calculatedLength = Mi1SInfo.getFirmware1LengthIn(wholeFw); + Assert.assertTrue("Unexpected firmware length: " + wholeFw.length, calculatedLength < wholeFw.length); + int calculatedVersion = Mi1SInfo.getFirmware1VersionFrom(wholeFw); +// Assert.assertEquals("Unexpected firmware version: " + calculatedVersion, MI_FW_VERSION, calculatedVersion); + + String version = MiBandFWHelper.formatFirmwareVersion(calculatedVersion); + Assert.assertTrue(version.startsWith("1.")); + } + + @Test + public void testFirmwareMi1A() throws Exception{ + byte[] wholeFw = getFirmwareMi1A(); + Assert.assertNotNull(wholeFw); + + Assert.assertTrue(Mi1SInfo.isSingleMiBandFirmware(wholeFw)); + int calculatedLength = Mi1SInfo.getFirmware1LengthIn(wholeFw); + Assert.assertTrue("Unexpected firmware length: " + wholeFw.length, calculatedLength < wholeFw.length); + int calculatedVersion = Mi1SInfo.getFirmware1VersionFrom(wholeFw); +// Assert.assertEquals("Unexpected firmware version: " + calculatedVersion, MI1A_FW_VERSION, calculatedVersion); + + String version = MiBandFWHelper.formatFirmwareVersion(calculatedVersion); + Assert.assertTrue(version.startsWith("5.")); + } + + @Test + public void testFirmwareMi1S() throws Exception{ + byte[] wholeFw = getFirmwareMi1S(); + Assert.assertNotNull(wholeFw); + + Assert.assertFalse(Mi1SInfo.isSingleMiBandFirmware(wholeFw)); + + // Mi Band version + int calculatedLengthFw1 = Mi1SInfo.getFirmware1LengthIn(wholeFw); + int calculatedOffsetFw1 = Mi1SInfo.getFirmware1OffsetIn(wholeFw); + int endIndexFw1 = calculatedOffsetFw1 + calculatedLengthFw1; + + int calculatedLengthFw2 = Mi1SInfo.getFirmware2LengthIn(wholeFw); + int calculatedOffsetFw2 = Mi1SInfo.getFirmware2OffsetIn(wholeFw); + int endIndexFw2 = calculatedOffsetFw2 + calculatedLengthFw2; + + Assert.assertTrue(endIndexFw1 <= wholeFw.length - calculatedLengthFw2); + Assert.assertTrue(endIndexFw2 <= wholeFw.length); + + Assert.assertTrue(endIndexFw1 <= calculatedOffsetFw2); + int calculatedVersionFw1 = Mi1SInfo.getFirmware1VersionFrom(wholeFw); +// Assert.assertEquals("Unexpected firmware 1 version: " + calculatedVersionFw1, MI1S_FW1_VERSION, calculatedVersionFw1); + String version1 = MiBandFWHelper.formatFirmwareVersion(calculatedVersionFw1); + Assert.assertTrue(version1.startsWith("4.")); + + // HR version + int calculatedVersionFw2 = Mi1SInfo.getFirmware2VersionFrom(wholeFw); +// Assert.assertEquals("Unexpected firmware 2 version: " + calculatedVersionFw2, MI1S_FW2_VERSION, calculatedVersionFw2); + String version2 = MiBandFWHelper.formatFirmwareVersion(calculatedVersionFw2); + Assert.assertTrue(version2.startsWith("1.")); + } + + private File getFirmwareDir() { + String path = System.getProperty("MiFirmwareDir"); + Assert.assertNotNull(path); + File dir = new File(path); + Assert.assertTrue(dir.isDirectory()); + return dir; + } + + private byte[] getFirmwareMi() throws IOException { + return getFirmware(new File(getFirmwareDir(), "Mili.fw")); + } + + private byte[] getFirmwareMi1A() throws IOException { + return getFirmware(new File(getFirmwareDir(), "Mili_1a.fw")); + } + + private byte[] getFirmwareMi1S() throws IOException { + return getFirmware(new File(getFirmwareDir(), "Mili_hr.fw")); + } + + private byte[] getFirmware(File aFile) throws IOException { + Assert.assertNotNull(aFile); + try (FileInputStream stream = new FileInputStream(aFile)) { + return FileUtils.readAll(stream, MAX_FILE_SIZE_BYTES); + } + } + +}