/* 
 * E-XML Library:  For XML, XML-RPC, HTTP, and related.
 * Copyright (C) 2002-2008  Elias Ross
 * 
 * genman@noderunner.net
 * http://noderunner.net/~genman
 * 
 * 1025 NE 73RD ST
 * SEATTLE WA 98115
 * USA
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * $Id$
 */

package net.noderunner.exml;

import java.util.Collection;
import java.util.Iterator;

public class StringPoolTest
	extends junit.framework.TestCase
{
	static boolean runSoftTest = false;

	public static void main(String[] args) {
		if (args.length > 0)
			runSoftTest = true;
		junit.textui.TestRunner.run(StringPoolTest.class);
	}

	public StringPoolTest(String name) {
		super(name);
	}

	public void testCollection() {
		Collection c = new StringPool();
		assertTrue("empty", c.isEmpty());
		assertEquals("size 0", 0, c.size());
		Collection c2 = new StringPool();
		assertEquals("same", c, c2);
		Iterator i = c.iterator();
		assertEquals("hasNext false", false, i.hasNext());
		try {
			i.remove();
			fail("UnsupportedOperationException expected");
		} catch (UnsupportedOperationException e) {
		}
	}

	public void testCollection3() {
		StringPool sp = new StringPool(16);
		sp.intern("a");
		sp.intern("b");
		sp.intern("c");
		Iterator i = sp.iterator();
		while (i.hasNext()) {
			i.next();
		}
	}

	public void testCollection2() {
		StringPool sp = new StringPool(16);
		String h = "hello";
		String h2 = "hello2";
		sp.intern(h);
		sp.intern(h2);
		assertTrue("contains h", sp.contains(h));
		assertTrue("contains h2", sp.contains(h2));
		StringPool sp2 = new StringPool(17);
		sp2.intern(h);
		sp2.intern(h2);
		assertTrue("containsAll 1", sp.containsAll(sp2));
		assertTrue("containsAll 2", sp2.containsAll(sp));
		assertEquals("same contents", sp, sp2);
	}

	public void testIntern() {
		StringPool sp = new StringPool();
		String h1 = sp.intern("hello");
		String h2 = sp.intern("hello");
		assertTrue("internally same", h1 == h2);
		assertEquals("size 1", 1, sp.size());
	}

	public void testHashCode() {
		String abc = "abcd1234!@#$";
		int code = StringPool.hashCode(abc.toCharArray(), 0, abc.length());
		int code2 = abc.hashCode();
		assertEquals("hash codes the same", code, code2);
	}

	public void testRemove() {
		StringPool sp = new StringPool(16);
		String h = "hello";
		String h2 = "hello2";
		sp.add(h);
		sp.add(h2);
		sp.add(h);
		assertEquals("size 2", 2, sp.size());
		assertTrue("contains h", sp.contains(h));
		sp.remove(h);
		assertTrue("no contains h", !sp.contains(h));
		sp.remove(h);
		assertTrue("no contains h", !sp.contains(h));
		sp.remove(h2);
		assertTrue("no contains h2", !sp.contains(h2));
		assertEquals("size empty", 0, sp.size());
	}

	// This takes a long time to automatically run
	public void testSoftPool() {
		if (!runSoftTest)
			return;
		StringPool sp = new StringPool(16);
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < 3000; i++)
			sb.append("abcdefghijklmnopqrstuvwxyz");
		String s = sb.toString();
		String special = "how special!";
		sp.add(special);
		System.out.println("contents " + sp.size());
		for (int i = 0; i < 1000; i++) {
			s = "" + sb + i % 5000;
			String iterned = sp.intern(s);
			String iterned2 = sp.intern(s.toCharArray(), 0, s.length());
			assertTrue("string not null", iterned != null);
			assertTrue("itern  equal", s == iterned);
			assertTrue("itern2 equal", s == iterned2);
			if (i % 1000 == 0)
				System.out.println("I is " + i / 1000 + " buckets " + sp.buckets());
		}
		assertTrue("special here", sp.contains(special));
		System.out.println("contents " + sp.size());
	}

	public void testIntern2() {
		StringPool sp = new StringPool();
		String h1 = sp.intern("hello");
		char c[] = "hello".toCharArray();
		String h2 = sp.intern(c, 0, c.length);
		assertTrue("internally same", h1 == h2);
		assertEquals("size 1", 1, sp.size());
		// try some more
		char c2[] = " hello ".toCharArray();
		String h3 = sp.intern(c2, 1, 5);
		assertEquals("size 1" + sp, 1, sp.size());
		assertEquals("hello", h3);
		assertTrue("internally same" + sp, h1 == h3);
	}

	/*
	   This is slow, so only run if recreate() has changed
	public void testRecreate() {
		String s = "message";
		StringPool sp = new StringPool(4);
		int c = 100000;
		for (int j = 0; j < 10; j++) {
			for (int i = 0; i < c; i++) {
				sp.intern(s + i);
				Thread.yield();
			}
			System.gc();
		}
		System.out.println(sp.toString().length());
		System.gc();
		for (int i = 0; i < c; i++) {
			assertEquals(s + i, sp.intern(s + i));
		}
	}
	*/

	public void testAddLots() {
		StringPool sp = new StringPool(4);
		for (int i = 0; i < 128; i++) {
			String s = "number " + i;
			String a = sp.intern(s);
			String b = sp.intern(s);
			assertTrue("intern equality", a == b);
		}
		assertEquals("size 128", 128, sp.size());
		for (int i = 0; i < 128; i++) {
			String s = "number " + i;
			assertTrue("contains it " + sp, sp.contains(s));
		}
		assertEquals("size 128", 128, sp.size());
		Iterator i = sp.iterator();
		assertEquals("hasNext true", true, i.hasNext());
	}

	public void testIntern3() {
                String a = "a";
                StringPool sp = new StringPool(4);
                String a2 = sp.intern(new char[] { 'a' }, 0, 1);
                assertTrue("object equals", a == a2);
                String a3 = sp.intern(new char[] { 'a' }, 0, 1);
                assertTrue("object equals", a2 == a3);
                String a0 = new StringBuffer().append('a').toString();
                assertTrue("object equals", a == sp.intern(a0));
        }

}

