/*
 * 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) {
            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 = 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");
            }
        }
        memInfo.append(memoryInfo());
        memInfo.append('\n');

        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();
    }
}

@@ -2086,147 +2086,8 @@
 ) %7B%0A
-            System.gc();%0A            System.runFinalization();%0A            memInfo.append(memoryInfo());%0A            memInfo.append('%5Cn');%0A
     
@@ -2467,34 +2467,91 @@
       %7D%0A        
-%7D%0A
+    System.gc();%0A            System.runFinalization();%0A    
         memInfo.
@@ -2572,32 +2572,36 @@
 nfo());%0A        
+    
 memInfo.append('
@@ -2597,32 +2597,281 @@
 fo.append('%5Cn');
+%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        %7D
 %0A%0A        assert

Enforce internal cleanup.