Skip to content

Commit

Permalink
AsyncProperty Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
AustinShalit committed Aug 24, 2017
1 parent 3977868 commit 1b233e5
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
*/
public class AsyncProperty<T> extends SimpleObjectProperty<T> {

private final Map<ChangeListener<? super T>, ChangeListener<? super T>> wrappers
= new WeakHashMap<>();
private final Map<ChangeListener<? super T>, ChangeListener<? super T>> wrappers = new WeakHashMap<>();

public AsyncProperty() {
super();
Expand All @@ -37,9 +36,7 @@ public void addListener(ChangeListener<? super T> listener) {
if (wrappers.containsKey(listener)) {
return;
}
wrappers.put(listener, (obs, prev, cur) -> {
AsyncUtils.runAsync(() -> listener.changed(obs, prev, cur));
});
wrappers.put(listener, (obs, prev, cur) -> AsyncUtils.runAsync(() -> listener.changed(obs, prev, cur)));
super.addListener(wrappers.get(listener));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package edu.wpi.first.shuffleboard.api.properties;

import javafx.application.Platform;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.testfx.framework.junit5.ApplicationTest;
import org.testfx.util.WaitForAsyncUtils;

import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class AsyncPropertyTest extends ApplicationTest {

@Override
public void start(Stage stage) throws Exception {
// Setup FxToolkit
}

@Test
public void listenerAddedTwiceIsCalledTest() {
AsyncProperty<String> asyncProperty = new AsyncProperty<>();
CompletableFuture<Boolean> listenerFired = new CompletableFuture<>();
ChangeListener<String> listener = (observable, oldValue, newValue) -> listenerFired.complete(true);

asyncProperty.addListener(listener);
asyncProperty.addListener(listener);
asyncProperty.set("Value");
WaitForAsyncUtils.waitForFxEvents();

assertTrue(listenerFired.getNow(false));
}

@Test
public void removeListenerTest() {
AsyncProperty<String> asyncProperty = new AsyncProperty<>();
CompletableFuture<Boolean> listenerFired = new CompletableFuture<>();
ChangeListener<String> listener = (observable, oldValue, newValue) -> listenerFired.complete(true);

asyncProperty.addListener(listener);
asyncProperty.removeListener(listener);
asyncProperty.set("Value");
WaitForAsyncUtils.waitForFxEvents();

assertThrows(TimeoutException.class, () -> listenerFired.get(1, TimeUnit.SECONDS));
}

@Test
public void listenerIsRunOnFxThreadTest() {
AsyncProperty<String> asyncProperty = new AsyncProperty<>();
SimpleObjectProperty<String> boundProperty = new SimpleObjectProperty<>();
asyncProperty.bind(boundProperty);

CompletableFuture<Boolean> listenerActionThread = new CompletableFuture<>();
asyncProperty.addListener((observable, oldValue, newValue)
-> listenerActionThread.complete(Platform.isFxApplicationThread()));
boundProperty.set("Test");

assertTimeoutPreemptively(Duration.ofSeconds(3),
() -> assertTrue(listenerActionThread.get(), "Listener was not run on JavaFX Thread"));
}

@Nested
public class SetTest extends ApplicationTest {

private Label label;
private CompletableFuture<Throwable> exceptionThrown;

@Override
public void start(Stage stage) throws Exception {
label = new Label();
stage.setScene(new Scene(label));
stage.show();

exceptionThrown = new CompletableFuture<>();
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> exceptionThrown.complete(throwable));
}

@Test
public void setRunsOnFxThreadTest() throws Throwable {
AsyncProperty<String> property = new AsyncProperty<>();
Platform.runLater(() -> label.textProperty().bind(property));
WaitForAsyncUtils.waitForFxEvents();

property.set("Test");
WaitForAsyncUtils.waitForFxEvents();

assertFalse(exceptionThrown.isDone(), exceptionThrown.getNow(new Throwable()).getMessage());
}
}

@Nested
public class ConstructorTest {

@Test
public void initialValueConstructorTest() {
AsyncProperty<String> asyncProperty = new AsyncProperty<>("Default");
assertEquals("Default", asyncProperty.getValue());
}

@Test
public void beanNameConstructorBeanSetTest() {
Object bean = new Object();
AsyncProperty<String> asyncProperty = new AsyncProperty<>(bean, "");

assertEquals(bean, asyncProperty.getBean());
}

@Test
public void beanNameConstructorNameSetTest() {
AsyncProperty<String> asyncProperty = new AsyncProperty<>(null, "aName");

assertEquals("aName", asyncProperty.getName());
}

@Test
public void beanNameValueConstructorBeanSetTest() {
Object bean = new Object();
AsyncProperty<String> asyncProperty = new AsyncProperty<>(bean, "", "");

assertEquals(bean, asyncProperty.getBean());
}

@Test
public void beanNameValueConstructorNameSetTest() {
AsyncProperty<String> asyncProperty = new AsyncProperty<>(null, "myName", "");

assertEquals("myName", asyncProperty.getName());
}

@Test
public void beanNameValueConstructorValueSetTest() {
AsyncProperty<String> asyncProperty = new AsyncProperty<>(null, "", "testValue");

assertEquals("testValue", asyncProperty.getValue());
}

}

}

0 comments on commit 1b233e5

Please sign in to comment.