[C++] Whiteboxで内部オブジェクトをmockオブジェクトに置き換える

テストしたいクラス


public class MyClass 
{
    private InternalClass internalClass;
    void SomeMethod() 
    {
        internalClass.InternalMethod(); 
    }
}

MyClassの内部で作られるクラス


public class InternalClass 
{
    // MyClass#SomeMethod()の中で呼ばれるMock化したいメソッド
    public void InternalMethod() 
    {
        // do something
    }
}

テストコード


public class MyClassUTest 
{
    @Spy
    InternalClass mockInternalClass = new InternalClass();

    MyClass MyClass;

    @Before 
    void setUp() 
    {
        myClass = new MyClass();
        doNothing().when(internalClass).internalMethod(any());
        Whitebox.setInternalState(myClass, "internalClass", mockInternalClass);

    }

    @Test
    public void testMyClass()
    {
        myClass.SomeMethod();
    }
}

[C++] PowerMockで内部オブジェクトをmock化する

テストしたいクラス


public class SomeClass 
{
    private InternalClass internalClass;
    void SomeMethod() 
    {
        internalClass.InternalMethod(); 
    }
}

SomeClassの内部で作られるクラス


public class InternalClass 
{
    // SomeClass#SomeMethod()の中で呼ばれるMock化したいメソッド
    public void InternalMethod() 
    {
        // do something
    }
}

テストコード

@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeClass.class)
public class SomeClassUTest 
{
    @Mock
    InternalClass internalClass;

    @Before 
    void setUp() 
    {
        doNothing().when(internalClass).internalMethod(any());
        PowerMockito
           .whenNew(InternalClass.class)
           .withAnyArguments()
           .thenReturn(internalClass);
    }

    @Test
    public void testSomeClass()
    {
        someClass = new SomeClass();
        someClass.SomeMethod();
    }
}

[C++/Windows] wstring/UTF16でエンコードされたファイルを読み込む

wstring の場合

#include <codecvt>
#include <iostream>
#include <locale>
#include <fstream>

int main()
{
    std::basic_ifstream<wchar_t> ifs("C:\\hoge1.txt", std::ios::binary);
    ifs.imbue(std::locale(
        ifs.getloc(), 
        new std::codecvt_utf16<wchar_t, 0x10ffff, std::codecvt_mode( std::little_endian |std::consume_header)>));

    std::vector<wchar_t> buf(100);
    ifs.read(buf.data(), 100);
    std::basic_string<wchar_t> istr(buf.data());
}

UTF16の場合

#include <codecvt>
#include <iostream>
#include <locale>
#include <fstream>

int main()
{
    std::basic_ifstream<uint16_t> ifs("C:\\hoge1.txt", std::ios::binary);
    ifs.imbue(std::locale(
        ifs.getloc(), 
        new std::codecvt_utf16<uint16_t, 0x10ffff, std::codecvt_mode( std::little_endian |std::consume_header)>));

    std::vector<uint16_t> buf(100);
    ifs.read(buf.data(), 100);
    std::basic_string<uint16_t> istr(buf.data());
}

[C++] UTF32からUTF16への変換

#include <codedvt>
#include <locale>

const std::u16string u32ToU16(std::u32string u32Str) {
    // codecvt_mode で little endian を指定
    std::wstring_convert<std::codecvt_utf16<uint32_t, 0x10ffff, (std::codecvt_mode)1>, uint32_t> converter;
    return reinterpret_cast<const char16_t *>(converter.to_bytes(reinterpret_cast<const uint32_t*>(u32Str.c_str())).c_str());
}

VS2015の不具合(*)によりchar32_tが使えないためuint32_tを指定しているが、LinuxやMacであればchar32_tでよいはず。

(*リンクエラーになる)

[C++] std::stringにキャストされた場合に文字列を返すようにする

クラスのオブジェクトがstd::stringとしてキャストされた場合任意の文字列を返すようにする。
ロギングなどで複数の別々のクラスをstringとして扱って統計情報などを出力したりするのに使える。

#include <iostream>
#include <string>

class Coordinate {
private:
    int _x;
    int _y;
public:
    Coordinate(int x, int y): _y(y), _x(x) {}
    explicit operator std::string () const {
        return "x=" + std::to_string(_x) + ", y=" + std::to_string(_y);
    }
};

int main() {
    Coordinate coord(300, 400);
    std::cout << static_cast(coord) << std::endl;
}

[C++] オブジェクトのアドレスを表示

オブジェクトのアドレスを表示するコードです。
一言で言えば stati_cast で void のポインタにキャストして stream に渡してるということです。

#include <iostream>
#include <vector>

void showAddress() {
    
    std::vector<char> vec(100);
    
    //vectorオブジェクトのアドレスを表示
    std::cout << "vec   = "
         << static_cast<void *>(&vec)
    << std::endl;
    
    //vector内部で使われているバッファのアドレスを表示
    std::cout << "data  = " <<
         static_cast<void *>(vec.data())
    << std::endl;

    // new して確保したchar配列のアドレスを表示
    char *chars = new char[100];
    std::cout << "chars = " <<
        static_cast<void *>(chars)
    << std::endl;
}

int main(){

    showAddress();
}

出力(Mac上のXcodeでビルドし実行)

$ ./ShowAddress
vec   = 0x7fff5fbff6e8
data  = 0x100400100
chars = 0x100400170

vector オブジェクトはスタック上に、vector内部で確保されるバッファとnewで確保したオブジェクトは別のメモリ領域に確保されている様子がみえます。

[C++] ファイルを読み込んでstd::stringを得る

テキストファイルからstd::stringを得るコードです。
ファイルサイズ分のメモリを一度に確保するので大きなサイズのファイルの読み込みには向きません。


#include <iostream>
#include <fstream>
#include <vector>

std::string getStringFromFile(const std::string& filePath) {
    
    std::ifstream ifs(filePath, std::ios::binary);
    
    // ファイルサイズを得る
    ifs.seekg(0, std::ios::end);
    size_t sz = ifs.tellg();
    ifs.seekg(0, std::ios::beg);
    
    //ファイルサイズ分ファイルから読み込む
    std::vector<char> buf(sz);
    ifs.read(buf.data(), sz);
    
    //読み込んだcharデータからstringを作成
    return std::string(buf.data(), sz);
}

int main() {
    
    std::string str = getStringFromFile("/var/tmp/note.txt");    
    std::cout << str << std::endl;
}

出力結果

$ echo "こんにちは、世界!" >> /var/tmp/note.txt
$ ./GetStrigFromFile
こんにちは、世界!

[C++] ファイルサイズの取得

ディスク上のファイルのファイルサイズを取得するサンプルコードです。

#include <iostream>
#include <fstream>

int main () {
    
    std::ifstream ifs("/var/tmp/data.xml");
    ifs.seekg(0, std::ios::end);
    std::ifstream::pos_type end = ifs.tellg();
    std::cout
        << std::to_string(end)
        << " bytes "
        << std::endl;
    return 0;
}

出力結果

$ ./GetFileSize
5976576 bytes 

[C++] バイト単位のファイルサイズを単位文字付きで表示する

バイト単位のサイズをログファイルや標準出力に出力する場合に分かりやすいように適切な単位(MB,GBなど)で表示するためのサンプルコードです。

#include <iostream>

struct SizeUnit {
    
    size_t factor;
    std::string unitStr;
};

const static SizeUnit NONE = { 1, "bytes" };
const static SizeUnit KILO = { 1024, "KB" };
const static SizeUnit MEGA = { KILO.factor * 1024, "MB" };
const static SizeUnit GIGA = { MEGA.factor * 1024, "GB" };
const static SizeUnit TERA = { GIGA.factor * 1024, "TB" };


const static int BUFSIZE = 100;

std::string format(const size_t sz, SizeUnit sizeUnit) {

    char buf[BUFSIZE];
    std::string fmt = sz % sizeUnit.factor == 0 ? "%.0f %s" : "%.1f %s";
    
    std::snprintf(
        buf, BUFSIZE, fmt.data(),
        static_cast<double>(sz)/static_cast<double>(sizeUnit.factor),
        sizeUnit.unitStr.data());

    return std::string(buf);
}

std::string getFormattedNumber(const size_t sz){

    if( sz > TERA.factor) {
        return format(sz, TERA);
    } else if( sz > GIGA.factor) {
        return format(sz, GIGA);
    } else if (sz > MEGA.factor) {
        return format(sz, MEGA);
    } else if (sz > KILO.factor) {
        return format(sz, KILO);
    } else {
        return format(sz, NONE);
    }
}

int main() {
    
    std::cout
        << getFormattedNumber(234) << std::endl
        << getFormattedNumber(34543) << std::endl
        << getFormattedNumber(345387320) << std::endl
        << getFormattedNumber(275123793035) << std::endl
        << getFormattedNumber(31038852073273) << std::endl;
}

出力結果はこちら

$ ./GetformattedNumber
234 bytes
33.7 GB
329.4 MB
256.2 GB
28.2 TB