xref: /sqlite-3.40.0/src/test_func.c (revision 8a29dfde)
1 /*
2 ** 2008 March 19
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 ** Code for testing all sorts of SQLite interfaces.  This code
13 ** implements new SQL functions used by the test scripts.
14 **
15 ** $Id: test_func.c,v 1.4 2008/04/10 17:14:07 drh Exp $
16 */
17 #include "sqlite3.h"
18 #include "tcl.h"
19 #include <stdlib.h>
20 #include <string.h>
21 #include <assert.h>
22 
23 
24 /*
25 ** Allocate nByte bytes of space using sqlite3_malloc(). If the
26 ** allocation fails, call sqlite3_result_error_nomem() to notify
27 ** the database handle that malloc() has failed.
28 */
29 static void *testContextMalloc(sqlite3_context *context, int nByte){
30   char *z = sqlite3_malloc(nByte);
31   if( !z && nByte>0 ){
32     sqlite3_result_error_nomem(context);
33   }
34   return z;
35 }
36 
37 /*
38 ** This function generates a string of random characters.  Used for
39 ** generating test data.
40 */
41 static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){
42   static const unsigned char zSrc[] =
43      "abcdefghijklmnopqrstuvwxyz"
44      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
45      "0123456789"
46      ".-!,:*^+=_|?/<> ";
47   int iMin, iMax, n, r, i;
48   unsigned char zBuf[1000];
49 
50   /* It used to be possible to call randstr() with any number of arguments,
51   ** but now it is registered with SQLite as requiring exactly 2.
52   */
53   assert(argc==2);
54 
55   iMin = sqlite3_value_int(argv[0]);
56   if( iMin<0 ) iMin = 0;
57   if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1;
58   iMax = sqlite3_value_int(argv[1]);
59   if( iMax<iMin ) iMax = iMin;
60   if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1;
61   n = iMin;
62   if( iMax>iMin ){
63     sqlite3_randomness(sizeof(r), &r);
64     r &= 0x7fffffff;
65     n += r%(iMax + 1 - iMin);
66   }
67   assert( n<sizeof(zBuf) );
68   sqlite3_randomness(n, zBuf);
69   for(i=0; i<n; i++){
70     zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)];
71   }
72   zBuf[n] = 0;
73   sqlite3_result_text(context, (char*)zBuf, n, SQLITE_TRANSIENT);
74 }
75 
76 /*
77 ** The following two SQL functions are used to test returning a text
78 ** result with a destructor. Function 'test_destructor' takes one argument
79 ** and returns the same argument interpreted as TEXT. A destructor is
80 ** passed with the sqlite3_result_text() call.
81 **
82 ** SQL function 'test_destructor_count' returns the number of outstanding
83 ** allocations made by 'test_destructor';
84 **
85 ** WARNING: Not threadsafe.
86 */
87 static int test_destructor_count_var = 0;
88 static void destructor(void *p){
89   char *zVal = (char *)p;
90   assert(zVal);
91   zVal--;
92   sqlite3_free(zVal);
93   test_destructor_count_var--;
94 }
95 static void test_destructor(
96   sqlite3_context *pCtx,
97   int nArg,
98   sqlite3_value **argv
99 ){
100   char *zVal;
101   int len;
102 
103   test_destructor_count_var++;
104   assert( nArg==1 );
105   if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
106   len = sqlite3_value_bytes(argv[0]);
107   zVal = testContextMalloc(pCtx, len+3);
108   if( !zVal ){
109     return;
110   }
111   zVal[len+1] = 0;
112   zVal[len+2] = 0;
113   zVal++;
114   memcpy(zVal, sqlite3_value_text(argv[0]), len);
115   sqlite3_result_text(pCtx, zVal, -1, destructor);
116 }
117 static void test_destructor16(
118   sqlite3_context *pCtx,
119   int nArg,
120   sqlite3_value **argv
121 ){
122   char *zVal;
123   int len;
124 
125   test_destructor_count_var++;
126   assert( nArg==1 );
127   if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
128   len = sqlite3_value_bytes16(argv[0]);
129   zVal = testContextMalloc(pCtx, len+3);
130   if( !zVal ){
131     return;
132   }
133   zVal[len+1] = 0;
134   zVal[len+2] = 0;
135   zVal++;
136   memcpy(zVal, sqlite3_value_text16(argv[0]), len);
137   sqlite3_result_text16(pCtx, zVal, -1, destructor);
138 }
139 static void test_destructor_count(
140   sqlite3_context *pCtx,
141   int nArg,
142   sqlite3_value **argv
143 ){
144   sqlite3_result_int(pCtx, test_destructor_count_var);
145 }
146 
147 /*
148 ** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata()
149 ** interface.
150 **
151 ** The test_auxdata() SQL function attempts to register each of its arguments
152 ** as auxiliary data.  If there are no prior registrations of aux data for
153 ** that argument (meaning the argument is not a constant or this is its first
154 ** call) then the result for that argument is 0.  If there is a prior
155 ** registration, the result for that argument is 1.  The overall result
156 ** is the individual argument results separated by spaces.
157 */
158 static void free_test_auxdata(void *p) {sqlite3_free(p);}
159 static void test_auxdata(
160   sqlite3_context *pCtx,
161   int nArg,
162   sqlite3_value **argv
163 ){
164   int i;
165   char *zRet = testContextMalloc(pCtx, nArg*2);
166   if( !zRet ) return;
167   memset(zRet, 0, nArg*2);
168   for(i=0; i<nArg; i++){
169     char const *z = (char*)sqlite3_value_text(argv[i]);
170     if( z ){
171       int n;
172       char *zAux = sqlite3_get_auxdata(pCtx, i);
173       if( zAux ){
174         zRet[i*2] = '1';
175         assert( strcmp(zAux,z)==0 );
176       }else {
177         zRet[i*2] = '0';
178       }
179       n = strlen(z) + 1;
180       zAux = testContextMalloc(pCtx, n);
181       if( zAux ){
182         memcpy(zAux, z, n);
183         sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata);
184       }
185       zRet[i*2+1] = ' ';
186     }
187   }
188   sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata);
189 }
190 
191 /*
192 ** A function to test error reporting from user functions. This function
193 ** returns a copy of its first argument as the error message.  If the
194 ** second argument exists, it becomes the error code.
195 */
196 static void test_error(
197   sqlite3_context *pCtx,
198   int nArg,
199   sqlite3_value **argv
200 ){
201   sqlite3_result_error(pCtx, (char*)sqlite3_value_text(argv[0]), -1);
202   if( nArg==2 ){
203     sqlite3_result_error_code(pCtx, sqlite3_value_int(argv[1]));
204   }
205 }
206 
207 static int registerTestFunctions(sqlite3 *db){
208   static const struct {
209      char *zName;
210      signed char nArg;
211      unsigned char eTextRep; /* 1: UTF-16.  0: UTF-8 */
212      void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
213   } aFuncs[] = {
214     { "randstr",               2, SQLITE_UTF8, randStr    },
215     { "test_destructor",       1, SQLITE_UTF8, test_destructor},
216     { "test_destructor16",     1, SQLITE_UTF8, test_destructor16},
217     { "test_destructor_count", 0, SQLITE_UTF8, test_destructor_count},
218     { "test_auxdata",         -1, SQLITE_UTF8, test_auxdata},
219     { "test_error",            1, SQLITE_UTF8, test_error},
220     { "test_error",            2, SQLITE_UTF8, test_error},
221   };
222   int i;
223   extern int Md5_Register(sqlite3*);
224 
225   for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
226     sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
227         aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0);
228   }
229   Md5_Register(db);
230   return SQLITE_OK;
231 }
232 
233 /*
234 ** TCLCMD:  autoinstall_test_functions
235 **
236 ** Invoke this TCL command to use sqlite3_auto_extension() to cause
237 ** the standard set of test functions to be loaded into each new
238 ** database connection.
239 */
240 static int autoinstall_test_funcs(
241   void * clientData,
242   Tcl_Interp *interp,
243   int objc,
244   Tcl_Obj *CONST objv[]
245 ){
246   sqlite3_auto_extension((void*)registerTestFunctions);
247   return TCL_OK;
248 }
249 
250 
251 
252 /*
253 ** Register commands with the TCL interpreter.
254 */
255 int Sqlitetest_func_Init(Tcl_Interp *interp){
256   static struct {
257      char *zName;
258      Tcl_ObjCmdProc *xProc;
259   } aObjCmd[] = {
260      { "autoinstall_test_functions",    autoinstall_test_funcs },
261   };
262   int i;
263   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
264     Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
265   }
266   sqlite3_auto_extension((void*)registerTestFunctions);
267   return TCL_OK;
268 }
269