1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.net.server;
15
16 import static org.junit.Assert.assertFalse;
17 import static org.junit.Assert.assertNotNull;
18 import static org.junit.Assert.assertSame;
19 import static org.junit.Assert.assertTrue;
20
21 import java.util.concurrent.Executor;
22 import java.util.concurrent.ExecutorService;
23 import java.util.concurrent.Executors;
24 import java.util.concurrent.TimeUnit;
25 import java.util.concurrent.locks.Condition;
26 import java.util.concurrent.locks.Lock;
27 import java.util.concurrent.locks.ReentrantLock;
28
29 import org.junit.After;
30 import org.junit.Before;
31 import org.junit.Test;
32
33 import ch.qos.logback.core.net.mock.MockContext;
34 import ch.qos.logback.core.net.server.test.MockServerListener;
35
36 public class ConcurrentServerRunnerTest {
37
38 private static final int DELAY = 10000;
39 private static final int SHORT_DELAY = 10;
40
41 private MockContext context = new MockContext();
42 private MockServerListener<MockClient> listener = new MockServerListener<MockClient>();
43
44 private ExecutorService executor = Executors.newCachedThreadPool();
45 private InstrumentedConcurrentServerRunner runner = new InstrumentedConcurrentServerRunner(listener, executor);
46
47 @Before
48 public void setUp() throws Exception {
49 runner.setContext(context);
50 }
51
52 @After
53 public void tearDown() throws Exception {
54 executor.shutdownNow();
55 assertTrue(executor.awaitTermination(DELAY, TimeUnit.MILLISECONDS));
56 }
57
58 @Test
59 public void testStartStop() throws Exception {
60 assertFalse(runner.isRunning());
61 executor.execute(runner);
62 assertTrue(runner.awaitRunState(true, DELAY));
63 int retries = DELAY / SHORT_DELAY;
64 synchronized (listener) {
65 while (retries-- > 0 && listener.getWaiter() == null) {
66 listener.wait(SHORT_DELAY);
67 }
68 }
69 assertNotNull(listener.getWaiter());
70 runner.stop();
71 assertTrue(listener.isClosed());
72 assertFalse(runner.awaitRunState(false, DELAY));
73 }
74
75 @Test
76 public void testRunOneClient() throws Exception {
77 executor.execute(runner);
78 MockClient client = new MockClient();
79 listener.addClient(client);
80 int retries = DELAY / SHORT_DELAY;
81 synchronized (client) {
82 while (retries-- > 0 && !client.isRunning()) {
83 client.wait(SHORT_DELAY);
84 }
85 }
86 assertTrue(runner.awaitRunState(true, DELAY));
87 client.close();
88 runner.stop();
89 }
90
91 @Test
92 public void testRunManyClients() throws Exception {
93 executor.execute(runner);
94 int count = 10;
95 while (count-- > 0) {
96 MockClient client = new MockClient();
97 listener.addClient(client);
98 int retries = DELAY / SHORT_DELAY;
99 synchronized (client) {
100 while (retries-- > 0 && !client.isRunning()) {
101 client.wait(SHORT_DELAY);
102 }
103 }
104 assertTrue(runner.awaitRunState(true, DELAY));
105 }
106 runner.stop();
107 }
108
109 @Test
110 public void testRunClientAndVisit() throws Exception {
111 executor.execute(runner);
112 MockClient client = new MockClient();
113 listener.addClient(client);
114 int retries = DELAY / SHORT_DELAY;
115 synchronized (client) {
116 while (retries-- > 0 && !client.isRunning()) {
117 client.wait(SHORT_DELAY);
118 }
119 }
120 assertTrue(runner.awaitRunState(true, DELAY));
121 MockClientVisitor visitor = new MockClientVisitor();
122 runner.accept(visitor);
123 assertSame(client, visitor.getLastVisited());
124 runner.stop();
125 }
126
127 static class InstrumentedConcurrentServerRunner extends ConcurrentServerRunner<MockClient> {
128
129 private final Lock lock = new ReentrantLock();
130 private final Condition runningCondition = lock.newCondition();
131
132 public InstrumentedConcurrentServerRunner(ServerListener<MockClient> listener, Executor executor) {
133 super(listener, executor);
134 }
135
136 @Override
137 protected boolean configureClient(MockClient client) {
138 return true;
139 }
140
141 @Override
142 protected void setRunning(boolean running) {
143 lock.lock();
144 try {
145 super.setRunning(running);
146 runningCondition.signalAll();
147 } finally {
148 lock.unlock();
149 }
150 }
151
152 public boolean awaitRunState(boolean state, long delay) throws InterruptedException {
153 lock.lock();
154 try {
155 while (isRunning() != state) {
156 runningCondition.await(delay, TimeUnit.MILLISECONDS);
157 }
158 return isRunning();
159 } finally {
160 lock.unlock();
161 }
162 }
163 }
164
165 }