2013年5月31日金曜日

[gtest] make する

個人メモ。
  1. aclocal
    aclocal.m4 が生成される。
  2. libtoolize
  3. automake
    Makefile.in が生成される。
  4. autoconf
    configure が生成される。
  5. ./configure
    Makefile が生成される。
  6. make

テスト
  1. Makefile 作るまで一緒
  2. make check-TESTS

2013年5月24日金曜日

[gtest] ASSERT_* マクロで void 以外を return できるようにする

Google C++ Testing Framework の Google グループで「 non-void function でも ASSERT_ マクロが使えないのか」というのを見かけたので対応させてみました。

iutest では既に対応していたので、その実装を Google Test に移植したものになります。
※ ちゃんとチェックしていないのでビルドエラーなど出るかもしれません。

ソースコード
まずは、以下のクラスを追加します。
namespace testing
{

template<typename T>
struct AssertionReturn
{
  T value;
  AssertionReturn() {}
  AssertionReturn(const T& v) : value(v) {}
};
    
namespace internal {

template<typename T>struct AssertionFixed;

class AssertionMessage : public Message
{
public:
  template<typename T>
  AssertionMessage& operator << (T value)
  {
    Message::operator << (value);
    return *this;
  }
  template<typename R>
  AssertionFixed<R> operator << (const AssertionReturn<R>& r)
  {
    return AssertionFixed<R>(*this, r);
  }
};

template<typename T>
struct AssertionFixed
{
  AssertionMessage message;
  AssertionReturn<T> ret;
  AssertionFixed(const AssertionMessage& msg, const AssertionReturn<T>& r) : message(msg), ret(r) {}
};

} // namespace internal
} // namespace testing

続いて、AssertHelper を継承して AssertHelperEx を作ります。
class AssertHelperEx : public AssertHelper {
 public:
  // Constructor.
  AssertHelperEx(TestPartResult::Type type,
               const char* file,
               int line,
               const char* message)
    : AssertHelper(type, file, line, message) {}

  void operator=(const Message& message) const
  {
    AssertHelper::operator = (message);
  }
  template<typename R>
  R operator=(const AssertionFixed<R>& fixed) const
  {
    AssertHelper::operator = (fixed.message);
    return fixed.ret.value;
  }
private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperEx);
};

最後に、include/gtest/internal/gtest-internal.h の GTEST_MESSAGE_AT_ を以下のように書き換えます。
#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
  ::testing::internal::AssertHelperEx(result_type, file, line, message) \
    = ::testing::internal::AssertionMessage()

簡単に解説
ASSERT_ マクロは最終的に
return
    ::testing::internal::AssertHelper(result_type, file, line, message)
        = ::testing::Message()
のようになっています。
AssertHelper::operator=(const Message& message) が void を返すので、void を返す関数でしか使用できません。

void 以外の型を返すために、特定のオブジェクトが代入されたら、そのテンプレート引数の型を返す operator = を定義しています。
イメージとしてはこんな感じ。
return
    ::testing::internal::AssertHelper(result_type, file, line, message)
        = ::testing::AssertionReturn<int>(1)
上記の例では、int を return するようになります。
今回の修正では、AssertionReturn が特定のオブジェクトになります。
ユーザーはこの AssertionReturn を使用して、戻り値の型と値を指定します。

ただ、これでは既存の ::testing::Message の機能が使えないですし、ユーザーが型指定できません。
そこで、AssertionMessage が ::testing::Messageの動作をしつつ、AssertionReturn が与えられたら AssertionFixed を返す役割を果たします。
AssertionFixed は、Message と AssertionReturn を所持しています。

最後に、AssertionHelper に AssertionFixed を受け取る operator = を定義すればよいのですが、
そのまま AssertionHelper に実装してしまうとライブラリのリビルドが必要になってしまいます。
そこで、AssertionHelper を継承した AssertionHelperEx クラスに実装しています。

使い方
ASSERT_ マクロの後ろに oerator << を使用して AssertionReturn を渡すだけです。
int ReturnTest(void)
{
    IUTEST_ASSERT_TRUE(false) << ::iutest::AssertionReturn<int>(-1);
    return 0;
}

最後に
冒頭で iutest には既に実装済みと言いましたが、AssertionReturn があるとテストがとても楽にかけます。
Google Test 使っててコレがなくてメンドクセとなってましたが、意外と楽に移植できました。

あとは、例外を使うテスティングフレームワークを使うという選択もあります。
iutest には ASSERT_ マクロが例外を使ってテストを中断するようにも設定できます。
例外を使う場合は、IUTEST_USE_THROW_ON_ASSERT_FAILURE を事前に定義してください。
ただし、return する場合と挙動が異なりますので、挙動を理解した上で使用してください。

2013年5月13日月曜日

[Visual Studio 2012] 覚えておくとちょっと便利な TIPS

1. スタートページの"最近使用したファイル"の表示数を変更する
スタートページにある"最近使用したファイル"は便利なのですが、たくさんのプロジェクトを扱っていると
よく使っているプロジェクトがあぶれてしまうことがあります。

そういう場合は、"最近使用したファイル"の表示数を増やしましょう。

設定
[ツール] -> [オプション] の [環境] -> [全般] を開きます。


["10" 項目が最近使用した一覧に表示されています(R)] の部分の数値を好きな数値に変更してください。
これで設定は終わりです。
上にある[ウィンドウ メニュー]の方は、[ファイル(F)]メニューにある最近使用したファイルの表示数の設定になります。

2. オレオレファイル拡張子をハイライトさせる

Boost の .ipp や CUDA の .cu ファイルなど C++ のファイルですが、
デフォルト設定ではシンタックスハイライトインテリセンスが機能しません。
その他にも、とある言語の構文を持ちつつも、拡張子の異なるファイルを扱う場合があると思います。

その場合、拡張子を割り当てることでシンタックスハイライトとインテリセンスを使えるようになります。

設定方法
[ツール] -> [オプション] の [テキストエディタ] -> [ファイル拡張子] を開きます。



拡張子エディットボックスに拡張子名を入力します。
エディターコンボボックスから適切なものを選択し、追加ボタンを押します。

以上で設定は終わりです。

ちゃんとハイライトされてます。


3. IntelliSense エラーレポートの無効化
IntelliSense のエラーがエラー一覧ウィンドウに表示されるようになったのですが、
個人的にあまり嬉しいことがなかった(むしろ邪魔)ので、無効にしてます。

設定方法
[ツール] -> [オプション] の [テキストエディタ] -> [C/C++] の [詳細] を開きます。


そこに、[IntelliSense] -> [エラーレポートの無効化] があるので、その値を True に変更します。
これで、エラーレポートが表示されません。

4. 変数の値の書き換え
デバッグ時に変数の値を変更できることはご存知かと思いますが、
この値を変更するときに"式"を入力するとそれを評価した値に変更してくれます。

例えば、下記のようなソースコードで、if 文の中を通らせたい場合、
void f(int x, int y)
{
    // ... なにか処理
    if( x == kBEGIN_X )
    {
        // ... なにか処理
    }
}
kBEGIN_X の値を知らなくても x に、kBEGIN_X を入力することで済みます。


パソコンを修理に出しました

ノートPC の液晶の調子が悪いので修理に出しました。
しばらくは家でのプログラミングはお休みして、のんびりしたいと思います。

2013年5月6日月曜日

iutest_c v1.2.0 をリリースしました

iutest_c v1.2.0 をリリースしました。
今回は「値のパラメータ化テスト」が主な変更点になります。


iutest の記述と大分異なりますが、直感的な記述ができるようになったと思います。
IUTEST_INSTANTIATE_TEST_CASE_P(int, A, TestP, iuRange, 0, 2 );

IUTEST_P(int, TestP, Test)
{
    const int x = param; // パラメータは param 引数として渡されます
    const int kMax = 10;
    IUTEST_ASSERT_LT(x, kMax);
}

次のバージョンでは、Combine と組み込み向け対応を強化したいと思います。
それでは。