現在、社内で単体テストを導入し、システムコールをモックする最善の方法を考えています。
次のコードを検討してください
int fd = open(path, O_RDONLY);
if (fd < 0) {
LOG.error() << "cannot load plugin " << path << std::endl;
return ERROR(ERROR_OPENING_PLUGING);
}
// do other stuff
明らかに、 openのシステム コールをモックする必要があります。
これを行うには、次の方法を見つけました。
正しい - デザインに関しては醜い方法です。インターフェイスと実装を作成する
class ISystem { public: typedef std::auto_ptr<ISystem> Ptr; ISystem() {}; virtual ~ISystem() {}; virtual int open(const char* file, int path) = 0; }; class System : public ISystem { public: System() {}; virtual ~System() {}; virtual int open(const char* file, int path); static ISystem::Ptr Get(); };
そしてそれを使う
Common::Error dlopen_signed(ISystem::Ptr& system, const char* path, int flags, void*& ret)
{
int fd = system->open(path, O_RDONLY);
if (fd < 0) {
LOG.error() << "cannot load plugin " << path << std::endl;
return ERROR(ERROR_OPENING_PLUGING);
}
char fd_path[32];
すべての関数にはもう 1 つの引数 (ISystem::Ptr& システム) が必要なので、これは好きではありません。これは、すべての製品コードで同じです。
また、速度についても不明です(これには、非常に高速でなければならない基本的なシステムコールの追加レイヤーが含まれます)
2) リンク シームを使用する リンカーは、システム バージョンよりもユーザー バージョンの関数を優先するように設計されています。
しかし、これは一部のシステム コール (open など) では機能せず (理由がわからない)、このソリューションは少しハック的です。
3) --wrap コンパイラ機能を使用する
--wrap symbol シンボルのラッパー関数を使用します。シンボルへの未定義の参照は、__wrap_symbol に解決されます。__real_symbol への未定義の参照は、symbol に解決されます。これは、システム関数のラッパーを提供するために使用できます。ラッパー関数は __wrap_symbol という名前にする必要があります。システム関数を呼び出したい場合は、__real_symbol を呼び出す必要があります。以下は簡単な例です。
void *
__wrap_malloc (int c)
{
printf ("malloc called with %ld\n", c);
return __real_malloc (c);
}
この解決策は素晴らしいですが、私が推測するすべてのコンパイラで機能するとは限りません。
問題は、プロジェクトでどちらを使用していますか?