/*
* Copyright 2015 Cel Skeggs
*
* This file is part of the CCRE, the Common Chicken Runtime Engine.
*
* The CCRE is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* The CCRE is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the CCRE. If not, see <http://www.gnu.org/licenses/>.
*/
package ccre.channel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.NoSuchElementException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ccre.testing.CountingEventOutput;
@SuppressWarnings("javadoc")
public class AbstractUpdatingInputTest {
private final EventOutput evil = new EventOutput() {
@Override
public void event() {
throw new NoSuchElementException("Attempted to fire an EVIL event.");
}
};
private CountingEventOutput ceo, ceo2, ceo3;
@Before
public void setUp() throws Exception {
ceo = new CountingEventOutput();
ceo2 = new CountingEventOutput();
ceo3 = new CountingEventOutput();
}
@After
public void tearDown() throws Exception {
ceo = ceo2 = ceo3 = null;
update = null;
}
// No tests for update() or the constructor are provided, as they are
// essentially a copy of the functionality from DerivedUpdate.
EventOutput update;
@Test
public void testOnUpdate() {
AbstractUpdatingInput dui = new AbstractUpdatingInput() {
{
update = () -> {
for (int i = 0; i < 10; i++) {
ceo.ifExpected = true;
ceo3.ifExpected = true;
perform();
ceo.check();
ceo3.check();
}
ceo2.event();
};
}
};
dui.onUpdate(ceo);
dui.onUpdate(ceo3);
for (int i = 0; i < 10; i++) {
ceo2.ifExpected = true;
update.event();
ceo2.check();
}
}
private boolean enabled, enabled3;
@Test
public void testOnUpdateR() {
AbstractUpdatingInput dui = new AbstractUpdatingInput() {
{
update = () -> {
for (int i = 0; i < 10; i++) {
ceo.ifExpected = enabled;
ceo3.ifExpected = enabled3;
perform();
ceo.check();
ceo3.check();
}
ceo2.event();
};
}
};
enabled = enabled3 = true;
CancelOutput dereg = dui.onUpdate(ceo);
CancelOutput dereg3 = dui.onUpdate(ceo3);
for (int i = 0; i < 10; i++) {
ceo2.ifExpected = true;
update.event();
ceo2.check();
}
dereg.cancel();
enabled = false;
for (int i = 0; i < 10; i++) {
ceo2.ifExpected = true;
update.event();
ceo2.check();
}
dereg3.cancel();
enabled3 = false;
for (int i = 0; i < 10; i++) {
ceo2.ifExpected = true;
update.event();
ceo2.check();
}
}
@Test(expected = NullPointerException.class)
public void testOnUpdateNull() {
new AbstractUpdatingInput() {
}.onUpdate(null);
}
@Test(expected = NoSuchElementException.class)
public void testSimpleError() {
new AbstractUpdatingInput() {
{
update = this::perform;
}
}.onUpdate(evil);
update.event();
}
@Test(expected = NoSuchElementException.class)
public void testDualErrorA() {
AbstractUpdatingInput dui = new AbstractUpdatingInput() {
{
update = this::perform;
}
};
dui.onUpdate(evil);
dui.onUpdate(ceo);
ceo.ifExpected = true;
try {
update.event();
} catch (NoSuchElementException e) {
assertEquals(e.getSuppressed().length, 0);
ceo.check();
throw e;
}
}
@Test(expected = NoSuchElementException.class)
public void testDualErrorB() {
AbstractUpdatingInput dui = new AbstractUpdatingInput() {
{
update = this::perform;
}
};
dui.onUpdate(ceo);
dui.onUpdate(evil);
ceo.ifExpected = true;
try {
update.event();
fail();
} catch (NoSuchElementException e) {
assertEquals(e.getSuppressed().length, 0);
ceo.check();
throw e;
}
}
@Test
public void testDualErrorBoth() {
AbstractUpdatingInput dui = new AbstractUpdatingInput() {
{
update = this::perform;
}
};
dui.onUpdate(evil);
dui.onUpdate(evil);
try {
update.event();
fail();
} catch (NoSuchElementException e) {
assertEquals(e.getSuppressed().length, 1);
assertTrue(e.getSuppressed()[0] instanceof NoSuchElementException);
}
}
@Test
public void testTrualErrorFirst() {
AbstractUpdatingInput dui = new AbstractUpdatingInput() {
{
update = this::perform;
}
};
dui.onUpdate(evil);
dui.onUpdate(ceo);
dui.onUpdate(ceo3);
ceo.ifExpected = ceo3.ifExpected = true;
try {
update.event();
fail();
} catch (NoSuchElementException e) {
ceo.check();
ceo3.check();
assertEquals(e.getSuppressed().length, 0);
}
}
@Test
public void testTrualErrorMiddle() {
AbstractUpdatingInput dui = new AbstractUpdatingInput() {
{
update = this::perform;
}
};
dui.onUpdate(ceo);
dui.onUpdate(evil);
dui.onUpdate(ceo3);
ceo.ifExpected = ceo3.ifExpected = true;
try {
update.event();
fail();
} catch (NoSuchElementException e) {
ceo.check();
ceo3.check();
assertEquals(e.getSuppressed().length, 0);
}
}
@Test
public void testTrualErrorLast() {
AbstractUpdatingInput dui = new AbstractUpdatingInput() {
{
update = this::perform;
}
};
dui.onUpdate(ceo);
dui.onUpdate(ceo3);
dui.onUpdate(evil);
ceo.ifExpected = ceo3.ifExpected = true;
try {
update.event();
fail();
} catch (NoSuchElementException e) {
ceo.check();
ceo3.check();
assertEquals(e.getSuppressed().length, 0);
}
}
@Test
public void testTrualErrorTwice() {
AbstractUpdatingInput dui = new AbstractUpdatingInput() {
{
update = this::perform;
}
};
dui.onUpdate(evil);
dui.onUpdate(evil);
dui.onUpdate(ceo);
ceo.ifExpected = true;
try {
update.event();
fail();
} catch (NoSuchElementException e) {
ceo.check();
assertEquals(e.getSuppressed().length, 1);
assertTrue(e.getSuppressed()[0] instanceof NoSuchElementException);
}
}
}