blob: 0fa212196d5278cac14c104c0cd749da1d6680fa [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 * @test
26 * @bug 7654321
27 * @summary Tests the NotificationBuffer class.
28 * @author Eamonn McManus
29 * @run clean NotificationBufferTest
30 * @run build NotificationBufferTest NotificationSender NotificationSenderMBean
31 * @run main NotificationBufferTest
32 */
33
34import java.util.Arrays;
35import java.util.Collections;
36import java.util.HashSet;
37import java.util.List;
38import java.util.Set;
39import java.util.HashMap;
40
41import javax.management.MBeanServer;
42import javax.management.MBeanServerFactory;
43import javax.management.MBeanServerInvocationHandler;
44import javax.management.MBeanServerNotification;
45import javax.management.Notification;
46import javax.management.NotificationFilter;
47import javax.management.NotificationFilterSupport;
48import javax.management.ObjectName;
49import javax.management.loading.MLet;
50
51import javax.management.remote.NotificationResult;
52import javax.management.remote.TargetedNotification;
53
54import com.sun.jmx.remote.internal.ArrayNotificationBuffer;
55import com.sun.jmx.remote.internal.NotificationBufferFilter;
56import com.sun.jmx.remote.internal.NotificationBuffer;
57
58public class NotificationBufferTest {
59
60 public static void main(String[] args) {
61// System.setProperty("java.util.logging.config.file",
62// "../../../../logging.properties");
63// // we are in <workspace>/build/test/JTwork/scratch
64 try {
65// java.util.logging.LogManager.getLogManager().readConfiguration();
66 boolean ok = test();
67 if (ok) {
68 System.out.println("Test completed");
69 return;
70 } else {
71 System.out.println("Test failed!");
72 System.exit(1);
73 }
74 } catch (Exception e) {
75 System.err.println("Unexpected exception: " + e);
76 e.printStackTrace();
77 System.exit(1);
78 }
79 }
80
81 private static boolean test() throws Exception {
82 MBeanServer mbs = MBeanServerFactory.createMBeanServer();
83
84 Integer queuesize = new Integer(10);
85 HashMap env = new HashMap();
86 env.put(com.sun.jmx.remote.util.EnvHelp.BUFFER_SIZE_PROPERTY, queuesize);
87 final NotificationBuffer nb =
88 ArrayNotificationBuffer.getNotificationBuffer(mbs, env);
89
90 final ObjectName senderName = new ObjectName("dom:type=sender");
91 final ObjectName wildcardName = new ObjectName("*:*");
92 final String notifType =
93 MBeanServerNotification.REGISTRATION_NOTIFICATION;
94
95 Integer allListenerId = new Integer(99);
96 NotificationBufferFilter allListenerFilter =
97 makeFilter(allListenerId, wildcardName, null);
98 NotificationFilterSupport regFilter = new NotificationFilterSupport();
99 regFilter.enableType(notifType);
100
101 // Get initial sequence number
102 NotificationResult nr =
103 nb.fetchNotifications(allListenerFilter, 0, 0L, 0);
104 int nnotifs = nr.getTargetedNotifications().length;
105 if (nnotifs > 0) {
106 System.out.println("Expected 0 notifs for initial fetch, " +
107 "got " + nnotifs);
108 return false;
109 }
110 System.out.println("Got 0 notifs for initial fetch, OK");
111
112 long earliest = nr.getEarliestSequenceNumber();
113 long next = nr.getNextSequenceNumber();
114 if (earliest != next) {
115 System.out.println("Expected earliest==next in initial fetch, " +
116 "earliest=" + earliest + "; next=" + next);
117 return false;
118 }
119 System.out.println("Got earliest==next in initial fetch, OK");
120
121 mbs.createMBean(MLet.class.getName(), null);
122 mbs.createMBean(NotificationSender.class.getName(), senderName);
123
124 NotificationSenderMBean sender = (NotificationSenderMBean)
125 MBeanServerInvocationHandler.newProxyInstance(mbs,
126 senderName,
127 NotificationSenderMBean.class,
128 false);
129
130 /* We test here that MBeans already present when the
131 NotificationBuffer was created get a listener for the
132 buffer, as do MBeans created later. The
133 MBeanServerDelegate was already present, while the
134 NotificationSender was created later. */
135
136 // Check that the NotificationSender does indeed have a listener
137 /* Note we are dependent on the specifics of our JMX
138 implementation here. There is no guarantee that the MBean
139 creation listeners will have run to completion when
140 creation of the MBean returns. */
141 int nlisteners = sender.getListenerCount();
142 if (nlisteners != 1) {
143 System.out.println("Notification sender should have 1 listener, " +
144 "has " + nlisteners);
145 return false;
146 }
147 System.out.println("Notification sender has 1 listener, OK");
148
149 // Now we should see two creation notifications
150 nr = nb.fetchNotifications(allListenerFilter, next, 0L,
151 Integer.MAX_VALUE);
152 TargetedNotification[] tns = nr.getTargetedNotifications();
153 if (tns.length != 2) {
154 System.out.println("Expected 2 notifs, got: " +
155 Arrays.asList(tns));
156 return false;
157 }
158 if (!(tns[0].getNotification() instanceof MBeanServerNotification)
159 || !(tns[1].getNotification() instanceof MBeanServerNotification))
160 {
161 System.out.println("Expected 2 MBeanServerNotifications, got: " +
162 Arrays.asList(tns));
163 return false;
164 }
165 if (!tns[0].getListenerID().equals(tns[1].getListenerID())
166 || !tns[0].getListenerID().equals(allListenerId)) {
167 System.out.println("Bad listener IDs: " + Arrays.asList(tns));
168 return false;
169 }
170 System.out.println("Got 2 different MBeanServerNotifications, OK");
171
172 // If we ask for max 1 notifs, we should only get one
173 nr = nb.fetchNotifications(allListenerFilter, next, 0L, 1);
174 tns = nr.getTargetedNotifications();
175 if (tns.length != 1) {
176 System.out.println("Expected 1 notif, got: " + Arrays.asList(tns));
177 return false;
178 }
179 TargetedNotification tn1 = tns[0];
180 System.out.println("Got 1 notif when asked for 1, OK");
181
182 // Now we should get the other one
183 nr = nb.fetchNotifications(allListenerFilter, nr.getNextSequenceNumber(),
184 0L, 1);
185 tns = nr.getTargetedNotifications();
186 if (tns.length != 1) {
187 System.out.println("Expected 1 notif, got: " + Arrays.asList(tns));
188 return false;
189 }
190 TargetedNotification tn2 = tns[0];
191 System.out.println("Got 1 notif when asked for 1 again, OK");
192
193 if (tn1.getNotification() == tn2.getNotification()) {
194 System.out.println("Returned same notif twice: " + tn1);
195 return false;
196 }
197 System.out.println("2 creation notifs are different, OK");
198
199 // Now we should get none (timeout is 0)
200 long oldNext = nr.getNextSequenceNumber();
201 nr = nb.fetchNotifications(allListenerFilter, oldNext, 0L,
202 Integer.MAX_VALUE);
203 tns = nr.getTargetedNotifications();
204 if (tns.length != 0) {
205 System.out.println("Expected 0 notifs, got: " +
206 Arrays.asList(tns));
207 return false;
208 }
209 System.out.println("Got 0 notifs with 0 timeout, OK");
210 if (nr.getNextSequenceNumber() != oldNext) {
211 System.out.println("Sequence number changed: " + oldNext + " -> " +
212 nr.getNextSequenceNumber());
213 return false;
214 }
215 System.out.println("Next seqno unchanged with 0 timeout, OK");
216
217 // Check that timeouts work
218 long startTime = System.currentTimeMillis();
219 nr = nb.fetchNotifications(allListenerFilter, oldNext, 250L,
220 Integer.MAX_VALUE);
221 tns = nr.getTargetedNotifications();
222 if (tns.length != 0) {
223 System.out.println("Expected 0 notifs, got: " +
224 Arrays.asList(tns));
225 return false;
226 }
227 long endTime = System.currentTimeMillis();
228 long elapsed = endTime - startTime;
229 if (elapsed < 250L) {
230 System.out.println("Elapsed time shorter than timeout: " +
231 elapsed);
232 return false;
233 }
234 System.out.println("Timeout worked, OK");
235
236 // Check that notification filtering works
237 NotificationFilter senderFilter = new NotificationFilter() {
238 public boolean isNotificationEnabled(Notification n) {
239 if (!(n instanceof MBeanServerNotification))
240 return false;
241 MBeanServerNotification mbsn = (MBeanServerNotification) n;
242 return (mbsn.getMBeanName().equals(senderName));
243 }
244 };
245 Integer senderListenerId = new Integer(88);
246 NotificationBufferFilter senderListenerFilter =
247 makeFilter(senderListenerId, wildcardName, senderFilter);
248 nr = nb.fetchNotifications(senderListenerFilter, 0, 1000L,
249 Integer.MAX_VALUE);
250 tns = nr.getTargetedNotifications();
251 if (tns.length != 1) {
252 System.out.println("Expected 1 notif, got: " + Arrays.asList(tns));
253 return false;
254 }
255 MBeanServerNotification mbsn =
256 (MBeanServerNotification) tns[0].getNotification();
257 if (!mbsn.getMBeanName().equals(senderName)) {
258 System.out.println("Expected notif with senderName, got: " +
259 mbsn + " (" + mbsn.getMBeanName() + ")");
260 return false;
261 }
262 System.out.println("Successfully applied NotificationFilter, OK");
263
264 // Now send 8 notifs to fill up our 10-element buffer
265 sender.sendNotifs("tiddly.pom", 8);
266 nr = nb.fetchNotifications(allListenerFilter, 0, 1000L,
267 Integer.MAX_VALUE);
268 tns = nr.getTargetedNotifications();
269 if (tns.length != 10) {
270 System.out.println("Expected 10 notifs, got: " +
271 Arrays.asList(tns));
272 return false;
273 }
274 System.out.println("Got full buffer of 10 notifications, OK");
275
276 // Check that the 10 notifs are the ones we expected
277 for (int i = 0; i < 10; i++) {
278 String expected =
279 (i < 2) ? notifType : "tiddly.pom";
280 String found = tns[i].getNotification().getType();
281 if (!found.equals(expected)) {
282 System.out.println("Notif " + i + " bad type: expected <" +
283 expected + ">, found <" + found + ">");
284 return false;
285 }
286 }
287 System.out.println("Notifs have right types, OK");
288
289 // Check that ObjectName filtering works
290 NotificationBufferFilter senderNameFilter =
291 makeFilter(new Integer(66), senderName, null);
292 nr = nb.fetchNotifications(senderNameFilter, 0, 0L,
293 Integer.MAX_VALUE);
294 tns = nr.getTargetedNotifications();
295 if (tns.length != 8) {
296 System.out.println("Bad result from ObjectName filtering: " +
297 Arrays.asList(tns));
298 return false;
299 }
300 System.out.println("ObjectName filtering works, OK");
301
302 // Send one more notif, which should cause the oldest one to drop
303 sender.sendNotifs("foo.bar", 1);
304 nr = nb.fetchNotifications(allListenerFilter, 0, 1000L,
305 Integer.MAX_VALUE);
306 if (nr.getEarliestSequenceNumber() <= earliest) {
307 System.out.println("Expected earliest to increase: " +
308 nr.getEarliestSequenceNumber() + " should be > "
309 + earliest);
310 return false;
311 }
312 System.out.println("Earliest notif dropped, OK");
313
314 // Check that the 10 notifs are the ones we expected
315 tns = nr.getTargetedNotifications();
316 for (int i = 0; i < 10; i++) {
317 String expected =
318 (i < 1) ? notifType
319 : (i < 9) ? "tiddly.pom" : "foo.bar";
320 String found = tns[i].getNotification().getType();
321 if (!found.equals(expected)) {
322 System.out.println("Notif " + i + " bad type: expected <" +
323 expected + ">, found <" + found + ">");
324 return false;
325 }
326 }
327 System.out.println("Notifs have right types, OK");
328
329 // Apply a filter that only selects the first notif, with max notifs 1,
330 // then check that it skipped past the others even though it already
331 // had its 1 notif
332 NotificationBufferFilter firstFilter =
333 makeFilter(new Integer(55), wildcardName, regFilter);
334 nr = nb.fetchNotifications(firstFilter, 0, 1000L, 1);
335 tns = nr.getTargetedNotifications();
336 if (tns.length != 1
337 || !tns[0].getNotification().getType().equals(notifType)) {
338 System.out.println("Unexpected return from filtered call: " +
339 Arrays.asList(tns));
340 return false;
341 }
342 nr = nb.fetchNotifications(allListenerFilter, nr.getNextSequenceNumber(),
343 0L, 1000);
344 tns = nr.getTargetedNotifications();
345 if (tns.length != 0) {
346 System.out.println("Expected 0 notifs, got: " +
347 Arrays.asList(tns));
348 return false;
349 }
350
351 // Create a second, larger buffer, which should share the same notifs
352 nr = nb.fetchNotifications(allListenerFilter, 0,
353 1000L, Integer.MAX_VALUE);
354 queuesize = new Integer(20);
355 env.put(com.sun.jmx.remote.util.EnvHelp.BUFFER_SIZE_PROPERTY, queuesize);
356 NotificationBuffer nb2 =
357 ArrayNotificationBuffer.getNotificationBuffer(mbs, env);
358 NotificationResult nr2 =
359 nb2.fetchNotifications(allListenerFilter, 0,
360 1000L, Integer.MAX_VALUE);
361 if (nr.getEarliestSequenceNumber() != nr2.getEarliestSequenceNumber()
362 || nr.getNextSequenceNumber() != nr2.getNextSequenceNumber()
363 || !sameTargetedNotifs(nr.getTargetedNotifications(),
364 nr2.getTargetedNotifications()))
365 return false;
366 System.out.println("Adding second buffer preserved notif list, OK");
367
368 // Check that the capacity is now 20
369 sender.sendNotifs("propter.hoc", 10);
370 nr2 = nb2.fetchNotifications(allListenerFilter, 0,
371 1000L, Integer.MAX_VALUE);
372 if (nr.getEarliestSequenceNumber() !=
373 nr2.getEarliestSequenceNumber()) {
374 System.out.println("Earliest seq number changed after notifs " +
375 "that should have fit");
376 return false;
377 }
378 TargetedNotification[] tns2 = new TargetedNotification[10];
379 Arrays.asList(nr2.getTargetedNotifications()).subList(0, 10).toArray(tns2);
380 if (!sameTargetedNotifs(nr.getTargetedNotifications(), tns2)) {
381 System.out.println("Early notifs changed after notifs " +
382 "that should have fit");
383 return false;
384 }
385 System.out.println("New notifications fit in now-larger buffer, OK");
386
387 // Drop the second buffer and check that the capacity shrinks
388 nb2.dispose();
389 NotificationResult nr3 =
390 nb.fetchNotifications(allListenerFilter, 0,
391 1000L, Integer.MAX_VALUE);
392 if (nr3.getEarliestSequenceNumber() != nr.getNextSequenceNumber()) {
393 System.out.println("After shrink, notifs not dropped as expected");
394 return false;
395 }
396 if (nr3.getNextSequenceNumber() != nr2.getNextSequenceNumber()) {
397 System.out.println("After shrink, next seq no does not match");
398 return false;
399 }
400 tns2 = new TargetedNotification[10];
401 Arrays.asList(nr2.getTargetedNotifications()).subList(10, 20).toArray(tns2);
402 if (!sameTargetedNotifs(nr3.getTargetedNotifications(), tns2)) {
403 System.out.println("Later notifs not preserved after shrink");
404 return false;
405 }
406 System.out.println("Dropping second buffer shrank capacity, OK");
407
408 // Final test: check that destroying the final shared buffer
409 // removes its listeners
410 nb.dispose();
411 nlisteners = sender.getListenerCount();
412 if (nlisteners != 0) {
413 System.out.println("Disposing buffer should leave 0 listeners, " +
414 "but notification sender has " + nlisteners);
415 return false;
416 }
417 System.out.println("Dropping first buffer drops listeners, OK");
418
419 return true;
420 }
421
422 private static boolean sameTargetedNotifs(TargetedNotification[] tn1,
423 TargetedNotification[] tn2) {
424 if (tn1.length != tn2.length) {
425 System.out.println("Not same length");
426 return false;
427 }
428 for (int i = 0; i < tn1.length; i++) {
429 TargetedNotification n1 = tn1[i];
430 TargetedNotification n2 = tn2[i];
431 if (n1.getNotification() != n2.getNotification()
432 || !n1.getListenerID().equals(n2.getListenerID()))
433 return false;
434 }
435 return true;
436 }
437
438 private static NotificationBufferFilter makeFilter(final Integer id,
439 final ObjectName pattern,
440 final NotificationFilter filter) {
441 return new NotificationBufferFilter() {
442 public void apply(List<TargetedNotification> notifs,
443 ObjectName source, Notification notif) {
444 if (pattern.apply(source)) {
445 if (filter == null || filter.isNotificationEnabled(notif))
446 notifs.add(new TargetedNotification(notif, id));
447 }
448 }
449 };
450 };
451}