Author: suresh Date: Fri May 24 22:36:52 2013 New Revision: 1486244 URL: http://svn.apache.org/r1486244 Log: HADOOP-8562. Merge r1480883 for HADOOP-9553, r1480880 for HADOOP-9556, r1478633, r1478592 for HADOOP-9483, r1478577 for HADOOP-9043
Added: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/readlink.c - copied unchanged from r1478633, hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/readlink.c Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/local/RawLocalFs.java hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/include/winutils.h hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/main.c hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/symlink.c hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/winutils.vcxproj hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestLocalFSFileContextSymlink.java hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestActiveStandbyElectorRealZK.java hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverController.java hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverControllerStress.java hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestWinUtils.java Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt?rev=1486244&r1=1486243&r2=1486244&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt (original) +++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt Fri May 24 22:36:52 2013 @@ -88,6 +88,9 @@ Release 2.0.5-beta - UNRELEASED HADOOP-9150. Avoid unnecessary DNS resolution attempts for logical URIs (todd) + HADOOP-9540. Expose the InMemoryS3 and S3N FilesystemStores implementations + for Unit testing. (Hari via stevel) + BUG FIXES HADOOP-9294. GetGroupsTestBase fails on Windows. (Chris Nauroth via suresh) @@ -347,11 +350,23 @@ Release 2.0.5-beta - UNRELEASED HADOOP-9413. Add common utils for File#setReadable/Writable/Executable & File#canRead/Write/Execute that work cross-platform. (Ivan Mitic via suresh) + + HADOOP-9043. Disallow in winutils creating symlinks with forwards slashes. + (Chris Nauroth via suresh) + + HADOOP-9483. winutils support for readlink command. + (Arpit Agarwal via suresh) HADOOP-9488. FileUtil#createJarWithClassPath only substitutes environment variables from current process environment/does not support overriding when launching new process (Chris Nauroth via bikas) + HADOOP-9556. disable HA tests on Windows that fail due to ZooKeeper client + connection management bug. (Chris Nauroth via suresh) + + HADOOP-9553. TestAuthenticationToken fails on Windows. + (Arpit Agarwal via suresh) + Release 2.0.4-beta - UNRELEASED INCOMPATIBLE CHANGES Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/local/RawLocalFs.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/local/RawLocalFs.java?rev=1486244&r1=1486243&r2=1486244&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/local/RawLocalFs.java (original) +++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/local/RawLocalFs.java Fri May 24 22:36:52 2013 @@ -18,6 +18,7 @@ package org.apache.hadoop.fs.local; import java.io.IOException; +import java.io.File; import java.io.FileNotFoundException; import java.net.URI; import java.net.URISyntaxException; @@ -90,8 +91,8 @@ public class RawLocalFs extends Delegate // NB: Use createSymbolicLink in java.nio.file.Path once available try { Shell.execCommand(Shell.getSymlinkCommand( - getPathWithoutSchemeAndAuthority(target), - getPathWithoutSchemeAndAuthority(link))); + getPathWithoutSchemeAndAuthority(target).getPath(), + getPathWithoutSchemeAndAuthority(link).getPath())); } catch (IOException x) { throw new IOException("Unable to create symlink: "+x.getMessage()); } @@ -167,12 +168,12 @@ public class RawLocalFs extends Delegate throw new AssertionError(); } - private static String getPathWithoutSchemeAndAuthority(Path path) { - // This code depends on Path.toString() to remove the leading slash before - // the drive specification on Windows. + private static File getPathWithoutSchemeAndAuthority(Path path) { Path newPath = path.isUriPathAbsolute() ? new Path(null, null, path.toUri().getPath()) : path; - return newPath.toString(); + + // Path.toString() removes leading slash before drive spec on Windows. + return new File(newPath.toString()); } } Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/include/winutils.h URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/include/winutils.h?rev=1486244&r1=1486243&r2=1486244&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/include/winutils.h (original) +++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/include/winutils.h Fri May 24 22:36:52 2013 @@ -104,6 +104,9 @@ void TaskUsage(); int Symlink(__in int argc, __in_ecount(argc) wchar_t *argv[]); void SymlinkUsage(); +int Readlink(__in int argc, __in_ecount(argc) wchar_t *argv[]); +void ReadlinkUsage(); + int SystemInfo(); void SystemInfoUsage(); Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/main.c URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/main.c?rev=1486244&r1=1486243&r2=1486244&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/main.c (original) +++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/main.c Fri May 24 22:36:52 2013 @@ -55,6 +55,10 @@ int wmain(__in int argc, __in_ecount(arg { return Symlink(argc - 1, argv + 1); } + else if (wcscmp(L"readlink", cmd) == 0) + { + return Readlink(argc - 1, argv + 1); + } else if (wcscmp(L"task", cmd) == 0) { return Task(argc - 1, argv + 1); @@ -105,6 +109,10 @@ The available commands and their usages SymlinkUsage(); fwprintf(stdout, L"\n\n"); + fwprintf(stdout, L"%-10s%s\n\n", L"readlink", L"Print the target of a symbolic link."); + ReadlinkUsage(); + fwprintf(stdout, L"\n\n"); + fwprintf(stdout, L"%-15s%s\n\n", L"systeminfo", L"System information."); SystemInfoUsage(); fwprintf(stdout, L"\n\n"); Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/symlink.c URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/symlink.c?rev=1486244&r1=1486243&r2=1486244&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/symlink.c (original) +++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/symlink.c Fri May 24 22:36:52 2013 @@ -60,6 +60,17 @@ int Symlink(__in int argc, __in_ecount(a goto SymlinkEnd; } + if (wcschr(longLinkName, L'/') != NULL || wcschr(longFileName, L'/') != NULL) + { + // Reject forward-slash separated paths as they result in unusable symlinks. + // + fwprintf(stderr, + L"Rejecting forward-slash separated path which would result in an " + L"unusable symlink: link = %s, target = %s\n", longLinkName, longFileName); + ret = FAILURE; + goto SymlinkEnd; + } + // Check if the the process's access token has the privilege to create // symbolic links. Without this step, the call to CreateSymbolicLink() from // users have the privilege to create symbolic links will still succeed. Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/winutils.vcxproj URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/winutils.vcxproj?rev=1486244&r1=1486243&r2=1486244&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/winutils.vcxproj (original) +++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/winutils/winutils.vcxproj Fri May 24 22:36:52 2013 @@ -160,6 +160,7 @@ </Link> </ItemDefinitionGroup> <ItemGroup> + <ClCompile Include="readlink.c" /> <ClCompile Include="symlink.c" /> <ClCompile Include="systeminfo.c" /> <ClCompile Include="chmod.c" /> @@ -178,4 +179,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> +</Project> \ No newline at end of file Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestLocalFSFileContextSymlink.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestLocalFSFileContextSymlink.java?rev=1486244&r1=1486243&r2=1486244&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestLocalFSFileContextSymlink.java (original) +++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestLocalFSFileContextSymlink.java Fri May 24 22:36:52 2013 @@ -27,6 +27,7 @@ import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.FileUtil; import static org.apache.hadoop.fs.FileContextTestHelper.*; import static org.junit.Assert.*; +import static org.junit.Assume.assumeTrue; import org.junit.Test; import org.junit.Before; @@ -65,7 +66,44 @@ public class TestLocalFSFileContextSymli fc = FileContext.getLocalFSFileContext(); super.setUp(); } - + + @Override + public void testCreateDanglingLink() throws IOException { + // Dangling symlinks are not supported on Windows local file system. + assumeTrue(!Path.WINDOWS); + super.testCreateDanglingLink(); + } + + @Override + public void testCreateFileViaDanglingLinkParent() throws IOException { + assumeTrue(!Path.WINDOWS); + super.testCreateFileViaDanglingLinkParent(); + } + + @Override + public void testOpenResolvesLinks() throws IOException { + assumeTrue(!Path.WINDOWS); + super.testOpenResolvesLinks(); + } + + @Override + public void testRecursiveLinks() throws IOException { + assumeTrue(!Path.WINDOWS); + super.testRecursiveLinks(); + } + + @Override + public void testRenameDirToDanglingSymlink() throws IOException { + assumeTrue(!Path.WINDOWS); + super.testRenameDirToDanglingSymlink(); + } + + @Override + public void testStatDanglingLink() throws IOException { + assumeTrue(!Path.WINDOWS); + super.testStatDanglingLink(); + } + @Test /** lstat a non-existant file using a partially qualified path */ public void testDanglingLinkFilePartQual() throws IOException { @@ -87,6 +125,7 @@ public class TestLocalFSFileContextSymli @Test /** Stat and lstat a dangling link */ public void testDanglingLink() throws IOException { + assumeTrue(!Path.WINDOWS); Path fileAbs = new Path(testBaseDir1()+"/file"); Path fileQual = new Path(testURI().toString(), fileAbs); Path link = new Path(testBaseDir1()+"/linkToFile"); Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestActiveStandbyElectorRealZK.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestActiveStandbyElectorRealZK.java?rev=1486244&r1=1486243&r2=1486244&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestActiveStandbyElectorRealZK.java (original) +++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestActiveStandbyElectorRealZK.java Fri May 24 22:36:52 2013 @@ -20,6 +20,7 @@ package org.apache.hadoop.ha; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; import java.util.Collections; import java.util.UUID; @@ -28,6 +29,7 @@ import org.apache.commons.logging.impl.L import org.apache.hadoop.ha.ActiveStandbyElector.ActiveStandbyElectorCallback; import org.apache.hadoop.ha.ActiveStandbyElector.State; import org.apache.hadoop.ha.HAZKUtil.ZKAuthInfo; +import org.apache.hadoop.util.Shell; import org.apache.log4j.Level; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.server.ZooKeeperServer; @@ -59,6 +61,8 @@ public class TestActiveStandbyElectorRea @Override public void setUp() throws Exception { + // skip tests on Windows until after resolution of ZooKeeper client bug + assumeTrue(!Shell.WINDOWS); super.setUp(); zkServer = getServer(serverFactory); Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverController.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverController.java?rev=1486244&r1=1486243&r2=1486244&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverController.java (original) +++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverController.java Fri May 24 22:36:52 2013 @@ -18,6 +18,7 @@ package org.apache.hadoop.ha; import static org.junit.Assert.*; +import static org.junit.Assume.assumeTrue; import java.security.NoSuchAlgorithmException; @@ -28,6 +29,7 @@ import org.apache.hadoop.ha.HAServicePro import org.apache.hadoop.ha.HealthMonitor.State; import org.apache.hadoop.ha.MiniZKFCCluster.DummyZKFC; import org.apache.hadoop.test.GenericTestUtils; +import org.apache.hadoop.util.Shell; import org.apache.hadoop.util.Time; import org.apache.log4j.Level; import org.apache.zookeeper.KeeperException; @@ -66,6 +68,8 @@ public class TestZKFailoverController ex @Before public void setupConfAndServices() { + // skip tests on Windows until after resolution of ZooKeeper client bug + assumeTrue(!Shell.WINDOWS); conf = new Configuration(); conf.set(ZKFailoverController.ZK_ACL_KEY, TEST_ACL); conf.set(ZKFailoverController.ZK_AUTH_KEY, TEST_AUTH_GOOD); Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverControllerStress.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverControllerStress.java?rev=1486244&r1=1486243&r2=1486244&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverControllerStress.java (original) +++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverControllerStress.java Fri May 24 22:36:52 2013 @@ -17,10 +17,13 @@ */ package org.apache.hadoop.ha; +import static org.junit.Assume.assumeTrue; + import java.util.Random; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.util.Shell; import org.apache.hadoop.util.Time; import org.junit.After; import org.junit.Before; @@ -45,6 +48,8 @@ public class TestZKFailoverControllerStr @Before public void setupConfAndServices() throws Exception { + // skip tests on Windows until after resolution of ZooKeeper client bug + assumeTrue(!Shell.WINDOWS); conf = new Configuration(); conf.set(ZKFailoverController.ZK_QUORUM_KEY, hostPort); this.cluster = new MiniZKFCCluster(conf, getServer(serverFactory)); @@ -52,7 +57,9 @@ public class TestZKFailoverControllerStr @After public void stopCluster() throws Exception { - cluster.stop(); + if (cluster != null) { + cluster.stop(); + } } /** Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestWinUtils.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestWinUtils.java?rev=1486244&r1=1486243&r2=1486244&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestWinUtils.java (original) +++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestWinUtils.java Fri May 24 22:36:52 2013 @@ -19,6 +19,7 @@ package org.apache.hadoop.util; import static org.junit.Assert.*; +import static org.junit.Assume.assumeTrue; import java.io.File; import java.io.FileInputStream; @@ -32,6 +33,8 @@ import org.apache.hadoop.fs.FileUtil; import org.junit.After; import org.junit.Before; import org.junit.Test; +import static org.junit.Assume.*; +import static org.hamcrest.CoreMatchers.*; /** * Test cases for helper Windows winutils.exe utility. @@ -44,6 +47,8 @@ public class TestWinUtils { @Before public void setUp() { + // Not supported on non-Windows platforms + assumeTrue(Shell.WINDOWS); TEST_DIR.mkdirs(); } @@ -70,11 +75,6 @@ public class TestWinUtils { @Test (timeout = 30000) public void testLs() throws IOException { - if (!Shell.WINDOWS) { - // Not supported on non-Windows platforms - return; - } - final String content = "6bytes"; final int contentSize = content.length(); File testFile = new File(TEST_DIR, "file1"); @@ -104,11 +104,6 @@ public class TestWinUtils { @Test (timeout = 30000) public void testGroups() throws IOException { - if (!Shell.WINDOWS) { - // Not supported on non-Windows platforms - return; - } - String currentUser = System.getProperty("user.name"); // Verify that groups command returns information about the current user @@ -229,11 +224,6 @@ public class TestWinUtils { @Test (timeout = 30000) public void testBasicChmod() throws IOException { - if (!Shell.WINDOWS) { - // Not supported on non-Windows platforms - return; - } - // - Create a file. // - Change mode to 377 so owner does not have read permission. // - Verify the owner truly does not have the permissions to read. @@ -285,11 +275,6 @@ public class TestWinUtils { @Test (timeout = 30000) public void testChmod() throws IOException { - if (!Shell.WINDOWS) { - // Not supported on non-Windows platforms - return; - } - testChmodInternal("7", "-------rwx"); testChmodInternal("70", "----rwx---"); testChmodInternal("u-x,g+r,o=g", "-rw-r--r--"); @@ -322,11 +307,6 @@ public class TestWinUtils { @Test (timeout = 30000) public void testChown() throws IOException { - if (!Shell.WINDOWS) { - // Not supported on non-Windows platforms - return; - } - File a = new File(TEST_DIR, "a"); assertTrue(a.createNewFile()); String username = System.getProperty("user.name"); @@ -349,4 +329,117 @@ public class TestWinUtils { assertTrue(a.delete()); assertFalse(a.exists()); } + + @Test (timeout = 30000) + public void testSymlinkRejectsForwardSlashesInLink() throws IOException { + File newFile = new File(TEST_DIR, "file"); + assertTrue(newFile.createNewFile()); + String target = newFile.getPath(); + String link = new File(TEST_DIR, "link").getPath().replaceAll("\\\\", "/"); + try { + Shell.execCommand(Shell.WINUTILS, "symlink", link, target); + fail(String.format("did not receive expected failure creating symlink " + + "with forward slashes in link: link = %s, target = %s", link, target)); + } catch (IOException e) { + LOG.info( + "Expected: Failed to create symlink with forward slashes in target"); + } + } + + @Test (timeout = 30000) + public void testSymlinkRejectsForwardSlashesInTarget() throws IOException { + File newFile = new File(TEST_DIR, "file"); + assertTrue(newFile.createNewFile()); + String target = newFile.getPath().replaceAll("\\\\", "/"); + String link = new File(TEST_DIR, "link").getPath(); + try { + Shell.execCommand(Shell.WINUTILS, "symlink", link, target); + fail(String.format("did not receive expected failure creating symlink " + + "with forward slashes in target: link = %s, target = %s", link, target)); + } catch (IOException e) { + LOG.info( + "Expected: Failed to create symlink with forward slashes in target"); + } + } + + @Test (timeout = 30000) + public void testReadLink() throws IOException { + // Create TEST_DIR\dir1\file1.txt + // + File dir1 = new File(TEST_DIR, "dir1"); + assertTrue(dir1.mkdirs()); + + File file1 = new File(dir1, "file1.txt"); + assertTrue(file1.createNewFile()); + + File dirLink = new File(TEST_DIR, "dlink"); + File fileLink = new File(TEST_DIR, "flink"); + + // Next create a directory symlink to dir1 and a file + // symlink to file1.txt. + // + Shell.execCommand( + Shell.WINUTILS, "symlink", dirLink.toString(), dir1.toString()); + Shell.execCommand( + Shell.WINUTILS, "symlink", fileLink.toString(), file1.toString()); + + // Read back the two links and ensure we get what we expected. + // + String readLinkOutput = Shell.execCommand(Shell.WINUTILS, + "readlink", + dirLink.toString()); + assertThat(readLinkOutput, equalTo(dir1.toString())); + + readLinkOutput = Shell.execCommand(Shell.WINUTILS, + "readlink", + fileLink.toString()); + assertThat(readLinkOutput, equalTo(file1.toString())); + + // Try a few invalid inputs and verify we get an ExitCodeException for each. + // + try { + // No link name specified. + // + Shell.execCommand(Shell.WINUTILS, "readlink", ""); + fail("Failed to get Shell.ExitCodeException when reading bad symlink"); + } catch (Shell.ExitCodeException ece) { + assertThat(ece.getExitCode(), is(1)); + } + + try { + // Bad link name. + // + Shell.execCommand(Shell.WINUTILS, "readlink", "ThereIsNoSuchLink"); + fail("Failed to get Shell.ExitCodeException when reading bad symlink"); + } catch (Shell.ExitCodeException ece) { + assertThat(ece.getExitCode(), is(1)); + } + + try { + // Non-symlink directory target. + // + Shell.execCommand(Shell.WINUTILS, "readlink", dir1.toString()); + fail("Failed to get Shell.ExitCodeException when reading bad symlink"); + } catch (Shell.ExitCodeException ece) { + assertThat(ece.getExitCode(), is(1)); + } + + try { + // Non-symlink file target. + // + Shell.execCommand(Shell.WINUTILS, "readlink", file1.toString()); + fail("Failed to get Shell.ExitCodeException when reading bad symlink"); + } catch (Shell.ExitCodeException ece) { + assertThat(ece.getExitCode(), is(1)); + } + + try { + // Too many parameters. + // + Shell.execCommand(Shell.WINUTILS, "readlink", "a", "b"); + fail("Failed to get Shell.ExitCodeException with bad parameters"); + } catch (Shell.ExitCodeException ece) { + assertThat(ece.getExitCode(), is(1)); + } + } }