xref: /sqlite-3.40.0/src/test_init.c (revision d5578433)
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_methods2 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 } wrapped;
44 
45 static int wrMemInit(void *pAppData){
46   int rc;
47   if( wrapped.mem_fail ){
48     rc = SQLITE_ERROR;
49   }else{
50     rc = wrapped.mem.xInit(wrapped.mem.pAppData);
51   }
52   if( rc==SQLITE_OK ){
53     wrapped.mem_init = 1;
54   }
55   return rc;
56 }
57 static void wrMemShutdown(void *pAppData){
58   wrapped.mem.xShutdown(wrapped.mem.pAppData);
59   wrapped.mem_init = 0;
60 }
61 static void *wrMemMalloc(int n)           {return wrapped.mem.xMalloc(n);}
62 static void wrMemFree(void *p)            {wrapped.mem.xFree(p);}
63 static void *wrMemRealloc(void *p, int n) {return wrapped.mem.xRealloc(p, n);}
64 static int wrMemSize(void *p)             {return wrapped.mem.xSize(p);}
65 static int wrMemRoundup(int n)            {return wrapped.mem.xRoundup(n);}
66 
67 
68 static int wrMutexInit(void){
69   int rc;
70   if( wrapped.mutex_fail ){
71     rc = SQLITE_ERROR;
72   }else{
73     rc = wrapped.mutex.xMutexInit();
74   }
75   if( rc==SQLITE_OK ){
76     wrapped.mutex_init = 1;
77   }
78   return rc;
79 }
80 static int wrMutexEnd(void){
81   wrapped.mutex.xMutexEnd();
82   wrapped.mutex_init = 0;
83   return SQLITE_OK;
84 }
85 static sqlite3_mutex *wrMutexAlloc(int e){
86   return wrapped.mutex.xMutexAlloc(e);
87 }
88 static void wrMutexFree(sqlite3_mutex *p){
89   wrapped.mutex.xMutexFree(p);
90 }
91 static void wrMutexEnter(sqlite3_mutex *p){
92   wrapped.mutex.xMutexEnter(p);
93 }
94 static int wrMutexTry(sqlite3_mutex *p){
95   return wrapped.mutex.xMutexTry(p);
96 }
97 static void wrMutexLeave(sqlite3_mutex *p){
98   wrapped.mutex.xMutexLeave(p);
99 }
100 static int wrMutexHeld(sqlite3_mutex *p){
101   return wrapped.mutex.xMutexHeld(p);
102 }
103 static int wrMutexNotheld(sqlite3_mutex *p){
104   return wrapped.mutex.xMutexNotheld(p);
105 }
106 
107 
108 
109 static int wrPCacheInit(void *pArg){
110   int rc;
111   if( wrapped.pcache_fail ){
112     rc = SQLITE_ERROR;
113   }else{
114     rc = wrapped.pcache.xInit(wrapped.pcache.pArg);
115   }
116   if( rc==SQLITE_OK ){
117     wrapped.pcache_init = 1;
118   }
119   return rc;
120 }
121 static void wrPCacheShutdown(void *pArg){
122   wrapped.pcache.xShutdown(wrapped.pcache.pArg);
123   wrapped.pcache_init = 0;
124 }
125 
126 static sqlite3_pcache *wrPCacheCreate(int a, int b, int c){
127   return wrapped.pcache.xCreate(a, b, c);
128 }
129 static void wrPCacheCachesize(sqlite3_pcache *p, int n){
130   wrapped.pcache.xCachesize(p, n);
131 }
132 static int wrPCachePagecount(sqlite3_pcache *p){
133   return wrapped.pcache.xPagecount(p);
134 }
135 static sqlite3_pcache_page *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){
136   return wrapped.pcache.xFetch(p, a, b);
137 }
138 static void wrPCacheUnpin(sqlite3_pcache *p, sqlite3_pcache_page *a, int b){
139   wrapped.pcache.xUnpin(p, a, b);
140 }
141 static void wrPCacheRekey(
142   sqlite3_pcache *p,
143   sqlite3_pcache_page *a,
144   unsigned b,
145   unsigned c
146 ){
147   wrapped.pcache.xRekey(p, a, b, c);
148 }
149 static void wrPCacheTruncate(sqlite3_pcache *p, unsigned a){
150   wrapped.pcache.xTruncate(p, a);
151 }
152 static void wrPCacheDestroy(sqlite3_pcache *p){
153   wrapped.pcache.xDestroy(p);
154 }
155 
156 static void installInitWrappers(void){
157   sqlite3_mutex_methods mutexmethods = {
158     wrMutexInit,  wrMutexEnd,   wrMutexAlloc,
159     wrMutexFree,  wrMutexEnter, wrMutexTry,
160     wrMutexLeave, wrMutexHeld,  wrMutexNotheld
161   };
162   sqlite3_pcache_methods2 pcachemethods = {
163     1, 0,
164     wrPCacheInit,      wrPCacheShutdown,  wrPCacheCreate,
165     wrPCacheCachesize, wrPCachePagecount, wrPCacheFetch,
166     wrPCacheUnpin,     wrPCacheRekey,     wrPCacheTruncate,
167     wrPCacheDestroy
168   };
169   sqlite3_mem_methods memmethods = {
170     wrMemMalloc,   wrMemFree,    wrMemRealloc,
171     wrMemSize,     wrMemRoundup, wrMemInit,
172     wrMemShutdown,
173     0
174   };
175 
176   memset(&wrapped, 0, sizeof(wrapped));
177 
178   sqlite3_shutdown();
179   sqlite3_config(SQLITE_CONFIG_GETMUTEX, &wrapped.mutex);
180   sqlite3_config(SQLITE_CONFIG_GETMALLOC, &wrapped.mem);
181   sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &wrapped.pcache);
182   sqlite3_config(SQLITE_CONFIG_MUTEX, &mutexmethods);
183   sqlite3_config(SQLITE_CONFIG_MALLOC, &memmethods);
184   sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcachemethods);
185 }
186 
187 static int init_wrapper_install(
188   ClientData clientData, /* Unused */
189   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
190   int objc,              /* Number of arguments */
191   Tcl_Obj *CONST objv[]  /* Command arguments */
192 ){
193   int i;
194   installInitWrappers();
195   for(i=1; i<objc; i++){
196     char *z = Tcl_GetString(objv[i]);
197     if( strcmp(z, "mem")==0 ){
198       wrapped.mem_fail = 1;
199     }else if( strcmp(z, "mutex")==0 ){
200       wrapped.mutex_fail = 1;
201     }else if( strcmp(z, "pcache")==0 ){
202       wrapped.pcache_fail = 1;
203     }else{
204       Tcl_AppendResult(interp, "Unknown argument: \"", z, "\"");
205       return TCL_ERROR;
206     }
207   }
208   return TCL_OK;
209 }
210 
211 static int init_wrapper_uninstall(
212   ClientData clientData, /* Unused */
213   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
214   int objc,              /* Number of arguments */
215   Tcl_Obj *CONST objv[]  /* Command arguments */
216 ){
217   if( objc!=1 ){
218     Tcl_WrongNumArgs(interp, 1, objv, "");
219     return TCL_ERROR;
220   }
221 
222   memset(&wrapped, 0, sizeof(&wrapped));
223   sqlite3_shutdown();
224   sqlite3_config(SQLITE_CONFIG_MUTEX, &wrapped.mutex);
225   sqlite3_config(SQLITE_CONFIG_MALLOC, &wrapped.mem);
226   sqlite3_config(SQLITE_CONFIG_PCACHE2, &wrapped.pcache);
227   return TCL_OK;
228 }
229 
230 static int init_wrapper_clear(
231   ClientData clientData, /* Unused */
232   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
233   int objc,              /* Number of arguments */
234   Tcl_Obj *CONST objv[]  /* Command arguments */
235 ){
236   if( objc!=1 ){
237     Tcl_WrongNumArgs(interp, 1, objv, "");
238     return TCL_ERROR;
239   }
240 
241   wrapped.mem_fail = 0;
242   wrapped.mutex_fail = 0;
243   wrapped.pcache_fail = 0;
244   return TCL_OK;
245 }
246 
247 static int init_wrapper_query(
248   ClientData clientData, /* Unused */
249   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
250   int objc,              /* Number of arguments */
251   Tcl_Obj *CONST objv[]  /* Command arguments */
252 ){
253   Tcl_Obj *pRet;
254 
255   if( objc!=1 ){
256     Tcl_WrongNumArgs(interp, 1, objv, "");
257     return TCL_ERROR;
258   }
259 
260   pRet = Tcl_NewObj();
261   if( wrapped.mutex_init ){
262     Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mutex", -1));
263   }
264   if( wrapped.mem_init ){
265     Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mem", -1));
266   }
267   if( wrapped.pcache_init ){
268     Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("pcache", -1));
269   }
270 
271   Tcl_SetObjResult(interp, pRet);
272   return TCL_OK;
273 }
274 
275 int Sqlitetest_init_Init(Tcl_Interp *interp){
276   static struct {
277      char *zName;
278      Tcl_ObjCmdProc *xProc;
279   } aObjCmd[] = {
280     {"init_wrapper_install",   init_wrapper_install},
281     {"init_wrapper_query",     init_wrapper_query  },
282     {"init_wrapper_uninstall", init_wrapper_uninstall},
283     {"init_wrapper_clear",     init_wrapper_clear}
284   };
285   int i;
286 
287   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
288     Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
289   }
290 
291   return TCL_OK;
292 }
293