001    // jademx - JADE management using JMX
002    // Copyright 2005 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.MissingResourceException;
021    import java.util.ResourceBundle;
022    
023    import jade.core.Runtime;
024    import jade.jademx.JadeMXSuiteTest;
025    import jade.jademx.server.JadeMXServer;
026    import jade.jademx.server.JadeMXServerFactory;
027    import jade.jademx.util.ThrowableUtil;
028    
029    import javax.management.MBeanServer;
030    import javax.management.ObjectName;
031    
032    import junit.framework.Test;
033    import junit.framework.TestCase;
034    import junit.framework.TestSuite;
035    
036    /** 
037     * JadeRuntime MBean test
038     * @author David Bernstein, <a href="http://www.caboodlenetworks.com"
039     *  >Caboodle Networks, Inc.</a>
040     */
041    public class JadeRuntimeTest extends TestCase {
042        
043        /** test(suite) name */
044        private static String name = 
045            JadeMXSuiteTest.nameWithClass( 
046                    JadeRuntimeTest.class, 
047                            "testing JadeRuntime: JADE runtime MBean class");
048        
049        
050        /**
051         * make TestCase for JadeRuntime
052         */
053        public JadeRuntimeTest() {
054            super();
055            setName( name );
056        }
057        
058        /** JadeRuntime created by setUp() */
059        private JadeRuntimeMBean jadeRuntime = null;
060        
061        /** jadeMXServer we're using */
062        private JadeMXServer jadeMXServer = null;
063        
064        /* (non-Javadoc)
065         * @see junit.framework.TestCase#setUp()
066         */
067        protected void setUp() throws Exception {
068            //System.err.println(">>>starting test "+getName()+"...");
069            // first get JadeMXServer
070            try {
071                jadeMXServer = JadeMXServerFactory.jadeMXServerBySysProp();
072            }
073            catch ( Exception e ) {
074                fail( ThrowableUtil.errMsg( 
075                        "problem creating JadeMXServer by system property", e) );
076            }
077            // make a JadeFactory to create jademx MBeans
078            JadeFactory jadeFactory = new JadeFactory( jadeMXServer );
079            // create the JadeRuntime MBean to root all the jademx MBeans
080            try {
081                jadeRuntime = jadeFactory.runtimeInstance();
082            }
083            catch ( Exception e ) {
084                fail( ThrowableUtil.errMsg( 
085                        "problem getting runtime instance from jade factory", e) );
086            }
087        }
088        
089        
090    
091        /* (non-Javadoc)
092         * @see junit.framework.TestCase#tearDown()
093         */
094        protected void tearDown() throws Exception {
095            if ( null != jadeRuntime ) {
096                jadeRuntime.shutdown();
097            }
098            //JadeMXSuiteTest.listMBeans( jadeMXServer, 
099            //    "exiting JadeRuntimeTest.tearDown() for test "+getName()+"...");
100        }
101        // tests
102        
103        /**
104         * test runtime copyright notice
105         */
106        public void testGetCopyrightNotice() {
107            String copyrightNotice = jadeRuntime.getCopyrightNotice();
108            assertEquals( "JadeRuntimeMBean.getCopyrightNotice() returned "+
109                    copyrightNotice+
110                    " instead of "+Runtime.getCopyrightNotice(), 
111                    Runtime.getCopyrightNotice(), copyrightNotice );
112        }
113        
114        
115        /**
116         * test runtime version information
117         */
118        public void testGetVersionInfo() {
119            String versionInfo = jadeRuntime.getVersionInfo();
120            assertEquals( "JadeRuntimeMBean.getVersionInfo() returned "+
121                    versionInfo+
122                    " instead of "+Runtime.instance().getVersionInfo(), 
123                    Runtime.instance().getVersionInfo(), versionInfo );
124        }
125        
126        
127        /**
128         * test runtime version
129         */
130        public void testGetVersion() {
131            String actualVersion = jadeRuntime.getVersion();
132            String versionInfo = Runtime.instance().getVersionInfo();
133            int dashIndex = versionInfo.indexOf('-');
134            String expectedVersion = versionInfo.substring( 0, dashIndex-1 );
135            expectedVersion = expectedVersion.trim();
136            expectedVersion = expectedVersion.replaceAll("JADE","");
137            assertEquals( "JadeRuntimeMBean.getVersion() returned "+
138                    actualVersion+
139                    " instead of "+expectedVersion, 
140                    expectedVersion, actualVersion );
141        }
142        
143        
144        /**
145         * test runtime version timestamp
146         */
147        public void testGetVersionTimestamp() {
148            String actualVersionTimestamp = jadeRuntime.getVersionTimestamp();
149            String versionInfo = Runtime.instance().getVersionInfo();
150            int dashIndex = versionInfo.indexOf('-');
151            String expectedVersionTimestamp = 
152                    cvsDateToTimestamp( versionInfo.substring( dashIndex+1 ) );
153            assertEquals( "JadeRuntimeMBean.getVersionTimestamp() returned "+
154                    actualVersionTimestamp+
155                    " instead of "+expectedVersionTimestamp, 
156                    expectedVersionTimestamp, actualVersionTimestamp );
157        }
158        
159        /** jademx resource bundle name */
160        private static final String JADEMX_BUNDLE_NAME = 
161            "jade.jademx.config.jademx";
162        /** name of jademx major version property */
163        private static final String JADEMX_MAJOR_VERSION_PROP =
164            "jademx.major.version";
165        /** name of jademx minor version property */
166        private static final String JADEMX_MINOR_VERSION_PROP =
167            "jademx.minor.version";
168        /** name of jademx patch version property */
169        private static final String JADEMX_PATCH_VERSION_PROP =
170            "jademx.patch.version";
171        /** name of jademx cvs date property */
172        private static final String JADEMX_CVS_DATE_PROP =
173            "jademx.cvs.date";
174        
175        /**
176         * test jademx version
177         */
178        public void testGetJademxVersion() {
179            String actualVersion = jadeRuntime.getJademxVersion();
180            String expectedVersion = null;
181            ResourceBundle b = ResourceBundle.getBundle(JADEMX_BUNDLE_NAME);
182            try {
183                String major = b.getString( JADEMX_MAJOR_VERSION_PROP );
184                String minor = b.getString( JADEMX_MINOR_VERSION_PROP );
185                String patch = b.getString( JADEMX_PATCH_VERSION_PROP );
186                expectedVersion = major + "." + minor + "." + patch;
187            }
188            catch ( MissingResourceException mre ) {
189                expectedVersion = "!!!";
190            }
191    
192            assertEquals( "JadeRuntimeMBean.getJademxVersion() returned "+
193                    actualVersion+
194                    " instead of "+expectedVersion, 
195                    expectedVersion, actualVersion );
196        }
197        
198        /**
199         *  test jademx timestamp
200         */
201        public void testGetJademxTimestamp() {
202            String actualTS = jadeRuntime.getJademxTimestamp();
203            ResourceBundle b = ResourceBundle.getBundle(JADEMX_BUNDLE_NAME);
204            String cvsDate = null;
205            try {
206                cvsDate = b.getString( JADEMX_CVS_DATE_PROP );
207            }
208            catch ( MissingResourceException mre ) {
209                cvsDate = "?";
210            }
211            int colonPos = cvsDate.indexOf(':');
212            int dollarPos = cvsDate.lastIndexOf('$');
213            String date = cvsDate.substring(colonPos + 1, dollarPos);
214            String expectedTS = cvsDateToTimestamp( date );
215            assertEquals( expectedTS, actualTS );
216        }
217    
218        /**
219         * convert cvs-style date/time string to iso 8601 timestamp
220         * @param cvsDate date to convert
221         * @return equivalent iso8601 timestamp
222         */
223        private String cvsDateToTimestamp( String cvsDate ) {
224            String timestamp = cvsDate.trim();
225            timestamp = timestamp.replace('/','-');
226            timestamp = timestamp.replace(' ','T');
227            return timestamp;
228        }
229    
230        /** resource name for configuration of one empty configuration */
231        private static final String EMPTY_CONFIG_RESOURCE =
232            "jade/jademx/config/empty-config.xml";
233        /** resource name for configuration of one empty platform */
234        private static final String EMPTY_PLATFORM_CONFIG_RESOURCE =
235            "jade/jademx/config/one-empty-platform.xml";
236        /** resource name for configuration of one empty platform */
237        private static final String EMPTY_PLATFORM_NOMTP_CONFIG_RESOURCE =
238            "jade/jademx/config/one-empty-platform-nomtp.xml";
239        /** resource name for configuration of two ping agents */
240        private static final String TWO_PING_CONFIG_RESOURCE =
241            "jade/jademx/config/two-ping-agents.xml";
242        /** resource name for configuration that doesn't exist */
243        private static final String NONEXISTENT_CONFIG_RESOURCE =
244            "jade/jademx/config/nonexistent.xml";
245        /** resource name for configuration with bad XML */
246        private static final String BAD_CONFIG_RESOURCE =
247            "jade/jademx/config/bad-jademx-configuration.xml";
248        /** resource name for configuration with bad XML: multiple jademx-config elements */
249        private static final String BAD_CONFIG_RESOURCE_MULTICFG =
250            "jade/jademx/config/bad-cfg-multicfg.xml";    
251        /** resource name for configuration with bad XML: zero jademx-config elements */
252        private static final String BAD_CONFIG_RESOURCE_NOCFG =
253            "jade/jademx/config/bad-cfg-nocfg.xml";    
254        /** resource name for configuration with bad XML: multiple runtime elements */
255        private static final String BAD_CONFIG_RESOURCE_MULTIRUNTIME =
256            "jade/jademx/config/bad-cfg-multiruntime.xml";    
257        
258        /**
259         * run test of instantiating one empty platform
260         * @param isUrl true iff configuration specified by URL, else resource
261         * @param returnMBean true iff want MBean back, else MBean's name
262         */
263        private void runTestOneEmptyPlatform( boolean isUrl, boolean returnMBean ) {
264            JadePlatform platformMBeans[] = null;
265            String       platformNames[] = null;
266            String       urlString = null;
267            String       NO_SUCH_PLATFORM_NAME = "no-such-platform";
268            if ( isUrl ) {
269                ClassLoader myClassLoader = this.getClass().getClassLoader();
270                urlString = myClassLoader.getResource( 
271                        EMPTY_PLATFORM_CONFIG_RESOURCE ).toString();
272            }
273            int platformCount = 0;
274            try {
275                if ( returnMBean ) {
276                    platformMBeans = 
277                        ( isUrl
278                                ? jadeRuntime.platformsFromConfigUrl( 
279                                        urlString )
280                                : jadeRuntime.platformsFromConfigResource( 
281                                        EMPTY_PLATFORM_CONFIG_RESOURCE ) );
282                    // should be exactly one platform returned
283                    assertNotNull( 
284                            "JadeRuntime.platformsFromConfigResources()"+
285                            " returned null", 
286                            platformMBeans );
287                    platformCount = platformMBeans.length;
288                    
289                    JadePlatform platforms[] = jadeRuntime.getPlatforms();
290                    assertEquals( "expected exactly one platform to be returned by getPlatforms()",
291                            1, platforms.length);
292                    assertEquals( platformMBeans[0], platforms[0]);
293                }
294                else {
295                    platformNames =
296                        ( isUrl
297                                ? jadeRuntime.platformNamesFromConfigUrl( 
298                                        urlString )
299                                : jadeRuntime.platformNamesFromConfigResource( 
300                                        EMPTY_PLATFORM_CONFIG_RESOURCE ) );
301                    // should be exactly one platform returned
302                    assertNotNull( 
303                            "JadeRuntime.platformNamesFromConfigResources()"+
304                            " returned null", 
305                            platformNames );
306                    platformCount = platformNames.length;
307                    
308                    ObjectName platformObjectNames[] = jadeRuntime.getPlatformObjectNames();
309                    assertEquals( "expected exactly one platform to be returned by getPlatformObjectNames()",
310                            1, platformObjectNames.length);
311                    String pName = platformObjectNames[0].toString();
312                    assertEquals( platformNames[0], pName );
313                    
314                    String pNames[] = jadeRuntime.getPlatformNames();
315                    assertEquals( "expected exactly one platform to be returned by getPlatformNames()",
316                            1, pNames.length);
317                    assertEquals( platformNames[0], pNames[0] );
318                }
319            }
320            catch ( Exception e ) {
321                fail( ThrowableUtil.errMsg( 
322                        "Exception creating empty platform ", e) );
323            }  
324            assertEquals( "expected exactly one platform to be returned",
325                    1, platformCount);
326    
327    
328            MBeanServer mBeanServer = jadeMXServer.getMBeanServer();
329            ObjectName platformObjName = null;
330            int agentCount = -1;
331            if ( returnMBean ) {
332                agentCount = platformMBeans[0].getAgents().length;
333                String jadePlatformName = platformMBeans[0].getPlatformName();
334                try {
335                    JadePlatform jp = 
336                        jadeRuntime.platformFromJadeName( jadePlatformName );
337                    assertEquals(
338                            "didn't get expected JadePlatform for JADE platform \""+
339                            jadePlatformName+"\"", platformMBeans[0], jp );
340                    jp = jadeRuntime.platformFromJadeName( NO_SUCH_PLATFORM_NAME );
341                    assertNull( "expected to get null looking for JadePlatform "+
342                            "for JADE platform \""+NO_SUCH_PLATFORM_NAME+"\"", jp );
343    
344                } 
345                catch ( Exception e ) {
346                    fail( ThrowableUtil.errMsg( 
347                            "Exception getting MBean for JADE platform "+
348                            jadePlatformName, e) );
349                }
350            }
351            else {
352                try {
353                    platformObjName = new ObjectName( platformNames[0] );
354                }
355                catch ( Exception e ) {
356                    fail( ThrowableUtil.errMsg( 
357                            "Exception constructing ObjectName for platform "+
358                            platformNames[0], e) );
359                }
360                try {
361                    String agentNames[] = (String[])mBeanServer.getAttribute( 
362                            platformObjName, JadePlatformMBean.ATTR_AGENT_NAMES );
363                    agentCount = agentNames.length;
364                }
365                catch ( Exception e ) {
366                    fail( ThrowableUtil.errMsg( 
367                            "Exception using MBeanServer to get attribute "+
368                            JadePlatformMBean.ATTR_AGENT_NAMES, e) );
369                }
370                String jadePlatformName = null;
371                try {
372                    jadePlatformName = (String)mBeanServer.getAttribute( 
373                            platformObjName, JadePlatformMBean.ATTR_PLATFORM_NAME );
374                }
375                catch ( Exception e ) {
376                    fail( ThrowableUtil.errMsg( 
377                            "Exception using MBeanServer to get attribute "+
378                            JadePlatformMBean.ATTR_PLATFORM_NAME, e) );
379                }
380                try {
381                    String platformName = 
382                        (String)mBeanServer.invoke( 
383                                jadeRuntime.getObjectName(), 
384                                JadeRuntimeMBean.OPER_PLATFORM_NAME_FROM_JADE_NAME, 
385                                new Object[] { jadePlatformName }, 
386                                JadeRuntime.SIGN_STR );
387                    assertEquals("expected to get \""+platformNames[0]+
388                           "\" looking for jademx platform name of JADE platform \""
389                           +jadePlatformName+"\"", platformNames[0], platformName);
390                    platformName = 
391                        (String)mBeanServer.invoke( 
392                                jadeRuntime.getObjectName(), 
393                                JadeRuntimeMBean.OPER_PLATFORM_NAME_FROM_JADE_NAME, 
394                                new Object[] { NO_SUCH_PLATFORM_NAME }, 
395                                JadeRuntime.SIGN_STR );
396                    assertNull( "expected to get null looking for JadePlatform "+
397                            "for JADE platform \""+NO_SUCH_PLATFORM_NAME+"\"", 
398                            platformName);
399                }
400                catch ( Exception e ) {
401                    fail( ThrowableUtil.errMsg( 
402                            "Exception using MBeanServer to invoke operation \""+
403                            JadeRuntimeMBean.OPER_PLATFORM_NAME_FROM_JADE_NAME +
404                            "\" on JadeRuntime \""+jadeRuntime+
405                            "\" with argument \""+
406                            jadePlatformName + "\"",
407                            e ) );
408                }
409            }
410            assertEquals( "expected zero agents to be returned",
411                    0,agentCount);
412            
413            // shut down the platform
414            try {
415                if ( returnMBean ) {
416                    platformMBeans[0].kill();
417                }
418                else {
419                    mBeanServer.invoke( platformObjName, JadePlatform.OPER_KILL,
420                            new Object[0], new String[0 ] );
421                }
422            }
423            catch ( Exception e ) {
424                fail( ThrowableUtil.errMsg( 
425                        "Exception shutting down platform", e ) );
426            }
427            
428        }
429        
430        /**
431         * test creating a single empty platform from config spec'd by resource.
432         */
433        public void testOneEmptyPlatformResource() {
434            runTestOneEmptyPlatform( false, true );
435        }
436        
437        /**
438         * test getting platform name from config specified by java resource
439         */
440        public void testOneEmptyPlatformResourceName() {
441            runTestOneEmptyPlatform( false, false );
442        }
443        
444        /**
445         * test creating a single empty platform from config spec'd by URL
446         */
447        public void testOneEmptyPlatformURL() {
448            runTestOneEmptyPlatform( true, true );
449        }
450        
451        /**
452         * test getting platform name from config specified by java URL
453         */
454        public void testOneEmptyPlatformURLName() {
455            runTestOneEmptyPlatform( true, false );
456        }
457        
458        /**
459         * test trying to use a configuration that doesn't exist
460         */
461        public void testNonExistentConfig() {
462            try {
463                //JadePlatform platformMBeans[] = 
464                    jadeRuntime.platformsFromConfigResource( 
465                        NONEXISTENT_CONFIG_RESOURCE );
466                fail("didn't raise exception trying to use non-existent config");
467            }
468            catch ( JademxException e ) {
469                assertTrue(true);
470            }
471        }
472        
473        
474        /**
475         * test trying to use a badly formatted url for configuration 
476         */
477        public void testBadConfigURL() {
478            try {
479                //JadePlatform platformMBeans[] = 
480                    jadeRuntime.platformsFromConfigUrl( 
481                        "ptth\\:" );
482                fail("didn't raise exception trying to use bad URL for config");
483            }
484            catch ( JademxException e ) {
485                assertTrue(true);
486            }
487        }
488        
489        
490        /**
491         * test trying to use a configuration with bad XML
492         */
493        public void testBadConfig() {
494            try {
495                //JadePlatform platformMBeans[] = 
496                    jadeRuntime.platformsFromConfigResource( 
497                        BAD_CONFIG_RESOURCE );
498                fail("didn't raise exception trying to use bad config");
499            }
500            catch ( JademxException e ) {
501                assertTrue(true);
502            }
503        }
504    
505        /**
506         * test trying to use a configuration with bad XML: multiple configurations
507         */
508        public void testBadConfigMultiCfg() {
509            try {
510                //JadePlatform platformMBeans[] = 
511                    jadeRuntime.platformsFromConfigResource( 
512                        BAD_CONFIG_RESOURCE_MULTICFG );
513                fail("didn't raise exception trying to use bad config with multiple jademx-config elements");
514            }
515            catch ( JademxException e ) {
516                assertTrue(true);
517            }
518        }
519        
520        
521        /**
522         * test trying to use a configuration with bad XML: zero configurations
523         */
524        public void testBadConfigNoCfg() {
525            try {
526                //JadePlatform platformMBeans[] = 
527                    jadeRuntime.platformsFromConfigResource( 
528                        BAD_CONFIG_RESOURCE_NOCFG);
529                fail("didn't raise exception trying to use bad config with zero jademx-config elements");
530            }
531            catch ( JademxException e ) {
532                assertTrue(true);
533            }
534        }
535        
536        
537        /**
538         * test trying to use a configuration with bad XML: multiple runtimes
539         */
540        public void testBadConfigMultiRuntime() {
541            try {
542                //JadePlatform platformMBeans[] = 
543                    jadeRuntime.platformsFromConfigResource( 
544                        BAD_CONFIG_RESOURCE_MULTIRUNTIME );
545                fail("didn't raise exception trying to use bad config with multiple runtime elements");
546            }
547            catch ( JademxException e ) {
548                assertTrue(true);
549            }
550        }
551        
552        
553        
554        /**
555         * verify the platform with two agents
556         * @param platformMBeans
557         */
558        private void verifyTwoAgentPlatform( JadePlatform platformMBeans[] ) {
559            int platformCount = platformMBeans.length;
560            assertEquals( "expected exactly one platform to be returned",
561                    1, platformCount);
562            JadeAgent agentMBeans[] = platformMBeans[0].getAgents();
563            int agentCount = agentMBeans.length;
564            assertEquals( "expected two agents to be returned",
565                    2, agentCount );
566            // shut down the platform
567            try {
568                jadeRuntime.shutdown();
569            }
570            catch ( Exception e ) {
571                fail( ThrowableUtil.errMsg( 
572                        "Exception shutting down platform", e ) );
573            }
574            finally {
575                // stop tearDown() from trying the same thing
576                jadeRuntime = null;
577            }
578        }
579        
580        /**
581         * test intantiating a platform with two agents via XML
582         */
583        public void testTwoAgentPlatformXML() {
584            JadePlatform platformMBeans[] = null;
585            try {
586                platformMBeans = jadeRuntime.platformsFromConfigResource( 
587                        TWO_PING_CONFIG_RESOURCE );
588                // should be exactly one platform returned
589                assertNotNull( 
590                        "JadeRuntime.platformsFromConfigResources()"+
591                        " returned null", 
592                        platformMBeans );
593            }
594            catch ( JademxException e ) {
595                fail( ThrowableUtil.errMsg( 
596                        "Exception creating two agent platform", e) );
597            }
598            verifyTwoAgentPlatform( platformMBeans );
599        }
600    
601        /**
602         * try testing empty configuration
603         */
604        public void testEmptyConfig() {
605            try {
606                jadeRuntime.platformsFromConfigResource( 
607                        EMPTY_CONFIG_RESOURCE );
608                fail("didn't raise exception trying to use bad config with zero platforms");
609            }
610            catch ( JademxException e ) {
611                assertTrue(true);
612            }
613        }
614        
615        /**
616         * try testing empty platform with NOMTP specified
617         */
618        public void testEmptyPlatformNoMTP() {
619            JadePlatform platformMBeans[] = null;
620            int platformCount = 0;
621            try {
622                platformMBeans = jadeRuntime.platformsFromConfigResource( 
623                        EMPTY_PLATFORM_NOMTP_CONFIG_RESOURCE );
624                // should be exactly one platform returned
625                assertNotNull( 
626                        "JadeRuntime.platformsFromConfigResources()"+
627                        " returned null", 
628                        platformMBeans );
629                platformCount = platformMBeans.length;
630            }
631            catch ( JademxException e ) {
632                fail( ThrowableUtil.errMsg( 
633                        "Exception creating two agent platform", e) );
634            }
635            assertEquals( "expected exactly one platform to be returned",
636                    1, platformCount);
637            JadeAgent agentMBeans[] = platformMBeans[0].getAgents();
638            int agentCount = agentMBeans.length;
639            assertEquals( "expected zero agents to be returned",
640                    0, agentCount );
641        }
642        
643        // suite
644    
645        /**
646         * return the implicit suite of tests
647         * @return the implicit suite of tests
648         */
649        public static Test suite() {
650            return new TestSuite( JadeRuntimeTest.class, name);
651        }
652    
653    
654        
655    }