/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.geode.internal.cache;

import static org.apache.geode.cache.Region.SEPARATOR;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;

import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

import org.apache.geode.LogWriter;
import org.apache.geode.cache.CacheWriter;
import org.apache.geode.cache.CacheWriterException;
import org.apache.geode.cache.EntryEvent;
import org.apache.geode.cache.EntryExistsException;
import org.apache.geode.cache.EntryNotFoundException;
import org.apache.geode.cache.PartitionedRegionStorageException;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionDestroyedException;
import org.apache.geode.cache.RegionEvent;
import org.apache.geode.cache30.RegionTestCase;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.logging.internal.log4j.api.LogService;

/**
 * Test for Partitioned Region operations on a single node. Following tests are included:
 * <P>
 * (1) testPut() - Tests the put() functionality for the partitioned region.
 * <p>
 *
 *
 */
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class PartitionedRegionSingleNodeOperationsJUnitTest {
  private static final Logger logger = LogService.getLogger();

  static DistributedSystem sys = null;

  static int var = 1;

  final String val = "string_value";

  LogWriter logWriter = null;

  @Before
  public void setUp() throws Exception {
    logWriter = PartitionedRegionTestHelper.getLogger();
  }

  @After
  public void tearDown() {
    PartitionedRegionTestHelper.closeCache();
  }

  /**
   * This isa test for PartitionedRegion put() operation.
   * <p>
   * Following functionalities are tested:
   * <p>
   * 1) put() on PR with localMaxMemory = 0. PartitionedRegionException expected.
   * <p>
   * 2)test the put() operation and validate that old values are returned in case of PR with scope
   * D_ACK.
   * <p>
   *
   *
   */
  @Test
  public void test000Put() throws Exception {
    String regionname = "testPut";
    int localMaxMemory = 0;
    System.setProperty(PartitionedRegion.RETRY_TIMEOUT_PROPERTY, "20000");
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion(regionname, String.valueOf(localMaxMemory), 0);
    System.setProperty(PartitionedRegion.RETRY_TIMEOUT_PROPERTY,
        Integer.toString(PartitionedRegionHelper.DEFAULT_TOTAL_WAIT_RETRY_ITERATION));
    final String expectedExceptions = PartitionedRegionStorageException.class.getName();
    logger.info("<ExpectedException action=add>" + expectedExceptions + "</ExpectedException>");
    try {
      pr.put(1, val);
      fail(
          "testPut()- The expected PartitionedRegionException was not thrown for localMaxMemory = 0");
    } catch (PartitionedRegionStorageException ex) {
      if (logWriter.fineEnabled()) {
        logWriter.fine(
            "testPut() - Got a correct exception-PartitionedRegionStorageException for localMaxMemory=0 ");
      }
    }
    logger.info("<ExpectedException action=remove>" + expectedExceptions + "</ExpectedException>");

    if (!pr.isDestroyed()) {
      pr.destroyRegion();
    }

    pr = (PartitionedRegion) PartitionedRegionTestHelper.createPartitionedRegion(regionname,
        String.valueOf(400), 0);
    final int maxEntries = 3;
    for (int num = 0; num < maxEntries; num++) {
      final Integer key = num;
      final Object oldVal = pr.put(key, val);
      // Assert a more generic return value here because the bucket has not been allocated yet
      // thus do not know if the value is local or not
      assertTrue(oldVal == null);
      assertEquals(val, pr.get(key));

      final Region.Entry entry = pr.getEntry(key);
      assertNotNull(entry);
      assertEquals(val, entry.getValue());
      assertTrue(pr.containsValue(val));
      if (RegionTestCase.entryIsLocal(entry)) {
        assertEquals("Failed for key " + num, val, pr.put(key, key));
      } else {
        assertEquals("Failed for key " + num, null, pr.put(key, key));
      }
      assertEquals((num + 1) * 2, pr.getCache().getCachePerfStats().getPuts());
    }

    if (!pr.isDestroyed()) {
      pr.destroyRegion();
    }

    pr = (PartitionedRegion) PartitionedRegionTestHelper.createPartitionedRegion(regionname,
        String.valueOf(400), 0);

    for (int num = 0; num < maxEntries; num++) {
      pr.put(num, val);
      Object retval = pr.get(num);
      assertEquals(val, retval);
    }

    for (int num = 0; num < maxEntries; num++) {
      if (RegionTestCase.entryIsLocal(pr.getEntry(num))) {
        assertEquals(val, pr.put(num, val));
      } else {
        assertEquals(null, pr.put(num, val));
      }
    }

    final Object dummyVal = "DummyVal";
    for (int num = 0; num < maxEntries; num++) {
      final Object getObj = pr.get(num);
      final Object oldPut = pr.put(num, dummyVal);
      if (((EntrySnapshot) pr.getEntry(num)).wasInitiallyLocal()) {
        assertEquals("Returned value from put operation is not same as the old value", getObj,
            oldPut);

      } else {
        assertEquals(null, oldPut);
      }
      assertEquals("testPut()- error in putting the value in the Partitioned Region", dummyVal,
          pr.get(num));
    }
  }

  /**
   * This is a test for PartitionedRegion destroy(key) operation.
   *
   */
  @Test
  public void test001Destroy() throws Exception {
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion("testDestroy", String.valueOf(200), 0);

    final String expectedExceptions = EntryNotFoundException.class.getName();
    final String addExpected =
        "<ExpectedException action=add>" + expectedExceptions + "</ExpectedException>";
    final String removeExpected =
        "<ExpectedException action=remove>" + expectedExceptions + "</ExpectedException>";
    logger.info(addExpected);
    for (int num = 0; num < 3; num++) {
      try {
        pr.destroy(num);
        fail(
            "Destroy doesn't throw EntryNotFoundException for the entry which never existed in the system");
      } catch (EntryNotFoundException ignored) {
      }
    }
    logger.info(removeExpected);

    for (int num = 0; num < 3; num++) {
      pr.put(num, val);
      final long initialDestroyCount = getDestroyCount(pr);
      pr.destroy(num);
      assertEquals(initialDestroyCount + 1, getDestroyCount(pr));
    }

    for (int num = 0; num < 3; num++) {
      Object retval = pr.get(num);
      if (retval != null) {
        fail("testDestroy()- entry not destroyed  properly in destroy(key)");
      }
    }

    logger.info(addExpected);
    for (int num = 0; num < 3; num++) {
      try {
        pr.destroy(num);
        fail(
            "Destroy doesn't throw EntryNotFoundException for the entry which is already deleted from the system");
      } catch (EntryNotFoundException ignored) {
      }
    }
    logger.info(removeExpected);

    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testDestroy() Completed successfully ... ");
    }
  }

  private long getDestroyCount(PartitionedRegion pr) {
    return pr.getCache().getCachePerfStats().getDestroys();
  }

  private long getCreateCount(PartitionedRegion pr) {
    return pr.getCache().getCachePerfStats().getCreates();
  }

  /**
   * This is a test for PartitionedRegion get(key) operation.
   *
   */
  @Test
  public void test002Get() throws Exception {
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion("testGet", String.valueOf(200), 0);
    for (int num = 0; num < 3; num++) {
      pr.put(num, val);
      Object retval = pr.get(num);
      if (!val.equals(String.valueOf(retval))) {
        fail("testGet() - get operation failed for Partitioned Region ");
      }
    }
    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testGet() Completed successfully ... ");
    }
  }

  /**
   * This is a test for PartitionedRegion destroyRegion() operation.
   */

  @Test
  public void test003DestroyRegion() throws Exception {
    String regionName = "testDestroyRegion";
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion(regionName, String.valueOf(200), 0);
    pr.put(1, 1);
    pr.get(1);

    if (pr.isDestroyed()) {
      fail(
          "PartitionedRegionSingleNodeOperationsJUnitTest:testDestroyRegion(): Returns true in isDestroyed method, before the region is destroyed");
    }

    logWriter.info("JDEBUG 1");
    pr.destroyRegion();
    logWriter.info("JDEBUG 2");

    // Validate that the meta-data and bucket regions are cleaned.
    assertTrue(pr.isDestroyed());
    // assertTrue(pr.getBucket2Node().isEmpty());

    Region root = PartitionedRegionHelper.getPRRoot(PartitionedRegionTestHelper.createCache());
    // assertNull(PartitionedRegionHelper.getPRConfigRegion(root,
    // PartitionedRegionTestHelper.createCache()).get(regionName));
    for (final Object o : root.subregions(false)) {
      Region rg = (Region) o;
      // System.out.println("Region = " + rg.getName());
      assertEquals(
          rg.getName().indexOf(PartitionedRegionHelper.BUCKET_REGION_PREFIX + pr.getPRId() + "_"),
          -1);
    }

    if (!pr.isDestroyed()) {
      fail("testDestroyRegion(): "
          + "Returns false in isDestroyed method, after the region is destroyed");
    }
    logWriter.info("JDEBUG 3");
    try {
      pr.put(2, 2);
      fail("testdestroyRegion() Expected RegionDestroyedException not thrown");
    } catch (RegionDestroyedException ex) {
      if (logWriter.fineEnabled()) {
        logWriter.fine(
            "testDestroyRegion() got a corect RegionDestroyedException for put() after destroyRegion()");
      }
    }
    logWriter.info("JDEBUG 4");
    try {
      pr.get(2);
      fail("testdestroyRegion() - Expected RegionDestroyedException not thrown");
    } catch (RegionDestroyedException ex) {
      if (logWriter.fineEnabled()) {
        logWriter.fine("PartitionedRegionSingleNodeOperationsJUnitTest - "
            + "testDestroyRegion() got a correct RegionDestroyedException for get() after destroyRegion()");
      }
    }
    logWriter.info("JDEBUG 5");

    try {
      pr.destroy(1);
      fail("testdestroyRegion() Expected RegionDestroyedException not thrown");
    } catch (RegionDestroyedException ex) {
      if (logWriter.fineEnabled()) {
        logWriter.fine("PartitionedRegionSingleNodeOperationsJUnitTest - "
            + "testDestroyRegion() got a correct RegionDestroyedException for destroy() after destroyRegion()");
      }
    }
    logWriter.info("JDEBUG 6");

    pr = (PartitionedRegion) PartitionedRegionTestHelper.createPartitionedRegion(regionName,
        String.valueOf(200), 0);

    if (logWriter.fineEnabled()) {
      logWriter.fine("PartitionedRegionSingleNodeOperationsJUnitTest - testDestroyRegion():"
          + " PartitionedRegion with same name as the destroyed region, can be created.");
    }

    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testDestroyRegion(): Completed Successfully ...");
    }
  }

  /**
   * Tests getCache() API of PR. This should return same value as the cache used.
   *
   */
  @Test
  public void test004GetCache() throws Exception {
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion("testGetCache", String.valueOf(200), 0);

    GemFireCacheImpl ca = (GemFireCacheImpl) pr.getCache();
    if (!PartitionedRegionTestHelper.createCache().equals(ca)) {
      fail("testGetCache() - getCache method is not returning proper cache handle");
    }

    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testGetCache() Completed Successfully");
    }
  }

  /**
   * Tests getFullPath() API of PartitionedRegion.
   *
   */
  @Test
  public void test005GetFullPath() throws Exception {
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion("testGetFullPath", String.valueOf(200), 0);
    String fullPath = pr.getFullPath();
    if (!(SEPARATOR + "testGetFullPath").equals(fullPath)) {
      fail("testGetFullPath() - getFullPath method is not returning proper fullPath");
    }
    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testGetFullPath() Completed Successfully");
    }
  }

  /**
   * Tests getParentRegion() API of PR. This should return null as PR doesnt have a parentRegion
   *
   */
  @Test
  public void test006GetParentRegion() throws Exception {
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion("testGetParentRegion", String.valueOf(200), 0);
    Region parentRegion = pr.getParentRegion();
    if (parentRegion != null) {
      fail("getParentRegion method is not returning null as parent region for a PartitionedRegion");
    }

    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testGetParentRegion() Completed Successfully");
    }
  }

  /**
   * Tests getName() API of PR. Name returned should be same as the one used to create PR.
   *
   */
  @Test
  public void test007GetName() throws Exception {
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion("testGetName", String.valueOf(200), 0);
    String name = pr.getName();
    if (!("testGetName").equals(name)) {
      fail("getName() method is not returning proper region name");
    }

    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testGetName() Completed Successfully");
    }
  }

  /**
   * This method validates containsKey() operations.
   */
  @Test
  public void test008ContainsKey() throws Exception {
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion("testContainsKey", String.valueOf(200), 0);
    for (int num = 0; num < 3; num++) {
      pr.put(num, val);
      boolean retval = pr.containsKey(num);
      if (!retval) {
        fail("PartitionedRegionSingleNodeOperationTest:testContainsKey() operation failed");
      }
    }

    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testContainsKey() Completed successfully ... ");
    }
  }

  /**
   * This method validates containsKey() operations.
   */
  @Test
  public void test009ContainsValueForKey() throws Exception {
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion("testContainsValueForKey", String.valueOf(200), 0);
    for (int num = 0; num < 3; num++) {
      pr.put(num, val);
      boolean retval = pr.containsValueForKey(num);
      if (!retval) {
        fail(
            "PartitionedRegionSingleNodeOperationTest:testContainsValueForKey()  operation failed");
      }
    }
    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testContainsValueForKey() Completed successfully ... ");
    }
  }

  /**
   * Tests close() API of PR. It should close the accessor and delete the data-store and related
   * meta-data information.
   *
   */
  @Test
  public void test010Close() throws Exception {
    logWriter.fine("Getting inside testClose method");
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion("testClose", String.valueOf(200), 0);
    pr.put("K1", "V1");
    pr.get("K1");
    pr.close();
    if (!pr.isClosed || !pr.isDestroyed()) {
      fail("testClose(): After close isClosed = " + pr.isClosed + " and isDestroyed = "
          + pr.isDestroyed());
    }
    try {
      pr.put("K2", "V2");
      fail("testClose(): put operation completed on a closed PartitionedRegion. ");
    } catch (RegionDestroyedException ignored) {
    }
    // validating get operation

    try {
      pr.get("K1");
      fail("testClose(): get operation should not succeed on closed PartitionedRegion. ");
    } catch (RegionDestroyedException expected) {
      // if (logger.fineEnabled()) {
      // logger.fine("Got correct RegionDestroyedException after close() ");
      // }
    }

    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testClose() Completed successfully ... ");
    }
  }

  /**
   * Tests localDestroyRegion() API of PR. It should locallyDestroy the accessor, data store and
   * meta-data.
   *
   */
  @Test
  public void test011LocalDestroyRegion() throws Exception {
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion("testClose", String.valueOf(200), 0);
    pr.put("K1", "V1");
    pr.get("K1");
    pr.localDestroyRegion();
    if (pr.isClosed || !pr.isDestroyed()) {
      fail("testClose(): After close isClosed = " + pr.isClosed + " and isDestroyed = "
          + pr.isDestroyed());
    }
    try {
      pr.put("K2", "V2");
      fail("testClose(): put operation completed on a closed PartitionedRegion. ");
    } catch (RegionDestroyedException ignored) {
    }
    try {
      pr.get("K1");
      fail("testClose(): get operation should not succeed on closed PartitionedRegion. ");
    } catch (RegionDestroyedException expected) {
      if (logWriter.fineEnabled()) {
        logWriter.fine("Got correct RegionDestroyedException after close() ");
      }
    }

    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testClose() Completed successfully ... ");
    }
  }

  /**
   * This method is used to test the isDestroyed() functionality.
   *
   */
  @Test
  public void test012IsDestroyed() throws Exception {
    String regionName = "testIsDestroyed";
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion(regionName, String.valueOf(200), 0);
    pr.put(1, 1);
    pr.get(1);

    if (pr.isDestroyed()) {
      fail(
          "PartitionedRegionSingleNodeOperationsJUnitTest:testIsDestroyed(): Returns true in isDestroyed method, before the region is destroyed");
    }

    pr.destroyRegion();

    if (!pr.isDestroyed()) {
      fail("PartitionedRegionSingleNodeOperationsJUnitTest:testIsDestroyed(): "
          + "Returns false in isDestroyed method, after the region is destroyed");
    }

    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testIsDestroyed() Completed successfully ... ");
    }
  }

  /**
   * This method validates that PR closed behavior matches that of local region closed behavior.
   *
   */
  /*
   * public void xxNoTestValidateCloseFunction() throws Exception { String partitionRegionName =
   * "testValidateCloseFunction"; PartitionedRegion pr =
   * (PartitionedRegion)PartitionedRegionTestHelper .createPartitionedRegion(partitionRegionName,
   * String.valueOf(200), 2, Scope.DISTRIBUTED_ACK); String diRegion = "diRegion";
   *
   * Region distRegion = null;
   *
   * AttributesFactory af = new AttributesFactory(); RegionAttributes regionAttributes; // setting
   * property af.setScope(Scope.DISTRIBUTED_ACK); // creating region attributes regionAttributes =
   * af.create(); try { distRegion = PartitionedRegionTestHelper.createCache().createRegion(
   * diRegion, regionAttributes); } catch (RegionExistsException rex) { distRegion =
   * PartitionedRegionTestHelper.createCache() .getRegion(diRegion); } // Closing the regions
   * distRegion.close(); pr.close();
   *
   * if (!pr.getCache().equals(distRegion.getCache())) {
   * fail("testValidateCloseFunction: getCache is not matching. "); } else { if
   * (logger.fineEnabled()) { logger.fine("getCache() matched on closed PR and distributed region
   * "); } } if (distRegion.getName().length() != pr.getName().length()) {
   * fail("testValidateCloseFunction: getName behavior not matching. "); } else { if
   * (logger.fineEnabled()) { logger.fine("getName) matched on closed PR and distributed region ");
   * } }
   *
   * if (distRegion.getFullPath().length() != pr.getFullPath().length()) {
   * fail("testValidateCloseFunction: getFullPath behavior not matching. "); } else { if
   * (logger.fineEnabled()) { logger .fine("getFullPath) matched on closed PR and distributed region
   * "); } }
   *
   * if (logger.fineEnabled()) { logger .fine("PartitionedRegionSingleNodeOperationsJUnitTest -
   * testValidateCloseFunction() Completed successfully ... "); } }
   */

  // /**
  // * This method is used to test the entrySet method. It verifies that it throws
  // * UnsupportedOperationException.
  // *
  // */
  // public void xxNoTestEntrySet() throws Exception
  // {
  // String regionName = "testEntrySet";
  // PartitionedRegion pr = (PartitionedRegion)PartitionedRegionTestHelper
  // .createPartitionedRegion(regionName, String.valueOf(200), 0,
  // Scope.DISTRIBUTED_ACK);
  //
  // try {
  // Set s = pr.entrySet(true);
  // fail("testEntrySet() does NOT throw UnsupportedOperationException");
  // }
  // catch (UnsupportedOperationException onse) {
  // if (logger.fineEnabled()) {
  // logger
  // .fine("testEntrySet() is correctly throwing UnsupportedOperationException on an empty PR");
  // }
  // }
  //
  // pr.put(new Integer(1), new Integer(1));
  //
  // try {
  // Set s = pr.entrySet(true);
  // fail("testEntrySet() does NOT throw UnsupportedOperationException");
  // }
  // catch (UnsupportedOperationException onse) {
  // if (logger.fineEnabled()) {
  // logger
  // .fine("testEntrySet() is correctly throwing UnsupportedOperationException on a non-empty PR");
  // }
  // }
  //
  // if (logger.fineEnabled()) {
  // logger
  // .fine("PartitionedRegionSingleNodeOperationsJUnitTest - testEntrySet() Completed successfully
  // ... ");
  // }
  // }

  /**
   * Test either the keySet() or keys() methods, which logically are expected to be the same
   */
  private void keysSetTester(Region pr) {
    assertEquals(Collections.EMPTY_SET, pr.keySet());
    pr.put(1, "won");
    pr.put(2, "to");
    pr.put(3, "free");
    pr.put(5, "hive");
    final Set ks = pr.keySet();
    assertEquals(4, ks.size());

    try {
      ks.clear();
      fail("Expected key set to be read only");
    } catch (Exception ignored) {
    }
    try {
      ks.add("foo");
      fail("Expected key set to be read only");
    } catch (Exception ignored) {
    }
    try {
      ks.addAll(Arrays.asList("one", "two", "three"));
      fail("Expected key set to be read only");
    } catch (Exception ignored) {
    }
    try {
      ks.remove("boom");
      fail("Expected key set to be read only");
    } catch (Exception ignored) {
    }
    try {
      ks.removeAll(Arrays.asList(1, 2));
      fail("Expected key set to be read only");
    } catch (Exception ignored) {
    }
    try {
      ks.retainAll(Arrays.asList(3, 5));
      fail("Expected key set to be read only");
    } catch (Exception ignored) {
    }

    final Iterator ksI = ks.iterator();
    for (int i = 0; i < 4; i++) {
      try {
        ksI.remove();
        fail("Expected key set iterator to be read only");
      } catch (Exception ignored) {
      }
      assertTrue(ksI.hasNext());
      Object key = ksI.next();
      assertEquals(Integer.class, key.getClass());
    }
    try {
      ksI.remove();
      fail("Expected key set iterator to be read only");
    } catch (Exception ignored) {
    }
    try {
      ksI.next();
      fail("Expected no such element exception");
    } catch (NoSuchElementException ignored) {
    }
  }

  @Test
  public void test014KeySet() throws Exception {
    String regionName = "testKeysSet";
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion(regionName, String.valueOf(200), 0);
    keysSetTester(pr);
  }

  // /**
  // * This method is used to test the keySet method. It verifies that it throws
  // * UnsupportedOperationException.
  // *
  // */
  // public void xxNoTestKeySet() throws Exception
  // {
  // String regionName = "testKeySet";
  // PartitionedRegion pr = (PartitionedRegion)PartitionedRegionTestHelper
  // .createPartitionedRegion(regionName, String.valueOf(200), 0,
  // Scope.DISTRIBUTED_ACK);
  //
  // try {
  // Set s = pr.keySet();
  // fail("testKeySet() does NOT throw UnsupportedOperationException");
  // }
  // catch (UnsupportedOperationException onse) {
  // if (logger.fineEnabled()) {
  // logger
  // .fine("testKeySet() is correctly throwing UnsupportedOperationException on an empty PR");
  // }
  // }
  //
  // pr.put(new Integer(1), new Integer(1));
  //
  // try {
  // Set s = pr.keySet();
  // fail("testKeySet() does NOT throw UnsupportedOperationException");
  // }
  // catch (UnsupportedOperationException onse) {
  //
  // if (logger.fineEnabled()) {
  // logger
  // .fine("testKeySet() is correctly throwing UnsupportedOperationException on a non-empty PR");
  // }
  // }
  //
  // if (logger.fineEnabled()) {
  // logger
  // .fine("PartitionedRegionSingleNodeOperationsJUnitTest - testKeySet() Completed successfully ...
  // ");
  // }
  // }

  // /**
  // * This method is used to test the putAll method. It verifies that it throws
  // * UnsupportedOperationException.
  // *
  // */
  // public void xxNoTestPutAll() throws Exception
  // {
  // final String rName = "testPutAll";
  // PartitionedRegion pr = (PartitionedRegion)PartitionedRegionTestHelper
  // .createPartitionedRegion(rName, String.valueOf(8), 0,
  // Scope.DISTRIBUTED_ACK);
  // try {
  // assertNotNull(pr);
  // final String foo = "foo";
  // final String bing = "bing";
  // final String supper = "super";
  // HashMap data = new HashMap();
  // data.put(foo, "bar");
  // data.put(bing, "bam");
  // data.put(supper, "hero");
  //
  // assertNull(pr.get(foo));
  // assertNull(pr.get(bing));
  // assertNull(pr.get(supper));
  // try {
  // pr.putAll(data);
  // fail("testPutAll() does NOT throw UnsupportedOperationException");
  // }
  // catch (UnsupportedOperationException onse) {
  // if (logger.fineEnabled()) {
  // logger
  // .fine("testPutall() is correctly throwing UnsupportedOperationException on an empty PR");
  // }
  // }
  // assertNull(pr.get(foo));
  // assertNull(pr.get(bing));
  // assertNull(pr.get(supper));
  // }
  // finally {
  // pr.destroyRegion();
  // }
  // }

  // /**
  // * This method is used to test the values functionality. It verifies that it
  // * throws UnsupportedOperationException.
  // *
  // */
  // public void xxNoTestValues() throws Exception
  // {
  // String regionName = "testValues";
  // PartitionedRegion pr = (PartitionedRegion)PartitionedRegionTestHelper
  // .createPartitionedRegion(regionName, String.valueOf(200), 0,
  // Scope.DISTRIBUTED_ACK);
  // try {
  // Collection c = pr.values();
  // fail("testValues() does NOT throw UnsupportedOperationException");
  // }
  // catch (UnsupportedOperationException onse) {
  // if (logger.fineEnabled()) {
  // logger
  // .fine("testValues() correctly throwing UnsupportedOperationException on an empty PR ");
  // }
  // }
  //
  // pr.put(new Integer(1), new Integer(1));
  //
  // try {
  // Collection c = pr.values();
  // fail("testValues() does NOT throw UnsupportedOperationException");
  // }
  // catch (UnsupportedOperationException onse) {
  //
  // if (logger.fineEnabled()) {
  // logger
  // .fine("testValues() is correctly throwing UnsupportedOperationException on a non-empty PR ");
  // }
  // }
  // if (logger.fineEnabled()) {
  // logger
  // .fine("PartitionedRegionSingleNodeOperationsJUnitTest - testValues() Completed successfully ...
  // ");
  // }
  // }

  // /**
  // * This method validates containsKey operations. It verifies that it throws
  // * UnsupportedOperationException.
  // */
  // public void xxNoTestContainsValue() throws Exception
  // {
  // int key = 0;
  // Region pr = (PartitionedRegion)PartitionedRegionTestHelper
  // .createPartitionedRegion("testContainsValue", String.valueOf(200), 0,
  // Scope.DISTRIBUTED_ACK);
  // for (int num = 0; num < 3; num++) {
  // key++;
  // pr.put(new Integer(key), val);
  // try {
  // boolean retval = pr.containsValue(val);
  // fail("PartitionedRegionSingleNodeOperationTest:testContainsValue() operation failed");
  // }
  // catch (UnsupportedOperationException onse) {
  //
  // if (logger.fineEnabled()) {
  // logger
  // .fine(" testContainsValue is correctly throwing UnsupportedOperationException for value = "
  // + val);
  // }
  // }
  // }
  // if (logger.fineEnabled()) {
  // logger
  // .fine("PartitionedRegionSingleNodeOperationsJUnitTest - testContainsValue() Completed
  // successfully ... ");
  // }
  // }

  /**
   * This method is used to test the setUserAttributes functionality. It verifies that it sets the
   * UserAttributes on an open PR without throwing any exception. It also verifies that it throws
   * RegionDestroyedException on a closed PR.
   *
   */
  @Test
  public void test015SetUserAttributes() throws Exception {
    String regionName = "testSetUserAttributes";
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion(regionName, String.valueOf(200), 0);
    String s = "DUMMY";
    pr.setUserAttribute(s);

    // Close PR
    pr.close();

    try {
      pr.setUserAttribute(s);
      fail(
          "testSetUserAttributes() doesnt throw RegionDestroyedException on a closed PartitionedRegion.");
    } catch (RegionDestroyedException rde) {

      if (logWriter.fineEnabled()) {
        logWriter.fine(
            "testSetUserAttributes(): setUserAttributes() throws RegionDestroyedException on a closed PartitionedRegion. ");
      }
    }

    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testSetUserAttributes() Completed successfully ... ");
    }
  }

  /**
   * This method is used to test the getUserAttributes functionality. It verifies that it gets the
   * UserAttributes on an open PR without throwing any exception. It also verifies that it throws
   * RegionDestroyedException on a closed PR.
   *
   */
  @Test
  public void test016GetUserAttributes() throws Exception {
    String regionName = "testGetUserAttributes";
    PartitionedRegion pr = (PartitionedRegion) PartitionedRegionTestHelper
        .createPartitionedRegion(regionName, String.valueOf(200), 0);

    String s = "DUMMY";
    pr.setUserAttribute(s);
    Object o = pr.getUserAttribute();
    if (!o.equals(s)) {
      fail("testGetUserAttributes() returns null on an open accessor");
    }

    // Close PR
    pr.close();

    assertEquals(s, pr.getUserAttribute());

    if (logWriter.fineEnabled()) {
      logWriter.fine(
          "PartitionedRegionSingleNodeOperationsJUnitTest - testGetUserAttributes() Completed successfully ... ");
    }
  }

  /**
   * This method is used to test the getAttributesMutator functionality. It verifies that it gets
   * the handle for attributes mutator on an open PR without throwing any exception. It also
