測試檔案系統合約

執行測試

正常的 Hadoop 測試執行會測試那些可透過本機檔案系統在本地端測試的檔案系統。這通常表示透過 HDFS MiniCluster 執行 file:// 及其底層的 LocalFileSystem,以及 hdfs://

除非有提供檔案系統的遠端伺服器之特定組態,否則會略過其他檔案系統。

這些檔案系統繫結必須在 XML 組態檔案中定義,通常為 hadoop-common-project/hadoop-common/src/test/resources/contract-test-options.xml。此檔案會被排除,且不應簽入。

ftp://

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>

測試新的檔案系統

在合約測試中新增新的檔案系統的核心是新增一個新的合約類別,然後為每個您想測試的測試套件建立一個新的非抽象測試類別。

  1. 請勿嘗試將這些測試新增到 Hadoop 本身。它們不會被新增到原始碼樹中。測試必須與您自己的檔案系統原始碼共存。
  2. 在您的測試原始碼樹中建立一個套件 (通常在 contract 下),供檔案和測試使用。
  3. 為您自己的合約實作建立 AbstractFSContract 的子類別。
  4. 對於您計畫支援的每個測試套件,建立一個非抽象子類別,名稱以 Test 和檔案系統的名稱開頭。範例:TestHDFSRenameContract
  5. 這些非抽象類別必須實作抽象方法 createContract()
  6. 識別並記錄特定專案的 src/test/resources/contract-test-options.xml 檔案中必須定義的任何檔案系統繫結。
  7. 執行測試,直到它們運作為止。

以下為本地檔案系統的 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 測試案例未通過合約測試之一,您可以怎麼做?

這取決於問題的原因

  1. 案例:自訂 FileSystem 子類別類別未正確實作規格。修正。
  2. 案例:基礎檔案系統的行為與 Hadoop 的預期不符。理想情況下,修正。或嘗試讓您的 FileSystem 子類別隱藏差異,例如透過轉換例外。
  3. 案例:您的檔案系統與 Hadoop 之間存在基本架構差異。範例:不同的並行性和一致性模型。建議:記錄並清楚說明檔案系統與 HDFS 不相容。
  4. 案例:測試與規格不符。修正:修補測試,將修補程式提交至 Hadoop。
  5. 案例:規格不正確。基礎規格(少數例外情況除外)為 HDFS。如果規格與 HDFS 不符,通常應假設 HDFS 為 FileSystem 應執行的操作之實際定義。如果發生不符情況,請在 hdfs-dev 郵件清單中提出。請注意,儘管 FileSystem 測試存在於核心 Hadoop 程式碼庫中,但擁有 FileSystem 規格及其隨附測試的是 HDFS 團隊。

如果測試需要略過,因為某項功能不受支援,請在 ContractOptions 類別中尋找現有的組態選項。如果沒有方法,短期修正方法是覆寫方法並使用 ContractTestUtils.skip() 訊息來記錄略過測試的事實。使用此方法會將訊息列印至記錄檔,然後告訴測試執行器測試已略過。這會突顯問題。

建議的策略是呼叫超類別、捕捉例外情況,並驗證例外情況類別和錯誤字串的一部分與目前實作所引發的相符。如果超類別實際上已成功(也就是說,它失敗的方式與實作目前未執行的相同),它也應 fail()。這將確保測試路徑仍會執行,測試的任何其他失敗(可能是回歸)都會被發現。而且,如果功能已實作,則會發現變更。

長期解決方案是增強基本測試以新增新的選用功能金鑰。這需要與 hdfs-dev 郵件清單上的開發人員合作。

「Lax vs Strict」例外情況

合約測試包含嚴格與寬鬆例外情況的概念。嚴格例外情況報告表示:使用 IOException 的特定子類別報告失敗,例如 FileNotFoundExceptionEOFException 等。寬鬆報告表示擲回 IOException

儘管 FileSystem 應引發更嚴格的例外情況,但可能存在無法引發的原因。仍允許引發寬鬆例外情況,它僅會阻礙使用者應用程式中失敗的診斷。若要宣告 FileSystem 不支援更嚴格的例外情況,請將選項 fs.contract.supports-strict-exceptions 設為 false。

支援具有登入和驗證參數的 FileSystem

針對遠端檔案系統的測試需要指定檔案系統的 URL;針對需要登入詳細資料的遠端檔案系統的測試需要使用者名稱/ID 和密碼。

所有這些詳細資料都必須放在檔案 src/test/resources/contract-test-options.xml 中,且您的 SCM 工具設定為絕不將此檔案提交至 Subversion、Git 或等效工具。此外,建置必須設定為絕不將此檔案綑綁在任何產生的 -test 人工製品中。Hadoop 建置會執行此動作,將 src/test/**/*.xml 排除在 JAR 檔案之外。此外,需要建立 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 相容」。這些測試會嘗試檢視每個操作的獨立功能,並專注於每個動作的前置條件和後置條件。未涵蓋的核心領域為並行性和分布式系統的故障面向。

  • 一致性:所有變更是否立即可見?
  • 原子性:HDFS 保證為原子的操作在新的檔案系統中是否也同樣為原子?
  • 冪等性:如果檔案系統實作任何重試原則,即使其他用戶端操作檔案系統,它是否仍為冪等?
  • 可擴充性:它是否支援與 HDFS 一樣大的檔案,或在單一目錄中支援與 HDFS 一樣多的檔案?
  • 耐用性:檔案是否實際上會持續存在,且持續多久?

檔案系統 API 的使用也有一些特定面向

  • hadoop -fs CLI 相容。
  • 區塊大小原則是否會產生適合分析工作的檔案分割。(例如,區塊大小為 1 符合規格,但由於它會指示 MapReduce 工作一次處理一個位元組,因此無法使用)。

歡迎驗證這些行為的測試。

新增測試套件

  1. 新的測試應使用每個作業一個測試類別來區分,就像對 seek()rename()create() 等執行的作業一樣。這是為了符合 FileSystem 合約規範依作業區分的拆分方式。這也能讓 FileSystem 實作者一次處理一個測試套件,更為容易。
  2. 使用新的抽象測試套件類別,繼承 AbstractFSContractTestBase。再次強調,在標題中使用 Abstract
  3. 查看 org.apache.hadoop.fs.contract.ContractTestUtils,取得有助於測試的實用程式類別,其中包含許多以檔案系統為中心的斷言。使用這些斷言來對檔案系統狀態進行斷言,並在斷言實際失敗時,包含目錄清單和不匹配檔案的傾印等診斷資訊。
  4. 針對本機、原生本機和 HDFS 檔案系統撰寫測試 - 如果其中一個測試失敗,就表示有問題的跡象 - 儘管要注意它們確實有差異
  5. 在核心檔案系統通過測試後,在物件儲存體上進行測試。
  6. 嘗試記錄失敗,並提供盡可能多的詳細資訊 - 除錯失敗的人員會很感激。

根目錄操作測試

某些測試會直接針對根檔案系統執行,嘗試執行類似變更 “/” 等動作。根目錄是 “特殊的”,測試這一點很重要,特別是在非 POSIX 檔案系統(例如物件儲存體)上。這些測試可能會對原生檔案系統造成極大的破壞,因此請小心使用。

  1. AbstractRootDirectoryContractTest 下新增測試,或建立新的測試,其中 (a) 標題中包含 Root,以及 (b) 在設定方法中檢查,如果已停用根目錄測試,則略過測試

      skipIfUnsupported(TEST_ROOT_TESTS_ENABLED);
    
  2. 不要提供針對本機 FS 執行的此測試套件實作。

擴充性測試

設計用於產生可擴充性負載的測試 - 包括大量的檔案,以及較少的較大檔案,應設計為可設定,以便測試套件使用者可以設定檔案數量和大小。

請注意,在物件儲存體上,目錄變更作業通常為 O(files)*O(data),而刪除作業為 O(files)。後者表示,甚至任何目錄清理作業都可能需要時間,並可能逾時。設計測試時,務必考慮到在所有作業中都可能延遲的遠端檔案系統。

擴充規格

規格並不完整。它沒有完整涵蓋 FileSystem 類別,而且現有已指定類別中可能有些部分未涵蓋。

  1. 查看類別/介面/方法的實作,以了解它們的作用,特別是 HDFS 和本機。這些是目前已完成工作的文件。
  2. 查看 POSIX API 規格。
  3. 在 HDFS JIRA 中搜尋關於 FileSystem 主題的討論,並嘗試了解預期會發生什麼事,以及實際上發生了什麼事。
  4. 使用 IDE 找出方法如何在 Hadoop、HBase 和堆疊的其他部分中使用。雖然這假設這些是代表性的 Hadoop 應用程式,但它至少會顯示應用程式預期FileSystem 如何運作。
  5. 查看 java.io 來源,了解預期已綁定的 FileSystem 類別如何運作,並仔細閱讀其 javadoc。
  6. 如果有些東西不清楚,請在 hdfs-dev 清單中提出。
  7. 不要害怕撰寫測試作為實驗,並釐清實際發生了什麼事。使用 HDFS 行為作為規範指南。