/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.extensions; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import org.opends.server.TestCaseUtils; import org.opends.server.api.Backend; import org.opends.server.api.EntryCache; import org.opends.server.core.DirectoryServer; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.opends.server.types.LockType; import org.opends.server.admin.std.server.EntryCacheCfg; import static org.testng.Assert.*; /** * A common set of test cases for all entry cache implementations. */ public abstract class CommonEntryCacheTestCase extends ExtensionsTestCase { /** * Number of unique dummy test entries. * Note that the value affects MAXENTRIES. */ protected int NUMTESTENTRIES = 30; /** * Maximum number of entries the cache can hold. * Note that the value depends on NUMTESTENTRIES. */ protected int MAXENTRIES = 10; /** * Number of loops for each concurrency test. */ protected int CONCURRENCYLOOPS = 1000; /** * Dummy test entries. * Note that this list should contain at least two entry * elements for the following tests to function properly. */ protected ArrayList testEntriesList; /** * Cache implementation instance. */ protected EntryCache cache; /** * Entry cache configuration instance. */ protected EntryCacheCfg configuration; /** * Indicates whether a concurrent test thread should assert * that the cache is empty before executing the actual test. */ private AtomicBoolean cacheEmptyAssert = new AtomicBoolean(); /** * Tests the containsEntry method. * * @throws Exception If an unexpected problem occurs. */ public void testContainsEntry() throws Exception { assertNull(cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + cache.toVerboseString()); TestCaseUtils.initializeTestBackend(false); Backend b = DirectoryServer.getBackend(DN.decode("o=test")); assertFalse(cache.containsEntry(testEntriesList.get(0).getDN()), "Not expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); cache.putEntry(testEntriesList.get(0), b, 1); assertTrue(cache.containsEntry(testEntriesList.get(0).getDN()), "Expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); // Clear the cache so that other tests can start from scratch. cache.clear(); } /** * Tests the first getEntry method, which takes a single DN * argument. * * @throws Exception If an unexpected problem occurs. */ public void testGetEntry1() throws Exception { assertNull(cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + cache.toVerboseString()); TestCaseUtils.initializeTestBackend(false); Backend b = DirectoryServer.getBackend(DN.decode("o=test")); assertNull(cache.getEntry(testEntriesList.get(0).getDN()), "Not expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); cache.putEntry(testEntriesList.get(0), b, 1); assertNotNull(cache.getEntry(testEntriesList.get(0).getDN()), "Expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); // Clear the cache so that other tests can start from scratch. cache.clear(); } /** * Tests the second getEntry method, which takes a DN, lock type, * and list attributes. * * @throws Exception If an unexpected problem occurs. */ @SuppressWarnings("unchecked") public void testGetEntry2() throws Exception { assertNull(cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + cache.toVerboseString()); TestCaseUtils.initializeTestBackend(false); Backend b = DirectoryServer.getBackend(DN.decode("o=test")); assertNull(cache.getEntry(testEntriesList.get(0).getDN(), LockType.NONE, new ArrayList()), "Not expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); cache.putEntry(testEntriesList.get(0), b, 1); assertNotNull(cache.getEntry(testEntriesList.get(0).getDN(), LockType.NONE, new ArrayList()), "Expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); // Clear the cache so that other tests can start from scratch. cache.clear(); } /** * Tests the third getEntry method, which takes a backend, entry * ID, lock type, and list attributes. * * @throws Exception If an unexpected problem occurs. */ @SuppressWarnings("unchecked") public void testGetEntry3() throws Exception { assertNull(cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + cache.toVerboseString()); TestCaseUtils.initializeTestBackend(false); Backend b = DirectoryServer.getBackend(DN.decode("o=test")); assertNull(cache.getEntry(b, -1, LockType.NONE, new ArrayList()), "Not expected to find entry id " + Integer.toString(-1) + " in the cache. Cache contents:\n" + cache.toVerboseString()); cache.putEntry(testEntriesList.get(0), b, 1); assertNotNull(cache.getEntry(b, 1, LockType.NONE, new ArrayList()), "Expected to find entry id " + Integer.toString(1) + " in the cache. Cache contents:\n" + cache.toVerboseString()); // Clear the cache so that other tests can start from scratch. cache.clear(); } /** * Tests the getEntryID method. * * @throws Exception If an unexpected problem occurs. */ public void testGetEntryID() throws Exception { assertNull(cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + cache.toVerboseString()); TestCaseUtils.initializeTestBackend(false); Backend b = DirectoryServer.getBackend(DN.decode("o=test")); assertEquals(cache.getEntryID(testEntriesList.get(0).getDN()), -1, "Not expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); cache.putEntry(testEntriesList.get(0), b, 1); assertEquals(cache.getEntryID(testEntriesList.get(0).getDN()), 1, "Expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); // Clear the cache so that other tests can start from scratch. cache.clear(); } /** * Tests the putEntry method. * * @throws Exception If an unexpected problem occurs. */ public void testPutEntry() throws Exception { assertNull(cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + cache.toVerboseString()); TestCaseUtils.initializeTestBackend(false); Backend b = DirectoryServer.getBackend(DN.decode("o=test")); cache.putEntry(testEntriesList.get(0), b, 1); assertNotNull(cache.getEntry(testEntriesList.get(0).getDN()), "Expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); // Clear the cache so that other tests can start from scratch. cache.clear(); } /** * Tests the putEntryIfAbsent method. * * @throws Exception If an unexpected problem occurs. */ public void testPutEntryIfAbsent() throws Exception { assertNull(cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + cache.toVerboseString()); TestCaseUtils.initializeTestBackend(false); Backend b = DirectoryServer.getBackend(DN.decode("o=test")); assertTrue(cache.putEntryIfAbsent(testEntriesList.get(0), b, 1), "Not expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); assertFalse(cache.putEntryIfAbsent(testEntriesList.get(0), b, 1), "Expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); // Clear the cache so that other tests can start from scratch. cache.clear(); } /** * Tests the removeEntry method. * * @throws Exception If an unexpected problem occurs. */ public void testRemoveEntry() throws Exception { assertNull(cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + cache.toVerboseString()); TestCaseUtils.initializeTestBackend(false); Backend b = DirectoryServer.getBackend(DN.decode("o=test")); cache.removeEntry(testEntriesList.get(0).getDN()); cache.putEntry(testEntriesList.get(0), b, 1); cache.removeEntry(testEntriesList.get(0).getDN()); assertNull(cache.getEntry(testEntriesList.get(0).getDN()), "Not expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); // Clear the cache so that other tests can start from scratch. cache.clear(); } /** * Tests the clear method. * * @throws Exception If an unexpected problem occurs. */ public void testClear() throws Exception { assertNull(cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + cache.toVerboseString()); TestCaseUtils.initializeTestBackend(false); Backend b = DirectoryServer.getBackend(DN.decode("o=test")); cache.clear(); cache.putEntry(testEntriesList.get(0), b, 1); cache.clear(); assertNull(cache.getEntry(testEntriesList.get(0).getDN()), "Not expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); // Clear the cache so that other tests can start from scratch. cache.clear(); } /** * Tests the clearBackend method. * * @throws Exception If an unexpected problem occurs. */ @SuppressWarnings("unchecked") public void testClearBackend() throws Exception { assertNull(cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + cache.toVerboseString()); TestCaseUtils.initializeTestBackend(false); Backend b = DirectoryServer.getBackend(DN.decode("o=test")); Backend c = DirectoryServer.getBackend(DN.decode("cn=config")); cache.clearBackend(b); cache.putEntry(testEntriesList.get(0), b, 1); cache.putEntry(testEntriesList.get(1), c, 1); cache.clearBackend(b); assertNull(cache.getEntry(b, 1, LockType.NONE, new ArrayList()), "Not expected to find entry id " + Integer.toString(1) + " on backend " + b.getBackendID() + " in the cache. Cache contents:\n" + cache.toVerboseString()); assertNotNull(cache.getEntry(c, 1, LockType.NONE, new ArrayList()), "Expected to find entry id " + Integer.toString(1) + " on backend " + c.getBackendID() + " in the cache. Cache contents:\n" + cache.toVerboseString()); // Clear the cache so that other tests can start from scratch. cache.clear(); } /** * Tests the clearSubtree method. * * @throws Exception If an unexpected problem occurs. */ public void testClearSubtree() throws Exception { assertNull(cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + cache.toVerboseString()); TestCaseUtils.initializeTestBackend(false); Backend b = DirectoryServer.getBackend(DN.decode("o=test")); Backend c = DirectoryServer.getBackend(DN.decode("cn=config")); cache.putEntry(testEntriesList.get(0), b, 1); Entry testEntry = testEntriesList.get(1); testEntry.setDN(testEntry.getDN().decode( testEntry.getDN().getRDN() + ",cn=config")); cache.putEntry(testEntry, c, 1); cache.clearSubtree(DN.decode("o=test")); assertNull(cache.getEntry(testEntriesList.get(0).getDN()), "Not expected to find " + testEntriesList.get(0).getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); assertNotNull(cache.getEntry(testEntry.getDN()), "Expected to find " + testEntry.getDN().toString() + " in the cache. Cache contents:\n" + cache.toVerboseString()); // Clear the cache so that other tests can start from scratch. cache.clear(); } /** * Tests the handleLowMemory method. * * @throws Exception If an unexpected problem occurs. */ public void testHandleLowMemory() throws Exception { assertNull(cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + cache.toVerboseString()); cache.handleLowMemory(); // Clear the cache so that other tests can start from scratch. cache.clear(); } /** * Tests the entry cache concurrency/threadsafety by executing * core entry cache operations on several threads concurrently. * * @throws Exception If an unexpected problem occurs. */ public void testCacheConcurrency() throws Exception { if(cacheEmptyAssert.compareAndSet(false, true)) { assertNull(cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + cache.toVerboseString()); } Backend b = DirectoryServer.getBackend(DN.decode("o=test")); for(int loops = 0; loops < CONCURRENCYLOOPS; loops++) { for(int i = 0; i < NUMTESTENTRIES; i++) { cache.putEntry(testEntriesList.get(i), b, i); cache.getEntry(testEntriesList.get(i).getDN()); } } // Clear the cache so that other tests can start from scratch. cache.clear(); } }