/*
* Copyright 2015-2016 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.cluck;
import java.io.IOException;
import java.io.OutputStream;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ccre.channel.BooleanCell;
import ccre.channel.BooleanInput;
import ccre.channel.BooleanOutput;
import ccre.channel.EventCell;
import ccre.channel.EventInput;
import ccre.channel.EventOutput;
import ccre.channel.FloatCell;
import ccre.channel.FloatInput;
import ccre.channel.FloatOutput;
import ccre.log.LogLevel;
import ccre.log.LoggingTarget;
import ccre.log.VerifyingLoggingTarget;
import ccre.testing.CountingBooleanOutput;
import ccre.testing.CountingEventOutput;
import ccre.testing.CountingFloatOutput;
import ccre.util.Utils;
import ccre.util.Values;
@SuppressWarnings("javadoc")
public class CluckPublisherTest {
private CluckNode node;
// TODO: test subscribing with a slash
@Before
public void setUp() throws Exception {
node = new CluckNode();
}
@After
public void tearDown() throws Exception {
node = null;
}
@Test
public void testEventOutput() {
for (int i = 0; i < 20; i++) {
String name = Values.getRandomString();
if (name.contains("/") || node.hasLink(name)) {
i--;
continue;
}
CountingEventOutput ceo = new CountingEventOutput();
CluckPublisher.publish(node, name, ceo);
EventOutput proxy = CluckPublisher.subscribeEO(node, name);
for (int j = 0; j < 10; j++) {
ceo.ifExpected = true;
proxy.event();
ceo.check();
}
}
}
@Test(expected = NullPointerException.class)
public void testEventOutputNullA() {
CluckPublisher.publish(null, "hello", EventOutput.ignored);
}
@Test(expected = NullPointerException.class)
public void testEventOutputNullB() {
CluckPublisher.publish(node, null, EventOutput.ignored);
}
@Test(expected = NullPointerException.class)
public void testEventOutputNullC() {
CluckPublisher.publish(node, "hello", (EventOutput) null);
}
@Test(expected = IllegalArgumentException.class)
public void testEventOutputWithSlash() {
CluckPublisher.publish(node, "hello/other", EventOutput.ignored);
}
@Test(expected = NullPointerException.class)
public void testSubscribeEONullA() {
CluckPublisher.subscribeEO(null, "hello");
}
@Test(expected = NullPointerException.class)
public void testSubscribeEONullB() {
CluckPublisher.subscribeEO(node, null);
}
@Test
public void testEventInput() {
for (int i = 0; i < 20; i++) {
String name = Values.getRandomString();
if (name.contains("/") || node.hasLink(name)) {
i--;
continue;
}
CountingEventOutput ceo = new CountingEventOutput();
EventCell es = new EventCell();
CluckPublisher.publish(node, name, es.asInput());
CluckPublisher.subscribeEI(node, name).send(ceo);
for (int j = 0; j < 10; j++) {
ceo.ifExpected = true;
es.event();
ceo.check();
}
}
}
@Test(expected = NullPointerException.class)
public void testEventInputNullA() {
CluckPublisher.publish(null, "hello", EventInput.never);
}
@Test(expected = NullPointerException.class)
public void testEventInputNullB() {
CluckPublisher.publish(node, null, EventInput.never);
}
@Test(expected = NullPointerException.class)
public void testEventInputNullC() {
CluckPublisher.publish(node, "hello", (EventInput) null);
}
@Test(expected = IllegalArgumentException.class)
public void testEventInputWithSlash() {
CluckPublisher.publish(node, "hello/other", EventInput.never);
}
@Test(expected = NullPointerException.class)
public void testSubscribeEINullA() {
CluckPublisher.subscribeEI(null, "hello");
}
@Test(expected = NullPointerException.class)
public void testSubscribeEINullB() {
CluckPublisher.subscribeEI(node, null);
}
@Test
public void testBooleanOutput() {
for (int i = 0; i < 20; i++) {
String name = Values.getRandomString();
if (name.contains("/") || node.hasLink(name)) {
i--;
continue;
}
CountingBooleanOutput cbo = new CountingBooleanOutput();
CluckPublisher.publish(node, name, cbo);
BooleanOutput proxy = CluckPublisher.subscribeBO(node, name);
for (boolean b : Values.interestingBooleans) {
cbo.valueExpected = b;
cbo.ifExpected = true;
proxy.set(b);
cbo.check();
}
}
}
@Test(expected = NullPointerException.class)
public void testBooleanOutputNullA() {
CluckPublisher.publish(null, "hello", BooleanOutput.ignored);
}
@Test(expected = NullPointerException.class)
public void testBooleanOutputNullB() {
CluckPublisher.publish(node, null, BooleanOutput.ignored);
}
@Test(expected = NullPointerException.class)
public void testBooleanOutputNullC() {
CluckPublisher.publish(node, "hello", (BooleanOutput) null);
}
@Test(expected = IllegalArgumentException.class)
public void testBooleanOutputWithSlash() {
CluckPublisher.publish(node, "hello/other", BooleanOutput.ignored);
}
@Test(expected = NullPointerException.class)
public void testSubscribeBONullA() {
CluckPublisher.subscribeBO(null, "hello");
}
@Test(expected = NullPointerException.class)
public void testSubscribeBONullB() {
CluckPublisher.subscribeBO(node, null);
}
@Test
public void testBooleanInput() {
for (int i = 0; i < 20; i++) {
String name = Values.getRandomString();
if (name.contains("/") || node.hasLink(name)) {
i--;
continue;
}
CountingBooleanOutput cbo = new CountingBooleanOutput();
BooleanCell bs = new BooleanCell();
CluckPublisher.publish(node, name, bs.asInput());
cbo.ifExpected = true;
cbo.valueExpected = false;
CluckPublisher.subscribeBI(node, name, false).send(cbo);
cbo.check();
for (boolean b : Values.interestingBooleans) {
cbo.valueExpected = b;
cbo.ifExpected = b != bs.get();
bs.set(b);
cbo.check();
}
}
}
@Test(expected = NullPointerException.class)
public void testBooleanInputNullA() {
CluckPublisher.publish(null, "hello", BooleanInput.alwaysFalse);
}
@Test(expected = NullPointerException.class)
public void testBooleanInputNullB() {
CluckPublisher.publish(node, null, BooleanInput.alwaysFalse);
}
@Test(expected = NullPointerException.class)
public void testBooleanInputNullC() {
CluckPublisher.publish(node, "hello", (BooleanInput) null);
}
@Test(expected = IllegalArgumentException.class)
public void testBooleanInputWithSlash() {
CluckPublisher.publish(node, "hello/other", BooleanInput.alwaysFalse);
}
@Test(expected = NullPointerException.class)
public void testSubscribeBINullA() {
CluckPublisher.subscribeBI(null, "hello", false);
}
@Test(expected = NullPointerException.class)
public void testSubscribeBINullB() {
CluckPublisher.subscribeBI(node, null, false);
}
@Test
public void testFloatOutput() {
for (int i = 0; i < 20; i++) {
String name = Values.getRandomString();
if (name.contains("/") || node.hasLink(name)) {
i--;
continue;
}
CountingFloatOutput cfo = new CountingFloatOutput();
CluckPublisher.publish(node, name, cfo);
FloatOutput proxy = CluckPublisher.subscribeFO(node, name);
for (float f : Values.interestingFloats) {
cfo.valueExpected = f;
cfo.ifExpected = true;
proxy.set(f);
cfo.check();
}
}
}
@Test(expected = NullPointerException.class)
public void testFloatOutputNullA() {
CluckPublisher.publish(null, "hello", FloatOutput.ignored);
}
@Test(expected = NullPointerException.class)
public void testFloatOutputNullB() {
CluckPublisher.publish(node, null, FloatOutput.ignored);
}
@Test(expected = NullPointerException.class)
public void testFloatOutputNullC() {
CluckPublisher.publish(node, "hello", (FloatOutput) null);
}
@Test(expected = IllegalArgumentException.class)
public void testFloatOutputWithSlash() {
CluckPublisher.publish(node, "hello/other", FloatOutput.ignored);
}
@Test(expected = NullPointerException.class)
public void testSubscribeFONullA() {
CluckPublisher.subscribeFO(null, "hello");
}
@Test(expected = NullPointerException.class)
public void testSubscribeFONullB() {
CluckPublisher.subscribeFO(node, null);
}
@Test
public void testFloatInput() {
for (float starting : Values.interestingFloats) {
String name = Values.getRandomString();
while (name.contains("/") || node.hasLink(name)) {
name = Values.getRandomString();
}
CountingFloatOutput cfo = new CountingFloatOutput();
FloatCell fs = new FloatCell(starting);
CluckPublisher.publish(node, name, fs.asInput());
cfo.ifExpected = true;
cfo.valueExpected = Float.NaN;
CluckPublisher.subscribeFI(node, name, false).send(new FloatOutput() {
private boolean first = true;
@Override
public void set(float v) {
cfo.set(v);
if (first) {
first = false;
cfo.check();
// this is because the subscription will first send a
// NaN and then update itself very quickly when the
// response returns (which is almost immediately)
cfo.ifExpected = !Float.isNaN(starting);
cfo.valueExpected = starting;
}
}
});
cfo.check(); // TODO: debug flakiness here
cfo.valueExpected = 0;
cfo.ifExpected = Float.floatToIntBits(starting) != Float.floatToIntBits(0);
fs.set(0);
cfo.check();
for (float f : Values.interestingFloats) {
cfo.valueExpected = f;
cfo.ifExpected = true;
fs.set(f);
cfo.check();
}
}
}
@Test(expected = NullPointerException.class)
public void testFloatInputNullA() {
CluckPublisher.publish(null, "hello", FloatInput.zero);
}
@Test(expected = NullPointerException.class)
public void testFloatInputNullB() {
CluckPublisher.publish(node, null, FloatInput.zero);
}
@Test(expected = NullPointerException.class)
public void testFloatInputNullC() {
CluckPublisher.publish(node, "hello", (FloatInput) null);
}
@Test(expected = IllegalArgumentException.class)
public void testFloatInputWithSlash() {
CluckPublisher.publish(node, "hello/other", FloatInput.zero);
}
@Test(expected = NullPointerException.class)
public void testSubscribeFINullA() {
CluckPublisher.subscribeFI(null, "hello", false);
}
@Test(expected = NullPointerException.class)
public void testSubscribeFINullB() {
CluckPublisher.subscribeFI(node, null, false);
}
@Test
public void testLoggingTarget() {
for (int i = 0; i < 5; i++) {
String name = Values.getRandomString();
if (name.contains("/") || node.hasLink(name)) {
i--;
continue;
}
VerifyingLoggingTarget vlt = new VerifyingLoggingTarget();
CluckPublisher.publish(node, name, vlt);
LoggingTarget lt = CluckPublisher.subscribeLT(node, name);
for (LogLevel level : LogLevel.allLevels) {
for (String message : Values.getRandomStrings(5)) {
if (Values.getRandomBoolean()) {
String extra = Values.getRandomBoolean() ? Values.getRandomString() : null;
if (extra != null && extra.isEmpty()) {
extra = null;
}
vlt.ifExpected = true;
vlt.isThrowableExpected = false;
vlt.levelExpected = level;
vlt.messageExpected = message;
vlt.stringExpected = extra;
lt.log(level, message, extra);
vlt.check();
} else {
Throwable thr = Values.getRandomBoolean() ? new Throwable("A STRING") : null;
vlt.ifExpected = true;
vlt.isThrowableExpected = false;
vlt.levelExpected = level;
vlt.messageExpected = message;
vlt.stringExpected = Utils.toStringThrowable(thr);
lt.log(level, message, thr);
vlt.check();
}
}
}
}
}
@Test(expected = NullPointerException.class)
public void testLoggingTargetNullA() {
CluckPublisher.publish(null, "hello", LoggingTarget.ignored);
}
@Test(expected = NullPointerException.class)
public void testLoggingTargetNullB() {
CluckPublisher.publish(node, null, LoggingTarget.ignored);
}
@Test(expected = NullPointerException.class)
public void testLoggingTargetNullC() {
CluckPublisher.publish(node, "hello", (LoggingTarget) null);
}
@Test(expected = IllegalArgumentException.class)
public void testLoggingTargetWithSlash() {
CluckPublisher.publish(node, "hello/other", LoggingTarget.ignored);
}
@Test(expected = NullPointerException.class)
public void testSubscribeLTNullA() {
CluckPublisher.subscribeLT(null, "hello");
}
@Test(expected = NullPointerException.class)
public void testSubscribeLTNullB() {
CluckPublisher.subscribeLT(node, null);
}
@Test
public void testOutputStream() throws IOException {
for (int i = 0; i < 20; i++) {
String name = Values.getRandomString();
if (name.contains("/") || node.hasLink(name)) {
i--;
continue;
}
VerifyingOutputStream vos = new VerifyingOutputStream();
CluckPublisher.publish(node, name, vos);
OutputStream proxy = CluckPublisher.subscribeOS(node, name);
for (byte[] bytes : Values.getRandomByteses(30, 0, 2000)) {
vos.bytesExpected = bytes;
vos.indexExpected = 0;
proxy.write(bytes);
vos.check();
}
}
}
@Test(expected = NullPointerException.class)
public void testOutputStreamNullA() {
CluckPublisher.publish(null, "hello", new VerifyingOutputStream());
}
@Test(expected = NullPointerException.class)
public void testOutputStreamNullB() {
CluckPublisher.publish(node, null, new VerifyingOutputStream());
}
@Test(expected = NullPointerException.class)
public void testOutputStreamNullC() {
CluckPublisher.publish(node, "hello", (OutputStream) null);
}
@Test(expected = IllegalArgumentException.class)
public void testOutputStreamWithSlash() {
CluckPublisher.publish(node, "hello/other", new VerifyingOutputStream());
}
@Test(expected = NullPointerException.class)
public void testSubscribeOSNullA() {
CluckPublisher.subscribeOS(null, "hello");
}
@Test(expected = NullPointerException.class)
public void testSubscribeOSNullB() {
CluckPublisher.subscribeOS(node, null);
}
@Test
public void testRevOutputStream() throws IOException {
for (int i = 0; i < 20; i++) {
String name = Values.getRandomString();
if (name.contains("/") || node.hasLink(name)) {
i--;
continue;
}
VerifyingOutputStream vos = new VerifyingOutputStream();
OutputStream proxy = CluckPublisher.publishOS(node, name);
CluckPublisher.subscribe(node, name, vos);
for (byte[] bytes : Values.getRandomByteses(30, 0, 2000)) {
vos.bytesExpected = bytes;
vos.indexExpected = 0;
proxy.write(bytes);
vos.check();
}
}
}
@Test(expected = NullPointerException.class)
public void testRevOutputStreamNullA() {
CluckPublisher.publishOS(null, "hello");
}
@Test(expected = NullPointerException.class)
public void testRevOutputStreamNullB() {
CluckPublisher.publishOS(node, null);
}
@Test(expected = IllegalArgumentException.class)
public void testRevOutputStreamWithSlash() {
CluckPublisher.publishOS(node, "hello/other");
}
@Test(expected = NullPointerException.class)
public void testRevSubscribeOSNullA() {
CluckPublisher.subscribe(null, "hello", new VerifyingOutputStream());
}
@Test(expected = NullPointerException.class)
public void testRevSubscribeOSNullB() {
CluckPublisher.subscribe(node, null, new VerifyingOutputStream());
}
@Test(expected = NullPointerException.class)
public void testRevSubscribeOSNullC() {
CluckPublisher.subscribe(node, "hello", (OutputStream) null);
}
}