You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by ae...@apache.org on 2018/01/02 18:16:16 UTC
[37/38] hadoop git commit: HADOOP-15117. open(PathHandle) contract
test should be exhaustive for default options
HADOOP-15117. open(PathHandle) contract test should be exhaustive for default options
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/7fe6f83c
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/7fe6f83c
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/7fe6f83c
Branch: refs/heads/HDFS-7240
Commit: 7fe6f83c8f0f67b1456c37d94b0de807e81a904a
Parents: 4bb765e
Author: Chris Douglas <cd...@apache.org>
Authored: Sat Dec 30 17:58:35 2017 -0800
Committer: Chris Douglas <cd...@apache.org>
Committed: Sat Dec 30 17:58:35 2017 -0800
----------------------------------------------------------------------
.../fs/contract/AbstractContractOpenTest.java | 258 -------------------
.../AbstractContractPathHandleTest.java | 246 ++++++++++++++++++
.../hadoop/hdfs/protocol/HdfsPathHandle.java | 3 +
.../hdfs/TestHDFSContractPathHandle.java | 55 ++++
4 files changed, 304 insertions(+), 258 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hadoop/blob/7fe6f83c/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractOpenTest.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractOpenTest.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractOpenTest.java
index ab179eb..d475c6e 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractOpenTest.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractOpenTest.java
@@ -19,27 +19,17 @@ package org.apache.hadoop.fs.contract;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.InvalidPathHandleException;
-import org.apache.hadoop.fs.Options.HandleOpt;
import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.fs.PathHandle;
-import org.apache.hadoop.fs.RawPathHandle;
import org.apache.hadoop.io.IOUtils;
-import static org.apache.hadoop.fs.contract.ContractTestUtils.appendFile;
import static org.apache.hadoop.fs.contract.ContractTestUtils.createFile;
import static org.apache.hadoop.fs.contract.ContractTestUtils.dataset;
-import static org.apache.hadoop.fs.contract.ContractTestUtils.skip;
import static org.apache.hadoop.fs.contract.ContractTestUtils.touch;
-import static org.apache.hadoop.fs.contract.ContractTestUtils.verifyRead;
-import static org.apache.hadoop.fs.contract.ContractTestUtils.verifyFileContents;
import org.junit.Test;
@@ -173,252 +163,4 @@ public abstract class AbstractContractOpenTest
instream.close();
}
- /**
- * Skip a test case if the FS doesn't support file references.
- * The feature is assumed to be unsupported unless stated otherwise.
- */
- protected void assumeSupportsFileReference() throws IOException {
- if (getContract().isSupported(SUPPORTS_FILE_REFERENCE, false)) {
- return;
- }
- skip("Skipping as unsupported feature: " + SUPPORTS_FILE_REFERENCE);
- }
-
- /**
- * Skip a test case if the FS doesn't support content validation.
- * The feature is assumed to be unsupported unless stated otherwise.
- */
- protected void assumeSupportsContentCheck() throws IOException {
- if (getContract().isSupported(SUPPORTS_CONTENT_CHECK, false)) {
- return;
- }
- skip("Skipping as unsupported feature: " + SUPPORTS_CONTENT_CHECK);
- }
-
- private PathHandle getHandleOrSkip(FileStatus stat, HandleOpt... opts) {
- try {
- return getFileSystem().getPathHandle(stat, opts);
- } catch (UnsupportedOperationException e) {
- skip("FileSystem does not support " + Arrays.toString(opts));
- }
- // unreachable
- return null;
- }
-
- /**
- * Verify {@link HandleOpt#exact()} handle semantics.
- * @throws Throwable on error
- */
- @Test
- public void testOpenFileByExact() throws Throwable {
- describe("verify open(getPathHandle(FileStatus, exact())) operations" +
- "detect changes");
- assumeSupportsContentCheck();
- assumeSupportsFileReference();
- Path path1 = path("testopenfilebyexact1");
- Path path2 = path("testopenfilebyexact2");
- byte[] file1 = dataset(TEST_FILE_LEN, 43, 255);
- createFile(getFileSystem(), path1, false, file1);
- FileStatus stat1 = getFileSystem().getFileStatus(path1);
- assertNotNull(stat1);
- assertEquals(path1, stat1.getPath());
- ContractTestUtils.rename(getFileSystem(), path1, path2);
- FileStatus stat2 = getFileSystem().getFileStatus(path2);
- assertNotNull(stat2);
- assertEquals(path2, stat2.getPath());
- // create identical file at same location, orig still exists at path2
- createFile(getFileSystem(), path1, false, file1);
-
- PathHandle fd1 = getHandleOrSkip(stat1, HandleOpt.exact());
- PathHandle fd2 = getHandleOrSkip(stat2, HandleOpt.exact());
-
- // verify path1, path2 contents identical
- verifyFileContents(getFileSystem(), path1, file1);
- verifyFileContents(getFileSystem(), path2, file1);
- try {
- // the PathHandle will not resolve, even though
- // the original entity exists, it has not been modified, and an
- // identical file exists at the old path. The handle would also
- // fail to resolve if path1 had been modified
- instream = getFileSystem().open(fd1);
- fail("Expected an exception");
- } catch (InvalidPathHandleException e) {
- // expected
- }
-
- // verify unchanged resolves
- instream = getFileSystem().open(fd2);
- verifyRead(instream, file1, 0, TEST_FILE_LEN);
- }
-
- /**
- * Verify {@link HandleOpt#content()} handle semantics.
- * @throws Throwable on error
- */
- @Test
- public void testOpenFileByContent() throws Throwable {
- describe("verify open(getPathHandle(FileStatus, content())) operations" +
- "follow relocation");
- assumeSupportsContentCheck();
- assumeSupportsFileReference();
- Path path1 = path("testopenfilebycontent1");
- Path path2 = path("testopenfilebycontent2");
- byte[] file1 = dataset(TEST_FILE_LEN, 43, 255);
- createFile(getFileSystem(), path1, false, file1);
- FileStatus stat = getFileSystem().getFileStatus(path1);
- assertNotNull(stat);
- assertEquals(path1, stat.getPath());
- // rename the file after obtaining FileStatus
- ContractTestUtils.rename(getFileSystem(), path1, path2);
-
- // obtain handle to entity from #getFileStatus call
- PathHandle fd = getHandleOrSkip(stat, HandleOpt.content());
-
- try (FSDataInputStream in = getFileSystem().open(fd)) {
- // verify read of consistent content at new location
- verifyRead(in, file1, 0, TEST_FILE_LEN);
- }
-
- // modify the file at its new location by appending data
- byte[] file1a = dataset(TEST_FILE_LEN, 44, 255);
- appendFile(getFileSystem(), path2, file1a);
- byte[] file1x = Arrays.copyOf(file1, file1.length + file1a.length);
- System.arraycopy(file1a, 0, file1x, file1.length, file1a.length);
- // verify fd entity contains contents of file1 + appended bytes
- verifyFileContents(getFileSystem(), path2, file1x);
-
- try {
- // handle should not resolve when content changed
- instream = getFileSystem().open(fd);
- fail("Failed to detect change to content");
- } catch (InvalidPathHandleException e) {
- // expected
- }
- }
-
-
- /**
- * Verify {@link HandleOpt#path()} handle semantics.
- * @throws Throwable on error
- */
- @Test
- public void testOpenFileByPath() throws Throwable {
- describe("verify open(getPathHandle(FileStatus, path())) operations" +
- "detect changes");
- assumeSupportsContentCheck();
- Path path1 = path("testopenfilebypath1");
- Path path2 = path("testopenfilebypath2");
-
- byte[] file1 = dataset(TEST_FILE_LEN, 43, 255);
- createFile(getFileSystem(), path1, false, file1);
- FileStatus stat1 = getFileSystem().getFileStatus(path1);
- assertNotNull(stat1);
- assertEquals(path1, stat1.getPath());
- ContractTestUtils.rename(getFileSystem(), path1, path2);
- FileStatus stat2 = getFileSystem().getFileStatus(path2);
- assertNotNull(stat2);
- assertEquals(path2, stat2.getPath());
- // create identical file at same location, orig still exists at path2
- createFile(getFileSystem(), path1, false, file1);
-
- PathHandle fd1 = getHandleOrSkip(stat1, HandleOpt.path());
- PathHandle fd2 = getHandleOrSkip(stat2, HandleOpt.path());
-
- // verify path1, path2 contents identical
- verifyFileContents(getFileSystem(), path1, file1);
- verifyFileContents(getFileSystem(), path2, file1);
- try {
- // verify attempt to resolve the handle fails
- instream = getFileSystem().open(fd1);
- fail("Expected an exception");
- } catch (InvalidPathHandleException e) {
- // expected
- }
-
- // verify content change OK
- byte[] file2a = dataset(TEST_FILE_LEN, 44, 255);
- ContractTestUtils.appendFile(getFileSystem(), path2, file2a);
- byte[] file2x = Arrays.copyOf(file1, file1.length + file2a.length);
- System.arraycopy(file2a, 0, file2x, file1.length, file2a.length);
- // verify path2 contains contents of orig + appended bytes
- verifyFileContents(getFileSystem(), path2, file2x);
- // verify open by fd succeeds
- instream = getFileSystem().open(fd2);
- verifyRead(instream, file2x, 0, 2 * TEST_FILE_LEN);
- }
-
- /**
- * Verify {@link HandleOpt#reference()} handle semantics.
- * @throws Throwable on error
- */
- @Test
- public void testOpenFileByReference() throws Throwable {
- describe("verify open(getPathHandle(FileStatus, reference())) operations" +
- " are independent of rename");
- assumeSupportsFileReference();
- Path path1 = path("testopenfilebyref1");
- Path path2 = path("testopenfilebyref2");
-
- byte[] file1 = dataset(TEST_FILE_LEN, 43, 255);
- createFile(getFileSystem(), path1, false, file1);
- FileStatus stat = getFileSystem().getFileStatus(path1);
- assertNotNull(stat);
- assertEquals(path1, stat.getPath());
- ContractTestUtils.rename(getFileSystem(), path1, path2);
-
- byte[] file2 = dataset(TEST_FILE_LEN, 44, 255);
- createFile(getFileSystem(), path1, false, file2);
- byte[] file1a = dataset(TEST_FILE_LEN, 42, 255);
- appendFile(getFileSystem(), path2, file1a);
- byte[] file1x = Arrays.copyOf(file1, file1.length + file1a.length);
- System.arraycopy(file1a, 0, file1x, file1.length, file1a.length);
-
- PathHandle fd = getHandleOrSkip(stat, HandleOpt.reference());
-
- // verify path2 contains contents of file1 + appended bytes
- verifyFileContents(getFileSystem(), path2, file1x);
- // verify path1 contents contents of file2
- verifyFileContents(getFileSystem(), path1, file2);
-
- // verify fd contains contents of file1 + appended bytes
- instream = getFileSystem().open(fd);
- verifyRead(instream, file1x, 0, 2 * TEST_FILE_LEN);
- }
-
- /**
- * Verify {@link PathHandle} may be serialized and restored.
- * @throws Throwable on error
- */
- @Test
- public void testOpenFileBySerializedReference() throws Throwable {
- describe("verify PathHandle supports generic serialization");
- assumeSupportsFileReference();
- Path path1 = path("testopenfilebyref1");
- Path path2 = path("testopenfilebyref2");
-
- byte[] file1 = dataset(TEST_FILE_LEN, 43, 255);
- createFile(getFileSystem(), path1, false, file1);
- FileStatus stat = getFileSystem().getFileStatus(path1);
- assertNotNull(stat);
- assertEquals(path1, stat.getPath());
- ContractTestUtils.rename(getFileSystem(), path1, path2);
-
- byte[] file2 = dataset(TEST_FILE_LEN, 44, 255);
- createFile(getFileSystem(), path1, false, file2);
-
- PathHandle fd = getHandleOrSkip(stat, HandleOpt.reference());
-
- // serialize PathHandle
- ByteBuffer sb = fd.bytes();
- PathHandle fdb = new RawPathHandle(sb);
-
- instream = getFileSystem().open(fdb);
- // verify stat contains contents of file1
- verifyRead(instream, file1, 0, TEST_FILE_LEN);
- // verify path2 contains contents of file1
- verifyFileContents(getFileSystem(), path2, file1);
- // verify path1 contents contents of file2
- verifyFileContents(getFileSystem(), path1, file2);
- }
-
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/7fe6f83c/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractPathHandleTest.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractPathHandleTest.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractPathHandleTest.java
new file mode 100644
index 0000000..fbe28c3
--- /dev/null
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractPathHandleTest.java
@@ -0,0 +1,246 @@
+/*
+ * 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.
+ */
+package org.apache.hadoop.fs.contract;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FSDataInputStream;
+import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.fs.InvalidPathHandleException;
+import org.apache.hadoop.fs.Options.HandleOpt;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.PathHandle;
+import static org.apache.hadoop.fs.contract.ContractTestUtils.appendFile;
+import static org.apache.hadoop.fs.contract.ContractTestUtils.createFile;
+import static org.apache.hadoop.fs.contract.ContractTestUtils.dataset;
+import static org.apache.hadoop.fs.contract.ContractTestUtils.skip;
+import static org.apache.hadoop.fs.contract.ContractTestUtils.verifyRead;
+import static org.apache.hadoop.fs.contract.ContractTestUtils.verifyFileContents;
+import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.IO_FILE_BUFFER_SIZE_KEY;
+
+import org.apache.hadoop.fs.RawPathHandle;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * Test {@link PathHandle} operations and semantics.
+ * @see ContractOptions#SUPPORTS_FILE_REFERENCE
+ * @see ContractOptions#SUPPORTS_CONTENT_CHECK
+ * @see org.apache.hadoop.fs.FileSystem#getPathHandle(FileStatus, HandleOpt...)
+ * @see org.apache.hadoop.fs.FileSystem#open(PathHandle)
+ * @see org.apache.hadoop.fs.FileSystem#open(PathHandle, int)
+ */
+@RunWith(Parameterized.class)
+public abstract class AbstractContractPathHandleTest
+ extends AbstractFSContractTestBase {
+
+ private final HandleOpt[] opts;
+ private final boolean serialized;
+
+ private static final byte[] B1 = dataset(TEST_FILE_LEN, 43, 255);
+ private static final byte[] B2 = dataset(TEST_FILE_LEN, 44, 255);
+
+ /**
+ * Create an instance of the test from {@link #params()}.
+ * @param testname Name of the set of options under test
+ * @param opts Set of {@link HandleOpt} params under test.
+ * @param serialized Serialize the handle before using it.
+ */
+ public AbstractContractPathHandleTest(String testname, HandleOpt[] opts,
+ boolean serialized) {
+ this.opts = opts;
+ this.serialized = serialized;
+ }
+
+ /**
+ * Run test against all combinations of default options. Also run each
+ * after converting the PathHandle to bytes and back.
+ * @return
+ */
+ @Parameterized.Parameters(name="Test{0}")
+ public static Collection<Object[]> params() {
+ return Arrays.asList(
+ Arrays.asList("Exact", HandleOpt.exact()),
+ Arrays.asList("Content", HandleOpt.content()),
+ Arrays.asList("Path", HandleOpt.path()),
+ Arrays.asList("Reference", HandleOpt.reference())
+ ).stream()
+ .flatMap((x) -> Arrays.asList(true, false).stream()
+ .map((b) -> {
+ ArrayList<Object> y = new ArrayList<>(x);
+ y.add(b);
+ return y;
+ }))
+ .map(ArrayList::toArray)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ protected Configuration createConfiguration() {
+ Configuration conf = super.createConfiguration();
+ conf.setInt(IO_FILE_BUFFER_SIZE_KEY, 4096);
+ return conf;
+ }
+
+ @Test
+ public void testIdent() throws IOException {
+ describe("verify simple open, no changes");
+ FileStatus stat = testFile(B1);
+ PathHandle fd = getHandleOrSkip(stat);
+ verifyFileContents(getFileSystem(), stat.getPath(), B1);
+
+ try (FSDataInputStream in = getFileSystem().open(fd)) {
+ verifyRead(in, B1, 0, TEST_FILE_LEN);
+ }
+ }
+
+ @Test
+ public void testChanged() throws IOException {
+ describe("verify open(PathHandle, changed(*))");
+ assumeSupportsContentCheck();
+ HandleOpt.Data data = HandleOpt.getOpt(HandleOpt.Data.class, opts)
+ .orElseThrow(IllegalArgumentException::new);
+ FileStatus stat = testFile(B1);
+ // modify the file by appending data
+ appendFile(getFileSystem(), stat.getPath(), B2);
+ byte[] b12 = Arrays.copyOf(B1, B1.length + B2.length);
+ System.arraycopy(B2, 0, b12, B1.length, B2.length);
+ // verify fd entity contains contents of file1 + appended bytes
+ verifyFileContents(getFileSystem(), stat.getPath(), b12);
+ // get the handle *after* the file has been modified
+ PathHandle fd = getHandleOrSkip(stat);
+
+ try (FSDataInputStream in = getFileSystem().open(fd)) {
+ assertTrue("Failed to detect content change", data.allowChange());
+ verifyRead(in, b12, 0, b12.length);
+ } catch (InvalidPathHandleException e) {
+ assertFalse("Failed to allow content change", data.allowChange());
+ }
+ }
+
+ @Test
+ public void testMoved() throws IOException {
+ describe("verify open(PathHandle, moved(*))");
+ assumeSupportsFileReference();
+ HandleOpt.Location loc = HandleOpt.getOpt(HandleOpt.Location.class, opts)
+ .orElseThrow(IllegalArgumentException::new);
+ FileStatus stat = testFile(B1);
+ // rename the file after obtaining FileStatus
+ ContractTestUtils.rename(getFileSystem(), stat.getPath(),
+ path(stat.getPath() + "2"));
+ // obtain handle to entity from #getFileStatus call
+ PathHandle fd = getHandleOrSkip(stat);
+
+ try (FSDataInputStream in = getFileSystem().open(fd)) {
+ assertTrue("Failed to detect location change", loc.allowChange());
+ verifyRead(in, B1, 0, B1.length);
+ } catch (InvalidPathHandleException e) {
+ assertFalse("Failed to allow location change", loc.allowChange());
+ }
+ }
+
+ @Test
+ public void testChangedAndMoved() throws IOException {
+ describe("verify open(PathHandle, changed(*), moved(*))");
+ assumeSupportsFileReference();
+ assumeSupportsContentCheck();
+ HandleOpt.Data data = HandleOpt.getOpt(HandleOpt.Data.class, opts)
+ .orElseThrow(IllegalArgumentException::new);
+ HandleOpt.Location loc = HandleOpt.getOpt(HandleOpt.Location.class, opts)
+ .orElseThrow(IllegalArgumentException::new);
+ FileStatus stat = testFile(B1);
+ Path dst = path(stat.getPath() + "2");
+ ContractTestUtils.rename(getFileSystem(), stat.getPath(), dst);
+ appendFile(getFileSystem(), dst, B2);
+ PathHandle fd = getHandleOrSkip(stat);
+
+ byte[] b12 = Arrays.copyOf(B1, B1.length + B2.length);
+ System.arraycopy(B2, 0, b12, B1.length, B2.length);
+ try (FSDataInputStream in = getFileSystem().open(fd)) {
+ assertTrue("Failed to detect location change", loc.allowChange());
+ assertTrue("Failed to detect content change", data.allowChange());
+ verifyRead(in, b12, 0, b12.length);
+ } catch (InvalidPathHandleException e) {
+ if (data.allowChange()) {
+ assertFalse("Failed to allow location change", loc.allowChange());
+ }
+ if (loc.allowChange()) {
+ assertFalse("Failed to allow content change", data.allowChange());
+ }
+ }
+ }
+
+ private FileStatus testFile(byte[] content) throws IOException {
+ Path path = path(methodName.getMethodName());
+ createFile(getFileSystem(), path, false, content);
+ FileStatus stat = getFileSystem().getFileStatus(path);
+ assertNotNull(stat);
+ assertEquals(path, stat.getPath());
+ return stat;
+ }
+
+ /**
+ * Skip a test case if the FS doesn't support file references.
+ * The feature is assumed to be unsupported unless stated otherwise.
+ */
+ protected void assumeSupportsFileReference() throws IOException {
+ if (getContract().isSupported(SUPPORTS_FILE_REFERENCE, false)) {
+ return;
+ }
+ skip("Skipping as unsupported feature: " + SUPPORTS_FILE_REFERENCE);
+ }
+
+ /**
+ * Skip a test case if the FS doesn't support content validation.
+ * The feature is assumed to be unsupported unless stated otherwise.
+ */
+ protected void assumeSupportsContentCheck() throws IOException {
+ if (getContract().isSupported(SUPPORTS_CONTENT_CHECK, false)) {
+ return;
+ }
+ skip("Skipping as unsupported feature: " + SUPPORTS_CONTENT_CHECK);
+ }
+
+ /**
+ * Utility method to obtain a handle or skip the test if the set of opts
+ * are not supported.
+ * @param stat Target file status
+ * @return Handle to the indicated entity or skip the test
+ */
+ protected PathHandle getHandleOrSkip(FileStatus stat) {
+ try {
+ PathHandle fd = getFileSystem().getPathHandle(stat, opts);
+ if (serialized) {
+ ByteBuffer sb = fd.bytes();
+ return new RawPathHandle(sb);
+ }
+ return fd;
+ } catch (UnsupportedOperationException e) {
+ skip("FileSystem does not support " + Arrays.toString(opts));
+ }
+ // unreachable
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/7fe6f83c/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/HdfsPathHandle.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/HdfsPathHandle.java b/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/HdfsPathHandle.java
index 14661ae..a04aeeb 100644
--- a/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/HdfsPathHandle.java
+++ b/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/HdfsPathHandle.java
@@ -66,6 +66,9 @@ public final class HdfsPathHandle implements PathHandle {
public void verify(HdfsLocatedFileStatus stat)
throws InvalidPathHandleException {
+ if (null == stat) {
+ throw new InvalidPathHandleException("Could not resolve handle");
+ }
if (mtime != null && mtime != stat.getModificationTime()) {
throw new InvalidPathHandleException("Content changed");
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/7fe6f83c/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/fs/contract/hdfs/TestHDFSContractPathHandle.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/fs/contract/hdfs/TestHDFSContractPathHandle.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/fs/contract/hdfs/TestHDFSContractPathHandle.java
new file mode 100644
index 0000000..c65a60b
--- /dev/null
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/fs/contract/hdfs/TestHDFSContractPathHandle.java
@@ -0,0 +1,55 @@
+/**
+ * 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.
+ */
+package org.apache.hadoop.fs.contract.hdfs;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Options;
+import org.apache.hadoop.fs.contract.AbstractContractPathHandleTest;
+import org.apache.hadoop.fs.contract.AbstractFSContract;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+import java.io.IOException;
+
+/**
+ * Verify HDFS compliance with {@link org.apache.hadoop.fs.PathHandle}
+ * semantics.
+ */
+public class TestHDFSContractPathHandle
+ extends AbstractContractPathHandleTest {
+
+ public TestHDFSContractPathHandle(String testname, Options.HandleOpt[] opts,
+ boolean serialized) {
+ super(testname, opts, serialized);
+ }
+
+ @BeforeClass
+ public static void createCluster() throws IOException {
+ HDFSContract.createCluster();
+ }
+
+ @AfterClass
+ public static void teardownCluster() throws IOException {
+ HDFSContract.destroyCluster();
+ }
+
+ @Override
+ protected AbstractFSContract createContract(Configuration conf) {
+ return new HDFSContract(conf);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org