org.neo4j.test.TargetDirectory.java Source code

Java tutorial

Introduction

Here is the source code for org.neo4j.test.TargetDirectory.java

Source

/**
 * Copyright (c) 2002-2014 "Neo Technology,"
 * Network Engine for Objects in Lund AB [http://neotechnology.com]
 *
 * This file is part of Neo4j.
 *
 * Neo4j is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.neo4j.test;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;

import org.apache.commons.codec.digest.DigestUtils;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

import org.neo4j.graphdb.mockfs.EphemeralFileSystemAbstraction;
import org.neo4j.io.fs.DefaultFileSystemAbstraction;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.io.fs.FileUtils;

import static java.lang.String.format;

public class TargetDirectory {
    /**
     * This class defines a JUnit rule which ensures that the test's working directory is cleaned up. The clean-up
     * only happens if the test passes, to help diagnose test failures.  For example:
     * <pre>
     *   public class SomeTest
     *   {
     *     @Rule
     *     public TargetDirectory.TestDirectory dir = testDirForTest( getClass() );
     *
     *     @Test
     *     public void shouldDoSomething()
     *     {
     *       File storeDir = dir.graphDbDir();
     *       // do stuff with store dir
     *     }
     *   }
     * </pre>
     */
    public class TestDirectory implements TestRule {
        private File subdir = null;

        private TestDirectory() {
        }

        public String absolutePath() {
            return directory().getAbsolutePath();
        }

        public File directory() {
            if (subdir == null) {
                throw new IllegalStateException("Not initialized");
            }
            return subdir;
        }

        public File file(String name) {
            return new File(directory(), name);
        }

        public File directory(String name) {
            File dir = new File(directory(), name);
            if (!fileSystem.fileExists(dir)) {
                fileSystem.mkdir(dir);
            }
            return dir;
        }

        public File graphDbDir() {
            return directory("graph-db");
        }

        @Override
        public Statement apply(final Statement base, Description description) {
            subdir = directoryForDescription(description);
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    boolean success = false;
                    try {
                        base.evaluate();
                        success = true;
                    } finally {
                        complete(success);
                    }
                }
            };
        }

        @Override
        public String toString() {
            String subdirName = subdir == null ? "<uninitialized>" : subdir.toString();
            return format("%s[%s]", getClass().getSimpleName(), subdirName);
        }

        private void complete(boolean success) {
            if (success && subdir != null) {
                try {
                    recursiveDelete(subdir);
                } catch (RuntimeException e) {
                    if (e.getCause() != null
                            && e.getCause() instanceof FileUtils.MaybeWindowsMemoryMappedFileReleaseProblem) {
                        System.err.println(
                                "Failed to delete test directory, maybe due to Windows memory-mapped file problem");
                    } else {
                        throw e;
                    }
                }
            }
            subdir = null;
        }
    }

    private final FileSystemAbstraction fileSystem;
    private final File base;

    /**
     * @deprecated Use {@link org.neo4j.test.TargetDirectory.TestDirectory} instead of creating
     * {@link org.neo4j.test.TargetDirectory} directly. The easiest way to do this is with
     * {@link #testDirForTest(Class)}.
     */
    public static TargetDirectory forTest(Class<?> owningTest) {
        return new TargetDirectory(new DefaultFileSystemAbstraction(), owningTest);
    }

    public static TestDirectory testDirForTest(Class<?> owningTest) {
        return new TargetDirectory(new DefaultFileSystemAbstraction(), owningTest).testDirectory();
    }

    public static TestDirectory testDirForTestWithEphemeralFS(EphemeralFileSystemAbstraction fileSystem,
            Class<?> owningTest) {
        return new TargetDirectory(fileSystem, owningTest).testDirectory();
    }

    private TargetDirectory(FileSystemAbstraction fileSystem, Class<?> owningTest) {
        this.fileSystem = fileSystem;
        this.base = new File(new File(locateTarget(owningTest), "test-data"), owningTest.getName())
                .getAbsoluteFile();
    }

    public File cacheDirectory(String name) {
        File dir = new File(ensureBase(), name);
        if (!fileSystem.fileExists(dir)) {
            fileSystem.mkdir(dir);
        }
        return dir;
    }

    public File existingDirectory(String name) {
        return new File(base, name);
    }

    public File cleanDirectory(String name) {
        File dir = new File(ensureBase(), name);
        if (fileSystem.fileExists(dir)) {
            recursiveDelete(dir);
        }
        fileSystem.mkdir(dir);
        return dir;
    }

    public File directoryForDescription(Description description) {
        String test = description.getMethodName();
        String dir = DigestUtils.md5Hex(test);
        register(test, dir);
        return cleanDirectory(dir);
    }

    public File file(String name) {
        return new File(ensureBase(), name);
    }

    public TestDirectory testDirectory() {
        return new TestDirectory();
    }

    public File makeGraphDbDir() {
        return cleanDirectory("graph-db");
    }

    public void cleanup() throws IOException {
        fileSystem.deleteRecursively(base);
        fileSystem.mkdirs(base);
    }

    private void recursiveDelete(File file) {
        try {
            fileSystem.deleteRecursively(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void register(String test, String dir) {
        try {
            FileUtils.writeToFile(new File(ensureBase(), ".register"), format("%s=%s\n", dir, test), true);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private File ensureBase() {
        if (fileSystem.fileExists(base) && !fileSystem.isDirectory(base)) {
            throw new IllegalStateException(base + " exists and is not a directory!");
        }

        try {
            fileSystem.mkdirs(base);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return base;
    }

    private static File locateTarget(Class<?> owningTest) {
        try {
            File codeSource = new File(owningTest.getProtectionDomain().getCodeSource().getLocation().toURI());
            if (codeSource.isDirectory()) {
                // code loaded from a directory
                return codeSource.getParentFile();
            }
        } catch (URISyntaxException e) {
            // ignored
        }
        return new File("target");
    }
}