blob: 77683c05646f8bb942e4e9b543faf355885016b0 [file] [log] [blame]
// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package io.v.android.impl.google.discovery.plugins.ble;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
import junit.framework.TestCase;
import org.joda.time.Duration;
import org.junit.Test;
import io.v.v23.discovery.AdId;
import io.v.v23.discovery.Advertisement;
import io.v.v23.discovery.Attributes;
import io.v.v23.discovery.Attachments;
import io.v.x.ref.lib.discovery.AdInfo;
import io.v.x.ref.lib.discovery.AdHash;
import io.v.x.ref.lib.discovery.EncryptionAlgorithm;
import io.v.x.ref.lib.discovery.EncryptionKey;
import static com.google.common.truth.Truth.assertThat;
import static io.v.impl.google.lib.discovery.DiscoveryTestUtil.assertThat;
/**
* Tests for {@link DeviceCache}.
*/
public class DeviceCacheTest extends TestCase {
private static Random rand = new Random();
private static byte[] randBytes(int size) {
byte[] bytes = new byte[size];
rand.nextBytes(bytes);
return bytes;
}
private static AdInfo newAdInfo(String interfaceName) {
return new AdInfo(
new Advertisement(
new AdId(randBytes(AdId.VDL_TYPE.getLength())),
interfaceName,
ImmutableList.<String>of(),
new Attributes(),
new Attachments()),
new EncryptionAlgorithm(),
ImmutableList.<EncryptionKey>of(),
new AdHash(randBytes(AdHash.VDL_TYPE.getLength())),
ImmutableList.<String>of(),
false);
}
private static AdInfo copyAdInfo(AdInfo adinfo) {
return new AdInfo(
new Advertisement(
adinfo.getAd().getId(),
adinfo.getAd().getInterfaceName(),
adinfo.getAd().getAddresses(),
adinfo.getAd().getAttributes(),
adinfo.getAd().getAttachments()),
adinfo.getEncryptionAlgorithm(),
adinfo.getEncryptionKeys(),
adinfo.getHash(),
adinfo.getDirAddrs(),
adinfo.getLost());
}
private static List<AdInfo> newAdInfoList(AdInfo... adinfos) {
return Lists.transform(
ImmutableList.copyOf(adinfos),
new Function<AdInfo, AdInfo>() {
@Override
public AdInfo apply(AdInfo adinfo) {
return copyAdInfo(adinfo);
}
});
}
private static class MockHandler implements Plugin.ScanHandler {
private List<AdInfo> updates = new ArrayList<>();
@Override
public synchronized void handleUpdate(AdInfo adinfo) {
updates.add(copyAdInfo(adinfo));
notifyAll();
}
}
public void testSaveDeveice() {
DeviceCache cache = new DeviceCache(Duration.standardMinutes(10));
// The advertisements here are not relevant since we are just checking
// the seen stamp function.
long stamp = 10001;
assertThat(cache.haveSeenStamp(stamp, "device")).isFalse();
cache.saveDevice(stamp, "device", ImmutableList.<AdInfo>of());
assertThat(cache.haveSeenStamp(stamp, "device")).isTrue();
cache.shutdownCache();
}
public void testSaveDeviceWithDifferentStampCode() {
DeviceCache cache = new DeviceCache(Duration.standardMinutes(10));
// The advertisements here are not relevant since we are just checking
// the seen stamp function.
long stamp = 10001;
assertThat(cache.haveSeenStamp(stamp, "device")).isFalse();
cache.saveDevice(stamp, "device", ImmutableList.<AdInfo>of());
assertThat(cache.haveSeenStamp(stamp, "device")).isTrue();
cache.saveDevice(stamp + 1, "device", ImmutableList.<AdInfo>of());
assertThat(cache.haveSeenStamp(stamp + 1, "device")).isTrue();
assertThat(cache.haveSeenStamp(stamp, "device")).isFalse();
cache.shutdownCache();
}
public void testAddingScannerBeforeSavingDevice() {
DeviceCache cache = new DeviceCache(Duration.standardMinutes(10));
long stamp = 10001;
AdInfo adinfo1 = newAdInfo("interface1");
AdInfo adinfo2 = newAdInfo("interface2");
MockHandler handler1 = new MockHandler();
cache.addScanner("interface1", handler1);
MockHandler handler2 = new MockHandler();
cache.addScanner("", handler2);
cache.saveDevice(stamp, "device", newAdInfoList(adinfo1, adinfo2));
// Make sure that the handlers are called;
assertThat(handler1.updates.size()).isEqualTo(1);
assertThat(handler1.updates.get(0)).isEqualTo(adinfo1);
assertThat(handler2.updates).isEqualTo(adinfo1, adinfo2);
cache.shutdownCache();
}
public void testAddingScannerAfterSavingDevice() {
DeviceCache cache = new DeviceCache(Duration.standardMinutes(10));
long stamp = 10001;
AdInfo adinfo1 = newAdInfo("interface1");
AdInfo adinfo2 = newAdInfo("interface2");
cache.saveDevice(stamp, "device", newAdInfoList(adinfo1, adinfo2));
MockHandler handler1 = new MockHandler();
cache.addScanner("interface1", handler1);
MockHandler handler2 = new MockHandler();
cache.addScanner("", handler2);
// Make sure that the handlers are called;
assertThat(handler1.updates.size()).isEqualTo(1);
assertThat(handler1.updates.get(0)).isEqualTo(adinfo1);
assertThat(handler2.updates).isEqualTo(adinfo1, adinfo2);
cache.shutdownCache();
}
public void testRemovingAdvertisement() {
DeviceCache cache = new DeviceCache(Duration.standardMinutes(10));
long stamp = 10001;
AdInfo adinfo1 = newAdInfo("interface1");
AdInfo adinfo2 = newAdInfo("interface2");
MockHandler handler = new MockHandler();
cache.addScanner("interface1", handler);
cache.saveDevice(stamp, "device", newAdInfoList(adinfo1, adinfo2));
cache.saveDevice(stamp + 1, "device", newAdInfoList(adinfo2));
// Make sure that the handler is called;
assertThat(handler.updates.size()).isEqualTo(2);
assertThat(handler.updates.get(0)).isEqualTo(adinfo1, false);
assertThat(handler.updates.get(1)).isEqualTo(adinfo1, true);
cache.shutdownCache();
}
public void testAddingSameAdvertisement() {
DeviceCache cache = new DeviceCache(Duration.standardMinutes(10));
long stamp = 10001;
AdInfo adinfo = newAdInfo("interface1");
MockHandler handler = new MockHandler();
cache.addScanner("interface1", handler);
cache.saveDevice(stamp, "device", newAdInfoList(adinfo));
cache.saveDevice(stamp + 1, "device", newAdInfoList(adinfo));
// Make sure that the handler is called;
assertThat(handler.updates.size()).isEqualTo(1);
assertThat(handler.updates.get(0)).isEqualTo(adinfo);
cache.shutdownCache();
}
public void testRemovingScanner() {
DeviceCache cache = new DeviceCache(Duration.standardMinutes(10));
long stamp = 10001;
AdInfo adinfo1 = newAdInfo("interface1");
AdInfo adinfo2 = newAdInfo("interface2");
MockHandler handler = new MockHandler();
cache.addScanner("interface1", handler);
cache.saveDevice(stamp, "device", newAdInfoList(adinfo1));
assertThat(handler.updates.size()).isEqualTo(1);
assertThat(handler.updates.get(0)).isEqualTo(adinfo1);
cache.removeScanner(handler);
cache.saveDevice(stamp, "device", newAdInfoList(adinfo2));
// Make sure that the handler is not called any more;
assertThat(handler.updates.size()).isEqualTo(1);
cache.shutdownCache();
}
@Test(timeout = 30000)
public void testCacheEviction() {
// TODO(jhahn): Use a fake ScheduledExecutorService.
DeviceCache cache = new DeviceCache(Duration.millis(2));
long stamp = 10001;
AdInfo adinfo = newAdInfo("interface1");
MockHandler handler = new MockHandler();
cache.addScanner("interface1", handler);
cache.saveDevice(stamp, "device", newAdInfoList(adinfo));
synchronized (handler) {
try {
while (handler.updates.size() < 2) {
handler.wait();
}
} catch (InterruptedException e) {
// Keep waiting.
}
}
// Make sure that the handler is called;
assertThat(handler.updates.size()).isEqualTo(2);
assertThat(handler.updates.get(0)).isEqualTo(adinfo, false);
assertThat(handler.updates.get(1)).isEqualTo(adinfo, true);
// Make sure that there is no cached entries.
handler = new MockHandler();
cache.addScanner("interface1", handler);
assertThat(handler.updates.size()).isEqualTo(0);
cache.shutdownCache();
}
}