From 640cf32a0e54486fbe0e3817304edefef863df05 Mon Sep 17 00:00:00 2001 From: Austin Shalit Date: Fri, 29 Jul 2016 15:38:33 -0700 Subject: [PATCH 1/6] Add NetworkTableSource --- .../edu/wpi/grip/core/GripCoreModule.java | 4 + .../main/java/edu/wpi/grip/core/Source.java | 5 + .../operations/network/GripNetworkModule.java | 5 + .../network/MapNetworkReceiverFactory.java | 10 ++ .../operations/network/NetworkReceiver.java | 34 +++++ .../network/networktables/NTManager.java | 67 ++++++++- .../wpi/grip/core/sockets/SocketHints.java | 8 + .../core/sources/NetworkTableEntrySource.java | 140 ++++++++++++++++++ .../java/edu/wpi/grip/core/PipelineTest.java | 5 +- .../java/edu/wpi/grip/core/PythonTest.java | 5 +- .../test/java/edu/wpi/grip/core/StepTest.java | 5 +- .../network/MockGripNetworkModule.java | 4 + .../network/MockMapNetworkPublisher.java | 1 + .../network/MockNetworkReceiver.java | 28 ++++ .../network/NetworkPackageSanityTest.java | 1 + .../grip/core/serialization/ProjectTest.java | 5 +- .../grip/core/sources/CameraSourceTest.java | 5 +- .../sources/NetworkTableEntrySourceTest.java | 31 ++++ .../wpi/grip/ui/pipeline/AddSourceButton.java | 70 +++++++-- .../java/edu/wpi/grip/ui/PaletteTest.java | 4 +- .../grip/ui/pipeline/AddSourceButtonTest.java | 24 ++- .../wpi/grip/ui/pipeline/PipelineUITest.java | 5 +- .../InputSocketControllerFactoryTest.java | 7 +- .../preview/ImageSocketPreviewViewTest.java | 5 +- .../PointSizeSocketPreviewViewTest.java | 9 +- 25 files changed, 453 insertions(+), 34 deletions(-) create mode 100644 core/src/main/java/edu/wpi/grip/core/operations/network/MapNetworkReceiverFactory.java create mode 100644 core/src/main/java/edu/wpi/grip/core/operations/network/NetworkReceiver.java create mode 100644 core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java create mode 100644 core/src/test/java/edu/wpi/grip/core/operations/network/MockNetworkReceiver.java create mode 100644 core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java diff --git a/core/src/main/java/edu/wpi/grip/core/GripCoreModule.java b/core/src/main/java/edu/wpi/grip/core/GripCoreModule.java index 5e52da585a..314e77170a 100644 --- a/core/src/main/java/edu/wpi/grip/core/GripCoreModule.java +++ b/core/src/main/java/edu/wpi/grip/core/GripCoreModule.java @@ -11,6 +11,7 @@ import edu.wpi.grip.core.sources.HttpSource; import edu.wpi.grip.core.sources.ImageFileSource; import edu.wpi.grip.core.sources.MultiImageFileSource; +import edu.wpi.grip.core.sources.NetworkTableEntrySource; import edu.wpi.grip.core.util.ExceptionWitness; import edu.wpi.grip.core.util.GripMode; @@ -144,6 +145,9 @@ public void hear(TypeLiteral type, TypeEncounter encounter) { install(new FactoryModuleBuilder() .implement(HttpSource.class, HttpSource.class) .build(HttpSource.Factory.class)); + install(new FactoryModuleBuilder() + .implement(NetworkTableEntrySource.class, NetworkTableEntrySource.class) + .build(NetworkTableEntrySource.Factory.class)); install(new FactoryModuleBuilder().build(ExceptionWitness.Factory.class)); } diff --git a/core/src/main/java/edu/wpi/grip/core/Source.java b/core/src/main/java/edu/wpi/grip/core/Source.java index 7c2a929f8b..5c4e9087dc 100644 --- a/core/src/main/java/edu/wpi/grip/core/Source.java +++ b/core/src/main/java/edu/wpi/grip/core/Source.java @@ -5,6 +5,7 @@ import edu.wpi.grip.core.sources.HttpSource; import edu.wpi.grip.core.sources.ImageFileSource; import edu.wpi.grip.core.sources.MultiImageFileSource; +import edu.wpi.grip.core.sources.NetworkTableEntrySource; import edu.wpi.grip.core.util.ExceptionWitness; import com.google.common.collect.ImmutableList; @@ -111,6 +112,8 @@ public static class SourceFactoryImpl implements SourceFactory { MultiImageFileSource.Factory multiImageFactory; @Inject HttpSource.Factory httpFactory; + @Inject + NetworkTableEntrySource.Factory networkTableEntryFactory; @Override public Source create(Class type, Properties properties) throws IOException { @@ -122,6 +125,8 @@ public Source create(Class type, Properties properties) throws IOException { return multiImageFactory.create(properties); } else if (type.isAssignableFrom(HttpSource.class)) { return httpFactory.create(properties); + } else if (type.isAssignableFrom(NetworkTableEntrySource.class)) { + return networkTableEntryFactory.create(properties); } else { throw new IllegalArgumentException(type + " was not a valid type"); } diff --git a/core/src/main/java/edu/wpi/grip/core/operations/network/GripNetworkModule.java b/core/src/main/java/edu/wpi/grip/core/operations/network/GripNetworkModule.java index f38cab7ee2..f965528f34 100644 --- a/core/src/main/java/edu/wpi/grip/core/operations/network/GripNetworkModule.java +++ b/core/src/main/java/edu/wpi/grip/core/operations/network/GripNetworkModule.java @@ -34,5 +34,10 @@ protected void configure() { bind(ROSNetworkPublisherFactory.class) .annotatedWith(Names.named("rosManager")) .to(ROSManager.class); + + // Network receiver bindings + bind(MapNetworkReceiverFactory.class) + .annotatedWith(Names.named("ntManager")) + .to(NTManager.class); } } diff --git a/core/src/main/java/edu/wpi/grip/core/operations/network/MapNetworkReceiverFactory.java b/core/src/main/java/edu/wpi/grip/core/operations/network/MapNetworkReceiverFactory.java new file mode 100644 index 0000000000..4a717dba30 --- /dev/null +++ b/core/src/main/java/edu/wpi/grip/core/operations/network/MapNetworkReceiverFactory.java @@ -0,0 +1,10 @@ +package edu.wpi.grip.core.operations.network; + + +/** + * A factory to create {@link NetworkReceiver NetworkRecievers}. + */ +@FunctionalInterface +public interface MapNetworkReceiverFactory { + NetworkReceiver create(String path); +} diff --git a/core/src/main/java/edu/wpi/grip/core/operations/network/NetworkReceiver.java b/core/src/main/java/edu/wpi/grip/core/operations/network/NetworkReceiver.java new file mode 100644 index 0000000000..7d3c83021c --- /dev/null +++ b/core/src/main/java/edu/wpi/grip/core/operations/network/NetworkReceiver.java @@ -0,0 +1,34 @@ +package edu.wpi.grip.core.operations.network; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * Manages the interface between the {@link PublishAnnotatedOperation} and the actual network + * protocol implemented by a specific {@link Manager}. + */ +public abstract class NetworkReceiver implements AutoCloseable { + + protected final String path; + + /** + * Create a new NetworkReceiver with the specified path. + * + * @param path The path of the object to get + */ + public NetworkReceiver(String path) { + checkArgument(!path.isEmpty(), "Name cannot be an empty string"); + this.path = path; + } + + /** + * Get the value of the object. + * + * @return The value of this NetworkReceiver + */ + public abstract Object getValue(); + + /** + * Close the network reciever. This should not throw an exception. + */ + public abstract void close(); +} diff --git a/core/src/main/java/edu/wpi/grip/core/operations/network/networktables/NTManager.java b/core/src/main/java/edu/wpi/grip/core/operations/network/networktables/NTManager.java index c0cc69ed56..11bc462191 100644 --- a/core/src/main/java/edu/wpi/grip/core/operations/network/networktables/NTManager.java +++ b/core/src/main/java/edu/wpi/grip/core/operations/network/networktables/NTManager.java @@ -5,6 +5,8 @@ import edu.wpi.grip.core.operations.network.Manager; import edu.wpi.grip.core.operations.network.MapNetworkPublisher; import edu.wpi.grip.core.operations.network.MapNetworkPublisherFactory; +import edu.wpi.grip.core.operations.network.MapNetworkReceiverFactory; +import edu.wpi.grip.core.operations.network.NetworkReceiver; import edu.wpi.grip.core.settings.ProjectSettings; import edu.wpi.grip.core.util.GripMode; @@ -25,7 +27,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; - +import javafx.beans.property.SimpleObjectProperty; import javax.inject.Inject; import static com.google.common.base.Preconditions.checkNotNull; @@ -34,11 +36,11 @@ * This class encapsulates the way we map various settings to the global NetworkTables state. */ @Singleton -public class NTManager implements Manager, MapNetworkPublisherFactory { +public class NTManager implements Manager, MapNetworkPublisherFactory, MapNetworkReceiverFactory { /* * Nasty hack that is unavoidable because of how NetworkTables works. */ - private static final AtomicInteger publisherCount = new AtomicInteger(0); + private static final AtomicInteger count = new AtomicInteger(0); /** * Information from: https://github.com/PeterJohnson/ntcore/blob/master/src/Log.h and @@ -120,11 +122,64 @@ public void updateSettings(ProjectSettingsChangedEvent event) { @Override public

MapNetworkPublisher

create(Set keys) { - // Keep track of ever publisher created. - publisherCount.getAndAdd(1); + // Keep track of every publisher created. + count.getAndAdd(1); return new NTPublisher<>(keys); } + @Override + public NetworkReceiver create(String path) { + count.getAndAdd(1); + return new NTReceiver(path); + } + + private static final class NTReceiver extends NetworkReceiver { + + private int entryListenerFunctionUid; + private final SimpleObjectProperty objectProperty = new SimpleObjectProperty(); + + protected NTReceiver(String path) { + super(path); + NetworkTablesJNI.addConnectionListener((uid, connected, conn) -> { + if (connected) { + addListener(); + NetworkTablesJNI.removeConnectionListener(uid); + } + }, true); + synchronized (NetworkTable.class) { + NetworkTable.initialize(); + } + } + + private void addListener() { + entryListenerFunctionUid = NetworkTablesJNI.addEntryListener(path, + (uid, key, value, flags) -> objectProperty.set(value), + ITable.NOTIFY_IMMEDIATE + | ITable.NOTIFY_NEW + | ITable.NOTIFY_UPDATE + | ITable.NOTIFY_DELETE + | ITable.NOTIFY_LOCAL); + } + + @Override + public Object getValue() { + return objectProperty.getValue(); + } + + @Override + public void close() { + NetworkTablesJNI.removeEntryListener(entryListenerFunctionUid); + + synchronized (NetworkTable.class) { + // This publisher is no longer used. + if (NTManager.count.addAndGet(-1) == 0) { + // We are the last publisher so shut it down + NetworkTable.shutdown(); + } + } + } + } + private static final class NTPublisher

extends MapNetworkPublisher

{ private final ImmutableSet keys; private Optional name = Optional.empty(); @@ -184,7 +239,7 @@ public void close() { } synchronized (NetworkTable.class) { // This publisher is no longer used. - if (NTManager.publisherCount.addAndGet(-1) == 0) { + if (NTManager.count.addAndGet(-1) == 0) { // We are the last publisher so shut it down NetworkTable.shutdown(); } diff --git a/core/src/main/java/edu/wpi/grip/core/sockets/SocketHints.java b/core/src/main/java/edu/wpi/grip/core/sockets/SocketHints.java index d5e51dd415..695dbb0fbd 100644 --- a/core/src/main/java/edu/wpi/grip/core/sockets/SocketHints.java +++ b/core/src/main/java/edu/wpi/grip/core/sockets/SocketHints.java @@ -193,5 +193,13 @@ public static SocketHint createNumberSocketHint(final String identifier, defaultValue) { return createNumberSocketHintBuilder(identifier, defaultValue).build(); } + + public static SocketHint createStringSocketHint(final String identifier, + String defaultValue) { + return new SocketHint.Builder(String.class) + .identifier(identifier) + .initialValue(defaultValue) + .build(); + } } } diff --git a/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java b/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java new file mode 100644 index 0000000000..0925fc0795 --- /dev/null +++ b/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java @@ -0,0 +1,140 @@ +package edu.wpi.grip.core.sources; + +import edu.wpi.grip.core.Source; +import edu.wpi.grip.core.events.SourceRemovedEvent; +import edu.wpi.grip.core.operations.network.MapNetworkReceiverFactory; +import edu.wpi.grip.core.operations.network.NetworkReceiver; +import edu.wpi.grip.core.sockets.OutputSocket; +import edu.wpi.grip.core.sockets.SocketHint; +import edu.wpi.grip.core.sockets.SocketHints; +import edu.wpi.grip.core.util.ExceptionWitness; + +import com.google.common.collect.ImmutableList; +import com.google.common.eventbus.Subscribe; +import com.google.inject.assistedinject.Assisted; +import com.google.inject.assistedinject.AssistedInject; +import com.google.inject.name.Named; +import com.thoughtworks.xstream.annotations.XStreamAlias; + +import java.util.List; +import java.util.Properties; + +/** + * Provides a way to get a {@link Types Type} from a NetworkTable that GRIP is connected to. + */ +@XStreamAlias("grip:NetworkValue") +public class NetworkTableEntrySource extends Source { + + private static final String PATH_PROPERTY = "networktable_path"; + private static final String TYPE_PROPERTY = "BOOLEAN"; + + private final OutputSocket output; + private final String path; + private final Types type; + private NetworkReceiver networkReceiver; + + public interface Factory { + NetworkTableEntrySource create(Properties properties); + + NetworkTableEntrySource create(String path, Types type); + } + + public enum Types { + BOOLEAN, NUMBER, STRING; + + @Override + public String toString() { + return super.toString().charAt(0) + super.toString().substring(1).toLowerCase(); + } + + } + + @AssistedInject + NetworkTableEntrySource( + ExceptionWitness.Factory exceptionWitnessFactory, + OutputSocket.Factory osf, + @Named("ntManager") MapNetworkReceiverFactory networkReceiverFactory, + @Assisted Properties properties) { + this(exceptionWitnessFactory, + osf, + networkReceiverFactory, + properties.getProperty(PATH_PROPERTY), + Types.valueOf(properties.getProperty(TYPE_PROPERTY))); + } + + @AssistedInject + NetworkTableEntrySource( + ExceptionWitness.Factory exceptionWitnessFactory, + OutputSocket.Factory osf, + @Named("ntManager") MapNetworkReceiverFactory networkReceiverFactory, + @Assisted String path, + @Assisted Types type) { + super(exceptionWitnessFactory); + this.path = path; + this.type = type; + networkReceiver = networkReceiverFactory.create(path); + output = osf.create(createOutputSocket(type)); + } + + @Override + public String getName() { + return path; + } + + @Override + protected List createOutputSockets() { + return ImmutableList.of( + output + ); + } + + @Override + protected boolean updateOutputSockets() { + try { + output.setValue(networkReceiver.getValue()); + } catch (ClassCastException ex) { + getExceptionWitness().flagException(ex, getName() + " is not of type " + + output.getSocketHint().getTypeLabel()); + return false; + } + return true; + } + + @Override + public Properties getProperties() { + Properties properties = new Properties(); + properties.setProperty(PATH_PROPERTY, path); + properties.setProperty(TYPE_PROPERTY, type.toString().toUpperCase()); + return properties; + } + + @Override + public void initialize() { + updateOutputSockets(); + } + + @Subscribe + public void onSourceRemovedEvent(SourceRemovedEvent event) { + if (event.getSource() == this) { + networkReceiver.close(); + } + } + + /** + * Create a SocketHint from the given type. + * + * @param type The type of SocketHint to create + */ + private static SocketHint createOutputSocket(Types type) { + switch (type) { + case BOOLEAN: + return SocketHints.Outputs.createBooleanSocketHint(Types.BOOLEAN.toString(), false); + case NUMBER: + return SocketHints.Outputs.createNumberSocketHint(Types.NUMBER.toString(), 0.0); + case STRING: + return SocketHints.Outputs.createStringSocketHint(Types.STRING.toString(), ""); + default: + throw new IllegalArgumentException("Invalid NetworkTable source type"); + } + } +} \ No newline at end of file diff --git a/core/src/test/java/edu/wpi/grip/core/PipelineTest.java b/core/src/test/java/edu/wpi/grip/core/PipelineTest.java index a93a51a38a..e5becbe12e 100644 --- a/core/src/test/java/edu/wpi/grip/core/PipelineTest.java +++ b/core/src/test/java/edu/wpi/grip/core/PipelineTest.java @@ -4,6 +4,7 @@ import edu.wpi.grip.core.events.ConnectionRemovedEvent; import edu.wpi.grip.core.events.SourceAddedEvent; import edu.wpi.grip.core.events.SourceRemovedEvent; +import edu.wpi.grip.core.operations.network.MockGripNetworkModule; import edu.wpi.grip.core.sockets.InputSocket; import edu.wpi.grip.core.sockets.MockInputSocket; import edu.wpi.grip.core.sockets.MockOutputSocket; @@ -15,6 +16,7 @@ import com.google.common.eventbus.EventBus; import com.google.inject.Guice; import com.google.inject.Injector; +import com.google.inject.util.Modules; import org.junit.After; import org.junit.Before; @@ -43,7 +45,8 @@ public class PipelineTest { public void setUp() { testModule = new GripCoreTestModule(); testModule.setUp(); - final Injector injector = Guice.createInjector(testModule); + final Injector injector = Guice.createInjector(Modules.override(testModule) + .with(new MockGripNetworkModule())); stepFactory = injector.getInstance(Step.Factory.class); eventBus = injector.getInstance(EventBus.class); pipeline = injector.getInstance(Pipeline.class); diff --git a/core/src/test/java/edu/wpi/grip/core/PythonTest.java b/core/src/test/java/edu/wpi/grip/core/PythonTest.java index ed37e68a5a..cbd4110511 100644 --- a/core/src/test/java/edu/wpi/grip/core/PythonTest.java +++ b/core/src/test/java/edu/wpi/grip/core/PythonTest.java @@ -1,6 +1,7 @@ package edu.wpi.grip.core; import edu.wpi.grip.core.operations.PythonScriptFile; +import edu.wpi.grip.core.operations.network.MockGripNetworkModule; import edu.wpi.grip.core.sockets.InputSocket; import edu.wpi.grip.core.sockets.OutputSocket; import edu.wpi.grip.core.sockets.Socket; @@ -10,6 +11,7 @@ import com.google.common.eventbus.EventBus; import com.google.inject.Guice; import com.google.inject.Injector; +import com.google.inject.util.Modules; import org.junit.After; import org.junit.Before; @@ -31,7 +33,8 @@ public class PythonTest { public void setUp() { testModule = new GripCoreTestModule(); testModule.setUp(); - final Injector injector = Guice.createInjector(testModule); + final Injector injector = Guice.createInjector(Modules.override(testModule) + .with(new MockGripNetworkModule())); eventBus = injector.getInstance(EventBus.class); isf = injector.getInstance(InputSocket.Factory.class); osf = injector.getInstance(OutputSocket.Factory.class); diff --git a/core/src/test/java/edu/wpi/grip/core/StepTest.java b/core/src/test/java/edu/wpi/grip/core/StepTest.java index 4fa4841f50..3fba56e8e0 100644 --- a/core/src/test/java/edu/wpi/grip/core/StepTest.java +++ b/core/src/test/java/edu/wpi/grip/core/StepTest.java @@ -1,5 +1,6 @@ package edu.wpi.grip.core; +import edu.wpi.grip.core.operations.network.MockGripNetworkModule; import edu.wpi.grip.core.sockets.InputSocket; import edu.wpi.grip.core.sockets.OutputSocket; import edu.wpi.grip.core.sockets.Socket; @@ -9,6 +10,7 @@ import com.google.common.eventbus.EventBus; import com.google.inject.Guice; import com.google.inject.Injector; +import com.google.inject.util.Modules; import org.junit.After; import org.junit.Before; @@ -24,7 +26,8 @@ public class StepTest { @Before public void setUp() { testModule.setUp(); - Injector injector = Guice.createInjector(testModule); + Injector injector = Guice.createInjector(Modules.override(testModule) + .with(new MockGripNetworkModule())); InputSocket.Factory isf = injector.getInstance(InputSocket.Factory.class); OutputSocket.Factory osf = injector.getInstance(OutputSocket.Factory.class); additionMeta = new OperationMetaData(AdditionOperation.DESCRIPTION, () -> new diff --git a/core/src/test/java/edu/wpi/grip/core/operations/network/MockGripNetworkModule.java b/core/src/test/java/edu/wpi/grip/core/operations/network/MockGripNetworkModule.java index d3017c439e..1aac03e77c 100644 --- a/core/src/test/java/edu/wpi/grip/core/operations/network/MockGripNetworkModule.java +++ b/core/src/test/java/edu/wpi/grip/core/operations/network/MockGripNetworkModule.java @@ -21,5 +21,9 @@ protected void configure() { bind(ROSNetworkPublisherFactory.class) .annotatedWith(Names.named("rosManager")) .to(MockROSManager.class); + + bind(MapNetworkReceiverFactory.class) + .annotatedWith(Names.named("ntManager")) + .to(MockNetworkReceiver.class); } } diff --git a/core/src/test/java/edu/wpi/grip/core/operations/network/MockMapNetworkPublisher.java b/core/src/test/java/edu/wpi/grip/core/operations/network/MockMapNetworkPublisher.java index 493b45e9ee..e34d36e75d 100644 --- a/core/src/test/java/edu/wpi/grip/core/operations/network/MockMapNetworkPublisher.java +++ b/core/src/test/java/edu/wpi/grip/core/operations/network/MockMapNetworkPublisher.java @@ -46,4 +46,5 @@ public void close() { public MapNetworkPublisher create(Set keys) { return new MockMapNetworkPublisher<>(keys); } + } diff --git a/core/src/test/java/edu/wpi/grip/core/operations/network/MockNetworkReceiver.java b/core/src/test/java/edu/wpi/grip/core/operations/network/MockNetworkReceiver.java new file mode 100644 index 0000000000..58d4bceac2 --- /dev/null +++ b/core/src/test/java/edu/wpi/grip/core/operations/network/MockNetworkReceiver.java @@ -0,0 +1,28 @@ +package edu.wpi.grip.core.operations.network; + +@SuppressWarnings("PMD.UncommentedEmptyMethodBody") +public class MockNetworkReceiver extends NetworkReceiver implements MapNetworkReceiverFactory { + + public MockNetworkReceiver() { + super("/Test/path"); + } + + public MockNetworkReceiver(String path) { + super(path); + } + + @Override + public Object getValue() { + return null; + } + + @Override + public void close() { + + } + + @Override + public NetworkReceiver create(String path) { + return new MockNetworkReceiver(path); + } +} diff --git a/core/src/test/java/edu/wpi/grip/core/operations/network/NetworkPackageSanityTest.java b/core/src/test/java/edu/wpi/grip/core/operations/network/NetworkPackageSanityTest.java index 937b3c15e1..ec9a0aacde 100644 --- a/core/src/test/java/edu/wpi/grip/core/operations/network/NetworkPackageSanityTest.java +++ b/core/src/test/java/edu/wpi/grip/core/operations/network/NetworkPackageSanityTest.java @@ -7,5 +7,6 @@ public class NetworkPackageSanityTest extends AbstractPackageSanityTests { public NetworkPackageSanityTest() { super(); publicApiOnly(); + ignoreClasses(c -> c.getName().contains("Mock")); } } diff --git a/core/src/test/java/edu/wpi/grip/core/serialization/ProjectTest.java b/core/src/test/java/edu/wpi/grip/core/serialization/ProjectTest.java index e62021d756..255543df86 100644 --- a/core/src/test/java/edu/wpi/grip/core/serialization/ProjectTest.java +++ b/core/src/test/java/edu/wpi/grip/core/serialization/ProjectTest.java @@ -13,6 +13,7 @@ import edu.wpi.grip.core.events.ProjectSettingsChangedEvent; import edu.wpi.grip.core.events.SourceAddedEvent; import edu.wpi.grip.core.operations.PythonScriptFile; +import edu.wpi.grip.core.operations.network.MockGripNetworkModule; import edu.wpi.grip.core.settings.ProjectSettings; import edu.wpi.grip.core.sockets.InputSocket; import edu.wpi.grip.core.sockets.OutputSocket; @@ -25,6 +26,7 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; +import com.google.inject.util.Modules; import org.junit.After; import org.junit.Before; @@ -64,7 +66,8 @@ public class ProjectTest { public void setUp() throws Exception { testModule = new GripCoreTestModule(); testModule.setUp(); - final Injector injector = Guice.createInjector(testModule); + final Injector injector = Guice.createInjector(Modules.override(testModule) + .with(new MockGripNetworkModule())); connectionFactory = injector .getInstance(Key.get(new TypeLiteral>() { })); diff --git a/core/src/test/java/edu/wpi/grip/core/sources/CameraSourceTest.java b/core/src/test/java/edu/wpi/grip/core/sources/CameraSourceTest.java index adf3422c54..c6f4dbbc26 100644 --- a/core/src/test/java/edu/wpi/grip/core/sources/CameraSourceTest.java +++ b/core/src/test/java/edu/wpi/grip/core/sources/CameraSourceTest.java @@ -2,6 +2,7 @@ import edu.wpi.grip.core.events.UnexpectedThrowableEvent; +import edu.wpi.grip.core.operations.network.MockGripNetworkModule; import edu.wpi.grip.core.sockets.OutputSocket; import edu.wpi.grip.core.util.ImageLoadingUtility; import edu.wpi.grip.core.util.MockExceptionWitness; @@ -14,6 +15,7 @@ import com.google.common.util.concurrent.Service; import com.google.inject.Guice; import com.google.inject.Injector; +import com.google.inject.util.Modules; import net.jodah.concurrentunit.Waiter; @@ -55,7 +57,8 @@ public class CameraSourceTest { public void setUp() throws Exception { this.testModule = new GripCoreTestModule(); testModule.setUp(); - final Injector injector = Guice.createInjector(testModule); + final Injector injector = Guice.createInjector(Modules.override(testModule) + .with(new MockGripNetworkModule())); this.cameraSourceFactory = injector.getInstance(CameraSource.Factory.class); this.osf = injector.getInstance(OutputSocket.Factory.class); diff --git a/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java b/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java new file mode 100644 index 0000000000..b4b70ab7a0 --- /dev/null +++ b/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java @@ -0,0 +1,31 @@ +package edu.wpi.grip.core.sources; + +import edu.wpi.grip.core.operations.network.MapNetworkReceiverFactory; +import edu.wpi.grip.core.operations.network.MockNetworkReceiver; +import edu.wpi.grip.core.sockets.MockOutputSocketFactory; +import edu.wpi.grip.core.sockets.OutputSocket; +import edu.wpi.grip.core.util.MockExceptionWitness; + +import com.google.common.eventbus.EventBus; + +import org.junit.Before; + +public class NetworkTableEntrySourceTest { + + /** + * Checks that object creation works. + */ + @Before + public void setup() { + EventBus eventBus = new EventBus(); + OutputSocket.Factory osf = new MockOutputSocketFactory(eventBus); + MapNetworkReceiverFactory nrf = new MockNetworkReceiver(); + + new NetworkTableEntrySource(origin -> new MockExceptionWitness(eventBus, origin), + osf, + nrf, + "/Test/path", + NetworkTableEntrySource.Types.BOOLEAN); + } + +} diff --git a/ui/src/main/java/edu/wpi/grip/ui/pipeline/AddSourceButton.java b/ui/src/main/java/edu/wpi/grip/ui/pipeline/AddSourceButton.java index fb02d993d4..17b1f2741a 100644 --- a/ui/src/main/java/edu/wpi/grip/ui/pipeline/AddSourceButton.java +++ b/ui/src/main/java/edu/wpi/grip/ui/pipeline/AddSourceButton.java @@ -7,6 +7,7 @@ import edu.wpi.grip.core.sources.HttpSource; import edu.wpi.grip.core.sources.ImageFileSource; import edu.wpi.grip.core.sources.MultiImageFileSource; +import edu.wpi.grip.core.sources.NetworkTableEntrySource; import edu.wpi.grip.ui.util.DPIUtility; import edu.wpi.grip.ui.util.SupplierWithIO; @@ -25,13 +26,15 @@ import java.util.function.Consumer; import java.util.function.Predicate; import javafx.application.Platform; +import javafx.beans.value.ChangeListener; import javafx.event.ActionEvent; import javafx.event.EventHandler; +import javafx.scene.Node; import javafx.scene.Parent; import javafx.scene.control.Button; import javafx.scene.control.ButtonBar; import javafx.scene.control.ButtonType; -import javafx.scene.control.Control; +import javafx.scene.control.ComboBox; import javafx.scene.control.Dialog; import javafx.scene.control.MenuButton; import javafx.scene.control.MenuItem; @@ -40,6 +43,7 @@ import javafx.scene.image.ImageView; import javafx.scene.layout.GridPane; import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; import javafx.scene.text.Text; import javafx.stage.FileChooser; import javafx.stage.FileChooser.ExtensionFilter; @@ -59,6 +63,7 @@ public class AddSourceButton extends MenuButton { private final MenuItem webcamButton; private final MenuItem ipcamButton; private final MenuItem httpButton; + private final MenuItem networktablesButton; private Optional

activeDialog = Optional.empty(); @Inject @@ -66,7 +71,8 @@ public class AddSourceButton extends MenuButton { MultiImageFileSource.Factory multiImageSourceFactory, ImageFileSource.Factory imageSourceFactory, CameraSource.Factory cameraSourceFactory, - HttpSource.Factory httpSourceFactory) { + HttpSource.Factory httpSourceFactory, + NetworkTableEntrySource.Factory networkTableSourceFactory) { super("Add Source"); this.eventBus = eventBus; @@ -214,6 +220,46 @@ public class AddSourceButton extends MenuButton { }); }); + networktablesButton = addMenuItem("NetworkTable", + getClass().getResource("/edu/wpi/grip/ui/icons/publish.png"), mouseEvent -> { + final Parent root = this.getScene().getRoot(); + // Show a dialog to pick the server path images will be uploaded on + final String rootString = "/"; + final VBox fields = new VBox(); + final TextField tablePath = new TextField(rootString); + final ComboBox type = new ComboBox<>(); + final SourceDialog dialog = new SourceDialog(root, fields); + + type.setPromptText("Select a data type"); + type.getItems().setAll(NetworkTableEntrySource.Types.values()); + type.setMaxWidth(Double.MAX_VALUE); + fields.getChildren().add(tablePath); + fields.getChildren().add(type); + tablePath.setPromptText("Ex: /GRIP/fps"); + dialog.getDialogPane().lookupButton(ButtonType.OK).setDisable(true); // Default disabled + + ChangeListener changeListener = (observable, oldValue, newValue) -> { + boolean valid = tablePath.getText().startsWith(rootString) + && tablePath.getText().length() > rootString.length() + && type.getValue() != null; + dialog.getDialogPane().lookupButton(ButtonType.OK).setDisable(!valid); + }; + + tablePath.textProperty().addListener(changeListener); + type.valueProperty().addListener(changeListener); + + dialog.setTitle("Choose NetworkTable path"); + dialog.setHeaderText("Enter the NetworkTable path"); + dialog.showAndWait() + .filter(ButtonType.OK::equals) + .ifPresent(bt -> { + final NetworkTableEntrySource networkTableEntrySource + = networkTableSourceFactory.create(tablePath.getText(), type.getValue()); + networkTableEntrySource.initialize(); + eventBus.post(new SourceAddedEvent(networkTableEntrySource)); + }); + }); + } /** @@ -225,7 +271,6 @@ public class AddSourceButton extends MenuButton { private void loadCamera(Dialog dialog, SupplierWithIO cameraSourceSupplier, Consumer failureCallback) { assert Platform.isFxApplicationThread() : "Should only run in FX thread"; - activeDialog = Optional.of(dialog); dialog.showAndWait().filter(Predicate.isEqual(ButtonType.OK)).ifPresent(result -> { try { // Will try to create the camera with the values from the supplier @@ -237,7 +282,6 @@ private void loadCamera(Dialog dialog, SupplierWithIO loadCamera(dialog, cameraSourceSupplier, failureCallback); } }); - activeDialog = Optional.empty(); } /** @@ -271,6 +315,11 @@ MenuItem getHttpButton() { return httpButton; } + @VisibleForTesting + MenuItem getNetworktablesButton() { + return networktablesButton; + } + @VisibleForTesting void closeDialogs() { activeDialog.ifPresent(dialog -> { @@ -288,21 +337,24 @@ public interface Factory { AddSourceButton create(); } - private static class SourceDialog extends Dialog { + private class SourceDialog extends Dialog { private final Text errorText = new Text(); - private SourceDialog(final Parent root, Control inputField) { + private SourceDialog(final Parent root, Node customField) { super(); + setOnShowing(event -> activeDialog = Optional.of(this)); + setOnHidden(event -> activeDialog = Optional.empty()); + this.getDialogPane().getStyleClass().add(SOURCE_DIALOG_STYLE_CLASS); final GridPane gridContent = new GridPane(); gridContent.setMaxWidth(Double.MAX_VALUE); - GridPane.setHgrow(inputField, Priority.ALWAYS); + GridPane.setHgrow(customField, Priority.ALWAYS); GridPane.setHgrow(errorText, Priority.NEVER); - errorText.wrappingWidthProperty().bind(inputField.widthProperty()); + errorText.setWrappingWidth(customField.getLayoutBounds().getWidth()); gridContent.add(errorText, 0, 0); - gridContent.add(inputField, 0, 1); + gridContent.add(customField, 0, 1); getDialogPane().setContent(gridContent); getDialogPane().setStyle(root.getStyle()); diff --git a/ui/src/test/java/edu/wpi/grip/ui/PaletteTest.java b/ui/src/test/java/edu/wpi/grip/ui/PaletteTest.java index 1ea7b749f1..1095f18b65 100644 --- a/ui/src/test/java/edu/wpi/grip/ui/PaletteTest.java +++ b/ui/src/test/java/edu/wpi/grip/ui/PaletteTest.java @@ -6,6 +6,7 @@ import edu.wpi.grip.core.Step; import edu.wpi.grip.core.events.OperationAddedEvent; import edu.wpi.grip.core.events.StepAddedEvent; +import edu.wpi.grip.core.operations.network.MockGripNetworkModule; import edu.wpi.grip.core.sockets.InputSocket; import edu.wpi.grip.core.sockets.OutputSocket; import edu.wpi.grip.util.GripCoreTestModule; @@ -40,7 +41,8 @@ public class PaletteTest extends ApplicationTest { public void start(Stage stage) throws IOException { testModule.setUp(); - Injector injector = Guice.createInjector(Modules.override(testModule).with(new GripUiModule())); + Injector injector = Guice.createInjector(Modules.override(testModule) + .with(new GripUiModule(), new MockGripNetworkModule())); eventBus = injector.getInstance(EventBus.class); FXMLLoader loader = new FXMLLoader(getClass().getResource("Palette.fxml")); diff --git a/ui/src/test/java/edu/wpi/grip/ui/pipeline/AddSourceButtonTest.java b/ui/src/test/java/edu/wpi/grip/ui/pipeline/AddSourceButtonTest.java index 16eeb24937..d6294f3ff3 100644 --- a/ui/src/test/java/edu/wpi/grip/ui/pipeline/AddSourceButtonTest.java +++ b/ui/src/test/java/edu/wpi/grip/ui/pipeline/AddSourceButtonTest.java @@ -1,6 +1,5 @@ package edu.wpi.grip.ui.pipeline; - import edu.wpi.grip.core.sources.CameraSource; import edu.wpi.grip.core.sources.MockCameraSource; @@ -42,7 +41,9 @@ public void start(Stage stage) { this.eventBus = new EventBus("Test Event Bus"); this.mockCameraSourceFactory = new MockCameraSourceFactory(eventBus); - addSourceView = new AddSourceButton(eventBus, null, null, mockCameraSourceFactory, null); + + addSourceView + = new AddSourceButton(eventBus, null, null, mockCameraSourceFactory, null, null); final Scene scene = new Scene(addSourceView, 800, 600); stage.setScene(scene); @@ -71,6 +72,22 @@ public void testClickOnCreateIPCameraOpensDialog() throws Exception { verifyThat("." + AddSourceButton.SOURCE_DIALOG_STYLE_CLASS, NodeMatchers.isVisible()); } + @Test + @SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") + public void testClickOnCreateHttpOpensDialog() throws Exception { + Platform.runLater(() -> addSourceView.getHttpButton().fire()); + WaitForAsyncUtils.waitForFxEvents(); + verifyThat("." + AddSourceButton.SOURCE_DIALOG_STYLE_CLASS, NodeMatchers.isVisible()); + } + + @Test + @SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") + public void testClickOnCreateNetworkTableOpensDialog() throws Exception { + Platform.runLater(() -> addSourceView.getNetworktablesButton().fire()); + WaitForAsyncUtils.waitForFxEvents(); + verifyThat("." + AddSourceButton.SOURCE_DIALOG_STYLE_CLASS, NodeMatchers.isVisible()); + } + @Test public void testCreatesSourceStarted() throws Exception { // When @@ -131,7 +148,8 @@ public void start(Stage stage) { this.eventBus = new EventBus("Test Event Bus"); this.mockCameraSourceFactory = new MockCameraSourceFactory(eventBus); - addSourceView = new AddSourceButton(eventBus, null, null, mockCameraSourceFactory, null); + addSourceView + = new AddSourceButton(eventBus, null, null, mockCameraSourceFactory, null, null); final Scene scene = new Scene(addSourceView, 800, 600); stage.setScene(scene); diff --git a/ui/src/test/java/edu/wpi/grip/ui/pipeline/PipelineUITest.java b/ui/src/test/java/edu/wpi/grip/ui/pipeline/PipelineUITest.java index 873a44849e..57076b5112 100644 --- a/ui/src/test/java/edu/wpi/grip/ui/pipeline/PipelineUITest.java +++ b/ui/src/test/java/edu/wpi/grip/ui/pipeline/PipelineUITest.java @@ -7,6 +7,7 @@ import edu.wpi.grip.core.Pipeline; import edu.wpi.grip.core.Step; import edu.wpi.grip.core.SubtractionOperation; +import edu.wpi.grip.core.operations.network.MockGripNetworkModule; import edu.wpi.grip.core.sockets.InputSocket; import edu.wpi.grip.core.sockets.OutputSocket; import edu.wpi.grip.core.util.MockExceptionWitness; @@ -56,8 +57,8 @@ public class PipelineUITest extends ApplicationTest { public void start(Stage stage) { testModule = new GripCoreTestModule(); testModule.setUp(); - final Injector injector = Guice.createInjector(Modules.override(testModule).with(new - GripUiModule())); + final Injector injector = Guice.createInjector(Modules.override(testModule) + .with(new GripUiModule(), new MockGripNetworkModule())); eventBus = injector.getInstance(EventBus.class); pipeline = injector.getInstance(Pipeline.class); InputSocket.Factory isf = injector.getInstance(InputSocket.Factory.class); diff --git a/ui/src/test/java/edu/wpi/grip/ui/pipeline/input/InputSocketControllerFactoryTest.java b/ui/src/test/java/edu/wpi/grip/ui/pipeline/input/InputSocketControllerFactoryTest.java index ab4f61170a..c86b032567 100644 --- a/ui/src/test/java/edu/wpi/grip/ui/pipeline/input/InputSocketControllerFactoryTest.java +++ b/ui/src/test/java/edu/wpi/grip/ui/pipeline/input/InputSocketControllerFactoryTest.java @@ -4,6 +4,7 @@ import edu.wpi.grip.core.Palette; import edu.wpi.grip.core.Step; import edu.wpi.grip.core.operations.OperationsFactory; +import edu.wpi.grip.core.operations.network.MockGripNetworkModule; import edu.wpi.grip.core.sockets.InputSocket; import edu.wpi.grip.ui.GripUiModule; import edu.wpi.grip.util.GripCoreTestModule; @@ -56,7 +57,8 @@ public static Collection data() { GripCoreTestModule testModule = new GripCoreTestModule(); testModule.setUp(); - Injector injector = Guice.createInjector(testModule); + Injector injector = Guice.createInjector(Modules.override(testModule) + .with(new MockGripNetworkModule())); final Palette palette = injector.getInstance(Palette.class); final EventBus eventBus = injector.getInstance(EventBus.class); OperationsFactory.create(eventBus).addOperations(); @@ -80,7 +82,8 @@ public static Collection data() { public void start(Stage stage) { testModule = new GripCoreTestModule(); testModule.setUp(); - Injector injector = Guice.createInjector(Modules.override(testModule).with(new GripUiModule())); + Injector injector = Guice.createInjector(Modules.override(testModule) + .with(new GripUiModule(), new MockGripNetworkModule())); inputSocketControllerFactory = injector.getInstance(InputSocketControllerFactory.class); stepFactory = injector.getInstance(Step.Factory.class); gridPane = new GridPane(); diff --git a/ui/src/test/java/edu/wpi/grip/ui/preview/ImageSocketPreviewViewTest.java b/ui/src/test/java/edu/wpi/grip/ui/preview/ImageSocketPreviewViewTest.java index 7ec34290ea..e866ddf8e8 100644 --- a/ui/src/test/java/edu/wpi/grip/ui/preview/ImageSocketPreviewViewTest.java +++ b/ui/src/test/java/edu/wpi/grip/ui/preview/ImageSocketPreviewViewTest.java @@ -1,5 +1,6 @@ package edu.wpi.grip.ui.preview; +import edu.wpi.grip.core.operations.network.MockGripNetworkModule; import edu.wpi.grip.core.sockets.OutputSocket; import edu.wpi.grip.core.sockets.SocketHint; import edu.wpi.grip.ui.GripUiModule; @@ -33,8 +34,8 @@ public void start(Stage stage) { testModule = new GripCoreTestModule(); testModule.setUp(); - final Injector injector = Guice.createInjector(Modules.override(testModule).with(new - GripUiModule())); + final Injector injector = Guice.createInjector(Modules.override(testModule) + .with(new GripUiModule(), new MockGripNetworkModule())); final ImageSocketPreviewView imageSocketPreviewView = new ImageSocketPreviewView(new MockGripPlatform(new EventBus()), injector.getInstance(OutputSocket.Factory.class) diff --git a/ui/src/test/java/edu/wpi/grip/ui/preview/PointSizeSocketPreviewViewTest.java b/ui/src/test/java/edu/wpi/grip/ui/preview/PointSizeSocketPreviewViewTest.java index cf9afdc075..4cf60c20b1 100644 --- a/ui/src/test/java/edu/wpi/grip/ui/preview/PointSizeSocketPreviewViewTest.java +++ b/ui/src/test/java/edu/wpi/grip/ui/preview/PointSizeSocketPreviewViewTest.java @@ -1,5 +1,6 @@ package edu.wpi.grip.ui.preview; +import edu.wpi.grip.core.operations.network.MockGripNetworkModule; import edu.wpi.grip.core.sockets.OutputSocket; import edu.wpi.grip.core.sockets.SocketHint; import edu.wpi.grip.ui.GripUiModule; @@ -39,8 +40,8 @@ public static class PointSocketPreviewViewTest extends ApplicationTest { public void start(Stage stage) { testModule = new GripCoreTestModule(); testModule.setUp(); - final Injector injector = Guice.createInjector(Modules.override(testModule).with(new - GripUiModule())); + final Injector injector = Guice.createInjector(Modules.override(testModule) + .with(new GripUiModule(), new MockGripNetworkModule())); final OutputSocket pointOutputSocket = injector.getInstance(OutputSocket.Factory.class) .create(new SocketHint.Builder<>(Point.class) @@ -80,8 +81,8 @@ public static class SizeSocketPreviewViewTest extends ApplicationTest { public void start(Stage stage) { testModule = new GripCoreTestModule(); testModule.setUp(); - final Injector injector = Guice.createInjector(Modules.override(testModule).with(new - GripUiModule())); + final Injector injector = Guice.createInjector(Modules.override(testModule) + .with(new GripUiModule(), new MockGripNetworkModule())); final OutputSocket sizeOutputSocket = injector.getInstance(OutputSocket.Factory.class) .create(new SocketHint.Builder<>(Size.class) From daa5110a4630c7bf512d84eaa414203cf21bd5fe Mon Sep 17 00:00:00 2001 From: Austin Shalit Date: Tue, 2 Aug 2016 13:51:11 -0700 Subject: [PATCH 2/6] Add Tests --- .gitignore | 4 + .../operations/network/NetworkReceiver.java | 9 + .../network/networktables/NTManager.java | 29 ++-- .../core/sources/NetworkTableEntrySource.java | 9 +- .../network/MockGripNetworkModule.java | 3 +- .../network/MockNetworkReceiver.java | 28 ---- .../networktables/TestingNTManager.java | 36 ++++ .../sources/NetworkTableEntrySourceTest.java | 156 ++++++++++++++++-- 8 files changed, 218 insertions(+), 56 deletions(-) delete mode 100644 core/src/test/java/edu/wpi/grip/core/operations/network/MockNetworkReceiver.java create mode 100644 core/src/test/java/edu/wpi/grip/core/operations/network/networktables/TestingNTManager.java diff --git a/.gitignore b/.gitignore index fc7b805616..366b7a981f 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,7 @@ bower_components **/generated */generated_tests /bin/ + +### NetworkTables +networktables.ini +networktables.ini.bak diff --git a/core/src/main/java/edu/wpi/grip/core/operations/network/NetworkReceiver.java b/core/src/main/java/edu/wpi/grip/core/operations/network/NetworkReceiver.java index 7d3c83021c..ff66844d9a 100644 --- a/core/src/main/java/edu/wpi/grip/core/operations/network/NetworkReceiver.java +++ b/core/src/main/java/edu/wpi/grip/core/operations/network/NetworkReceiver.java @@ -1,5 +1,7 @@ package edu.wpi.grip.core.operations.network; +import java.util.function.Consumer; + import static com.google.common.base.Preconditions.checkArgument; /** @@ -27,6 +29,13 @@ public NetworkReceiver(String path) { */ public abstract Object getValue(); + /** + * Add a listener to the NetworkReceiver item. + * + * @param consumer The consumer to call when this item has a update + */ + public abstract void addListener(Consumer consumer); + /** * Close the network reciever. This should not throw an exception. */ diff --git a/core/src/main/java/edu/wpi/grip/core/operations/network/networktables/NTManager.java b/core/src/main/java/edu/wpi/grip/core/operations/network/networktables/NTManager.java index 11bc462191..f9485b5cff 100644 --- a/core/src/main/java/edu/wpi/grip/core/operations/network/networktables/NTManager.java +++ b/core/src/main/java/edu/wpi/grip/core/operations/network/networktables/NTManager.java @@ -21,13 +21,15 @@ import edu.wpi.first.wpilibj.tables.ITable; import java.io.File; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; import java.util.logging.Level; import java.util.logging.Logger; -import javafx.beans.property.SimpleObjectProperty; import javax.inject.Inject; import static com.google.common.base.Preconditions.checkNotNull; @@ -47,7 +49,7 @@ public class NTManager implements Manager, MapNetworkPublisherFactory, MapNetwor * https://github.com/PeterJohnson/ntcore/blob/e6054f543a6ab10aa27af6cace855da66d67ee44 * /include/ntcore_c.h#L39 */ - private static final Map ntLogLevels = ImmutableMap.builder() + protected static final Map ntLogLevels = ImmutableMap.builder() .put(40, Level.SEVERE) .put(30, Level.WARNING) .put(20, Level.INFO) @@ -136,16 +138,13 @@ public NetworkReceiver create(String path) { private static final class NTReceiver extends NetworkReceiver { private int entryListenerFunctionUid; - private final SimpleObjectProperty objectProperty = new SimpleObjectProperty(); + private Object object = false; + private final List> listeners = new LinkedList<>(); protected NTReceiver(String path) { super(path); - NetworkTablesJNI.addConnectionListener((uid, connected, conn) -> { - if (connected) { - addListener(); - NetworkTablesJNI.removeConnectionListener(uid); - } - }, true); + addListener(); + synchronized (NetworkTable.class) { NetworkTable.initialize(); } @@ -153,7 +152,10 @@ protected NTReceiver(String path) { private void addListener() { entryListenerFunctionUid = NetworkTablesJNI.addEntryListener(path, - (uid, key, value, flags) -> objectProperty.set(value), + (uid, key, value, flags) -> { + object = value; + listeners.forEach(c -> c.accept(object)); + }, ITable.NOTIFY_IMMEDIATE | ITable.NOTIFY_NEW | ITable.NOTIFY_UPDATE @@ -161,9 +163,14 @@ private void addListener() { | ITable.NOTIFY_LOCAL); } + @Override + public void addListener(Consumer consumer) { + listeners.add(consumer); + } + @Override public Object getValue() { - return objectProperty.getValue(); + return object; } @Override diff --git a/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java b/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java index 0925fc0795..682cb1b534 100644 --- a/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java +++ b/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java @@ -1,6 +1,7 @@ package edu.wpi.grip.core.sources; import edu.wpi.grip.core.Source; +import edu.wpi.grip.core.events.SourceHasPendingUpdateEvent; import edu.wpi.grip.core.events.SourceRemovedEvent; import edu.wpi.grip.core.operations.network.MapNetworkReceiverFactory; import edu.wpi.grip.core.operations.network.NetworkReceiver; @@ -10,6 +11,7 @@ import edu.wpi.grip.core.util.ExceptionWitness; import com.google.common.collect.ImmutableList; +import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.AssistedInject; @@ -51,11 +53,13 @@ public String toString() { @AssistedInject NetworkTableEntrySource( + EventBus eventBus, ExceptionWitness.Factory exceptionWitnessFactory, OutputSocket.Factory osf, @Named("ntManager") MapNetworkReceiverFactory networkReceiverFactory, @Assisted Properties properties) { - this(exceptionWitnessFactory, + this(eventBus, + exceptionWitnessFactory, osf, networkReceiverFactory, properties.getProperty(PATH_PROPERTY), @@ -64,6 +68,7 @@ public String toString() { @AssistedInject NetworkTableEntrySource( + EventBus eventBus, ExceptionWitness.Factory exceptionWitnessFactory, OutputSocket.Factory osf, @Named("ntManager") MapNetworkReceiverFactory networkReceiverFactory, @@ -74,6 +79,8 @@ public String toString() { this.type = type; networkReceiver = networkReceiverFactory.create(path); output = osf.create(createOutputSocket(type)); + + networkReceiver.addListener(o -> eventBus.post(new SourceHasPendingUpdateEvent(this))); } @Override diff --git a/core/src/test/java/edu/wpi/grip/core/operations/network/MockGripNetworkModule.java b/core/src/test/java/edu/wpi/grip/core/operations/network/MockGripNetworkModule.java index 1aac03e77c..afa34b3907 100644 --- a/core/src/test/java/edu/wpi/grip/core/operations/network/MockGripNetworkModule.java +++ b/core/src/test/java/edu/wpi/grip/core/operations/network/MockGripNetworkModule.java @@ -1,5 +1,6 @@ package edu.wpi.grip.core.operations.network; +import edu.wpi.grip.core.operations.network.networktables.TestingNTManager; import edu.wpi.grip.core.operations.network.ros.MockROSManager; import edu.wpi.grip.core.operations.network.ros.ROSNetworkPublisherFactory; @@ -24,6 +25,6 @@ protected void configure() { bind(MapNetworkReceiverFactory.class) .annotatedWith(Names.named("ntManager")) - .to(MockNetworkReceiver.class); + .to(TestingNTManager.class); } } diff --git a/core/src/test/java/edu/wpi/grip/core/operations/network/MockNetworkReceiver.java b/core/src/test/java/edu/wpi/grip/core/operations/network/MockNetworkReceiver.java deleted file mode 100644 index 58d4bceac2..0000000000 --- a/core/src/test/java/edu/wpi/grip/core/operations/network/MockNetworkReceiver.java +++ /dev/null @@ -1,28 +0,0 @@ -package edu.wpi.grip.core.operations.network; - -@SuppressWarnings("PMD.UncommentedEmptyMethodBody") -public class MockNetworkReceiver extends NetworkReceiver implements MapNetworkReceiverFactory { - - public MockNetworkReceiver() { - super("/Test/path"); - } - - public MockNetworkReceiver(String path) { - super(path); - } - - @Override - public Object getValue() { - return null; - } - - @Override - public void close() { - - } - - @Override - public NetworkReceiver create(String path) { - return new MockNetworkReceiver(path); - } -} diff --git a/core/src/test/java/edu/wpi/grip/core/operations/network/networktables/TestingNTManager.java b/core/src/test/java/edu/wpi/grip/core/operations/network/networktables/TestingNTManager.java new file mode 100644 index 0000000000..558f78b410 --- /dev/null +++ b/core/src/test/java/edu/wpi/grip/core/operations/network/networktables/TestingNTManager.java @@ -0,0 +1,36 @@ +package edu.wpi.grip.core.operations.network.networktables; + +import com.google.inject.Singleton; + +import edu.wpi.first.wpilibj.networktables.NetworkTable; +import edu.wpi.first.wpilibj.networktables.NetworkTablesJNI; + +import java.io.File; +import java.util.logging.Logger; + +/** + * This class encapsulates the way we map various settings to the global NetworkTables state. + */ +@Singleton +public class TestingNTManager extends NTManager { + + private static final Logger logger = Logger.getLogger(TestingNTManager.class.getName()); + + public TestingNTManager() { + // We may have another instance of this method lying around + NetworkTable.shutdown(); + + // Redirect NetworkTables log messages to our own log files. This gets rid of console spam, + // and it also lets + // us grep through NetworkTables messages just like any other messages. + NetworkTablesJNI.setLogger((level, file, line, msg) -> { + String filename = new File(file).getName(); + logger.log(ntLogLevels.get(level), String.format("NetworkTables: %s:%d %s", filename, line, + msg)); + }, 0); + + NetworkTable.setServerMode(); + NetworkTable.initialize(); + } + +} diff --git a/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java b/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java index b4b70ab7a0..d1e704ba15 100644 --- a/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java +++ b/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java @@ -1,31 +1,157 @@ package edu.wpi.grip.core.sources; -import edu.wpi.grip.core.operations.network.MapNetworkReceiverFactory; -import edu.wpi.grip.core.operations.network.MockNetworkReceiver; +import edu.wpi.grip.core.events.SourceRemovedEvent; +import edu.wpi.grip.core.operations.network.networktables.TestingNTManager; import edu.wpi.grip.core.sockets.MockOutputSocketFactory; -import edu.wpi.grip.core.sockets.OutputSocket; import edu.wpi.grip.core.util.MockExceptionWitness; import com.google.common.eventbus.EventBus; -import org.junit.Before; +import edu.wpi.first.wpilibj.networktables.NetworkTablesJNI; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; public class NetworkTableEntrySourceTest { - /** - * Checks that object creation works. - */ - @Before - public void setup() { - EventBus eventBus = new EventBus(); - OutputSocket.Factory osf = new MockOutputSocketFactory(eventBus); - MapNetworkReceiverFactory nrf = new MockNetworkReceiver(); + private EventBus eventBus; + private MockOutputSocketFactory osf; + private TestingNTManager testingNtManager; + + private NetworkTableEntrySource source; + + private static final double TEST_NUMBER = 13.13; + private static final String TEST_STRING = "Some test string"; + private static final String BOOLEAN_PATH = "/GRIP/test/boolean"; + private static final String NUMBER_PATH = "/GRIP/test/number"; + private static final String STRING_PATH = "/GRIP/test/string"; + + public NetworkTableEntrySourceTest() { + eventBus = new EventBus(); + osf = new MockOutputSocketFactory(eventBus); + testingNtManager = new TestingNTManager(); + + NetworkTablesJNI.putBoolean(BOOLEAN_PATH, true); + NetworkTablesJNI.putDouble(NUMBER_PATH, TEST_NUMBER); + NetworkTablesJNI.putString(STRING_PATH, TEST_STRING); + } + + @After + public void cleanup() { + eventBus.post(new SourceRemovedEvent(source)); + } + + @Test + public void testBoolean() { + source = new NetworkTableEntrySource(eventBus, + origin -> new MockExceptionWitness(eventBus, origin), + osf, + testingNtManager, + BOOLEAN_PATH, + NetworkTableEntrySource.Types.BOOLEAN); + + Assert.assertTrue(source.updateOutputSockets()); + Assert.assertTrue((boolean) source.getOutputSockets().get(0).getValue().get()); + } - new NetworkTableEntrySource(origin -> new MockExceptionWitness(eventBus, origin), + @Test + public void testBooleanWrongTypeNumber() { + source = new NetworkTableEntrySource(eventBus, + origin -> new MockExceptionWitness(eventBus, origin), osf, - nrf, - "/Test/path", + testingNtManager, + NUMBER_PATH, NetworkTableEntrySource.Types.BOOLEAN); + + Assert.assertFalse(source.updateOutputSockets()); + } + + @Test + public void testBooleanWrongTypeString() { + source = new NetworkTableEntrySource(eventBus, + origin -> new MockExceptionWitness(eventBus, origin), + osf, + testingNtManager, + STRING_PATH, + NetworkTableEntrySource.Types.BOOLEAN); + + Assert.assertFalse(source.updateOutputSockets()); + } + + @Test + public void testNumber() { + source = new NetworkTableEntrySource(eventBus, + origin -> new MockExceptionWitness(eventBus, origin), + osf, + testingNtManager, + NUMBER_PATH, + NetworkTableEntrySource.Types.NUMBER); + + Assert.assertTrue(source.updateOutputSockets()); + Assert.assertEquals( + TEST_NUMBER, (double) source.getOutputSockets().get(0).getValue().get(), 0.00001); + } + + @Test + public void testNumberWrongTypeBoolean() { + source = new NetworkTableEntrySource(eventBus, + origin -> new MockExceptionWitness(eventBus, origin), + osf, + testingNtManager, + BOOLEAN_PATH, + NetworkTableEntrySource.Types.NUMBER); + + Assert.assertFalse(source.updateOutputSockets()); + } + + @Test + public void testNumberWrongTypeString() { + source = new NetworkTableEntrySource(eventBus, + origin -> new MockExceptionWitness(eventBus, origin), + osf, + testingNtManager, + STRING_PATH, + NetworkTableEntrySource.Types.NUMBER); + + Assert.assertFalse(source.updateOutputSockets()); + } + + @Test + public void testString() { + source = new NetworkTableEntrySource(eventBus, + origin -> new MockExceptionWitness(eventBus, origin), + osf, + testingNtManager, + STRING_PATH, + NetworkTableEntrySource.Types.STRING); + + Assert.assertTrue(source.updateOutputSockets()); + Assert.assertEquals(TEST_STRING, source.getOutputSockets().get(0).getValue().get()); + } + + @Test + public void testStringWrongTypeBoolean() { + source = new NetworkTableEntrySource(eventBus, + origin -> new MockExceptionWitness(eventBus, origin), + osf, + testingNtManager, + BOOLEAN_PATH, + NetworkTableEntrySource.Types.STRING); + + Assert.assertFalse(source.updateOutputSockets()); + } + + @Test + public void testStringWrongTypeNumber() { + source = new NetworkTableEntrySource(eventBus, + origin -> new MockExceptionWitness(eventBus, origin), + osf, + testingNtManager, + NUMBER_PATH, + NetworkTableEntrySource.Types.STRING); + + Assert.assertFalse(source.updateOutputSockets()); } } From abd31fbd75212433806056017ad8f7dc3168b8c6 Mon Sep 17 00:00:00 2001 From: Austin Shalit Date: Tue, 2 Aug 2016 19:03:26 -0700 Subject: [PATCH 3/6] Solve comments --- .../operations/network/NetworkReceiver.java | 4 +- .../network/networktables/NTManager.java | 6 +- .../core/sources/NetworkTableEntrySource.java | 57 ++++++++++--------- .../network/MockMapNetworkPublisher.java | 1 - .../sources/NetworkTableEntrySourceTest.java | 31 +++++----- 5 files changed, 55 insertions(+), 44 deletions(-) diff --git a/core/src/main/java/edu/wpi/grip/core/operations/network/NetworkReceiver.java b/core/src/main/java/edu/wpi/grip/core/operations/network/NetworkReceiver.java index ff66844d9a..a48a1fd3c6 100644 --- a/core/src/main/java/edu/wpi/grip/core/operations/network/NetworkReceiver.java +++ b/core/src/main/java/edu/wpi/grip/core/operations/network/NetworkReceiver.java @@ -3,6 +3,7 @@ import java.util.function.Consumer; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; /** * Manages the interface between the {@link PublishAnnotatedOperation} and the actual network @@ -18,7 +19,8 @@ public abstract class NetworkReceiver implements AutoCloseable { * @param path The path of the object to get */ public NetworkReceiver(String path) { - checkArgument(!path.isEmpty(), "Name cannot be an empty string"); + checkNotNull(path, "Path cannot be null"); + checkArgument(!path.isEmpty(), "Path cannot be an empty string"); this.path = path; } diff --git a/core/src/main/java/edu/wpi/grip/core/operations/network/networktables/NTManager.java b/core/src/main/java/edu/wpi/grip/core/operations/network/networktables/NTManager.java index f9485b5cff..4ffa01f351 100644 --- a/core/src/main/java/edu/wpi/grip/core/operations/network/networktables/NTManager.java +++ b/core/src/main/java/edu/wpi/grip/core/operations/network/networktables/NTManager.java @@ -178,9 +178,9 @@ public void close() { NetworkTablesJNI.removeEntryListener(entryListenerFunctionUid); synchronized (NetworkTable.class) { - // This publisher is no longer used. + // This receiver is no longer used. if (NTManager.count.addAndGet(-1) == 0) { - // We are the last publisher so shut it down + // We are the last resource using NetworkTables so shut it down NetworkTable.shutdown(); } } @@ -247,7 +247,7 @@ public void close() { synchronized (NetworkTable.class) { // This publisher is no longer used. if (NTManager.count.addAndGet(-1) == 0) { - // We are the last publisher so shut it down + // We are the last resource using NetworkTables so shut it down NetworkTable.shutdown(); } } diff --git a/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java b/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java index 682cb1b534..92da04dd4d 100644 --- a/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java +++ b/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java @@ -10,6 +10,7 @@ import edu.wpi.grip.core.sockets.SocketHints; import edu.wpi.grip.core.util.ExceptionWitness; +import com.google.common.base.CaseFormat; import com.google.common.collect.ImmutableList; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; @@ -24,12 +25,13 @@ /** * Provides a way to get a {@link Types Type} from a NetworkTable that GRIP is connected to. */ -@XStreamAlias("grip:NetworkValue") +@XStreamAlias("grip:NetworkTableValue") public class NetworkTableEntrySource extends Source { private static final String PATH_PROPERTY = "networktable_path"; private static final String TYPE_PROPERTY = "BOOLEAN"; + private final EventBus eventBus; private final OutputSocket output; private final String path; private final Types type; @@ -42,13 +44,35 @@ public interface Factory { } public enum Types { - BOOLEAN, NUMBER, STRING; + BOOLEAN { + @Override + protected SocketHint createSocketHint() { + return SocketHints.Outputs.createBooleanSocketHint(Types.BOOLEAN.toString(), false); + } + }, + NUMBER { + @Override + protected SocketHint createSocketHint() { + return SocketHints.Outputs.createNumberSocketHint(Types.NUMBER.toString(), 0.0); + } + }, + STRING { + @Override + protected SocketHint createSocketHint() { + return SocketHints.Outputs.createStringSocketHint(Types.STRING.toString(), ""); + } + }; + + Types() { + + } + + protected abstract SocketHint createSocketHint(); @Override public String toString() { - return super.toString().charAt(0) + super.toString().substring(1).toLowerCase(); + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()); } - } @AssistedInject @@ -75,12 +99,11 @@ public String toString() { @Assisted String path, @Assisted Types type) { super(exceptionWitnessFactory); + this.eventBus = eventBus; this.path = path; this.type = type; networkReceiver = networkReceiverFactory.create(path); - output = osf.create(createOutputSocket(type)); - - networkReceiver.addListener(o -> eventBus.post(new SourceHasPendingUpdateEvent(this))); + output = osf.create(type.createSocketHint()); } @Override @@ -117,7 +140,7 @@ public Properties getProperties() { @Override public void initialize() { - updateOutputSockets(); + networkReceiver.addListener(o -> eventBus.post(new SourceHasPendingUpdateEvent(this))); } @Subscribe @@ -126,22 +149,4 @@ public void onSourceRemovedEvent(SourceRemovedEvent event) { networkReceiver.close(); } } - - /** - * Create a SocketHint from the given type. - * - * @param type The type of SocketHint to create - */ - private static SocketHint createOutputSocket(Types type) { - switch (type) { - case BOOLEAN: - return SocketHints.Outputs.createBooleanSocketHint(Types.BOOLEAN.toString(), false); - case NUMBER: - return SocketHints.Outputs.createNumberSocketHint(Types.NUMBER.toString(), 0.0); - case STRING: - return SocketHints.Outputs.createStringSocketHint(Types.STRING.toString(), ""); - default: - throw new IllegalArgumentException("Invalid NetworkTable source type"); - } - } } \ No newline at end of file diff --git a/core/src/test/java/edu/wpi/grip/core/operations/network/MockMapNetworkPublisher.java b/core/src/test/java/edu/wpi/grip/core/operations/network/MockMapNetworkPublisher.java index e34d36e75d..493b45e9ee 100644 --- a/core/src/test/java/edu/wpi/grip/core/operations/network/MockMapNetworkPublisher.java +++ b/core/src/test/java/edu/wpi/grip/core/operations/network/MockMapNetworkPublisher.java @@ -46,5 +46,4 @@ public void close() { public MapNetworkPublisher create(Set keys) { return new MockMapNetworkPublisher<>(keys); } - } diff --git a/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java b/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java index d1e704ba15..c7a6d1f143 100644 --- a/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java +++ b/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java @@ -10,9 +10,12 @@ import edu.wpi.first.wpilibj.networktables.NetworkTablesJNI; import org.junit.After; -import org.junit.Assert; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + public class NetworkTableEntrySourceTest { private EventBus eventBus; @@ -51,8 +54,9 @@ public void testBoolean() { BOOLEAN_PATH, NetworkTableEntrySource.Types.BOOLEAN); - Assert.assertTrue(source.updateOutputSockets()); - Assert.assertTrue((boolean) source.getOutputSockets().get(0).getValue().get()); + assertTrue("Socket could not be updated", source.updateOutputSockets()); + assertTrue("The socket's value was false, expected true.", + (boolean) source.getOutputSockets().get(0).getValue().get()); } @Test @@ -64,7 +68,7 @@ public void testBooleanWrongTypeNumber() { NUMBER_PATH, NetworkTableEntrySource.Types.BOOLEAN); - Assert.assertFalse(source.updateOutputSockets()); + assertFalse("The socket was able to update with an invalid type", source.updateOutputSockets()); } @Test @@ -76,7 +80,7 @@ public void testBooleanWrongTypeString() { STRING_PATH, NetworkTableEntrySource.Types.BOOLEAN); - Assert.assertFalse(source.updateOutputSockets()); + assertFalse("The socket was able to update with an invalid type", source.updateOutputSockets()); } @Test @@ -88,8 +92,8 @@ public void testNumber() { NUMBER_PATH, NetworkTableEntrySource.Types.NUMBER); - Assert.assertTrue(source.updateOutputSockets()); - Assert.assertEquals( + assertTrue("Socket could not be updated", source.updateOutputSockets()); + assertEquals("Expected numbers to be equal -- they are not equal", TEST_NUMBER, (double) source.getOutputSockets().get(0).getValue().get(), 0.00001); } @@ -102,7 +106,7 @@ public void testNumberWrongTypeBoolean() { BOOLEAN_PATH, NetworkTableEntrySource.Types.NUMBER); - Assert.assertFalse(source.updateOutputSockets()); + assertFalse("The socket was able to update with an invalid type", source.updateOutputSockets()); } @Test @@ -114,7 +118,7 @@ public void testNumberWrongTypeString() { STRING_PATH, NetworkTableEntrySource.Types.NUMBER); - Assert.assertFalse(source.updateOutputSockets()); + assertFalse("The socket was able to update with an invalid type", source.updateOutputSockets()); } @Test @@ -126,8 +130,9 @@ public void testString() { STRING_PATH, NetworkTableEntrySource.Types.STRING); - Assert.assertTrue(source.updateOutputSockets()); - Assert.assertEquals(TEST_STRING, source.getOutputSockets().get(0).getValue().get()); + assertTrue("Socket could not be updated", source.updateOutputSockets()); + assertEquals("Expected Strings to be equal -- they are not equal", + TEST_STRING, source.getOutputSockets().get(0).getValue().get()); } @Test @@ -139,7 +144,7 @@ public void testStringWrongTypeBoolean() { BOOLEAN_PATH, NetworkTableEntrySource.Types.STRING); - Assert.assertFalse(source.updateOutputSockets()); + assertFalse("The socket was able to update with an invalid type", source.updateOutputSockets()); } @Test @@ -151,7 +156,7 @@ public void testStringWrongTypeNumber() { NUMBER_PATH, NetworkTableEntrySource.Types.STRING); - Assert.assertFalse(source.updateOutputSockets()); + assertFalse("The socket was able to update with an invalid type", source.updateOutputSockets()); } } From e8cd49ecf1cc72022238e73782026c816345af24 Mon Sep 17 00:00:00 2001 From: Austin Shalit Date: Tue, 9 Aug 2016 10:26:57 -0700 Subject: [PATCH 4/6] Update XStreamAlias --- .../java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java b/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java index f0742f3608..98d6e7be21 100644 --- a/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java +++ b/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java @@ -25,7 +25,7 @@ /** * Provides a way to get a {@link Types Type} from a NetworkTable that GRIP is connected to. */ -@XStreamAlias("grip:NetworkTableValue") +@XStreamAlias("grip:NetworkTableEntry") public class NetworkTableEntrySource extends Source { private static final String PATH_PROPERTY = "networktable_path"; From 40450c523964c59aa640b2b29da80a647dada85a Mon Sep 17 00:00:00 2001 From: Austin Shalit Date: Sat, 27 Aug 2016 12:12:37 -0400 Subject: [PATCH 5/6] Only use networktables when we need it --- .../core/operations/network/MockGripNetworkModule.java | 3 +-- .../core/operations/network/MockNetworkReceiver.java | 9 +++++++++ .../network/networktables/TestingNTManager.java | 7 ++++++- .../grip/core/sources/NetworkTableEntrySourceTest.java | 10 ++++++++-- 4 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 core/src/test/java/edu/wpi/grip/core/operations/network/MockNetworkReceiver.java diff --git a/core/src/test/java/edu/wpi/grip/core/operations/network/MockGripNetworkModule.java b/core/src/test/java/edu/wpi/grip/core/operations/network/MockGripNetworkModule.java index afa34b3907..1aac03e77c 100644 --- a/core/src/test/java/edu/wpi/grip/core/operations/network/MockGripNetworkModule.java +++ b/core/src/test/java/edu/wpi/grip/core/operations/network/MockGripNetworkModule.java @@ -1,6 +1,5 @@ package edu.wpi.grip.core.operations.network; -import edu.wpi.grip.core.operations.network.networktables.TestingNTManager; import edu.wpi.grip.core.operations.network.ros.MockROSManager; import edu.wpi.grip.core.operations.network.ros.ROSNetworkPublisherFactory; @@ -25,6 +24,6 @@ protected void configure() { bind(MapNetworkReceiverFactory.class) .annotatedWith(Names.named("ntManager")) - .to(TestingNTManager.class); + .to(MockNetworkReceiver.class); } } diff --git a/core/src/test/java/edu/wpi/grip/core/operations/network/MockNetworkReceiver.java b/core/src/test/java/edu/wpi/grip/core/operations/network/MockNetworkReceiver.java new file mode 100644 index 0000000000..6d90778633 --- /dev/null +++ b/core/src/test/java/edu/wpi/grip/core/operations/network/MockNetworkReceiver.java @@ -0,0 +1,9 @@ +package edu.wpi.grip.core.operations.network; + +public class MockNetworkReceiver implements MapNetworkReceiverFactory { + + @Override + public NetworkReceiver create(String path) { + return null; + } +} diff --git a/core/src/test/java/edu/wpi/grip/core/operations/network/networktables/TestingNTManager.java b/core/src/test/java/edu/wpi/grip/core/operations/network/networktables/TestingNTManager.java index 558f78b410..0afd6aa860 100644 --- a/core/src/test/java/edu/wpi/grip/core/operations/network/networktables/TestingNTManager.java +++ b/core/src/test/java/edu/wpi/grip/core/operations/network/networktables/TestingNTManager.java @@ -12,7 +12,7 @@ * This class encapsulates the way we map various settings to the global NetworkTables state. */ @Singleton -public class TestingNTManager extends NTManager { +public class TestingNTManager extends NTManager implements AutoCloseable { private static final Logger logger = Logger.getLogger(TestingNTManager.class.getName()); @@ -33,4 +33,9 @@ public TestingNTManager() { NetworkTable.initialize(); } + @Override + public void close() { + NetworkTable.shutdown(); + } + } diff --git a/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java b/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java index a09426937e..e8d8eef4b3 100644 --- a/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java +++ b/core/src/test/java/edu/wpi/grip/core/sources/NetworkTableEntrySourceTest.java @@ -10,6 +10,7 @@ import edu.wpi.first.wpilibj.networktables.NetworkTablesJNI; import org.junit.After; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -20,9 +21,9 @@ public class NetworkTableEntrySourceTest { private final EventBus eventBus; private final MockOutputSocketFactory osf; - private final TestingNTManager testingNtManager; private NetworkTableEntrySource source; + private TestingNTManager testingNtManager; private static final double TEST_NUMBER = 13.13; private static final String TEST_STRING = "Some test string"; @@ -33,6 +34,10 @@ public class NetworkTableEntrySourceTest { public NetworkTableEntrySourceTest() { eventBus = new EventBus(); osf = new MockOutputSocketFactory(eventBus); + } + + @Before + public void setUp() { testingNtManager = new TestingNTManager(); NetworkTablesJNI.putBoolean(BOOLEAN_PATH, true); @@ -41,8 +46,9 @@ public NetworkTableEntrySourceTest() { } @After - public void cleanup() { + public void tearDown() { eventBus.post(new SourceRemovedEvent(source)); + testingNtManager.close(); } @Test From fc680f89299be36ef7389c25e0efdfdb9cf02723 Mon Sep 17 00:00:00 2001 From: Austin Shalit Date: Sat, 27 Aug 2016 13:30:12 -0400 Subject: [PATCH 6/6] Cleanup --- .../edu/wpi/grip/core/sources/NetworkTableEntrySource.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java b/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java index 98d6e7be21..9742a4392c 100644 --- a/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java +++ b/core/src/main/java/edu/wpi/grip/core/sources/NetworkTableEntrySource.java @@ -73,6 +73,10 @@ protected SocketHint createSocketHint() { public String toString() { return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()); } + + public String toProperty() { + return toString().toUpperCase(); + } } @AssistedInject @@ -134,7 +138,7 @@ protected boolean updateOutputSockets() { public Properties getProperties() { Properties properties = new Properties(); properties.setProperty(PATH_PROPERTY, path); - properties.setProperty(TYPE_PROPERTY, type.toString().toUpperCase()); + properties.setProperty(TYPE_PROPERTY, type.toProperty()); return properties; }