/**
* Copyright © 2014 Instituto Superior Técnico
*
* This file is part of Bennu Signals.
*
* Bennu Signals 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.
*
* Bennu Signals 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 Bennu Signals. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fenixedu.bennu.core.signals;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.slf4j.impl.SimpleLogger;
import pt.ist.fenixframework.DomainRoot;
import pt.ist.fenixframework.FenixFramework;
import pt.ist.fenixframework.TransactionManager;
import com.google.common.eventbus.Subscribe;
@RunWith(JUnit4.class)
public class SignalsTest {
@BeforeClass
public static void init() throws IOException {
System.setProperty(SimpleLogger.LOG_FILE_KEY, File.createTempFile("log", "log").getAbsolutePath());
Signal.init();
}
@Before
public void cleanup() {
Signal.clear("x");
}
@Test
public void testInTransactionNotification() throws Exception {
AtomicBoolean bool = new AtomicBoolean(false);
Signal.register("x", new Listener(bool));
TransactionManager manager = FenixFramework.getTransactionManager();
manager.begin();
Signal.emit("x", new DomainObjectEvent<>(FenixFramework.getDomainRoot()));
Assert.assertEquals(false, bool.get());
manager.commit();
Assert.assertEquals(true, bool.get());
}
@Test
public void testOutsideTransactionNotification() throws Exception {
AtomicBoolean bool = new AtomicBoolean(false);
Signal.registerWithoutTransaction("x", new Listener(bool));
TransactionManager manager = FenixFramework.getTransactionManager();
manager.begin();
Signal.emit("x", new DomainObjectEvent<>(FenixFramework.getDomainRoot()));
Assert.assertEquals(false, bool.get());
manager.commit();
Assert.assertEquals(true, bool.get());
}
public static class Listener {
private final AtomicBoolean bool;
public Listener(AtomicBoolean bool) {
this.bool = bool;
}
@Subscribe
public void handleEvent(DomainObjectEvent<DomainRoot> event) {
Assert.assertTrue("Event is not for domain root!", event.getInstance() instanceof DomainRoot);
Assert.assertTrue("Instances do not match!", event.getInstance() == FenixFramework.getDomainRoot());
bool.set(true);
}
}
@Test
public void testLambdaSignals() throws Exception {
AtomicBoolean bool = new AtomicBoolean(false);
Signal.register("x", (DomainObjectEvent<DomainRoot> event) -> {
Assert.assertTrue("Event is not for domain root!", event.getInstance() instanceof DomainRoot);
Assert.assertTrue("Instances do not match!", event.getInstance() == FenixFramework.getDomainRoot());
bool.set(true);
});
TransactionManager manager = FenixFramework.getTransactionManager();
manager.begin();
Assert.assertEquals(false, bool.get());
Signal.emit("x", new DomainObjectEvent<>(FenixFramework.getDomainRoot()));
Assert.assertEquals(false, bool.get());
manager.commit();
Assert.assertEquals(true, bool.get());
}
@Test
public void testExceptionHandling() {
AtomicBoolean bool = new AtomicBoolean(false);
Signal.register("x", (event) -> {
throw new NullPointerException();
});
boolean caught = false;
try {
TransactionManager manager = FenixFramework.getTransactionManager();
manager.begin();
Assert.assertEquals(false, bool.get());
Signal.emit("x", new DomainObjectEvent<>(FenixFramework.getDomainRoot()));
Assert.assertEquals(false, bool.get());
manager.commit();
} catch (Throwable e) {
caught = true;
Assert.assertTrue("Wrong Exception", e.getCause() instanceof RuntimeException);
Assert.assertTrue("Wrong Exception", e.getMessage().equals("Exceptions while emiting signals"));
Assert.assertTrue("Incorrect Exception emited", e.getCause().getCause() instanceof NullPointerException);
}
Assert.assertTrue("Exception not thrown", caught);
}
@Test
public void testMultipleExceptionHandling() {
AtomicBoolean bool = new AtomicBoolean(false);
Signal.register("x", (event) -> {
throw new NullPointerException();
});
Signal.register("x", (event) -> {
throw new UnsupportedOperationException();
});
boolean caught = false;
try {
TransactionManager manager = FenixFramework.getTransactionManager();
manager.begin();
Assert.assertEquals(false, bool.get());
Signal.emit("x", new DomainObjectEvent<>(FenixFramework.getDomainRoot()));
Assert.assertEquals(false, bool.get());
manager.commit();
} catch (Throwable e) {
caught = true;
Assert.assertTrue("Wrong Exception", e.getCause() instanceof RuntimeException);
Assert.assertTrue("Wrong Exception", e.getMessage().equals("Exceptions while emiting signals"));
Assert.assertTrue("Incorrect Exception emited", e.getCause().getCause() instanceof NullPointerException
|| e.getCause().getCause() instanceof UnsupportedOperationException);
}
Assert.assertTrue("Exception not thrown", caught);
}
@Test
public void testSilentExceptionHandling() {
AtomicBoolean bool = new AtomicBoolean(false);
Signal.registerWithoutTransaction("x", (event) -> {
throw new NullPointerException();
});
try {
TransactionManager manager = FenixFramework.getTransactionManager();
manager.begin();
Assert.assertEquals(false, bool.get());
Signal.emit("x", new DomainObjectEvent<>(FenixFramework.getDomainRoot()));
Assert.assertEquals(false, bool.get());
manager.commit();
} catch (Throwable e) {
Assert.fail("Thrown exception");
e.printStackTrace();
}
}
@Test
public void testMultipleSilentExceptionHandling() {
AtomicBoolean bool = new AtomicBoolean(false);
Signal.registerWithoutTransaction("x", (event) -> {
throw new NullPointerException();
});
Signal.registerWithoutTransaction("x", (event) -> {
throw new UnsupportedOperationException();
});
try {
TransactionManager manager = FenixFramework.getTransactionManager();
manager.begin();
Assert.assertEquals(false, bool.get());
Signal.emit("x", new DomainObjectEvent<>(FenixFramework.getDomainRoot()));
Assert.assertEquals(false, bool.get());
manager.commit();
} catch (Throwable e) {
Assert.fail("Thrown exception");
e.printStackTrace();
}
}
@Test
public void testSignalEmitingWithinSignal() throws Exception {
AtomicBoolean bool = new AtomicBoolean(false);
Signal.register("signal1", (DomainObjectEvent<DomainRoot> event) -> {
Signal.emit("signal2", event);
});
Signal.register("signal2", (DomainObjectEvent<DomainRoot> event) -> {
bool.set(true);
});
TransactionManager manager = FenixFramework.getTransactionManager();
manager.begin();
Signal.emit("signal1", new DomainObjectEvent<>(FenixFramework.getDomainRoot()));
manager.commit();
Assert.assertTrue("Second signal wasn't emited", bool.get());
}
@Test
public void testSignalEmitingWithinSignalWithoutTransaction() throws Exception {
AtomicBoolean bool = new AtomicBoolean(false);
Signal.registerWithoutTransaction("signal1", (DomainObjectEvent<DomainRoot> event) -> {
Signal.emit("signal2", event);
});
Signal.registerWithoutTransaction("signal2", (DomainObjectEvent<DomainRoot> event) -> {
bool.set(true);
});
TransactionManager manager = FenixFramework.getTransactionManager();
manager.begin();
Signal.emit("signal1", new DomainObjectEvent<>(FenixFramework.getDomainRoot()));
manager.commit();
Assert.assertTrue("Second signal wasn't emited", bool.get());
}
}