| opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/CommonEntryCacheTestCase.java | ●●●●● patch | view | raw | blame | history | |
| opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FIFOEntryCacheTestCase.java | ●●●●● patch | view | raw | blame | history | |
| opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FileSystemEntryCacheTestCase.java | ●●●●● patch | view | raw | blame | history | |
| opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SoftReferenceEntryCacheTestCase.java | ●●●●● patch | view | raw | blame | history |
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/CommonEntryCacheTestCase.java
New file @@ -0,0 +1,506 @@ /* * 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<Entry> 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 <CODE>containsEntry</CODE> 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 <CODE>getEntry</CODE> 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 <CODE>getEntry</CODE> 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<Lock>()), "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<Lock>()), "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 <CODE>getEntry</CODE> 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<Lock>()), "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<Lock>()), "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 <CODE>getEntryID</CODE> 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 <CODE>putEntry</CODE> 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 <CODE>putEntryIfAbsent</CODE> 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 <CODE>removeEntry</CODE> 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 <CODE>clear</CODE> 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 <CODE>clearBackend</CODE> 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<Lock>()), "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<Lock>()), "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 <CODE>clearSubtree</CODE> 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 <CODE>handleLowMemory</CODE> 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(); } } opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FIFOEntryCacheTestCase.java
New file @@ -0,0 +1,370 @@ /* * 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 org.opends.server.TestCaseUtils; import org.opends.server.admin.server.AdminTestCaseUtils; import org.testng.annotations.BeforeClass; import org.opends.server.admin.std.meta.*; import org.opends.server.api.Backend; import org.opends.server.core.DirectoryServer; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import static org.testng.Assert.*; /** * A set of test cases for FIFO entry cache implementation. */ @Test(groups = "entrycache") public class FIFOEntryCacheTestCase extends CommonEntryCacheTestCase { /** * Initialize the entry cache test. * * @throws Exception If an unexpected problem occurs. */ @BeforeClass() @SuppressWarnings("unchecked") public void entryCacheTestInit() throws Exception { // Ensure that the server is running. TestCaseUtils.startServer(); // Configure this entry cache. Entry cacheConfigEntry = TestCaseUtils.makeEntry( "dn: cn=Entry Cache,cn=config", "objectClass: ds-cfg-fifo-entry-cache", "objectClass: ds-cfg-entry-cache", "objectClass: top", "cn: Entry Cache", "ds-cfg-entry-cache-class: org.opends.server.extensions.FIFOEntryCache", "ds-cfg-entry-cache-enabled: true", "ds-cfg-max-entries: " + Integer.toString(super.MAXENTRIES)); super.configuration = AdminTestCaseUtils.getConfiguration( EntryCacheCfgDefn.getInstance(), cacheConfigEntry); // Force GC to make sure we have enough memory for // the cache capping constraints to work properly. System.gc(); // Initialize the cache. super.cache = new FIFOEntryCache(); super.cache.initializeEntryCache(configuration); // Make some dummy test entries. super.testEntriesList = new ArrayList<Entry>(super.NUMTESTENTRIES); for(int i = 0; i < super.NUMTESTENTRIES; i++ ) { super.testEntriesList.add(TestCaseUtils.makeEntry( "dn: uid=test" + Integer.toString(i) + ".user" + Integer.toString(i) + ",ou=test" + Integer.toString(i) + ",o=test", "objectClass: person", "objectClass: inetorgperson", "objectClass: top", "objectClass: organizationalperson", "postalAddress: somewhere in Testville" + Integer.toString(i), "street: Under Construction Street" + Integer.toString(i), "l: Testcounty" + Integer.toString(i), "st: Teststate" + Integer.toString(i), "telephoneNumber: +878 8378 8378" + Integer.toString(i), "mobile: +878 8378 8378" + Integer.toString(i), "homePhone: +878 8378 8378" + Integer.toString(i), "pager: +878 8378 8378" + Integer.toString(i), "mail: test" + Integer.toString(i) + ".user" + Integer.toString(i) + "@testdomain.net", "postalCode: 8378" + Integer.toString(i), "userPassword: testpassword" + Integer.toString(i), "description: description for Test" + Integer.toString(i) + "User" + Integer.toString(i), "cn: Test" + Integer.toString(i) + "User" + Integer.toString(i), "sn: User" + Integer.toString(i), "givenName: Test" + Integer.toString(i), "initials: TST" + Integer.toString(i), "employeeNumber: 8378" + Integer.toString(i), "uid: test" + Integer.toString(i) + ".user" + Integer.toString(i)) ); } } /** * Finalize the entry cache test. * * @throws Exception If an unexpected problem occurs. */ @AfterClass() public void entryCacheTestFini() throws Exception { super.cache.finalizeEntryCache(); } /** * {@inheritDoc} */ @Test() @Override public void testContainsEntry() throws Exception { super.testContainsEntry(); } /** * {@inheritDoc} */ @Test() @Override public void testGetEntry1() throws Exception { super.testGetEntry1(); } /** * {@inheritDoc} */ @Test() @Override public void testGetEntry2() throws Exception { super.testGetEntry2(); } /** * {@inheritDoc} */ @Test() @Override public void testGetEntry3() throws Exception { super.testGetEntry3(); } /** * {@inheritDoc} */ @Test() @Override public void testGetEntryID() throws Exception { super.testGetEntryID(); } /** * {@inheritDoc} */ @Test() @Override public void testPutEntry() throws Exception { super.testPutEntry(); } /** * {@inheritDoc} */ @Test() @Override public void testPutEntryIfAbsent() throws Exception { super.testPutEntryIfAbsent(); } /** * {@inheritDoc} */ @Test() @Override public void testRemoveEntry() throws Exception { super.testRemoveEntry(); } /** * {@inheritDoc} */ @Test() @Override public void testClear() throws Exception { super.testClear(); } /** * {@inheritDoc} */ @Test() @Override public void testClearBackend() throws Exception { super.testClearBackend(); } /** * {@inheritDoc} */ @Test() @Override public void testClearSubtree() throws Exception { super.testClearSubtree(); } /** * {@inheritDoc} */ @Test() @Override public void testHandleLowMemory() throws Exception { assertNull(super.cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + super.cache.toVerboseString()); Backend b = DirectoryServer.getBackend(DN.decode("o=test")); for(int i = 0; i < super.NUMTESTENTRIES; i++ ) { super.cache.putEntry(super.testEntriesList.get(i), b, i); } super.cache.handleLowMemory(); // Make sure that the entries put previously on the // cache are no longer there after handleLowMemory. for(int i = 0; i < super.NUMTESTENTRIES; i++ ) { assertFalse(super.cache.containsEntry( super.testEntriesList.get(i).getDN()), "Not expected to find " + super.testEntriesList.get(i).getDN().toString() + " in the " + "cache. Cache contents:\n" + super.cache.toVerboseString()); } // Clear the cache so that other tests can start from scratch. super.cache.clear(); } /** * {@inheritDoc} */ @Test(groups="slow", threadPoolSize = 10, invocationCount = 10, timeOut = 60000) @Override public void testCacheConcurrency() throws Exception { super.testCacheConcurrency(); } /** * Tests cache rotation on specific number of entries. */ @Test() public void testCacheRotation() throws Exception { assertNull(super.cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + super.cache.toVerboseString()); Backend b = DirectoryServer.getBackend(DN.decode("o=test")); for(int i = 0; i < super.NUMTESTENTRIES; i++ ) { super.cache.putEntry(super.testEntriesList.get(i), b, i); } // Make sure first MAXENTRIES out of NUMTESTENTRIES rotated. for(int i = 0; i < super.MAXENTRIES; i++ ) { assertFalse(super.cache.containsEntry( super.testEntriesList.get(i).getDN()), "Not expected to find " + super.testEntriesList.get(i).getDN().toString() + " in the " + "cache. Cache contents:\n" + super.cache.toVerboseString()); } // Make sure remaining NUMTESTENTRIES are still in the cache. for(int i = (super.NUMTESTENTRIES - super.MAXENTRIES); i < super.NUMTESTENTRIES; i++) { assertTrue(super.cache.containsEntry( super.testEntriesList.get(i).getDN()), "Expected to find " + super.testEntriesList.get(i).getDN().toString() + " in the " + "cache. Cache contents:\n" + super.cache.toVerboseString()); } // Clear the cache so that other tests can start from scratch. super.cache.clear(); } } opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FileSystemEntryCacheTestCase.java
New file @@ -0,0 +1,689 @@ /* * 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.io.File; import java.util.ArrayList; import org.opends.server.TestCaseUtils; import org.opends.server.admin.server.AdminTestCaseUtils; import org.testng.annotations.BeforeClass; import org.opends.server.admin.std.meta.*; import org.opends.server.api.Backend; import org.opends.server.core.DirectoryServer; import org.opends.server.types.Attribute; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; import static org.testng.Assert.*; /** * A set of test cases for FileSystem entry cache implementation. */ @Test(groups = "entrycache") public class FileSystemEntryCacheTestCase extends CommonEntryCacheTestCase { /** * Configuration entry for this cache. */ private static Entry cacheConfigEntry; /** * Utility method to restore default cache configuration. */ @SuppressWarnings("unchecked") private void restoreCacheDefaults() throws Exception { // Finalize this cache so it can be reconfigured. super.cache.finalizeEntryCache(); // Configure this cache back to defaults. super.configuration = AdminTestCaseUtils.getConfiguration( EntryCacheCfgDefn.getInstance(), cacheConfigEntry); // Initialize the cache. super.cache = new FileSystemEntryCache(); super.cache.initializeEntryCache(configuration); } /** * Utility method to configure the cache with LRU access order. */ @SuppressWarnings("unchecked") private void setupLRUCache() throws Exception { // Finalize this cache so it can be reconfigured. super.cache.finalizeEntryCache(); // Configure this cache as LRU. Entry newCacheConfigEntry = cacheConfigEntry.duplicate(true); Attribute cacheConfigTypeAttr = new Attribute("ds-cfg-cache-type", "LRU"); newCacheConfigEntry.addAttribute(cacheConfigTypeAttr, null); super.configuration = AdminTestCaseUtils.getConfiguration( EntryCacheCfgDefn.getInstance(), newCacheConfigEntry); // Initialize the cache. super.cache = new FileSystemEntryCache(); super.cache.initializeEntryCache(configuration); // Make sure the cache is empty. assertNull(super.cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + super.cache.toVerboseString()); } /** * Utility method to initialize persistent cache. */ @SuppressWarnings("unchecked") private void persistentCacheSetup() throws Exception { // Make sure JE directory exist. File tempDir = TestCaseUtils.createTemporaryDirectory("db-cachetest"); String jeDir = tempDir.getAbsolutePath(); // Create dummy JE backend for this test. TestCaseUtils.dsconfig("create-backend", "--backend-name", "cacheTest", "--type", "je", "--set", "backend-directory:" + jeDir, "--set", "backend-base-dn:o=cachetest", "--set", "backend-import-temp-directory:importTmp", "--set", "backend-writability-mode:enabled", "--set", "backend-enabled:true"); // Finalize this cache so it can be reconfigured. super.cache.finalizeEntryCache(); // Configure this cache as persistent cache with // unlimited number of entries. Entry newCacheConfigEntry = cacheConfigEntry.duplicate(true); Attribute cacheConfigPersistAttr = new Attribute("ds-cfg-persistent-cache", "true"); newCacheConfigEntry.addAttribute(cacheConfigPersistAttr, null); Attribute cacheConfigMaxAttr = new Attribute("ds-cfg-max-entries", Integer.toString(super.MAXENTRIES)); newCacheConfigEntry.removeAttribute(cacheConfigMaxAttr, null); super.configuration = AdminTestCaseUtils.getConfiguration( EntryCacheCfgDefn.getInstance(), newCacheConfigEntry); // Initialize the cache. super.cache = new FileSystemEntryCache(); super.cache.initializeEntryCache(configuration); // Make sure the cache is empty. assertNull(super.cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + super.cache.toVerboseString()); } /** * Utility method to finalize persistent cache. */ private void persistentCacheTeardown() throws Exception { File tempDir = TestCaseUtils.createTemporaryDirectory("db-cachetest"); TestCaseUtils.dsconfig("delete-backend", "--backend-name", "cacheTest"); TestCaseUtils.deleteDirectory(tempDir); // Configure this cache back to defaults. restoreCacheDefaults(); } /** * Initialize the entry cache test. * * @throws Exception If an unexpected problem occurs. */ @BeforeClass @SuppressWarnings("unchecked") public void entryCacheTestInit() throws Exception { // Ensure that the server is running. TestCaseUtils.startServer(); // Configure this entry cache. cacheConfigEntry = TestCaseUtils.makeEntry( "dn: cn=Entry Cache,cn=config", "objectClass: ds-cfg-file-system-entry-cache", "objectClass: ds-cfg-entry-cache", "objectClass: top", "cn: Entry Cache", "ds-cfg-entry-cache-class: " + "org.opends.server.extensions.FileSystemEntryCache", "ds-cfg-entry-cache-enabled: true", "ds-cfg-max-entries: " + Integer.toString(super.MAXENTRIES)); super.configuration = AdminTestCaseUtils.getConfiguration( EntryCacheCfgDefn.getInstance(), cacheConfigEntry); // Force GC to make sure we have enough memory for // the cache capping constraints to work properly. System.gc(); // Initialize the cache. super.cache = new FileSystemEntryCache(); super.cache.initializeEntryCache(configuration); // Make some dummy test entries. super.testEntriesList = new ArrayList<Entry>(super.NUMTESTENTRIES); for(int i = 0; i < super.NUMTESTENTRIES; i++ ) { super.testEntriesList.add(TestCaseUtils.makeEntry( "dn: uid=test" + Integer.toString(i) + ".user" + Integer.toString(i) + ",ou=test" + Integer.toString(i) + ",o=test", "objectClass: person", "objectClass: inetorgperson", "objectClass: top", "objectClass: organizationalperson", "postalAddress: somewhere in Testville" + Integer.toString(i), "street: Under Construction Street" + Integer.toString(i), "l: Testcounty" + Integer.toString(i), "st: Teststate" + Integer.toString(i), "telephoneNumber: +878 8378 8378" + Integer.toString(i), "mobile: +878 8378 8378" + Integer.toString(i), "homePhone: +878 8378 8378" + Integer.toString(i), "pager: +878 8378 8378" + Integer.toString(i), "mail: test" + Integer.toString(i) + ".user" + Integer.toString(i) + "@testdomain.net", "postalCode: 8378" + Integer.toString(i), "userPassword: testpassword" + Integer.toString(i), "description: description for Test" + Integer.toString(i) + "User" + Integer.toString(i), "cn: Test" + Integer.toString(i) + "User" + Integer.toString(i), "sn: User" + Integer.toString(i), "givenName: Test" + Integer.toString(i), "initials: TST" + Integer.toString(i), "employeeNumber: 8378" + Integer.toString(i), "uid: test" + Integer.toString(i) + ".user" + Integer.toString(i)) ); } } /** * Finalize the entry cache test. * * @throws Exception If an unexpected problem occurs. */ @AfterClass public void entryCacheTestFini() throws Exception { super.cache.finalizeEntryCache(); } /** * {@inheritDoc} */ @Test() @Override public void testContainsEntry() throws Exception { super.testContainsEntry(); } /** * {@inheritDoc} */ @Test() @Override public void testGetEntry1() throws Exception { super.testGetEntry1(); } /** * {@inheritDoc} */ @Test() @Override public void testGetEntry2() throws Exception { super.testGetEntry2(); } /** * {@inheritDoc} */ @Test() @Override public void testGetEntry3() throws Exception { super.testGetEntry3(); } /** * {@inheritDoc} */ @Test() @Override public void testGetEntryID() throws Exception { super.testGetEntryID(); } /** * {@inheritDoc} */ @Test() @Override public void testPutEntry() throws Exception { super.testPutEntry(); } /** * {@inheritDoc} */ @Test() @Override public void testPutEntryIfAbsent() throws Exception { super.testPutEntryIfAbsent(); } /** * {@inheritDoc} */ @Test() @Override public void testRemoveEntry() throws Exception { super.testRemoveEntry(); } /** * {@inheritDoc} */ @Test() @Override public void testClear() throws Exception { super.testClear(); } /** * {@inheritDoc} */ @Test() @Override public void testClearBackend() throws Exception { super.testClearBackend(); } /** * {@inheritDoc} */ @Test() @Override public void testClearSubtree() throws Exception { super.testClearSubtree(); } /** * {@inheritDoc} */ @Test() @Override public void testHandleLowMemory() throws Exception { super.testHandleLowMemory(); } /** * {@inheritDoc} */ @Test(groups="slow", threadPoolSize = 10, invocationCount = 10, // In case of disk based FS. timeOut = 600000) @Override public void testCacheConcurrency() throws Exception { super.testCacheConcurrency(); } @BeforeGroups(groups = "testLRUCacheConcurrency") public void LRUCacheConcurrencySetup() throws Exception { // Setup LRU cache. setupLRUCache(); } @AfterGroups(groups = "testLRUCacheConcurrency") public void LRUCacheConcurrencyCleanup() throws Exception { // Configure this cache back to defaults. restoreCacheDefaults(); } /** * Tests the entry cache concurrency/threadsafety by executing * core entry cache operations on several threads concurrently * on LRU access order cache. * * @throws Exception If an unexpected problem occurs. */ @Test(groups = { "slow", "testLRUCacheConcurrency" }, threadPoolSize = 10, invocationCount = 10, // In case of disk based FS. timeOut = 600000) public void testLRUCacheConcurrency() throws Exception { super.testCacheConcurrency(); } /** * Tests FIFO cache rotation on specific number of entries. */ @Test(groups = "slow") public void testCacheRotationFIFO() throws Exception { assertNull(super.cache.toVerboseString(), "Expected empty cache. " + "Cache contents:\n" + super.cache.toVerboseString()); // Put some test entries in the cache. Backend b = DirectoryServer.getBackend(DN.decode("o=test")); for(int i = 0; i < super.NUMTESTENTRIES; i++ ) { super.cache.putEntry(super.testEntriesList.get(i), b, i); } // Make sure first MAXENTRIES out of NUMTESTENTRIES rotated. for(int i = 0; i < super.MAXENTRIES; i++ ) { assertFalse(super.cache.containsEntry( super.testEntriesList.get(i).getDN()), "Not expected to find " + super.testEntriesList.get(i).getDN().toString() + " in the " + "cache. Cache contents:\n" + super.cache.toVerboseString()); } // Make sure remaining NUMTESTENTRIES are still in the cache. for(int i = (super.NUMTESTENTRIES - super.MAXENTRIES); i < super.NUMTESTENTRIES; i++) { assertTrue(super.cache.containsEntry( super.testEntriesList.get(i).getDN()), "Expected to find " + super.testEntriesList.get(i).getDN().toString() + " in the " + "cache. Cache contents:\n" + super.cache.toVerboseString()); } // Clear the cache so that other tests can start from scratch. super.cache.clear(); } /** * Tests LRU cache rotation on specific number of entries. */ @Test(groups = "slow") @SuppressWarnings("unchecked") public void testCacheRotationLRU() throws Exception { // Setup LRU cache. setupLRUCache(); // Put some test entries in the cache. Backend b = DirectoryServer.getBackend(DN.decode("o=test")); for(int i = 0; i < super.NUMTESTENTRIES; i++) { super.cache.putEntry(super.testEntriesList.get(i), b, i); // Sacrifice one cache entry to support rotation. for(int j = 0; j < (super.MAXENTRIES - 1); j++) { // Generate access. super.cache.getEntry(super.testEntriesList.get(j).getDN()); } } // Make sure MAXENTRIES - 1 are still in the cache. for(int i = 0; i < (super.MAXENTRIES - 1); i++) { assertTrue(super.cache.containsEntry( super.testEntriesList.get(i).getDN()), "Expected to find " + super.testEntriesList.get(i).getDN().toString() + " in the " + "cache. Cache contents:\n" + super.cache.toVerboseString()); } // Plus the last cache entry added. assertTrue(super.cache.containsEntry( super.testEntriesList.get(super.NUMTESTENTRIES - 1).getDN()), "Expected to find " + super.testEntriesList.get(super.NUMTESTENTRIES - 1).getDN().toString() + " in the cache. Cache contents:\n" + super.cache.toVerboseString()); // And remaining NUMTESTENTRIES - 1 are now rotated. for(int i = (super.MAXENTRIES - 1); i < (super.NUMTESTENTRIES - 1); i++) { assertFalse(super.cache.containsEntry( super.testEntriesList.get(i).getDN()), "Not expected to find " + super.testEntriesList.get(i).getDN().toString() + " in the " + "cache. Cache contents:\n" + super.cache.toVerboseString()); } // Clear the cache so that other tests can start from scratch. super.cache.clear(); // Configure this cache back to defaults. restoreCacheDefaults(); } /** * Tests cache persistence with consistent backend. */ @Test(groups = "slow") @SuppressWarnings("unchecked") public void testCachePersistence() throws Exception { // Setup this test. persistentCacheSetup(); // Put some test entries in the cache. Backend b = DirectoryServer.getBackend(DN.decode("o=cachetest")); for(int i = 0; i < super.NUMTESTENTRIES; i++) { super.cache.putEntry(super.testEntriesList.get(i), b, i); } // Should trigger backend checksum. b.finalizeBackend(); // Finalize and persist this cache. super.cache.finalizeEntryCache(); // Get cachetest backend online again. b.initializeBackend(); // Initialize the cache again. super.cache = new FileSystemEntryCache(); super.cache.initializeEntryCache(configuration); // Check that this cache is persistent indeed. for(int i = 0; i < super.NUMTESTENTRIES; i++) { assertTrue(super.cache.containsEntry( super.testEntriesList.get(i).getDN()), "Expected to find " + super.testEntriesList.get(i).getDN().toString() + " in the " + "cache. Cache contents:\n" + super.cache.toVerboseString()); } // Clear the cache so that other tests can start from scratch. super.cache.clear(); // Finalize this cache so it can be reconfigured. super.cache.finalizeEntryCache(); // Clean up. b.finalizeBackend(); persistentCacheTeardown(); } /** * Tests cache persistence with inconsistent backend. */ @Test(groups = "slow") @SuppressWarnings("unchecked") public void testCachePersistenceInconsistent() throws Exception { // Setup this test. persistentCacheSetup(); // Put some test entries in the cache. Backend b = DirectoryServer.getBackend(DN.decode("o=cachetest")); for(int i = 0; i < super.NUMTESTENTRIES; i++) { super.cache.putEntry(super.testEntriesList.get(i), b, i); } // Should trigger backend checksum. b.finalizeBackend(); // Finalize and persist this cache. super.cache.finalizeEntryCache(); // Get cachetest backend online again. b.initializeBackend(); // Add dummy entry to cachetest backend to trigger inconsistent // offline state with persistent entry cache. TestCaseUtils.addEntry( "dn: o=cachetest", "objectClass: top", "objectClass: organization"); // Should trigger backend checksum. b.finalizeBackend(); // Get cachetest backend online again, now modified. b.initializeBackend(); // Initialize the cache again. super.cache = new FileSystemEntryCache(); super.cache.initializeEntryCache(configuration); // Check that this cache is persistent indeed. for(int i = 0; i < super.NUMTESTENTRIES; i++) { assertFalse(super.cache.containsEntry( super.testEntriesList.get(i).getDN()), "Not expected to find " + super.testEntriesList.get(i).getDN().toString() + " in the " + "cache. Cache contents:\n" + super.cache.toVerboseString()); } // Clear the cache so that other tests can start from scratch. super.cache.clear(); // Finalize this cache so it can be reconfigured. super.cache.finalizeEntryCache(); // Clean up. b.finalizeBackend(); persistentCacheTeardown(); } } opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SoftReferenceEntryCacheTestCase.java
New file @@ -0,0 +1,303 @@ /* * 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 org.opends.server.TestCaseUtils; import org.opends.server.admin.server.AdminTestCaseUtils; import org.testng.annotations.BeforeClass; import org.opends.server.admin.std.meta.*; import org.opends.server.types.Entry; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import static org.testng.Assert.*; /** * A set of test cases for SoftReference entry cache implementation. */ @Test(groups = "entrycache") public class SoftReferenceEntryCacheTestCase extends CommonEntryCacheTestCase { /** * Initialize the entry cache test. * * @throws Exception If an unexpected problem occurs. */ @BeforeClass() @SuppressWarnings("unchecked") public void entryCacheTestInit() throws Exception { // Ensure that the server is running. TestCaseUtils.startServer(); // Configure this entry cache. Entry cacheConfigEntry = TestCaseUtils.makeEntry( "dn: cn=Entry Cache,cn=config", "objectClass: ds-cfg-soft-reference-entry-cache", "objectClass: ds-cfg-entry-cache", "objectClass: top", "cn: Entry Cache", "ds-cfg-entry-cache-class: " + "org.opends.server.extensions.SoftReferenceEntryCache", "ds-cfg-entry-cache-enabled: true"); super.configuration = AdminTestCaseUtils.getConfiguration( EntryCacheCfgDefn.getInstance(), cacheConfigEntry); // Force GC to make sure we have enough memory for // the cache capping constraints to work properly. System.gc(); // Initialize the cache. super.cache = new SoftReferenceEntryCache(); super.cache.initializeEntryCache(configuration); // Make some dummy test entries. super.testEntriesList = new ArrayList<Entry>(super.NUMTESTENTRIES); for(int i = 0; i < super.NUMTESTENTRIES; i++ ) { super.testEntriesList.add(TestCaseUtils.makeEntry( "dn: uid=test" + Integer.toString(i) + ".user" + Integer.toString(i) + ",ou=test" + Integer.toString(i) + ",o=test", "objectClass: person", "objectClass: inetorgperson", "objectClass: top", "objectClass: organizationalperson", "postalAddress: somewhere in Testville" + Integer.toString(i), "street: Under Construction Street" + Integer.toString(i), "l: Testcounty" + Integer.toString(i), "st: Teststate" + Integer.toString(i), "telephoneNumber: +878 8378 8378" + Integer.toString(i), "mobile: +878 8378 8378" + Integer.toString(i), "homePhone: +878 8378 8378" + Integer.toString(i), "pager: +878 8378 8378" + Integer.toString(i), "mail: test" + Integer.toString(i) + ".user" + Integer.toString(i) + "@testdomain.net", "postalCode: 8378" + Integer.toString(i), "userPassword: testpassword" + Integer.toString(i), "description: description for Test" + Integer.toString(i) + "User" + Integer.toString(i), "cn: Test" + Integer.toString(i) + "User" + Integer.toString(i), "sn: User" + Integer.toString(i), "givenName: Test" + Integer.toString(i), "initials: TST" + Integer.toString(i), "employeeNumber: 8378" + Integer.toString(i), "uid: test" + Integer.toString(i) + ".user" + Integer.toString(i)) ); } } /** * Finalize the entry cache test. * * @throws Exception If an unexpected problem occurs. */ @AfterClass() public void entryCacheTestFini() throws Exception { super.cache.finalizeEntryCache(); } /** * {@inheritDoc} */ @Test() @Override public void testContainsEntry() throws Exception { super.testContainsEntry(); } /** * {@inheritDoc} */ @Test() @Override public void testGetEntry1() throws Exception { super.testGetEntry1(); } /** * {@inheritDoc} */ @Test() @Override public void testGetEntry2() throws Exception { super.testGetEntry2(); } /** * {@inheritDoc} */ @Test() @Override public void testGetEntry3() throws Exception { super.testGetEntry3(); } /** * {@inheritDoc} */ @Test() @Override public void testGetEntryID() throws Exception { super.testGetEntryID(); } /** * {@inheritDoc} */ @Test() @Override public void testPutEntry() throws Exception { super.testPutEntry(); } /** * {@inheritDoc} */ @Test() @Override public void testPutEntryIfAbsent() throws Exception { super.testPutEntryIfAbsent(); } /** * {@inheritDoc} */ @Test() @Override public void testRemoveEntry() throws Exception { super.testRemoveEntry(); } /** * {@inheritDoc} */ @Test() @Override public void testClear() throws Exception { super.testClear(); } /** * {@inheritDoc} */ @Test() @Override public void testClearBackend() throws Exception { super.testClearBackend(); } /** * {@inheritDoc} */ @Test() @Override public void testClearSubtree() throws Exception { super.testClearSubtree(); } /** * {@inheritDoc} */ @Test() @Override public void testHandleLowMemory() throws Exception { super.cache.handleLowMemory(); } /** * {@inheritDoc} */ @Test(groups="slow", threadPoolSize = 10, invocationCount = 10, timeOut = 60000) @Override public void testCacheConcurrency() throws Exception { super.testCacheConcurrency(); } }