/*
 * Copyright (C) 2004 Joe Walnes.
 * Copyright (C) 2006, 2007, 2008 XStream Committers.
 * All rights reserved.
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 * 
 * Created on 30. May 2004 by Joe Walnes
 */
package com.thoughtworks.xstream.core.util;

import junit.framework.TestCase;

import java.lang.reflect.Field;


public class ObjectIdDictionaryTest extends TestCase {

    public void testMapsIdsToObjectReferences() {
        ObjectIdDictionary dict = new ObjectIdDictionary();
        Object a = new Object();
        Object b = new Object();
        Object c = new Object();
        dict.associateId(a, "id a");
        dict.associateId(b, "id b");
        dict.associateId(c, "id c");
        assertEquals("id a", dict.lookupId(a));
        assertEquals("id b", dict.lookupId(b));
        assertEquals("id c", dict.lookupId(c));
    }

    public void testTreatsObjectsThatAreEqualButNotSameInstanceAsDifferentReference() {
        ObjectIdDictionary dict = new ObjectIdDictionary();
        Integer a = new Integer(3);
        Integer b = new Integer(3);
        dict.associateId(a, "id a");
        dict.associateId(b, "id b");
        assertEquals("id a", dict.lookupId(a));
        assertEquals("id b", dict.lookupId(b));
    }

    public void testEnforceSameSystemHashCodeForGCedObjects() throws SecurityException, NoSuchFieldException, IllegalAccessException {
        final Field invalidCounter = ObjectIdDictionary.class.getDeclaredField("invalidCounter");
        invalidCounter.setAccessible(true);
        final StringBuffer memInfo = new StringBuffer("MemoryInfo:\n");
        memInfo.append(memoryInfo());
        memInfo.append('\n');

        // create 100000 Strings and call GC after creation of 10000
        final int loop = 10;
        final int elements = 10000;
        final int[] dictSizes = new int[loop * elements];
        ObjectIdDictionary dict = new ObjectIdDictionary();
        for (int i = 0; i < loop; ++i) {
            for (int j = 0; j < elements; ++j) {
                final int count = i * elements + j;
                final String s = new String("JUnit ") + count; // enforce new object
                dictSizes[i * elements + j] = dict.size();
                assertFalse("Failed in (" + i + "/" + j + ")", dict.containsId(s));
                dict.associateId(s, "X");
            }
            System.gc();
            System.runFinalization();
            memInfo.append(memoryInfo());
            memInfo.append('\n');
            for (int j = 0; j < elements; ++j) {
                final int count = i * elements + j;
                final String s = "JUnit " + count;
                dict.containsId(s); // force lookup and internal cleanup
            }
        }

        assertFalse("Algorithm did not reach last element", 0 == dictSizes[loop * elements - 1]);
        assertFalse("Dictionary did not shrink " + memInfo + "InvalidCounter: " + invalidCounter.getInt(dict),
            loop * elements - 1 == dictSizes[loop * elements - 1]);
    }
    
    private String memoryInfo() {
        Runtime runtime = Runtime.getRuntime();
        StringBuffer buffer = new StringBuffer("Memory: ");
        buffer.append(runtime.freeMemory());
        buffer.append(" free / ");
        buffer.append(runtime.maxMemory());
        buffer.append(" max / ");
        buffer.append(runtime.totalMemory());
        buffer.append(" total");
        return buffer.toString();
    }
}

@@ -437,18 +437,105 @@
 .ref
-lect.Field
+.SoftReference;%0Aimport java.lang.reflect.Field;%0Aimport java.util.ArrayList;%0Aimport java.util.List
 ;%0A%0A%0A
@@ -2222,60 +2222,8 @@
 ) %7B%0A
-                final int count = i * elements + j;%0A
     
@@ -2274,21 +2274,17 @@
 it %22) + 
-count
+j
 ; // enf
@@ -2502,71 +2502,8 @@
   %7D%0A
-            System.gc();%0A            System.runFinalization();%0A
     
@@ -2578,247 +2578,8 @@
 ');%0A
-            for (int j = 0; j %3C elements; ++j) %7B%0A                final int count = i * elements + j;%0A                final String s = %22JUnit %22 + count;%0A                dict.containsId(s); // force lookup and internal cleanup%0A            %7D%0A
     
@@ -2863,24 +2863,800 @@
 - 1%5D);%0A    %7D
+%0A%0A    private void forceGC() %7B%0A        SoftReference ref = new SoftReference(new byte%5B1024*16%5D);%0A        for (int count = 0; ref.get() != null && count++ %3C 10; ) %7B%0A            List memory = new ArrayList();%0A            try %7B%0A                while(ref.get() != null) %7B%0A                    memory.add(new byte%5B1024*16%5D);%0A                %7D%0A            %7D catch (OutOfMemoryError error) %7B%0A                // expected%0A            %7D%0A            memory.clear();%0A            memory = null;%0A            System.gc();%0A            System.runFinalization();%0A            try %7B%0A                Thread.sleep(200);%0A            %7D catch (InterruptedException e) %7B%0A                // ignore%0A            %7D%0A        %7D%0A%0A        assertNull(%22This JVM is not releasing memory!%22, ref.get() != null);%0A    %7D
 %0A    %0A    pr
@@ -3901,19 +3901,21 @@
 runtime.
-max
+total
 Memory()
@@ -3945,14 +3945,13 @@
 d(%22 
-max / 
+total
 %22);%0A
@@ -3972,37 +3972,35 @@
 .append(runtime.
-total
+max
 Memory());%0A     
@@ -4010,37 +4010,38 @@
 buffer.append(%22 
-total
+max / 
 %22);%0A        retu

Try different strategy to fill memory.