001 // jademx - JADE management using JMX
002 // Copyright 2005-2006 Caboodle Networks, Inc.
003 //
004 // This library is free software; you can redistribute it and/or
005 // modify it under the terms of the GNU Lesser General Public
006 // License as published by the Free Software Foundation; either
007 // version 2.1 of the License, or (at your option) any later version.
008 //
009 // This library is distributed in the hope that it will be useful,
010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 // Lesser General Public License for more details.
013 //
014 // You should have received a copy of the GNU Lesser General Public
015 // License along with this library; if not, write to the Free Software
016 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
017
018 package jade.jademx.mbean;
019
020 import java.util.Arrays;
021 import java.util.LinkedList;
022
023 import javax.management.Attribute;
024 import javax.management.AttributeList;
025 import javax.management.ListenerNotFoundException;
026 import javax.management.MBeanAttributeInfo;
027 import javax.management.MBeanInfo;
028 import javax.management.MBeanNotificationInfo;
029 import javax.management.MBeanOperationInfo;
030 import javax.management.Notification;
031 import javax.management.NotificationListener;
032 import javax.management.ObjectName;
033 import javax.management.ReflectionException;
034
035 import jade.jademx.JadeMXSuiteTest;
036 import jade.jademx.agent.Arg;
037 import jade.jademx.agent.JademxAgent;
038 import jade.jademx.agent.JademxPingAgent;
039 import jade.jademx.server.JadeMXServer;
040 import jade.jademx.server.JadeMXServerFactory;
041 import jade.wrapper.AgentState;
042 import junit.framework.Test;
043 import junit.framework.TestCase;
044 import junit.framework.TestSuite;
045
046 /**
047 * JadeAgent MBean test
048 * @author David Bernstein, <a href="http://www.caboodlenetworks.com"
049 * >Caboodle Networks, Inc.</a>
050 */
051 public class JadeAgentTest extends TestCase implements NotificationListener {
052
053 ///** test(suite) name */
054 //private static String name =
055 // JadeMXSuiteTest.nameWithClass(
056 // JadePlatformTest.class,
057 // "testing JadeAgent: JADE agent MBean class");
058
059
060 /** jadeMXServer we're using */
061 private JadeMXServer jadeMXServer = null;
062
063 /** runtime for test use */
064 private JadeRuntime jadeRuntime = null;
065
066 /** mbean for platform under test */
067 JadePlatform platformMBean = null;
068
069 ///** resource name for configuration of one empty platform */
070 //private static final String EMPTY_PLATFORM_CONFIG_RESOURCE =
071 // "jade/jademx/config/one-empty-platform.xml";
072 /** resource name for configuration of two ping agents */
073 private static final String TWO_PING_CONFIG_RESOURCE =
074 "jade/jademx/config/two-ping-agents.xml";
075 /** name for 1st ping agent */
076 private static final String AGENT_LOCAL_NAME_PINGER1 = "pinger1";
077 /** name for 2nd ping agent */
078 private static final String AGENT_LOCAL_NAME_PINGER2 = "pinger2";
079
080
081 // tests
082
083
084 /* (non-Javadoc)
085 * @see junit.framework.TestCase#setUp()
086 */
087 protected void setUp() throws Exception {
088 // first get JadeMXServer
089 jadeMXServer = JadeMXServerFactory.jadeMXServerBySysProp();
090 // now get a factory to use
091 JadeFactory jadeFactory =
092 new JadeFactory( jadeMXServer );
093 jadeRuntime = (JadeRuntime)jadeFactory.runtimeInstance();
094 //JadeMXSuiteTest.listMBeans(mBeanServer, "at end of setUp()");
095 JadePlatform platformMBeans[] =
096 jadeRuntime.platformsFromConfigResource(
097 TWO_PING_CONFIG_RESOURCE );
098 platformMBean = platformMBeans[0];
099 notificationQueue = new LinkedList();
100 }
101
102
103
104 /* (non-Javadoc)
105 * @see junit.framework.TestCase#tearDown()
106 */
107 protected void tearDown() throws Exception {
108 //JadeMXSuiteTest.listMBeans(mBeanServer,
109 //"at start of JadePlatformTest.tearDown()");
110 if ( null != jadeRuntime ) {
111 jadeRuntime.shutdown();
112 }
113 //JadeMXSuiteTest.listMBeans(mBeanServer,
114 //"at end of JadePlatformTest.tearDown()");
115 }
116
117
118 /** a queue for notifications */
119 private LinkedList notificationQueue = null;
120 /* (non-Javadoc)
121 * @see javax.management.NotificationListener#handleNotification(
122 * javax.management.Notification, java.lang.Object)
123 */
124 public void handleNotification(Notification notification, Object handback) {
125 //System.err.println("JadeAgentTest.handleNotification(): "+
126 // "got notification "+notification);
127 synchronized ( notificationQueue ) {
128 notificationQueue.addLast( notification );
129 notificationQueue.notifyAll();
130 }
131 }
132 /** expected arguments for pinger2 */
133 private final static Object PINGER2_ARGS_AS_OBJ =
134 new Object[] {"foo","bar",new Arg("baz")};
135 private final static Object PINGER2_ARGS_AS_ARR[] =
136 (Object[])PINGER2_ARGS_AS_OBJ;
137
138 /**
139 * test getting agent's arguments
140 * @throws JademxException unexpected problems with jademx
141 */
142 public void testGetArguments() throws JademxException {
143 int ARG_COUNT = PINGER2_ARGS_AS_ARR.length;
144 String ARG0 = (String)PINGER2_ARGS_AS_ARR[0];
145 String ARG1 = (String)PINGER2_ARGS_AS_ARR[1];
146 Arg ARG2 = (Arg) PINGER2_ARGS_AS_ARR[2];
147 JadeAgent jadeAgent = platformMBean.getAgent( AGENT_LOCAL_NAME_PINGER2);
148 Object args[] = jadeAgent.getArguments();
149 int argLen = args.length;
150 assertEquals("expected 3 arguments but found "+argLen,
151 ARG_COUNT, argLen );
152 assertEquals("expected argument 0 to be \""+
153 ARG0+"\" but it's \""+args[0], ARG0, args[0]);
154 assertEquals("expected argument 1 to be \""+
155 ARG1+"\" but it's \""+args[1], ARG1, args[1]);
156 assertEquals("expected argument 2 to be "+
157 ARG2+" but it's \""+args[2], ARG2, args[2]);
158 }
159
160 /** expected class name for pinger2 agent */
161 private final String PINGER2_CLASS_NAME =
162 JademxPingAgent.class.getName();
163
164 /**
165 * test getting agent's classname
166 * @throws JademxException unexpected problems with jademx
167 */
168 public void testGetClassName() throws JademxException {
169 JadeAgent jadeAgent = platformMBean.getAgent( AGENT_LOCAL_NAME_PINGER2);
170 String actualCN = jadeAgent.getClassName();
171 assertEquals("expected agent class name \""+PINGER2_CLASS_NAME+
172 "\" but got \""+actualCN+"\"",PINGER2_CLASS_NAME,actualCN);
173 }
174
175
176 /**
177 * test getting agent's local name
178 * @throws JademxException unexpected problems with jademx
179 */
180 public void testGetLocalName() throws JademxException {
181 JadeAgent jadeAgent = platformMBean.getAgent( AGENT_LOCAL_NAME_PINGER2);
182 String actualLN = jadeAgent.getLocalName();
183 assertEquals("expected agent local name \""+AGENT_LOCAL_NAME_PINGER2+
184 "\" but got \""+actualLN+"\"",
185 AGENT_LOCAL_NAME_PINGER2,actualLN);
186 }
187
188 /** expected string MBean name for pinger2 agent */
189 private final static String PINGER2_EXPECTED_PLATFORM_OBJECT_NAME_STRING =
190 "jade:Name=platform0,Runtime=default,Type=Platform";
191
192 /**
193 * test getting agent's platform's object name string
194 * @throws JademxException unexpected problems with jademx
195 */
196 public void testGetPlatformObjectNameString() throws JademxException {
197 JadeAgent jadeAgent = platformMBean.getAgent( AGENT_LOCAL_NAME_PINGER2);
198
199 String actualPN = jadeAgent.getPlatformObjectNameString();
200 assertEquals("expected platform ObjectName string \""+
201 PINGER2_EXPECTED_PLATFORM_OBJECT_NAME_STRING+
202 "\" but got \""+actualPN+"\"",
203 PINGER2_EXPECTED_PLATFORM_OBJECT_NAME_STRING,actualPN);
204 }
205
206 /** expected full JADE name name for pinger2 agent */
207 private String pinger2ExpectedFullName() {
208 String platformJadeName = platformMBean.getPlatformName();
209 String expectedFN = AGENT_LOCAL_NAME_PINGER2 + "@" + platformJadeName;
210 return expectedFN;
211 }
212
213 /**
214 * test getting agent's full JADE name
215 * @throws JademxException unexpected problems with jademx
216 */
217 public void testGetFullName() throws JademxException {
218 JadeAgent jadeAgent = platformMBean.getAgent( AGENT_LOCAL_NAME_PINGER2);
219 //String platformJadeName = platformMBean.getPlatformName();
220 String agentFullJadeName = jadeAgent.getFullName();
221 String expectedFN = pinger2ExpectedFullName();
222 assertEquals("expected full name \""+expectedFN+"\" but got \""+
223 agentFullJadeName + "\"", expectedFN, agentFullJadeName );
224 }
225
226 /**
227 * test getting agent's JADE state code
228 * @throws JademxException unexpected problems with jademx
229 */
230 public void testGetStateCode() throws JademxException {
231 JadeAgent jadeAgent = platformMBean.getAgent( AGENT_LOCAL_NAME_PINGER2);
232 int actualStateCode = jadeAgent.getStateCode();
233 if ( ( actualStateCode != AgentState.cAGENT_STATE_INITIATED ) &&
234 ( actualStateCode != AgentState.cAGENT_STATE_ACTIVE ) &&
235 ( actualStateCode != AgentState.cAGENT_STATE_IDLE ) ) {
236 fail("expected state code "+AgentState.cAGENT_STATE_INITIATED+
237 " or "+AgentState.cAGENT_STATE_ACTIVE+
238 " or "+AgentState.cAGENT_STATE_IDLE+
239 " but got "+
240 actualStateCode);
241 }
242 }
243
244 /**
245 * test getting agent's state JADE name
246 * @throws JademxException unexpected problems with jademx
247 */
248 public void testGetStateName() throws JademxException {
249 JadeAgent jadeAgent = platformMBean.getAgent( AGENT_LOCAL_NAME_PINGER2);
250 String actualStateName = jadeAgent.getStateName();
251 final String initiated = "Initiated";
252 final String active = "Active";
253 final String idle = "Idle";
254 if ( !initiated.equals( actualStateName ) &&
255 !active.equals( actualStateName ) &&
256 !idle.equals( actualStateName ) ) {
257 fail("expected state name \""+initiated+
258 "\" or \""+active+
259 "\" or \""+idle+
260 "\" but got \""+
261 actualStateName+"\"");
262 }
263 }
264
265
266 /**
267 * test getting name property for the agent mbean
268 * @throws JademxException unexpected problems with jademx
269 */
270 public void testAgentNameProp() throws JademxException {
271 JadeAgent jadeAgent = platformMBean.getAgent( AGENT_LOCAL_NAME_PINGER2);
272 String nameProp = jadeAgent.getMBeanNamePropVal();
273 assertEquals("expected JadeAgent name property to be local name \""+
274 AGENT_LOCAL_NAME_PINGER2+"\" but it's \""+
275 nameProp,
276 AGENT_LOCAL_NAME_PINGER2, nameProp );
277 }
278
279 /**
280 * test killing an agent
281 * @throws JademxException unexpected problems with jademx
282 */
283 public void testAgentKill() throws JademxException {
284 JadeAgent jadeAgent = platformMBean.getAgent( AGENT_LOCAL_NAME_PINGER2);
285 jadeAgent.kill();
286 // killing an agent is asynchronous and so may not see evidence
287 // of it immediately
288 }
289
290 /** string verion of expected MBean name for pinger2 agent */
291 private final static String PINGER2_EXPECTED_MBEAN_NAME_STRING =
292 "jade:Name=pinger2,Platform=platform0,Runtime=default,Type=Agent";
293
294
295 /**
296 * test MBeanInfo for agent
297 * @throws JademxException unexpected problems with jademx
298 */
299 public void testAgentMBeanInfo() throws JademxException {
300
301 // verify agent binding
302 JadeAgent jadeAgentPinger2 =
303 platformMBean.getAgent( AGENT_LOCAL_NAME_PINGER2);
304 boolean boundPinger2 =
305 jadeAgentPinger2.waitForJademxAgentBinding(59*1000/*59sec*/,0);
306 assertTrue("jademx agent didn't bind", boundPinger2);
307
308 // exercise some other times for waiting
309 boundPinger2 =
310 jadeAgentPinger2.waitForJademxAgentBinding(61*1000/*61sec*/,0);
311 assertTrue("jademx agent didn't bind", boundPinger2);
312 boundPinger2 =
313 jadeAgentPinger2.waitForJademxAgentBinding(1,0);
314 assertTrue("jademx agent didn't bind", boundPinger2);
315 boundPinger2 =
316 jadeAgentPinger2.waitForJademxAgentBinding(0,0);
317 assertTrue("jademx agent didn't bind", boundPinger2);
318 boundPinger2 =
319 jadeAgentPinger2.waitForJademxAgentBinding(60*1000,1);//1min+1ns
320 assertTrue("jademx agent didn't bind", boundPinger2);
321 boundPinger2 =
322 jadeAgentPinger2.waitForJademxAgentBinding(1000,1);//1ms+1ns
323 assertTrue("jademx agent didn't bind", boundPinger2);
324 boundPinger2 =
325 jadeAgentPinger2.waitForJademxAgentBinding(0,1001);
326 assertTrue("jademx agent didn't bind", boundPinger2);
327 boundPinger2 =
328 jadeAgentPinger2.waitForJademxAgentBinding(0,1);
329 assertTrue("jademx agent didn't bind", boundPinger2);
330
331 // test bad nanosecond arguments
332 try {
333 jadeAgentPinger2.waitForJademxAgentBinding(0,-1);
334 fail("didn't raise IllegalArgumentException for bad nano -1");
335 }
336 catch ( IllegalArgumentException iae ) {
337 assertTrue(true);
338 }
339 try {
340 jadeAgentPinger2.waitForJademxAgentBinding(0,1000000);
341 fail("didn't raise IllegalArgumentException for bad nano 1000000");
342 }
343 catch ( IllegalArgumentException iae ) {
344 assertTrue(true);
345 }
346 // try nanosecond resolution expecting agent to be already bound
347 boundPinger2 =
348 jadeAgentPinger2.waitForJademxAgentBinding(0,1);
349 assertTrue("jademx agent didn't bind when already bound with 1ns wait",
350 boundPinger2);
351
352 // verify expected feature counts
353 MBeanInfo mbi = jadeAgentPinger2.getMBeanInfo();
354 MBeanAttributeInfo mbais[] = mbi.getAttributes();
355 int aCount = mbais.length;
356 mbi.getDescription();
357 MBeanOperationInfo mbois[] = mbi.getOperations();
358 int oCount = mbois.length;
359 MBeanNotificationInfo mbnis[] = mbi.getNotifications();
360 int nCount = mbnis.length;
361 int nTypeCount = 0;
362 for ( int i = 0; i < nCount; i++ ) {
363 MBeanNotificationInfo mbni = mbnis[i];
364 String notifTypes[] = mbni.getNotifTypes();
365 nTypeCount += notifTypes.length;
366 }
367 final int EXPECTED_ATTR_COUNT = 34;
368 final int EXPECTED_OPER_COUNT = 5;
369 final int EXPECTED_NOTIF_COUNT = 3;
370 // ease future debugging
371 if ( EXPECTED_ATTR_COUNT != aCount ) {
372 for ( int i = 0; i < aCount; i++ ) {
373 MBeanAttributeInfo mbai = mbais[i];
374 System.err.println("attribute "+i+": "+mbai.getName()+"("+
375 "type="+mbai.getType()+
376 ",readable="+mbai.isReadable()+
377 ",writable="+mbai.isWritable()+
378 ")");
379 }
380 }
381 if ( EXPECTED_OPER_COUNT != oCount ) {
382 for ( int i = 0; i < oCount; i++ ) {
383 MBeanOperationInfo mboi = mbois[i];
384 System.err.println("operation "+i+": "+mboi.getName()+
385 "(type="+mboi.getReturnType()+")");
386 }
387 }
388 if ( EXPECTED_NOTIF_COUNT != nTypeCount ) {
389 int nIndex = 0;
390 for ( int i = 0; i < nCount; i++ ) {
391 MBeanNotificationInfo mbni = mbnis[i];
392 String notifTypes[] = mbni.getNotifTypes();
393 int nTypesCount = notifTypes.length;
394 for ( int j = 0; j < nTypesCount; j++ ) {
395 System.err.println("notification "+(nIndex++)+": "+mbni.getName()+
396 ", type \""+notifTypes[j]+"\"");
397 }
398 }
399 }
400 assertEquals("wrong number of attributes", EXPECTED_ATTR_COUNT, aCount);
401 assertEquals("wrong number of operations", EXPECTED_OPER_COUNT, oCount);
402 assertEquals("wrong number of notifications", EXPECTED_NOTIF_COUNT,
403 nTypeCount);
404
405 // get all the attribute values
406 String aNames[] = new String[aCount];
407 for ( int i = 0; i < aCount; i++ ) {
408 aNames[i] = mbais[i].getName();
409 }
410 AttributeList aList = jadeAgentPinger2.getAttributes( aNames );
411
412 // verify features, including attribute values
413 verifyAttr( mbi, JadeAgentMBeanDef.ATTR_ARGUMENTS,
414 Object[].class.getName(), true, false, aList,
415 PINGER2_ARGS_AS_OBJ );
416 verifyAttr( mbi, JadeAgentMBeanDef.ATTR_CLASS_NAME,
417 String.class.getName(), true, false, aList,
418 PINGER2_CLASS_NAME );
419 verifyAttr( mbi, JadeAgentMBeanDef.ATTR_LOCAL_NAME,
420 String.class.getName(), true, false, aList,
421 AGENT_LOCAL_NAME_PINGER2 );
422 verifyAttr( mbi, JadeAgentMBeanDef.ATTR_PLATFORM_OBJECT_NAME_STRING,
423 String.class.getName(), true, false, aList,
424 PINGER2_EXPECTED_PLATFORM_OBJECT_NAME_STRING );
425 verifyAttr( mbi, JadeAgentMBeanDef.ATTR_FULL_NAME,
426 String.class.getName(), true, false, aList,
427 pinger2ExpectedFullName() );
428 verifyAttr( mbi, JadeAgentMBeanDef.ATTR_STATE_CODE,
429 int.class.getName(), true, false, aList, null );
430 verifyAttr( mbi, JadeAgentMBeanDef.ATTR_STATE_NAME,
431 String.class.getName(), true, false, aList, null );
432 verifyAttr( mbi, JadeAgentMBeanDef.ATTR_MBEAN_NAME,
433 String.class.getName(), true, false, aList,
434 PINGER2_EXPECTED_MBEAN_NAME_STRING );
435 ObjectName on = null;
436 try {
437 on = new ObjectName(PINGER2_EXPECTED_MBEAN_NAME_STRING);
438 }
439 catch ( Exception e ) {
440 throw new JademxException( e );
441 }
442 verifyAttr( mbi, JadeAgentMBeanDef.ATTR_OBJECT_NAME,
443 ObjectName.class.getName(), true, false, aList,
444 on );
445 verifyAttr( mbi, JadeAgentMBeanDef.ATTR_JADE_FACTORY,
446 JadeFactory.class.getName(), true, false, aList,
447 jadeRuntime.getJadeFactory() );
448 verifyAttr( mbi, JadeAgentMBeanDef.ATTR_TYPE,
449 String.class.getName(), true, false, aList,
450 JadeAgentMBeanDef.TYPE );
451 verifyAttr( mbi, JademxPingAgent.ATTR_RESPONSE_NAME,
452 String.class.getName(), true, true, aList,
453 JademxPingAgent.DEFAULT_ANSWER );
454
455 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_CONTENT_NAME,
456 boolean.class.getName(), true, true, aList,
457 Boolean.TRUE );
458 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_CONVERSATION_ID_NAME,
459 boolean.class.getName(), true, true, aList,
460 Boolean.TRUE );
461 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_ENCODING_NAME,
462 boolean.class.getName(), true, true, aList,
463 Boolean.TRUE );
464 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_ENVELOPE_NAME,
465 boolean.class.getName(), true, true, aList,
466 Boolean.FALSE );
467 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_IN_REPLY_TO_NAME,
468 boolean.class.getName(), true, true, aList,
469 Boolean.TRUE );
470 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_LANGUAGE_NAME,
471 boolean.class.getName(), true, true, aList,
472 Boolean.TRUE );
473 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_ONTOLOGY_NAME,
474 boolean.class.getName(), true, true, aList,
475 Boolean.TRUE );
476 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_PERFORMATIVE_NAME,
477 boolean.class.getName(), true, true, aList,
478 Boolean.TRUE );
479 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_PROTOCOL_NAME,
480 boolean.class.getName(), true, true, aList,
481 Boolean.TRUE );
482 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_RECEIVER_NAME,
483 boolean.class.getName(), true, true, aList,
484 Boolean.TRUE );
485 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_REPLY_BY_NAME,
486 boolean.class.getName(), true, true, aList,
487 Boolean.TRUE );
488 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_REPLY_TO_NAME,
489 boolean.class.getName(), true, true, aList,
490 Boolean.TRUE );
491 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_REPLY_WITH_NAME,
492 boolean.class.getName(), true, true, aList,
493 Boolean.TRUE );
494 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_SENDER_NAME,
495 boolean.class.getName(), true, true, aList,
496 Boolean.TRUE );
497 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_CMP_USER_PROPERTIES_NAME,
498 boolean.class.getName(), true, true, aList,
499 Boolean.TRUE );
500 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_IGNORE_CONTENT_AID_ADDRESSES_NAME,
501 boolean.class.getName(), true, true, aList,
502 Boolean.TRUE );
503 verifyAttr( mbi, JademxAgent.ATTR_UNIT_TEST_NEWLINES_NORMALIZED_NAME,
504 boolean.class.getName(), true, true, aList,
505 Boolean.TRUE );
506
507
508
509 verifyOper( mbi, JadeAgentMBeanDef.OPER_KILL_NAME,
510 void.class.getName() );
511 verifyOper( mbi, JademxPingAgent.OPER_PING_NAME,
512 JademxPingAgent.OPER_PING_TYPE );
513 verifyNotif( mbi, JademxPingAgent.NOTIF_PINGED_NAME );
514
515 // test getting non-existent attribute
516 aNames = new String[] {"NoSuchAttribute"};
517 try {
518 aList = jadeAgentPinger2.getAttributes( aNames );
519 fail("didn't generate expected RuntimeException getting "+
520 "non-existent attribute \""+aNames[0]+"\"");
521 }
522 catch ( RuntimeException re ) {
523 assertTrue(true);
524 }
525
526 // test setting non-existent attribute
527 aList = new AttributeList(1);
528 aList.add( new Attribute( "NoSuchAttribute", "fubar" ) );
529 try {
530 jadeAgentPinger2.setAttributes( aList );
531 fail("didn't generate expected RuntimeException setting "+
532 "non-existent attribute");
533 }
534 catch ( RuntimeException re ) {
535 assertTrue(true);
536 }
537 // verify setting response attribute
538
539 aList = new AttributeList(1);
540 String NEW_RESPONSE = "hello, world!";
541 aList.add( new Attribute(
542 JademxPingAgent.ATTR_RESPONSE_NAME, NEW_RESPONSE ) );
543 jadeAgentPinger2.setAttributes( aList );
544 String crntResponse = null;
545 try {
546 crntResponse = (String)jadeAgentPinger2.getAttribute(
547 JademxPingAgent.ATTR_RESPONSE_NAME );
548 }
549 catch ( Exception e ) {
550 throw new JademxException(e);
551 }
552 assertEquals("expected value of \""+JademxPingAgent.ATTR_RESPONSE_NAME+
553 "\" attribute to be \""+NEW_RESPONSE+"\" but it's \""+
554 crntResponse+"\"",
555 NEW_RESPONSE, crntResponse );
556
557 // get notification info.
558 // this is being set asynchrononously so it may or may not yet be
559 // set at this point.
560 //MBeanNotificationInfo nI[] =
561 jadeAgentPinger2.getNotificationInfo();
562
563 // verify ping operation and verify pinged notification
564
565 JadeAgent jadeAgentPinger1 =
566 platformMBean.getAgent( AGENT_LOCAL_NAME_PINGER1);
567 //boolean boundPinger1 =
568 jadeAgentPinger1.waitForJademxAgentBinding(59*1000/*59sec*/,0);
569 assertTrue("jademx agent "+AGENT_LOCAL_NAME_PINGER1+" didn't bind",
570 boundPinger2);
571 String jadeNamePinger1 = jadeAgentPinger1.getFullName();
572 String jadeNamePinger2 = jadeAgentPinger2.getFullName();
573
574 //TODO: try with a filter...
575 Object handback = new Object();
576 jadeAgentPinger2.addNotificationListener( this, null, handback );
577
578 String pingResponse = null;
579 try {
580 pingResponse = (String)jadeAgentPinger1.invoke(
581 JademxPingAgent.OPER_PING_NAME,
582 new Object[] { jadeNamePinger2 },
583 JademxPingAgent.OPER_PING_SIGNATURE );
584 }
585 catch ( Exception e ) {
586 String msg =
587 "exception using agent "+AGENT_LOCAL_NAME_PINGER1+
588 " to ping agent "+AGENT_LOCAL_NAME_PINGER2;
589 System.err.println( msg );
590 e.printStackTrace();
591 throw new JademxException( msg, e );
592 }
593 assertEquals(
594 "using agent "+AGENT_LOCAL_NAME_PINGER1+
595 " to ping agent "+AGENT_LOCAL_NAME_PINGER2+
596 " expected response \""+NEW_RESPONSE+
597 "\" but got \""+pingResponse+"\"",
598 NEW_RESPONSE, pingResponse );
599 Notification notification = null;
600 final long MAX_WAIT_MS = 59 * 1000;
601 long startTimeMs = System.currentTimeMillis();
602 long nowMs = startTimeMs;
603 //Thread myThread = Thread.currentThread();
604 while ( ( null == notification ) &&
605 ( nowMs < ( startTimeMs + MAX_WAIT_MS ) ) ) {
606 synchronized ( notificationQueue ) {
607 try {
608 if ( notificationQueue.size() == 0 ) {
609 notificationQueue.wait( MAX_WAIT_MS );
610 }
611 }
612 catch ( InterruptedException ie ) {
613 throw new JademxException(ie);
614 }
615 if ( notificationQueue.size() > 0 ) {
616 notification =
617 (Notification)notificationQueue.removeFirst();
618 }
619 }
620 nowMs = System.currentTimeMillis();
621 }
622 assertNotNull( "never got pinged notification", notification );
623 assertEquals( "expected notification type \""+
624 JademxPingAgent.NOTIF_PINGED_NAME+"\" but got \""+
625 notification.getType()+"\"",
626 JademxPingAgent.NOTIF_PINGED_NAME, notification.getType() );
627 String expMsgPrefix = "this agent was pinged by pinger1@";
628 assertTrue("expected notification message \""+notification.getMessage()+
629 "\" to start with \""+expMsgPrefix+"\"",
630 notification.getMessage().startsWith(expMsgPrefix));
631 long expMsgSeqNum = 0;
632 assertEquals( "expected notification sequence number "+expMsgSeqNum+
633 " but got "+notification.getSequenceNumber(),
634 expMsgSeqNum, notification.getSequenceNumber() );
635 assertEquals("expected notification user data \""+jadeNamePinger1+
636 "\" but got \""+notification.getUserData()+"\"",
637 jadeNamePinger1, notification.getUserData() );
638 assertEquals("expected notification source "+
639 jadeAgentPinger2.getObjectName()+
640 " but got "+notification.getSource() ,
641 jadeAgentPinger2.getObjectName(), notification.getSource() );
642
643 // remove notification listener using NotificationBroadcaster interface
644 try {
645 jadeAgentPinger2.removeNotificationListener( this );
646 }
647 catch ( Exception e ) {
648 throw new JademxException(
649 "exception removing self as notification listener "+
650 "using NotificationBroadcaster interface", e );
651 }
652 // test adding null notification listener
653 try {
654 jadeAgentPinger2.addNotificationListener( null, null, null);
655 fail("didn't raise IllegalArgumentException for null "+
656 "notification listener");
657 }
658 catch ( IllegalArgumentException iae ) {
659 assertTrue(true);
660 }
661 // remove notification listener using NotificationEmitter interface
662 jadeAgentPinger2.addNotificationListener( this, null, handback );
663 jadeAgentPinger2.addNotificationListener( this, null, handback );//NOP
664 Object handback2 = new Object();
665 jadeAgentPinger2.addNotificationListener( this, null, handback2 );
666 try {
667 jadeAgentPinger2.removeNotificationListener( this, null, handback );
668 }
669 catch ( Exception e ) {
670 throw new JademxException(
671 "exception removing 1st notification listener "+
672 "using NotificationEmitter interface", e );
673 }
674 try {
675 jadeAgentPinger2.removeNotificationListener( this, null, handback2 );
676 }
677 catch ( Exception e ) {
678 throw new JademxException(
679 "exception removing 2nd notification listener "+
680 "using NotificationEmitter interface", e );
681 }
682 // try removing non-existent listeners
683 try {
684 jadeAgentPinger2.removeNotificationListener( null );
685 fail("didn't raise ListenerNotFoundException removing null "+
686 "notification listener using NotificationBroadcaster interface");
687 }
688 catch ( ListenerNotFoundException e ) {
689 assertTrue(true);
690 }
691 try {
692 jadeAgentPinger2.removeNotificationListener( null, null, null );
693 fail("didn't raise ListenerNotFoundException removing null "+
694 "notification listener using NotificationBroadcaster interface");
695 }
696 catch ( ListenerNotFoundException e ) {
697 assertTrue(true);
698 }
699
700 // test operation where arguments/signature wrong
701 try {
702 jadeAgentPinger1.invoke(
703 JademxPingAgent.OPER_PING_NAME,
704 new Object[0],
705 new String[0] );
706 fail("didn't raise ReflectionException for bad args/signature");
707 }
708 catch ( ReflectionException re ) {
709 assertTrue(true);
710 }
711 catch ( Exception e ) {
712 throw new JademxException("unexpected exception raised for "+
713 "operation with bad args/signature", e );
714 }
715
716
717 // verify kill operation
718 try {
719 jadeAgentPinger2.invoke(
720 JadeAgentMBeanDef.OPER_KILL_NAME,
721 new Object[0],
722 JadeAgent.OPER_KILL_SIGNATURE );
723 }
724 catch ( Exception e ) {
725 String msg =
726 "exception killing agent "+AGENT_LOCAL_NAME_PINGER2;
727 System.err.println( msg );
728 e.printStackTrace();
729 throw new JademxException( msg, e );
730 }
731
732
733 }
734
735 /**
736 * verify that given attribute in given MBeanInfo
737 * @param mbi MBeanInfo to look in
738 * @param name attribute name
739 * @param type attribute type
740 * @param readable attribute readability
741 * @param writable attribute writability
742 * @param aList attribute list to get actual value from
743 * @param value expected value: if null then don't check
744 */
745 private void verifyAttr(
746 MBeanInfo mbi,
747 String name,
748 String type,
749 boolean readable,
750 boolean writable,
751 AttributeList aList,
752 Object value ) {
753 boolean found = false;
754 MBeanAttributeInfo mbais[] = mbi.getAttributes();
755 int aCount = mbais.length;
756 for ( int i = 0; i < aCount; i++ ) {
757 MBeanAttributeInfo mbai = mbais[i];
758 if ( mbai.getName().equals( name ) &&
759 mbai.getType().equals( type ) &&
760 ( mbai.isReadable() == readable ) &&
761 ( mbai.isWritable() == writable ) ) {
762 found = true;
763 break;
764 }
765 }
766 // help in future debugging
767 if ( !found ) {
768 System.err.println(aCount+" attributes");
769 for ( int i = 0; i < aCount; i++ ) {
770 MBeanAttributeInfo mbai = mbais[i];
771 System.err.println("attribute "+i+": "+mbai.getName()+"("+
772 "type="+mbai.getType()+
773 ",readable="+mbai.isReadable()+
774 ",writable="+mbai.isWritable()+
775 ")");
776 }
777 }
778 assertTrue("attribute name \""+name+"\", type \""+type+"\""+
779 ", readable="+readable+", writable="+writable+" not found",
780 found );
781 if ( null != value ) {
782 int aListLen = aList.size();
783 for ( int i = 0; i < aListLen; i++ ) {
784 Attribute a = (Attribute)aList.get( i );
785 if ( name.equals( a.getName() ) ) {
786 Object aVal = a.getValue();
787 assertTrue("expected and actual attribute values must "+
788 "both be either array or not array: value="+
789 value.toString()+",aVal="+aVal.toString(),
790 value.getClass().isArray()==aVal.getClass().isArray() );
791 boolean isArray = value.getClass().isArray();
792 assertTrue("for attribute "+name+" expected value "+value+
793 " but got "+aVal,
794 ( isArray
795 ? Arrays.deepEquals( (Object[])value, (Object[])aVal )
796 : ( value.equals(aVal))
797 ));
798 }
799 }
800 }
801 }
802
803 /**
804 * verify given operation in given MBeanInfo
805 * @param mbi MBeanInfo to look in
806 * @param name operation name
807 * @param type operation type
808 */
809 private void verifyOper( MBeanInfo mbi,
810 String name,
811 String type ) {
812 boolean found = false;
813 MBeanOperationInfo mbois[] = mbi.getOperations();
814 int oCount = mbois.length;
815 //System.err.println(oCount+" operations");
816 for ( int i = 0; i < oCount; i++ ) {
817 MBeanOperationInfo mboi = mbois[i];
818 if ( mboi.getName().equals( name ) &&
819 mboi.getReturnType().equals( type ) ) {
820 found = true;
821 break;
822 }
823 }
824 // help in future debugging
825 if ( !found ) {
826 System.err.println(oCount+" operations ");
827 for ( int i = 0; i < oCount; i++ ) {
828 MBeanOperationInfo mboi = mbois[i];
829 System.err.println("operation "+i+": "+mboi.getName()+
830 "(type="+mboi.getReturnType()+")");
831 }
832 }
833 assertTrue("operation name \""+name+"\", type \""+type+"\" not found",
834 found );
835 }
836
837 /**
838 * verify given notification in given MBeanInfo
839 * @param mbi MBeanInfo to look in
840 * @param type notification type
841 */
842 private void verifyNotif( MBeanInfo mbi, String type ) {
843 boolean found = false;
844 MBeanNotificationInfo mbnis[] = mbi.getNotifications();
845 int nCount = mbnis.length;
846 for ( int i = 0; i < nCount; i++ ) {
847 MBeanNotificationInfo mbni = mbnis[i];
848 String notifTypes[] = mbni.getNotifTypes();
849 int nTypeCount = notifTypes.length;
850 for ( int j = 0; j < nTypeCount; j++ ) {
851 if ( notifTypes[j].equals( type ) ) {
852 found = true;
853 break;
854 }
855 //System.err.println("JadeAgentTest.verifyNotif():notification "+i+": "+mbni.getName()+
856 // ", type \""+notifTypes[j]+"\"");
857 }
858 }
859 // help in future debugging
860 if ( !found ) {
861 for ( int i = 0; i < nCount; i++ ) {
862 MBeanNotificationInfo mbni = mbnis[i];
863 String notifTypes[] = mbni.getNotifTypes();
864 int nTypeCount = notifTypes.length;
865 for ( int j = 0; j < nTypeCount; j++ ) {
866 System.err.println("JadeAgentTest.verifyNotif():notification "+i+": "+mbni.getName()+
867 ", type \""+notifTypes[j]+"\"");
868 }
869 }
870 }
871 assertTrue("notification type \""+type+"\" not found", found );
872 }
873
874
875 // suite
876
877 /**
878 * return the implicit suite of tests
879 * @return the implicit suite of tests
880 */
881 public static Test suite() {
882 return new TestSuite(
883 JadeAgentTest.class,
884 JadeMXSuiteTest.nameWithClass( JadeAgentTest.class,
885 "testing JadeAgent: jade agent MBean class") );
886 }
887
888
889
890 }