1 /*
2 ** 2007 March 29
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 ** This file contains obscure tests of the C-interface required
14 ** for completeness. Test code is written in C for these cases
15 ** as there is not much point in binding to Tcl.
16 */
17 #include "sqliteInt.h"
18 #if defined(INCLUDE_SQLITE_TCL_H)
19 #  include "sqlite_tcl.h"
20 #else
21 #  include "tcl.h"
22 #endif
23 #include <stdlib.h>
24 #include <string.h>
25 
26 /*
27 ** c_collation_test
28 */
c_collation_test(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])29 static int SQLITE_TCLAPI c_collation_test(
30   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
31   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
32   int objc,              /* Number of arguments */
33   Tcl_Obj *CONST objv[]  /* Command arguments */
34 ){
35   const char *zErrFunction = "N/A";
36   sqlite3 *db;
37 
38   int rc;
39   if( objc!=1 ){
40     Tcl_WrongNumArgs(interp, 1, objv, "");
41     return TCL_ERROR;
42   }
43 
44   /* Open a database. */
45   rc = sqlite3_open(":memory:", &db);
46   if( rc!=SQLITE_OK ){
47     zErrFunction = "sqlite3_open";
48     goto error_out;
49   }
50 
51   rc = sqlite3_create_collation(db, "collate", 456, 0, 0);
52   if( rc!=SQLITE_MISUSE ){
53     sqlite3_close(db);
54     zErrFunction = "sqlite3_create_collation";
55     goto error_out;
56   }
57 
58   sqlite3_close(db);
59   return TCL_OK;
60 
61 error_out:
62   Tcl_ResetResult(interp);
63   Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0);
64   return TCL_ERROR;
65 }
66 
67 /*
68 ** c_realloc_test
69 */
c_realloc_test(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])70 static int SQLITE_TCLAPI c_realloc_test(
71   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
72   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
73   int objc,              /* Number of arguments */
74   Tcl_Obj *CONST objv[]  /* Command arguments */
75 ){
76   void *p;
77   const char *zErrFunction = "N/A";
78 
79   if( objc!=1 ){
80     Tcl_WrongNumArgs(interp, 1, objv, "");
81     return TCL_ERROR;
82   }
83 
84   p = sqlite3_malloc(5);
85   if( !p ){
86     zErrFunction = "sqlite3_malloc";
87     goto error_out;
88   }
89 
90   /* Test that realloc()ing a block of memory to a negative size is
91   ** the same as free()ing that memory.
92   */
93   p = sqlite3_realloc(p, -1);
94   if( p ){
95     zErrFunction = "sqlite3_realloc";
96     goto error_out;
97   }
98 
99   return TCL_OK;
100 
101 error_out:
102   Tcl_ResetResult(interp);
103   Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0);
104   return TCL_ERROR;
105 }
106 
107 
108 /*
109 ** c_misuse_test
110 */
c_misuse_test(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])111 static int SQLITE_TCLAPI c_misuse_test(
112   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
113   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
114   int objc,              /* Number of arguments */
115   Tcl_Obj *CONST objv[]  /* Command arguments */
116 ){
117   const char *zErrFunction = "N/A";
118   sqlite3 *db = 0;
119   sqlite3_stmt *pStmt;
120   int rc;
121 
122   if( objc!=1 ){
123     Tcl_WrongNumArgs(interp, 1, objv, "");
124     return TCL_ERROR;
125   }
126 
127   /* Open a database. Then close it again. We need to do this so that
128   ** we have a "closed database handle" to pass to various API functions.
129   */
130   rc = sqlite3_open(":memory:", &db);
131   if( rc!=SQLITE_OK ){
132     zErrFunction = "sqlite3_open";
133     goto error_out;
134   }
135   sqlite3_close(db);
136 
137 
138   rc = sqlite3_errcode(db);
139   if( rc!=SQLITE_MISUSE ){
140     zErrFunction = "sqlite3_errcode";
141     goto error_out;
142   }
143 
144   pStmt = (sqlite3_stmt*)1234;
145   rc = sqlite3_prepare(db, 0, 0, &pStmt, 0);
146   if( rc!=SQLITE_MISUSE ){
147     zErrFunction = "sqlite3_prepare";
148     goto error_out;
149   }
150   assert( pStmt==0 ); /* Verify that pStmt is zeroed even on a MISUSE error */
151 
152   pStmt = (sqlite3_stmt*)1234;
153   rc = sqlite3_prepare_v2(db, 0, 0, &pStmt, 0);
154   if( rc!=SQLITE_MISUSE ){
155     zErrFunction = "sqlite3_prepare_v2";
156     goto error_out;
157   }
158   assert( pStmt==0 );
159 
160 #ifndef SQLITE_OMIT_UTF16
161   pStmt = (sqlite3_stmt*)1234;
162   rc = sqlite3_prepare16(db, 0, 0, &pStmt, 0);
163   if( rc!=SQLITE_MISUSE ){
164     zErrFunction = "sqlite3_prepare16";
165     goto error_out;
166   }
167   assert( pStmt==0 );
168   pStmt = (sqlite3_stmt*)1234;
169   rc = sqlite3_prepare16_v2(db, 0, 0, &pStmt, 0);
170   if( rc!=SQLITE_MISUSE ){
171     zErrFunction = "sqlite3_prepare16_v2";
172     goto error_out;
173   }
174   assert( pStmt==0 );
175 #endif
176 
177   return TCL_OK;
178 
179 error_out:
180   Tcl_ResetResult(interp);
181   Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0);
182   return TCL_ERROR;
183 }
184 
185 /*
186 ** Register commands with the TCL interpreter.
187 */
Sqlitetest9_Init(Tcl_Interp * interp)188 int Sqlitetest9_Init(Tcl_Interp *interp){
189   static struct {
190      char *zName;
191      Tcl_ObjCmdProc *xProc;
192      void *clientData;
193   } aObjCmd[] = {
194      { "c_misuse_test",    c_misuse_test, 0 },
195      { "c_realloc_test",   c_realloc_test, 0 },
196      { "c_collation_test", c_collation_test, 0 },
197   };
198   int i;
199   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
200     Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
201         aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
202   }
203   return TCL_OK;
204 }
205