C++
TDD
CppUTest

BeagleBoneを使いCode Composer Studio上でCppUTestを試す

More than 1 year has passed since last update.

CppUTestを使ってみる

テストフレームワークの一つであるCppUTestを実機で動作させてみる。

ダウンロード

この辺りからダウンロードしてくる。執筆時点のバージョンは3.8だった。

ワークスペースの準備

ターゲットはTI社製Cortex-A8を搭載したBeagleBone(ブラックではない)で、開発環境はTI社謹製のCode Composer Studio v6.0.1(以下、CCSv6)でやってみる。(古くて申し訳ないが筆者が一番使っている環境なのでご了承頂きたい)

CCSを起動し、Workspaceに適当な名前(ここではBeagleBone_CppUTestとしたが、設定時にスペルミスしたので適切に読み替えて下さい)を入れてOKを押下。

image001.png

ライブラリの生成

プロジェクトの作成

まず、CppUTestライブラリを生成するプロジェクトを作成する。

File => New => CCS Projectで新規プロジェクトを作成する。

Description Comment
Target BeagleBoneを選択
Project name 何でもいいと思うがここではCppUTestとした
Compiler version 筆者が使っているTI製を選択(TI v5.1.6)
Output type Advanced settingsからStatic Libraryを選択
Project templates Empty Projectを選択

Advanced settingは通常現れないので▼を押して表示する。

image008.png

入力が完了したらFinishを押下。

image010.png

UppUTestのインポート

プロジェクトを右クリック(もしくはプロジェクトを選んでFileメニュー)からImportでImportダイアログを開く。General⇒File Systemを選んでNextをクリック。Browseを押下してCppUTestディレクトリを指定してOKを押下。

image003.png

次のようにインポートするインクルードファイルとソースファイルを指定する。PlatformsはインクルードではGcc、ソースファイルではIarを選ぶ。なお、ソースファイルに含まれる拡張子dspのような不要なファイルは組み込まない。Finishをクリックしてインポートを実行する。

image004.png

インポート後のプロジェクトは次のようになる。

image006.png

プロジェクトの設定

まずインクルードディレクトリを指定する。プロジェクトを右クリック(もしくはプロジェクトを選択してFileメニュー)からPropertiesを選択し、プロパティダイアログを表示する。左のツリービューからBuild⇒ARM Compiler⇒Include Optionsを選択し、右下のディレクトリサーチ追加ペインにあるAddボタンをクリックし、Workspaceボタンから参照して次のようにプロジェクト内のインクルードパスを指定する。

image012.png

OKを押下すると次のようなディレクトリ指定となるので更にOKを押下する。

image014.png

ディレクトリパスに追加されていることを確認する。

image016.png

続けてシンボル定義をしておく。同じプロパティダイアログのツリービューからBuild⇒ARM Compiler⇒Advanced Options⇒Predefined Symbolsを選択し、右上のPre-define NAMEペインのAddボタンをクリックし、次のようにシンボル「_LIB」を定義する。

image018.png

追加されていることを確認する。

image020.png

最後に言語オプションで例外ハンドリングを有効にする。同じプロパティダイアログのツリービューからBuild⇒ARM Compiler⇒Advanced Options⇒Language Optionsを選択し、Enable C++ exception handling (--exceptions)Enable support for GCC extensions (--gcc)にチェックを入れ、OKボタンをクリックする。

image022.png

メモリーリーク検出を抑制

時間の関係でうまく動作させる方法が分からなかったので一旦メモリリークの検出を抑制する。/CppUTest/include/CppUTest/CppUTestConfig.hファイルを編集し、#define CPPUTEST_MEM_LEAK_DETECTION_DISABLEDを追記する。

CppUTestConfig.h
/* Is memory leak detection enabled?
 *   Controls the override of the global operator new/deleted and malloc/free.
 *   Without this, there will be no memory leak detection in C/C++.
*/

#define     CPPUTEST_MEM_LEAK_DETECTION_DISABLED

#ifndef CPPUTEST_USE_MEM_LEAK_DETECTION
 #ifdef CPPUTEST_MEM_LEAK_DETECTION_DISABLED
  #define CPPUTEST_USE_MEM_LEAK_DETECTION 0
 #else
  #define CPPUTEST_USE_MEM_LEAK_DETECTION 1
 #endif
#endif

ビルド

ビルドを実行(別段の理由が無ければCtrl+Bでよい)し、ライブラリCppUTest.libが生成する。ライブラリファイルはDebug(設定によりRelease)以下に生成される。

image024.png

テストケースの実装

プロジェクトの作成

続いてテストケースを実装してみる。今回は簡単のため同じワークスペース上でテストケースを実装する。File => New => CCS Projectで新規プロジェクトを作成する。

Description Comment
Target BeagleBoneを選択
Connection Texas Instruments XDS100v2 USB Debug Probeを選択
Project name 何でもいいと思うがここではRunnerとした
Compiler version 筆者が使っているTI製を選択(TI v5.1.6)
Output type Advanced settingsからExecutableを選択
Project templates 標準出力の見本のあるHello Worldを選択

入力が完了したらFinishを押下。

image025.png

CppUTestなので自動生成されたhello.cをhello.cppにリネームしておく。

image027.png

インクルードパスの指定

インクルードディレクトリの指定をライブラリの時とおなじ要領で設定する。同じワークスペース上にあるときはWorkspaceボタンを押下して次のように設定すれば良い。なお、ワークスペース内に無いときはFile Systemで指定する。

image028.png

ライブラリの指定

Build⇒ARM Linker⇒File Search Pathを選び右上のInclude library fileペインでAddボタンを押下し、CppUTest.libを指定する。なお、次画面は指定後の画面。

image032.png

Addボタンを押下するとAdd file pathダイアログが開くのでWorkspaceボタンを押下し、次のようにワークスペース内にある事前に作成したライブラリを指定する。

image034.png

言語オプションで例外ハンドリングを有効にする。同じプロパティダイアログのツリービューからBuild⇒ARM Compiler⇒Advanced Options⇒Language Optionsを選択し、Enable C++ exception handling (--exceptions)Enable support for GCC extensions (--gcc)にチェックを入れ、OKボタンをクリックする。

image036.png

CppUTestのテストを実行するには一定以上のスタックサイズとヒープサイズが必要になる。正確に見積もりしていないが、メモリーも沢山ある事だし両方とも0x100000を指定する。Build⇒ARM Linker⇒Basic Optionsを選び、Set C system stack sizeに0x10000、Heap Size for C/C++ dynamic memory allocationに0x10000を指定する。

image038.png

確認してOKボタンを押下する。

セクションの設定

サンプルプログラムはSRAM上に配置するように設定されているが、CppUTestがまあまあ大きいので納まらないため、DDR上に配置するよう、AM335x.cmdを次のように編集しておく。つまり、L3OCMC0DDR0に全て置換し、.ARM.exidx.ARM.extabを追加する。

#ifdef A8_CORE     /* A8 memory map */
MEMORY
{
    SRAM:     o = 0x402F0400  l = 0x0000FC00  /* 64kB internal SRAM */
    L3OCMC0:  o = 0x40300000  l = 0x00010000  /* 64kB L3 OCMC SRAM */
    M3SHUMEM: o = 0x44D00000  l = 0x00004000  /* 16kB M3 Shared Unified Code Space */
    M3SHDMEM: o = 0x44D80000  l = 0x00002000  /* 8kB M3 Shared Data Memory */
    DDR0:     o = 0x80000000  l = 0x40000000  /* 1GB external DDR Bank 0 */
}

SECTIONS
{
    .ARM.exidx     >  DDR0
    .ARM.extab     >  DDR0
    .text          >  DDR0
    .stack         >  DDR0
    .bss           >  DDR0
    .cio           >  DDR0
    .const         >  DDR0
    .data          >  DDR0
    .switch        >  DDR0
    .sysmem        >  DDR0
    .far           >  DDR0
    .args          >  DDR0
    .ppinfo        >  DDR0
    .ppdata        >  DDR0

    /* TI-ABI or COFF sections */
    .pinit         >  DDR0
    .cinit         >  DDR0

    /* EABI sections */
    .binit         >  DDR0
    .init_array    >  DDR0
    .neardata      >  DDR0
    .fardata       >  DDR0
    .rodata        >  DDR0
}
#endif             /* A8 memory map */

テストケースの実装

今回の例ではメイン関数にテストケースを直接コーディングして動作を確認する。

hello.cpp
/*
 * hello.cpp
 */

#include <stdio.h>

#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness.h>

int main(void)
{
    printf("Hello World!\n");

    static char *argv[] = { "main" };
    CommandLineTestRunner::RunAllTests(sizeof(argv)/sizeof(*argv), argv);
}

int hoge(void)
{
    return 3;
}

int hoge(int a)
{
    return a + 1;
}

TEST_GROUP(TestSuiteHoge)
{};

TEST(TestSuiteHoge, TestCaseHoge)
{
    LONGS_EQUAL(3, hoge());
}

TEST(TestSuiteHoge, TestCaseHoge2)
{
    LONGS_EQUAL(3, hoge(2));
}

実行と結果

BeagleBoneはマルチコアなのでA8側に接続、ロードして実行する。

image043.png

実行結果

ロード後Resumeを選択して実行する。結果はCIOコンソールに出力される。

image044.png