Package co.paralleluniverse.actors.behaviors

Source Code of co.paralleluniverse.actors.behaviors.ServerTest$Message

/*
* Quasar: lightweight threads and actors for the JVM.
* Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*   or (per the licensee's choosing)
* under the terms of the GNU Lesser General Public License version 3.0
* as published by the Free Software Foundation.
*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package co.paralleluniverse.actors.behaviors;

import co.paralleluniverse.actors.ActorRef;
import co.paralleluniverse.actors.BasicActor;
import co.paralleluniverse.actors.Actor;
import co.paralleluniverse.actors.ActorRegistry;
import co.paralleluniverse.actors.LocalActor;
import co.paralleluniverse.actors.MailboxConfig;
import co.paralleluniverse.common.util.Debug;
import co.paralleluniverse.common.util.Exceptions;
import co.paralleluniverse.fibers.Fiber;
import co.paralleluniverse.fibers.FiberForkJoinScheduler;
import co.paralleluniverse.fibers.FiberScheduler;
import co.paralleluniverse.fibers.SuspendExecution;
import co.paralleluniverse.strands.Strand;
import co.paralleluniverse.strands.channels.Channels;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import static org.hamcrest.CoreMatchers.*;
import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;

/**
* These tests are also good tests for sendSync, as they test sendSync (and receive) from both fibers and threads.
*
* @author pron
*/
public class ServerTest {
    @Rule
    public TestName name = new TestName();
    @Rule
    public TestRule watchman = new TestWatcher() {
        @Override
        protected void starting(Description desc) {
            if (Debug.isDebug()) {
                System.out.println("STARTING TEST " + desc.getMethodName());
                Debug.record(0, "STARTING TEST " + desc.getMethodName());
            }
        }

        @Override
        public void failed(Throwable e, Description desc) {
            System.out.println("FAILED TEST " + desc.getMethodName() + ": " + e.getMessage());
            e.printStackTrace(System.err);
            if (Debug.isDebug() && !(e instanceof OutOfMemoryError)) {
                Debug.record(0, "EXCEPTION IN THREAD " + Thread.currentThread().getName() + ": " + e + " - " + Arrays.toString(e.getStackTrace()));
                Debug.dumpRecorder("~/quasar.dump");
            }
        }

        @Override
        protected void succeeded(Description desc) {
            Debug.record(0, "DONE TEST " + desc.getMethodName());
        }
    };

    @After
    public void tearDown() {
        ActorRegistry.clear();
    }

    static final MailboxConfig mailboxConfig = new MailboxConfig(10, Channels.OverflowPolicy.THROW);
    private FiberScheduler scheduler;

    public ServerTest() {
        scheduler = new FiberForkJoinScheduler("test", 4, null, false);
    }

    private Server<Message, Integer, Message> spawnServer(ServerHandler<Message, Integer, Message> server) {
        return new ServerActor<>("server", server).spawn(scheduler);
    }

    private <T extends Actor<Message, V>, Message, V> T spawnActor(T actor) {
        Fiber fiber = new Fiber(scheduler, actor);
        fiber.setUncaughtExceptionHandler(new Strand.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Strand s, Throwable e) {
                e.printStackTrace();
                throw Exceptions.rethrow(e);
            }
        });
        fiber.start();
        return actor;
    }

    @Test
    public void whenServerStartsThenInitIsCalled() throws Exception {
        final ServerHandler<Message, Integer, Message> server = mock(ServerHandler.class);
        Server<Message, Integer, Message> gs = spawnServer(server);

        try {
            LocalActor.join(gs, 100, TimeUnit.MILLISECONDS);
            fail("actor died");
        } catch (TimeoutException e) {
        }

        verify(server).init();
    }

    @Test
    public void whenShutdownIsCalledInInitThenServerStops() throws Exception {
        Server<Message, Integer, Message> gs = spawnServer(new AbstractServerHandler<Message, Integer, Message>() {
            @Override
            public void init() {
                ServerActor.currentServerActor().shutdown();
            }
        });

        LocalActor.join(gs, 100, TimeUnit.MILLISECONDS);
    }

    @Test
    public void whenCalledThenResultIsReturned() throws Exception {
        final Server<Message, Integer, Message> s = spawnServer(new AbstractServerHandler<Message, Integer, Message>() {
            @Override
            public Integer handleCall(ActorRef<?> from, Object id, Message m) {
                ServerActor.currentServerActor().shutdown();
                return m.a + m.b;
            }
        });

        Actor<Message, Integer> actor = spawnActor(new BasicActor<Message, Integer>(mailboxConfig) {
            protected Integer doRun() throws SuspendExecution, InterruptedException {
                return s.call(new Message(3, 4));
            }
        });

        int res = actor.get();
        assertThat(res, is(7));

        LocalActor.join(s, 100, TimeUnit.MILLISECONDS);
    }

    @Test
    public void whenCalledFromThreadThenResultIsReturned() throws Exception {
        Server<Message, Integer, Message> s = spawnServer(new AbstractServerHandler<Message, Integer, Message>() {
            @Override
            public Integer handleCall(ActorRef<?> from, Object id, Message m) {
                ServerActor.currentServerActor().shutdown();
                return m.a + m.b;
            }
        });

        int res = s.call(new Message(3, 4));

        assertThat(res, is(7));

        LocalActor.join(s, 100, TimeUnit.MILLISECONDS);
    }

    @Test
    public void whenCalledAndTimeoutThenThrowTimeout() throws Exception {
        Server<Message, Integer, Message> s = spawnServer(new AbstractServerHandler<Message, Integer, Message>() {
            @Override
            public Integer handleCall(ActorRef<?> from, Object id, Message m) throws SuspendExecution {
                try {
                    Strand.sleep(50);
                    ServerActor.currentServerActor().shutdown();
                    return m.a + m.b;
                } catch (InterruptedException ex) {
                    System.out.println("?????: " + Arrays.toString(ex.getStackTrace()));
                    return 40;
                }
            }
        });

        try {
            int res = s.call(new Message(3, 4), 10, TimeUnit.MILLISECONDS);
            fail("res: " + res);
        } catch (TimeoutException e) {
        }

        LocalActor.join(s, 100, TimeUnit.MILLISECONDS);
    }

    @Test
    public void testDefaultTimeout1() throws Exception {
        Server<Message, Integer, Message> s = spawnServer(new AbstractServerHandler<Message, Integer, Message>() {
            @Override
            public Integer handleCall(ActorRef<?> from, Object id, Message m) throws SuspendExecution {
                try {
                    Strand.sleep(50);
                    ServerActor.currentServerActor().shutdown();
                    return m.a + m.b;
                } catch (InterruptedException ex) {
                    System.out.println("?????: " + Arrays.toString(ex.getStackTrace()));
                    return 40;
                }
            }
        });

        s.setDefaultTimeout(10, TimeUnit.MILLISECONDS);
        try {
            int res = s.call(new Message(3, 4));
            fail("res: " + res);
        } catch (RuntimeException e) {
            assertThat(e.getCause(), instanceOf(TimeoutException.class));
        }

        LocalActor.join(s, 100, TimeUnit.MILLISECONDS);
    }

    @Test
    public void testDefaultTimeout2() throws Exception {
        Server<Message, Integer, Message> s = spawnServer(new AbstractServerHandler<Message, Integer, Message>() {
            @Override
            public Integer handleCall(ActorRef<?> from, Object id, Message m) throws SuspendExecution {
                try {
                    Strand.sleep(50);
                    ServerActor.currentServerActor().shutdown();
                    return m.a + m.b;
                } catch (InterruptedException ex) {
                    System.out.println("?????: " + Arrays.toString(ex.getStackTrace()));
                    return 40;
                }
            }
        });

        s.setDefaultTimeout(100, TimeUnit.MILLISECONDS);
        int res = s.call(new Message(3, 4));
        assertThat(res, is(7));

        LocalActor.join(s, 100, TimeUnit.MILLISECONDS);
    }

    @Test
    public void whenHandleCallThrowsExceptionThenItPropagatesToCaller() throws Exception {
        final ServerHandler<Message, Integer, Message> server = mock(ServerHandler.class);
        when(server.handleCall(any(ActorRef.class), anyObject(), any(Message.class))).thenThrow(new RuntimeException("my exception"));

        final Server<Message, Integer, Message> s = spawnServer(server);

        Actor<Message, Void> actor = spawnActor(new BasicActor<Message, Void>(mailboxConfig) {
            protected Void doRun() throws SuspendExecution, InterruptedException {
                try {
                    int res = s.call(new Message(3, 4));
                    fail();
                } catch (RuntimeException e) {
                    assertThat(e.getMessage(), equalTo("my exception"));
                }
                return null;
            }
        });

        actor.join();
        try {
            LocalActor.join(s, 100, TimeUnit.MILLISECONDS);
            fail("actor died");
        } catch (TimeoutException e) {
        }
    }

    @Test
    public void whenHandleCallThrowsExceptionThenItPropagatesToThreadCaller() throws Exception {
        final ServerHandler<Message, Integer, Message> server = mock(ServerHandler.class);
        when(server.handleCall(any(ActorRef.class), anyObject(), any(Message.class))).thenThrow(new RuntimeException("my exception"));

        final Server<Message, Integer, Message> s = spawnServer(server);

        try {
            int res = s.call(new Message(3, 4));
            fail();
        } catch (RuntimeException e) {
            assertThat(e.getMessage(), equalTo("my exception"));
        }

        try {
            LocalActor.join(s, 100, TimeUnit.MILLISECONDS);
            fail("actor died");
        } catch (TimeoutException e) {
        }
    }

    @Test
    public void whenActorDiesThenCausePropagatesToThreadCaller() throws Exception {
        final ServerHandler<Message, Integer, Message> server = mock(ServerHandler.class);
        doThrow(new RuntimeException("my exception")).when(server).init();

        final Server<Message, Integer, Message> s = spawnServer(server);

        try {
            int res = s.call(new Message(3, 4));
            fail();
        } catch (RuntimeException e) {
            assertThat(e.getMessage(), equalTo("my exception"));
        }

        try {
            LocalActor.join(s, 100, TimeUnit.MILLISECONDS);
            fail();
        } catch (ExecutionException e) {
            assertThat(e.getCause().getMessage(), equalTo("my exception"));
        }
    }

    @Test
    public void whenTimeoutThenHandleTimeoutIsCalled() throws Exception {
        final AtomicInteger counter = new AtomicInteger(0);

        ServerActor<Message, Integer, Message> s = spawnActor(new ServerActor<Message, Integer, Message>() {
            @Override
            protected void init() {
                setTimeout(20, TimeUnit.MILLISECONDS);
            }

            @Override
            protected void handleTimeout() {
                counter.incrementAndGet();
                if (counter.get() >= 5)
                    shutdown();
            }
        });

        s.join(500, TimeUnit.MILLISECONDS); // should be enough
        assertThat(counter.get(), is(5));
    }

    @Test
    public void whenCalledThenDeferredResultIsReturned() throws Exception {
        final Server<Message, Integer, Message> s = new ServerActor<Message, Integer, Message>() {
            private int a, b;
            private ActorRef<?> from;
            private Object id;
            private boolean received;

            @Override
            public void init() throws SuspendExecution {
                setTimeout(50, TimeUnit.MILLISECONDS);
            }

            @Override
            public Integer handleCall(ActorRef<?> from, Object id, Message m) {
                // save for later
                this.a = m.a;
                this.b = m.b;
                this.from = from;
                this.id = id;
                this.received = true;
                return null;
            }

            @Override
            protected void handleTimeout() throws SuspendExecution {
                if (received) {
                    reply(from, id, a + b);
                    shutdown();
                }
            }
        }.spawn();

        Actor<Message, Integer> actor = spawnActor(new BasicActor<Message, Integer>(mailboxConfig) {
            protected Integer doRun() throws SuspendExecution, InterruptedException {
                return s.call(new Message(3, 4));
            }
        });

        int res = actor.get();
        assertThat(res, is(7));

        LocalActor.join(s, 100, TimeUnit.MILLISECONDS);
    }

    @Test
    public void whenCalledFromThreadThenDeferredResultIsReturned() throws Exception {
        final Server<Message, Integer, Message> s = new ServerActor<Message, Integer, Message>() {
            private int a, b;
            private ActorRef<?> from;
            private Object id;
            private boolean received;

            @Override
            public void init() throws SuspendExecution {
                setTimeout(50, TimeUnit.MILLISECONDS);
            }

            @Override
            public Integer handleCall(ActorRef<?> from, Object id, Message m) {
                // save for later
                this.a = m.a;
                this.b = m.b;
                this.from = from;
                this.id = id;
                this.received = true;
                return null;
            }

            @Override
            protected void handleTimeout() throws SuspendExecution {
                if (received) {
                    reply(from, id, a + b);
                    shutdown();
                }
            }
        }.spawn();

        int res = s.call(new Message(3, 4));

        assertThat(res, is(7));
        LocalActor.join(s, 100, TimeUnit.MILLISECONDS);
    }

    @Test
    public void whenActorDiesDuringDeferredHandlingThenCausePropagatesToThreadCaller() throws Exception {
        final Server<Message, Integer, Message> s = new ServerActor<Message, Integer, Message>() {
            private boolean received;

            @Override
            public void init() throws SuspendExecution {
                setTimeout(50, TimeUnit.MILLISECONDS);
            }

            @Override
            public Integer handleCall(ActorRef<?> from, Object id, Message m) {
                this.received = true;
                return null;
            }

            @Override
            protected void handleTimeout() throws SuspendExecution {
                if (received)
                    throw new RuntimeException("my exception");
            }
        }.spawn();

        try {
            int res = s.call(new Message(3, 4));
            fail();
        } catch (RuntimeException e) {
            assertThat(e.getMessage(), equalTo("my exception"));
        }

        try {
            LocalActor.join(s, 100, TimeUnit.MILLISECONDS);
            fail();
        } catch (ExecutionException e) {
            assertThat(e.getCause().getMessage(), equalTo("my exception"));
        }
    }

    @Test
    public void whenCastThenHandleCastIsCalled() throws Exception {
        final ServerHandler<Message, Integer, Message> server = mock(ServerHandler.class);
        final Server<Message, Integer, Message> s = spawnServer(server);

        s.cast(new Message(3, 4));

        s.shutdown();
        LocalActor.join(s);

        verify(server).handleCast(any(ActorRef.class), anyObject(), eq(new Message(3, 4)));
    }

    @Test
    public void whenSentMessageHandleInfoIsCalled() throws Exception {
        final ServerHandler<Message, Integer, Message> server = mock(ServerHandler.class);
        final Server<Message, Integer, Message> s = spawnServer(server);

        s.send("foo");

        s.shutdown();
        LocalActor.join(s);

        verify(server).handleInfo("foo");
    }

    @Test
    public void whenSentShutdownThenTerminateIsCalledAndServerStopped() throws Exception {
        final ServerHandler<Message, Integer, Message> server = mock(ServerHandler.class);
        final Server<Message, Integer, Message> s = spawnServer(server);

        s.shutdown();
        LocalActor.join(s);

        verify(server).terminate(null);
    }

    @Test
    public void whenHandleInfoThrowsExceptionThenTerminateIsCalled() throws Exception {
        final ServerHandler<Message, Integer, Message> server = mock(ServerHandler.class);

        final Exception myException = new RuntimeException("my exception");
        doThrow(myException).when(server).handleInfo(anyObject());
        final Server<Message, Integer, Message> s = spawnServer(server);

        s.send("foo");

        try {
            LocalActor.join(s);
            fail();
        } catch (Exception e) {
            assertThat(e.getCause().getMessage(), equalTo("my exception"));
        }

        verify(server).terminate(myException);
    }

    @Test
    public void testRegistration() throws Exception {
        Server<Message, Integer, Message> s = new ServerActor<Message, Integer, Message>() {
            @Override
            protected void init() throws SuspendExecution, InterruptedException {
                // Strand.sleep(1000);
                register("my-server");
            }
        }.spawn();

        assertTrue(s == (Server) ActorRegistry.getActor("my-server"));
    }

    static class Message {
        final int a;
        final int b;

        public Message(int a, int b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public int hashCode() {
            int hash = 3;
            hash = 43 * hash + this.a;
            hash = 43 * hash + this.b;
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            final Message other = (Message) obj;
            if (this.a != other.a)
                return false;
            if (this.b != other.b)
                return false;
            return true;
        }
    }
}
TOP

Related Classes of co.paralleluniverse.actors.behaviors.ServerTest$Message

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.