blob: 5a91cdc65868cfb0bfc5c5d07f48e8e50bac7a0e [file] [log] [blame]
// Copyright 2015 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.moments.lib;
import android.os.Handler;
import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import io.v.moments.ifc.AdConverter;
import io.v.moments.ifc.HasId;
import io.v.moments.ifc.IdSet;
import io.v.moments.ifc.ListObserver;
import io.v.v23.discovery.Attachments;
import io.v.v23.discovery.Attributes;
import io.v.v23.discovery.Found;
import io.v.v23.discovery.Lost;
import io.v.v23.discovery.Service;
import io.v.v23.discovery.Update;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class DiscoveredListTest {
static final Thing THING0 = makeThing("hey0");
static final Thing THING1 = makeThing("hey1");
static final Id ID0 = THING0.getId();
@Rule
public ExpectedException mThrown = ExpectedException.none();
@Mock
ListObserver mObserver;
@Mock
AdConverter<Thing> mConverter;
@Mock
IdSet mRejects;
@Mock
Handler mHandler;
@Mock
io.v.v23.discovery.Service mAdvertisement;
@Captor
ArgumentCaptor<Runnable> mRunnable;
DiscoveredList<Thing> mList;
static Thing makeThing(String v) {
return new Thing(v, Id.makeRandom());
}
@Before
public void setup() {
mList = new DiscoveredList<>(mConverter, mRejects, mHandler);
// By default, ID0 is not rejected.
when(mRejects.contains(ID0)).thenReturn(false);
when(mAdvertisement.getInstanceId()).thenReturn(ID0.toString());
}
@Test
public void newListEmpty() throws Exception {
assertEquals(0, mList.size());
}
@Test
public void constructorFailsWithNoConverter() throws Exception {
mThrown.expect(IllegalArgumentException.class);
mThrown.expectMessage("Null converter");
mList = new DiscoveredList<>(null, mRejects, mHandler);
}
@Test
public void constructorFailsWithNoIdSet() throws Exception {
mThrown.expect(IllegalArgumentException.class);
mThrown.expectMessage("Null rejects");
mList = new DiscoveredList<>(mConverter, null, mHandler);
}
@Test
public void constructorFailsWithNoHandler() throws Exception {
mThrown.expect(IllegalArgumentException.class);
mThrown.expectMessage("Null handler");
mList = new DiscoveredList<>(mConverter, mRejects, null);
}
@Test
public void addFailsWithNoObserver() throws Exception {
mThrown.expect(IllegalStateException.class);
mThrown.expectMessage("No observer for add");
mList.push(THING0);
}
@Test
public void setFailsWithNoObserver() throws Exception {
mThrown.expect(IllegalStateException.class);
mThrown.expectMessage("No observer for set");
mList.set(0, THING1);
}
@Test
public void changeFailsWithNoObserver() throws Exception {
mThrown.expect(IllegalStateException.class);
mThrown.expectMessage("No observer for change");
mList.change(0);
}
@Test
public void removeFailsWithNoObserver() throws Exception {
mThrown.expect(IllegalStateException.class);
mThrown.expectMessage("No observer for remove");
mList.remove(0);
}
@Test
public void insertionWorks() throws Exception {
mList.setObserver(mObserver);
mList.push(THING0);
verify(mObserver).notifyItemInserted(0);
assertEquals(1, mList.size());
assertEquals(THING0, mList.get(0));
}
/**
* Advertisements from others (not-self) should be handled/observed.
*/
@Test
public void handleNormalFound() throws Exception {
mList.setObserver(mObserver);
when(mConverter.make(mAdvertisement)).thenReturn(THING0);
mList.scanUpdateReceived(new Update.Found(new Found(mAdvertisement)));
verify(mHandler).post(mRunnable.capture());
mRunnable.getValue().run();
assertEquals(1, mList.size());
assertEquals(THING0, mList.get(0));
verify(mObserver).notifyItemInserted(0);
}
/**
* Advertisements from self should not be handled/observed.
*/
@Test
public void handleSelfFound() throws Exception {
mList.setObserver(mObserver);
when(mRejects.contains(ID0)).thenReturn(true);
mList.scanUpdateReceived(new Update.Found(new Found(mAdvertisement)));
verifyZeroInteractions(mHandler);
verifyZeroInteractions(mObserver);
assertEquals(0, mList.size());
}
/**
* Do nothing upon loss of an unrecognized advertisement.
*/
@Test
public void handleUnrecognizedLost() throws Exception {
mList.setObserver(mObserver);
mList.scanUpdateReceived(new Update.Lost(new Lost(mAdvertisement)));
verify(mHandler).post(mRunnable.capture());
mRunnable.getValue().run();
// Currently nothing happens - not even an error.
assertEquals(0, mList.size());
verifyZeroInteractions(mHandler);
verifyZeroInteractions(mObserver);
}
/**
* Do nothing upon loss of a self-advertisement.
*/
@Test
public void handleSelfLost() throws Exception {
mList.setObserver(mObserver);
when(mRejects.contains(ID0)).thenReturn(true);
mList.scanUpdateReceived(new Update.Lost(new Lost(mAdvertisement)));
verify(mHandler).post(mRunnable.capture());
mRunnable.getValue().run();
// Currently nothing happens.
assertEquals(0, mList.size());
verifyZeroInteractions(mHandler);
verifyZeroInteractions(mObserver);
}
/**
* Handle the loss of a non-self advertisement.
*/
@Test
public void handleNormalLost() throws Exception {
mList.setObserver(mObserver);
mList.add(0, THING0);
verify(mObserver).notifyItemInserted(0);
assertEquals(1, mList.size());
mList.scanUpdateReceived(new Update.Lost(new Lost(mAdvertisement)));
verify(mHandler).post(mRunnable.capture());
mRunnable.getValue().run();
assertEquals(0, mList.size());
verify(mObserver).notifyItemRemoved(0);
}
@Test
public void dropAll() throws Exception {
mList.setObserver(mObserver);
mList.push(THING0);
mList.push(THING1);
verify(mObserver, times(2)).notifyItemInserted(0);
assertEquals(2, mList.size());
mList.dropAll();
verify(mHandler).post(mRunnable.capture());
mRunnable.getValue().run();
assertEquals(0, mList.size());
verify(mObserver).notifyItemRemoved(1);
verify(mObserver).notifyItemRemoved(0);
verifyNoMoreInteractions(mObserver);
}
@Test
public void badInsertionFails() throws Exception {
mThrown.expect(IndexOutOfBoundsException.class);
mList.setObserver(mObserver);
mList.add(333, THING0);
verify(mObserver, never()).notifyItemInserted(333);
}
@Test
public void removeWorks() throws Exception {
mList.setObserver(mObserver);
mList.add(0, THING0);
verify(mObserver).notifyItemInserted(0);
mList.add(1, THING1);
verify(mObserver).notifyItemInserted(1);
assertEquals(2, mList.size());
assertEquals(THING0, mList.get(0));
assertEquals(THING1, mList.get(1));
assertEquals(THING0, mList.remove(0));
verify(mObserver).notifyItemRemoved(0);
assertEquals(1, mList.size());
assertEquals(THING1, mList.get(0));
}
@Test
public void badRemoveFails() throws Exception {
mThrown.expect(IndexOutOfBoundsException.class);
mList.setObserver(mObserver);
mList.remove(333);
verifyZeroInteractions(mObserver);
}
@Test
public void setWorks() throws Exception {
mList.setObserver(mObserver);
mList.add(0, THING0);
verify(mObserver).notifyItemInserted(0);
assertEquals(1, mList.size());
assertEquals(THING0, mList.get(0));
mList.set(0, THING1);
assertEquals(1, mList.size());
assertEquals(THING1, mList.get(0));
verify(mObserver).notifyItemChanged(0);
}
@Test
public void badSetFails() throws Exception {
mThrown.expect(IndexOutOfBoundsException.class);
mList.setObserver(mObserver);
mList.set(0, THING0);
verifyZeroInteractions(mObserver);
}
@Test
public void changeWorks() throws Exception {
mList.setObserver(mObserver);
mList.add(0, THING0);
verify(mObserver).notifyItemInserted(0);
// Not truly changing, since there's no check for it.
mList.change(0);
verify(mObserver).notifyItemChanged(0);
}
@Test
public void badChangeFails() throws Exception {
mThrown.expect(IndexOutOfBoundsException.class);
mList.setObserver(mObserver);
mList.change(333);
verifyZeroInteractions(mObserver);
}
static class Thing implements HasId {
private String mValue;
private Id mId;
public Thing(String v, Id id) {
mValue = v;
mId = id;
}
public Id getId() {
return mId;
}
}
}