aboutsummaryrefslogtreecommitdiffstats
path: root/weaver/testsrc
diff options
context:
space:
mode:
authorAndy Clement <andrew.clement@gmail.com>2012-10-29 12:46:03 -0700
committerAndy Clement <andrew.clement@gmail.com>2012-10-29 12:46:03 -0700
commitdf1823b297d7b543c1917804ac650502bd4601b2 (patch)
tree145af00113f611598a09c5970c390fdc6f8ca716 /weaver/testsrc
parent8a6608f4d5d1a2aa8aa49a0a38da66a54d53c917 (diff)
downloadaspectj-df1823b297d7b543c1917804ac650502bd4601b2.tar.gz
aspectj-df1823b297d7b543c1917804ac650502bd4601b2.zip
391123: ltw cache improvements
Diffstat (limited to 'weaver/testsrc')
-rw-r--r--weaver/testsrc/org/aspectj/weaver/tools/cache/AbstractCacheBackingTestSupport.java379
-rw-r--r--weaver/testsrc/org/aspectj/weaver/tools/cache/AsynchronousFileCacheBackingTestSupport.java193
-rw-r--r--weaver/testsrc/org/aspectj/weaver/tools/cache/CacheTests.java2
-rw-r--r--weaver/testsrc/org/aspectj/weaver/tools/cache/DefaultCacheKeyResolverTest.java3
-rw-r--r--weaver/testsrc/org/aspectj/weaver/tools/cache/DefaultFileCacheBackingTest.java22
-rw-r--r--weaver/testsrc/org/aspectj/weaver/tools/cache/FlatFileCacheBackingTest.java154
-rw-r--r--weaver/testsrc/org/aspectj/weaver/tools/cache/SimpleClassCacheTest.java12
-rw-r--r--weaver/testsrc/org/aspectj/weaver/tools/cache/WeavedClassCacheTest.java34
-rw-r--r--weaver/testsrc/org/aspectj/weaver/tools/cache/ZippedFileCacheBackingTest.java154
9 files changed, 900 insertions, 53 deletions
diff --git a/weaver/testsrc/org/aspectj/weaver/tools/cache/AbstractCacheBackingTestSupport.java b/weaver/testsrc/org/aspectj/weaver/tools/cache/AbstractCacheBackingTestSupport.java
new file mode 100644
index 000000000..d8c1f27b6
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/tools/cache/AbstractCacheBackingTestSupport.java
@@ -0,0 +1,379 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Lyor Goldstein (vmware) add support for weaved class being re-defined
+ *******************************************************************************/
+package org.aspectj.weaver.tools.cache;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.StreamCorruptedException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.CodeSource;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import junit.framework.TestCase;
+
+import org.aspectj.util.FileUtil;
+import org.aspectj.util.LangUtil;
+import org.aspectj.weaver.tools.cache.AbstractIndexedFileCacheBacking.IndexEntry;
+
+/**
+ */
+public abstract class AbstractCacheBackingTestSupport extends TestCase {
+ public static final String JAR_FILE_SUFFIX=".jar";
+ /**
+ * Prefix used in URL(s) that reference a resource inside a JAR
+ */
+ public static final String JAR_URL_PREFIX="jar:";
+ /**
+ * Separator used in URL(s) that reference a resource inside a JAR
+ * to denote the sub-path inside the JAR
+ */
+ public static final char RESOURCE_SUBPATH_SEPARATOR='!';
+
+ private File targetFolder;
+ private File testTempFolder;
+ protected File root;
+
+ public static final String TEMP_SUBFOLDER_NAME="temp";
+
+ protected AbstractCacheBackingTestSupport() {
+ super();
+ }
+
+ protected AbstractCacheBackingTestSupport(String name) {
+ super(name);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ if (root == null) {
+ root = createTempFile("aspectj", "testdir");
+ FileUtil.deleteContents(root);
+ }
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ if (root != null) {
+ FileUtil.deleteContents(root);
+ root = null;
+ }
+
+ if (targetFolder != null) {
+ FileUtil.deleteContents(targetFolder);
+ }
+
+ super.tearDown();
+ }
+
+ protected File ensureTempFolderExists () throws IllegalStateException {
+ synchronized(TEMP_SUBFOLDER_NAME) {
+ if (testTempFolder == null) {
+ File parent=detectTargetFolder();
+ testTempFolder = new File(parent, TEMP_SUBFOLDER_NAME);
+ }
+ }
+
+ return ensureFolderExists(testTempFolder);
+ }
+
+ protected File detectTargetFolder () throws IllegalStateException {
+ synchronized(TEMP_SUBFOLDER_NAME) {
+ if (targetFolder == null) {
+ if ((targetFolder=detectTargetFolder(getClass())) == null) {
+ throw new IllegalStateException("Failed to detect target folder");
+ }
+ }
+ }
+
+ return targetFolder;
+ }
+
+ protected File createTempFile (String prefix, String suffix) throws IOException {
+ File destFolder=ensureTempFolderExists();
+ return File.createTempFile(prefix, suffix, destFolder);
+ }
+
+ public static final File ensureFolderExists (File folder) throws IllegalStateException {
+ if (folder == null) {
+ throw new IllegalArgumentException("No folder to ensure existence");
+ }
+
+ if ((!folder.exists()) && (!folder.mkdirs())) {
+ throw new IllegalStateException("Failed to create " + folder.getAbsolutePath());
+ }
+
+ return folder;
+ }
+ /**
+ * @param anchor An anchor {@link Class} whose container we want to use
+ * as the starting point for the &quot;target&quot; folder lookup up the
+ * hierarchy
+ * @return The &quot;target&quot; <U>folder</U> - <code>null</code> if not found
+ * @see #detectTargetFolder(File)
+ */
+ public static final File detectTargetFolder (Class<?> anchor) {
+ return detectTargetFolder(getClassContainerLocationFile(anchor));
+ }
+
+ /**
+ * @param anchorFile An anchor {@link File) we want to use
+ * as the starting point for the &quot;target&quot; folder lookup up the
+ * hierarchy
+ * @return The &quot;target&quot; <U>folder</U> - <code>null</code> if not found
+ */
+ public static final File detectTargetFolder (File anchorFile) {
+ for (File file=anchorFile; file != null; file=file.getParentFile()) {
+ if (!file.isDirectory()) {
+ continue;
+ }
+
+ String name=file.getName();
+ if ("bin".equals(name) || "src".equals(name)) {
+ File parent=file.getParentFile();
+ return new File(parent, "target");
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @param clazz A {@link Class} object
+ * @return A {@link File} of the location of the class bytes container
+ * - e.g., the root folder, the containing JAR, etc.. Returns
+ * <code>null</code> if location could not be resolved
+ * @throws IllegalArgumentException If location is not a valid
+ * {@link File} location
+ * @see #getClassContainerLocationURI(Class)
+ * @see File#File(URI)
+ */
+ public static File getClassContainerLocationFile (Class<?> clazz)
+ throws IllegalArgumentException {
+ try {
+ URI uri=getClassContainerLocationURI(clazz);
+ return (uri == null) ? null : new File(uri);
+ } catch(URISyntaxException e) {
+ throw new IllegalArgumentException(e.getClass().getSimpleName() + ": " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * @param clazz A {@link Class} object
+ * @return A {@link URI} to the location of the class bytes container
+ * - e.g., the root folder, the containing JAR, etc.. Returns
+ * <code>null</code> if location could not be resolved
+ * @throws URISyntaxException if location is not a valid URI
+ * @see #getClassContainerLocationURL(Class)
+ */
+ public static URI getClassContainerLocationURI (Class<?> clazz) throws URISyntaxException {
+ URL url=getClassContainerLocationURL(clazz);
+ return (url == null) ? null : url.toURI();
+ }
+
+ /**
+ * @param clazz A {@link Class} object
+ * @return A {@link URL} to the location of the class bytes container
+ * - e.g., the root folder, the containing JAR, etc.. Returns
+ * <code>null</code> if location could not be resolved
+ */
+ public static URL getClassContainerLocationURL (Class<?> clazz) {
+ ProtectionDomain pd=clazz.getProtectionDomain();
+ CodeSource cs=(pd == null) ? null : pd.getCodeSource();
+ URL url=(cs == null) ? null : cs.getLocation();
+ if (url == null) {
+ ClassLoader cl=getDefaultClassLoader(clazz);
+ String className=clazz.getName().replace('.', '/') + ".class";
+ if ((url=cl.getResource(className)) == null) {
+ return null;
+ }
+
+ String srcForm=getURLSource(url);
+ if (LangUtil.isEmpty(srcForm)) {
+ return null;
+ }
+
+ try {
+ url = new URL(srcForm);
+ } catch(MalformedURLException e) {
+ throw new IllegalArgumentException("getClassContainerLocationURL(" + clazz.getName() + ")"
+ + "Failed to create URL=" + srcForm + " from " + url.toExternalForm()
+ + ": " + e.getMessage());
+ }
+ }
+
+ return url;
+ }
+ /**
+ * @param anchor An &quot;anchor&quot; {@link Class} to be used in case
+ * no thread context loader is available
+ * @return A {@link ClassLoader} to be used by the caller. The loader is
+ * resolved in the following manner:</P></BR>
+ * <UL>
+ * <LI>
+ * If a non-<code>null</code> loader is returned from the
+ * {@link Thread#getContextClassLoader()} call then use it.
+ * </LI>
+ *
+ * <LI>
+ * Otherwise, use the same loader that was used to load the anchor class.
+ * </LI>
+ * </UL>
+ * @throws IllegalArgumentException if no anchor class provided (regardless of
+ * whether it is used or not)
+ */
+ public static ClassLoader getDefaultClassLoader(Class<?> anchor) {
+ if (anchor == null) {
+ throw new IllegalArgumentException("No anchor class provided");
+ }
+
+ Thread t=Thread.currentThread();
+ ClassLoader cl=t.getContextClassLoader();
+ if (cl == null) {
+ // No thread context class loader -> use class loader of this class.
+ cl = anchor.getClassLoader();
+ }
+
+ if (cl == null) { // no class loader - assume system
+ cl = ClassLoader.getSystemClassLoader();
+ }
+
+ return cl;
+
+ }
+ public static final String getURLSource (File file) {
+ return getURLSource((file == null) ? null : file.toURI());
+ }
+
+ public static final String getURLSource (URI uri) {
+ return getURLSource((uri == null) ? null : uri.toString());
+ }
+
+ /**
+ * @param url The {@link URL} value - ignored if <code>null</code>
+ * @return The URL(s) source path where {@link #JAR_URL_PREFIX} and
+ * any sub-resource are stripped
+ * @see #getURLSource(String)
+ */
+ public static final String getURLSource (URL url) {
+ return getURLSource((url == null) ? null : url.toExternalForm());
+ }
+
+ /**
+ * @param externalForm The {@link URL#toExternalForm()} string - ignored if
+ * <code>null</code>/empty
+ * @return The URL(s) source path where {@link #JAR_URL_PREFIX} and
+ * any sub-resource are stripped
+ */
+ public static final String getURLSource (String externalForm) {
+ String url=externalForm;
+ if (LangUtil.isEmpty(url)) {
+ return url;
+ }
+
+ url = stripJarURLPrefix(externalForm);
+ if (LangUtil.isEmpty(url)){
+ return url;
+ }
+
+ int sepPos=url.indexOf(RESOURCE_SUBPATH_SEPARATOR);
+ if (sepPos < 0) {
+ return adjustURLPathValue(url);
+ } else {
+ return adjustURLPathValue(url.substring(0, sepPos));
+ }
+ }
+
+ /**
+ * @param path A URL path value
+ * @return The path after stripping any trailing '/' provided the path
+ * is not '/' itself
+ */
+ public static final String adjustURLPathValue(final String path) {
+ final int pathLen=LangUtil.isEmpty(path) ? 0 : path.length();
+ if ((pathLen <= 1) || (path.charAt(pathLen - 1) != '/')) {
+ return path;
+ }
+
+ return path.substring(0, pathLen - 1);
+ }
+
+ public static final String adjustURLPathValue(URL url) {
+ return adjustURLPathValue((url == null) ? null : url.getPath());
+ }
+
+ public static String stripJarURLPrefix(String externalForm) {
+ String url=externalForm;
+ if (LangUtil.isEmpty(url)) {
+ return url;
+ }
+
+ if (url.startsWith(JAR_URL_PREFIX)) {
+ return url.substring(JAR_URL_PREFIX.length());
+ }
+
+ return url;
+ }
+
+ protected static final void writeIndex (File indexFile, IndexEntry ... entries) throws IOException {
+ writeIndex(indexFile, LangUtil.isEmpty(entries) ? Collections.<IndexEntry>emptyList() : Arrays.asList(entries));
+ }
+
+ protected static final void writeIndex (File indexFile, Collection<? extends IndexEntry> entries) throws IOException {
+ File indexDir=indexFile.getParentFile();
+ if ((!indexDir.exists()) && (!indexDir.mkdirs())) {
+ throw new IOException("Failed to create path to " + indexFile.getAbsolutePath());
+ }
+
+ int numEntries=LangUtil.isEmpty(entries) ? 0 : entries.size();
+ IndexEntry[] entryValues=(numEntries <= 0) ? null : entries.toArray(new IndexEntry[numEntries]);
+ // if no entries, simply delete the index file
+ if (LangUtil.isEmpty(entryValues)) {
+ if (indexFile.exists() && (!indexFile.delete())) {
+ throw new StreamCorruptedException("Failed to clean up index file at " + indexFile.getAbsolutePath());
+ }
+
+ return;
+ }
+
+ ObjectOutputStream oos=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(indexFile), 4096));
+ try {
+ oos.writeObject(entryValues);
+ } finally {
+ oos.close();
+ }
+ }
+
+ public static final void assertArrayEquals (String msg, byte[] expected, byte[] actual) {
+ int eLen=LangUtil.isEmpty(expected) ? 0 : expected.length;
+ int aLen=LangUtil.isEmpty(actual) ? 0 : expected.length;
+ assertEquals(msg + "[mismatched length]", eLen, aLen);
+
+ for (int index=0; index < eLen; index++) {
+ byte eb=expected[index], ab=actual[index];
+ if (eb != ab) {
+ fail(msg + ": Mismatched value at index=" + index
+ + " - " + ab + " instead of " + eb
+ + ": expected=" + Arrays.toString(expected) + ", actual=" + Arrays.toString(actual));
+ }
+ }
+ }
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/tools/cache/AsynchronousFileCacheBackingTestSupport.java b/weaver/testsrc/org/aspectj/weaver/tools/cache/AsynchronousFileCacheBackingTestSupport.java
new file mode 100644
index 000000000..7d1b66407
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/tools/cache/AsynchronousFileCacheBackingTestSupport.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Lyor Goldstein (vmware) add support for weaved class being re-defined
+ *******************************************************************************/
+package org.aspectj.weaver.tools.cache;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Random;
+import java.util.TreeMap;
+
+import org.aspectj.util.FileUtil;
+import org.aspectj.util.LangUtil;
+import org.aspectj.weaver.tools.cache.AbstractIndexedFileCacheBacking.IndexEntry;
+
+/**
+ */
+public abstract class AsynchronousFileCacheBackingTestSupport
+ extends AbstractCacheBackingTestSupport {
+ private File cacheDir, indexFile;
+ protected final byte[] bytes=new byte[Byte.MAX_VALUE];
+ protected final Random random=new Random(System.nanoTime());
+
+ protected AsynchronousFileCacheBackingTestSupport() {
+ super();
+ }
+
+ protected AsynchronousFileCacheBackingTestSupport(String name) {
+ super(name);
+ }
+
+ @Override
+ public void setUp () throws Exception {
+ super.setUp();
+ cleanupCache();
+
+ random.nextBytes(bytes);
+ }
+
+ @Override
+ public void tearDown () throws Exception {
+ cleanupCache();
+ super.tearDown();
+ }
+
+ protected void cleanupCache() {
+ if (indexFile != null) {
+ if (FileUtil.deleteContents(indexFile) > 0) {
+ System.out.println("Deleted " + indexFile);
+ }
+ indexFile = null;
+ }
+
+ if (cacheDir != null) {
+ if (FileUtil.deleteContents(cacheDir) > 0) {
+ System.out.println("Deleted " + cacheDir);
+ }
+ cacheDir = null;
+ }
+ }
+
+ protected File getIndexFile () {
+ if (indexFile == null) {
+ File parent=getCacheDir();
+ indexFile=new File(parent, AbstractIndexedFileCacheBacking.INDEX_FILE);
+ }
+
+ return indexFile;
+ }
+
+ protected File getCacheDir () {
+ if (cacheDir == null) {
+ File targetDir=detectTargetFolder();
+ cacheDir = new File(targetDir, "dir-" + String.valueOf(Math.random()));
+ }
+
+ return ensureFolderExists(cacheDir);
+ }
+
+ protected abstract AsynchronousFileCacheBacking createFileBacking (File dir);
+
+ public void testDeleteIndexFileOnEmptyIndex () throws Exception {
+ IndexEntry[] entries={
+ createIndexEntry("weaved-empty", false, false, bytes, bytes),
+ createIndexEntry("generated-empty", true, false, bytes, bytes)
+ };
+ File cacheIndex=getIndexFile();
+ writeIndex(cacheIndex, entries);
+ assertTrue("No initial index file available: " + cacheIndex, cacheIndex.canRead());
+
+ AsynchronousFileCacheBacking cache=createFileBacking(getCacheDir());
+ // the call should read an empty index since no data files exist
+ Map<String, IndexEntry> indexMap=cache.getIndexMap();
+ assertEquals("Mismatched index size", 0, indexMap.size());
+
+ // no data files were created
+ Map<String, byte[]> bytesMap=cache.getBytesMap();
+ assertEquals("Mismatched bytes size", 0, bytesMap.size());
+
+ writeIndex(cache.getIndexFile(), cache.getIndexEntries());
+
+ assertFalse("Index file still available: " + cacheIndex, cacheIndex.canRead());
+ }
+
+ protected long generateNewBytes () {
+ final long CRC=AbstractCacheBacking.crc(bytes);
+ long crc=CRC;
+ // 8 tries should be enough to find a non-matching CRC...
+ for (int index=0; (index < Byte.SIZE) && (CRC == crc) && (crc != -1L); index++) {
+ random.nextBytes(bytes);
+ crc = AbstractCacheBacking.crc(bytes);
+ }
+ assertTrue("Could not generate different CRC for " + CRC, crc != CRC);
+
+ return crc;
+ }
+
+ protected Map<String, File> createDataFiles (IndexEntry ... entries) throws IOException {
+ return createDataFiles(LangUtil.isEmpty(entries) ? Collections.<IndexEntry>emptyList() : Arrays.asList(entries));
+ }
+
+ protected Map<String, File> createDataFiles (Collection<? extends IndexEntry> entries) throws IOException {
+ if (LangUtil.isEmpty(entries)) {
+ return Collections.emptyMap();
+ }
+
+ Map<String, File> files=new TreeMap<String, File>();
+ for (IndexEntry entry : entries) {
+ File file=createDataFile(entry);
+ if (file != null) {
+ files.put(entry.key, file);
+ }
+ }
+
+ return files;
+ }
+
+ protected File createDataFile (IndexEntry entry) throws IOException {
+ return createDataFile(entry, entry.ignored ? null : bytes);
+ }
+
+ protected File createDataFile (IndexEntry entry, byte[] dataBytes) throws IOException {
+ return createDataFile(entry.key, dataBytes);
+ }
+
+ protected File createDataFile (String key, byte[] dataBytes) throws IOException {
+ if (LangUtil.isEmpty(dataBytes)) {
+ return null;
+ }
+
+ File parent=getCacheDir(), file=new File(parent, key);
+ OutputStream out=new FileOutputStream(file);
+ try {
+ out.write(dataBytes);
+ } finally {
+ out.close();
+ }
+
+ return file;
+ }
+
+ protected static final IndexEntry createIgnoredEntry (String key) {
+ return createIndexEntry(key, false, true, null, null);
+ }
+
+ protected static final IndexEntry createIndexEntry (String key, boolean generated, boolean ignored, byte[] bytes, byte[] originalBytes) {
+ IndexEntry entry=new IndexEntry();
+ entry.key = key;
+ entry.generated = generated;
+ entry.ignored = ignored;
+ if (ignored) {
+ assertFalse(key + " ignored cannot be generated", generated);
+ } else {
+ entry.crcClass = AbstractCacheBacking.crc(originalBytes);
+ entry.crcWeaved = AbstractCacheBacking.crc(bytes);
+ }
+
+ return entry;
+ }
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/tools/cache/CacheTests.java b/weaver/testsrc/org/aspectj/weaver/tools/cache/CacheTests.java
index 861f637fc..b59665b4e 100644
--- a/weaver/testsrc/org/aspectj/weaver/tools/cache/CacheTests.java
+++ b/weaver/testsrc/org/aspectj/weaver/tools/cache/CacheTests.java
@@ -24,6 +24,8 @@ public class CacheTests {
suite.addTestSuite(WeavedClassCacheTest.class);
suite.addTestSuite(DefaultCacheKeyResolverTest.class);
suite.addTestSuite(DefaultFileCacheBackingTest.class);
+ suite.addTestSuite(FlatFileCacheBackingTest.class);
+ suite.addTestSuite(ZippedFileCacheBackingTest.class);
return suite;
}
}
diff --git a/weaver/testsrc/org/aspectj/weaver/tools/cache/DefaultCacheKeyResolverTest.java b/weaver/testsrc/org/aspectj/weaver/tools/cache/DefaultCacheKeyResolverTest.java
index 8dbe31463..139488b3c 100644
--- a/weaver/testsrc/org/aspectj/weaver/tools/cache/DefaultCacheKeyResolverTest.java
+++ b/weaver/testsrc/org/aspectj/weaver/tools/cache/DefaultCacheKeyResolverTest.java
@@ -28,6 +28,9 @@ public class DefaultCacheKeyResolverTest extends TestCase {
DefaultCacheKeyResolver resolver = new DefaultCacheKeyResolver();
class BasicTestCL extends ClassLoader {
+ public BasicTestCL () {
+ super();
+ }
}
class URLTestCL extends URLClassLoader {
diff --git a/weaver/testsrc/org/aspectj/weaver/tools/cache/DefaultFileCacheBackingTest.java b/weaver/testsrc/org/aspectj/weaver/tools/cache/DefaultFileCacheBackingTest.java
index 682869750..2d5ec0c77 100644
--- a/weaver/testsrc/org/aspectj/weaver/tools/cache/DefaultFileCacheBackingTest.java
+++ b/weaver/testsrc/org/aspectj/weaver/tools/cache/DefaultFileCacheBackingTest.java
@@ -16,42 +16,22 @@ package org.aspectj.weaver.tools.cache;
import java.io.File;
import java.util.zip.CRC32;
-import junit.framework.TestCase;
-
-import org.aspectj.util.FileUtil;
import org.aspectj.util.LangUtil;
import org.aspectj.weaver.tools.cache.AbstractIndexedFileCacheBacking.IndexEntry;
/**
*/
-public class DefaultFileCacheBackingTest extends TestCase {
+public class DefaultFileCacheBackingTest extends AbstractCacheBackingTestSupport {
private final byte[] FAKE_BYTES = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
private final String FAKE_CLASS = "com.example.foo.Bar";
private final CacheKeyResolver resolver = new DefaultCacheKeyResolver();
private final CachedClassReference fakeRef = resolver.weavedKey(FAKE_CLASS, FAKE_BYTES);
private final String fakeKey=fakeRef.getKey();
- private File root;
-
public DefaultFileCacheBackingTest () {
super();
}
- @Override
- public void setUp() throws Exception {
- if (root == null) {
- File tempFile = File.createTempFile("aspectj", "test");
- File tempDir = tempFile.getParentFile();
- root = new File(tempDir, "aspectj-test-cache");
- }
- }
-
- @Override
- public void tearDown() throws Exception {
- FileUtil.deleteContents(root);
- root = null;
- }
-
public void testCreateBacking() throws Exception {
CacheBacking backing = DefaultFileCacheBacking.createBacking(root);
assertNotNull(backing);
diff --git a/weaver/testsrc/org/aspectj/weaver/tools/cache/FlatFileCacheBackingTest.java b/weaver/testsrc/org/aspectj/weaver/tools/cache/FlatFileCacheBackingTest.java
new file mode 100644
index 000000000..8c6df7ad8
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/tools/cache/FlatFileCacheBackingTest.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2012 VMware, Inc.
+ *
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Lyor Goldstein
+ *******************************************************************************/
+
+package org.aspectj.weaver.tools.cache;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.aspectj.weaver.tools.cache.AbstractIndexedFileCacheBacking.IndexEntry;
+
+/**
+ * @author Lyor Goldstein
+ */
+public class FlatFileCacheBackingTest extends AsynchronousFileCacheBackingTestSupport {
+ public FlatFileCacheBackingTest() {
+ super();
+ }
+
+ @Override
+ protected FlatFileCacheBacking createFileBacking(File dir) {
+ return new FlatFileCacheBacking(dir);
+ }
+
+ public void testReadIndex () throws IOException {
+ IndexEntry[] entries={
+ createIgnoredEntry("ignored"),
+ createIndexEntry("weaved", false, false, bytes, bytes),
+ createIndexEntry("generated", true, false, bytes, bytes)
+ };
+ File indexFile=getIndexFile();
+ writeIndex(indexFile, entries);
+ Map<String, File> dataFiles=createDataFiles(entries);
+
+ File cacheDir=getCacheDir();
+ AsynchronousFileCacheBacking cache=createFileBacking(cacheDir);
+ Map<String, IndexEntry> indexMap=cache.getIndexMap();
+ assertEquals("Mismatched index size", entries.length, indexMap.size());
+
+ Map<String, byte[]> bytesMap=cache.getBytesMap();
+ assertEquals("Mismatched bytes size", dataFiles.size() /* the ignored one has no file */, bytesMap.size());
+
+ for (IndexEntry entry : entries) {
+ String key=entry.key;
+ assertNotNull("Missing entry for key=" + key, indexMap.get(key));
+
+ if (entry.ignored) {
+ assertNull("Unexpected bytes for ignored key=" + key, bytesMap.get(key));
+ } else {
+ assertArrayEquals("Mismatched contents for key=" + key, bytes, bytesMap.get(key));
+ }
+ }
+ }
+
+ public void testIgnoredBadCrcDataFiles () throws Exception {
+ IndexEntry[] entries={
+ createIndexEntry("weaved-goodData", false, false, bytes, bytes),
+ createIndexEntry("badData-weaved", false, false, bytes, bytes),
+ createIndexEntry("generated-goodData", true, false, bytes, bytes),
+ createIndexEntry("badData-generated", true, false, bytes, bytes)
+ };
+ File indexFile=getIndexFile();
+ writeIndex(indexFile, entries);
+
+ Map<String,File> dataFiles=createDataFiles(entries);
+ long newCrc=generateNewBytes();
+ assertTrue("Bad new CRC", newCrc != (-1L));
+
+ Map<String,File> badFiles=new TreeMap<String, File>();
+ for (IndexEntry entry : entries) {
+ String key=entry.key;
+ if (key.startsWith("badData")) {
+ File file=dataFiles.get(key);
+ OutputStream out=new FileOutputStream(file);
+ try {
+ out.write(bytes);
+ } finally {
+ out.close();
+ }
+ dataFiles.remove(key);
+ badFiles.put(key, file);
+ }
+ }
+
+ File cacheDir=getCacheDir();
+ FlatFileCacheBacking cache=createFileBacking(cacheDir);
+ Map<String, IndexEntry> indexMap=cache.getIndexMap();
+ assertEquals("Mismatched index size", dataFiles.size(), indexMap.size());
+
+ Map<String, byte[]> bytesMap=cache.getBytesMap();
+ assertEquals("Mismatched bytes size", dataFiles.size(), bytesMap.size());
+
+ for (Map.Entry<String,File> badEntry : badFiles.entrySet()) {
+ String key=badEntry.getKey();
+ assertFalse("Unexpectedly indexed: " + key, indexMap.containsKey(key));
+ assertFalse("Unexpectedly loaded: " + key, bytesMap.containsKey(key));
+
+ File file=badEntry.getValue();
+ assertFalse("Unexpectedly still readable: " + key, file.canRead());
+ }
+ }
+
+ public void testSkipMissingDataFileOnReadIndex () throws IOException {
+ IndexEntry[] entries={
+ createIndexEntry("weaved-noData", false, false, null, null),
+ createIndexEntry("withData-weaved", false, false, bytes, bytes),
+ createIndexEntry("generated-noData", true, false, null, null),
+ createIndexEntry("withData-generated", true, false, bytes, bytes)
+ };
+ File indexFile=getIndexFile();
+ writeIndex(indexFile, entries);
+
+ Map<String,File> dataFiles=new TreeMap<String, File>();
+ for (IndexEntry entry : entries) {
+ String key=entry.key;
+ if (key.startsWith("withData")) {
+ dataFiles.put(key, createDataFile(entry, bytes));
+ }
+ }
+
+ File cacheDir=getCacheDir();
+ FlatFileCacheBacking cache=createFileBacking(cacheDir);
+ Map<String, IndexEntry> indexMap=cache.getIndexMap();
+ assertEquals("Mismatched index size", dataFiles.size(), indexMap.size());
+
+ Map<String, byte[]> bytesMap=cache.getBytesMap();
+ assertEquals("Mismatched bytes size", dataFiles.size(), bytesMap.size());
+
+ for (IndexEntry entry : entries) {
+ String key=entry.key;
+ if (key.startsWith("withData")) {
+ assertTrue("Not indexed: " + key, indexMap.containsKey(key));
+ assertTrue("Not loaded: " + key, bytesMap.containsKey(key));
+ } else {
+ assertFalse("Unexpectedly indexed: " + key, indexMap.containsKey(key));
+ assertFalse("Unexpectedly loaded: " + key, bytesMap.containsKey(key));
+ }
+ }
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/tools/cache/SimpleClassCacheTest.java b/weaver/testsrc/org/aspectj/weaver/tools/cache/SimpleClassCacheTest.java
index 0624d0ff0..68fac6913 100644
--- a/weaver/testsrc/org/aspectj/weaver/tools/cache/SimpleClassCacheTest.java
+++ b/weaver/testsrc/org/aspectj/weaver/tools/cache/SimpleClassCacheTest.java
@@ -12,17 +12,9 @@
package org.aspectj.weaver.tools.cache;
-import junit.framework.TestCase;
-import org.aspectj.bridge.AbortException;
-import org.aspectj.bridge.IMessage;
-import org.aspectj.bridge.IMessageHandler;
-import org.aspectj.weaver.tools.GeneratedClassHandler;
-
import java.io.File;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
+
+import junit.framework.TestCase;
/**
*/
diff --git a/weaver/testsrc/org/aspectj/weaver/tools/cache/WeavedClassCacheTest.java b/weaver/testsrc/org/aspectj/weaver/tools/cache/WeavedClassCacheTest.java
index d972bff8b..a02400eb8 100644
--- a/weaver/testsrc/org/aspectj/weaver/tools/cache/WeavedClassCacheTest.java
+++ b/weaver/testsrc/org/aspectj/weaver/tools/cache/WeavedClassCacheTest.java
@@ -12,23 +12,26 @@
package org.aspectj.weaver.tools.cache;
-import junit.framework.TestCase;
-import org.aspectj.bridge.AbortException;
-import org.aspectj.bridge.IMessage;
-import org.aspectj.bridge.IMessageHandler;
-import org.aspectj.weaver.tools.GeneratedClassHandler;
-
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
+import org.aspectj.bridge.AbortException;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.weaver.tools.GeneratedClassHandler;
+
/**
*/
-public class WeavedClassCacheTest extends TestCase {
+public class WeavedClassCacheTest extends AbstractCacheBackingTestSupport {
String FAKE_CLASS = "com.example.foo.Bar";
byte[] FAKE_BYTES = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ public WeavedClassCacheTest () {
+ super();
+ }
+
public class MemoryCacheBacking implements CacheBacking {
HashMap<String, CachedClassEntry> cache = new HashMap<String, CachedClassEntry>();
@@ -73,9 +76,11 @@ public class WeavedClassCacheTest extends TestCase {
}
public void dontIgnore(IMessage.Kind kind) {
+ // do nothing
}
public void ignore(IMessage.Kind kind) {
+ // do nothing
}
};
@@ -83,7 +88,6 @@ public class WeavedClassCacheTest extends TestCase {
public int accepts = 0;
public List<String> classesISaw = new LinkedList<String>();
- @Override
public void acceptClass (String name, byte[] originalBytes, byte[] wovenBytes) {
accepts++;
classesISaw.add(name);
@@ -111,20 +115,6 @@ public class WeavedClassCacheTest extends TestCase {
assertTrue(newHandle instanceof GeneratedCachedClassHandler);
}
-
-// public void testExistingGeneratedClassesPassedThroughHandler() throws Exception {
-// String classA = "com.generated.A";
-// String classB = "com.generated.B";
-// reset();
-// memoryBacking.put(new CachedClassEntry(resolver.generatedKey(classA), FAKE_BYTES, CachedClassEntry.EntryType.GENERATED), FAKE_BYTES);
-// memoryBacking.put(new CachedClassEntry(resolver.generatedKey(classB), FAKE_BYTES, CachedClassEntry.EntryType.GENERATED), FAKE_BYTES);
-// createCache();
-// assertEquals(2, generatedClassHandler.accepts);
-// for (String cName : generatedClassHandler.classesISaw) {
-// assertTrue("Got: " + cName, cName.equals(classA) || cName.equals(classB));
-// }
-// }
-
public void testCache() throws Exception {
reset();
WeavedClassCache cache = createCache();
diff --git a/weaver/testsrc/org/aspectj/weaver/tools/cache/ZippedFileCacheBackingTest.java b/weaver/testsrc/org/aspectj/weaver/tools/cache/ZippedFileCacheBackingTest.java
new file mode 100644
index 000000000..4c41c1807
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/tools/cache/ZippedFileCacheBackingTest.java
@@ -0,0 +1,154 @@
+/**
+ * Copyright (c) 2012 VMware, Inc.
+ *
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Lyor Goldstein
+ */
+
+package org.aspectj.weaver.tools.cache;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.aspectj.util.FileUtil;
+import org.aspectj.weaver.tools.cache.AbstractIndexedFileCacheBacking.IndexEntry;
+
+/**
+ *
+ */
+public class ZippedFileCacheBackingTest extends AsynchronousFileCacheBackingTestSupport {
+ private File zipTestFile;
+
+ public ZippedFileCacheBackingTest() {
+ super();
+ }
+
+ public void testReadIndex () throws Exception {
+ IndexEntry[] entries={
+ createIgnoredEntry("ignored"),
+ createIndexEntry("weaved", false, false, bytes, bytes),
+ createIndexEntry("generated", true, false, bytes, bytes)
+ };
+ File indexFile=getIndexFile();
+ writeIndex(indexFile, entries);
+
+ Map<String,byte[]> entriesMap=new TreeMap<String,byte[]>();
+ for (IndexEntry ie : entries) {
+ if (ie.ignored) {
+ continue;
+ }
+
+ entriesMap.put(ie.key, bytes);
+ }
+
+ File zipFile=getZipFile();
+ ZippedFileCacheBacking.writeZipClassBytes(zipFile, entriesMap);
+
+ File cacheDir=getCacheDir();
+ AsynchronousFileCacheBacking cache=createFileBacking(cacheDir);
+ Map<String, IndexEntry> indexMap=cache.getIndexMap();
+ assertEquals("Mismatched index size", entries.length, indexMap.size());
+
+ Map<String, byte[]> bytesMap=cache.getBytesMap();
+ assertEquals("Mismatched bytes size", entriesMap.size() /* the ignored one has no file */, bytesMap.size());
+
+ for (IndexEntry entry : entries) {
+ String key=entry.key;
+ assertNotNull("Missing entry for key=" + key, indexMap.get(key));
+
+ if (entry.ignored) {
+ assertNull("Unexpected bytes for ignored key=" + key, bytesMap.get(key));
+ } else {
+ assertArrayEquals("Mismatched contents for key=" + key, bytes, bytesMap.get(key));
+ }
+ }
+ }
+
+ public void testReadWriteZipClassBytes () throws IOException {
+ Map<String,byte[]> entriesMap=new TreeMap<String,byte[]>();
+ for (int index=0; index < Byte.SIZE; index++) {
+ String name="classBytes#" + index;
+ random.nextBytes(bytes);
+ entriesMap.put(name, bytes);
+ }
+
+ File zipFile=getZipFile();
+ ZippedFileCacheBacking.writeZipClassBytes(zipFile, entriesMap);
+
+ Map<String, byte[]> bytesMap=ZippedFileCacheBacking.readZipClassBytes(zipFile);
+ assertEquals("Mismatched recovered entries size", entriesMap.size(), bytesMap.size());
+ for (Map.Entry<String,byte[]> bytesEntry : entriesMap.entrySet()) {
+ String key=bytesEntry.getKey();
+ byte[] expected=bytesEntry.getValue(), actual=bytesMap.get(key);
+ assertArrayEquals("Mismatched data for " + key, expected, actual);
+ }
+ }
+
+ public void testReadClassBytes () throws IOException {
+ IndexEntry[] entries={
+ createIgnoredEntry("ignoredReadClassBytes"),
+ createIndexEntry("weavedReadClassBytes", false, false, bytes, bytes),
+ createIndexEntry("generatedReadClassBytes", true, false, bytes, bytes)
+ };
+ File indexFile=getIndexFile();
+ writeIndex(indexFile, entries);
+
+ long newCrc=generateNewBytes();
+ assertTrue("Bad new CRC", newCrc != (-1L));
+
+ Map<String,byte[]> entriesMap=new TreeMap<String,byte[]>();
+ for (IndexEntry ie : entries) {
+ if (ie.ignored) {
+ continue;
+ }
+
+ entriesMap.put(ie.key, bytes);
+ }
+
+ File zipFile=getZipFile();
+ ZippedFileCacheBacking.writeZipClassBytes(zipFile, entriesMap);
+
+ File cacheDir=getCacheDir();
+ AsynchronousFileCacheBacking cache=createFileBacking(cacheDir);
+ Map<String, IndexEntry> indexMap=cache.getIndexMap();
+ assertEquals("Mismatched index size", 1 /* only the ignored entry */, indexMap.size());
+
+ Map<String, byte[]> bytesMap=cache.getBytesMap();
+ assertEquals("Non empty data bytes", 0, bytesMap.size());
+ assertFalse("Zip file not deleted: " + zipFile, zipFile.canRead());
+ }
+
+ protected File getZipFile () {
+ if (zipTestFile == null) {
+ File cacheDir=getCacheDir();
+ zipTestFile = new File(cacheDir, ZippedFileCacheBacking.ZIP_FILE);
+ }
+
+ return zipTestFile;
+ }
+
+ @Override
+ protected void cleanupCache() {
+ if (zipTestFile != null) {
+ if (FileUtil.deleteContents(zipTestFile) > 0) {
+ System.out.println("Deleted " + zipTestFile);
+ }
+ zipTestFile = null;
+ }
+
+ super.cleanupCache();
+ }
+
+ @Override
+ protected ZippedFileCacheBacking createFileBacking(File dir) {
+ return new ZippedFileCacheBacking(dir);
+ }
+} \ No newline at end of file