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 }