重要なSQLite DBファイルの読み取りに失敗した場合(I/Oエラーの原因)、ソフトウェアが期待どおりに反応するかどうかを自動的にテストしたいと思います。まさにそれは数日前にクライアントで起こった。手動で修正しましたが、修正するための自動コードを作成し、壊れたファイルにアクセスしてテストする必要があります。
Unixのすべてがファイルであるため、私がファイルを読み取ろうとすると(たとえば、/ devに)常にI/Oエラーを引き起こす特別なファイルがあるのではないかと思いました。
同様のファイル(imo)は次のようになります。
/dev/full
書き込もうとすると、常に「デバイスに空き容量がありません」と表示されます/dev/null
および/dev/zero
だから私はそのようなファイルがあるべきだと思いました(しかしまだ見つけていません)。
誰かがそのようなファイルまたは他の方法を知っていて、私が望ましい結果を得ることができますか(故意に障害のあるパーティションイメージ、LD_PRELOADを使用したopen()のラッパーなど)。
ここに行くための最良の方法は何ですか?
dmsetup
を使用すると、error
またはflakey
ターゲットを使用してデバイスマッパーデバイスを作成し、障害をシミュレートできます。
dmsetup create test --table '0 123 flakey 1 0 /dev/loop0'
ここで、123はデバイスの長さ(セクター単位)で、/ dev/loop0はエラーをシミュレートする元のデバイスです。エラーの場合、常にエラーを返すため、後続の引数は必要ありません。
スタックオーバーフローとサーバーフォールトには、これに対する優れた回答がすでにありますが、いくつかの手法が欠けていました。簡単にするために、VM/Linuxブロックデバイス/ Linuxファイルシステム/ LinuxユーザースペースライブラリI/Oフォールトインジェクションメカニズムのリストを次に示します。
--layout
オプション を参照してください。LD_PRELOAD
で使用できます)。FAIL_MAKE_REQUEST=y
でカーネルをビルドする必要があります)。BLK_DEV_NULL_BLK_FAULT_INJECTION=y
を使用して作成)。delay
または error
などの NBDkitフィルター を介してホストに提供される合成ネットワークブロックデバイスを作成します=次に、nbd-client
(kernel + NBD userspace bits、kernel> = 4.18 with NBD support、nbdclient > = 3.18およびnbdkit> = 1.8.1推奨- NBDKitデモビデオ の20分前後を参照)。おまけの事実: SQLiteには、エラーをシミュレートするためのVFSドライバーがあります なので、テストカバレッジを適切に取得できます。
関連:
I/Oに フォールトインジェクション メカニズムが必要です。
Linuxでは、事前のセットアップを必要とせず、異常なエラーを生成するメソッドがあります(EIO「入出力エラー」ではなく、ESRCH「そのようなプロセスはありません」)。
cat /proc/1234/mem
1234は、テストしているプロセスと同じユーザーとして実行されているプロセスのPIDですが、そのプロセス自体ではありません。 rubasov に対するクレジット thinking for /proc/$pid/mem
。
プロセス自体のPIDを使用すると、EIOが取得されますが、これは、プロセスのメモリにマップされていない領域から読み取る場合に限られます。最初のページはマップされないので、ファイルを順番に読み取っても問題ありませんが、ファイルの中央を直接検索するデータベースプロセスには適していません。
ルートとしてさらに設定すると、 デバイスマッパーを利用 して有効なセクターと不良セクターのファイルを作成できます。
別のアプローチは、小さな Fuse ファイルシステムを実装することです。 EIOは、ユーザー空間のファイルシステムドライバーが何か間違っている場合のデフォルトのエラーコードであるため、簡単に達成できます。 Perl と Python の両方のバインディングにはサンプルが付属しており、既存のファイルをほとんどミラーリングするファイルシステムをすばやく作成できますが、慎重に選択した場所にEIOを挿入できます。既存のそのようなファイルシステムがあります: petardfs ( article )、私はそれが箱から出してどれだけうまく機能するのかわかりません。
さらに別の方法は LD_PRELOAD
ラッパー。既存のものは Libfi (ユーザー空間でのフォールトインジェクション)です。 POSIX API呼び出しをオーバーロードするライブラリをプリロードすることで機能します。単純なディレクティブまたは任意のCコードを記述して、通常の動作をオーバーライドできます。
この種の目的のために正確に作成されたCharybdeFSを使用できます。
これは、PetardFSのようなパススルーFuseファイルシステムですが、はるかに構成可能です。
こちらのCharybdeFSクックブックを参照してください: http://www.scylladb.com/2016/05/02/fault-injection-filesystem-cookbook/
データベースをテストするのに十分高度です。
デバイスファイルを「I/Oエラーのあるファイル」として使用しても問題がなければ、解決策ははるかに簡単です。私の提案は、通常のファイルにそのようなエラーがあるはずの場合です。
> dd if=/dev/zero of=/path/to/ext2.img bs=10M count=10
> losetup /dev/loop0 /path/to/ext2.img
> blockdev --getsz /dev/loop0
204800
> echo "0 204800 linear /dev/loop0 0" | dmsetup create sane_dev
> mke2fs /dev/mapper/sane_dev # ext2 reicht
> mount -t ext2 /dev/mapper/sane_dev /some/where
> dd if=/dev/zero of=/some/where/unreadable_file bs=512 count=4
> hdparm --fibmap /some/where/unreadable_file
/mnt/tmp/unreadable_file:
filesystem blocksize 1024, begins at LBA 0; assuming 512 byte sectors.
byte_offset begin_LBA end_LBA sectors
0 2050 2053 4
> umount /dev/mapper/sane_dev
> dmsetup remove sane_dev
> start_sector=$((204800-2053-1))
> echo $'0 2053 linear /dev/loop0 0\n2053 1 error\n2054 '"${start_sector} linear /dev/loop0 2054" |
> dmsetup create error_dev
> mount -t ext2 /dev/mapper/error_dev /some/where
> cat /some/where/unreadable_file # 3rd sector of file is unreadable
cat: /some/where/unreadable_file: Input/output error
エラーなしでそのファイルから単一のセクターを読み取ることができなかったため、少し混乱していることを認めなければなりません(dd .. seek=...
)。多分それは先読みの問題です。