package org.jboss.cache.util;

import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.fail;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;

import org.jboss.util.stream.MarshalledValueInputStream;
import org.jboss.util.stream.MarshalledValueOutputStream;
import org.testng.annotations.Test;

@Test(groups={"functional", "transaction"})
public class MapCopyTest
{
   public void testSerializable() throws Exception
   {
      HashMap<String, String> hm = new HashMap<String, String>();
      hm.put(null, null);
      hm.put("y", "z");
      MapCopy<String, String> mc = new MapCopy<String, String>(hm);
      assertEquals(hm, mc);
      ByteArrayOutputStream os = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(os);
      oos.writeObject(mc);
      ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
      ObjectInputStream ois = new ObjectInputStream(is);
      Object o = ois.readObject();
      assertEquals(hm, o);
   }

   public void testSerializableWithMarshalledValueStream() throws Exception
   {
      HashMap<String, String> hm = new HashMap<String, String>();
      hm.put(null, null);
      hm.put("y", "z");
      MapCopy<String, String> mc = new MapCopy<String, String>(hm);
      assertEquals(hm, mc);
      ByteArrayOutputStream os = new ByteArrayOutputStream();
      ObjectOutputStream oos = new MarshalledValueOutputStream(os);
      oos.writeObject(mc);
      ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
      ObjectInputStream ois = new MarshalledValueInputStream(is);
      Object o = ois.readObject();
      assertEquals(hm, o);
   }

   public void testNull()
   {
      HashMap<String, String> hm = new HashMap<String, String>();
      hm.put(null, null);
      MapCopy<String, String> mc = new MapCopy<String, String>(hm);
      assertEquals(hm, mc);
      assertEquals(hm.toString(), mc.toString());

      hm.put(null, "x");
      hm.put("y", null);
      mc = new MapCopy<String, String>(hm);
      mc.toString();
      assertEquals(true, mc.containsKey("y"));
   }

   public void testAll()
   {
      HashMap<String, String> hm = new HashMap<String, String>();
      hm.put("a", "b");
      hm.put("b", "c");
      MapCopy<String, String> mc = new MapCopy<String, String>(hm);
      assertEquals(hm, mc);
      assertEquals(hm.size(), mc.size());
      try
      {
         mc.clear();
         fail("read only");
      }
      catch (UnsupportedOperationException e)
      {
      }
      HashMap<String, String> bhm = new HashMap<String, String>(hm);
      hm.put("b", "d");
      assertEquals(bhm, mc);
      Map.Entry<String, String> me = mc.entrySet().iterator().next();
      try
      {
         me.setValue("arg");
         fail("read only");
      }
      catch (UnsupportedOperationException e)
      {
      }
   }

   public void testModifications()
   {
      Map<String, String> hm = new HashMap<String, String>();
      hm.put("a", "b");
      Map<String, String> mc = new MapCopy<String, String>(hm);

      try
      {
         mc.put("x", "y");
         fail("should fail");
      }
      catch (UnsupportedOperationException uoe)
      {
         // ok
      }

      try
      {
         mc.remove("a");
         fail("should fail");
      }
      catch (UnsupportedOperationException uoe)
      {
         // ok
      }

      try
      {
         mc.keySet().iterator().remove();
         fail("should fail");
      }
      catch (UnsupportedOperationException uoe)
      {
         // ok
      }

      try
      {
         mc.entrySet().iterator().remove();
         fail("should fail");
      }
      catch (UnsupportedOperationException uoe)
      {
         // ok
      }

      try
      {
         mc.values().iterator().remove();
         fail("should fail");
      }
      catch (UnsupportedOperationException uoe)
      {
         // ok
      }


   }
}
