xref: /sqlite-3.40.0/src/test_func.c (revision da84ca8d)
1984bfaa4Sdrh /*
2984bfaa4Sdrh ** 2008 March 19
3984bfaa4Sdrh **
4984bfaa4Sdrh ** The author disclaims copyright to this source code.  In place of
5984bfaa4Sdrh ** a legal notice, here is a blessing:
6984bfaa4Sdrh **
7984bfaa4Sdrh **    May you do good and not evil.
8984bfaa4Sdrh **    May you find forgiveness for yourself and forgive others.
9984bfaa4Sdrh **    May you share freely, never taking more than you give.
10984bfaa4Sdrh **
11984bfaa4Sdrh *************************************************************************
12984bfaa4Sdrh ** Code for testing all sorts of SQLite interfaces.  This code
13984bfaa4Sdrh ** implements new SQL functions used by the test scripts.
14984bfaa4Sdrh **
15*da84ca8dSdrh ** $Id: test_func.c,v 1.2 2008/03/19 16:35:24 drh Exp $
16984bfaa4Sdrh */
17984bfaa4Sdrh #include "sqlite3.h"
18984bfaa4Sdrh #include "tcl.h"
19984bfaa4Sdrh #include <stdlib.h>
20984bfaa4Sdrh #include <string.h>
21984bfaa4Sdrh #include <assert.h>
22984bfaa4Sdrh 
23984bfaa4Sdrh 
24984bfaa4Sdrh /*
25984bfaa4Sdrh ** Allocate nByte bytes of space using sqlite3_malloc(). If the
26984bfaa4Sdrh ** allocation fails, call sqlite3_result_error_nomem() to notify
27984bfaa4Sdrh ** the database handle that malloc() has failed.
28984bfaa4Sdrh */
29984bfaa4Sdrh static void *testContextMalloc(sqlite3_context *context, int nByte){
30984bfaa4Sdrh   char *z = sqlite3_malloc(nByte);
31984bfaa4Sdrh   if( !z && nByte>0 ){
32984bfaa4Sdrh     sqlite3_result_error_nomem(context);
33984bfaa4Sdrh   }
34984bfaa4Sdrh   return z;
35984bfaa4Sdrh }
36984bfaa4Sdrh 
37984bfaa4Sdrh /*
38984bfaa4Sdrh ** This function generates a string of random characters.  Used for
39984bfaa4Sdrh ** generating test data.
40984bfaa4Sdrh */
41984bfaa4Sdrh static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){
42984bfaa4Sdrh   static const unsigned char zSrc[] =
43984bfaa4Sdrh      "abcdefghijklmnopqrstuvwxyz"
44984bfaa4Sdrh      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
45984bfaa4Sdrh      "0123456789"
46984bfaa4Sdrh      ".-!,:*^+=_|?/<> ";
47984bfaa4Sdrh   int iMin, iMax, n, r, i;
48984bfaa4Sdrh   unsigned char zBuf[1000];
49984bfaa4Sdrh 
50984bfaa4Sdrh   /* It used to be possible to call randstr() with any number of arguments,
51984bfaa4Sdrh   ** but now it is registered with SQLite as requiring exactly 2.
52984bfaa4Sdrh   */
53984bfaa4Sdrh   assert(argc==2);
54984bfaa4Sdrh 
55984bfaa4Sdrh   iMin = sqlite3_value_int(argv[0]);
56984bfaa4Sdrh   if( iMin<0 ) iMin = 0;
57984bfaa4Sdrh   if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1;
58984bfaa4Sdrh   iMax = sqlite3_value_int(argv[1]);
59984bfaa4Sdrh   if( iMax<iMin ) iMax = iMin;
60984bfaa4Sdrh   if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1;
61984bfaa4Sdrh   n = iMin;
62984bfaa4Sdrh   if( iMax>iMin ){
63984bfaa4Sdrh     sqlite3_randomness(sizeof(r), &r);
64984bfaa4Sdrh     r &= 0x7fffffff;
65984bfaa4Sdrh     n += r%(iMax + 1 - iMin);
66984bfaa4Sdrh   }
67984bfaa4Sdrh   assert( n<sizeof(zBuf) );
68984bfaa4Sdrh   sqlite3_randomness(n, zBuf);
69984bfaa4Sdrh   for(i=0; i<n; i++){
70984bfaa4Sdrh     zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)];
71984bfaa4Sdrh   }
72984bfaa4Sdrh   zBuf[n] = 0;
73984bfaa4Sdrh   sqlite3_result_text(context, (char*)zBuf, n, SQLITE_TRANSIENT);
74984bfaa4Sdrh }
75984bfaa4Sdrh 
76984bfaa4Sdrh /*
77984bfaa4Sdrh ** The following two SQL functions are used to test returning a text
78984bfaa4Sdrh ** result with a destructor. Function 'test_destructor' takes one argument
79984bfaa4Sdrh ** and returns the same argument interpreted as TEXT. A destructor is
80984bfaa4Sdrh ** passed with the sqlite3_result_text() call.
81984bfaa4Sdrh **
82984bfaa4Sdrh ** SQL function 'test_destructor_count' returns the number of outstanding
83984bfaa4Sdrh ** allocations made by 'test_destructor';
84984bfaa4Sdrh **
85984bfaa4Sdrh ** WARNING: Not threadsafe.
86984bfaa4Sdrh */
87984bfaa4Sdrh static int test_destructor_count_var = 0;
88984bfaa4Sdrh static void destructor(void *p){
89984bfaa4Sdrh   char *zVal = (char *)p;
90984bfaa4Sdrh   assert(zVal);
91984bfaa4Sdrh   zVal--;
92984bfaa4Sdrh   sqlite3_free(zVal);
93984bfaa4Sdrh   test_destructor_count_var--;
94984bfaa4Sdrh }
95984bfaa4Sdrh static void test_destructor(
96984bfaa4Sdrh   sqlite3_context *pCtx,
97984bfaa4Sdrh   int nArg,
98984bfaa4Sdrh   sqlite3_value **argv
99984bfaa4Sdrh ){
100984bfaa4Sdrh   char *zVal;
101984bfaa4Sdrh   int len;
102984bfaa4Sdrh 
103984bfaa4Sdrh   test_destructor_count_var++;
104984bfaa4Sdrh   assert( nArg==1 );
105984bfaa4Sdrh   if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
106984bfaa4Sdrh   len = sqlite3_value_bytes(argv[0]);
107984bfaa4Sdrh   zVal = testContextMalloc(pCtx, len+3);
108984bfaa4Sdrh   if( !zVal ){
109984bfaa4Sdrh     return;
110984bfaa4Sdrh   }
111984bfaa4Sdrh   zVal[len+1] = 0;
112984bfaa4Sdrh   zVal[len+2] = 0;
113984bfaa4Sdrh   zVal++;
114984bfaa4Sdrh   memcpy(zVal, sqlite3_value_text(argv[0]), len);
115984bfaa4Sdrh   sqlite3_result_text(pCtx, zVal, -1, destructor);
116984bfaa4Sdrh }
117*da84ca8dSdrh static void test_destructor16(
118*da84ca8dSdrh   sqlite3_context *pCtx,
119*da84ca8dSdrh   int nArg,
120*da84ca8dSdrh   sqlite3_value **argv
121*da84ca8dSdrh ){
122*da84ca8dSdrh   char *zVal;
123*da84ca8dSdrh   int len;
124*da84ca8dSdrh 
125*da84ca8dSdrh   test_destructor_count_var++;
126*da84ca8dSdrh   assert( nArg==1 );
127*da84ca8dSdrh   if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
128*da84ca8dSdrh   len = sqlite3_value_bytes16(argv[0]);
129*da84ca8dSdrh   zVal = testContextMalloc(pCtx, len+3);
130*da84ca8dSdrh   if( !zVal ){
131*da84ca8dSdrh     return;
132*da84ca8dSdrh   }
133*da84ca8dSdrh   zVal[len+1] = 0;
134*da84ca8dSdrh   zVal[len+2] = 0;
135*da84ca8dSdrh   zVal++;
136*da84ca8dSdrh   memcpy(zVal, sqlite3_value_text16(argv[0]), len);
137*da84ca8dSdrh   sqlite3_result_text16(pCtx, zVal, -1, destructor);
138*da84ca8dSdrh }
139984bfaa4Sdrh static void test_destructor_count(
140984bfaa4Sdrh   sqlite3_context *pCtx,
141984bfaa4Sdrh   int nArg,
142984bfaa4Sdrh   sqlite3_value **argv
143984bfaa4Sdrh ){
144984bfaa4Sdrh   sqlite3_result_int(pCtx, test_destructor_count_var);
145984bfaa4Sdrh }
146984bfaa4Sdrh 
147984bfaa4Sdrh /*
148984bfaa4Sdrh ** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata()
149984bfaa4Sdrh ** interface.
150984bfaa4Sdrh **
151984bfaa4Sdrh ** The test_auxdata() SQL function attempts to register each of its arguments
152984bfaa4Sdrh ** as auxiliary data.  If there are no prior registrations of aux data for
153984bfaa4Sdrh ** that argument (meaning the argument is not a constant or this is its first
154984bfaa4Sdrh ** call) then the result for that argument is 0.  If there is a prior
155984bfaa4Sdrh ** registration, the result for that argument is 1.  The overall result
156984bfaa4Sdrh ** is the individual argument results separated by spaces.
157984bfaa4Sdrh */
158984bfaa4Sdrh static void free_test_auxdata(void *p) {sqlite3_free(p);}
159984bfaa4Sdrh static void test_auxdata(
160984bfaa4Sdrh   sqlite3_context *pCtx,
161984bfaa4Sdrh   int nArg,
162984bfaa4Sdrh   sqlite3_value **argv
163984bfaa4Sdrh ){
164984bfaa4Sdrh   int i;
165984bfaa4Sdrh   char *zRet = testContextMalloc(pCtx, nArg*2);
166984bfaa4Sdrh   if( !zRet ) return;
167984bfaa4Sdrh   memset(zRet, 0, nArg*2);
168984bfaa4Sdrh   for(i=0; i<nArg; i++){
169984bfaa4Sdrh     char const *z = (char*)sqlite3_value_text(argv[i]);
170984bfaa4Sdrh     if( z ){
171984bfaa4Sdrh       int n;
172984bfaa4Sdrh       char *zAux = sqlite3_get_auxdata(pCtx, i);
173984bfaa4Sdrh       if( zAux ){
174984bfaa4Sdrh         zRet[i*2] = '1';
175984bfaa4Sdrh         assert( strcmp(zAux,z)==0 );
176984bfaa4Sdrh       }else {
177984bfaa4Sdrh         zRet[i*2] = '0';
178984bfaa4Sdrh       }
179984bfaa4Sdrh       n = strlen(z) + 1;
180984bfaa4Sdrh       zAux = testContextMalloc(pCtx, n);
181984bfaa4Sdrh       if( zAux ){
182984bfaa4Sdrh         memcpy(zAux, z, n);
183984bfaa4Sdrh         sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata);
184984bfaa4Sdrh       }
185984bfaa4Sdrh       zRet[i*2+1] = ' ';
186984bfaa4Sdrh     }
187984bfaa4Sdrh   }
188984bfaa4Sdrh   sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata);
189984bfaa4Sdrh }
190984bfaa4Sdrh 
191984bfaa4Sdrh /*
192984bfaa4Sdrh ** A function to test error reporting from user functions. This function
193984bfaa4Sdrh ** returns a copy of its first argument as an error.
194984bfaa4Sdrh */
195984bfaa4Sdrh static void test_error(
196984bfaa4Sdrh   sqlite3_context *pCtx,
197984bfaa4Sdrh   int nArg,
198984bfaa4Sdrh   sqlite3_value **argv
199984bfaa4Sdrh ){
200984bfaa4Sdrh   sqlite3_result_error(pCtx, (char*)sqlite3_value_text(argv[0]), 0);
201984bfaa4Sdrh }
202984bfaa4Sdrh 
203984bfaa4Sdrh static int registerTestFunctions(sqlite3 *db){
204984bfaa4Sdrh   static const struct {
205984bfaa4Sdrh      char *zName;
206984bfaa4Sdrh      signed char nArg;
207984bfaa4Sdrh      unsigned char eTextRep; /* 1: UTF-16.  0: UTF-8 */
208984bfaa4Sdrh      void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
209984bfaa4Sdrh   } aFuncs[] = {
210984bfaa4Sdrh     { "randstr",               2, SQLITE_UTF8, randStr    },
211984bfaa4Sdrh     { "test_destructor",       1, SQLITE_UTF8, test_destructor},
212*da84ca8dSdrh     { "test_destructor16",     1, SQLITE_UTF8, test_destructor16},
213984bfaa4Sdrh     { "test_destructor_count", 0, SQLITE_UTF8, test_destructor_count},
214984bfaa4Sdrh     { "test_auxdata",         -1, SQLITE_UTF8, test_auxdata},
215984bfaa4Sdrh     { "test_error",            1, SQLITE_UTF8, test_error},
216984bfaa4Sdrh   };
217984bfaa4Sdrh   int i;
218984bfaa4Sdrh 
219984bfaa4Sdrh   for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
220984bfaa4Sdrh     sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
221984bfaa4Sdrh         aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0);
222984bfaa4Sdrh   }
223984bfaa4Sdrh   return SQLITE_OK;
224984bfaa4Sdrh }
225984bfaa4Sdrh 
226984bfaa4Sdrh /*
227984bfaa4Sdrh ** TCLCMD:  autoinstall_test_functions
228984bfaa4Sdrh **
229984bfaa4Sdrh ** Invoke this TCL command to use sqlite3_auto_extension() to cause
230984bfaa4Sdrh ** the standard set of test functions to be loaded into each new
231984bfaa4Sdrh ** database connection.
232984bfaa4Sdrh */
233984bfaa4Sdrh static int autoinstall_test_funcs(
234984bfaa4Sdrh   void * clientData,
235984bfaa4Sdrh   Tcl_Interp *interp,
236984bfaa4Sdrh   int objc,
237984bfaa4Sdrh   Tcl_Obj *CONST objv[]
238984bfaa4Sdrh ){
239984bfaa4Sdrh   sqlite3_auto_extension((void*)registerTestFunctions);
240984bfaa4Sdrh   return TCL_OK;
241984bfaa4Sdrh }
242984bfaa4Sdrh 
243984bfaa4Sdrh 
244984bfaa4Sdrh 
245984bfaa4Sdrh /*
246984bfaa4Sdrh ** Register commands with the TCL interpreter.
247984bfaa4Sdrh */
248984bfaa4Sdrh int Sqlitetest_func_Init(Tcl_Interp *interp){
249984bfaa4Sdrh   static struct {
250984bfaa4Sdrh      char *zName;
251984bfaa4Sdrh      Tcl_ObjCmdProc *xProc;
252984bfaa4Sdrh   } aObjCmd[] = {
253984bfaa4Sdrh      { "autoinstall_test_functions",    autoinstall_test_funcs },
254984bfaa4Sdrh   };
255984bfaa4Sdrh   int i;
256984bfaa4Sdrh   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
257984bfaa4Sdrh     Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
258984bfaa4Sdrh   }
259984bfaa4Sdrh   sqlite3_auto_extension((void*)registerTestFunctions);
260984bfaa4Sdrh   return TCL_OK;
261984bfaa4Sdrh }
262