テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

(writeboost report) dmtestの設計アイデア

ローカルで開発を続けている. わかりやすく, ドミトリや他のテスターが容易にテストを追加していけるものにしたい. それは, Scalaを広めることにもなる.

RubyだとかPythonだとかスクリプト言語でソフトウェアを書くと, 経験上100%保守不能になる. これは私の力量不足ではなく, 言語の欠陥であると感じているため, 保守し続けるソフトウェアにこれらの言語を使うことはやめた.

trait Stack[+D <: Device] {
  protected def makeDevice: D
  protected def removeDevice(): Unit
  protected def underlyingStacks: Iterable[Stack[Device]]

  val cached = makeDevice
  final def getDevice: D = cached

  final def purgeDevice(): Unit = {
    if (purgeGuard) {
      // TODO log
      return
    }
    removeDevice()
    underlyingStacks.foreach(_.purgeDevice())
  }

  private var purgeGuard = false
  def lock: this.type = { purgeGuard = true; this }
  def unlock: this.type = { purgeGuard = false; this }
}

StackとDeviceと概念を分ける. StackはDeviceを生成するものである. StackがJVM上に生成された時には, Deviceは生成されている(RAII的なリソース管理の考え方). 初期化が遅延されるということはない.

Stackは木構造である. 基本的にはルートが利用されなくなった時には全デバイスを落とすことになるが, lockすることも出来る. これは例えば,

  1. ライトブーストを使ってIOをする
  2. その後, backing deviceのみを取り出してIOをする

と言ったケースに対応するためである. その他のケースでは自動的に削除されるようにしたい. (purgeDeviceも隠蔽すべきかも知れない)

trait Device {
  def fullPath: Path
  def size: Sector = ???
}

Deviceというのは, 何らかのパスを持っておりアクセス可能なものである. サブクラスとしては, Direct, Loopback, DMDevice(のサブクラスはLinear, Writeboost, ...)が存在する. Directにより, 現行のDMTSでは出来ない「Linearスタックを介さずに性能測定をする」というシナリオを実現出来る. Loopbackにより, このテストフレームワーク自体の回帰テストTravisで実行出来る.

Directはこんな感じになる.

object Direct {
  case class D(fullPath: Path) extends Device
  class S(fullPath: Path) extends Stack[D] {
    override protected def makeDevice: D = D(fullPath)
    override def removeDevice: Unit = {}
    override def underlyingStacks: Iterable[Stack[Device]] = Iterable.empty
  }
}

Linearはこんな感じになる. DMDeviceには, 作成時に一意な名前(dmtest-$k)が付与される.

object Linear {
  case class D() extends DMDevice
  case class S(backing: Stack[Device], start: Sector, len: Sector) extends Stack[D] {
    override protected def makeDevice: D = ???
    override def removeDevice: Unit = ???
    override def underlyingStacks: Iterable[Stack[Device]] = Seq(backing)
  }
}

dmtestは, デバイスを生成して, それをテストするところまでしか提供しない. つまり, テスト自体のフレームワークはユーザがご自由に選択くださいという形にする. QuickCheckまでは不明だが, ある程度スタックをランダムに自動生成するという仕組みは実現出来そうな気はしている.