• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package tests.SQLite;
18 
19 import dalvik.annotation.AndroidOnly;
20 import dalvik.annotation.KnownFailure;
21 import dalvik.annotation.TestLevel;
22 import dalvik.annotation.TestTargetClass;
23 import dalvik.annotation.TestTargetNew;
24 import dalvik.annotation.TestTargets;
25 import tests.support.DatabaseCreator;
26 import tests.support.MockFunction;
27 import tests.support.ThreadPool;
28 import tests.support.resource.Support_Resources;
29 
30 import java.io.File;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.OutputStream;
34 import java.io.UnsupportedEncodingException;
35 import java.net.URL;
36 import java.sql.DatabaseMetaData;
37 import java.sql.ResultSet;
38 import java.sql.SQLException;
39 import java.sql.Statement;
40 
41 import SQLite.Authorizer;
42 import SQLite.Blob;
43 import SQLite.BusyHandler;
44 import SQLite.Callback;
45 import SQLite.Constants;
46 import SQLite.Database;
47 import SQLite.Exception;
48 import SQLite.Function;
49 import SQLite.FunctionContext;
50 import SQLite.ProgressHandler;
51 import SQLite.Stmt;
52 import SQLite.TableResult;
53 import SQLite.Trace;
54 import SQLite.Vm;
55 
56 import java.util.ArrayList;
57 import java.util.Arrays;
58 import java.util.List;
59 import java.util.logging.Logger;
60 
61 @TestTargetClass(Database.class)
62 public class DatabaseTest extends SQLiteTest {
63 
64     /**
65      * The SQLite db file.
66      */
67 //    protected final File dbFile = new File("sqliteTest.db");
68 //
69 //    private final String connectionURL = "jdbc:sqlite:/" + dbFile.getPath();
70 //
71 //    private final String classname = "SQLite.JDBCDriver";
72 //
73 //    private static Connection conn = null;
74 
75     private static ErrorTracker tracker = null;
76 
77     private Statement statement;
78 
79     private Database db = null;
80 
81     private static final int numThreads = 10;
82 
83     private static final int numOfRecords = 30;
84 
setUp()85     public void setUp() throws java.lang.Exception {
86         try {
87             super.setUp();
88             assertNotNull("Could not establish DB connection",conn);
89             tracker = new ErrorTracker();
90 
91             statement = conn.createStatement();
92 
93           //Cleanup tables if necessary
94 
95             DatabaseMetaData meta = conn.getMetaData();
96             assertNotNull(meta);
97             if (meta != null) {
98             ResultSet userTab = meta.getTables(null, null, null, null);
99             while (userTab.next()) {
100             String tableName = userTab.getString("TABLE_NAME");
101                this.statement.execute("drop table "+tableName);
102             }
103             }
104 
105             // Create default test table
106 //            statement = conn.createStatement();
107             statement.execute(DatabaseCreator.CREATE_TABLE_SIMPLE1);
108             statement.close();
109 
110             try {
111             db = new Database();
112             db.open(dbFile.getPath(), 0);
113             db.busy_handler(null);
114             } catch (Exception e) {
115                 System.out.println("2: Error opening File: Dir "+dbFile.getPath()+" Name: "+dbFile.getPath());
116             } catch (java.lang.Exception e) {
117                 System.err.println("Non SQLException "+e.getMessage());
118             }
119         } catch (Exception e) {
120             System.out.println("Database setup fails: "+e.getMessage());
121             e.printStackTrace();
122         }
123 
124     }
125 
tearDown()126     public void tearDown() {
127 
128         try {
129             db.close();
130         }catch (Exception e) {
131             if (! (e.getMessage().equals("database already closed"))) {
132                 System.err.println("Error closing DB "+dbFile.getPath());
133             }
134         }
135 //        conn.close();
136 //        dbFile.delete();
137         tracker.reset();
138         super.tearDown();
139     }
140 
141     /**
142      * @tests Database#Database()
143      */
144     @TestTargetNew(
145         level = TestLevel.COMPLETE,
146         notes = "constructor test",
147         method = "Database",
148         args = {}
149     )
testDatabase()150     public void testDatabase() {
151         // db closed
152         Database db2 = new Database();
153         try {
154             db.close();
155             db2 = new Database();
156             db2.open(dbFile.getPath(), 0);
157             db2.close();
158             db.open(dbFile.getPath(), 0);
159         } catch (Exception e) {
160             fail("Database object could not be created "+e.getMessage());
161             e.printStackTrace();
162         }
163         //db is open
164         try {
165             db2.open(dbFile.getPath(), 0);
166             db2.close();
167         } catch (Exception e) {
168             fail("Second Database object could not be created "+e.getMessage());
169             e.printStackTrace();
170         }
171     }
172 
173     /**
174      * @tests Database#finalize()
175      */
176     @TestTargetNew(
177         level = TestLevel.NOT_FEASIBLE,
178         notes = "method test",
179         method = "finalize",
180         args = {}
181     )
testFinalize()182     public void testFinalize() {
183     }
184 
185     /**
186      * @tests {@link Database#open(String, int)}.
187      */
188     @TestTargetNew(
189         level = TestLevel.COMPLETE,
190         notes = "method test. Test fails.",
191         method = "open",
192         args = {java.lang.String.class, int.class}
193     )
testOpen()194     public void testOpen() {
195         try {
196             db.close();
197             db.open(dbFile.getPath(), 0);
198         } catch (Exception e) {
199             fail("Database object could not be opened: " + e.getMessage());
200             e.printStackTrace();
201         }
202         // open second db while db1 still open
203         Database db2 = new Database();
204         try {
205             db2.open(dbFile.getPath(), 0);
206             db2.open(dbFile.getPath(), 0);
207             db2.close();
208         } catch (Exception e) {
209             fail("Database object could not be opened: " + e.getMessage());
210             e.printStackTrace();
211         }
212         // open non db file
213         File tempDir = Support_Resources.createTempFolder();
214         final String resourceName = "blob.c";
215         try {
216             URL file = Class.forName(this.getClass().getName())
217             .getResource("/blob.c");
218             db2.open(file.getPath(), 0);
219            fail("Should not be able to open non db file");
220         } catch (Exception e) {
221             assertEquals("unknown error in open", e.getMessage());
222         } catch (java.lang.Exception e) {
223             fail("Error in setup " + e.getMessage());
224             e.printStackTrace();
225         }
226 
227     }
228 
229     /**
230      * @tests Database#open_aux_file(String)
231      */
232     @TestTargetNew(
233         level = TestLevel.SUFFICIENT,
234         notes = "not supported",
235         method = "open_aux_file",
236         args = {java.lang.String.class}
237     )
testOpen_aux_file()238     public void testOpen_aux_file() {
239         File temp = null;
240         try {
241             db.open_aux_file("");
242             fail("open should fail");
243         } catch (Exception e) {
244             assertEquals("unsupported", e.getMessage());
245         }
246 
247      /*
248         try {
249             temp = File.createTempFile("openAuxMethod", ".db");
250             db.open_aux_file("");
251             db.exec("create table AUX_TABLE", null);
252             db.close();
253         } catch (Exception e) {
254             temp.delete();
255             fail("Error handling temporary file "+e.getMessage());
256             e.printStackTrace();
257         } catch (IOException e) {
258             temp.delete();
259             fail("Could not create temporary File");
260             e.printStackTrace();
261         }
262         try {
263             db.open(dbFile.getPath(),0);
264             db.exec("select * from AUX_TABLE", null);
265             fail("Statement should fail");
266         } catch (Exception e) {
267             // TODO Auto-generated catch block
268             e.printStackTrace();
269         }
270 
271         temp.delete();
272         */
273     }
274 
275     /**
276      * @tests Database#close()
277      */
278     @TestTargetNew(
279         level = TestLevel.COMPLETE,
280         notes = "method test",
281         method = "close",
282         args = {}
283     )
testClose()284     public void testClose() {
285         try {
286             db.close();
287             db.get_table("test");
288         } catch (Exception e) {
289             assertTrue(e.getMessage().equals("database already closed"));
290             try {
291                 db.open(dbFile.getPath(), 0);
292             } catch (Exception e1) {
293                 fail("Database object could not be reopened after 'close': "
294                         + e.getMessage());
295                 e1.printStackTrace();
296             }
297         }
298 
299         try {
300             db.close();
301             db.close();
302         } catch (Exception e) {
303             assertTrue(e.getMessage().equals("database already closed"));
304             try {
305                 db.open(dbFile.getPath(), 0);
306             } catch (Exception e1) {
307                 fail("Database object could not be reopened after 'close': "
308                         + e.getMessage());
309                 e1.printStackTrace();
310             }
311         }
312     }
313 
314     /**
315      * @tests Database#exec(String, Callback)
316      */
317     @TestTargetNew(
318         level = TestLevel.COMPLETE,
319         notes = "method test",
320         method = "exec",
321         args = {java.lang.String.class, Callback.class}
322     )
testExecStringCallback()323     public void testExecStringCallback() {
324         TableResult res = new TableResult();
325         try {
326             db.exec("insert into " + DatabaseCreator.SIMPLE_TABLE1
327                     + " VALUES(1, 10, 20)", null);
328             db.exec("select * from " + DatabaseCreator.SIMPLE_TABLE1, res);
329             db
330                     .exec("delete from " + DatabaseCreator.SIMPLE_TABLE1
331                             + " where 1", null);
332         } catch (Exception e) {
333             fail("Database error");
334             e.printStackTrace();
335         }
336         String row[] = (String[]) res.rows.elementAt(0);
337         assertEquals(Integer.parseInt(row[0]), 1);
338         assertEquals(Integer.parseInt(row[1]), 10);
339         assertEquals(Integer.parseInt(row[2]), 20);
340     }
341 
342     /**
343      * @tests Database#exec(String, Callback, String[])
344      */
345     @TestTargetNew(
346         level = TestLevel.COMPLETE,
347         notes = "method test",
348         method = "exec",
349         args = {java.lang.String.class, Callback.class, java.lang.String[].class}
350     )
testExecStringCallbackStringArray()351     public void testExecStringCallbackStringArray() {
352         TableResult res = new TableResult();
353         String args[] = new String[1];
354         args[0] = "table";
355         try {
356             db.exec("select name from sqlite_master where type = '%q';", res,
357                     args);
358             String[] s = (String[]) res.rows.elementAt(0);
359             assertEquals(s[0], DatabaseCreator.SIMPLE_TABLE1);
360         } catch (Exception e) {
361             fail("DB Error occurred");
362             e.printStackTrace();
363         }
364 
365         try {
366             db.exec("select name from sqlite_master where type = ", res, args);
367             fail("Testmethod should fail");
368         } catch (Exception e) {
369             // Ok
370         }
371     }
372 
373     /**
374      * @tests {@link Database#last_insert_rowid()}
375      */
376     @TestTargetNew(
377         level = TestLevel.COMPLETE,
378         notes = "method test",
379         method = "last_insert_rowid",
380         args = {}
381     )
testLast_insert_rowid()382     public void testLast_insert_rowid() {
383         assertEquals(0, db.last_insert_rowid());
384         try {
385             db
386                     .exec(
387                             "create table TEST5(id integer, firstname text, lastname text);",
388                             null);
389             db.exec("insert into TEST5 values (1,'James','Bond');", null);
390             db.exec("insert into TEST5 values (2,'Fiona','Apple');", null);
391         } catch (Exception e) {
392             fail("Error in test setup: " + e.getMessage());
393             e.printStackTrace();
394         }
395         assertEquals(2, db.last_insert_rowid());
396         assertEquals(db.last_insert_rowid(), db.last_insert_rowid());
397 
398         try {
399             db.exec("drop table TEST5;", null);
400         } catch (Exception e) {
401             fail("Error in test setup: " + e.getMessage());
402             e.printStackTrace();
403         }
404         assertEquals(2, db.last_insert_rowid());
405     }
406 
407     /**
408      * @throws Exception
409      * @tests {@link Database#interrupt()}
410      */
411     @TestTargetNew(
412         level = TestLevel.COMPLETE,
413         notes = "",
414         method = "interrupt",
415         args = {}
416     )
417     @KnownFailure("Reason for failure unknown: Database should be locked. " +
418                    "Specification of interrupt is scarce.")
testInterrupt()419     public void testInterrupt() throws Exception {
420         ThreadPool threadPool = new ThreadPool(numThreads);
421 
422         // initialization
423         ResultSet userTabs;
424         try {
425             userTabs = conn.getMetaData().getTables(null, null, null, null);
426             while (userTabs.next()) {
427                 String tableName = userTabs.getString("TABLE_NAME");
428                 if (tableName.equals(DatabaseCreator.TEST_TABLE1)) {
429                     statement.execute(DatabaseCreator.DROP_TABLE1);
430                 }
431             }
432             db.exec(DatabaseCreator.CREATE_TABLE3, null);
433             db.exec(DatabaseCreator.CREATE_TABLE1, null);
434         } catch (SQLException e1) {
435             fail("Error initializing test " + e1.toString());
436             e1.printStackTrace();
437         } catch (Exception e) {
438             fail("Error initializing test " + e.getMessage());
439             e.printStackTrace();
440         }
441 
442         int id1 = numOfRecords - 3;
443         threadPool.runTask(createTask1(id1, dbFile.getPath(), tracker));
444         // should not be able to do any other insertions since task 1 holds lock
445         int id2 = numOfRecords + 3;
446         threadPool
447                 .runTask(createTask2Interrupt(id2, dbFile.getPath(), tracker));
448 
449         threadPool.join();
450 
451         List<String> errors = tracker.getErrors();
452         System.out.println("Last error: " + db.error_message());
453         if (errors.size() > 0) {
454             assertEquals(errors.get(0), db
455                     .error_string(Constants.SQLITE_LOCKED));
456             for (String s : errors) {
457                 Logger.global.info("INTERRUPT Error: " + s);
458             }
459 
460         } else {
461             fail("Should have one exception: database should be locked.");
462         }
463 
464         // reset
465 
466         db
467                 .exec(
468                         "delete from " + DatabaseCreator.TEST_TABLE1
469                                 + " where 1", null);
470         db
471                 .exec(
472                         "delete from " + DatabaseCreator.TEST_TABLE3
473                                 + " where 1", null);
474 
475     }
476 
477     /**
478      * @tests {@link Database#changes()}
479      */
480     @TestTargetNew(
481         level = TestLevel.COMPLETE,
482         notes = "test fails",
483         method = "changes",
484         args = {}
485     )
486     @KnownFailure("Returns wrong number for updates: returns value > 1 for select.")
testChanges()487     public void testChanges() {
488         TableResult res = new TableResult();
489         try {
490             assertTrue(db.changes() == 0);
491             db.exec("INSERT INTO " + DatabaseCreator.SIMPLE_TABLE1
492                     + " VALUES(2, 5, 7);", null);
493             int rows = (int) db.changes();
494             assertEquals(1,db.changes());
495             db.exec("update " + DatabaseCreator.SIMPLE_TABLE1
496                     + " set speed = 7, size= 5 where id = 2;", null);
497             assertEquals(1,db.changes());
498             db.exec("select * from " + DatabaseCreator.SIMPLE_TABLE1, res);
499             assertEquals(0,db.changes());
500             db.exec("INSERT INTO " + DatabaseCreator.SIMPLE_TABLE1
501                     + " VALUES(8, 5, 7);", null);
502             db.exec("Update "+DatabaseCreator.SIMPLE_TABLE1+" set speed = 10;",null);
503            assertTrue(db.changes() > 2);
504         } catch (Exception e) {
505             fail("Could not get changes: " + e.getMessage());
506             e.printStackTrace();
507         }
508     }
509 
510     /**
511      * @throws SQLException
512      * @throws Exception
513      * @tests {@link Database#busy_handler(BusyHandler)}
514      */
515     @TestTargets({
516     @TestTargetNew(
517         level = TestLevel.NOT_FEASIBLE,
518         notes = "method test fails once in a while. Cannot be sure that exception is thrown every time.",
519         method = "busy_handler",
520         args = {BusyHandler.class}
521     ),
522     @TestTargetNew(
523             level = TestLevel.NOT_FEASIBLE,
524             notes = "method test fails once in a while. Cannot be sure that exception is thrown every time.",
525             method = "busy",
526             clazz = BusyHandler.class,
527             args = {java.lang.String.class, int.class}
528         )
529     })
530     @KnownFailure("method test fails once in a while. "+
531             "Cannot be sure that exception is thrown in every test execution.")
testBusy_handler()532     public void testBusy_handler() throws SQLException, Exception {
533         TestBusyHandler bh = new TestBusyHandler();
534         db.busy_handler(bh);
535         int counter = 0;
536         ThreadPool threadPool = new ThreadPool(numThreads);
537 
538         // initialization
539         ResultSet userTabs;
540         try {
541             userTabs = conn.getMetaData().getTables(null, null, null, null);
542             while (userTabs.next()) {
543                 String tableName = userTabs.getString("TABLE_NAME");
544                 if (tableName.equals(DatabaseCreator.TEST_TABLE1)) {
545                     statement.execute(DatabaseCreator.DROP_TABLE1);
546                 }
547             }
548             db.exec(DatabaseCreator.CREATE_TABLE3, null);
549             db.exec(DatabaseCreator.CREATE_TABLE1, null);
550         } catch (SQLException e1) {
551             fail("Error initializing test " + e1.toString());
552             e1.printStackTrace();
553         } catch (Exception e) {
554             fail("Error initializing test " + e.getMessage());
555             e.printStackTrace();
556         }
557 
558 
559 //        try {
560 //            DatabaseCreator.fillTestTable1(conn, numOfRecords);
561             // set to fail immediately if table is locked.
562 //            db.busy_handler(bh);
563 //            db.busy_timeout(0);
564         try {
565             conn.setAutoCommit(false);
566             int id1 = numOfRecords - 3;
567             threadPool.runTask(createTask1(id1, dbFile.getPath(), tracker));
568             int id2 = numOfRecords + 3;
569             threadPool.runTask(createTask2(id2, dbFile.getPath(), tracker));
570             int oldID = 5;
571             int newID = 100;
572             threadPool.runTask(createTask3(oldID, dbFile.getPath(), newID,
573                     tracker));
574 
575             threadPool.join();
576 
577             List<String> errors = tracker.getErrors();
578             if (errors.size() > 0) {
579 //                 assertEquals(errors.get(0),
580 //                 db.error_string(Constants.SQLITE_LOCKED));
581                 for (String s: errors) {
582                   System.out.println("Round 2 Error: "+s);
583               }
584             } else {
585                 fail("No error happened");
586             }
587 
588             // reset
589 
590 
591             db.exec("delete from " + DatabaseCreator.TEST_TABLE1 + " where 1",
592                     null);
593             db.exec("delete from " + DatabaseCreator.TEST_TABLE3 + " where 1",
594                             null);
595 //
596 //            // increase timeout for retry
597 //            db.busy_timeout(1000);
598 //            db.busy_handler(bh);
599 //            tracker.reset();
600 
601 //            threadPool = new ThreadPool(numThreads);
602 //
603 //            threadPool.runTask(createTask1(id1, dbFile.getPath(), tracker));
604 //            threadPool.runTask(createTask2(id2, dbFile.getPath(), tracker));
605 //
606 //            threadPool.join();
607 //
608 //            errors = tracker.getErrors();
609 //            if (errors.size() > 0) {
610 //                // assertEquals(errors.get(0),
611 //                // db.error_string(Constants.SQLITE_LOCKED));
612 //                for (String s: errors) {
613 //                    System.out.println("Round 2 Error"+s);
614 //                }
615 //            } else {
616 //                // ok
617 //                System.out.println("BUSY: No Error!");
618 //            }
619 //
620 //
621         } catch (Exception e) {
622             fail("Error in test setup " + e.getMessage());
623             try {
624                 db.get_table("select * from " + DatabaseCreator.TEST_TABLE1,
625                         null).toString();
626             } catch (Exception e1) {
627 
628                 e1.printStackTrace();
629             }
630             e.printStackTrace();
631 //             } catch (SQLException e2) {
632 //             System.out.println("Error in test setup "+e2.toString());
633 //             try {
634 //             db.get_table("select * from "+DatabaseCreator.TEST_TABLE1,null).
635 //             toString();
636 //             } catch (Exception e1) {
637 //             e2.printStackTrace();
638 //             }
639         } finally {
640             conn.setAutoCommit(true);
641             db.exec(DatabaseCreator.DROP_TABLE1, null);
642             db.exec(DatabaseCreator.DROP_TABLE3, null);
643         }
644     }
645 
646     /**
647      * @throws Exception
648      * @throws SQLException
649      * @tests {@link Database#busy_timeout(int)}
650      */
651     @TestTargetNew(
652         level = TestLevel.NOT_FEASIBLE,
653         notes = "test fails. Cannot be sure that exception is thrown every time.",
654         method = "busy_timeout",
655         args = {int.class}
656     )
657     @KnownFailure("Database does not lock values")
testBusy_timeout()658     public void testBusy_timeout() throws Exception, SQLException {
659         int counter = 0;
660         ThreadPool threadPool = new ThreadPool(numThreads);
661 
662         // initialization
663         ResultSet userTabs;
664         try {
665             userTabs = conn.getMetaData().getTables(null, null, null, null);
666             while (userTabs.next()) {
667                 String tableName = userTabs.getString("TABLE_NAME");
668                 if (tableName.equals(DatabaseCreator.TEST_TABLE1)) {
669                     statement.execute(DatabaseCreator.DROP_TABLE1);
670                 }
671             }
672             db.exec(DatabaseCreator.CREATE_TABLE3, null);
673             db.exec(DatabaseCreator.CREATE_TABLE1, null);
674         } catch (SQLException e1) {
675             fail("Error initializing test " + e1.toString());
676             e1.printStackTrace();
677         } catch (Exception e) {
678             fail("Error initializing test " + e.getMessage());
679             e.printStackTrace();
680         }
681 
682 
683         // test run
684         try {
685             conn.setAutoCommit(false);
686 
687 //            DatabaseCreator.fillTestTable1(conn, numOfRecords);
688             // set to fail immediately if table is locked.
689             db.busy_handler(null);
690             db.busy_timeout(0);
691             int id1 = numOfRecords - 3;
692 
693             threadPool.runTask(createTask2(id1, dbFile.getPath(), tracker));
694             int id2 = numOfRecords + 3;
695             threadPool.runTask(createTask1(id2, dbFile.getPath(), tracker));
696             int oldID = 5;
697             int newID = 100;
698             threadPool.runTask(createTask3(oldID, dbFile.getPath(), newID,
699                     tracker));
700 
701             threadPool.join();
702 
703             List<String> errors = tracker.getErrors();
704             assertTrue("No error occurred on DB but should have",errors.size() > 0);
705 
706             assertEquals(errors.get(0),
707             db.error_string(Constants.SQLITE_LOCKED));
708             assertEquals(errors.get(0), "database is locked");
709 
710             // reset
711 
712             db.exec("delete from " + DatabaseCreator.TEST_TABLE1 + " where 1",
713                     null);
714             db.exec("delete from " + DatabaseCreator.TEST_TABLE3 + " where 1",
715                             null);
716 
717             // increase timeout for retry
718             db.busy_timeout(10000);
719             db.busy_handler(null);
720             tracker.reset();
721             threadPool = new ThreadPool(numThreads);
722 
723             threadPool.runTask(createTask1(id1, dbFile.getPath(), tracker));
724             threadPool.runTask(createTask2(id2, dbFile.getPath(), tracker));
725 
726             threadPool.join();
727 
728             errors = tracker.getErrors();
729             if (errors.size() > 0) {
730                 fail("busy timeout should prevent from lock exception!");
731                 for (String s: errors) {
732                     System.out.println("Round 2 Error"+s);
733                 }
734             } else {
735                 // ok
736             }
737 
738 
739         } catch (Exception e) {
740             fail("Error in test setup " + e.getMessage());
741             try {
742                 db.get_table("select * from " + DatabaseCreator.TEST_TABLE1,
743                         null).toString();
744             } catch (Exception e1) {
745 
746                 e1.printStackTrace();
747             }
748             e.printStackTrace();
749         } finally {
750             conn.setAutoCommit(true);
751             // cleanup
752             db.exec(DatabaseCreator.DROP_TABLE1, null);
753             db.exec(DatabaseCreator.DROP_TABLE3, null);
754         }
755     }
756 
757     /**
758      * @tests {@link Database#get_table(String)}
759      */
760     @TestTargetNew(
761         level = TestLevel.COMPLETE,
762         notes = "method test",
763         method = "get_table",
764         args = {java.lang.String.class}
765     )
testGet_tableString()766     public void testGet_tableString() {
767         TableResult emptyTable = new TableResult();
768         try {
769             //select from empty table
770             TableResult res = db.get_table("select * from "
771                     + DatabaseCreator.SIMPLE_TABLE1);
772             assertEquals(res.toString(), emptyTable.toString());
773             //fill table-> t
774 //            DatabaseCreator.fillSimpleTable1(conn);
775 //            res = db.get_table("select * from "
776 //                    + DatabaseCreator.SIMPLE_TABLE1);
777 //            assertFalse(emptyTable.toString().equals(res.toString()));
778 
779             try {
780                 db.exec("insert into " + DatabaseCreator.SIMPLE_TABLE1
781                         + " VALUES(1, 10, 20)", null);
782                 res = db.get_table("select * from " + DatabaseCreator.SIMPLE_TABLE1);
783                 db
784                         .exec("delete from " + DatabaseCreator.SIMPLE_TABLE1
785                                 + " where 1", null);
786             } catch (Exception e) {
787                 fail("Database error");
788                 e.printStackTrace();
789             }
790             String row[] = (String[]) res.rows.elementAt(0);
791             assertEquals(Integer.parseInt(row[0]), 1);
792             assertEquals(Integer.parseInt(row[1]), 10);
793             assertEquals(Integer.parseInt(row[2]), 20);
794         } catch (Exception e) {
795             fail("Error getting table " + e.getMessage());
796             e.printStackTrace();
797 //        } catch (SQLException e) {
798 //            fail("Error initialising table " + e.getMessage());
799 //            e.printStackTrace();
800         }
801     }
802 
803     /**
804      * @tests {@link Database#get_table(String, String[])}
805      */
806     @TestTargetNew(
807         level = TestLevel.COMPLETE,
808         notes = "method test",
809         method = "get_table",
810         args = {java.lang.String.class, java.lang.String[].class}
811     )
testGet_tableStringStringArray()812     public void testGet_tableStringStringArray() {
813         String args[] = new String[1];
814         args[0] = "table";
815         String argsFail[] = new String[1];
816         try {
817             TableResult res = db.get_table(
818                     "select name from sqlite_master where type = ", argsFail);
819             fail("Testmethod should fail");
820         } catch (Exception e) {
821             try {
822                 TableResult res = db.get_table(
823                         "select name from sqlite_master where type = '%q'",
824                         args);
825                 String[] s = (String[]) res.rows.elementAt(0);
826                 assertEquals(s[0], DatabaseCreator.SIMPLE_TABLE1);
827             } catch (Exception e2) {
828                 fail("Testmethod failed: " + e2.getMessage());
829                 e.printStackTrace();
830             }
831         }
832 
833     }
834 
835     /**
836      * @tests {@link Database#get_table(String, String[], TableResult)}
837      */
838     @TestTargets({
839         @TestTargetNew(
840             level = TestLevel.COMPLETE,
841             notes = "method test",
842             method = "get_table",
843             args = {java.lang.String.class, java.lang.String[].class, TableResult.class}
844         ),
845         @TestTargetNew(
846                 level = TestLevel.COMPLETE,
847                 notes = "method test",
848                 method = "toString",
849                 clazz = TableResult.class,
850                 args = {}
851             ),
852        @TestTargetNew(
853                     level = TestLevel.COMPLETE,
854                     notes = "method test",
855                     method = "types",
856                     clazz = TableResult.class,
857                     args = {String[].class}
858             ),
859        @TestTargetNew(
860                 level = TestLevel.COMPLETE,
861                 notes = "method test",
862                 method = "TableResult",
863                 clazz = TableResult.class,
864                 args = {}
865            ),
866        @TestTargetNew(
867                level = TestLevel.NOT_NECESSARY,
868                notes = "method test",
869                method = "columns",
870                clazz = TableResult.class,
871                args = {String[].class}
872           ),
873       @TestTargetNew(
874               level = TestLevel.NOT_NECESSARY,
875               notes = "method test",
876               method = "newrow",
877               clazz = TableResult.class,
878               args = {String[].class}
879          ),
880      @TestTargetNew(
881          level = TestLevel.NOT_NECESSARY,
882          notes = "method test",
883          method = "clear",
884          clazz = TableResult.class,
885          args = {}
886         )
887 
888     })
testGet_tableStringStringArrayTableResult()889     public void testGet_tableStringStringArrayTableResult() {
890         String args[] = new String[1];
891         String argsFail[] = new String[1];
892         TableResult res = new TableResult();
893         TableResult defaultTableRes = new TableResult();
894         args[0] = "table";
895 
896         try {
897             db.get_table("select name from sqlite_master where type = '%q'",
898                     argsFail, res);
899             assertEquals(defaultTableRes.toString(), res.toString());
900         } catch (Exception e) {
901             try {
902                 db.get_table(
903                         "select name from sqlite_master where type = '%q'",
904                         args, res);
905                 String[] s = (String[]) res.rows.elementAt(0);
906                 assertEquals(s[0], DatabaseCreator.SIMPLE_TABLE1);
907                 String[] types = res.types;
908                 System.out
909                         .println("DatabaseTest.testGet_tableStringStringArrayTableResult() "+types.toString());
910             } catch (Exception e2) {
911                 fail("Testmethod failed: " + e2.getMessage());
912                 e.printStackTrace();
913             }
914         }
915     }
916 
917 
918     /**
919      * @tests {@link Database#complete(String)}
920      */
921     @TestTargetNew(
922         level = TestLevel.COMPLETE,
923         notes = "method test",
924         method = "complete",
925         args = {java.lang.String.class}
926     )
testComplete()927     public void testComplete() {
928         assertFalse(db.complete("create"));
929         assertTrue(db.complete("create table TEST (res double);"));
930     }
931 
932     /**
933      * @tests {@link Database#version()}
934      */
935     @TestTargetNew(
936         level = TestLevel.COMPLETE,
937         notes = "method test",
938         method = "version",
939         args = {}
940     )
testVersion()941     public void testVersion() {
942         String version = db.version();
943         if (version != null) {
944         assertTrue(Integer.parseInt(db.version().substring(0,1)) > 0);
945         assertEquals(db.version(), db.version());
946         } else {
947             fail("DB version info missing");
948         }
949 
950     }
951 
952     /**
953      * @tests {@link Database#dbversion()}
954      */
955     @TestTargetNew(
956         level = TestLevel.COMPLETE,
957         notes = "method test",
958         method = "dbversion",
959         args = {}
960     )
testDbversion()961     public void testDbversion() {
962         String verNo = "";
963         try {
964             verNo = db.dbversion();
965             db.close();
966             assertEquals(db.dbversion(),"unknown");
967             db.open(dbFile.getPath(), 0);
968             assertEquals(verNo,db.dbversion());
969         } catch (Exception e) {
970             try {
971                 db.open(dbFile.getPath(), 0);
972             } catch (Exception e1) {
973                 fail("error in db setup "+e.getMessage());
974                 e.printStackTrace();
975             }
976             fail("error in db setup "+e.getMessage());
977             e.printStackTrace();
978         }
979 
980         assertTrue(Integer.parseInt(verNo.substring(0, 1))>= 3 );
981 
982     }
983 
984     /**
985      * @tests {@link Database#create_function(String, int, Function)}
986      */
987     @TestTargets({
988     @TestTargetNew(
989         level = TestLevel.COMPLETE,
990         notes = "method test",
991         method = "create_function",
992         args = {java.lang.String.class, int.class, Function.class}
993     ),
994     @TestTargetNew(
995         level = TestLevel.COMPLETE,
996         notes = "method test",
997         method = "create_function",
998         args = {java.lang.String.class, int.class, Function.class}
999         )
1000     })
testCreate_function()1001     public void testCreate_function() {
1002         try {
1003             double input = 1.0;
1004             db.exec("create table TEST (res double)", null);
1005             db.exec("insert into TEST values (" + Double.toString(input) + ")",
1006                     null);
1007             TableResult res = new TableResult();
1008             Function sinFunc = (Function) new SinFunc();
1009             db.create_function("sin", 1, sinFunc);
1010             db.exec("select sin(res) from TEST WHERE res = "
1011                     + Double.toString(input), res);
1012             String row[] = (String[]) res.rows.elementAt(0);
1013             String val = row[0];
1014             double sinusVal = Double.parseDouble(val);
1015             double funcVal = Math.sin(input);
1016 
1017             assertTrue(Math.round(funcVal) == Math.round(sinusVal));
1018         } catch (Exception e) {
1019             fail("Error happened creating function:" + e.getMessage());
1020             e.printStackTrace();
1021         }
1022     }
1023 
1024     /**
1025      * @tests {@link Database#create_aggregate(String, int, Function)}
1026      */
1027     @TestTargets({
1028 
1029     @TestTargetNew(
1030         level = TestLevel.COMPLETE,
1031         notes = "method test",
1032         method = "create_aggregate",
1033         args = {java.lang.String.class, int.class, Function.class}
1034     ),
1035     @TestTargetNew(
1036         level = TestLevel.COMPLETE,
1037         notes = "method test",
1038         method = "step",
1039         clazz = Function.class,
1040         args = {FunctionContext.class, String[].class}
1041             ),
1042     @TestTargetNew(
1043         level = TestLevel.COMPLETE,
1044         notes = "method test",
1045         method = "last_step",
1046         clazz = Function.class,
1047         args = {FunctionContext.class}
1048                 ),
1049     @TestTargetNew(
1050         level = TestLevel.COMPLETE,
1051         notes = "method test",
1052         method = "function",
1053         clazz = Function.class,
1054         args = {FunctionContext.class, String[].class}
1055                     )
1056     })
1057     @KnownFailure("Aggregation function not called")
testCreate_aggregate()1058     public void testCreate_aggregate() {
1059         TestTrace t = new TestTrace();
1060 
1061         MockFunction aggFunction = new MockFunction();
1062 
1063         try {
1064             db
1065                     .exec(
1066                             "create table TEST(id integer, firstname text, lastname text)",
1067                             null);
1068             db.exec("insert into TEST values(3, 'James', 'Bond'); ", null);
1069             db.exec("insert into TEST values(4, 'Fiona', 'Apple'); ", null);
1070             db.trace((Trace) t);
1071             db.create_aggregate("myaggfunc", 1, aggFunction);
1072             db.function_type("myaggfunc", Constants.SQLITE3_TEXT);
1073             db.exec("PRAGMA show_datatypes = on", null);
1074 
1075             assertFalse(aggFunction.functionCalled);
1076             assertFalse(aggFunction.stepCalled);
1077             assertFalse(aggFunction.lastStepCalled);
1078             db.exec("select myaggfunc(TEST.firstname) from TEST", t);
1079             assertTrue(aggFunction.stepCalled);
1080             assertTrue(aggFunction.lastStepCalled);
1081             assertTrue(aggFunction.functionCalled);
1082 
1083             assertEquals("James Fiona ",aggFunction.getAggValue());
1084             db.exec("drop table TEST", null);
1085         } catch (Exception e) {
1086             System.out.println(t.getTrace());
1087             fail("Error in test setup: " + e.getMessage());
1088             e.printStackTrace();
1089         }
1090 
1091         try {
1092             db.create_aggregate("myaggfunc", 0, null);
1093         } catch (Throwable e) {
1094             assertEquals("null SQLite.Function not allowed",e.getMessage());
1095         }
1096 
1097           try {
1098             db.create_aggregate("myaggfunc", 0, aggFunction);
1099         } catch (Throwable e) {
1100             assertEquals("wrong number of arguments to function myaggfunc()",e.getMessage());
1101         }
1102 
1103     }
1104 
1105     /**
1106      * @throws Exception
1107      * @tests {@link Database#function_type(String, int)}
1108      * This method does not make sense
1109      */
1110     @TestTargetNew(
1111         level = TestLevel.COMPLETE,
1112         notes = "Method does not make sense: for functions, return type is already set.",
1113         method = "function_type",
1114         args = {java.lang.String.class, int.class}
1115     )
testFunction_type()1116     public void testFunction_type() throws Exception {
1117 
1118         double input = 1.0;
1119         TableResult res = new TableResult();
1120         Function sinFunc = (Function) new SinFunc();
1121 
1122         db.exec("PRAGMA show_datatypes = on", null);
1123         db.exec("create table TEST (res double)", null);
1124         db.exec("insert into TEST values (" + Double.toString(input) + ")",
1125                 null);
1126 
1127         db.create_function("sin", 1, sinFunc);
1128         db.function_type("sin", Constants.SQLITE_FLOAT);
1129         res = db.get_table("select sin(res) from TEST WHERE res = "
1130                 + Double.toString(input));
1131 
1132         String row[] = (String[]) res.rows.elementAt(0);
1133         String val = row[0];
1134         assertTrue("double".equalsIgnoreCase(res.types[0]));
1135         assertSame(Math.round(Math.sin(input)), Math.round(Double.parseDouble(val)));
1136 
1137         // function determines return type: test that Double type is returned.
1138         db.function_type("sin", Constants.SQLITE_BLOB);
1139         Stmt s = db.prepare("select sin(res) from TEST WHERE res = ?");
1140         s.bind(1,input);
1141         s.step();
1142 
1143         res = db.get_table("select sin(res) from TEST WHERE res = "
1144                 + Double.toString(input));
1145         assertTrue("double".equalsIgnoreCase(res.types[0]));
1146         row = (String[]) res.rows.elementAt(0);
1147         val = row[0];
1148         assertSame(Math.round(Math.sin(input)), Math.round(Double.parseDouble(val)));
1149 
1150 
1151 
1152 
1153     }
1154 
1155     /**
1156      * @tests {@link Database#last_error()}
1157      */
1158     @TestTargetNew(
1159         level = TestLevel.COMPLETE,
1160         notes = "method test",
1161         method = "last_error",
1162         args = {}
1163     )
testLast_error()1164     public void testLast_error() {
1165         assertEquals(db.last_error(), Constants.SQLITE_OK);
1166         try {
1167             db.exec("create table TEST (res double)",null);
1168             db.exec("create table TEST (res double)",null);
1169             fail("Error should have happened");
1170         } catch (Exception e) {
1171             assertEquals(db.last_error(),db.last_error());
1172             assertEquals(db.last_error(),Constants.SQLITE_ERROR);
1173         }
1174 
1175     }
1176 
1177     /**
1178      * @tests {@link Database#set_last_error(int)}
1179      */
1180     @TestTargetNew(
1181         level = TestLevel.SUFFICIENT,
1182         notes = "don't now which other errors may occur from black-box approach.",
1183         method = "set_last_error",
1184         args = {int.class}
1185     )
testSet_last_error()1186     public void testSet_last_error() {
1187        assertEquals(db.last_error(), Constants.SQLITE_OK);
1188 
1189        try {
1190            db.exec("sel from test;", null);
1191        } catch (Exception e) {
1192            assertEquals(Constants.SQLITE_ERROR,db.last_error());
1193        }
1194     }
1195 
1196     /**
1197      * @tests {@link Database#error_message()}
1198      */
1199     @TestTargetNew(
1200         level = TestLevel.COMPLETE,
1201         notes = "method test",
1202         method = "error_message",
1203         args = {}
1204     )
testError_message()1205     public void testError_message() {
1206         String statement = "create table TEST (res double)";
1207         try {
1208             db.exec(statement,null);
1209             db.exec(statement,null);
1210             fail("DB Error expected");
1211         } catch (Exception e) {
1212             String dbError = db.error_message();
1213             assertTrue(e.getMessage().equals(dbError));
1214 
1215         }
1216     }
1217 
1218     /**
1219      * @tests {@link Database#error_string(int)}
1220      */
1221 
1222     @TestTargetNew(
1223         level = TestLevel.COMPLETE,
1224         notes = "not supported",
1225         method = "error_string",
1226         args = {int.class}
1227     )
testError_string()1228     public void testError_string() {
1229         TestTrace t = new TestTrace();
1230         assertEquals(db.last_error(), Constants.SQLITE_OK);
1231         String errorString = db.error_string(Constants.SQLITE_ERROR);
1232         try {
1233             db.trace((Trace) t);
1234             db.exec("create table TEST (res double)", t);
1235             db.exec("create table TEST (res double)", t);
1236         } catch (Exception e) {
1237             assertEquals(db.last_error(), Constants.SQLITE_ERROR);
1238             if (db.is3()) {
1239                 assertEquals("Unsupported Method (sqlite 3): error_string", db
1240                         .error_string(db.last_error()), errorString);
1241             }
1242         }
1243     }
1244 
1245     /**
1246      * @throws UnsupportedEncodingException
1247      * @tests {@link Database#set_encoding(String)}
1248      * Method unsupported? -> tests fail
1249      */
1250     @TestTargetNew(
1251         level = TestLevel.COMPLETE,
1252         notes = "method test fails.",
1253         method = "set_encoding",
1254         args = {java.lang.String.class}
1255     )
1256     @KnownFailure("ASCII encoding does not work: a UTF encoded val is returned. Spec is not sufficient. "
1257             + "Might be that test impl is wrong or String constructor for the ASCII encoding.")
testSet_encoding()1258     public void testSet_encoding() throws UnsupportedEncodingException {
1259         String input = "\u00bfMa\u00f1ana\u003f"; // ?Manana?
1260         TableResult res = new TableResult();
1261         String refOutput = null;
1262         Stmt stat = null;
1263 
1264         // DB setup
1265         try {
1266             db.exec("create table encodingTest (encoded text DEFAULT NULL);",
1267                     null);
1268             stat = db
1269                     .prepare("insert into encodingTest(encoded) values(:one);");
1270             stat.bind(1, input);
1271             stat.step();
1272             // stat.close();
1273             db.exec("select * from encodingTest;", res);
1274             String[] encInput = (String[]) res.rows.elementAt(0);
1275             String output = encInput[0];
1276             assertEquals(input, output);
1277             // db.exec("delete from encodingTest where 1", null);
1278         } catch (Exception e1) {
1279             fail("Error in test setup: " + e1.getMessage());
1280             e1.printStackTrace();
1281         }
1282 
1283      // tests for different encoding schemes
1284         String[] charsetNames = {"UTF-8", "UTF-16", "UTF-16BE", "UTF-16LE"};
1285         for (int i = 0; i < charsetNames.length; i++) {
1286             try {
1287                 byte[] encInput = input.getBytes(charsetNames[i]);
1288                 db.set_encoding(charsetNames[i]);
1289                 db.exec("select * from encodingTest;", res);
1290                 String[] encOutput = (String[]) res.rows.elementAt(0);
1291                 String inputAsString = new String(encInput,charsetNames[i]);
1292                 assertEquals(inputAsString, encOutput[0]);
1293             } catch (Exception e4) {
1294                 fail("Error setting the encoding." + e4.getMessage());
1295                 e4.printStackTrace();
1296             } catch (UnsupportedEncodingException e2) {
1297                 fail(e2.getMessage());
1298                 e2.printStackTrace();
1299             }
1300         }
1301 
1302         // Default tests
1303         try {
1304             db.set_encoding("UTF-16");
1305             db.exec("select * from encodingTest;", res);
1306             String[] encOutput1 = (String[]) res.rows.elementAt(0);
1307             assertEquals("Got "+encOutput1[0]+" as UTF-16",input,encOutput1[0]);
1308 
1309             db.set_encoding("US-ASCII");
1310             db.exec("select * from encodingTest;", res);
1311             String[] encOutput2 = (String[]) res.rows.elementAt(0);
1312             assertEquals(new String(input.getBytes(),"US-ASCII"),encOutput2[0]);
1313         } catch (Exception e) {
1314             fail("Error setting the encoding." + e.getMessage());
1315             e.printStackTrace();
1316         }
1317 
1318 
1319         // DB teardown
1320         try {
1321             stat.close();
1322             db.exec("delete from encodingTest", null);
1323             // reset encoding
1324         } catch (Exception e3) {
1325             fail("Error in teardown of encoding environment");
1326             e3.printStackTrace();
1327         }
1328 
1329         // Default tests
1330         try {
1331             db.set_encoding("");
1332             fail("invalid input should fail");
1333         } catch (Exception e) {
1334             //ok
1335         }
1336 
1337     }
1338 
1339     /**
1340      * Test fails -> implemented correctly?
1341      * @tests {@link Database#set_authorizer(Authorizer)}
1342      */
1343     @TestTargets({
1344     @TestTargetNew(
1345         level = TestLevel.COMPLETE,
1346         notes = "method test fails.",
1347         method = "set_authorizer",
1348         args = {Authorizer.class}
1349     ),
1350     @TestTargetNew(
1351             level = TestLevel.COMPLETE,
1352             notes = "method test fails.",
1353             method = "authorize",
1354             clazz = Authorizer.class,
1355             args = {int.class, java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class}
1356         )
1357     })
1358     @KnownFailure("Callback never made for authorization. "+
1359             "Results of private table are returned withouth furhter checks.")
testSet_authorizer()1360     public void testSet_authorizer() {
1361 
1362         TableResult resPriv = null;
1363         TableResult resPub = null;
1364         TableResult emptyTable = new TableResult();
1365         String insertPublic = "insert into public_table values(1,2)";
1366         String insertPrivate = "insert into private_table values(1,2)";
1367         try {
1368             // prepare, authorizer is not activated yet
1369             db.exec("create table public_table(c1 integer, c2 integer);", null);
1370             db.exec("create table private_table(c1 integer, c2 integer);", null);
1371             // inserts
1372             db.exec(insertPublic, null);
1373             db.exec(insertPrivate, null);
1374             // selects
1375             resPriv = db.get_table("select * from private_table");
1376             resPub = db.get_table("select * from public_table");
1377 
1378 //            db.exec("delete from public_table where 1", null);
1379 //            TableResult emptyPubTable = db.exec("select * from public");
1380 
1381             // set Authorizer (positive case): denies private table
1382             AuthorizerCallback cb = new AuthorizerCallback();
1383             db.set_authorizer(cb);
1384             //select
1385 
1386             db.exec("select * from private_table", cb);
1387             assertTrue(cb.wasCalled());
1388 
1389            /*
1390             TableResult res = db.get_table("select * from private_table");
1391             assertEquals(emptyTable.toString(),res.toString());
1392             assertFalse(emptyTable.equals(resPriv));
1393 
1394             res = db.get_table("select * from public_table");
1395             assertEquals(resPub,res);
1396             */
1397         } catch (Exception e) {
1398             fail("Error testing authorization: "+e.getMessage());
1399         }
1400 
1401         // Try insert
1402         try {
1403             db.exec(insertPublic, null);
1404             fail("authorization failed");
1405         } catch (Exception e) {
1406             try {
1407                 db.exec(insertPrivate, null);
1408                 fail("authorization failed");
1409             } catch (Exception e1) {
1410                 // ok
1411             }
1412         }
1413 
1414     }
1415 
1416     /**
1417      * @tests {@link Database#trace(Trace)}
1418      */
1419 
1420     @TestTargetNew(
1421         level = TestLevel.COMPLETE,
1422         notes = "method test",
1423         method = "trace",
1424         args = {Trace.class}
1425     )
testTrace()1426     public void testTrace() {
1427         String stmt = "create table TEST (res double);";
1428         TestTrace t = new TestTrace();
1429         assertFalse(t.traceCalled);
1430         assertEquals(db.last_error(),Constants.SQLITE_OK);
1431         try {
1432             db.trace((Trace) t);
1433             db.exec(stmt,t);
1434             assertTrue(t.traceCalled);
1435             assertEquals(t.getTrace(),stmt);
1436         } catch (Exception e) {
1437             fail("Error testing traces: "+e.getMessage());
1438             e.printStackTrace();
1439         }
1440 
1441         try {
1442             db.close();
1443             db.exec(stmt,t);
1444             fail("Exception Expected");
1445         } catch (Exception e) {
1446             //ok
1447         }
1448 
1449 
1450     }
1451 
1452     /**
1453      * @tests {@link Database#compile(String)}
1454      */
1455     @TestTargetNew(
1456         level = TestLevel.COMPLETE,
1457         notes = "method test",
1458         method = "compile",
1459         args = {java.lang.String.class}
1460     )
testCompileString()1461     public void testCompileString() {
1462         try {
1463             db.compile("select name from sqlite_master;");
1464         } catch (Exception e) {
1465             fail("Error compiling sql statement " + e.getMessage());
1466             e.printStackTrace();
1467         }
1468         try {
1469             db.compile("test");
1470             fail("Compiling of inaccurate statement does not fail.");
1471         } catch (Exception e) {
1472 
1473         }
1474     }
1475 
1476     /**
1477      * @tests {@link Database#compile(String, String[])}
1478      */
1479     @TestTargetNew(
1480         level = TestLevel.COMPLETE,
1481         notes = "method test",
1482         method = "compile",
1483         args = {java.lang.String.class, java.lang.String[].class}
1484     )
testCompileStringStringArray()1485     public void testCompileStringStringArray() {
1486         String args[] = new String[1];
1487         args[0] = "table";
1488         try {
1489             db.compile("select name from sqlite_master where type = '%q';",args);
1490         } catch (Exception e) {
1491             fail("Error compiling sql statement " + e.getMessage());
1492             e.printStackTrace();
1493         }
1494         try {
1495             db.compile("test",null);
1496             fail("Compiling of inaccurate statement does not fail.");
1497         } catch (Exception e) {
1498 
1499         }
1500     }
1501 
1502     /**
1503      * @tests {@link Database#prepare(String)}
1504      */
1505     @TestTargetNew(
1506         level = TestLevel.COMPLETE,
1507         notes = "method test",
1508         method = "prepare",
1509         args = {java.lang.String.class}
1510     )
testPrepare()1511     public void testPrepare() {
1512         Stmt st = null;
1513         Stmt st2 = null;
1514         // test empty statement
1515         try {
1516             st = db.prepare("");
1517             assertEquals(0, st.bind_parameter_count());
1518             st.step();
1519             fail("stmt should not be prepared");
1520         } catch (Exception e) {
1521             assertEquals("stmt already closed", e.getMessage());
1522         }
1523 
1524         // test statement with unbound arguments
1525         try {
1526             st2 = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
1527                     + " values (:one,:two,:three)");
1528             assertEquals(3, st2.bind_parameter_count());
1529             assertEquals(3, st2.bind_parameter_index(":three"));
1530             assertEquals(":two", st2.bind_parameter_name(2));
1531         } catch (Exception e) {
1532             fail("error in prepare method: " + e.getMessage());
1533             e.printStackTrace();
1534         } finally {
1535             try {
1536                 st2.close();
1537             } catch (Exception e) {
1538                 fail("error in prepare method cleanup: " + e.getMessage());
1539                 e.printStackTrace();
1540             }
1541         }
1542 
1543         try {
1544             db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
1545                     + " values(:one,:two,:three,:four);");
1546         } catch (Exception e) {
1547             assertEquals("table " + DatabaseCreator.SIMPLE_TABLE1
1548                     + " has 3 columns but 4 values were supplied", e
1549                     .getMessage());
1550         }
1551 
1552         try {
1553             db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
1554                     + " values(5, '10, 20);");
1555         } catch (Exception e) {
1556             assertEquals("unrecognized token: \"'10, 20);\"", e.getMessage());
1557         }
1558 
1559         try {
1560             db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
1561                     + " values(5, 10 20);");
1562         } catch (Exception e) {
1563             assertEquals("near \"20\": syntax error", e.getMessage());
1564         }
1565 
1566     }
1567 
1568     /**
1569      * @throws Exception
1570      * @throws java.lang.Exception
1571      * @tests {@link Database#open_blob(String, String, String, long, boolean)}
1572      * unsupported
1573      */
1574     @TestTargetNew(
1575         level = TestLevel.COMPLETE,
1576         notes = "not supported",
1577         method = "open_blob",
1578         args = {java.lang.String.class, java.lang.String.class, java.lang.String.class, long.class, boolean.class}
1579     )
1580     @KnownFailure("not supported")
testOpen_blob()1581     public void testOpen_blob() throws Exception, java.lang.Exception {
1582         Stmt statement2;
1583         Blob blobInput = new Blob();
1584 
1585 
1586         // Create test input Blob
1587         InputStream inStream = null;
1588         byte[] in = {(byte) 1, (byte) 2, (byte) 3, (byte) 4};
1589 
1590         // setup test input
1591         db.exec("create table TEST (res blob)",null);
1592         inStream = Class.forName(this.getClass().getName()).getResourceAsStream("/blob.c");
1593         assertNotNull(inStream);
1594 
1595 
1596         // insert byte array in db
1597         try {
1598             statement2 = db.prepare("insert into TEST(res) values (?)");
1599             statement2.bind(1, in);
1600             statement2.step();
1601             statement2.close();
1602         } catch (Exception e) {
1603             fail("Error happened inserting blob" + e.getMessage());
1604             e.printStackTrace();
1605         }
1606 
1607         // read from db
1608         byte[] output = null;
1609         Blob blob;
1610 
1611             blob = db.open_blob(dbFile.getPath(), "TEST", "res", 1, true);
1612             if (blob == null) {
1613                 fail("Blob could not be retrieved");
1614             }
1615             //read from blob and compare values (positive case)
1616             InputStream is = blob.getInputStream();
1617 
1618             int i = 0;
1619             int outByte = 0;
1620             byte[] out = new byte[4];
1621             while ((outByte = is.read()) > -1) {
1622                 out[i] = (byte) outByte;
1623                 i++;
1624             }
1625             is.close();
1626 
1627             blob.close();
1628 
1629             assertTrue(Arrays.equals(in, out));
1630 
1631             //read from blob and compare values (default blob)
1632             db.exec("insert into TEST values(zeroblob(128))", null);
1633             Blob blob2 = db.open_blob(dbFile.getPath(), "TEST", "res", 2, true);
1634             is = blob2.getInputStream();
1635             for (i = 0; i < 128; i++)  {
1636                assertEquals(0, is.read());
1637             }
1638             is.close();
1639     }
1640 
1641     /**
1642      * @tests {@link Database#is3()}
1643      */
1644     @TestTargetNew(
1645         level = TestLevel.COMPLETE,
1646         notes = "method test",
1647         method = "is3",
1648         args = {}
1649     )
testIs3()1650     public void testIs3() {
1651         int ver = Integer.parseInt(db.version().substring(0,1));
1652         if (db.is3()) {
1653             assertTrue( ver == 3);
1654         } else {
1655             assertTrue(ver != 3);
1656         }
1657     }
1658 
1659     /**
1660      * @tests {@link Database#progress_handler(int, ProgressHandler)}
1661      */
1662     @TestTargets ({
1663     @TestTargetNew(
1664         level = TestLevel.COMPLETE,
1665         notes = "method test",
1666         method = "progress_handler",
1667         args = {int.class, ProgressHandler.class}
1668     ),
1669     @TestTargetNew(
1670             level = TestLevel.COMPLETE,
1671             notes = "method test",
1672             method = "progress",
1673             clazz = ProgressHandler.class,
1674             args = {}
1675         )
1676     })
testProgress_handler()1677     public void testProgress_handler() {
1678         int inputVal = 3;
1679         TestProgressHandler prog = new TestProgressHandler();
1680         try {
1681             db.exec("create table TEST5(id integer, firstname text, lastname text)",null);
1682             Vm vm = db.compile("select * from TEST5; "
1683                     + "insert into TEST5 values(3, 'James', 'Bond'); "
1684                     + "delete from TEST5 where id = 3; "
1685                     + "select * from TEST5");
1686             int stmt = 0;
1687             do {
1688                 ++stmt;
1689                 if (stmt > inputVal) {
1690                     db.progress_handler(inputVal, prog);
1691                 } else {
1692                     assertEquals(0, prog.getCounts());
1693                 }
1694                 while (vm.step(prog)) {
1695                 }
1696             } while (vm.compile());
1697             assertEquals(inputVal,prog.getCounts());
1698         } catch (Exception e) {
1699             fail("Error in test setup: "+e.getMessage());
1700             e.printStackTrace();
1701         }
1702 
1703         // Boundary value test
1704         inputVal = 0;
1705         TestProgressHandler progBoundary = new TestProgressHandler();
1706         db.progress_handler(inputVal, progBoundary);
1707         try {
1708         Vm vm2 = db.compile("select * from TEST5; "
1709                 + "insert into TEST5 values(3, 'James', 'Bond'); "
1710                 + "delete from TEST5 where id = 3; "
1711                 + "select * from TEST5");
1712         do {
1713             vm2.step(progBoundary);
1714         } while (vm2.compile());
1715         assertEquals(inputVal, progBoundary.getCounts());
1716         }catch (Exception e) {
1717             fail("Error in test setup: "+e.getMessage());
1718             e.printStackTrace();
1719         }
1720 
1721         try {
1722             db.exec("drop table TEST5",null);
1723         } catch (Exception e) {
1724             System.out.println(e.getMessage());
1725             e.printStackTrace();
1726         }
1727     }
1728 
1729 
1730 
1731     class SinFunc implements Function {
1732 
1733 
function(FunctionContext fc, String args[])1734         public void function(FunctionContext fc, String args[]) {
1735             Double d = new Double(args[0]);
1736             fc.set_result(Math.sin(d.doubleValue()));
1737         }
1738 
last_step(FunctionContext fc)1739         public void last_step(FunctionContext fc) {
1740             // TODO Auto-generated method stub
1741 
1742         }
1743 
step(FunctionContext fc, String[] args)1744         public void step(FunctionContext fc, String[] args) {
1745             // TODO Auto-generated method stub
1746 
1747         }
1748     }
1749 
1750    @TestTargetClass(Trace.class)
1751     class TestTrace implements Trace,Callback {
1752 
1753     private StringBuffer buf = new StringBuffer();
1754 
1755     public boolean traceCalled = false;
1756 
getTrace()1757     public String getTrace() {
1758         return buf.toString();
1759     }
1760 
trace(String stmt)1761     public void trace(String stmt) {
1762         traceCalled = true;
1763         buf.append(stmt);
1764     }
1765 
columns(String[] coldata)1766     public void columns(String[] coldata) {
1767         // TODO Auto-generated method stub
1768 
1769     }
1770 
newrow(String[] rowdata)1771     public boolean newrow(String[] rowdata) {
1772         // TODO Auto-generated method stub
1773         return false;
1774     }
1775 
types(String[] types)1776     public void types(String[] types) {
1777         // TODO Auto-generated method stub
1778 
1779     }
1780    }
1781 
1782    @TestTargetClass(Authorizer.class)
1783    class AuthorizerCallback implements Authorizer,Callback {
1784        private boolean isAuthorizing = false;
1785 
wasCalled()1786        public boolean wasCalled() {
1787            return isAuthorizing;
1788        }
1789 
authorize(int action, String arg1, String arg2, String arg3, String arg4)1790     public int authorize(int action, String arg1, String arg2, String arg3,
1791             String arg4) {
1792         Logger.global.info("DB authorization callback "+action+" "+arg1+" "+arg2+" "+arg3+" "+arg4+" ");
1793         this.isAuthorizing = true;
1794         if (action != Constants.SQLITE_SELECT || arg1.contains("private_table")) {
1795         return Constants.SQLITE_DENY;
1796         } else {
1797         return Constants.SQLITE_OK;
1798         }
1799     }
1800 
columns(String[] coldata)1801     public void columns(String[] coldata) {
1802         // TODO Auto-generated method stub
1803 
1804     }
1805 
newrow(String[] rowdata)1806     public boolean newrow(String[] rowdata) {
1807         // TODO Auto-generated method stub
1808         return false;
1809     }
1810 
types(String[] types)1811     public void types(String[] types) {
1812         // TODO Auto-generated method stub
1813 
1814     }
1815 
1816    }
1817 
1818    class TestBusyHandler implements BusyHandler, Callback {
1819 
busy(String table, int count)1820     public boolean busy(String table, int count) {
1821         System.out.println("BUSY!");
1822         return true;
1823     }
1824 
columns(String[] coldata)1825     public void columns(String[] coldata) {
1826         // TODO Auto-generated method stub
1827 
1828     }
1829 
newrow(String[] rowdata)1830     public boolean newrow(String[] rowdata) {
1831         // TODO Auto-generated method stub
1832         return false;
1833     }
1834 
types(String[] types)1835     public void types(String[] types) {
1836         // TODO Auto-generated method stub
1837 
1838     }
1839 
1840    }
1841 
1842    class TestProgressHandler implements ProgressHandler,Callback {
1843 
1844     private boolean progressed = false;
1845 
1846     private int counter = 0;
1847 
isProgressed()1848     public boolean isProgressed() {
1849         return progressed;
1850     }
1851 
getCounts()1852     public int getCounts() {
1853         return counter;
1854     }
1855 
progress()1856     public boolean progress() {
1857         this.progressed = true;
1858         counter++;
1859         return true;
1860     }
1861 
columns(String[] coldata)1862     public void columns(String[] coldata) {
1863         // TODO Auto-generated method stub
1864 
1865     }
1866 
newrow(String[] rowdata)1867     public boolean newrow(String[] rowdata) {
1868         // TODO Auto-generated method stub
1869         return false;
1870     }
1871 
types(String[] types)1872     public void types(String[] types) {
1873         // TODO Auto-generated method stub
1874 
1875     }
1876 
1877    }
1878 
1879 //   class dbBusyThread implements Runnable {
1880 //
1881 //       String dbName = "sqliteTest.db";
1882 //
1883 //       Thread runner;
1884 //       public dbBusyThread() {
1885 //       }
1886 //       public dbBusyThread(String threadName) {
1887 //           runner = new Thread(this, threadName); // (1) Create a new thread.
1888 //           System.out.println(runner.getName());
1889 //           runner.start(); // (2) Start the thread.
1890 //       }
1891 //       public void run() {
1892 //            insert(3000);
1893 //        }
1894 //
1895 //       public void runNoDelay() {
1896 //           insert(0);
1897 //       }
1898 //
1899 //       synchronized private void insert(long delay) {
1900 //           Database db2 = new Database();
1901 //           try {
1902 //               db2.open(dbName, 0);
1903 //               db2.exec("insert into TEST5 values (4,'Anglina','Jolie');",
1904 //                       null);
1905 //               wait(delay);
1906 //           } catch (Exception e) {
1907 //               System.out.println("Error in Thread " + e.getMessage());
1908 //               e.printStackTrace();
1909 //           } catch (InterruptedException e2) {
1910 //               System.out.println("Error in Thread " + e2.getMessage());
1911 //               e2.printStackTrace();
1912 //           } finally {
1913 //              try {
1914 //               db2.close();
1915 //           } catch (Exception e) {
1916 //               // We do not handle this case
1917 //           }
1918 //           }
1919 //       }
1920 //   }
1921 
1922    /**
1923     * This method creates a Runnable that executes insert operation for the
1924     * first table
1925     */
createTask2Interrupt(final int id, final String dbName, final ErrorTracker errorTracker)1926    private static Runnable createTask2Interrupt(final int id,
1927             final String dbName, final ErrorTracker errorTracker) {
1928         return new Runnable() {
1929             public void run() {
1930                 Database db = new Database();
1931                 try {
1932                     String value = DatabaseCreator.defaultString + id;
1933 
1934                     db.open(dbName, 0);
1935                     String insertQuery = "INSERT INTO "
1936                             + DatabaseCreator.TEST_TABLE1
1937                             + " (id, field1, field2, field3) VALUES(" + id
1938                             + ", '" + value + "', " + id + ", " + id + ")";
1939                     db.exec(insertQuery, null);
1940                 } catch (Exception e) {
1941                     errorTracker.registerException(this, e);
1942                     try {
1943                         db.interrupt();
1944                         db.exec("DELETE FROM " + DatabaseCreator.SIMPLE_TABLE1
1945                                 + " WHERE id=" + id, null);
1946                     } catch (Exception e1) {
1947                         errorTracker.registerException(this, e1);
1948                     }
1949                 }
1950             }
1951         };
1952    }
1953 
1954    /**
1955     * This method creates a Runnable that executes delete operation for the
1956     * first table
1957     */
1958    private static Runnable createTask1(final int id,final String dbName, final ErrorTracker errorTracker) {
1959        return new Runnable() {
1960            public void run() {
1961                try {
1962                    Database db = new Database();
1963                    db.open(dbName, 0);
1964                    db.exec("DELETE FROM "
1965                            + DatabaseCreator.SIMPLE_TABLE1 + " WHERE id=" + id,null);
1966                } catch (Exception e) {
1967                    errorTracker.registerException(this, e);
1968                }
1969            }
1970        };
1971    }
1972 
1973    /**
1974     * This method creates a Runnable that executes insert operation for the
1975     * first table
1976     */
1977    private static Runnable createTask2(final int id, final String dbName, final ErrorTracker errorTracker ) {
1978        return new Runnable() {
1979            public void run() {
1980                try {
1981                    String value = DatabaseCreator.defaultString + id;
1982                    Database db = new Database();
1983                    db.open(dbName, 0);
1984                    String insertQuery = "INSERT INTO "
1985                            + DatabaseCreator.TEST_TABLE1
1986                            + " (id, field1, field2, field3) VALUES(" + id
1987                            + ", '" + value + "', " + id + ", " + id + ")";
1988                    db.exec(insertQuery,null);
1989                } catch (Exception e) {
1990                    errorTracker.registerException(this, e);
1991 
1992                }
1993            }
1994        };
1995    }
1996 
1997    /**
1998     * This method creates a Runnable that executes update operation for the one
1999     * record of the first table
2000     */
2001    private static Runnable createTask3(final int oldID, final String dbName,
2002             final int newID, final ErrorTracker errorTracker) {
2003         return new Runnable() {
2004             public void run() {
2005                 Database db = new Database();
2006                 try {
2007                     db.open(dbName, 0);
2008                     String value = DatabaseCreator.defaultString + newID;
2009                     String updateQuery = "UPDATE "
2010                             + DatabaseCreator.TEST_TABLE1 + " SET id=" + newID
2011                             + ", field1='" + value + "', field2=" + newID
2012                             + ", field3=" + newID + " WHERE id=" + oldID;
2013                     db.exec(updateQuery, null);
2014                 } catch (Exception e) {
2015                     errorTracker.registerException(this, e);
2016                 }
2017             }
2018         };
2019     }
2020 
2021    private class ErrorTracker {
2022         private List<String> errors = new ArrayList<String>();
2023 
2024         public void registerException(Runnable runnable, Exception e) {
2025             System.out.println("Registered: "+e.getMessage());
2026             errors.add(e.getMessage());
2027         }
2028 
2029         public List<String> getErrors() {
2030             return errors;
2031         }
2032 
2033         public void reset() {
2034             errors.clear();
2035         }
2036     }
2037 
2038 }
2039