">

ほそぼそストレージ研究所

LinuxNVMe操作アプリケーションを作ってみた-7-mock

投稿日 2026.04.30 カテゴリ nvme レベル 中級者
nvme linux implementation

はじめに

ここまでで、

  • Identify
  • SMART Log
  • Error Information Log

のような read-only 系の command を少しずつ実装してきました。

これらの実装の際に、今回は mock を導入しました。

最初の動機はかなり単純で、「mock があると検証がそれっぽくなるらしい」という程度のものでした。
今回のサブテーマである「品質向上」の一助になるかな?と思って導入してみました。

実際に使ってみると、確かに便利です。
が、しかし、それは「mock があれば何でも楽になる」という意味ではありませんでした。

残念なことに、mock は実機の動作をある程度想像できないと作れないです。

つまり、mockを使いこなせない初心者は、mockを使うために実機を触る、という本末転倒な状態になりかねないです。

mock の役割

今回の mock は、実機の代わりに command を受けて、想定した返り値を返す疑似実装です。

例えば、

  • IdentifyController なら VID / serial / model / firmware / ELPE
  • SMART Log なら温度、spare、used、read / write、時間系の項目
  • Error Information Log なら Error CountOpcode を含む entry

のような値を、自分で用意して返す形にしていました。

役割としては、

  • 実機が無くても command の流れを進められる
  • 表示や decode を先に確認できる
  • real device では出にくいケースも作れる

というものです。

ただ、ここで大事なのは、「何を返すべきか」を自分で決めなければいけないことです。

実際には、mock を作ること自体が難しかった

使ってみて分かったのは、mock は思っていたより難しいということでした。

理由は単純で、

  • 実機がどう返すのか
  • その field はどういう意味なのか
  • どんな値が自然なのか

をある程度想像できないと、mock の中身を作れないからです。

例えば SMART Log なら、

  • 温度はどれくらいの値が自然か
  • Available SparePercentage Used はどう見せるか
  • Data Units Read/Write はどのくらいの桁になるか
  • WCTT / CCTT は threshold ではなく time なのではないか

のような理解が必要でした。

Error Information Log でも、

  • count は page 数ではなく entry 数ではないか
  • Error Count == 0 は invalid entry ではないか
  • ELPE + 1 が最大件数なのではないか

ということが分からないと、mock 側の値も自然に決められません。

つまり今回の体験では、mock は「仕様が分からなくても先に進める道具」というより、ある程度仕様を想像できる人が使うと強い道具に近いものでした。

今回は AI がそのギャップをかなり埋めてくれた

とはいえ、自分は最初からそこまで想像できていたわけではありません。

今回かなり助かったのは、AI と相談しながら

  • どういう値を mock に入れると自然か
  • その field は何を意味しているのか
  • 単位は何か
  • この項目は本当に threshold なのか、time なのか

を一緒に整理できたことです。

つまり、今回は

  • 自分だけで実機を想像して mock を作った

というより、

  • AI を使って想定動作を補いながら mock を組み立てた

という進め方でした。

この意味では、mock が便利だったというより、mock を作るための理解を AI が補ってくれたという方が実感に近いです。

それでも mock があると進めやすかった

難しさはあったものの、mock を入れた効果はかなり大きかったです。

例えば、

  • SMART Log の表示形式を先に決める
  • No Error Log in Nvme のような出力を先に決める
  • --count の上限超えや warning を試す
  • 温度センサ 0no report として扱う

のようなことは、mock があるとかなり進めやすくなりました。

real device だけだと、

  • 今その error が本当に出ているか
  • 実機の値が都合よく欲しい形で出るか

にかなり左右されます。

一方で mock なら、

  • 今確認したい値を自分で置ける
  • 出したいケースを自分で作れる

ので、表示や decode の確認がしやすくなります。

今回の mock は静的だからこそ成立した

今回の実装では、mock はかなり静的です。

  • command ごとに決め打ちの値を返す
  • call 回数や順番で状態は変えない
  • retry や failure injection までは扱わない

という形です。

これは read-only 系の command を扱っていたからこそ成立した面があります。

今回の範囲では、

  • Identify
  • SMART
  • Error Information Log

のように「取得系」が中心だったので、まずは静的な mock でも十分役に立ちました。

逆に、もっと状態を持つ command や複雑な挙動を扱うなら、

  • 状態を持つ mock
  • 呼び出し順に応じて返り値が変わる mock

のような形も必要になるはずです。

また、今回の mock の粒度についても、後から振り返ると少し考える余地がありました。

今の実装は感覚として、

  • Identify 用の mock
  • SMART 用の mock
  • Error Information Log 用の mock

のように、1機能に対して 1 つの想定返り値を置く形に近いです。

これは v0 の read-only 実装には十分でしたが、正常系の device、温度が高い device、error を複数持つ device のように、device 自体の状態を先に決めて mock を作るやり方もありそうです。

そうすると、IdentifySMARTError Log の返り値に一貫性を持たせやすくなります。

real は何を確認する場所だったか

では real device は不要だったかというと、もちろんそうではありません。

real 側で見たかったのは、

  • command が本当に通るか
  • decode が実機でも破綻していないか
  • mock で置いた値のスケール感が大きく外れていないか
  • 実機特有の挙動はないか

という部分です。

特に Error Information Log では、

  • 実際の ELPE はいくつか
  • error が無い時にどう見えるか
  • Transport TypeOpcode はどんな値になるか

のようなことは、real で確認する意味がありました。

なので、自分の中では

  • mock は仕様を固定して進める場所
  • real はその理解が実機でも通るかを見る場所

という役割分担になっています。

まとめ

今回 mock と real の両方を持ってみて感じたのは、mock は単純な「実機の代用品」ではなかったということです。

mock には確かに便利さがあります。
ただ、その前提として、

  • 実機がどう返すかをある程度想像できること
  • field の意味や単位をある程度理解していること

が必要でした。

今回の体験としては、

  • mock があるから楽だった

というより、

  • AI と相談しながら mock を作れるようになったことで、実装と仕様理解が前に進んだ

という感覚に近いです。

そのうえで、

  • mock で仕様を固定する
  • real で実機確認をする

という二段構えにしたことで、IdentifySMARTError Log をかなり進めやすくなりました。

一方で、ここまで書いてくると、lower layer のテストは今の静的 mock だけでは足りないとも感じます。

open / ioctl / timeout / retry のような挙動を見たいなら、

  • stateful な mock
  • あるいは fake executor / fake driver

のようなものが必要になりそうです。