1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
/*
* 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 <iostream>
#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; \
}
|