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


import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.jgroups.util.Util;

import java.util.HashMap;

/**
 * Tests {@link Fqn}.
 * @author <a href="mailto:bela@jboss.org">Bela Ban</a> May 9, 2003
 * @version $Revision: 1.9 $
 */
public class FqnTest extends TestCase {

   public FqnTest(String s) {
      super(s);
   }

   public void testNull() {
      Fqn fqn=new Fqn();
      log("null fqn is " + fqn);
      assertEquals(0, fqn.size());
      int hcode=fqn.hashCode();
      assertTrue(hcode != -1);
   }

   public void testOne() {
      Fqn fqn=new Fqn(new Integer(22));
      log("one fqn is " + fqn);
      assertEquals(1, fqn.size());
      int hcode=fqn.hashCode();
      assertTrue(hcode != -1);
   }

   public void testEmptyFqn() {
      Fqn f1=new Fqn();
      Fqn f2=new Fqn();
      assertEquals(f1, f2);
   }

   public void testFqn() {
      Fqn fqn=Fqn.fromString("/a/b/c");
      log("fqn is " + fqn);
      assertEquals(3, fqn.size());

      Fqn fqn2=new Fqn(new Object[]{"a", "b", "c"});
      log("fqn2 is " + fqn2);
      assertEquals(3, fqn2.size());
      assertEquals("fqn should equal fqn2", fqn, fqn2);
      assertEquals(fqn.hashCode(), fqn2.hashCode());
   }

   public void testHereogeneousNames() {
      Fqn fqn=new Fqn(new Object[]{"string", new Integer(38), new Boolean(true)});
      log("fqn is " + fqn);
      assertEquals(3, fqn.size());

      Fqn fqn2=new Fqn(new Object[]{"string", new Integer(38), new Boolean(true)});
      assertEquals(fqn, fqn2);
      assertEquals(fqn.hashCode(), fqn2.hashCode());
   }

   public void testHashcode() {
      Fqn fqn1, fqn2;
      fqn1=new Fqn(new Object[]{"a", "b", "c"});
      fqn2=Fqn.fromString("/a/b/c");
      log("fqn is " + fqn1);
      assertEquals(fqn1, fqn2);

      HashMap map=new HashMap();
      map.put(fqn1, new Integer(33));
      map.put(fqn2, new Integer(34));
      assertEquals(1, map.size());
      assertEquals(new Integer(34), map.get(fqn1));
   }

   public void testHashcode2() {
      Fqn fqn=new Fqn(new Integer(-1));
      log("one fqn is " + fqn);
      assertEquals(1, fqn.size());
      int hcode=fqn.hashCode();
      assertTrue(hcode == -1);
   }

   public void testEquals() {
      Fqn fqn1 = new Fqn("person/test");

      Fqn f1, f2, f3;

      f1 = new Fqn(fqn1, "0");
      f2 = new Fqn(fqn1, "1");
      f3 = new Fqn(fqn1, "2");

      HashMap map = new HashMap();
      map.put(f1, "0");
      map.put(f2, "1");
      map.put(f3, "2");

      assertNotNull("f1 ", map.get(new Fqn(fqn1, "0")));
      assertNotNull("f2 ", map.get(new Fqn(fqn1, "1")));
      assertNotNull("f3 ", map.get(new Fqn(fqn1, "2")));
      
   }


   public void testEquals2() {
      Fqn f1, f2;
      f1=Fqn.fromString("/a/b/c");
      f2=Fqn.fromString("/a/b/c");
      assertEquals(f1, f2);

      f2=Fqn.fromString("/a/b");
      assertFalse(f1.equals(f2));

      f2=Fqn.fromString("/a/b/c/d");
      assertFalse(f1.equals(f2));
   }

   public void testEquals2WithMarshalling() throws Exception {
      Fqn f1, f2;
      f1=Fqn.fromString("/a/b/c");
      f2=marshalAndUnmarshal(f1);
      assertEquals(f1, f2);
   }


   public void testEquals3() {
      Fqn f1, f2;
      f1=new Fqn(new Object[]{"a", new Integer(322649), Boolean.TRUE});
      f2=new Fqn();
      assertFalse(f1.equals(f2));
      assertFalse(f2.equals(f1));

      f2=Fqn.fromString("a/322649/TRUE");
      assertFalse(f1.equals(f2));

      f2=new Fqn(new Object[]{"a", new Integer(322649), Boolean.FALSE});
      assertFalse(f1.equals(f2));

      f2=new Fqn(new Object[]{"a", new Integer(322649), Boolean.TRUE});
      assertEquals(f1, f2);
   }

   public void testEquals3WithMarshalling() throws Exception {
      Fqn f1, f2;
      f1=new Fqn(new Object[]{"a", new Integer(322649), Boolean.TRUE});
      f2=marshalAndUnmarshal(f1);
      assertEquals(f1, f2);
      assertEquals(f2, f1);

      f2=Fqn.fromString("a/322649/TRUE");
      f2=marshalAndUnmarshal(f2);
      assertFalse(f1.equals(f2));

      f2=new Fqn(new Object[]{"a", new Integer(322649), Boolean.FALSE});
      f2=marshalAndUnmarshal(f2);
      assertFalse(f1.equals(f2));

      f2=new Fqn(new Object[]{"a", new Integer(322649), Boolean.TRUE});
      f2=marshalAndUnmarshal(f2);
      assertEquals(f1, f2);
   }
   
   public void testEquals4()
   {
      Fqn fqn = Fqn.fromString("X");
      // Check casting
      assertFalse("Casting ok", fqn.equals("X"));
      // Check null
      assertFalse("null ok", fqn.equals(null));
   }

   public void testClone() throws CloneNotSupportedException {
      Fqn fqn1=Fqn.fromString("/a/b/c");
      Fqn fqn2=(Fqn)fqn1.clone();
      assertEquals(fqn1, fqn2);
      assertEquals(fqn1.hashCode(), fqn2.hashCode());
   }

   public void testNullElements() throws CloneNotSupportedException {
      Fqn fqn0=new Fqn((Object)null);
      assertEquals(1, fqn0.size());

      Fqn fqn1=new Fqn(new Object[]{"NULL", null, new Integer(0)});
      assertEquals(3, fqn1.size());

      Fqn fqn2=new Fqn(new Object[]{"NULL", null, new Integer(0), });
      assertEquals(fqn1.hashCode(), fqn2.hashCode());
      assertEquals(fqn1, fqn2);
      assertEquals(fqn1, fqn1.clone());
   }

   public void testIteration() {
      Fqn fqn=Fqn.fromString("/a/b/c");
      assertEquals(3, fqn.size());
      Fqn tmp_fqn=new Fqn();
      assertEquals(0, tmp_fqn.size());
      for(int i=0; i < fqn.size(); i++) {
         Object obj=fqn.get(i);
         tmp_fqn=new Fqn(tmp_fqn, obj);
         assertEquals(tmp_fqn.size(), i+1);
      }
      assertEquals(3, tmp_fqn.size());
      assertEquals(fqn, tmp_fqn);
   }

   public void testIsChildOf() {
      Fqn child=Fqn.fromString("/a/b");
      Fqn parent=Fqn.fromString("/a");
      assertTrue("Is child of ", child.isChildOf(parent));
      assertFalse("Is child of ", parent.isChildOf(child));
      assertTrue("Is same ", child.isChildOrEquals(child));

      parent=Fqn.fromString("/a/b/c");
      child=Fqn.fromString("/a/b/c/d/e/f/g/h/e/r/e/r/t/tt/");
      assertTrue(child.isChildOf(parent));
   }

   public void testIsChildOf2() {
      Fqn child=Fqn.fromString("/a/b/c/d");
      assertEquals("Fqn ", "/b/c/d", child.getFqnChild(1, child.size()).toString());
   }

   public void testParentage()
   {
       Fqn fqnRoot = new Fqn();
       Fqn parent = fqnRoot.getParent();
       assertEquals(parent, fqnRoot);

       Fqn fqnOne = Fqn.fromString("/one");
       parent = fqnOne.getParent();
       assertEquals(parent, fqnRoot);
       assertTrue(fqnOne.isChildOf(parent));

       Fqn fqnTwo = Fqn.fromString("/one/two");
       parent = fqnTwo.getParent();
       assertEquals(parent, fqnOne);
       assertTrue(fqnTwo.isChildOf(parent));

       Fqn fqnThree = Fqn.fromString("/one/two/three");
       parent = fqnThree.getParent();
       assertEquals(parent, fqnTwo);
       assertTrue(fqnThree.isChildOf(parent));

   }

   public void testRoot()
   {
       Fqn fqn = new Fqn();
       assertTrue(fqn.isRoot());

       fqn = Fqn.fromString("/one/two");
       assertFalse(fqn.isRoot());
   }

   public void testGetName()
   {
        Fqn integerFqn = new Fqn(new Integer(1));
        assertEquals("1", integerFqn.getName());

        Object object = new Object();
        Fqn objectFqn = new Fqn(object);
        assertEquals(object.toString(), objectFqn.getName());
   }


   Fqn marshalAndUnmarshal(Fqn fqn) throws Exception {
      byte[] buf=Util.objectToByteBuffer(fqn);
      Fqn newFqn=(Fqn)Util.objectFromByteBuffer(buf);
      return newFqn;
   }

   void log(String msg) {
      System.out.println("-- " + msg);
   }

   public static Test suite() {
      return new TestSuite(FqnTest.class);
   }

   public static void main(String[] args) {
      junit.textui.TestRunner.run(suite());
   }

}
