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