package org.sqlite;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.junit.Assert.assertEquals;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class BusyHandlerTest {
    private Connection conn;
    private Statement stat;

    @Before
    public void connect() throws Exception {
        conn = DriverManager.getConnection("jdbc:sqlite:target/test.db");
        stat = conn.createStatement();
    }

    @After
    public void close() throws SQLException {
        stat.close();
        conn.close();
    }

    public class BusyWork extends Thread {
        private final Connection conn;
        private final Statement stat;

        public BusyWork() throws Exception {
            conn = DriverManager.getConnection("jdbc:sqlite:target/test.db");
            stat = conn.createStatement();
            stat.setQueryTimeout(10);
        }

        @Override
        public void run(){

            try {
                synchronized(this) {
                    // Generate some work for the sqlite vm
                    stat.executeUpdate("drop table if exists foo;");
                    stat.executeUpdate("create table foo (id integer);");

                    int i = 0;
                    while (i<10000) {
                        String stmt = "insert into foo (id) values (" + i + ")";
                        stat.addBatch(stmt);
                        i++;
                    }
                }
            } catch (SQLException ex) {System.out.println("HERE"+ex.toString());}

            try {
                stat.executeBatch();
            } catch (SQLException ex) {System.out.println("BLOB"+ex.toString());}
        }
    }

    private void workWork() throws SQLException, InterruptedException {
        // I let busyWork inject first so it can busy the db
        Thread.sleep(1000);

        // Generate some work for the sqlite vm
        int i = 0;
        while (i<100) {
            stat.executeQuery("insert into foo (id) values (" + i + ")");
            i++;
        }
    }

    @Test
    public void basicBusyHandler() throws Exception {
        final int[] calls = {0};
        BusyHandler.setHandler(conn, new BusyHandler() {
            @Override
            protected int callback(int nbPrevInvok) throws SQLException {
                assertTrue(calls[0] == nbPrevInvok);
                calls[0]++;

                if (nbPrevInvok <= 1) {
                    return 1;
                } else {
                    return 0;
                }
            }
        });

        BusyWork busyWork = new BusyWork();
        busyWork.start();

        // I let busyWork prepare a huge insert
        Thread.sleep(1000);

        synchronized(busyWork){
            try{
                workWork();
            } catch(SQLException ex) {
                assertTrue(ex.getErrorCode() == SQLiteErrorCode.SQLITE_BUSY.code);
            }
        }

        busyWork.interrupt();
        assertTrue(calls[0] == 3);
    }

    @Test
    public void testUnregister() throws Exception {
        final int[] calls = {0};
        BusyHandler.setHandler(conn, new BusyHandler() {
            @Override
            protected int callback(int nbPrevInvok) throws SQLException {
                assertTrue(calls[0] == nbPrevInvok);
                calls[0]++;

                if (nbPrevInvok <= 1) {
                    return 1;
                } else {
                    return 0;
                }
            }
        });

        BusyWork busyWork = new BusyWork();
        busyWork.start();
        // I let busyWork prepare a huge insert
        Thread.sleep(1000);
        synchronized(busyWork){
            try{
                workWork();
            } catch(SQLException ex) {
                assertTrue(ex.getErrorCode() == SQLiteErrorCode.SQLITE_BUSY.code);
            }
        }
        assertTrue(calls[0] == 3);

        int totalCalls = calls[0];
        BusyHandler.clearHandler(conn);
        busyWork = new BusyWork();
        busyWork.start();
        // I let busyWork prepare a huge insert
        Thread.sleep(1000);
        synchronized(busyWork){
            try{
                workWork();
            } catch(SQLException ex) {
                assertTrue(ex.getErrorCode() == SQLiteErrorCode.SQLITE_BUSY.code);
            }
        }

        busyWork.interrupt();
        assertEquals(totalCalls, calls[0]);
    }

    @Test
    public void testInterrupt() throws Exception {

        try {
            BusyHandler.setHandler(conn, new BusyHandler() {
                @Override
                protected int callback(int nbPrevInvok) throws SQLException {
                    return 1;
                }
            });
            workWork();
        } catch (SQLException ex) {
            // Expected error
            return;
        }
        // Progress function throws, not reached
        fail();
    }
}

@@ -214,154 +214,46 @@
 ort 
-java.util.logging.Level;%0Aimport java.util.logging.Logger;%0Aimport static org.junit.Assert.assertEquals;%0A%0Aimport static org.junit.Assert.assertTrue;
+static org.junit.Assert.assertEquals;%0A
 %0Aimp
@@ -2436,33 +2436,23 @@
   assert
-True(calls%5B0%5D == 
+Equals(
 nbPrevIn
@@ -2446,32 +2446,42 @@
 uals(nbPrevInvok
+, calls%5B0%5D
 );%0A             
@@ -2956,34 +2956,15 @@
 sert
-True(ex.getErrorCode() == 
+Equals(
 SQLi
@@ -2983,32 +2983,51 @@
 SQLITE_BUSY.code
+, ex.getErrorCode()
 );%0A            %7D
@@ -3078,37 +3078,42 @@
       assert
-True(
+Equals(3, 
 calls%5B0%5D
  == 3);%0A    
@@ -3100,21 +3100,16 @@
 calls%5B0%5D
- == 3
 );%0A    %7D
@@ -3380,33 +3380,23 @@
   assert
-True(calls%5B0%5D == 
+Equals(
 nbPrevIn
@@ -3398,16 +3398,26 @@
 revInvok
+, calls%5B0%5D
 );%0A     
@@ -3898,34 +3898,15 @@
 sert
-True(ex.getErrorCode() == 
+Equals(
 SQLi
@@ -3925,32 +3925,51 @@
 SQLITE_BUSY.code
+, ex.getErrorCode()
 );%0A            %7D
@@ -3997,21 +3997,26 @@
 sert
-True(
+Equals(3, 
 calls%5B0%5D
  == 
@@ -4015,13 +4015,8 @@
 s%5B0%5D
- == 3
 );%0A%0A
@@ -4369,34 +4369,15 @@
 sert
-True(ex.getErrorCode() == 
+Equals(
 SQLi
@@ -4404,16 +4404,35 @@
 USY.code
+, ex.getErrorCode()
 );%0A     

use assertEquals instead of assertTrue so it tells the difference in the log