LibCMocks.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #include <cstdlib>
  19. #include <cstdarg>
  20. #include <iostream>
  21. #include <unistd.h> // needed for _POSIX_MONOTONIC_CLOCK
  22. #include <stdarg.h>
  23. #include "Util.h"
  24. #include "LibCMocks.h"
  25. #undef USING_DUMA
  26. using namespace std;
  27. // *****************************************************************************
  28. // gethostbyname
  29. struct hostent* gethostbyname(const char *name) {
  30. if(!Mock_gethostbyname::mock_)
  31. return LIBC_SYMBOLS.gethostbyname(name);
  32. return Mock_gethostbyname::mock_->call(name);
  33. }
  34. Mock_gethostbyname* Mock_gethostbyname::mock_=0;
  35. Mock_gethostbyname::~Mock_gethostbyname(){
  36. mock_=0;
  37. for(unsigned int i=0;i<gethostbynameReturns.size();i++)
  38. delete gethostbynameReturns[i];
  39. }
  40. Mock_gethostbyname::HostEntry& Mock_gethostbyname::addHostEntry(
  41. const char* hostName, short addrtype) {
  42. gethostbynameReturns.push_back(new HostEntry(hostName, addrtype));
  43. return *gethostbynameReturns.back();
  44. }
  45. hostent* Mock_gethostbyname::call(const char* name) {
  46. assert("Must add one or more mock hostent entries first"&&
  47. (gethostbynameReturns.size()!=0));
  48. return gethostbynameReturns[current++ % gethostbynameReturns.size()];
  49. }
  50. static char** appendString(char **list,const char* str,int len=0){
  51. const int SIZE_INCREMENT=16;
  52. if(list==0)
  53. list=(char**)LIBC_SYMBOLS.calloc(SIZE_INCREMENT,sizeof(char*));
  54. // find the first available slot
  55. int count=0;
  56. for(char** ptr=list; *ptr!=0; ptr++,count++);
  57. if(((count+1)%SIZE_INCREMENT)==0){
  58. list=(char**)LIBC_SYMBOLS.realloc(list,(count+1+SIZE_INCREMENT)*sizeof(char*));
  59. memset(list+count+1,0,SIZE_INCREMENT*sizeof(char*));
  60. }
  61. if(len==0){
  62. len=strlen(str)+1;
  63. }
  64. char* ptr=(char*)malloc(len);
  65. memcpy(ptr,str,len);
  66. list[count]=ptr;
  67. return list;
  68. }
  69. static void freeList(char **list){
  70. if(list==0) return;
  71. for(char** ptr=list; *ptr!=0; ptr++)
  72. LIBC_SYMBOLS.free((void*)*ptr);
  73. LIBC_SYMBOLS.free((void*)list);
  74. }
  75. Mock_gethostbyname::HostEntry::HostEntry(const char* hostName, short addrtype) {
  76. h_name=strdup(hostName);
  77. h_addrtype=addrtype;
  78. if(addrtype==AF_INET)
  79. h_length=4;
  80. else{
  81. #ifdef AF_INET6
  82. h_length=6; // TODO: not really sure, verify!
  83. #else
  84. assert("AF_INET6 not supported yet"&&false);
  85. #endif
  86. }
  87. h_aliases=h_addr_list=0;
  88. }
  89. Mock_gethostbyname::HostEntry::~HostEntry(){
  90. if(h_name) LIBC_SYMBOLS.free((void*)h_name);
  91. freeList(h_aliases); h_aliases=0;
  92. freeList(h_addr_list); h_addr_list=0;
  93. }
  94. Mock_gethostbyname::HostEntry& Mock_gethostbyname::HostEntry::addAlias(
  95. const char* alias) {
  96. h_aliases=appendString(h_aliases,alias);
  97. return *this;
  98. }
  99. Mock_gethostbyname::HostEntry& Mock_gethostbyname::HostEntry::addAddress(
  100. const char* addr4) {
  101. h_addr_list=appendString(h_addr_list,addr4,4);
  102. return *this;
  103. }
  104. // *****************************************************************************
  105. // calloc
  106. #ifndef USING_DUMA
  107. DECLARE_WRAPPER(void*,calloc,(size_t p1, size_t p2)){
  108. if(!Mock_calloc::mock_)
  109. return CALL_REAL(calloc,(p1,p2));
  110. return Mock_calloc::mock_->call(p1,p2);
  111. }
  112. #endif
  113. void* Mock_calloc::call(size_t p1, size_t p2){
  114. #ifndef USING_DUMA
  115. if(counter++ ==callsBeforeFailure){
  116. counter=0;
  117. errno=errnoOnFailure;
  118. return 0;
  119. }
  120. return CALL_REAL(calloc,(p1,p2));
  121. #else
  122. return 0;
  123. #endif
  124. }
  125. Mock_calloc* Mock_calloc::mock_=0;
  126. // *****************************************************************************
  127. // realloc
  128. #ifndef USING_DUMA
  129. DECLARE_WRAPPER(void*,realloc,(void* p, size_t s)){
  130. if(!Mock_realloc::mock_)
  131. return LIBC_SYMBOLS.realloc(p,s);
  132. return Mock_realloc::mock_->call(p,s);
  133. }
  134. #endif
  135. Mock_realloc* Mock_realloc::mock_=0;
  136. void* Mock_realloc::call(void* p, size_t s){
  137. if(counter++ ==callsBeforeFailure){
  138. counter=0;
  139. errno=errnoOnFailure;
  140. return 0;
  141. }
  142. return LIBC_SYMBOLS.realloc(p,s);
  143. }
  144. // *****************************************************************************
  145. // random
  146. RANDOM_RET_TYPE random(){
  147. if(!Mock_random::mock_)
  148. return LIBC_SYMBOLS.random();
  149. return Mock_random::mock_->call();
  150. }
  151. void srandom(unsigned long seed){
  152. if (!Mock_random::mock_)
  153. LIBC_SYMBOLS.srandom(seed);
  154. else
  155. Mock_random::mock_->setSeed(seed);
  156. }
  157. Mock_random* Mock_random::mock_=0;
  158. int Mock_random::call(){
  159. assert("Must specify one or more random integers"&&(randomReturns.size()!=0));
  160. return randomReturns[currentIdx++ % randomReturns.size()];
  161. }
  162. // *****************************************************************************
  163. // free
  164. #ifndef USING_DUMA
  165. DECLARE_WRAPPER(void,free,(void* p)){
  166. if(Mock_free_noop::mock_ && !Mock_free_noop::mock_->nested)
  167. Mock_free_noop::mock_->call(p);
  168. else
  169. CALL_REAL(free,(p));
  170. }
  171. #endif
  172. void Mock_free_noop::call(void* p){
  173. // on cygwin libc++ is linked statically
  174. // push_back() may call free(), hence the nesting guards
  175. synchronized(mx);
  176. nested++;
  177. callCounter++;
  178. requested.push_back(p);
  179. nested--;
  180. }
  181. void Mock_free_noop::freeRequested(){
  182. #ifndef USING_DUMA
  183. synchronized(mx);
  184. for(unsigned i=0; i<requested.size();i++)
  185. CALL_REAL(free,(requested[i]));
  186. #endif
  187. }
  188. int Mock_free_noop::getFreeCount(void* p){
  189. int cnt=0;
  190. synchronized(mx);
  191. for(unsigned i=0;i<requested.size();i++)
  192. if(requested[i]==p)cnt++;
  193. return cnt;
  194. }
  195. bool Mock_free_noop::isFreed(void* p){
  196. synchronized(mx);
  197. for(unsigned i=0;i<requested.size();i++)
  198. if(requested[i]==p)return true;
  199. return false;
  200. }
  201. Mock_free_noop* Mock_free_noop::mock_=0;
  202. // *****************************************************************************
  203. // socket
  204. int socket(int domain, int type, int protocol){
  205. if (!Mock_socket::mock_)
  206. return LIBC_SYMBOLS.socket(domain,type,protocol);
  207. return Mock_socket::mock_->callSocket(domain,type,protocol);
  208. }
  209. int close(int fd){
  210. if (!Mock_socket::mock_)
  211. return LIBC_SYMBOLS.close(fd);
  212. return Mock_socket::mock_->callClose(fd);
  213. }
  214. int getsockopt(int s,int level,int optname,void *optval,socklen_t *optlen){
  215. if (!Mock_socket::mock_)
  216. return LIBC_SYMBOLS.getsockopt(s,level,optname,optval,optlen);
  217. return Mock_socket::mock_->callGet(s,level,optname,optval,optlen);
  218. }
  219. int setsockopt(int s,int level,int optname,const void *optval,socklen_t optlen){
  220. if (!Mock_socket::mock_)
  221. return LIBC_SYMBOLS.setsockopt(s,level,optname,optval,optlen);
  222. return Mock_socket::mock_->callSet(s,level,optname,optval,optlen);
  223. }
  224. int connect(int s,const struct sockaddr *addr,socklen_t len){
  225. #ifdef AF_UNIX
  226. /* don't mock UNIX domain sockets */
  227. if (!Mock_socket::mock_ || addr->sa_family == AF_UNIX)
  228. #else
  229. if (!Mock_socket::mock_)
  230. #endif
  231. return LIBC_SYMBOLS.connect(s,addr,len);
  232. return Mock_socket::mock_->callConnect(s,addr,len);
  233. }
  234. ssize_t send(int s,const void *buf,size_t len,int flags){
  235. if (!Mock_socket::mock_)
  236. return LIBC_SYMBOLS.send(s,buf,len,flags);
  237. return Mock_socket::mock_->callSend(s,buf,len,flags);
  238. }
  239. ssize_t recv(int s,void *buf,size_t len,int flags){
  240. if (!Mock_socket::mock_)
  241. return LIBC_SYMBOLS.recv(s,buf,len,flags);
  242. return Mock_socket::mock_->callRecv(s,buf,len,flags);
  243. }
  244. Mock_socket* Mock_socket::mock_=0;
  245. // *****************************************************************************
  246. // fcntl
  247. extern "C" int fcntl(int fd,int cmd,...){
  248. va_list va;
  249. va_start(va,cmd);
  250. void* arg = va_arg(va, void *);
  251. va_end (va);
  252. if (!Mock_fcntl::mock_)
  253. return LIBC_SYMBOLS.fcntl(fd,cmd,arg);
  254. return Mock_fcntl::mock_->call(fd,cmd,arg);
  255. }
  256. Mock_fcntl* Mock_fcntl::mock_=0;
  257. // *****************************************************************************
  258. // select
  259. int select(int nfds,fd_set *rfds,fd_set *wfds,fd_set *efds,struct timeval *timeout){
  260. if (!Mock_select::mock_)
  261. return LIBC_SYMBOLS.select(nfds,rfds,wfds,efds,timeout);
  262. return Mock_select::mock_->call(nfds,rfds,wfds,efds,timeout);
  263. }
  264. Mock_select* Mock_select::mock_=0;
  265. // *****************************************************************************
  266. // poll
  267. Mock_poll* Mock_poll::mock_=0;
  268. int poll(struct pollfd *fds, POLL_NFDS_TYPE nfds, int timeout){
  269. if (!Mock_poll::mock_)
  270. return LIBC_SYMBOLS.poll(fds,nfds,timeout);
  271. return Mock_poll::mock_->call(fds,nfds,timeout);
  272. }
  273. /*
  274. * Recent gcc with -O2 and glibc FORTIFY feature may cause our poll
  275. * mock to be ignored.
  276. */
  277. #if __USE_FORTIFY_LEVEL > 0
  278. int __poll_chk (struct pollfd *__fds, nfds_t __nfds, int __timeout,
  279. __SIZE_TYPE__ __fdslen) {
  280. return poll(__fds, __nfds, __timeout);
  281. }
  282. #endif
  283. // *****************************************************************************
  284. // gettimeofday
  285. int gettimeofday(struct timeval *tp, GETTIMEOFDAY_ARG2_TYPE tzp){
  286. if (!Mock_gettimeofday::mock_)
  287. return LIBC_SYMBOLS.gettimeofday(tp,tzp);
  288. return Mock_gettimeofday::mock_->call(tp,tzp);
  289. }
  290. Mock_gettimeofday* Mock_gettimeofday::mock_=0;
  291. // *****************************************************************************
  292. #ifdef _POSIX_MONOTONIC_CLOCK
  293. // clock_gettime
  294. int clock_gettime(clockid_t id, struct timespec *tp) {
  295. if (!Mock_gettimeofday::mock_)
  296. return LIBC_SYMBOLS.clock_gettime(id,tp);
  297. struct timeval tv = { 0 };
  298. int res = Mock_gettimeofday::mock_->call(&tv, NULL);
  299. tp->tv_sec = tv.tv_sec;
  300. tp->tv_nsec = tv.tv_usec * 1000;
  301. return res;
  302. }
  303. #endif