package org.altbeacon.beacon; import org.altbeacon.beacon.distance.ModelSpecificDistanceCalculator; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import org.robolectric.annotation.Config; import java.util.Arrays; import java.util.List; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; @Config(sdk = 18) @RunWith(RobolectricTestRunner.class) /* HOW TO SEE DEBUG LINES FROM YOUR UNIT TESTS: 1. set a line like this at the start of your test: org.robolectric.shadows.ShadowLog.stream = System.err; 2. run the tests from the command line 3. Look at the test report file in your web browser, e.g. file:///Users/dyoung/workspace/AndroidProximityLibrary/build/reports/tests/index.html 4. Expand the System.err section */ public class BeaconTest { @Before public void before() { Beacon.setHardwareEqualityEnforced(false); } @Test public void testAccessBeaconIdentifiers() { Beacon beacon = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6) .setBluetoothAddress("1:2:3:4:5:6").build(); assertEquals("First beacon id should be 1", beacon.getIdentifier(0).toString(), "1"); assertEquals("Second beacon id should be 1", beacon.getIdentifier(1).toString(), "2"); assertEquals("Third beacon id should be 1", beacon.getIdentifier(2).toString(), "3"); assertEquals("First beacon id should be 1", beacon.getId1().toString(), "1"); assertEquals("Second beacon id should be 1", beacon.getId2().toString(), "2"); assertEquals("Third beacon id should be 1", beacon.getId3().toString(), "3"); } @Test public void testBeaconsWithSameIdentifersAreEqual() { Beacon beacon1 = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6) .setBluetoothAddress("1:2:3:4:5:6").build(); Beacon beacon2 = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6) .setBluetoothAddress("1:2:3:4:5:6").build(); assertEquals("Beacons with same identifiers are equal", beacon1, beacon2); } @Test public void testBeaconsWithDifferentId1AreNotEqual() { org.robolectric.shadows.ShadowLog.stream = System.err; Beacon beacon1 = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6) .setBluetoothAddress("1:2:3:4:5:6").build(); Beacon beacon2 = new AltBeacon.Builder().setMfgReserved(7).setId1("11").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6) .setBluetoothAddress("1:2:3:4:5:6").build(); assertTrue("Beacons with different id1 are not equal", !beacon1.equals(beacon2)); } @Test public void testBeaconsWithDifferentId2AreNotEqual() { Beacon beacon1 = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6) .setBluetoothAddress("1:2:3:4:5:6").build(); Beacon beacon2 = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("12").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6) .setBluetoothAddress("1:2:3:4:5:6").build(); assertTrue("Beacons with different id2 are not equal", !beacon1.equals(beacon2)); } @Test public void testBeaconsWithDifferentId3AreNotEqual() { Beacon beacon1 = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6) .setBluetoothAddress("1:2:3:4:5:6").build(); Beacon beacon2 = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("2").setId3("13").setRssi(4) .setBeaconTypeCode(5).setTxPower(6) .setBluetoothAddress("1:2:3:4:5:6").build(); assertTrue("Beacons with different id3 are not equal", !beacon1.equals(beacon2)); } @Test public void testBeaconsWithSameMacsAreEqual() { Beacon.setHardwareEqualityEnforced(true); Beacon beacon1 = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6) .setBluetoothAddress("1:2:3:4:5:6").build(); Beacon beacon2 = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6) .setBluetoothAddress("1:2:3:4:5:6").build(); assertTrue("Beacons with same same macs are equal", beacon1.equals(beacon2)); } @Test public void testBeaconsWithDifferentMacsAreNotEqual() { Beacon.setHardwareEqualityEnforced(true); Beacon beacon1 = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6) .setBluetoothAddress("1:2:3:4:5:6").build(); Beacon beacon2 = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6) .setBluetoothAddress("1:2:3:4:5:666666").build(); assertTrue("Beacons with different same macs are not equal", !beacon1.equals(beacon2)); } @Test public void testCalculateAccuracyWithRssiEqualsPower() { Beacon.setDistanceCalculator(new ModelSpecificDistanceCalculator(null, null)); double accuracy = Beacon.calculateDistance(-55, -55); assertEquals("Distance should be one meter if mRssi is the same as power", 1.0, accuracy, 0.1); } @Test public void testCalculateAccuracyWithRssiGreaterThanPower() { Beacon.setDistanceCalculator(new ModelSpecificDistanceCalculator(null, null)); double accuracy = Beacon.calculateDistance(-55, -50); assertTrue("Distance should be under one meter if mRssi is less negative than power. Accuracy was " + accuracy, accuracy < 1.0); } @Test public void testCalculateAccuracyWithRssiLessThanPower() { Beacon.setDistanceCalculator(new ModelSpecificDistanceCalculator(null, null)); double accuracy = Beacon.calculateDistance(-55, -60); assertTrue("Distance should be over one meter if mRssi is less negative than power. Accuracy was "+accuracy, accuracy > 1.0); } @Test public void testCalculateAccuracyWithRssiEqualsPowerOnInternalProperties() { Beacon.setDistanceCalculator(new ModelSpecificDistanceCalculator(null, null)); Beacon beacon = new Beacon.Builder().setTxPower(-55).setRssi(-55).build(); double distance = beacon.getDistance(); assertEquals("Distance should be one meter if mRssi is the same as power", 1.0, distance, 0.1); } @Test public void testCalculateAccuracyWithRssiEqualsPowerOnInternalPropertiesAndRunningAverage() { Beacon beacon = new Beacon.Builder().setTxPower(-55).setRssi(0).build(); beacon.setRunningAverageRssi(-55); double distance = beacon.getDistance(); assertEquals("Distance should be one meter if mRssi is the same as power", 1.0, distance, 0.1); } @Test public void testCanSerialize() throws Exception { org.robolectric.shadows.ShadowLog.stream = System.err; Beacon beacon = new AltBeacon.Builder().setId1("1").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6).setBluetoothName("xx") .setBluetoothAddress("1:2:3:4:5:6").setDataFields(Arrays.asList(100l)).build(); byte[] serializedBeacon = convertToBytes(beacon); Beacon beacon2 = (Beacon) convertFromBytes(serializedBeacon); assertEquals("Right number of identifiers after deserialization", 3, beacon2.mIdentifiers.size()); assertEquals("id1 is same after deserialization", beacon.getIdentifier(0), beacon2.getIdentifier(0)); assertEquals("id2 is same after deserialization", beacon.getIdentifier(1), beacon2.getIdentifier(1)); assertEquals("id3 is same after deserialization", beacon.getIdentifier(2), beacon2.getIdentifier(2)); assertEquals("txPower is same after deserialization", beacon.getTxPower(), beacon2.getTxPower()); assertEquals("rssi is same after deserialization", beacon.getRssi(), beacon2.getRssi()); assertEquals("distance is same after deserialization", beacon.getDistance(), beacon2.getDistance(), 0.001); assertEquals("bluetoothAddress is same after deserialization", beacon.getBluetoothAddress(), beacon2.getBluetoothAddress()); assertEquals("bluetoothAddress is same after deserialization", beacon.getBluetoothName(), beacon2.getBluetoothName()); assertEquals("beaconTypeCode is same after deserialization", beacon.getBeaconTypeCode(), beacon2.getBeaconTypeCode()); assertEquals("manufacturer is same after deserialization", beacon.getManufacturer(), beacon2.getManufacturer()); assertEquals("data field 0 is the same after deserialization", beacon.getDataFields().get(0), beacon2.getDataFields().get(0)); assertEquals("data field 0 is the right value", beacon.getDataFields().get(0), (Long) 100l); } @Test public void noDoubleWrappingOfExtraDataFields() { org.robolectric.shadows.ShadowLog.stream = System.err; Beacon beacon = new AltBeacon.Builder().setId1("1").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6).setBluetoothName("xx") .setBluetoothAddress("1:2:3:4:5:6").setDataFields(Arrays.asList(100l)).build(); List<Long> list = beacon.getExtraDataFields(); beacon.setExtraDataFields(list); assertTrue("getter should return same object after first wrap ", beacon.getExtraDataFields() == list); } @Test public void testHashCodeWithNullIdentifier() { Beacon beacon = new AltBeacon.Builder() .setIdentifiers(Arrays.asList( Identifier.parse("0x1234"), null)) .build(); assertTrue("hashCode() should not throw exception", beacon.hashCode() >= Integer.MIN_VALUE); } // utilty methods for testing serialization private byte[] convertToBytes(Object object) throws IOException { try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos)) { out.writeObject(object); return bos.toByteArray(); } } private Object convertFromBytes(byte[] bytes) throws IOException, ClassNotFoundException { try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInputStream in = new ObjectInputStream(bis)) { return in.readObject(); } } }