WEwLC で学んだ通りに進める。Test Harness で VM クラスのインスタンス化を試みる。クラス自体が少し大きい。
クラス自体ではなくまずはファイルを分割する。そうすればすくなくとも Build Dependency は減らす事が出来るし平均ビルド時間の向上もするだろう。Run-loop, Profiler, その他と分割。
よし VM インスタンス化できた。VM のインスタンス化はテストに共通する作業なので Google Test の "test fixture" 機能を利用する。
theVM がグローバルなのは良くない。今はしようがないがいずれ改善しよう。Test クラスを継承し VMTest を用意。
using namespace scheme; VM* theVM; class VMTest : public testing::Test { protected: virtual void SetUp() { Transcoder* transcoder = new Transcoder(new UTF8Codec, Transcoder::LF, Transcoder::IGNORE_ERROR); Object inPort = Object::makeTextualInputPort(new FileBinaryInputPort(stdin), transcoder); Object outPort = Object::makeTextualOutputPort(new FileBinaryOutputPort(stdout), transcoder); Object errorPort = Object::makeTextualOutputPort(new FileBinaryOutputPort(stderr), transcoder); theVM = new VM(10000, outPort, errorPort, inPort, false /* isProfiler */); } }; TEST_F(VMTest, Ref) { Vector* v = new Vector(2, Object::Undef); EXPECT_TRUE(v->ref(0).isUndef()); EXPECT_TRUE(v->ref(1).isUndef()); }
追加したいのはスタックトレースのテスト。コードを eval してスタックトレースを文字列を取り出して expected な結果を比較すれば良かろう。
まずは R5RS 相当のバックエンドのスタックトレース。動かない事は分かりきっているがテストコードを書いてみる。
TEST_F(VMTest, StackTrace) {
theVM->loadFile(UC("./work.scm"));
}
問題点は3つ
- 外部ファイルを読んでしまうものは WEwLC 的には Unit Test とは言わない。
- このファイルを実行すると loadFile は最終的に exit してしまう。
- スタックトレースが文字列として取り出せない。
(1)このファイルを実行すると load は最終的に exit してしまう
loadFile を virtual にして TestingVM クラスで load を override する。
class TestingVM : public VM { public: TestingVM(int stackSize, Object outPort, Object errorPort, Object inputPort, bool isProfiler = false) : VM(stackSize, outPort, errorPort, inputPort, isProfiler) { } virtual ~TestingVM() { } virtual void load(const ucs4string& file); };
と思ったが、これは最善の策ではない。exit を override する方が良い。
これで exit しなくなりました。
(2)スタックトレースが文字列として取り出せない。
エラーの内容は errorObj_ にあるのでこれを取り出せば良い。EXPECT_STREQ には c_str を渡さなければいけないので変換して渡す。
まずは失敗するテストにしてみよう。
theVM->loadFile(UC("./work.scm")); EXPECT_STREQ("", theVM->getLastError().toString()->data().ascii_c_str());
TestVector.cpp:65: Failure Value of: theVM->getLastError().toString()->data().ascii_c_str() Actual: " error in raise: unhandled exception has occurred Condition components: 1. &assertion 2. &who: display 3. &message: "textual-output-port required, but got 3" 4. &irritants: () Stack trace: 1. throw: <subr> 2. sys-display: <subr> 3. (a): ./work.scm:7 4. (b): ./work.scm:12 5. (<top-level>): <unknown location> " Expected: ""
失敗した。expected を挿入してもう一度やるとうまくいった。