/*
* Minha.pt: middleware testing platform.
* Copyright (c) 2011-2014, Universidade do Minho.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package pt.minha.test.model.lang;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList;
import mockit.Expectations;
import mockit.Mocked;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import pt.minha.api.Entry;
import pt.minha.api.Exit;
import pt.minha.api.Process;
import pt.minha.api.World;
import pt.minha.api.sim.Global;
import pt.minha.api.sim.Simulation;
public class SynchronizedTest {
private World world;
private Process proc;
@BeforeClass
public void init() throws Exception {
world = new Simulation();
proc = world.createHost().createProcess();
}
@AfterClass
public void cleanup() throws Exception {
world.close();
}
@Global
public static interface Callback {
public void enter(String name);
public void leave(String name);
}
@Global
public static interface Target {
public void execute(String name, int delay, Callback cb);
}
public static class Impl implements Target {
private static Object o = new Object();
public void execute(String name, int delay, Callback cb) {
synchronized(o) {
cb.enter(name);
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
cb.leave(name);
}
}
public void illegalWait() throws InterruptedException {
o.wait();
}
public void illegalNotify() throws InterruptedException {
o.notify();
}
}
public static class ImplArray implements Target {
private static Object o = new int[0];
public void execute(String name, int delay, Callback cb) {
synchronized(o) {
cb.enter(name);
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
cb.leave(name);
}
}
}
public static class ImplNative implements Target {
private static Object o = new ArrayList<Integer>();
public void execute(String name, int delay, Callback cb) {
synchronized(o) {
cb.enter(name);
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
cb.leave(name);
}
}
}
@Test
public void simple(@Mocked final Callback cb) throws Exception {
new Expectations() {
{
cb.enter("t1");
cb.leave("t1");
}
};
Entry<Target> en = proc.createEntry(Target.class, Impl.class.getName());
Exit<Callback> ex = proc.createExit(Callback.class, cb);
en.queue().execute("t1", 1000, ex.report());
world.run();
}
@Test
public void concurrent(@Mocked final Callback cb) throws Exception {
new Expectations() {
{
cb.enter("t1");
cb.leave("t1");
cb.enter("t2");
cb.leave("t2");
}
};
Entry<Target> en1 = proc.createEntry(Target.class, Impl.class.getName());
Entry<Target> en2 = proc.createEntry(Target.class, Impl.class.getName());
Exit<Callback> ex = proc.createExit(Callback.class, cb);
en1.at(1, SECONDS).queue().execute("t1", 2000, ex.report());
en2.at(2, SECONDS).queue().execute("t2", 0, ex.report());
world.run();
}
@Test
public void simpleOnArray(@Mocked final Callback cb) throws Exception {
new Expectations() {
{
cb.enter("t1");
cb.leave("t1");
}
};
Entry<Target> en = proc.createEntry(Target.class, ImplArray.class.getName());
Exit<Callback> ex = proc.createExit(Callback.class, cb);
en.queue().execute("t1", 1000, ex.report());
world.run();
}
// https://code.google.com/p/minha/issues/detail?id=5
@Test
public void simpleOnNative(@Mocked final Callback cb) throws Exception {
new Expectations() {
{
cb.enter("t1");
cb.leave("t1");
}
};
Entry<Target> en = proc.createEntry(Target.class, ImplNative.class.getName());
Exit<Callback> ex = proc.createExit(Callback.class, cb);
en.queue().execute("t1", 1000, ex.report());
world.run();
}
public static class ExceptionImpl implements Runnable {
private Object o = new Object();
public void run() {
try {
o.wait();
} catch (InterruptedException e) {
// don't care
}
}
}
// https://code.google.com/p/minha/issues/detail?id=17
@Test(expectedExceptions={IllegalMonitorStateException.class})
public void illegalMonitorState(@Mocked final Callback cb) throws Exception {
Entry<Runnable> en = proc.createEntry(Runnable.class, ExceptionImpl.class.getName());
en.call().run();
world.run();
}
}