Skip to content

Commit 7711a9e

Browse files
committed
Fix failing MonitorServiceImplTest tests
1 parent 6ebf706 commit 7711a9e

File tree

2 files changed

+107
-80
lines changed

2 files changed

+107
-80
lines changed

wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorServiceImpl.java

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import software.amazon.jdbc.util.ExecutorFactory;
4343
import software.amazon.jdbc.util.Messages;
4444
import software.amazon.jdbc.util.PropertyUtils;
45+
import software.amazon.jdbc.util.connection.ConnectionService;
4546
import software.amazon.jdbc.util.connection.ConnectionServiceImpl;
4647
import software.amazon.jdbc.util.events.DataAccessEvent;
4748
import software.amazon.jdbc.util.events.Event;
@@ -197,20 +198,15 @@ public <T extends Monitor> T runIfAbsent(
197198
cacheContainer = monitorCaches.computeIfAbsent(monitorClass, k -> supplier.get());
198199
}
199200

200-
TargetDriverHelper helper = new TargetDriverHelper();
201-
java.sql.Driver driver = helper.getTargetDriver(originalUrl, originalProps);
202-
final ConnectionProvider defaultConnectionProvider = new DriverConnectionProvider(driver);
203-
final Properties propsCopy = PropertyUtils.copyProperties(originalProps);
204-
final ConnectionServiceImpl connectionService = new ConnectionServiceImpl(
205-
storageService,
206-
this,
207-
telemetryFactory,
208-
defaultConnectionProvider,
209-
originalUrl,
210-
driverProtocol,
211-
driverDialect,
212-
dbDialect,
213-
propsCopy);
201+
final ConnectionService connectionService =
202+
getConnectionService(
203+
storageService,
204+
telemetryFactory,
205+
originalUrl,
206+
driverProtocol,
207+
driverDialect,
208+
dbDialect,
209+
originalProps);
214210

215211
Monitor monitor = cacheContainer.getCache().computeIfAbsent(key, k -> {
216212
MonitorItem monitorItem = new MonitorItem(() -> initializer.createMonitor(
@@ -228,6 +224,25 @@ public <T extends Monitor> T runIfAbsent(
228224
Messages.get("MonitorServiceImpl.unexpectedMonitorClass", new Object[] {monitorClass, monitor}));
229225
}
230226

227+
protected ConnectionService getConnectionService(StorageService storageService,
228+
TelemetryFactory telemetryFactory, String originalUrl, String driverProtocol, TargetDriverDialect driverDialect,
229+
Dialect dbDialect, Properties originalProps) throws SQLException {
230+
TargetDriverHelper helper = new TargetDriverHelper();
231+
java.sql.Driver driver = helper.getTargetDriver(originalUrl, originalProps);
232+
final ConnectionProvider defaultConnectionProvider = new DriverConnectionProvider(driver);
233+
final Properties propsCopy = PropertyUtils.copyProperties(originalProps);
234+
return new ConnectionServiceImpl(
235+
storageService,
236+
this,
237+
telemetryFactory,
238+
defaultConnectionProvider,
239+
originalUrl,
240+
driverProtocol,
241+
driverDialect,
242+
dbDialect,
243+
propsCopy);
244+
}
245+
231246
@Override
232247
public @Nullable <T extends Monitor> T get(Class<T> monitorClass, Object key) {
233248
CacheContainer cacheContainer = monitorCaches.get(monitorClass);

wrapper/src/test/java/software/amazon/jdbc/util/monitoring/MonitorServiceImplTest.java

Lines changed: 78 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -21,86 +21,98 @@
2121
import static org.junit.jupiter.api.Assertions.assertNotNull;
2222
import static org.junit.jupiter.api.Assertions.assertNull;
2323
import static org.junit.jupiter.api.Assertions.assertThrows;
24+
import static org.mockito.ArgumentMatchers.any;
25+
import static org.mockito.ArgumentMatchers.anyInt;
26+
import static org.mockito.Mockito.doNothing;
27+
import static org.mockito.Mockito.doReturn;
28+
import static org.mockito.Mockito.spy;
2429

2530
import java.sql.SQLException;
2631
import java.util.Collections;
2732
import java.util.HashSet;
2833
import java.util.Properties;
2934
import java.util.concurrent.TimeUnit;
3035
import org.junit.jupiter.api.AfterEach;
36+
import org.junit.jupiter.api.Assertions;
3137
import org.junit.jupiter.api.BeforeEach;
3238
import org.junit.jupiter.api.Test;
3339
import org.mockito.Mock;
3440
import org.mockito.MockitoAnnotations;
3541
import software.amazon.jdbc.dialect.Dialect;
3642
import software.amazon.jdbc.plugin.customendpoint.CustomEndpointMonitorImpl;
3743
import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect;
44+
import software.amazon.jdbc.util.connection.ConnectionService;
3845
import software.amazon.jdbc.util.events.EventPublisher;
3946
import software.amazon.jdbc.util.storage.StorageService;
4047
import software.amazon.jdbc.util.telemetry.TelemetryFactory;
4148

4249
class MonitorServiceImplTest {
43-
@Mock StorageService storageService;
44-
@Mock TelemetryFactory telemetryFactory;
45-
@Mock TargetDriverDialect targetDriverDialect;
46-
@Mock Dialect dbDialect;
47-
@Mock EventPublisher publisher;
48-
MonitorServiceImpl monitorService;
50+
@Mock StorageService mockStorageService;
51+
@Mock ConnectionService mockConnectionService;
52+
@Mock TelemetryFactory mockTelemetryFactory;
53+
@Mock TargetDriverDialect mockTargetDriverDialect;
54+
@Mock Dialect mockDbDialect;
55+
@Mock EventPublisher mockPublisher;
56+
MonitorServiceImpl spyMonitorService;
4957
private AutoCloseable closeable;
5058

5159
@BeforeEach
5260
void setUp() {
5361
closeable = MockitoAnnotations.openMocks(this);
54-
monitorService = new MonitorServiceImpl(publisher) {
55-
@Override
56-
protected void initCleanupThread(long cleanupIntervalNanos) {
57-
// Do nothing
58-
}
59-
};
62+
spyMonitorService = spy(new MonitorServiceImpl(mockPublisher));
63+
doNothing().when(spyMonitorService).initCleanupThread(anyInt());
64+
65+
try {
66+
doReturn(mockConnectionService).when(spyMonitorService)
67+
.getConnectionService(any(), any(), any(), any(), any(), any(), any());
68+
} catch (SQLException e) {
69+
Assertions.fail(
70+
"Encountered exception while stubbing MonitorServiceImpl#getConnectionService: " + e.getMessage());
71+
}
6072
}
6173

6274
@AfterEach
6375
void tearDown() throws Exception {
6476
closeable.close();
65-
monitorService.releaseResources();
77+
spyMonitorService.releaseResources();
6678
}
6779

6880
@Test
6981
public void testMonitorError_monitorReCreated() throws SQLException, InterruptedException {
70-
monitorService.registerMonitorTypeIfAbsent(
82+
spyMonitorService.registerMonitorTypeIfAbsent(
7183
NoOpMonitor.class,
7284
TimeUnit.MINUTES.toNanos(1),
7385
TimeUnit.MINUTES.toNanos(1),
7486
new HashSet<>(Collections.singletonList(MonitorErrorResponse.RECREATE)),
7587
null
7688
);
7789
String key = "testMonitor";
78-
NoOpMonitor monitor = monitorService.runIfAbsent(
90+
NoOpMonitor monitor = spyMonitorService.runIfAbsent(
7991
NoOpMonitor.class,
8092
key,
81-
storageService,
82-
telemetryFactory,
93+
mockStorageService,
94+
mockTelemetryFactory,
8395
"jdbc:postgresql://somehost/somedb",
8496
"someProtocol",
85-
targetDriverDialect,
86-
dbDialect,
97+
mockTargetDriverDialect,
98+
mockDbDialect,
8799
new Properties(),
88-
(connectionService, pluginService) -> new NoOpMonitor(monitorService, 30)
100+
(connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30)
89101
);
90102

91-
Monitor storedMonitor = monitorService.get(NoOpMonitor.class, key);
103+
Monitor storedMonitor = spyMonitorService.get(NoOpMonitor.class, key);
92104
assertNotNull(storedMonitor);
93105
assertEquals(monitor, storedMonitor);
94106
// need to wait to give time for the monitor executor to start the monitor thread.
95107
TimeUnit.MILLISECONDS.sleep(250);
96108
assertEquals(MonitorState.RUNNING, monitor.getState());
97109

98110
monitor.state.set(MonitorState.ERROR);
99-
monitorService.checkMonitors();
111+
spyMonitorService.checkMonitors();
100112

101113
assertEquals(MonitorState.STOPPED, monitor.getState());
102114

103-
Monitor newMonitor = monitorService.get(NoOpMonitor.class, key);
115+
Monitor newMonitor = spyMonitorService.get(NoOpMonitor.class, key);
104116
assertNotNull(newMonitor);
105117
assertNotEquals(monitor, newMonitor);
106118
// need to wait to give time for the monitor executor to start the monitor thread.
@@ -110,40 +122,40 @@ public void testMonitorError_monitorReCreated() throws SQLException, Interrupted
110122

111123
@Test
112124
public void testMonitorStuck_monitorReCreated() throws SQLException, InterruptedException {
113-
monitorService.registerMonitorTypeIfAbsent(
125+
spyMonitorService.registerMonitorTypeIfAbsent(
114126
NoOpMonitor.class,
115127
TimeUnit.MINUTES.toNanos(1),
116128
1, // heartbeat times out immediately
117129
new HashSet<>(Collections.singletonList(MonitorErrorResponse.RECREATE)),
118130
null
119131
);
120132
String key = "testMonitor";
121-
NoOpMonitor monitor = monitorService.runIfAbsent(
133+
NoOpMonitor monitor = spyMonitorService.runIfAbsent(
122134
NoOpMonitor.class,
123135
key,
124-
storageService,
125-
telemetryFactory,
136+
mockStorageService,
137+
mockTelemetryFactory,
126138
"jdbc:postgresql://somehost/somedb",
127139
"someProtocol",
128-
targetDriverDialect,
129-
dbDialect,
140+
mockTargetDriverDialect,
141+
mockDbDialect,
130142
new Properties(),
131-
(connectionService, pluginService) -> new NoOpMonitor(monitorService, 30)
143+
(connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30)
132144
);
133145

134-
Monitor storedMonitor = monitorService.get(NoOpMonitor.class, key);
146+
Monitor storedMonitor = spyMonitorService.get(NoOpMonitor.class, key);
135147
assertNotNull(storedMonitor);
136148
assertEquals(monitor, storedMonitor);
137149
// need to wait to give time for the monitor executor to start the monitor thread.
138150
TimeUnit.MILLISECONDS.sleep(250);
139151
assertEquals(MonitorState.RUNNING, monitor.getState());
140152

141153
// checkMonitors() should detect the heartbeat/inactivity timeout, stop the monitor, and re-create a new one.
142-
monitorService.checkMonitors();
154+
spyMonitorService.checkMonitors();
143155

144156
assertEquals(MonitorState.STOPPED, monitor.getState());
145157

146-
Monitor newMonitor = monitorService.get(NoOpMonitor.class, key);
158+
Monitor newMonitor = spyMonitorService.get(NoOpMonitor.class, key);
147159
assertNotNull(newMonitor);
148160
assertNotEquals(monitor, newMonitor);
149161
// need to wait to give time for the monitor executor to start the monitor thread.
@@ -153,7 +165,7 @@ public void testMonitorStuck_monitorReCreated() throws SQLException, Interrupted
153165

154166
@Test
155167
public void testMonitorExpired() throws SQLException, InterruptedException {
156-
monitorService.registerMonitorTypeIfAbsent(
168+
spyMonitorService.registerMonitorTypeIfAbsent(
157169
NoOpMonitor.class,
158170
TimeUnit.MILLISECONDS.toNanos(200), // monitor expires after 200ms
159171
TimeUnit.MINUTES.toNanos(1),
@@ -163,57 +175,57 @@ public void testMonitorExpired() throws SQLException, InterruptedException {
163175
null
164176
);
165177
String key = "testMonitor";
166-
NoOpMonitor monitor = monitorService.runIfAbsent(
178+
NoOpMonitor monitor = spyMonitorService.runIfAbsent(
167179
NoOpMonitor.class,
168180
key,
169-
storageService,
170-
telemetryFactory,
181+
mockStorageService,
182+
mockTelemetryFactory,
171183
"jdbc:postgresql://somehost/somedb",
172184
"someProtocol",
173-
targetDriverDialect,
174-
dbDialect,
185+
mockTargetDriverDialect,
186+
mockDbDialect,
175187
new Properties(),
176-
(connectionService, pluginService) -> new NoOpMonitor(monitorService, 30)
188+
(connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30)
177189
);
178190

179-
Monitor storedMonitor = monitorService.get(NoOpMonitor.class, key);
191+
Monitor storedMonitor = spyMonitorService.get(NoOpMonitor.class, key);
180192
assertNotNull(storedMonitor);
181193
assertEquals(monitor, storedMonitor);
182194
// need to wait to give time for the monitor executor to start the monitor thread.
183195
TimeUnit.MILLISECONDS.sleep(250);
184196
assertEquals(MonitorState.RUNNING, monitor.getState());
185197

186198
// checkMonitors() should detect the expiration timeout and stop/remove the monitor.
187-
monitorService.checkMonitors();
199+
spyMonitorService.checkMonitors();
188200

189201
assertEquals(MonitorState.STOPPED, monitor.getState());
190202

191-
Monitor newMonitor = monitorService.get(NoOpMonitor.class, key);
203+
Monitor newMonitor = spyMonitorService.get(NoOpMonitor.class, key);
192204
// monitor should have been removed when checkMonitors() was called.
193205
assertNull(newMonitor);
194206
}
195207

196208
@Test
197209
public void testMonitorMismatch() {
198-
assertThrows(IllegalStateException.class, () -> monitorService.runIfAbsent(
210+
assertThrows(IllegalStateException.class, () -> spyMonitorService.runIfAbsent(
199211
CustomEndpointMonitorImpl.class,
200212
"testMonitor",
201-
storageService,
202-
telemetryFactory,
213+
mockStorageService,
214+
mockTelemetryFactory,
203215
"jdbc:postgresql://somehost/somedb",
204216
"someProtocol",
205-
targetDriverDialect,
206-
dbDialect,
217+
mockTargetDriverDialect,
218+
mockDbDialect,
207219
new Properties(),
208220
// indicated monitor class is CustomEndpointMonitorImpl, but actual monitor is NoOpMonitor. The monitor
209221
// service should detect this and throw an exception.
210-
(connectionService, pluginService) -> new NoOpMonitor(monitorService, 30)
222+
(connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30)
211223
));
212224
}
213225

214226
@Test
215227
public void testRemove() throws SQLException, InterruptedException {
216-
monitorService.registerMonitorTypeIfAbsent(
228+
spyMonitorService.registerMonitorTypeIfAbsent(
217229
NoOpMonitor.class,
218230
TimeUnit.MINUTES.toNanos(1),
219231
TimeUnit.MINUTES.toNanos(1),
@@ -224,30 +236,30 @@ public void testRemove() throws SQLException, InterruptedException {
224236
);
225237

226238
String key = "testMonitor";
227-
NoOpMonitor monitor = monitorService.runIfAbsent(
239+
NoOpMonitor monitor = spyMonitorService.runIfAbsent(
228240
NoOpMonitor.class,
229241
key,
230-
storageService,
231-
telemetryFactory,
242+
mockStorageService,
243+
mockTelemetryFactory,
232244
"jdbc:postgresql://somehost/somedb",
233245
"someProtocol",
234-
targetDriverDialect,
235-
dbDialect,
246+
mockTargetDriverDialect,
247+
mockDbDialect,
236248
new Properties(),
237-
(connectionService, pluginService) -> new NoOpMonitor(monitorService, 30)
249+
(connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30)
238250
);
239251
assertNotNull(monitor);
240252

241253
// need to wait to give time for the monitor executor to start the monitor thread.
242254
TimeUnit.MILLISECONDS.sleep(250);
243-
Monitor removedMonitor = monitorService.remove(NoOpMonitor.class, key);
255+
Monitor removedMonitor = spyMonitorService.remove(NoOpMonitor.class, key);
244256
assertEquals(monitor, removedMonitor);
245257
assertEquals(MonitorState.RUNNING, monitor.getState());
246258
}
247259

248260
@Test
249261
public void testStopAndRemove() throws SQLException, InterruptedException {
250-
monitorService.registerMonitorTypeIfAbsent(
262+
spyMonitorService.registerMonitorTypeIfAbsent(
251263
NoOpMonitor.class,
252264
TimeUnit.MINUTES.toNanos(1),
253265
TimeUnit.MINUTES.toNanos(1),
@@ -258,24 +270,24 @@ public void testStopAndRemove() throws SQLException, InterruptedException {
258270
);
259271

260272
String key = "testMonitor";
261-
NoOpMonitor monitor = monitorService.runIfAbsent(
273+
NoOpMonitor monitor = spyMonitorService.runIfAbsent(
262274
NoOpMonitor.class,
263275
key,
264-
storageService,
265-
telemetryFactory,
276+
mockStorageService,
277+
mockTelemetryFactory,
266278
"jdbc:postgresql://somehost/somedb",
267279
"someProtocol",
268-
targetDriverDialect,
269-
dbDialect,
280+
mockTargetDriverDialect,
281+
mockDbDialect,
270282
new Properties(),
271-
(connectionService, pluginService) -> new NoOpMonitor(monitorService, 30)
283+
(connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30)
272284
);
273285
assertNotNull(monitor);
274286

275287
// need to wait to give time for the monitor executor to start the monitor thread.
276288
TimeUnit.MILLISECONDS.sleep(250);
277-
monitorService.stopAndRemove(NoOpMonitor.class, key);
278-
assertNull(monitorService.get(NoOpMonitor.class, key));
289+
spyMonitorService.stopAndRemove(NoOpMonitor.class, key);
290+
assertNull(spyMonitorService.get(NoOpMonitor.class, key));
279291
assertEquals(MonitorState.STOPPED, monitor.getState());
280292
}
281293

0 commit comments

Comments
 (0)