2013年10月28日月曜日

iutest v1.7.0 をリリースしました

iutest v1.7.0 をリリースしました。
今回の変更点は以下のとおりです。

  • 追加
    • 値のパラメータを operator + で連結できるように修正
    • 値のパラメータを連結する ::iutest::Concat を追加
    • テストフィクスチャの定義が省ける値のパラメータ化テストを追加(IUTEST_AP,IUTEST_INSTANTIATE_TEST_CASE_AP(Visual Studio では IUTEST_P,IUTEST_INSTANTIATE_TEST_CASE_P でも省略可能))
    • IUTEST_TYPED_TEST,IUTEST_TYPED_TEST_P の別名マクロを追加(IUTEST_T, IUTEST_TP)
    • xml 出力に timestamp を追加
    • 前提条件の検証用マクロ IUTEST_ASSUME_* を追加
    • Windows 向けメニュー登録ユーティリティを追加
    • SSTP 通知リスナーを追加
  • 修正
    • 値のパラメータ化テストが日本語テスト名に対応していなかった問題を修正
    • ビルドエラー修正
    • バグ修正

バグ修正
いろいろと更新しているうちに、エンバグや把握していなかった不具合が見つかったので、修正しました。
テストも増強したので、安定化したのではないかと思います。

SSTP 通知リスナーを追加
以前、ブログで書いた機能になります。
「[iutest] テスト結果を「伺か」にしゃべらせてみた」
こちらはお遊び的な機能になってます。

以降から、大きな機能追加を紹介します。

前提条件の検証用マクロ IUTEST_ASSUME_* を追加
ASSERT,EXPECT,INFORM とは違うフレーバーになります。
ASSUME では、検証に失敗した場合にテストをスキップします。

テストを特定の条件下でのみ実行したい場合に使用します。
例えば、整数型のサイズを条件としたときは、以下のように書きます。
struct hoge { int a; char b; };
IUTEST(Test, Size)
{
    IUTEST_ASSUME_EQ(4, sizeof(int));
    IUTEST_ASSERT_EQ(8, sizeof(hoge));
}

この機能は gtest モードでも利用可能です。

値のパラメータの連結に対応
値のパラメータを複数連結してパラメータを作成する機能を追加しました。
これにより、より複雑なパラメーターを簡単に作成できるようになりました。
// true,false + 1,10
IUTEST_INSTANTIATE_TEST_CASE_P(A1, ConcatTest
 , ::iutest::Concat(::iutest::Bool(), ::iutest::Values(1, 10)));

// operator + も利用可能
// 1-9 + true,false + 1, 10
IUTEST_INSTANTIATE_TEST_CASE_P(P5, ConcatTest
    , ::iutest::Range(1, 10) + ::iutest::Bool() + ::iutest::Values(1, 10));

テストフィクスチャの定義が省ける値のパラメータ化テストを追加
値のパラメータ化テストを書くには、テストフィクスチャの定義が必須でした。
しかしながら、ほとんどの場合、パラメータの型を決定するために定義するだけで、その作業は手間になっていました。
class BoolParamTest : public ::iutest::TestWithParam<bool> {};

IUTEST_P(BoolParamTest, Test)
{
    bool param = GetParam();
}

IUTEST_INSTANTIATE_TEST_CASE_P(My1, BoolParamTest, ::iutest::Bool());

そこで、テストフィクスチャの定義が不要な値のパラメータ化テストを追加しました。
IUTEST_AP(BoolParamTest, Test)
{
    bool param = GetParam<bool>();
}

IUTEST_INSTANTIATE_TEST_CASE_AP(My1, BoolParamTest, ::iutest::Bool());
パラメータを取り出す際は、GetParam Template 関数に型を指定して取り出します。
パラメータの型は内部的には any となっており、GetParam Template 関数は unsafe_any_cast した結果を返す点に注意してください。
(非 Template の GetParam を使うと ::iutest::any が取得できます。)

また、Visual Studio の場合、通常の IUTEST_P でもテストフィクスチャの定義が不要になります。
もちろん、定義をした場合でも今まで通り使用できます。
(※ この実装には __if_exists を使用しています。__if_exists については、後日ブログにしたいと思います。 )

Windows 向けメニュー登録ユーティリティを追加
Windows 向けに main からのテスト実行ではなく、メニューバーから任意のテストを実行するユーティリティを追加しました。
こちらは、GUI に関わるテストや統合されたアプリケーションでテストを行いたい場合に使うことを想定しています。
(io テストのような低レベルなものや、コンソールで完結できるものは通常どおり main から実行しましょう)
ようはランチャーのようなものです。

#include <util/iutest_util_menu.hpp>

// TestMenu ユーティリティのインスタンスを作る
// コンストラクタにはメニューIDの先頭の番号を指定します
static ::iuutil::TestMenu s_test_menu(4000);

/* ~中略~ */
    hWnd = CreateWindow( // ...

/* ~中略~ */

    // ウィンドウ作成後、ウィンドウのメニューハンドルを渡して Create
    s_test_menu.Create( GetMenu(hWnd) );
}

/* ~中略~ */
    switch (message)
    {
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            // メッセージハンドラに処理を追加
            s_test_menu.OnCommand(wmId);
            return DefWindowProc(hWnd, message, wParam, lParam);


こちらは実行すると以下のようにメニューが自動生成されます。

テストの出力は標準出力に吐かれるので、コンソールウィンドウを作っておくと良いかもしれません。

今後の予定
しばらくは、 C言語版の iutest_c に集中しようかな~と思います。
iutest でバグがあった場合は対応します。
バグがあったら是非報告してくださいm(__)m

2013年10月21日月曜日

休み明け

一週間ちょっと休暇を取っておりました。
休暇といっても、やること満載・仕事以上に大変なことが盛りだくさんな一週間でありましたが、
なんやかんやで過ぎてしまえばあっと言う間、楽しいお休みになりました。

まだまだ、やることが残っていますが(事後処理てきな)
それを終えたらようやくのんびりできそうです。


休みの間は一切プログラムに触れてませんでした。
こんなにプログラムをしていないのも久しぶりでございます。
脳みそがプログラムを受け付けない、なんだかそんな感覚がありますが、
そんなことも言ってられず、お仕事でリハビリ中です。

まぁ少しのんびりしたら、ぼちぼち活動していこうと思います。
では。

2013年10月9日水曜日

[iutest] テスト結果を「伺か」にしゃべらせてみた

第5回大阪Jenkins勉強会で「Jenkins に伺かせてみた」という発表があったようで、
スライドを見て面白そうだったので作ってみました。
伺かについてはこちらを参照してください。

使い方
listener/iutest_sstpnotifier.hpp をインクルードし、
IUTEST_RUN_ALLTEST を呼ぶ前に ::iutest::SetUpSSTPNotifier を呼んでください。

実行するとこのようにゴーストが結果をしゃべってくれます。

ゴーストについて

これができたからと言って、開発が楽になるとかそういったことはないんですが、
こういうこともできると楽しいですよね(^^

こちらの機能は trunk もしくは、近日公開予定の v1.7.0 に含まれます。

2013年10月1日火曜日

Arduino 自作ライブラリを作る

Arduino では C++ でライブラリを自作できるので、試してみました。

今現在、LED マトリックスで遊んでいるところなので、
それで使っている 74HC595 シフトレジスタの操作をライブラリにしてみたいと思います。

ライブラリの作成には以下のサイトを参考にしました。
arduinoIDEの使い方:自作ライブラリの作り方

ファイル構成
今回のライブラリ名は ShiftRegister とします。
構成は以下のように、任意フォルダの下に、ヘッダー・ソース・キーワードファイルを作ります。
[ShiftRegister]
|- lib74hc595.h
|- lib74hc595.cpp
|- keywords.txt
(ディレクトリ名とソースファイル名は異なっていても問題ありません。)

ヘッダー

#ifndef lib74hc595_H_
#define lib74hc595_H_
#include "arduino.h"

class ShiftRegister
{
public:
 ShiftRegister(int latch, int clock, int data);
 
public:
 void Begin(void);
 void Output(int mode, byte data);
 void Output16(int mode, int data);
 void End(void);
 
private:
 int latchPin, clockPin, dataPin;
};

#endif

Arduino の標準関数などは ardunino.h を include することで使用できます。

ソース

#include "arduino.h"
#include "lib74hc595.h"

ShiftRegister::ShiftRegister(int latch, int clock, int data)
: latchPin(latch), clockPin(clock), dataPin(data)
{
 pinMode(latchPin, OUTPUT);
 pinMode(clockPin, OUTPUT);
 pinMode(dataPin, OUTPUT);
}

void ShiftRegister::Begin(void)
{
    digitalWrite(latchPin, LOW);
}

void ShiftRegister::Output(int mode, byte data)
{
    shiftOut(dataPin, clockPin, mode, data);
}
void ShiftRegister::Output16(int mode, int data)
{
    if( mode == LSBFIRST )
    {
        shiftOut(dataPin, clockPin, mode, (data   )&0xFF);
        shiftOut(dataPin, clockPin, mode, (data>>8)&0xFF);
    }
    else
    {
        shiftOut(dataPin, clockPin, mode, (data>>8)&0xFF);
        shiftOut(dataPin, clockPin, mode, (data   )&0xFF);
    }
}

void ShiftRegister::End(void)
{
    digitalWrite(latchPin, HIGH);
}


特に気にすることなく C++ のコードを書きます。
ピン操作などは標準で用意されていますので、ただ呼ぶだけです。

キーワード
キーワードファイルを設定することで文字に色を付けることができます。
今回は以下のように設定しました。

ShiftRegister KEYWORD1
Begin KEYWORD2
End KEYWORD2
Output KEYWORD2

セットアップ
ライブラリが書けたら、Arduino IDE に認識してもらえるようにセットアップします。
と、いってもやることは先ほど作成したライブラリをディレクトリごとコピーするだけです。

コピー先はこちら > %ProgramFiles%\Arduino\libraries

コピーしたら次は使ってみましょう。

使う
作成したライブラリを使うには IDE のメニューの「スケッチ」の「ライブラリの使用」にライブラリリストが表示されるので、その中から追加した「ShiftRegister」を選択します。(名前はディレクトリ名になります。)

すると、コードにライブラリのヘッダーが include されます。

使い方も C++ とほぼ一緒です。
#include <lib74hc595.h>

int latchPin = 8;  // 74HC595のST_CPへ
int clockPin = 12; // 74HC595のSH_CPへ
int dataPin = 11;  // 74HC595のDSへ
int ledPin = 13;

ShiftRegister sr(latchPin, clockPin, dataPin);

void setup() {
  pinMode(ledPin, OUTPUT);
}
 
void loop() {
  for (int j = 0; j < 16; j++) {
    sr.Begin();
    // シフト演算を使って点灯するLEDを選択しています
    sr.Output(LSBFIRST, (1<<j)>>8);
    sr.Output(LSBFIRST, 1<<j);
    if( j % 2 == 0 ) {
      digitalWrite(ledPin, LOW);
    } else {
      digitalWrite(ledPin, HIGH);
    }
    // 送信終了後latchPinをHIGHにする
    sr.End();
//    delay(100);
  }
}

ライブラリを使用したライブラリ
別のライブラリを使用して、新しいライブラリを作ることもできます。
その場合は、普通に使用したいライブラリのヘッダーファイルを include して、
後は普通にライブラリを書くだけです。

#ifndef ledmatrix_H_
#define ledmatrix_H_
#include "arduino.h"
#include "lib74hc595.h"

class LedMatrix
{
public:
    enum {
          RED
        , GREEN
        , ORANGE
    };
    enum {
        MODE_NORMAL
        , MODE_INVERT
    };
public:
    LedMatrix(int latch, int clock, int data
    , int latch_r, int clock_r, int data_r
    , int latch_g, int clock_g, int data_g);

public:
    void setmode(int mode);
public:
    void bitblt(const uint16_t red[16], const uint16_t green[16]);
    void bitblt(const uint16_t data[16], int color);
    
    void slideout_h(const uint16_t red[][16], const uint16_t green[][16]
                      , int num, int delay_n);
    void slideout_h(const uint16_t data[][16], int num, int delay_n, int color);
    void flashout(const uint16_t array[][16], int num, int delay_n, int color);
    
private:
    void setcol(uint16_t red, uint16_t green);
    uint16_t getclearbit();
    
public:
    ShiftRegister m_raw;
    ShiftRegister m_red;
    ShiftRegister m_grn;
    
    int m_mode;
};

#endif

まとめ
まとまったコードをライブラリにすることで、メインのコードをコンパクトに書けるようになりました。
また、使い慣れた言語で書ける点も良い所です。

さて、この LED マトリックスの納期まで残り一週間ほどになってしまいました(汗
ライブラリを使ってコードの使いましができるようにはなったので、ラストスパート頑張ります。
では。