正常的 Hadoop 测试运行将测试那些可以通过本地文件系统在本地进行测试的文件系统。这通常意味着通过 HDFS MiniCluster 访问 file://
及其底层的 LocalFileSystem
,以及 hdfs://
。
除非提供文件系统的远程服务器有特定配置,否则将跳过其他文件系统。
这些文件系统绑定必须在 XML 配置文件中定义,通常为 hadoop-common-project/hadoop-common/src/test/resources/contract-test-options.xml
。此文件被排除在外,不应签入。
在 contract-test-options.xml
中,文件系统名称必须在属性 fs.contract.test.fs.ftp
中定义。然后必须提供连接到 FTP 服务器的特定登录选项。
还必须在选项 fs.contract.test.ftp.testdir
中提供测试目录的路径。这是执行操作的目录。
示例
<configuration> <property> <name>fs.contract.test.fs.ftp</name> <value>ftp://server1/</value> </property> <property> <name>fs.ftp.user.server1</name> <value>testuser</value> </property> <property> <name>fs.contract.test.ftp.testdir</name> <value>/home/testuser/test</value> </property> <property> <name>fs.ftp.password.server1</name> <value>secret-login</value> </property> </configuration>
将新文件系统添加到契约测试的核心是添加新契约类,然后为要测试的每个测试套件创建一个新的非抽象测试类。
contract
下创建包(通常)在您自己的测试源代码树中,用于文件和测试。AbstractFSContract
。Test
和文件系统名称开头。示例:TestHDFSRenameContract
。createContract()
。src/test/resources/contract-test-options.xml
文件中定义的任何文件系统绑定。例如,以下是本地文件系统 create()
测试的测试实现。
package org.apache.hadoop.fs.contract.localfs; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.contract.AbstractCreateContractTest; import org.apache.hadoop.fs.contract.AbstractFSContract; public class TestLocalCreateContract extends AbstractCreateContractTest { @Override protected AbstractFSContract createContract(Configuration conf) { return new LocalFSContract(conf); } }
AbstractFSContract
子类的标准实现技术是完全由存储在测试资源树中的 Hadoop XML 配置文件驱动的。最佳做法是将其存储在 /contract
下,文件系统名称为 contract/localfs.xml
。让 XML 文件定义所有文件系统选项使文件系统行为的列表立即可见。
LocalFSContract
是这种情况的一个特例,因为它必须根据其运行的操作系统调整其大小写敏感策略:对于 Windows 和 OS/X,文件系统不区分大小写,因此 ContractOptions.IS_CASE_SENSITIVE
选项必须设置为 false。此外,Windows 文件系统不支持 Unix 文件和目录权限,因此也必须设置相关标志。这是在从资源树加载 XML 契约文件之后完成的,只需更新现在加载的配置选项即可
getConf().setBoolean(getConfKey(ContractOptions.SUPPORTS_UNIX_PERMISSIONS), false);
如果您的新 FileSystem
测试用例未能通过契约测试之一,您可以做什么?
这取决于问题的根源
FileSystem
子类类未正确实现规范。修复。FileSystem
子类隐藏差异,例如通过转换异常。hdfs-dev
邮件列表中提出。请注意,虽然 FileSystem 测试存在于核心 Hadoop 代码库中,但 HDFS 团队拥有 FileSystem 规范及其附带的测试。如果由于不支持某个功能而需要跳过测试,请在 ContractOptions
类中查找现有的配置选项。如果没有方法,短期修复方法是覆盖该方法并使用 ContractTestUtils.skip()
消息来记录跳过测试这一事实。使用此方法会将消息打印到日志,然后告诉测试运行器已跳过测试。这突出了问题。
建议的策略是调用超类,捕获异常,并验证异常类和错误字符串的一部分与当前实现引发的异常相匹配。如果超类实际上成功了,它还应该 fail()
- 即它以当前实现尚未执行的方式失败了。这将确保仍然执行测试路径,测试的任何其他失败(可能是回归)都会被发现。而且,如果该功能确实得到实现,则会发现该更改。
长期解决方案是增强基本测试以添加新的可选功能键。这需要与 hdfs-dev
邮件列表中的开发人员合作。
契约测试包括严格与宽松异常的概念。严格异常报告意味着:使用 IOException
的特定子类(例如 FileNotFoundException
、EOFException
等)报告故障。宽松报告意味着抛出 IOException
。
虽然文件系统应该引发更严格的异常,但可能存在无法引发异常的原因。仍然允许引发宽松异常,它只是妨碍用户应用程序中故障的诊断。要声明文件系统不支持更严格的异常,请将选项 fs.contract.supports-strict-exceptions
设置为 false。
针对远程文件系统的测试需要指定到文件系统的 URL;针对需要登录详细信息的远程文件系统的测试需要用户名/ID 和密码。
所有这些详细信息必须放置在文件 src/test/resources/contract-test-options.xml
中,并且配置 SCM 工具以从不将此文件提交到 Subversion、Git 或同等工具中。此外,必须配置构建以从生成的任何 -test
工件中从不捆绑此文件。Hadoop 构建执行此操作,从 JAR 文件中排除 src/test/**/*.xml
。此外,需要创建 src/test/resources/auth-keys.xml
。它可以是 contract-test-options.xml
的副本。如果存在,AbstractFSContract
类会自动加载此资源文件;可以添加特定测试用例的特定密钥。
例如,以下是 S3A 测试密钥的外观
<configuration> <property> <name>fs.contract.test.fs.s3a</name> <value>s3a://tests3contract</value> </property> <property> <name>fs.s3a.access.key</name> <value>DONOTPCOMMITTHISKEYTOSCM</value> </property> <property> <name>fs.s3a.secret.key</name> <value>DONOTEVERSHARETHISSECRETKEY!</value> </property> </configuration>
如果在属性 fs.contract.test.fs.%s
中未定义文件系统 URL,则 AbstractBondedFSContract
会自动跳过测试套件,其中 %s
匹配文件系统的架构名称。
在运行测试时,需要关闭 maven.test.skip
,因为它在这些测试中默认情况下为 true。可以使用类似 mvn test -Ptests-on
的命令执行此操作。
通过所有文件系统契约测试并不意味着文件系统可以被描述为“与 HDFS 兼容”。这些测试尝试查看每个操作的隔离功能,并关注每个操作的前提条件和后置条件。未涵盖的核心领域是并发性和分布式系统中的故障方面。
文件系统 API 的使用还有一些特定方面
hadoop -fs
CLI 的兼容性。当然,欢迎对这些行为进行验证的测试。
seek()
、rename()
、create()
等。这是为了匹配文件系统契约规范按操作拆分的方式。它还使文件系统实现者一次处理一个测试套件变得更容易。AbstractFSContractTestBase
进行子类化。同样,在标题中使用 Abstract
。org.apache.hadoop.fs.contract.ContractTestUtils
,了解有助于测试的实用程序类,其中包含许多以文件系统为中心的断言。使用这些断言对文件系统状态进行断言,并在断言实际失败时包含诊断信息,如目录列表和不匹配文件的转储。一些测试直接针对根文件系统进行,尝试执行重命名“/”和类似操作等操作。根目录是“特殊的”,测试这一点非常重要,尤其是在非 POSIX 文件系统(如对象存储)上。这些测试可能对本机文件系统非常具有破坏性,因此请小心使用。
在 AbstractRootDirectoryContractTest
下添加测试,或创建一个新测试,其中 (a) 标题中包含 Root
,(b) 设置方法中包含一个检查,以在禁用根测试时跳过测试
skipIfUnsupported(TEST_ROOT_TESTS_ENABLED);
不要提供针对本地 FS 运行此测试套件的实现。
旨在生成可扩展负载的测试 - 包括大量小文件以及较少的大文件,应设计为可配置的,以便测试套件的用户可以配置文件数量和大小。
请注意,在对象存储上,目录重命名操作通常为 O(files)*O(data)
,而删除操作为 O(files)
。后者意味着即使任何目录清理操作也可能需要时间,并且可能会超时。设计针对远程文件系统的测试非常重要,因为所有操作都可能延迟。
该规范不完整。它没有完全涵盖 FileSystem 类,并且可能有一些未涵盖的现有指定类部分。