読者です 読者をやめる 読者になる 読者になる

CRESTの生成値が記録されない問題

CRESTは、デフォルトでは解析対象を実行する際に生成した値を出力しない。
生成値を出力する方法としては、公式サイトにて、run_crest本体のコードに細工する方法が以下で説明されている。
https://github.com/jburnim/crest/wiki/CREST-Frequently-Asked-Questions#does-crest-save-the-test-inputs-it-generates

ただ上記の場合、一回のイテレーションで生成する値がすべて0だった場合、値が保存されないようになっている。0とそれ以外での挙動の差異は、CRESTを使ってテスト設計からテスト実行まで自動化しようとする際に注意がいる。

原因として、コードを見ると、解析処理を行うSearch::RunProgram()にて、生成値を格納した引数inputsのサイズが0だと、生成する値をすべて0に初期化する処理を行っているようだ。そして調べて見る限り、CRESTは解析ですべての生成値が0だった場合、inputsをサイズ0のままにしてSearch::RunProgram()を実行し、生成値を初期化している。


そのため対策だけど、「記録された生成値ファイルが空であれば、生成値はすべて0にする」と判断すれば一応支障はなさそうだ。
一方0以外の時と同じように値を記録する際は、ソースコードでのSearch::WriteInputToFileOrDie()に細工が必要になる。例えば生成対象の変数が1つだけなら、以下の様な細工をすると生成値が0かどうかで場合分けが不要になる。

void Search::WriteInputToFileOrDie(const string& file, const vector<value_t>& input) {
  FILE* f = fopen(file.c_str(), "w");
  if (!f) {
    fprintf(stderr, "Failed to open %s.\n", file.c_str());
    perror("Error: ");
    exit(-1);
  }

  for (size_t i = 0; i < input.size(); i++) {
    fprintf(f, "%lld\n", input[i]);
  }
  if (input.size() == 0) {
    fprintf(f, "0\n");
  }
  fclose(f);
}

ただ、そもそも上記の公式の方法では、生成値の型や変数名といった構文情報が失われる。生成値を記録する際は、マクロのCREST_*()に細工して、解析対象から直接生成値を出力させたほうが都合が良いかもしれない。