C++

いなむ、テストの重要性を知るの巻

  • このエントリーをはてなブックマークに追加
  • Pocket

Visual Studioの非互換の修正を食らう

Visual Studio 2017で長らく放置されていたバグが修正された関係。

これ→http://enumhack.wp.xdomain.jp/fesetround

ちゃんとテストを書いていた

継続的インテグレーションとかよくわからんけど、ちゃんとテストを書いていた。

見た目ビルドテストという名前になっているが、実際はめっちゃちゃんとしたテストだったりする。

区間演算だと型違いのビルドテストの他にも、全関数のユニットテスト、例外チェックテスト、境界値テストなどいろいろとある。

今回のVisual Studio 2017の変更で境界値テストが落ちたことで、異常に気がついた。

ユニットテストを全部通して以来、ただのビルドテストと化していたがここにきてテストが重要な役割を果たしてくれたのだ!

しかし当初は原因がわからなかった

テストはクラッシュ、原因どうのこうのっていうレベルじゃない。

何が起きたのかのかも分かりはしない。こういう経験はしたことがある。

constepr, noexcept指定の関数で例外を発生させたときと似ている。

しかし、それらしい関数は軒並みnoexceptである。

そこで仕方なく、DEBUGモードを搭載した。

エラーが超絶深いところで発生したため、絶対に例外が発生しないと思っていた関数の中で例外が発生してしまったと考えた。

結果的にコードの大部分を魔黒にした、デバッグモードでは区間型をコンストラクションする前に例外チェックを仕込む。

例外が早い段階で飛べば簡単にエラーステータスがわかる。

あとは、Visual Studioのデバッガに全部なんとかしてもらうまでだ。

区間演算デバッグモード

区間クラスというのは上限と下限を持つクラスである。

当然、下限より上限が小さくなることは許されない。

    \[X=[1, 0]\]

(コード的にはinterval<>{ 1, 0 })

などという区間をコンストラクションしようとすればコンストラクタが例外を投げる。

ただし、区間演算でこのような区間が現れることが無いように巧妙にプログラミングされているはずだった。

オーバーフローする可能性がある関数はチェックが入るし、異常な入力は区間がコンストラクションされる前に関数が例外にするはずだったのだ。

例外処理は重いので、必要がないと判断した関数はnoexcept指定してある。

この前提を一回忘れる。

エラーは起こる。全部の関数で例外になる可能性がある。

ということで、デバッグモードでは全ての区間型がコンストラクションされる前に上限と下限のチェックがプリプロセス時に埋め込まれる。

いざ尋常にテストじゃ!

ここで、やっと境界値テストでコケていることが判明した。

実はこのテストは浮動小数点数演算の丸め方向制御をテストしたときの名残であった。

まさか浮動小数点数演算の振る舞いが変更されるとはこれっぽっちも思っていなかったため、ほぼ全てのチェックを通り抜けてコンストラクタに異常値が転送されていたようだ。

まとめ

テストは大事。

テストは資源。

当たり前のことを実感した。

  • このエントリーをはてなブックマークに追加
  • Pocket

コメント

  1. さこ より:

    うーん、いつも気持ち悪い喋り方するよなあ…ほんとに教員?

    1. enumhack より:

      いつも読んでくださっているようでありがとうございます!
      教員の喋り方にお詳しいのですね!

コメントを残す

*

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください