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