Package com.sun.sgs.test.app.util

Source Code of com.sun.sgs.test.app.util.TestScalableHashMap$Foo

/*
* Copyright 2007-2010 Sun Microsystems, Inc.
*
* This file is part of Project Darkstar Server.
*
* Project Darkstar Server is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation and
* distributed hereunder to you.
*
* Project Darkstar Server 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* --
*/

package com.sun.sgs.test.app.util;

import com.sun.sgs.app.ManagedObject;
import com.sun.sgs.app.ObjectNotFoundException;
import com.sun.sgs.app.util.ScalableHashMap;
import com.sun.sgs.app.util.ManagedSerializable;
import com.sun.sgs.auth.Identity;
import static com.sun.sgs.impl.sharedutil.Objects.uncheckedCast;
import com.sun.sgs.kernel.TransactionScheduler;
import com.sun.sgs.service.DataService;
import com.sun.sgs.test.util.SgsTestNode;
import com.sun.sgs.test.util.TestAbstractKernelRunnable;
import static com.sun.sgs.test.util.UtilReflection.getConstructor;
import static com.sun.sgs.test.util.UtilReflection.getMethod;
import com.sun.sgs.tools.test.FilteredNameRunner;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Random;
import java.util.Set;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
* Test the {@link ScalableHashMap} class.
*/
@RunWith(FilteredNameRunner.class)
public class TestScalableHashMap extends Assert {

    private static SgsTestNode serverNode;
    private static TransactionScheduler txnScheduler;
    private static Identity taskOwner;
    private static DataService dataService;

    /** A fixed random number generator for use in the test. */
    private static final Random RANDOM = new Random(1337);

    /** The four argument constructor. */
    private static final Constructor<ScalableHashMap>
  scalableHashMapConstructor = getConstructor(
      ScalableHashMap.class, int.class, int.class, int.class, int.class);

    /** The findMinDepthFor method. */
    private static final Method findMinDepthFor =
  getMethod(ScalableHashMap.class, "findMinDepthFor", int.class);

    /** The getMinTreeDepth method. */
    private static final Method getMinTreeDepth =
  getMethod(ScalableHashMap.class, "getMinTreeDepth");

    /** The getMaxTreeDepth method. */
    private static final Method getMaxTreeDepth =
  getMethod(ScalableHashMap.class, "getMaxTreeDepth");

    /** The getAvgTreeDepth method. */
    private static final Method getAvgTreeDepth =
  getMethod(ScalableHashMap.class, "getAvgTreeDepth");

    /** The checkLeafRefs method. */
    private static final Method checkLeafRefs =
  getMethod(ScalableHashMap.class, "checkLeafRefs");

    /**
     * Test management.
     */

    @BeforeClass public static void setUpClass() throws Exception {
  serverNode = new SgsTestNode("TestScalableHashMap", null,
             createProps("TestScalableHashMap"));
        txnScheduler = serverNode.getSystemRegistry().
            getComponent(TransactionScheduler.class);
        taskOwner = serverNode.getProxy().getCurrentOwner();
        dataService = serverNode.getDataService();
    }

    @AfterClass public static void tearDownClass() throws Exception {
  serverNode.shutdown(true);
    }

    /*
     * Test no arg constructor
     */

    @Test public void testConstructorNoArg() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      new ScalableHashMap<Integer,Integer>();
        assertEquals(6, getMaxTreeDepth(test));
        assertEquals(6, getMaxTreeDepth(test));
        dataService.setBinding("test", test);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertEquals(6, getMaxTreeDepth(test));
        assertEquals(6, getMinTreeDepth(test));
    }
      }, taskOwner);
    }

    /*
     * Test minimum concurrency constructor
     */

    @Test public void testConstructorOneArgDepth() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(1);
        assertEquals(1, getMaxTreeDepth(test));
        assertEquals(1, getMinTreeDepth(test));
    }
      }, taskOwner);
    }

    @Test public void testConstructorOneArgDepth3() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(3);
        assertEquals(3, getMaxTreeDepth(test));
        assertEquals(3, getMinTreeDepth(test));
    }
      }, taskOwner);
    }

    @Test public void testConstructorOneArgDepth4() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(5);
        assertEquals(4, getMaxTreeDepth(test));
        assertEquals(4, getMinTreeDepth(test));
    }
      }, taskOwner);
    }

    @Test public void testConstructorOneArgWithZeroMaxConcurrencyException()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        try {
      new ScalableHashMap<Integer,Integer>(0);
      fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException iae) {
        }
    }
      }, taskOwner);
    }

    /** This test reproduces the problem reported in sgs-server issue #160. */
    @Test
    public void testConstructorOneArgHighConcurrency() throws Exception {
  for (final int concurrency : new int[] { 256, 1024 }) {
      txnScheduler.runTask(
    new TestAbstractKernelRunnable() {
        public void run() throws Exception {
      Map<Integer, Integer> map =
          new ScalableHashMap<Integer,Integer>(256);
      map.keySet().iterator();
        }
    }, taskOwner);
  }
    }

    // NOTE: we do not test the maximum concurrency in the
    // constructor, as this would take far too long to test (hours).

    /*
     * Test copy constructor
     */

    @Test public void testCopyConstructor() throws Exception {
  final Map<Integer,Integer> control = new HashMap<Integer,Integer>();
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        for (int i = 0; i < 32; i++) {
      control.put(i,i);
        }
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(control);
        assertEquals(control, test);
        dataService.setBinding("test", test);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertEquals(control, test);
    }
      }, taskOwner);
    }

    @Test public void testNullCopyConstructor() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        try {
      new ScalableHashMap<Integer,Integer>(null);
      fail("Expected NullPointerException");
        } catch (NullPointerException npe) {
        }
    }
      }, taskOwner);
    }

    /*
     * Test non-public constructor
     */

    @Test public void testMultiParamConstructor() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        createScalableHashMap(Integer.class, Integer.class,
            1, 32, 5);
        createScalableHashMap(Integer.class, Integer.class,
            1, 32, 4);
    }
      }, taskOwner);
    }

    @Test public void testMultiParamConstructorBadMinConcurrency()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        try {
      createScalableHashMap(Integer.class, Integer.class,
                0, 1, 5);
      fail("Expected IllegalArgumentException");
        } catch(IllegalArgumentException iae) {
        }
    }
      }, taskOwner);
    }

    @Test public void testMultiParamConstructorBadSplitThreshold()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        try {
      createScalableHashMap(Integer.class, Integer.class,
                1, 0, 5);
      fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException iae) {
        }
    }
      }, taskOwner);
    }

    @Test public void testMultiParamConstructorBadDirectorySize()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        try {
      createScalableHashMap(Integer.class, Integer.class,
                1, 32, -1);
      fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException iae) {
        }
    }
      }, taskOwner);
    }

    /*
     * Test putAll
     */

    @Test public void testPutAllMisc() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();
        for (int i = 0; i < 32; i++) {
      control.put(i,i);
        }
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        test.putAll(control);
        assertEquals(control, test);
    }
      }, taskOwner);
     }

    @Test public void testPutAllNullArg() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        try {
      test.putAll(null);
      fail("Expected NullPointerException");
        } catch (NullPointerException e) {
        }
    }
      }, taskOwner);
    }

    @Test public void testPutAllNotSerializable() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Object,Object> test =
      new ScalableHashMap<Object,Object>();
        Object nonSerializable = Thread.currentThread();
        Map<Object,Object> other = new HashMap<Object,Object>();
        other.put(nonSerializable, Boolean.TRUE);
        try {
      test.putAll(other);
      fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
        }
        other.clear();
        other.put(Boolean.TRUE, nonSerializable);
        try {
      test.putAll(other);
      fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
        }
    }
      }, taskOwner);
    }

    @Test public void testPutAllNullItems() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Object,Object> test =
      new ScalableHashMap<Object,Object>();
        Object nonSerializable = Thread.currentThread();
        Map<Object,Object> control = new HashMap<Object,Object>();
        test.put(0, null);
        control.put(0, null);
        test.put(null, 0);
        control.put(null, 0);
        assertEquals(test, control);
    }
      }, taskOwner);
    }

    /*
     * Test put
     */

    @Test public void testPutMisc() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Foo> test = new ScalableHashMap<Integer,Foo>();
        Foo result = test.put(1, new Foo(1));
        assertEquals(null, result);
        result = test.put(1, new Foo(1));
        assertEquals(new Foo(1), result);
        result = test.put(1, new Foo(37));
        assertEquals(new Foo(1), result);
    }
      }, taskOwner);
    }

    @Test public void testPutNotSerializable() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Object,Object> test =
      new ScalableHashMap<Object,Object>();
        Object nonSerializable = Thread.currentThread();
        try {
      test.put(nonSerializable, Boolean.TRUE);
      fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
      assertTrue(test.isEmpty());
        }
        try {
      test.put(Boolean.TRUE, nonSerializable);
      fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
      assertTrue(test.isEmpty());
        }
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testPutOldValueNotFound() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test = new ScalableHashMap();
        dataService.setBinding("test", test);
        Bar bar = new Bar(1);
        dataService.setBinding("bar", bar);
        test.put(Boolean.TRUE, bar);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        dataService.removeObject(dataService.getBinding("bar"));
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        try {
      test.put(Boolean.TRUE, Boolean.FALSE);
      fail("Expected ObjectNotFoundException");
        } catch (ObjectNotFoundException e) {
      assertEquals(1, test.size());
        }
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        try {
      test.put(Boolean.TRUE, Boolean.FALSE);
      fail("Expected ObjectNotFoundException");
        } catch (ObjectNotFoundException e) {
      assertEquals(1, test.size());
        }
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testPutOldKeyNotFound() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test = new ScalableHashMap();
        dataService.setBinding("test", test);
        Bar bar = new Bar(1);
        dataService.setBinding("bar", bar);
        test.put(bar, Boolean.TRUE);
    }
      }, taskOwner);
  try {
      txnScheduler.runTask(
          new TestAbstractKernelRunnable() {
        public void run() throws Exception {
      dataService.removeObject(
          dataService.getBinding("bar"));
      ScalableHashMap test =
          (ScalableHashMap) dataService.getBinding("test");
      assertEquals(null, test.put(new Bar(1), Boolean.FALSE));
      assertEquals(Boolean.FALSE, test.get(new Bar(1)));
      throw new RuntimeException("Intentional Abort");
        }
    }, taskOwner);
  } catch (RuntimeException re) {}
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        dataService.removeObject(dataService.getBinding("bar"));
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertEquals(null, test.put(new Bar(1), Boolean.FALSE));
        assertEquals(Boolean.FALSE, test.get(new Bar(1)));
    }
      }, taskOwner);
    }

    @Test public void testPutNullKey() throws Exception {
  final Map<String,Integer> control = new HashMap<String,Integer>();
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<String,Integer> test =
      new ScalableHashMap<String,Integer>(16);
        test.put(null, 0);
        control.put(null, 0);
        assertEquals(control, test);
        dataService.setBinding("test", test);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        assertEquals(control, dataService.getBinding("test"));
    }
      }, taskOwner);     
    }

    @Test public void testPutNullValue() throws Exception {
  final Map<Integer,String> control = new HashMap<Integer,String>();
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,String> test =
      new ScalableHashMap<Integer,String>(16);
        test.put(0, null);
        control.put(0, null);
        assertEquals(control, test);
        dataService.setBinding("test", test);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        assertEquals(control, dataService.getBinding("test"));
    }
      }, taskOwner);
    }

    /*
     * Test get
     */

    @Test public void testGetMisc() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Foo> test = new ScalableHashMap<Integer,Foo>();
        assertEquals(null, test.get(1));
        test.put(1, new Foo(1));
        assertEquals(new Foo(1), test.get(1));
        assertEquals(null, test.get(new Foo(1)));
        assertEquals(null, test.get(2));
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testGetValueNotFound() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test = new ScalableHashMap();
        dataService.setBinding("test", test);
        Bar bar = new Bar(1);
        dataService.setBinding("bar", bar);
        test.put(Boolean.TRUE, bar);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        dataService.removeObject(dataService.getBinding("bar"));
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        try {
      test.get(Boolean.TRUE);
      fail("Expected ObjectNotFoundException");
        } catch (ObjectNotFoundException e) {
      assertEquals(1, test.size());
        }
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        try {
      test.get(Boolean.TRUE);
      fail("Expected ObjectNotFoundException");
        } catch (ObjectNotFoundException e) {
      assertEquals(1, test.size());
        }
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testGetKeyNotFound() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test = new ScalableHashMap();
        dataService.setBinding("test", test);
        Bar bar = new Bar(1);
        dataService.setBinding("bar", bar);
        test.put(bar, Boolean.TRUE);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        dataService.removeObject(dataService.getBinding("bar"));
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertEquals(null, test.get(new Bar(1)));
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertEquals(null, test.get(new Bar(1)));
    }
      }, taskOwner);
    }

    @Test public void testGetNullKey() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<String,Integer> test =
      new ScalableHashMap<String,Integer>(16);
        test.put(null, 0);
        assertEquals(new Integer(0), test.get(null));
        dataService.setBinding("test", test);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        assertEquals(
      new Integer(0),
      ((Map) dataService.getBinding("test")).get(null));
    }
      }, taskOwner);
    }

    @Test public void testGetNullValue() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,String> test =
      new ScalableHashMap<Integer,String>(16);
        test.put(0, null);
        assertEquals(null, test.get(0));
        dataService.setBinding("test", test);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        assertEquals(null,
         ((Map) dataService.getBinding(
             "test")).get(0));
    }
      }, taskOwner);
    }

    /*
     * Test containsKey
     */

    @Test public void testContainsKeyMisc() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Foo> test = new ScalableHashMap<Integer,Foo>();
        assertFalse(test.containsKey(1));
        test.put(1, new Foo(1));
        assertTrue(test.containsKey(1));
        assertFalse(test.containsKey(new Foo(1)));
        assertFalse(test.containsKey(2));
    }
      }, taskOwner);
    }

    @Test public void testContainsKeyNull() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<String,Integer> test =
      new ScalableHashMap<String,Integer>(16);
        test.put(null, 0);
        assertTrue(test.containsKey(null));
        dataService.setBinding("test", test);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        assertTrue(((Map) dataService.getBinding(
            "test")).containsKey(null));
    }
      }, taskOwner);
    }

    @Test public void testContainsKeyNullOnEmptyMap() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<String,Integer> test =
      new ScalableHashMap<String,Integer>(16);
        assertFalse(test.containsKey(null));
        dataService.setBinding("test", test);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        assertFalse(((Map) dataService.getBinding(
             "test")).containsKey(null));
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testContainsKeyKeyNotFound() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test = new ScalableHashMap(16);
        dataService.setBinding("test", test);
        Bar bar = new Bar(1);
        dataService.setBinding("bar", bar);
        test.put(bar, 1);
        test.put(new Bar(2), 2);
        }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        dataService.removeObject(dataService.getBinding("bar"));
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertFalse(test.containsKey(new Bar(1)));
        assertEquals(2, test.size());
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertFalse(test.containsKey(new Bar(1)));
        assertEquals(2, test.size());
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testContainsKeyValueNotFound() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test = new ScalableHashMap(16);
        dataService.setBinding("test", test);
        Bar bar = new Bar(1);
        dataService.setBinding("bar", bar);
        test.put(1, bar);
        test.put(2, new Bar(2));
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        dataService.removeObject(dataService.getBinding("bar"));
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertTrue(test.containsKey(1));
        assertEquals(2, test.size());
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertTrue(test.containsKey(1));
        assertEquals(2, test.size());
    }
      }, taskOwner);
    }

    @Test public void testContainsKeyOnSplitTree() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] inputs = new int[50];

        for (int i = 0; i < inputs.length; i++) {
      int j = RANDOM.nextInt();
      inputs[i] = j;
      test.put(j,-j);
        }

        for (int i = 0; i < inputs.length; i++) {
      assertTrue(test.containsKey(inputs[i]));
        }
    }
      }, taskOwner);
    }

    /*
     * Test containsValue
     */

    @Test public void testContainsValueMisc() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Foo> test = new ScalableHashMap<Integer,Foo>();
        assertFalse(test.containsValue(new Foo(1)));
        test.put(1, new Foo(1));
        assertTrue(test.containsValue(new Foo(1)));
        assertFalse(test.containsValue(1));
        assertFalse(test.containsValue(new Foo(2)));
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testContainsValueNull() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        test.put(0, null);
        dataService.setBinding("test", test);
        assertTrue(test.containsValue(null));
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      uncheckedCast(dataService.getBinding("test"));
        assertTrue(test.containsValue(null));
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testContainsValueNullEmptyMap() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        dataService.setBinding("test", test);
        assertFalse(test.containsValue(null));
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      uncheckedCast(dataService.getBinding("test"));
        assertFalse(test.containsValue(null));
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testContainsValueValueNotFound() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test = new ScalableHashMap();
        dataService.setBinding("test", test);
        Bar bar = new Bar(1);
        dataService.setBinding("bar", bar);
        test.put(1, bar);
        test.put(2, new Bar(2));
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        dataService.removeObject(dataService.getBinding("bar"));
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertFalse(test.containsValue(new Bar(1)));
        assertEquals(2, test.size());
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertFalse(test.containsValue(new Bar(1)));
        assertEquals(2, test.size());
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testContainsValueKeyNotFound() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test = new ScalableHashMap();
        dataService.setBinding("test", test);
        Bar bar = new Bar(1);
        dataService.setBinding("bar", bar);
        test.put(bar, 1);
        test.put(new Bar(2), 2);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        dataService.removeObject(dataService.getBinding("bar"));
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertTrue(test.containsValue(1));
        assertEquals(2, test.size());
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertTrue(test.containsValue(1));
        assertEquals(2, test.size());
    }
      }, taskOwner);
    }

    @Test public void testContainsValueNullOnSplitMap() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        test.put(0, null);
        assertTrue(test.containsValue(null));
    }
      }, taskOwner);
    }

    @Test public void testContainsValue() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] inputs = new int[50];

        for (int i = 0; i < inputs.length; i++) {
      int j = RANDOM.nextInt();
      inputs[i] = j;
      test.put(j,-j);
        }

        for (int i = 0; i < inputs.length; i++) {
      assertTrue(test.containsValue(-inputs[i]));
        }
    }
      }, taskOwner);
    }

    @Test public void testContainsValueOnSplitTree() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] inputs = new int[50];

        for (int i = 0; i < inputs.length; i++) {
      int j = RANDOM.nextInt();
      inputs[i] = j;
      test.put(j,-j);
        }

        for (int i = 0; i < inputs.length; i++) {
      assertTrue(test.containsValue(-inputs[i]));
        }
    }
      }, taskOwner);
    }

    /*
     * Test values
     */

    @SuppressWarnings("unchecked")
    @Test public void testValues() throws Exception {
  final Map<Integer,Integer> control = new HashMap<Integer,Integer>();
  final Collection<Integer> controlValues = control.values();
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        Collection<Integer> values = test.values();
       
        assertTrue(values.isEmpty());
        assertIteratorDone(values.iterator());

        for (int i = 0; i < 50; i++) {
      int j = RANDOM.nextInt();
      test.put(j,-j);
      control.put(j,-j);
        }

        assertEquals(50, values.size());
        assertTrue(controlValues.containsAll(values));
        assertIteratorContains(controlValues, values.iterator());

        dataService.setBinding("values",
             new ManagedSerializable(values));
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ManagedSerializable<Collection<Integer>> ms =
      uncheckedCast(dataService.getBinding("values"));
        Collection<Integer> values = ms.get();
        assertEquals(50, values.size());
        assertTrue(controlValues.containsAll(values));
        assertIteratorContains(controlValues, values.iterator());
    }
      }, taskOwner);
    }

    @Test public void testValuesOnSplitTree() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Collection<Integer> control = new ArrayList<Integer>(50);

        int[] inputs = new int[50];

        for (int i = 0; i < inputs.length; i++) {
      int j = RANDOM.nextInt();
      inputs[i] = j;
      test.put(j,-j);
      control.add(-j);
        }

        assertTrue(control.containsAll(test.values()));
    }
      }, taskOwner);
    }

    /*
     * Test keySet
     */

    @SuppressWarnings("unchecked")
    @Test public void testKeySet() throws Exception {
  final Map control = new HashMap();
  final Set controlKeys = control.keySet();
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map test = new ScalableHashMap();
        Set keys = test.keySet();
        assertEquals(controlKeys, keys);
        assertIteratorDone(keys.iterator());
        assertEquals(controlKeys.hashCode(), keys.hashCode());
        for (int i = 0; i < 50; i++) {
      int j = RANDOM.nextInt();
      test.put(j,-j);
      control.put(j,-j);
        }
        assertEquals(controlKeys, keys);
        assertIteratorContains(controlKeys, keys.iterator());
        assertEquals(controlKeys.hashCode(), keys.hashCode());
        dataService.setBinding("keys",
             new ManagedSerializable(keys));
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ManagedSerializable<Set> ms =
      uncheckedCast(dataService.getBinding("keys"));
        Set keys = ms.get();
        assertEquals(controlKeys, keys);
        assertIteratorContains(controlKeys, keys.iterator());
        assertEquals(controlKeys.hashCode(), keys.hashCode());
    }
      }, taskOwner);
    }

    /*
     * Test entrySet
     */

    @SuppressWarnings("unchecked")
    @Test public void testEntrySet() throws Exception {
  final Map control = new HashMap();
  final Set controlEntries = control.entrySet();
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map test = new ScalableHashMap();
        Set entries = test.entrySet();
        assertEquals(controlEntries, entries);
        assertIteratorDone(entries.iterator());
        assertEquals(controlEntries.hashCode(), entries.hashCode());
        for (int i = 0; i < 50; i++) {
      int j = RANDOM.nextInt();
      test.put(j,-j);
      control.put(j,-j);
        }
        assertEquals(controlEntries, entries);
        assertIteratorContains(controlEntries, entries.iterator());
        assertEquals(controlEntries.hashCode(), entries.hashCode());
        dataService.setBinding("entries",
             new ManagedSerializable(entries));
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ManagedSerializable<Set> ms =
      uncheckedCast(dataService.getBinding("entries"));
        Set entries = ms.get();
        assertEquals(controlEntries, entries);
        assertEquals(controlEntries.hashCode(), entries.hashCode());
    }
      }, taskOwner);
    }

    /*
     * Test equals and hashCode
     */

    @SuppressWarnings("unchecked")
    @Test public void testEquals() throws Exception {
  final Map control = new HashMap();
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test = new ScalableHashMap();
        assertFalse(test.equals(null));
        assertFalse(test.equals(1));
        assertTrue(test.equals(control));
        assertEquals(test.hashCode(), control.hashCode());
        for (int i = 0; i < 50; i++) {
      int j = RANDOM.nextInt();
      test.put(j,-j);
      control.put(j,-j);
        }
        assertTrue(test.equals(control));
        assertEquals(test.hashCode(), control.hashCode());
        dataService.setBinding("test", test);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertTrue(test.equals(control));
        assertEquals(test.hashCode(), control.hashCode());
    }
      }, taskOwner);
    }

    /*
     * Test toString
     */

    @Test public void testToString() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        assertEquals("{}", test.toString());
        test.put(1, 2);
        assertEquals("{1=2}", test.toString());
    }
      }, taskOwner);
    }

    /*
     * Test remove
     */

    @Test public void testRemoveMisc() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Foo> test = new ScalableHashMap<Integer,Foo>();
        assertEquals(null, test.remove(1));
        test.put(1, new Foo(1));
        assertEquals(null, test.remove(2));
        assertEquals(null, test.remove(new Foo(1)));
        assertEquals(new Foo(1), test.remove(1));
        assertTrue(test.isEmpty());
        assertEquals(null, test.remove(1));
    }
      }, taskOwner);
    }

    @Test public void testRemoveNullKey() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<String,Integer> test =
      new ScalableHashMap<String,Integer>(16);
        Map<String,Integer> control = new HashMap<String,Integer>();
        test.put(null, 0);
        control.put(null, 0);
        assertEquals(control, test);
        test.remove(null);
        control.remove(null);
        assertEquals(control, test);
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testRemoveValueNotFound() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test = new ScalableHashMap();
        dataService.setBinding("test", test);
        Bar bar = new Bar(1);
        dataService.setBinding("bar", bar);
        test.put(1, bar);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        dataService.removeObject(dataService.getBinding("bar"));
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        try {
      test.remove(1);
      fail("Expected ObjectNotFoundException");
        } catch (ObjectNotFoundException e) {
        }
        assertEquals(null, test.remove(2));
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        try {
      test.remove(1);
      fail("Expected ObjectNotFoundException");
        } catch (ObjectNotFoundException e) {
        }
        assertEquals(null, test.remove(2));
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testRemoveKeyNotFound() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test = new ScalableHashMap();
        dataService.setBinding("test", test);
        Bar bar = new Bar(1);
        dataService.setBinding("bar", bar);
        test.put(bar, 1);
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        dataService.removeObject(dataService.getBinding("bar"));
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertEquals(null, test.remove(new Bar(1)));
        assertEquals(null, test.remove(1));
        assertEquals(null, test.remove(new Bar(2)));
    }
      }, taskOwner);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test =
      (ScalableHashMap) dataService.getBinding("test");
        assertEquals(null, test.remove(new Bar(1)));
        assertEquals(null, test.remove(1));
        assertEquals(null, test.remove(new Bar(2)));
    }
      }, taskOwner);
    }

    /*
     * Test clear
     */

    @Test public void testClear() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] inputs = new int[50];

        for (int i = 0; i < inputs.length; i++) {
      int j = RANDOM.nextInt();
      inputs[i] = j;
      test.put(j,j);
      control.put(j,j);
        }
        assertEquals(control, test);

        DoneRemoving.init();
        test.clear();
        control.clear();

        /*
         * XXX: Test that clear does not change the minimum depth.
         * -tjb@sun.com (10/04/2007)
         */

        assertEquals(control, test);
    }
      }, taskOwner);
  DoneRemoving.await(1);
    }

    @SuppressWarnings("unchecked")
    @Test public void testMultipleClearOperations() throws Exception {
  final Map<Integer,Integer> control = new HashMap<Integer,Integer>();
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        DoneRemoving.init();
        test.clear();
        assertEquals(control, test);

        dataService.setBinding("test", test);
        }
      }, taskOwner);
  DoneRemoving.await(1);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      uncheckedCast(dataService.getBinding("test"));
        // add just a few elements
        for (int i = 0; i < 33; i++) {
      int j = RANDOM.nextInt();
      test.put(j,j);
        }

        test.clear();
        assertEquals(control, test);
    }
      }, taskOwner);
  DoneRemoving.await(1);
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      uncheckedCast(dataService.getBinding("test"));

        // add just enough elements to force a split
        for (int i = 0; i < 1024; i++) {
      int j = RANDOM.nextInt();
      test.put(j,j);
        }

        test.clear();
        assertEquals(control, test);
    }
      }, taskOwner);
  DoneRemoving.await(1);
    }

    /*
     * Miscellaneous tests
     */

    @Test public void testPutAndGetOnSingleLeaf() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        for (int count = 0; count < 64; ++count) {
      int i = RANDOM.nextInt();
      test.put(i, i);
      test.put(~i, ~i);
      control.put(i,i);
      control.put(~i, ~i);
      assertEquals(control, test);
        }
    }
      }, taskOwner);
    }

    @Test public void testPutAndGetOnSplitTree() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        for (int count = 0; count < 32; ++count) {
      int i = RANDOM.nextInt();
      test.put(i, i);
      control.put(i,i);
      assertEquals(control, test);
        }
    }
      }, taskOwner);
    }

    @Test public void testPutAndRemoveSingleLeaf() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        for (int i = 0; i < 54; i++) {
      test.put(i, i);
      test.put(~i, ~i);
      control.put(i, i);
      control.put(~i, ~i);
        }

        for (int i = 0; i < 54; i += 2) {
      test.remove(i);
      control.remove(i);
        }

        assertEquals(control, test);
    }
      }, taskOwner);
    }

    @Test public void testPutAndRemoveLopsidedPositiveKeys() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        for (int i = 0; i < 128; i++) {
      test.put(i, i);
      control.put(i, i);
        }

        assertEquals(control, test);

        for (int i = 0; i < 128; i += 2) {
      test.remove(i);
      control.remove(i);
        }

        assertEquals(control, test);
    }
      }, taskOwner);
    }

    @Test public void testPutAndRemoveLopsidedNegativeKeys() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        for (int i = 0; i < 128; i++) {
      test.put(-i, i);
      control.put(-i, i);
        }

        assertEquals(control, test);

        for (int i = 0; i < 128; i += 2) {
      test.remove(-i);
      control.remove(-i);
        }

        assertEquals(control, test);
    }
      }, taskOwner);
    }

    @Test public void testPutAndRemoveDoublyLopsided() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        for (int i = 0; i < 96; i++) {
      test.put(i, i);
      test.put(-i, -i);
      control.put(i, i);
      control.put(-i, -i);
        }

        assertEquals(control, test);

        for (int i = 0; i < 127; i += 2) {
      assertEquals(control.remove(i), test.remove(i));
        }

        assertEquals(control, test);
    }
      }, taskOwner);
    }

    @Test public void testPutAndRemoveHalfRandomKeys() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        Map<Integer,Integer> control =
      new LinkedHashMap<Integer,Integer>();

        int[] vals = new int[128];

        for (int i = 0; i < 128; i++) {
      int j = (i < 64) ? -RANDOM.nextInt() : RANDOM.nextInt();
      vals[i] = j;
      test.put(j, i);
      control.put(j, i);
        }

        assertEquals(control, test);

        for (int i = 0; i < 128; i += 2) {
      test.remove(vals[i]);
      control.remove(vals[i]);
        }

        assertEquals(control, test);
    }
      }, taskOwner);
    }

    @Test public void testPutAndRemoveHalfNegativeKeys() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        Map<Integer,Integer> control =
      new LinkedHashMap<Integer,Integer>();

        for (int i = 0; i < 128; i++) {
      test.put(-i, -i);
      control.put(-i, -i);
        }

        assertEquals(control, test);

        for (int i = 0; i < 128; i += 2) {
      test.remove(-i);
      control.remove(-i);
        }

        assertEquals(control, test);
    }
      }, taskOwner);
    }

    @Test public void testPutAndRemoveOnSplitTree0() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] a = new int[12];

        for (int i = 0; i < 12; i++) {
      int j = RANDOM.nextInt();
      a[i] = j;
      test.put(j, i);
      control.put(j, i);
        }

        assertEquals(control, test);
        checkLeafRefs(test);

        for (int i = 0; i < 12; i += 2) {
      test.remove(a[i]);
      control.remove(a[i]);
        }

        for (int i = 0; i < 6; i += 2) {
      test.get(a[i]);
        }

        for (int i = 1; i < 6; i += 2) {
      test.get(a[i]);
        }

        assertEquals(control, test);

        for (Integer k : control.keySet()) {
      assertTrue(test.containsKey(k));
      assertTrue(test.containsValue(control.get(k)));
        }

        for (Integer k : test.keySet()) {
      assertTrue(control.containsKey(k));
      assertTrue(control.containsValue(test.get(k)));
        }

        assertEquals(control, test);
        checkLeafRefs(test);
    }
      }, taskOwner);
    }

    @Test public void testPutAndRemoveOnSplitTree() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        for (int i = 0; i < 24; i++) {
      test.put(i, i);
      test.put(~i, ~i);
      control.put(i,i);
      control.put(~i, ~i);
        }

        for (int i = 0; i < 24; i += 2) {
      test.remove(i);
      control.remove(i);
        }

        assertEquals(control, test);
        checkLeafRefs(test);
    }
      }, taskOwner);
    }

    @Test public void testPutAndRemoveOnNoMergeTreeWithNoCollapse()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      createScalableHashMap(Integer.class, Integer.class,
                1, 8, 2);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] inputs = new int[1024];

        for (int i = 0; i < inputs.length; i++) {
      int j = RANDOM.nextInt();
      inputs[i] = j;
      test.put(j,j);
      control.put(j,j);
        }

        for (int i = 0; i < inputs.length; i += 2) {
      test.remove(inputs[i]);
      control.remove(inputs[i]);
        }

        assertEquals(control, test);
    }
      }, taskOwner);
    }

    @Test public void testPutAndRemoveOnNoMergeTreeWithCollapse()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      createScalableHashMap(Integer.class, Integer.class,
                1, 8, 4);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] inputs = new int[1024];

        for (int i = 0; i < inputs.length; i++) {
      int j = RANDOM.nextInt();
      inputs[i] = j;
      test.put(j,j);
      control.put(j,j);
        }

        for (int i = 0; i < inputs.length; i += 2) {
      test.remove(inputs[i]);
      control.remove(inputs[i]);
        }

        assertEquals(control, test);
    }
      }, taskOwner);
    }

    @Test public void testRepeatedPutAndRemove() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(1);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] inputs = new int[400];

        for (int i = 0; i < inputs.length; i++) {
      int j = RANDOM.nextInt();
      inputs[i] = j;
      test.put(j,j);
      control.put(j,j);
        }
        assertEquals(control, test);

        for (int i = 0; i < inputs.length; i += 4) {
      test.remove(inputs[i]);
      control.remove(inputs[i]);
        }
        assertEquals(control, test);

        for (int i = 0; i < inputs.length; i += 3) {
      test.put(inputs[i],inputs[i]);
      control.put(inputs[i],inputs[i]);
        }
        assertEquals(control, test);

        for (int i = 0; i < inputs.length; i += 2) {
      test.remove(inputs[i]);
      control.remove(inputs[i]);
        }

        assertEquals(control, test);
    }
      }, taskOwner);
    }

    @Test public void testRepeatedPutAndRemoveWithNoMergeAndNoCollapse()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      createScalableHashMap(Integer.class, Integer.class,
                1,32, 2);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] inputs = new int[1024];

        for (int i = 0; i < inputs.length; i++) {
      int j = RANDOM.nextInt();
      inputs[i] = j;
      test.put(j,j);
      control.put(j,j);
        }

        checkEquals(control, test);
        assertEquals(control, test);

        for (int i = 0; i < inputs.length; i += 4) {
      test.remove(inputs[i]);
      control.remove(inputs[i]);
        }

        checkEquals(control, test);
        assertEquals(control, test);

        for (int i = 0; i < inputs.length; i += 3) {
      test.put(inputs[i],inputs[i]);
      control.put(inputs[i],inputs[i]);
        }

        checkEquals(control, test);
        assertEquals(control, test);

        for (int i = 0; i < inputs.length; i += 2) {
      test.remove(inputs[i]);
      control.remove(inputs[i]);
        }

        assertEquals(control, test);
    }
      }, taskOwner);
    }

    @Test public void testRepeatedPutAndRemoveWithNoMergeAndCollapse()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      createScalableHashMap(Integer.class, Integer.class,
                1,32,4);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] inputs = new int[400];

        for (int i = 0; i < inputs.length; i++) {
      int j = RANDOM.nextInt();
      inputs[i] = j;
      test.put(j,j);
      control.put(j,j);
        }

        assertEquals(control, test);

        for (int i = 0; i < inputs.length; i += 4) {
      test.remove(inputs[i]);
      control.remove(inputs[i]);
        }
        assertEquals(control, test);

        for (int i = 0; i < inputs.length; i += 3) {
      test.put(inputs[i],inputs[i]);
      control.put(inputs[i],inputs[i]);
        }
        assertEquals(control, test);


        for (int i = 0; i < inputs.length; i += 2) {
      test.remove(inputs[i]);
      control.remove(inputs[i]);
        }

        assertEquals(control, test);
    }
      }, taskOwner);
    }

    @Test public void testPutAndRemoveOnSplitTree5() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] inputs = new int[50];

        for (int i = 0; i < inputs.length; i++)
      inputs[i] = RANDOM.nextInt();

        for (int i = 0; i < inputs.length; i++)  {
      int j = RANDOM.nextInt(inputs.length);
      test.put(inputs[j], inputs[j]);
      control.put(inputs[j], inputs[j]);
      assertEquals(control, test);
      checkLeafRefs(test);

      int k = RANDOM.nextInt(inputs.length);
      test.remove(inputs[k]);
      control.remove(inputs[k]);
      assertEquals(control, test);
      checkLeafRefs(test);

      int m = RANDOM.nextInt(inputs.length);
      test.put(inputs[m], inputs[m]);
      control.put(inputs[m], inputs[m]);
      assertEquals(control, test);
      checkLeafRefs(test);
        }
    }
      }, taskOwner);
    }

    @Test public void testInvalidGet() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();

        // put in numbers
        for (int i = 4000; i < 4100; i++) {
      test.put(i, i);
        }

        // get from outside the range of the put
        for (int i = 0; i < 100; i++) {
      assertEquals(null,test.get(i));
        }
    }
      }, taskOwner);
    }

    /*
     * Test size
     */

    @Test public void testLeafSize() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();

        assertEquals(0, test.size());
        assertTrue(test.isEmpty());

        for (int i = 0; i < 128; i++) {
      test.put(i, i);
        }

        assertEquals(128, test.size());
        assertFalse(test.isEmpty());

        // remove the evens
        for (int i = 0; i < 128; i += 2) {
      test.remove(i);
        }

        assertEquals(64, test.size());
        assertFalse(test.isEmpty());

        // remove the odds
        for (int i = 1; i < 128; i += 2) {
      test.remove(i);
        }

        assertEquals(0, test.size());
        assertTrue(test.isEmpty());
    }
      }, taskOwner);
    }

    @Test public void testLeafSizeAfterRemove() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();

        int SAMPLE_SIZE = 10;

        int[] inputs1 = new int[SAMPLE_SIZE];
        int[] inputs2 = new int[SAMPLE_SIZE];
        int[] inputs3 = new int[SAMPLE_SIZE];

        for (int i = 0; i < inputs1.length; i++) {
      inputs1[i] = RANDOM.nextInt();
      inputs2[i] = RANDOM.nextInt();
      inputs3[i] = RANDOM.nextInt();
        }

        for (int i = 0; i < inputs1.length; i++) {
      test.put(inputs1[i], inputs1[i]);
      test.put(inputs2[i], inputs2[i]);
      assertEquals(test.size(), (i+1)*2);
        }

        for (int i = 0; i < inputs1.length; i++) {
      int beforeSize = test.size();
      test.put(inputs3[i], inputs3[i]);
      test.remove(inputs2[i]);
      assertEquals(beforeSize, test.size());
        }
    }
      }, taskOwner);
    }

    @Test public void testTreeSizeOnSplitTree() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        // create a tree with an artificially small leaf size
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);

        assertEquals(0, test.size());

        for (int i = 0; i < 5; i++) {
      test.put(i, i);
        }

        assertEquals(5, test.size());

        for (int i = 5; i < 15; i++) {
      test.put(i,i);
        }

        assertEquals(15, test.size());

        for (int i = 15; i < 31; i++) {
      test.put(i,i);
        }

        assertEquals(31, test.size());
    }
      }, taskOwner);
    }

    @Test public void testTreeSizeOnSplitTreeWithRemovals() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        // create a tree with an artificially small leaf size
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);

        assertEquals(0, test.size());

        int[] inserts = new int[128];
        for (int i = 0; i < inserts.length; i++) {
      inserts[i] = RANDOM.nextInt();
        }

        // add 32
        for (int i = 0; i < 32; i++) {
      test.put(inserts[i], inserts[i]);
        }

        assertEquals(32, test.size());

        // remove 10
        for (int i = 0; i < 10; i++) {
      test.remove(inserts[i]);
        }

        assertEquals(22, test.size());

        // add 32
        for (int i = 32; i < 64; i++) {
      test.put(inserts[i],inserts[i]);
        }

        assertEquals(54, test.size());

        // remove 10
        for (int i = 32; i < 42; i++) {
      test.remove(inserts[i]);
        }

        // add 64
        for (int i = 64; i < 128; i++) {
      test.put(inserts[i],inserts[i]);
        }

        assertEquals(108, test.size());

        // remove 5
        for (int i = 64; i < 69; i++) {
      test.remove(inserts[i]);
        }
        assertEquals(103, test.size());
    }
      }, taskOwner);
    }

    /*
     * Test iterators
     */

    @Test public void testIteratorRemove() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Foo> test = new ScalableHashMap<Integer,Foo>();
        Set<Integer> keys = test.keySet();
        Iterator<Integer> keysIter = keys.iterator();
        try {
      keysIter.remove();
      fail("Expected IllegalStateException");
        } catch (IllegalStateException e) {
        }
        try {
      keysIter.next();
      fail("Expected NoSuchElementException");
        } catch (NoSuchElementException e) {
        }
        try {
      keysIter.remove();
      fail("Expected IllegalStateException");
        } catch (IllegalStateException e) {
        }
        test.put(1, new Foo(1));
        test.put(2, new Foo(2));
        keysIter = keys.iterator();
        assertEquals(new Integer(1), keysIter.next());
        keysIter.remove();
        assertEquals(1, test.size());
        assertTrue(test.containsKey(2));
        try {
      keysIter.remove();
      fail("Expected IllegalStateException");
        } catch (IllegalStateException e) {
        }
        assertEquals(new Integer(2), keysIter.next());
        keysIter.remove();
        assertTrue(test.isEmpty());
        try {
      keysIter.remove();
      fail("Expected IllegalStateException");
        } catch (IllegalStateException e) {
        }
        assertIteratorDone(keysIter);
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testIteratorNotFound() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap test = new ScalableHashMap();
        dataService.setBinding("test", test);
        Bar bar = new Bar(1);
        dataService.setBinding("bar", bar);
        test.put(1, bar);
        test.put(2, new Bar(2));
    }
      }, taskOwner);
  for (int i = 0; i < 2; i++) {
      final int local = i;
      txnScheduler.runTask(
          new TestAbstractKernelRunnable() {
        public void run() throws Exception {
      ScalableHashMap test =
          (ScalableHashMap) dataService.getBinding("test");
      dataService.setBinding("valuesIter",
          new ManagedSerializable(test.values().iterator()));
        }
    }, taskOwner);
      txnScheduler.runTask(
          new TestAbstractKernelRunnable() {
        public void run() throws Exception {
      if (local == 0) {
          dataService.removeObject(
        dataService.getBinding("bar"));
      }
      ManagedSerializable<Iterator> ms = uncheckedCast(
          dataService.getBinding("valuesIter"));
      dataService.markForUpdate(ms);
      Iterator valuesIter = ms.get();
      int count = 0;
      while (valuesIter.hasNext()) {
          count++;
          try {
        assertEquals(new Bar(2), valuesIter.next());
          } catch (ObjectNotFoundException e) {
          }
      }
      assertEquals(2, count);
        }
    }, taskOwner);
  }
    }

    @Test public void testIteratorOnSplitTree() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Set<Integer> control = new HashSet<Integer>();

        // get from outside the range of the put
        for (int i = 0; i < 33; i++) {
      int j = RANDOM.nextInt();
      test.put(j,j);
      control.add(j);
        }

        for (Integer i : test.keySet()) {
      control.remove(i);
        }

        assertEquals(0, control.size());
    }
      }, taskOwner);
    }

    @Test public void testIteratorOnSplitTreeWithRemovals() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        // create a tree with an artificially small leaf size
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        HashMap<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        assertEquals(0, test.size());

        int[] inserts = new int[128];
        for (int i = 0; i < inserts.length; i++) {
      inserts[i] = RANDOM.nextInt();
        }

        // add 32
        for (int i = 0; i < 32; i++) {
      test.put(inserts[i], inserts[i]);
      control.put(inserts[i], inserts[i]);
        }

        assertEquals(control, test);
        checkLeafRefs(test);

        // remove 10
        for (int i = 0; i < 10; i++) {
      test.remove(inserts[i]);
      control.remove(inserts[i]);
        }

        assertEquals(control, test);
        checkLeafRefs(test);

        // add 32
        for (int i = 32; i < 64; i++) {
      test.put(inserts[i],inserts[i]);
      control.put(inserts[i],inserts[i]);
        }

        assertEquals(control, test);
        checkLeafRefs(test);

        // remove 10
        for (int i = 32; i < 42; i++) {
      test.remove(inserts[i]);
      control.remove(inserts[i]);
        }

        assertEquals(control, test);
        checkLeafRefs(test);

        // add 64
        for (int i = 64; i < 128; i++) {
      test.put(inserts[i],inserts[i]);
      control.put(inserts[i],inserts[i]);
        }

        assertEquals(control, test);
        checkLeafRefs(test);

        // remove 5
        for (int i = 64; i < 69; i++) {
      test.remove(inserts[i]);
      control.remove(inserts[i]);
        }

        assertEquals(control, test);
        checkLeafRefs(test);
    }
      }, taskOwner);
    }

    @Test public void testKeyIterator() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        Set<Integer> control = new HashSet<Integer>();

        // get from outside the range of the put
        for (int i = 0; i < 100; i++) {
      test.put(i,i);
      control.add(i);
        }

        for (Integer i : test.keySet()) {
      control.remove(i);
        }

        assertEquals(0, control.size());
    }
      }, taskOwner);
    }

    @Test public void testKeyIteratorOnSplitMap() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Set<Integer> control = new HashSet<Integer>();

        // get from outside the range of the put
        for (int i = 0; i < 33; i++) {
      test.put(i,i);
      control.add(i);
        }

        for (Integer i : test.keySet()) {
      control.remove(i);
        }

        assertEquals(0, control.size());
    }
      }, taskOwner);
    }

    @Test public void testValuesIterator() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        Set<Integer> control = new HashSet<Integer>();

        // get from outside the range of the put
        for (int i = 0; i < 100; i++) {
      test.put(i,i);
      control.add(i);
        }

        for (Integer i : test.values()) {
      control.remove(i);
        }

        assertEquals(0, control.size());
    }
      }, taskOwner);
    }

    @Test public void testValuesIteratorOnSplitMap() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Set<Integer> control = new HashSet<Integer>();

        // get from outside the range of the put
        for (int i = 0; i < 33; i++) {
      test.put(i,i);
      control.add(i);
        }

        for (Integer i : test.values()) {
      control.remove(i);
        }

        assertEquals(0, control.size());
    }
      }, taskOwner);
    }

    @Test public void testInvalidRemove() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();

        // put in numbers
        for (int i = 4000; i < 4100; i++) {
      test.put(i, i);
        }

        // get from outside the range of the put
        for (int i = 0; i < 100; i++) {
      assertEquals(null, test.remove(i));
        }
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
  @Test public void testLeafSerialization() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>();
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] a = new int[100];

        for (int i = 0; i < a.length; i++) {
      int j = RANDOM.nextInt();
      test.put(j, j);
      control.put(j, j);
      a[i] = j;
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(test);

        byte[] serializedForm = baos.toByteArray();

        ByteArrayInputStream bais =
      new ByteArrayInputStream(serializedForm);
        ObjectInputStream ois = new ObjectInputStream(bais);

        ScalableHashMap<Integer,Integer> m =
      (ScalableHashMap<Integer,Integer>) ois.readObject();

        assertEquals(control, m);
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testSplitTreeSerialization() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] a = new int[100];

        for (int i = 0; i < a.length; i++) {
      int j = RANDOM.nextInt();
      test.put(j, j);
      control.put(j, j);
      a[i] = j;
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(test);

        byte[] serializedForm = baos.toByteArray();

        ByteArrayInputStream bais =
      new ByteArrayInputStream(serializedForm);
        ObjectInputStream ois = new ObjectInputStream(bais);

        ScalableHashMap<Integer,Integer> m =
      (ScalableHashMap<Integer,Integer>) ois.readObject();

        assertEquals(control, m);
    }
      }, taskOwner);
    }

    /*
     * Tests on ManagedObject vs. Serializable object keys
     *
     * These tests should expose any bugs in the ScalableHashMap.PrefixEntry
     * class, especially in the setValue() method.  These should also expose
     * any bugs in the KeyValuePair class
     */

    @Test public void testOnManagedObjectKeys() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Bar,Foo> test = new ScalableHashMap<Bar,Foo>();
        Map<Bar,Foo> control = new HashMap<Bar,Foo>();

        for (int i = 0; i < 64; i++) {
      test.put(new Bar(i), new Foo(i));
      control.put(new Bar(i), new Foo(i));
      assertEquals(control, test);
        }
    }
      }, taskOwner);
    }

    @Test public void testOnManagedObjectValues() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Foo,Bar> test = new ScalableHashMap<Foo,Bar>();
        Map<Foo,Bar> control = new HashMap<Foo,Bar>();

        for (int i = 0; i < 64; i++) {
      test.put(new Foo(i), new Bar(i));
      control.put(new Foo(i), new Bar(i));
      assertEquals(control, test);
        }
    }
      }, taskOwner);
    }

    @Test public void testOnManagedObjectKeysAndValues() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Bar,Bar> test = new ScalableHashMap<Bar,Bar>();
        Map<Bar,Bar> control = new HashMap<Bar,Bar>();

        for (int i = 0; i < 64; i++) {
      test.put(new Bar(i), new Bar(i));
      control.put(new Bar(i), new Bar(i));
      assertEquals(control, test);
        }
    }
      }, taskOwner);
    }

    @Test public void testSerializableKeysReplacedWithManagedObjects()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Foo,Foo> test = new ScalableHashMap<Foo,Foo>();
        Map<Foo,Foo> control = new HashMap<Foo,Foo>();

        for (int i = 0; i < 64; i++) {
      test.put(new Foo(i), new Foo(i));
      control.put(new Foo(i), new Foo(i));
      assertEquals(control, test);
        }

        for (int i = 0; i < 64; i++) {
      test.put(new Bar(i), new Foo(i));
      control.put(new Bar(i), new Foo(i));
      assertEquals(control, test);
        }
    }
      }, taskOwner);     
    }

    @Test public void testSerializableValuesReplacedWithManagedObjects()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        Map<Foo,Foo> test = new ScalableHashMap<Foo,Foo>();
        Map<Foo,Foo> control = new HashMap<Foo,Foo>();

        for (int i = 0; i < 64; i++) {
      test.put(new Foo(i), new Foo(i));
      control.put(new Foo(i), new Foo(i));
      assertEquals(control, test);
        }

        for (int i = 0; i < 64; i++) {
      test.put(new Foo(i), new Bar(i));
      control.put(new Foo(i), new Bar(i));
      assertEquals(control, test);
        }
    }
      }, taskOwner);
    }

    /*
     * Concurrent Iterator tests
     *
     * These tests should expose any problems when the
     * ScalableHashMap.ConcurrentIterator class is serialized and modifications
     * are made to the map before it is deserialized.  This should simulate the
     * conditions between transactions where the map might be modified
     */

    @SuppressWarnings("unchecked")
    @Test public void testConcurrentIterator() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] a = new int[128];

        for (int i = 0; i < a.length; i++) {
      int j = RANDOM.nextInt();
      test.put(j, j);
      control.put(j, j);
      a[i] = j;
        }

        Set<Map.Entry<Integer,Integer>> entrySet =
      control.entrySet();
        int entries = 0;

        for (Iterator<Map.Entry<Integer,Integer>> it =
           test.entrySet().iterator();
       it.hasNext(); ) {

      Map.Entry<Integer,Integer> e = it.next();
      assertTrue(entrySet.contains(e));
      entries++;
        }
        assertEquals(entrySet.size(), entries);
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testConcurrentIteratorSerialization() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] a = new int[256];

        for (int i = 0; i < a.length; i++) {
      int j = RANDOM.nextInt();
      test.put(j, j);
      control.put(j, j);
      a[i] = j;
        }

        Set<Map.Entry<Integer,Integer>> entrySet =
      control.entrySet();
        int entries = 0;

        Iterator<Map.Entry<Integer,Integer>> it =
      test.entrySet().iterator();
        for (int i = 0; i < a.length / 2; i++) {
      Map.Entry<Integer,Integer> e = it.next();
      assertTrue(entrySet.contains(e));
      entries++;
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(it);

        byte[] serializedForm = baos.toByteArray();

        ByteArrayInputStream bais =
      new ByteArrayInputStream(serializedForm);
        ObjectInputStream ois = new ObjectInputStream(bais);

        it = (Iterator<Map.Entry<Integer,Integer>>)
      ois.readObject();

        while(it.hasNext()) {
      Map.Entry<Integer,Integer> e = it.next();
      assertTrue(entrySet.contains(e));
      entries++;
        }

        assertEquals(entrySet.size(), entries);
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testConcurrentIteratorWithRemovals() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] a = new int[1024];

        for (int i = 0; i < a.length; i++) {
      int j = RANDOM.nextInt();
      test.put(j, j);
      control.put(j, j);
      a[i] = j;
        }

        Set<Map.Entry<Integer,Integer>> entrySet =
      control.entrySet();
        int entries = 0;

        Iterator<Map.Entry<Integer,Integer>> it =
      test.entrySet().iterator();

        // serialize the iterator
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(it);

        // then remove half of the entries
        for (int i = 0; i < a.length; i += 2) {
      test.remove(a[i]);
      control.remove(a[i]);
        }

        byte[] serializedForm = baos.toByteArray();

        ByteArrayInputStream bais =
      new ByteArrayInputStream(serializedForm);
        ObjectInputStream ois = new ObjectInputStream(bais);

        it = (Iterator<Map.Entry<Integer,Integer>>)
      ois.readObject();

        // ensure that the deserialized iterator reads the
        // remaining elements
        while(it.hasNext()) {
      Map.Entry<Integer,Integer> e = it.next();
      e.getKey();
      assertTrue(entrySet.contains(e));
      entries++;
        }

        assertEquals(entrySet.size(), entries);
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testConcurrentIteratorWithAdditions() throws Exception {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        // immediately get the iterator while the map size is zero
        Iterator<Map.Entry<Integer,Integer>> it =
      test.entrySet().iterator();

        // serialize the iterator
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(it);

        int[] a = new int[128];

        for (int i = 0; i < a.length; i++) {
      int j = RANDOM.nextInt();
      test.put(j, j);
      control.put(j, j);
      a[i] = j;
        }

        Set<Map.Entry<Integer,Integer>> entrySet =
      control.entrySet();
        int entries = 0;

        byte[] serializedForm = baos.toByteArray();

        ByteArrayInputStream bais =
      new ByteArrayInputStream(serializedForm);
        ObjectInputStream ois = new ObjectInputStream(bais);

        it = (Iterator<Map.Entry<Integer,Integer>>)
      ois.readObject();

        // ensure that the deserialized iterator reads all of
        // the new elements
        while(it.hasNext()) {
      Map.Entry<Integer,Integer> e = it.next();
      assertTrue(entrySet.contains(e));
      entries++;
        }

        assertEquals(entrySet.size(), entries);
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testConcurrentIteratorWithReplacements()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Integer,Integer> test =
      new ScalableHashMap<Integer,Integer>(16);
        Map<Integer,Integer> control =
      new HashMap<Integer,Integer>();

        int[] a = new int[128];

        for (int i = 0; i < a.length; i++) {
      int j = RANDOM.nextInt();
      test.put(j, j);
      control.put(j, j);
      a[i] = j;
        }

        Set<Map.Entry<Integer,Integer>> entrySet =
      control.entrySet();
        int entries = 0;

        Iterator<Map.Entry<Integer,Integer>> it =
      test.entrySet().iterator();
        for (int i = 0; i < a.length / 2; i++) {
      Map.Entry<Integer,Integer> e = it.next();
      assertTrue(entrySet.contains(e));
      entries++;
        }

        assertEquals(a.length / 2, entries);

        // serialize the iterator
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(it);

        // now replace all the elements in the map
        DoneRemoving.init();
        test.clear();
        control.clear();
        for (int i = 0; i < a.length; i++) {
      int j = RANDOM.nextInt();
      test.put(j, j);
      control.put(j, j);
      a[i] = j;
        }

        // reserialize the iterator
        byte[] serializedForm = baos.toByteArray();

        ByteArrayInputStream bais =
      new ByteArrayInputStream(serializedForm);
        ObjectInputStream ois = new ObjectInputStream(bais);

        it = (Iterator<Map.Entry<Integer,Integer>>)
      ois.readObject();

        while(it.hasNext()) {
      Map.Entry<Integer,Integer> e = it.next();
      assertTrue(entrySet.contains(e));
      entries++;
        }

        // due to the random nature of the entries, we can't check
        // that it read in another half other elements.  However
        // this should still check that no execptions were thrown.
    }
      }, taskOwner);
  DoneRemoving.await(1);
    }

    /*
     * Tests on concurrent iterator edge cases
     */

    @SuppressWarnings("unchecked")
    @Test public void testConcurrentIteratorSerializationEqualHashCodes()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Equals,Integer> test =
      new ScalableHashMap<Equals,Integer>(16);
        Map<Equals,Integer> control =
      new HashMap<Equals,Integer>();

        int[] a = new int[256];

        for (int i = 0; i < a.length; i++) {
      int j = RANDOM.nextInt();
      test.put(new Equals(j), j);
      control.put(new Equals(j), j);
      a[i] = j;
        }

        Iterator<Map.Entry<Equals,Integer>> it =
      test.entrySet().iterator();
        for (int i = 0; i < a.length / 2; i++) {
      Map.Entry<Equals,Integer> e = it.next();
      assertTrue(control.remove(e.getKey()) != null);
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(it);

        byte[] serializedForm = baos.toByteArray();

        ByteArrayInputStream bais =
      new ByteArrayInputStream(serializedForm);
        ObjectInputStream ois = new ObjectInputStream(bais);

        it = (Iterator<Map.Entry<Equals,Integer>>)
      ois.readObject();

        while(it.hasNext()) {
      Map.Entry<Equals,Integer> e = it.next();
      assertTrue(control.remove(e.getKey()) != null);
        }

        assertEquals(0, control.size());
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testConcurrentIteratorWithRemovalsEqualHashCodes()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Equals,Integer> test =
      new ScalableHashMap<Equals,Integer>(16);
        Map<Equals,Integer> control = new HashMap<Equals,Integer>();

        int[] a = new int[128];

        for (int i = 0; i < a.length; i++) {
      int j = RANDOM.nextInt();
      test.put(new Equals(j), j);
      control.put(new Equals(j), j);
      a[i] = j;
        }

        Set<Map.Entry<Equals,Integer>> entrySet =
      control.entrySet();
        int entries = 0;

        Iterator<Map.Entry<Equals,Integer>> it =
      test.entrySet().iterator();

        // serialize the iterator
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(it);

        // then remove half of the entries
        for (int i = 0; i < a.length; i += 2) {
      test.remove(a[i]);
      control.remove(a[i]);
        }

        byte[] serializedForm = baos.toByteArray();

        ByteArrayInputStream bais =
      new ByteArrayInputStream(serializedForm);
        ObjectInputStream ois = new ObjectInputStream(bais);

        it = (Iterator<Map.Entry<Equals,Integer>>) ois.readObject();

        // ensure that the deserialized iterator reads the
        // remaining elements
        while(it.hasNext()) {
      Map.Entry<Equals,Integer> e = it.next();
      assertTrue(entrySet.contains(e));
      entries++;
        }

        assertEquals(entrySet.size(), entries);
    }
      }, taskOwner);
    }

    @SuppressWarnings("unchecked")
    @Test public void testConcurrentIteratorWithAdditionsEqualHashCodes()
  throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Equals,Integer> test =
      new ScalableHashMap<Equals,Integer>(16);
        Map<Equals,Integer> control = new HashMap<Equals,Integer>();

        // immediately get the iterator while the map size is zero
        Iterator<Map.Entry<Equals,Integer>> it =
      test.entrySet().iterator();

        // serialize the iterator
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(it);

        int[] a = new int[128];

        for (int i = 0; i < a.length; i++) {
      int j = RANDOM.nextInt();
      test.put(new Equals(j), j);
      control.put(new Equals(j), j);
      a[i] = j;
        }

        int entries = 0;

        byte[] serializedForm = baos.toByteArray();

        ByteArrayInputStream bais =
      new ByteArrayInputStream(serializedForm);
        ObjectInputStream ois = new ObjectInputStream(bais);

        it = (Iterator<Map.Entry<Equals,Integer>>) ois.readObject();

        // ensure that the deserialized iterator reads all of
        // the new elements
        while(it.hasNext()) {
      Map.Entry<Equals,Integer> e = it.next();
      control.remove(e.getKey());
        }

        assertEquals(0, control.size());
    }
      }, taskOwner);
    }

     @SuppressWarnings("unchecked")
     @Test public void testConcurrentIteratorWithReplacementsOnEqualHashCodes()
   throws Exception
    {
  txnScheduler.runTask(
      new TestAbstractKernelRunnable() {
    public void run() throws Exception {
        ScalableHashMap<Equals,Integer> test =
      new ScalableHashMap<Equals,Integer>(16);
        Map<Equals,Integer> control = new HashMap<Equals,Integer>();

        int[] a = new int[128];

        for (int i = 0; i < a.length; i++) {
      int j = RANDOM.nextInt();
      test.put(new Equals(j), j);
      control.put(new Equals(j), j);
      a[i] = j;
        }

        Set<Map.Entry<Equals,Integer>> entrySet =
      control.entrySet();
        int entries = 0;

        Iterator<Map.Entry<Equals,Integer>> it =
      test.entrySet().iterator();
        for (int i = 0; i < a.length / 2; i++) {
      Map.Entry<Equals,Integer> e = it.next();
      assertTrue(entrySet.contains(e));
      entries++;
        }

        assertEquals(a.length / 2, entries);

        // serialize the iterator
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(it);

        // now replace all the elements in the map
        DoneRemoving.init();
        test.clear();
        control.clear();

        for (int i = 0; i < a.length; i++) {
      int j = RANDOM.nextInt();
      test.put(new Equals(j), j);
      control.put(new Equals(j), j);
      a[i] = j;
        }

        assertEquals(control.size(), test.size());

        // reserialize the iterator
        byte[] serializedForm = baos.toByteArray();

        ByteArrayInputStream bais =
      new ByteArrayInputStream(serializedForm);
        ObjectInputStream ois = new ObjectInputStream(bais);

        it = (Iterator<Map.Entry<Equals,Integer>>) ois.readObject();

        while (it.hasNext()) {
      Map.Entry<Equals,Integer> e = it.next();
      assertTrue(entrySet.contains(e));
      entries++;
        }

        // due to the random nature of the entries, we can't check
        // that it read in another half other elements.  However
        // this should still check that no exceptions were thrown.
    }
      }, taskOwner);
  DoneRemoving.await(1);
    }

    /*
     * Utility routines.
     */

    public boolean checkEquals(Map<Integer,Integer> m1,
             Map<Integer,Integer> m2) {

  if (m1.size() != m2.size()) {
      System.out.printf("sizes not equal: %d != %d\n",
            m1.size(), m2.size());
      return false;
  }

  Iterator<Entry<Integer,Integer>> i = m1.entrySet().iterator();
  while (i.hasNext()) {
      Entry<Integer,Integer> e = i.next();
      Integer key = e.getKey();
      Integer value = e.getValue();
      if (value == null) {
    if (!(m2.get(key)==null && m2.containsKey(key))) {
        System.out.printf("keys not equal, m2 has key: %s? %s\n",
              key, m2.containsKey(key));
        return false;
    }
      } else {
    if (!value.equals(m2.get(key))) {
        System.out.printf("m1.get(%s) not equal: %s: %s\n",
              key, value, m2.get(key));
        System.out.println("m2.containsKey() ? " +
               m2.containsKey(key));
        return false;
    }
      }
  }

  return true;
    }

    /**
     * Constructs an empty {@code ScalableHashMap} by calling the private
     * constructor to supply additional parameters.
     */
    @SuppressWarnings("unchecked")
    private static <K,V> ScalableHashMap<K,V> createScalableHashMap(
  Class<K> keyClass, Class<V> valueClass,
  int minConcurrency, int splitThreshold, int directorySize)
    {
  int minDepth = findMinDepthFor(minConcurrency);
  try {
      return (ScalableHashMap<K,V>)
    scalableHashMapConstructor.newInstance(
        0, minDepth, splitThreshold, directorySize);
  } catch (InvocationTargetException e) {
      throw (RuntimeException) e.getCause();
  } catch (Exception e) {
      throw new RuntimeException("Unexpected exception: " + e, e);
  }
    }

    /**
     * Returns the minimum depth of the tree necessary to support the requested
     * minimum number of concurrent write operations.
     */
    private static int findMinDepthFor(int minConcurrency) {
  try {
      return (Integer) findMinDepthFor.invoke(null, minConcurrency);
  } catch (InvocationTargetException e) {
      throw (RuntimeException) e.getCause();
  } catch (Exception e) {
      throw new RuntimeException("Unexpected exception: " + e, e);
  }
    }

    /**
     * Returns the minimum depth for any leaf node in the map's backing tree.
     * The root node has a depth of 1.
     */
    private int getMinTreeDepth(ScalableHashMap map) {
  try {
      return (Integer) getMinTreeDepth.invoke(map);
  } catch (Exception e) {
      throw new RuntimeException("Unexpected exception: " + e, e);
  }
    }

    /**
     * Returns the maximum depth for any leaf node in the map's backing tree.
     * The root node has a depth of 1.
     */
    private int getMaxTreeDepth(ScalableHashMap map) {
  try {
      return (Integer) getMaxTreeDepth.invoke(map);
  } catch (Exception e) {
      throw new RuntimeException("Unexpected exception: " + e, e);
  }
    }

    /**
     * Returns the average of all depth for the leaf nodes in the map's backing
     * tree.  The root node has a depth of 1.
     */
    private double getAvgTreeDepth(ScalableHashMap map) {
  try {
      return (Integer) getAvgTreeDepth.invoke(map);
  } catch (Exception e) {
      throw new RuntimeException("Unexpected exception: " + e, e);
  }
    }

    /**
     * Verifies the state of the doubly linked list of the map's leaf nodes.
     */
    private void checkLeafRefs(ScalableHashMap map) {
  try {
      checkLeafRefs.invoke(map);
  } catch (Exception e) {
      throw new RuntimeException("Unexpected exception: " + e, e);
  }
    }

    /** Checks that the iterator has no more entries. */
    private static void assertIteratorDone(Iterator<?> iterator) {
  assertFalse(iterator.hasNext());
  try {
      iterator.next();
      fail("Expected NoSuchElementException");
  } catch (NoSuchElementException e) {
  }
    }

    /**
     * Checks that the iterator returns objects equal to the contents of the
     * collection.
     */
    private static void assertIteratorContains(
  Collection<?> contents, Iterator<?> iterator)
    {
  Set<?> set = new HashSet<Object>(contents);
  while (iterator.hasNext()) {
      assertTrue(set.remove(iterator.next()));
  }
  assertTrue(set.isEmpty());
    }

    private static Properties createProps(String appName) throws Exception {
        Properties props = SgsTestNode.getDefaultProperties(appName, null,
                                           SgsTestNode.DummyAppListener.class);
        props.setProperty("com.sun.sgs.txn.timeout", "1000000");
        return props;
    }

    /*
     * Test classes
     */

    /**
     * A serializable object that is equal to objects of the same type with the
     * same value.
     */
    static class Foo implements Serializable {
  private static final long serialVersionUID = 1L;
  private final int i;

  Foo(int i) {
      this.i = i;
  }

  public int hashCode() {
      return i;
  }

  public boolean equals(Object o) {
      return o != null &&
    getClass() == o.getClass() &&
    ((Foo) o).i == i;
  }
    }

    /**
     * A managed object that is equal to objects of the same type with the
     * same value.
     */
    static class Bar extends Foo implements ManagedObject {
  private static final long serialVersionUID = 1L;

  Bar(int i) {
      super(i);
  }
    }

    /**
     * A serializable object that is equal to objects of the same type with the
     * type, but whose hashCode method always returns zero.
     */
    static class Equals extends Foo {
  private static final long serialVersionUID = 1L;

  Equals(int i) {
      super(i);
  }

  public int hashCode() {
      return 0;
  }
    }
}
TOP

Related Classes of com.sun.sgs.test.app.util.TestScalableHashMap$Foo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.