uk.co.unclealex.executable.impl.MakeLinksCommandRunnerTest.java Source code

Java tutorial

Introduction

Here is the source code for uk.co.unclealex.executable.impl.MakeLinksCommandRunnerTest.java

Source

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

package uk.co.unclealex.executable.impl;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedSet;

import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import uk.co.unclealex.executable.impl.MakeLinksCommandRunner;
import uk.co.unclealex.executable.impl.ReturnValue;
import uk.co.unclealex.executable.impl.ScriptNamesProvider;

import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * @author alex
 * 
 */
public class MakeLinksCommandRunnerTest {

    Path tmpDir;
    Path rootDir;
    Path scriptFile;
    Map<String, Path> symlinksByName;

    @Before
    public void setup() throws IOException, URISyntaxException {
        tmpDir = Files.createTempDirectory("makelinks-");
        scriptFile = Files.createTempFile("makelinks-", "-script-file.txt");
        Path otherFile = Files.createTempFile("makelinks-", "-other-file.txt");
        symlinksByName = Maps.newHashMap();
        symlinksByName.put(".script-file.txt", scriptFile);
        symlinksByName.put(".other-file.txt", otherFile);
        File rootFile = new File(getClass().getClassLoader().getResource("makelinks/makelinks.root").toURI());
        rootDir = rootFile.getParentFile().toPath();
    }

    @After
    public void teardown() throws IOException {
        FileUtils.deleteDirectory(tmpDir.toFile());
        for (Path path : symlinksByName.values()) {
            Files.delete(path);
        }
    }

    @Test
    public void testCannotOverwriteExistingBinNonDirectory() throws IOException, URISyntaxException {
        runTest("test-cannot-overwrite-existing-bin-non-directory", ReturnValue.ERROR);
    }

    @Test
    public void testCannotOverwriteNonSymlink() throws IOException, URISyntaxException {
        runTest("test-cannot-overwrite-non-symlink", ReturnValue.ERROR);
    }

    @Test
    public void testNonExistingBinDirectoryCreated() throws IOException, URISyntaxException {
        runTest("test-non-existing-bin-directory-created", ReturnValue.OK);
    }

    @Test
    public void testFresh() throws IOException, URISyntaxException {
        runTest("test-fresh", ReturnValue.OK);
    }

    @Test
    public void testReplace() throws IOException, URISyntaxException {
        runTest("test-replace", ReturnValue.OK);
    }

    public void runTest(String testCase, ReturnValue expectedReturnValue) throws IOException, URISyntaxException {
        Path sourceDir = setupTest(testCase);
        Path binDirectory = sourceDir.resolve("bin");
        MakeLinksCommandRunner makeLinksCommandRunner = new MakeLinksCommandRunner(new LinksScriptNamesProvider(),
                scriptFile, binDirectory);
        ReturnValue returnValue = makeLinksCommandRunner.run(System.in, System.out, System.err,
                new ArrayList<String>());
        Assert.assertEquals("The wrong return value was returned.", expectedReturnValue, returnValue);
        if (returnValue == ReturnValue.OK) {
            checkEqual(sourceDir, testCase);
        }
    }

    protected Path setupTest(String testCase) throws IOException {
        return copy(testCase, "source");
    }

    protected Path copy(String testCase, String directoryName) throws IOException {
        Path sourceDir = rootDir.resolve(testCase).resolve(directoryName);
        Path target = tmpDir.resolve(directoryName);
        Files.createDirectories(target);
        if (Files.exists(sourceDir)) {
            FileUtils.copyDirectory(sourceDir.toFile(), target.toFile());
            FileVisitor<Path> visitor = new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    String name = file.getFileName().toString();
                    for (Entry<String, Path> entry : symlinksByName.entrySet()) {
                        String suffix = entry.getKey();
                        Path symlink = entry.getValue();
                        if (name.endsWith(suffix)) {
                            Files.delete(file);
                            String newName = name.substring(0, name.length() - suffix.length());
                            Files.createSymbolicLink(file.resolveSibling(newName), symlink);
                            return FileVisitResult.CONTINUE;
                        }
                    }
                    return FileVisitResult.CONTINUE;
                }
            };
            Files.walkFileTree(target, visitor);
        }
        return target;
    }

    protected void checkEqual(Path actualDir, String testCase) throws IOException {
        Path expectedDir = copy(testCase, "expected");
        checkDirectoriesEqual(expectedDir, actualDir);
    }

    protected void checkDirectoriesEqual(Path expectedDir, Path actualDir) throws IOException {
        Assert.assertTrue("Path " + expectedDir + "is not a directory.",
                Files.isDirectory(expectedDir, LinkOption.NOFOLLOW_LINKS));
        Assert.assertTrue("Path " + actualDir + "is not a directory.",
                Files.isDirectory(actualDir, LinkOption.NOFOLLOW_LINKS));
        Assert.assertArrayEquals("Directory " + actualDir + " has the wrong file entries.",
                filenamesIn(expectedDir), filenamesIn(actualDir));
        DirectoryStream<Path> directoryStream = Files.newDirectoryStream(actualDir);
        for (Path expectedChild : directoryStream) {
            Path actualChild = expectedDir.resolve(expectedChild.getFileName());
            if (Files.isDirectory(expectedChild, LinkOption.NOFOLLOW_LINKS)) {
                Assert.assertTrue("Path " + actualChild + " is not a directory.",
                        Files.isDirectory(actualChild, LinkOption.NOFOLLOW_LINKS));
                checkDirectoriesEqual(expectedChild, actualChild);
            } else if (Files.isSymbolicLink(expectedChild)) {
                Assert.assertTrue("Path " + actualChild + " is not a symbolic link",
                        Files.isSymbolicLink(actualChild));
                Assert.assertEquals("Symbolic link " + actualChild + " points to the wrong place.",
                        Files.readSymbolicLink(expectedChild), Files.readSymbolicLink(actualChild));
            } else {
                Assert.assertTrue("Path " + actualChild + " has the wrong content.",
                        FileUtils.contentEquals(expectedChild.toFile(), actualChild.toFile()));
            }
        }
    }

    protected String[] filenamesIn(Path dir) throws IOException {
        Function<Path, String> nameFunction = new Function<Path, String>() {
            @Override
            public String apply(Path path) {
                return path.getFileName().toString();
            }
        };
        return Iterables.toArray(Sets.newTreeSet(Iterables.transform(Files.newDirectoryStream(dir), nameFunction)),
                String.class);
    }

    static class LinksScriptNamesProvider implements ScriptNamesProvider {
        @Override
        public SortedSet<String> getScriptNames() {
            return Sets.newTreeSet(Arrays.asList("scriptone", "scripttwo"));
        }
    }
}