/*
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package test.compliance.metadata;


import junit.framework.TestCase;
import junit.framework.AssertionFailedError;

import java.lang.reflect.Method;

import javax.management.MBeanAttributeInfo;
import javax.management.IntrospectionException;

import test.compliance.metadata.support.Trivial;

/**
 * Tests MBeanAttributeInfo.
 *
 * @author  <a href="mailto:juha@jboss.org">Juha Lindfors</a>.
 * @version $Revision: 1.4 $ 
 */
public class MBeanAttributeInfoTEST extends TestCase
{
   public MBeanAttributeInfoTEST(String s)
   {
      super(s);
   }

   /**
    * Tests <tt>MBeanAttributeInfo(String name, String descr, Method getter, Method setter)</tt> constructor.
    */
   public void testConstructorWithAccessorMethods()
   {
      try 
      {
         Class c = Trivial.class;
         Method getter = c.getMethod("getSomething", new Class[0]);
         Method setter = c.getMethod("setSomething", new Class[] { String.class });
         
         MBeanAttributeInfo info = new MBeanAttributeInfo("Something", "a description", getter, setter);
         
         assertTrue(info.getDescription().equals("a description"));
         assertTrue(info.getName().equals("Something"));
         assertTrue(info.getType().equals("java.lang.String"));
         assertTrue(info.isReadable() == true);
         assertTrue(info.isWritable() == true);
         assertTrue(info.isIs() == false);         
      }
      catch (AssertionFailedError e)
      {
         throw e;
      }
      catch (Throwable t)
      {
         t.printStackTrace();
         fail("Unexpected error: " + t.toString());
      }
   }
 
   /**
    * Tests <tt>MBeanAttributeInfo(String name, String descr, Method getter, Method setter)</tt> with misplaced accessor methods.
    */
   public void testConstructorWithMisplacedAccessorMethods()
   {
      try
      {
         Class c = Trivial.class;
         Method getter = c.getMethod("getSomething", new Class[0]);
         Method setter = c.getMethod("setSomething", new Class[] { String.class });
         
         MBeanAttributeInfo info = new MBeanAttributeInfo("Something", "a description", setter, getter);
         
         // shouldn't reach here
         fail("Introspection exception should have been thrown.");
      }
      catch (IntrospectionException e)
      {
         // this is expected
      }
      catch (AssertionFailedError e)
      {
         throw e;
      }
      catch (Throwable t)
      {
         t.printStackTrace();
         fail("Unexpected error: " + t.toString());
      }
   }
   
   /**
    * Tests <tt>MBeanAttributeInfo(String name, String descr, Method getter, Method setter)</tt> with invalid getter method.
    */
   public void testConstructorWithInvalidGetterMethod()
   {
      try
      {
         Class c = Trivial.class;
         Method getter = c.getMethod("getSomethingInvalid", new Class[] { Object.class });
         Method setter = c.getMethod("setSomethingInvalid", new Class[] { String.class });
         
         MBeanAttributeInfo info = new MBeanAttributeInfo("Something", "a description", getter, setter);
         
         // shouldn't reach here
         fail("Introspection exception should have been thrown.");
      }
      catch (IntrospectionException e)
      {
         // this is expected
      }
      catch (AssertionFailedError e)
      {
         throw e;
      }
      catch (Throwable t)
      {
         t.printStackTrace();
         fail("Unexpected error: " + t.toString());
      }
   }
   
   /**
    * Tests <tt>MBeanAttributeInfo(String name, String descr, Method getter, Method setter)</tt> with invalid getter method (void return type).
    */
   public void testConstructorWithInvalidGetterMethod2()
   {
      try
      {
         Class c = Trivial.class;
         Method getter = c.getMethod("getSomethingInvalid2", new Class[] { } );
         Method setter = c.getMethod("setSomethingInvalid2", new Class[] { String.class });
         
         MBeanAttributeInfo info = new MBeanAttributeInfo("Something", "a description", getter, setter);
         
         // shouldn't reach here
         fail("Introspection exception should have been thrown.");
      }
      catch (IntrospectionException e)
      {
         // this is expected
      }
      catch (AssertionFailedError e)
      {
         throw e;
      }
      catch (Throwable t)
      {
         t.printStackTrace();
         fail("Unexpected error: " + t.toString());
      }
   }

   public void testConstructorWithNonBooleanIsIs()
      throws Exception
   {
      try
      {
         new MBeanAttributeInfo("name", "type", "description", true, true, true);
      }
      catch (Exception e)
      {
         return;
      }
      fail("isIs is only allowed for boolean types");
   }

   public void testConstructorWithPrimitiveBooleanIsIs()
      throws Exception
   {
      new MBeanAttributeInfo("name", Boolean.TYPE.getName(), "description", true, true, true);
   }

   public void testConstructorWithObjectBooleanIsIs()
      throws Exception
   {
      new MBeanAttributeInfo("name", Boolean.class.getName(), "description", true, true, true);
   }

   public void testInvalidJavaName()
   {
      try
      {
         new MBeanAttributeInfo("invalid name", "type", "description", true, true, false);
      }
      catch (Exception e)
      {
         return;
      }
      fail("shouldn't allow an invalid java name");
   }

   public void testInvalidJavaType()
   {
      try
      {
         new MBeanAttributeInfo("name", "invalid type", "description", true, true, false);
      }
      catch (Exception e)
      {
         return;
      }
      fail("shouldn't allow an invalid java type");
   }

   public void testHashCode()
      throws Exception
   {
      MBeanAttributeInfo info1 = new MBeanAttributeInfo("name", "type", "description", true, true, false);
      MBeanAttributeInfo info2 = new MBeanAttributeInfo("name", "type", "description", true, true, false);

      assertTrue("Different instances with the same hashcode are equal", info1.hashCode() == info2.hashCode());
   }

   public void testEquals()
      throws Exception
   {
      MBeanAttributeInfo info = new MBeanAttributeInfo("name", "type", "description", true, true, false);

      assertTrue("Null should not be equal", info.equals(null) == false);
      assertTrue("Only MBeanAttributeInfo should be equal", info.equals(new Object()) == false);

      MBeanAttributeInfo info2 = new MBeanAttributeInfo("name", "type", "description", true, true, false);

      assertTrue("Different instances of the same data are equal", info.equals(info2));
      assertTrue("Different instances of the same data are equal", info2.equals(info));

      info2 = new MBeanAttributeInfo("name2", "type", "description", true, true, false);

      assertTrue("Different instances with different names are not equal", info.equals(info2) == false);
      assertTrue("Different instances with different names are not equal", info2.equals(info) == false);

      info2 = new MBeanAttributeInfo("name", "type2", "description", true, true, false);

      assertTrue("Different instances with different types are not equal", info.equals(info2) == false);
      assertTrue("Different instances with different types are not equal", info2.equals(info) == false);

      info2 = new MBeanAttributeInfo("name", "type", "description2", true, true, false);

      assertTrue("Different instances with different descriptions are not equal", info.equals(info2) == false);
      assertTrue("Different instances with different descritpions are not equal", info2.equals(info) == false);

      info2 = new MBeanAttributeInfo("name", "type", "description", false, true, false);

      assertTrue("Different instances with different readables are not equal", info.equals(info2) == false);
      assertTrue("Different instances with different readables are not equal", info2.equals(info) == false);

      info2 = new MBeanAttributeInfo("name", "type", "description", true, false, false);

      assertTrue("Different instances with different writables are not equal", info.equals(info2) == false);
      assertTrue("Different instances with different writables are not equal", info2.equals(info) == false);

      info2 = new MBeanAttributeInfo("name", Boolean.TYPE.getName(), "description", true, true, true);

      assertTrue("Different instances with different isIs are not equal", info.equals(info2) == false);
      assertTrue("Different instances with different isIs are not equal", info2.equals(info) == false);
   }
}