/* * resourced * * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #pragma once #include #include "cmocka-wrap.hpp" /* Macro WRAP is used for wrapping and mocking functions from libraries, e.g. from glibc or glib. * * Its params are: * - global_object - an object that actually handles the wrapped function; * - rettype - return type of the wrapped function; * - name - the name of the wrapped function; * - def_args - function arguments as defined in function declaration, e.g. (pid_t pid, int sig) * - call_args - function arguments as used in calling, e.g. (pid, sig) * * For example, writing WRAP(global_object, int, kill, (pid_t pid, int sig), (pid, sig)) does two things: * - declares a function: * extern "C" int __real_kill(pid_t pid, int sig); * - defines a function: * extern "C" int __wrap_kill(pid_t pid, int sig) { * // ... * auto ret = global_object->kill(pid, sig); * if (ret.first) * return ret.second; * return __real_kill(pid, sig); * } * * global_object can handle the wrapped function or pass it to the real version, by manipulating * its return value. */ #define WRAP(global_object, rettype, name, def_args, call_args) \ extern "C" rettype __real_##name def_args; \ extern "C" rettype __wrap_##name def_args { \ std::cerr << #name"\n"; \ assert_non_null(global_object); \ auto ret = global_object->name call_args; \ if (ret.first) \ return ret.second; \ return __real_##name call_args; \ } /* Macro WRAP64 is used for wrapping the large-file versions of the base call. * * Its params are similar to WRAP (except global_object), but they call the base version of * the call (so as to keep the queue of mocks intact, i.e. allow "__will_return(foo, x)" * to return the value even inside foo64. * * Keep in mind this only really works when the base call is mocked as well. */ #define WRAP64(rettype, name, def_args, call_args) \ extern "C" rettype __wrap_##name##64 def_args { \ return __wrap_##name call_args; \ } /* * Macro MOCK is used for redirecting function handlers for mocked functions from resourced * to global_test_lowmem_limit_env static object. * Its params are: * - global_object - an object that actually handles the mocked function; * - rettype - return type of the wrapped function; * - name - the name of the wrapped function; * - def_args - function arguments as defined in function declaration, e.g. (pid_t pid) * - call_args - function arguments as used in calling, e.g. (pid) * */ #define MOCK(global_object, rettype, name, def_args, call_args) \ extern "C" rettype name def_args { \ std::cerr << #name"\n"; \ if (!global_object) std::cerr << "no global_object!\n"; \ assert_non_null(global_object); \ return global_object->name call_args; \ }