Java tutorial
/** * 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")); } } }