/* * Copyright (c) 2012, NTT Multimedia Communications Laboratories, Inc. and Koushik Sen * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package tests; import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.*; public class BookStore { //--variables related to control concolic execution-------------------- private Connection connection = null; private Statement statement = null; private static final int SCREEN_VISIT_MAX = 1; private static final int SCREEN_COUNT_MAX = 25; private static final int S01_LOGIN_SCREEN = 1; private static final int S02_LOGIN_ERROR_SCREEN = 2; private static final int S03_MENU_SCREEN = 3; private static final int S04_SEARCH_BOOKS_SCREEN = 4; private static final int S05_NO_BOOK_SCREEN = 5; private static final int S06_SELECT_BOOKS_SCREEN = 6; private static final int S07_NO_SELECTION_SCREEN = 7; private static final int S08_TOO_EXPENSIVE_SCREEN = 8; private static final int S09_FINAL_CHECK_TO_ORDER_SCREEN = 9; private static final int S10_THANK_YOU_ORDER_SCREEN = 10; private static final int S11_DUPLICATE_ORDER_SCREEN = 11; private static final int S20_NO_ORDER_SCREEN = 20; private static final int S21_SELECT_ORDERS_SCREEN = 21; private static final int S22_NO_SELECTED_ORDER_SCREEN = 22; private static final int S23_FINAL_CHECK_TO_CANCEL_SCREEN = 23; private static final int S24_FINISHED_CANCEL_SCREEN = 24; private int[] screenVisitCountTable; //--------------------------------------------------------------------------- BookStoreScreenInputs screenInputs; //--input variables of concolic execution-------------------------------- //screen inputs private BookStoreScreenInputs[] screenInputsList; //global inputs private int g_customerId; //inner variables private ArrayList<Tuple2<Integer,Integer>> selectedBookIdPriceList; private ArrayList<Tuple2<Integer,Integer>> orderedBookIdPriceList; private ArrayList<Integer> selectedOrderIdList; //--------------------------------------------------------------------------- public static void main(String[] argv){ BookStore bookStore = new BookStore(); bookStore.initialize(); bookStore.execute(); bookStore.dispose(); } public void initialize(){ screenVisitCountTable = new int[SCREEN_COUNT_MAX]; screenInputsList = new BookStoreScreenInputs[SCREEN_VISIT_MAX]; for(int i=0;i<SCREEN_VISIT_MAX;i++){ screenInputsList[i] = new BookStoreScreenInputs(); } try { String databaseName = "sample.db"; Class.forName("org.sqlite.JDBC"); // delete the existing database File file = new File(databaseName); if(file.exists()){ file.delete(); } // create a database connection and statement connection = DriverManager.getConnection("jdbc:sqlite:"+databaseName); statement = connection.createStatement(); // create a database tables statement.executeUpdate("create table Customers (Id integer, Name string, PasswordHash integer, Age integer)"); statement.executeUpdate("create table Orders (Id integer, CustomerId integer,OrderDateTime integer,CancelDate integer, BookId integer, IsCanceled integer)"); statement.executeUpdate("create table Publishers (Id integer, Name string)"); statement.executeUpdate("create table Books (Id integer, ISBN integer, Title string,Price integer, Year integer, PublisherId integer, Stock integer)"); // create an example of inputs and initial database state createExampleInitialDatabaseState(); createExampleInitialInputsList(); } catch(Exception e) { System.err.println(e.getMessage()); } } public void createExampleInitialDatabaseState() throws SQLException{ //Customers statement.executeUpdate("insert into Customers values(0, 'Tanaka', 3,25)"); //Books statement.executeUpdate("insert into Books values(20, 1234567890, 'The Art of C++', 20, 1987, 20, 1)"); statement.executeUpdate("insert into Books values(21, 1234567891, 'The Art of C#', 25, 2000, 21, 1)"); statement.executeUpdate("insert into Books values(22, 1234567892, 'The Art of Lisp', 30, 1980, 20, 1)"); statement.executeUpdate("insert into Books values(23, 1234567894, 'Java HandBook', 5, 1999, 21, 1)"); //Publishers statement.executeUpdate("insert into Publishers values(20, 'Pearson Education')"); statement.executeUpdate("insert into Publishers values(21, 'O Reilly')"); //Orders statement.executeUpdate("insert into Orders values(20, 1, 20120310, NULL, 20, 0)"); } public void createExampleInitialInputsList() { BookStoreScreenInputs is = screenInputsList[0]; is.customerId = 0; is.password = 1; is.title = "The Art of C#"; is.publisherName = "O Reilly"; is.minYear = 2000; is.maxYear = 2010; } public void execute(){ try{ int state = S01_LOGIN_SCREEN; while(true){ // check screen visit count int screenVisitCount = screenVisitCountTable[state]; if(screenVisitCount >= SCREEN_VISIT_MAX){ System.err.println("Exceed the max count of screen visit"); return; } BookStoreScreenInputs is = screenInputsList[screenVisitCount]; // execution the business logic related to state (screen) switch (state){ case S01_LOGIN_SCREEN: state = s01_loginScreen(is.customerId, is.password); break; case S02_LOGIN_ERROR_SCREEN: state = s02_loginErrorScreen(); case S03_MENU_SCREEN: state = s03_menuScreen(is.whereGoto); break; case S04_SEARCH_BOOKS_SCREEN: state = s04_searchBooksScreen(is.title, is.publisherName, is.minYear, is.maxYear); break; case S05_NO_BOOK_SCREEN: state = s05_noBookScreen(); break; case S06_SELECT_BOOKS_SCREEN: System.out.println("Reach S06_SELECT_BOOKS_SCREEN..."); System.out.println("Screen S07 to S11 and S20 to S24 are not implemented."); return; //state = s06_selectBooksScreen(is.selectedBooksIndexes); break; case -1: System.err.println("Invalid state"); return; } } } catch(Exception e){ System.err.println(e.getMessage()); } } public int s01_loginScreen(int customerId, int password) throws SQLException { assume(customerId >= 0 && customerId <= 1000); assume(password >= 0 && password <= 20); ResultSet rs = statement.executeQuery("select Id from Customers where Id="+customerId+" and PasswordHash=" + hash(password)); ArrayList<Integer> customerIdList = new ArrayList<Integer>(); while(rs.next()) { customerIdList.add(rs.getInt("Id")); } if(customerIdList.size() > 0){ g_customerId = customerId; return S03_MENU_SCREEN; } else{ return S02_LOGIN_ERROR_SCREEN; } } private int s02_loginErrorScreen(){ return S01_LOGIN_SCREEN; } private int s03_menuScreen(int whereGoto) throws SQLException { assume(whereGoto == BookStoreScreenInputs.GOTO_ORDER || whereGoto == BookStoreScreenInputs.GOTO_CANCEL); if(whereGoto == BookStoreScreenInputs.GOTO_ORDER){ return S04_SEARCH_BOOKS_SCREEN; } else if(whereGoto == BookStoreScreenInputs.GOTO_CANCEL){ ResultSet rs = statement.executeQuery("select Id from Orders where CustomerId=" + g_customerId); ArrayList<Integer> orderIdList = new ArrayList<Integer>(); while(rs.next()) { orderIdList.add(rs.getInt("Id")); } if(orderIdList.size() > 0){ return S21_SELECT_ORDERS_SCREEN; } else{ return S20_NO_ORDER_SCREEN; } } else{ return -1; } } private int s04_searchBooksScreen(String title, String publisherName, int minYear, int maxYear) throws SQLException{ assume(title.length() >= 0 && title.length() <= 20); assume(publisherName.length() >= 0 && publisherName.length() <= 20); assume(minYear >= 1950 && minYear <= 2050); assume(maxYear >= 1950 && maxYear <= 2050); ResultSet rs = statement.executeQuery("select Books.Id, Books.Price " + "from Books inner join Publishers on Books.PublisherId = Publishers.Id " + "where Books.Title= '" + title + "' and Publishers.Name='"+publisherName+"' and Books.Year>=" + minYear + " and Books.Year<=" + maxYear + " and Books.Stock > 0"); selectedBookIdPriceList = new ArrayList<Tuple2<Integer,Integer>>(); while(rs.next()) { selectedBookIdPriceList.add(new Tuple2<Integer, Integer>(rs.getInt("Id"), rs.getInt("Price"))); } if(selectedBookIdPriceList.size() > 0){ return S06_SELECT_BOOKS_SCREEN; } else{ return S05_NO_BOOK_SCREEN; } } private int s05_noBookScreen() { return S04_SEARCH_BOOKS_SCREEN; } private int s06_selectBooksScreen(int[] selectedBooksIndexes) { // todo return 0; } private void assume(boolean b) { if (!b) System.err.println("Assumption is incorrect"); } private int hash(int password) { return password % 5 + 3; } public void dispose(){ try { if(connection != null) connection.close(); } catch(SQLException e) { // connection close failed. System.err.println(e); } } }