xref: /sqlite-3.40.0/src/test_init.c (revision e1ab2193)
1 /*
2 ** 2009 August 17
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 *************************************************************************
12 **
13 ** The code in this file is used for testing SQLite. It is not part of
14 ** the source code used in production systems.
15 **
16 ** Specifically, this file tests the effect of errors while initializing
17 ** the various pluggable sub-systems from within sqlite3_initialize().
18 ** If an error occurs in sqlite3_initialize() the following should be
19 ** true:
20 **
21 **   1) An error code is returned to the user, and
22 **   2) A subsequent call to sqlite3_shutdown() calls the shutdown method
23 **      of those subsystems that were initialized, and
24 **   3) A subsequent call to sqlite3_initialize() attempts to initialize
25 **      the remaining, uninitialized, subsystems.
26 */
27 
28 #include "sqliteInt.h"
29 #include <string.h>
30 #include <tcl.h>
31 
32 static struct Wrapped {
33   sqlite3_pcache_methods pcache;
34   sqlite3_mem_methods    mem;
35   sqlite3_mutex_methods  mutex;
36 
37   int mem_init;                /* True if mem subsystem is initalized */
38   int mem_fail;                /* True to fail mem subsystem inialization */
39   int mutex_init;              /* True if mutex subsystem is initalized */
40   int mutex_fail;              /* True to fail mutex subsystem inialization */
41   int pcache_init;             /* True if pcache subsystem is initalized */
42   int pcache_fail;             /* True to fail pcache subsystem inialization */
43   int osinit_fail;             /* True to fail OS subsystem inialization */
44 } wrapped;
45 
46 static int wrMemInit(void *pAppData){
47   int rc;
48   if( wrapped.mem_fail ){
49     rc = SQLITE_ERROR;
50   }else{
51     rc = wrapped.mem.xInit(wrapped.mem.pAppData);
52   }
53   if( rc==SQLITE_OK ){
54     wrapped.mem_init = 1;
55   }
56   return rc;
57 }
58 static void wrMemShutdown(void *pAppData){
59   wrapped.mem.xShutdown(wrapped.mem.pAppData);
60   wrapped.mem_init = 0;
61 }
62 static void *wrMemMalloc(int n)           {return wrapped.mem.xMalloc(n);}
63 static void wrMemFree(void *p)            {wrapped.mem.xFree(p);}
64 static void *wrMemRealloc(void *p, int n) {return wrapped.mem.xRealloc(p, n);}
65 static int wrMemSize(void *p)             {return wrapped.mem.xSize(p);}
66 static int wrMemRoundup(int n)            {return wrapped.mem.xRoundup(n);}
67 
68 
69 static int wrMutexInit(void){
70   int rc;
71   if( wrapped.mutex_fail ){
72     rc = SQLITE_ERROR;
73   }else{
74     rc = wrapped.mutex.xMutexInit();
75   }
76   if( rc==SQLITE_OK ){
77     wrapped.mutex_init = 1;
78   }
79   return rc;
80 }
81 static int wrMutexEnd(void){
82   wrapped.mutex.xMutexEnd();
83   wrapped.mutex_init = 0;
84   return SQLITE_OK;
85 }
86 static sqlite3_mutex *wrMutexAlloc(int e){
87   return wrapped.mutex.xMutexAlloc(e);
88 }
89 static void wrMutexFree(sqlite3_mutex *p){
90   wrapped.mutex.xMutexFree(p);
91 }
92 static void wrMutexEnter(sqlite3_mutex *p){
93   wrapped.mutex.xMutexEnter(p);
94 }
95 static int wrMutexTry(sqlite3_mutex *p){
96   return wrapped.mutex.xMutexTry(p);
97 }
98 static void wrMutexLeave(sqlite3_mutex *p){
99   wrapped.mutex.xMutexLeave(p);
100 }
101 static int wrMutexHeld(sqlite3_mutex *p){
102   return wrapped.mutex.xMutexHeld(p);
103 }
104 static int wrMutexNotheld(sqlite3_mutex *p){
105   return wrapped.mutex.xMutexNotheld(p);
106 }
107 
108 
109 
110 static int wrPCacheInit(void *pArg){
111   int rc;
112   if( wrapped.pcache_fail ){
113     rc = SQLITE_ERROR;
114   }else{
115     rc = wrapped.pcache.xInit(wrapped.pcache.pArg);
116   }
117   if( rc==SQLITE_OK ){
118     wrapped.pcache_init = 1;
119   }
120   return rc;
121 }
122 static void wrPCacheShutdown(void *pArg){
123   wrapped.pcache.xShutdown(wrapped.pcache.pArg);
124   wrapped.pcache_init = 0;
125 }
126 
127 static sqlite3_pcache *wrPCacheCreate(int a, int b){
128   return wrapped.pcache.xCreate(a, b);
129 }
130 static void wrPCacheCachesize(sqlite3_pcache *p, int n){
131   wrapped.pcache.xCachesize(p, n);
132 }
133 static int wrPCachePagecount(sqlite3_pcache *p){
134   return wrapped.pcache.xPagecount(p);
135 }
136 static void *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){
137   return wrapped.pcache.xFetch(p, a, b);
138 }
139 static void wrPCacheUnpin(sqlite3_pcache *p, void *a, int b){
140   wrapped.pcache.xUnpin(p, a, b);
141 }
142 static void wrPCacheRekey(sqlite3_pcache *p, void *a, unsigned b, unsigned c){
143   wrapped.pcache.xRekey(p, a, b, c);
144 }
145 static void wrPCacheTruncate(sqlite3_pcache *p, unsigned a){
146   wrapped.pcache.xTruncate(p, a);
147 }
148 static void wrPCacheDestroy(sqlite3_pcache *p){
149   wrapped.pcache.xDestroy(p);
150 }
151 
152 static void installInitWrappers(void){
153   sqlite3_mutex_methods mutexmethods = {
154     wrMutexInit,  wrMutexEnd,   wrMutexAlloc,
155     wrMutexFree,  wrMutexEnter, wrMutexTry,
156     wrMutexLeave, wrMutexHeld,  wrMutexNotheld
157   };
158   sqlite3_pcache_methods pcachemethods = {
159     0,
160     wrPCacheInit,      wrPCacheShutdown,  wrPCacheCreate,
161     wrPCacheCachesize, wrPCachePagecount, wrPCacheFetch,
162     wrPCacheUnpin,     wrPCacheRekey,     wrPCacheTruncate,
163     wrPCacheDestroy
164   };
165   sqlite3_mem_methods memmethods = {
166     wrMemMalloc,   wrMemFree,    wrMemRealloc,
167     wrMemSize,     wrMemRoundup, wrMemInit,
168     wrMemShutdown,
169     0
170   };
171 
172   memset(&wrapped, 0, sizeof(wrapped));
173 
174   sqlite3_shutdown();
175   sqlite3_config(SQLITE_CONFIG_GETMUTEX, &wrapped.mutex);
176   sqlite3_config(SQLITE_CONFIG_GETMALLOC, &wrapped.mem);
177   sqlite3_config(SQLITE_CONFIG_GETPCACHE, &wrapped.pcache);
178   sqlite3_config(SQLITE_CONFIG_MUTEX, &mutexmethods);
179   sqlite3_config(SQLITE_CONFIG_MALLOC, &memmethods);
180   sqlite3_config(SQLITE_CONFIG_PCACHE, &pcachemethods);
181 }
182 
183 static int init_wrapper_install(
184   ClientData clientData, /* Unused */
185   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
186   int objc,              /* Number of arguments */
187   Tcl_Obj *CONST objv[]  /* Command arguments */
188 ){
189   int i;
190   installInitWrappers();
191   for(i=1; i<objc; i++){
192     char *z = Tcl_GetString(objv[i]);
193     if( strcmp(z, "mem")==0 ){
194       wrapped.mem_fail = 1;
195     }else if( strcmp(z, "mutex")==0 ){
196       wrapped.mutex_fail = 1;
197     }else if( strcmp(z, "pcache")==0 ){
198       wrapped.pcache_fail = 1;
199     }else if( strcmp(z, "os")==0 ){
200       wrapped.osinit_fail = 1;
201     }else{
202       Tcl_AppendResult(interp, "Unknown argument: \"", z, "\"");
203       return TCL_ERROR;
204     }
205   }
206   return TCL_OK;
207 }
208 
209 static int init_wrapper_uninstall(
210   ClientData clientData, /* Unused */
211   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
212   int objc,              /* Number of arguments */
213   Tcl_Obj *CONST objv[]  /* Command arguments */
214 ){
215   if( objc!=1 ){
216     Tcl_WrongNumArgs(interp, 1, objv, "");
217     return TCL_ERROR;
218   }
219 
220   memset(&wrapped, 0, sizeof(&wrapped));
221   sqlite3_shutdown();
222   sqlite3_config(SQLITE_CONFIG_MUTEX, &wrapped.mutex);
223   sqlite3_config(SQLITE_CONFIG_MALLOC, &wrapped.mem);
224   sqlite3_config(SQLITE_CONFIG_PCACHE, &wrapped.pcache);
225   return TCL_OK;
226 }
227 
228 static int init_wrapper_clear(
229   ClientData clientData, /* Unused */
230   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
231   int objc,              /* Number of arguments */
232   Tcl_Obj *CONST objv[]  /* Command arguments */
233 ){
234   if( objc!=1 ){
235     Tcl_WrongNumArgs(interp, 1, objv, "");
236     return TCL_ERROR;
237   }
238 
239   wrapped.mem_fail = 0;
240   wrapped.mutex_fail = 0;
241   wrapped.pcache_fail = 0;
242   wrapped.osinit_fail = 0;
243   return TCL_OK;
244 }
245 
246 static int init_wrapper_query(
247   ClientData clientData, /* Unused */
248   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
249   int objc,              /* Number of arguments */
250   Tcl_Obj *CONST objv[]  /* Command arguments */
251 ){
252   Tcl_Obj *pRet;
253 
254   if( objc!=1 ){
255     Tcl_WrongNumArgs(interp, 1, objv, "");
256     return TCL_ERROR;
257   }
258 
259   pRet = Tcl_NewObj();
260   if( wrapped.mutex_init ){
261     Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mutex", -1));
262   }
263   if( wrapped.mem_init ){
264     Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mem", -1));
265   }
266   if( wrapped.pcache_init ){
267     Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("pcache", -1));
268   }
269   if( sqlite3GlobalConfig.isInit ){
270     Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("os", -1));
271   }
272 
273   Tcl_SetObjResult(interp, pRet);
274   return TCL_OK;
275 }
276 
277 int sqlite3TestFailOsInit(void){
278   return (wrapped.mem.xMalloc && wrapped.osinit_fail);
279 }
280 
281 int Sqlitetest_init_Init(Tcl_Interp *interp){
282   static struct {
283      char *zName;
284      Tcl_ObjCmdProc *xProc;
285   } aObjCmd[] = {
286     {"init_wrapper_install",   init_wrapper_install},
287     {"init_wrapper_query",     init_wrapper_query  },
288     {"init_wrapper_uninstall", init_wrapper_uninstall},
289     {"init_wrapper_clear",     init_wrapper_clear}
290   };
291   int i;
292 
293   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
294     Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
295   }
296 
297   return TCL_OK;
298 }
299 
300