content: package org.altbeacon.beacon;
  
  import static android.test.MoreAsserts.assertNotEqual;
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertNull;
  import static org.junit.Assert.assertTrue;
  import static org.junit.Assert.assertFalse;
  
  import org.robolectric.RobolectricTestRunner;
  
  import org.junit.runner.RunWith;
  import org.junit.Test;
  import org.robolectric.annotation.Config;
  
  import java.util.ArrayList;
  import java.util.Collections;
  
  import java.io.ObjectOutputStream;
  import java.io.ObjectInputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.ByteArrayInputStream;
  import java.io.IOException;
  
  @Config(sdk = 28)
  
  @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 RegionTest {
      @Test
      public void testBeaconMatchesRegionWithSameIdentifiers() {
          Beacon beacon = new AltBeacon.Builder().setId1("1").setId2("2").setId3("3").setRssi(4)
                  .setBeaconTypeCode(5).setTxPower(6).setBluetoothAddress("1:2:3:4:5:6").build();
          Region region = new Region("myRegion", Identifier.parse("1"), Identifier.parse("2"), Identifier.parse("3"));
          assertTrue("Beacon should match region with all identifiers the same", region.matchesBeacon(beacon));
      }
  
      @Test
      public void testBeaconMatchesRegionWithSameIdentifier1() {
          Beacon beacon = new AltBeacon.Builder().setId1("1").setId2("2").setId3("3").setRssi(4)
                  .setBeaconTypeCode(5).setTxPower(6).setBluetoothAddress("1:2:3:4:5:6").build();
          Region region = new Region("myRegion", Identifier.parse("1"), null, null);
          assertTrue("Beacon should match region with first identifier the same", region.matchesBeacon(beacon));
      }
  
      @Test
      public void testBeaconMatchesRegionWithSameIdentifier1And2() {
          Beacon beacon = new AltBeacon.Builder().setId1("1").setId2("2").setId3("3").setRssi(4)
                  .setBeaconTypeCode(5).setTxPower(6).setBluetoothAddress("1:2:3:4:5:6").build();
          Region region = new Region("myRegion", Identifier.parse("1"), Identifier.parse("2"), null);
          assertTrue("Beacon should match region with first two identifiers the same", region.matchesBeacon(beacon));
      }
  
      @Test
      public void testBeaconMatchesRegionWithDifferentIdentifier1() {
          Beacon beacon = new AltBeacon.Builder().setId1("1").setId2("2").setId3("3").setRssi(4)
                  .setBeaconTypeCode(5).setTxPower(6).setBluetoothAddress("1:2:3:4:5:6").build();
          Region region = new Region("myRegion", Identifier.parse("22222"), null, null);
          assertTrue("Beacon should not match region with first identifier different", !region.matchesBeacon(beacon));
      }
  
      @Test
      public void testBeaconMatchesRegionWithShorterIdentifierList() {
          Beacon beacon = new AltBeacon.Builder().setId1("1").setId2("2").setId3("3").setRssi(4)
                  .setBeaconTypeCode(5).setTxPower(6).setBluetoothAddress("1:2:3:4:5:6").build();
          Region region = new Region("myRegion", Collections.singletonList(Identifier.parse("1")));
          assertTrue("Beacon should match region with first identifier equal and shorter Identifier list", region.matchesBeacon(beacon));
      }
  
      @Test
      public void testBeaconMatchesRegionWithSingleNullIdentifierList() {
          Beacon beacon = new AltBeacon.Builder().setId1("1").setId2("2").setId3("3").setRssi(4)
                  .setBeaconTypeCode(5).setTxPower(6).setBluetoothAddress("1:2:3:4:5:6").build();
          ArrayList<Identifier> identifiers=new ArrayList<>();
          identifiers.add(null);
          Region region=new Region("all-beacons-region",identifiers);
          assertTrue("Beacon should match region with first identifier null and shorter Identifier list", region.matchesBeacon(beacon));
      }
  
      @Test
      public void testBeaconDoesntMatchRegionWithLongerIdentifierList() {
          Beacon beacon = new Beacon.Builder().setId1("1").setId2("2").setRssi(4)
                  .setBeaconTypeCode(5).setTxPower(6).setBluetoothAddress("1:2:3:4:5:6").build();
          Region region = new Region("myRegion", Identifier.parse("1"), Identifier.parse("2"), Identifier.parse("3"));
          assertFalse("Beacon should not match region with more identifers than the beacon", region.matchesBeacon(beacon));
      }
  
      @Test
      public void testBeaconDoesMatchRegionWithLongerIdentifierListWithSomeNull() {
          Beacon beacon = new Beacon.Builder().setId1("1").setId2("2").setRssi(4)
                  .setBeaconTypeCode(5).setTxPower(6).setBluetoothAddress("1:2:3:4:5:6").build();
          Region region = new Region("myRegion", null, null, null);
          assertTrue("Beacon should match region with more identifers than the beacon, if the region identifiers are null", region.matchesBeacon(beacon));
      }
  
      @Test
      public void testBeaconMatchesRegionWithSameBluetoothMac() {
          Beacon beacon = new AltBeacon.Builder().setId1("1").setId2("2").setId3("3").setRssi(4)
                  .setBeaconTypeCode(5).setTxPower(6).setBluetoothAddress("01:02:03:04:05:06").build();
          Region region = new Region("myRegion", "01:02:03:04:05:06");
          assertTrue("Beacon should match region with mac the same", region.matchesBeacon(beacon));
      }
  
      @Test
      public void testBeaconDoesNotMatchRegionWithDiffrentBluetoothMac() {
          Beacon beacon = new AltBeacon.Builder().setId1("1").setId2("2").setId3("3").setRssi(4)
                  .setBeaconTypeCode(5).setTxPower(6).setBluetoothAddress("01:02:03:04:05:06").build();
          Region region = new Region("myRegion", "01:02:03:04:05:99");
          assertFalse("Beacon should match region with mac the same", region.matchesBeacon(beacon));
      }
  
      @Test
      public void testBeaconMatchesRegionWithSameBluetoothMacAndIdentifiers() {
          Beacon beacon = new AltBeacon.Builder().setId1("1").setId2("2").setId3("3").setRssi(4)
                  .setBeaconTypeCode(5).setTxPower(6).setBluetoothAddress("01:02:03:04:05:06").build();
          ArrayList identifiers = new ArrayList<Identifier>();
          identifiers.add(Identifier.parse("1"));
          identifiers.add(Identifier.parse("2"));
          identifiers.add(Identifier.parse("3"));
          Region region = new Region("myRegion", identifiers , "01:02:03:04:05:06");
          assertTrue("Beacon should match region with mac the same", region.matchesBeacon(beacon));
      }
  
  
      @Test
      public void testCanSerialize() throws Exception {
          org.robolectric.shadows.ShadowLog.stream = System.err;
          Region region = new Region("myRegion", Identifier.parse("1"), Identifier.parse("2"), null);
          byte[] serializedRegion = convertToBytes(region);
          Region region2 = (Region) convertFromBytes(serializedRegion);
          assertEquals("Right number of identifiers after deserialization", 3, region2.mIdentifiers.size());
          assertEquals("uniqueId is same after deserialization", region.getUniqueId(), region2.getUniqueId());
          assertEquals("id1 is same after deserialization", region.getIdentifier(0), region2.getIdentifier(0));
          assertEquals("id2 is same after deserialization", region.getIdentifier(1), region2.getIdentifier(1));
          assertNull("id3 is null before deserialization", region.getIdentifier(2));
          assertNull("id3 is null after deserialization", region2.getIdentifier(2));
      }
  
      @Test
      public void testCanSerializeWithMac() throws Exception {
          org.robolectric.shadows.ShadowLog.stream = System.err;
          Region region = new Region("myRegion", "1B:2a:03:4C:6E:9F");
          byte[] serializedRegion = convertToBytes(region);
          Region region2 = (Region) convertFromBytes(serializedRegion);
          assertEquals("Right number of identifiers after deserialization", 0, region2.mIdentifiers.size());
          assertEquals("ac is same after deserialization", region.getBluetoothAddress(), region2.getBluetoothAddress());
      }
  
      @Test
      public void rejectsInvalidMac() {
          org.robolectric.shadows.ShadowLog.stream = System.err;
          try {
              Region region = new Region("myRegion", "this string is not a valid mac address!");
              assertTrue("IllegalArgumentException should have been thrown", false);
          }
          catch (IllegalArgumentException e) {
              assertEquals("Error message should be as expected",
                      "Invalid mac address: 'this string is not a valid mac address!' Must be 6 hex bytes separated by colons.",
                      e.getMessage());
          }
      }
  
  
      @Test
      public void testToString() {
          Region region = new Region("myRegion", Identifier.parse("1"), Identifier.parse("2"), null);
          assertEquals("id1: 1 id2: 2 id3: null", region.toString());
      }
  
      @Test
      public void testConvenienceIdentifierAccessors() {
          Region region = new Region("myRegion", Identifier.parse("1"), Identifier.parse("2"), Identifier.parse("3"));
          assertEquals("1", region.getId1().toString());
          assertEquals("2", region.getId2().toString());
          assertEquals("3", region.getId3().toString());
      }
  
      // 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();
          }
      }
  
  
  }
  