/*
 * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/*
 * @(#)sqlExceptionClient.java	1.6 02/01/12
 */

package com.sun.cts.tests.jdbc.ee.exception.sqlException;

import java.io.*;
import java.util.*;

import java.sql.*;
import javax.sql.*;

import com.sun.cts.util.*;
import com.sun.cts.porting.*;
import com.sun.cts.harness.*;

import java.rmi.RemoteException;

import javasoft.sqe.javatest.Status;
import com.sun.cts.tests.jdbc.ee.common.*;


// Merant DataSource class
//import com.merant.sequelink.jdbcx.datasource.*;


/**
 * The sqlExceptionClient class tests methods of SQLException class using
 * Sun's J2EE Reference Implementation.
 * @author  
 * @version 1.7, 06/16/99
 */

public class sqlExceptionClient extends ServiceEETest implements Serializable 
{
	private static final String testName = "jdbc.ee.exception.sqlException";

	//Naming specific member variables
	private CTSNamingContextInterface jc = null;

	//Harness requirements 

	private transient Connection conn = null;
	private ResultSet rs=null;
	private Statement stmt=null;
	private DataSource ds1 = null;
	private dbSchema dbSch=null;
	private rsSchema rsSch = null ;
	private	String drManager=null;
	private Properties sqlp = null;
	private boolean isThrown = false ; 
	private String sReason = null ;
	private String sSqlState = null ;
	private String sVendorCode = null;
	private String sUsr,sPass,sUrl ;
	private int vendorCode = 0,maxVal = 0,minVal = 0;
	private int[] updateCount = null ;

	/* Run test in standalone mode */
	public static void main(String[] args) 
	{
		sqlExceptionClient theTests = new sqlExceptionClient();
		Status s=theTests.run(args, System.out, System.err);
		s.exit();
	}

	/*
	 *   @class.setup_props: Driver, the Driver name;
	 *			db1, the database name with url;
	 *			user1, the database user name;
	 *			password1, the database password;
	 *			db2, the database name with url;
	 *			user2, the database user name;
	 *			password2, the database password;
	 *			DriverManager, flag for DriverManager;
	 *			ptable, the primary table;
	 *			ftable, the foreign table;
	 *			cofSize, the initial size of the ptable;
	 *			cofTypeSize, the initial size of the ftable;
	 *			binarySize, size of binary data type;
	 *			varbinarySize, size of varbinary data type;
	 *			longvarbinarySize, size of longvarbinary data type;
	 *  @class.testArgs:     -ap ctssql.stmt
	 */
	public void setup(String[] args,Properties p) throws Fault 
	{
		try
		{
			try
			{
				drManager = p.getProperty("DriverManager","");
				if (drManager.length() == 0)
					throw new Fault("Invalid DriverManager Name");
				sUrl =  p.getProperty("db1","" );
				sUsr = p.getProperty("user1","" );
				sPass = p.getProperty("password1","" );
				/*sqlp = new Properties();
				String sqlStmt= p.getProperty("rsQuery","");
				InputStream istr= new FileInputStream(sqlStmt);
				sqlp.load(istr);*/
				sqlp=p;
				if(drManager.equals("yes"))
				{
					logMsg("Using DriverManager");
					DriverManagerConnection dmCon = new DriverManagerConnection();
					conn = dmCon.getConnection(p);
				}
				else 
				{
					logMsg("Using DataSource");
					DataSourceConnection dsCon = new DataSourceConnection();
					conn = dsCon.getConnection(p);
				}
				dbSch=new dbSchema();
				rsSch = new rsSchema();
				dbSch.createData(p,conn);
				//conn.setAutoCommit(false);

				stmt=conn.createStatement();
				sReason   = sqlp.getProperty("Reason_BatUpdExec");
				logMsg("Reason : " + sReason);
				sSqlState  = sqlp.getProperty("SQLState_BatUpdExec");
				logMsg("SQLState : " + sSqlState);
				
				sVendorCode = sqlp.getProperty("VendorCode_BatUpdExec");
				logMsg("VendorCode : " + sVendorCode);
				
				sVendorCode = sVendorCode.trim();
				vendorCode = Integer.valueOf(sVendorCode).intValue();
						 		
			}
			catch(SQLException ex)
			{
				logErr("SQL Exception : " + ex.getMessage());
				throw new Fault("Set Up Failed");
			}
		} 
		catch  ( Exception e ) 
		{
			logErr("Setup Failed!");
			TestUtil.printStackTrace(e);
			throw new Fault("Setup Failed");
		}
	}
	

	/*
	 * @testName:         testSQLException01
	 * @assertion:        The class SQLException provides information about errors 
	 *                    in accessing the database.When an SQLException is thrown 
	 *                    it does not always mean method that caused it to be thrown 
	 *                    was not executed.This means the programmer should not 
	 *                    make any assumptions about the state of transactions based 
	 *                    on the exceptions.
	 *                    
	 *                    Constructs a fully specified SQLException Object 
	 *                    The vendor code is set to 0,SQLState is set to null and 
	 *                    reason is set to null
	 *                    
	 *                    (Refer JDBC 2.0 API Tutorial and Reference Section 36.1)
	 *                    
	 * @test_Strategy:    This method constructs a SQLException Object with
	 *                    no arguments and for that object the reason,SQLState 
	 *                    and ErrorCode are checked for default values.
	 *
	 */
	public void testSQLException01() throws Fault 
	{
		try
		{
			isThrown = false ;
			throw new SQLException();
		}
		catch(SQLException b)
		{
			isThrown = true ;
			if((b.getMessage() != null) || (b.getSQLState() != null) || (b.getErrorCode() != 0))
			{
				logErr("SQLException() Constructor Fails");
				throw new Fault("Call to SQLException() Constructor Fails");
			}
			else
			{
				logMsg("SQLException() Constructor is implemented");
			}
		}
		catch(Exception ex)
		{
			logErr("UnexpectedException " + ex.getMessage());
			throw new Fault("Call to SQLException() Failed!");
		}
		if(!isThrown)
		{
			logErr("SQLException() not thrown" );
			throw new Fault("Call to SQLException() Failed!");
		}
	}


	/*
	 * @testName:         testSQLException02
	 * @assertion:        The class SQLException provides information about errors 
	 *                    in accessing the database.When an SQLException is thrown 
	 *                    it does not always mean method that caused it to be thrown 
	 *                    was not executed.This means the programmer should not 
	 *                    make any assumptions about the state of transactions based 
	 *                    on the exceptions.
	 *                    
	 *                    Constructs a fully specified SQLException Object intialised 
	 *                    with reason .The vendor code is set to 0.and 
	 *                    SQLState is set to null 
	 *                    
	 *                    (Refer JDBC 2.0 API Tutorial and Reference Section 36.1)
	 *                    
	 * @test_Strategy:    This method constructs a SQLException Object
	 *                    with one argument and for that object the SQLState,
	 *                    ErrorCode are checked for default values.The
	 *                    reason is checked for whatever is been assigned
	 *                    while creating the new instance.
	 */

	public void testSQLException02() throws Fault 
	{
		try
		{
			isThrown = false ;
			throw new SQLException(sReason);
		}
		catch(SQLException b)
		{
			isThrown = true ;
			if((b.getSQLState() != null) || (b.getErrorCode() != 0))
			{
				logErr("SQLException(String) Constructor Fails");
				throw new Fault("Call to SQLException(String) Constructor Fails");
			}
			else
			{
				if((!sReason.equals(b.getMessage())))
				{
					logErr("SQLException(String) Constructor Fails");
					throw new Fault("Call to SQLException(String) Constructor Fails");
				}
				else
				{
					logMsg("SQLException Constructor implemented");
				}
			}
		}
		catch(Exception ex)
		{
			logErr("UnexpectedException " + ex.getMessage());
			throw new Fault("Call to SQLException(String) Constructor Fails");
		}
	
		if(!isThrown)
		{
			logErr("SQLException(String) Constructor Fails");
			throw new Fault("Call to SQLException(String) Constructor Fails");
		}

	}


	/*
	 * @testName:         testSQLException03
	 * @assertion:        The class SQLException provides information about errors 
	 *                    in accessing the database.When an SQLException is thrown 
	 *                    it does not always mean method that caused it to be thrown 
	 *                    was not executed.This means the programmer should not 
	 *                    make any assumptions about the state of transactions based 
	 *                    on the exceptions.
	 *                    
	 *                    Constructs a fully specified SQLException Object intialised 
	 *                    with reason and SQLState.The vendor code is set to 0.
	 *                    
	 *                    (Refer JDBC 2.0 API Tutorial and Reference Section 36.1)
	 *                    
	 * @test_Strategy:    This method constructs a SQLException Object
	 *                    with two arguments and for that object ErrorCode 
	 *                    is checked for default values.The reason and SQLState 
	 *                    are checked for whatever is been assigned while
	 *                    creating the new instance.
	 */
	public void testSQLException03() throws Fault 
	{
		try
		{
			isThrown = false ;
			throw new SQLException(sReason,sSqlState);
		}
		catch(SQLException b)
		{
			isThrown = true ;
			if((b.getErrorCode() != 0))
			{
				logErr("SQLException(String,String) Constructor Fails");
				throw new Fault("Call to SQLException(String,String) Constructor Fails");
			}
			else
			{
				if((!sSqlState.equals(b.getSQLState())) || (!sReason.equals(b.getMessage())))
				{
					logErr("SQLException(String,String) Constructor Fails");
					throw new Fault("Call to SQLException(String,String) Constructor Fails");
				}
				else
				{
					logMsg("Call to SQLException Passes");
				}
			}
		}
		catch(Exception ex)
		{
			logErr("UnexpectedException " + ex.getMessage());
			throw new Fault("Call to SQLException(String,String) Constructor Fails");
		}
	
		if(!isThrown)
		{
			logErr("SQLException(String,String) not thrown" );
			throw new Fault("Call to SQLException(String,String) Constructor Fails");
		}
	}


	/*
	 * @testName:         testSQLException04
	 * @assertion:        The class SQLException provides information about errors 
	 *                    in accessing the database.When an SQLException is thrown 
	 *                    it does not always mean method that caused it to be thrown 
	 *                    was not executed.This means the programmer should not make 
	 *                    any assumptions about the state of transactions based on 
	 *                    the exceptions.
	 *                    
	 *                    Constructs a fully specified SQLException Object
	 *                    
	 *                    (Refer JDBC 2.0 API Tutorial and Reference Section 36.1)
	 *                    
	 * @test_Strategy:    This method constructs a SQLException Object
	 *                    with three arguments .The reason,SQLState and 
	 *                    Errorcode is checked for whatever is been assigned 
	 *                    while creating the new instance.
	 */
	public void testSQLException04() throws Fault 
	{
		try
		{
			isThrown = false ;
			throw new SQLException(sReason,sSqlState,vendorCode);
		}
		catch(SQLException b)
		{
			isThrown = true ;
			if((!sReason.equals(b.getMessage())) || (!sSqlState.equals(b.getSQLState())) || (!(vendorCode == b.getErrorCode())))
			{
				logErr("SQLException(String,String,int) Constructor Fails");
				throw new Fault("Call to SQLException(String,String,int) Constructor Fails");
			}
			else
			{
				logMsg("SQLException(String,String,int) Constructor is implemented");
			}
		}
		catch(Exception ex)
		{
			logErr("Exception " + ex.getMessage());
			throw new Fault("Call to SQLException(String,String,int) Constructor is Failed!");
		}
	
		if(!isThrown)
		{
			logErr("SQLException(String,String,int) Constructor not thrown");
			throw new Fault("Call to SQLException(String,String,int) Constructor is Failed!");
		}
	}


	/*
	 * @testName:         testGetErrorCode
	 * @assertion:        The class SQLException provides information about errors
	 *                    in accessing the database.When an SQLException is thrown 
	 *                    it does not always mean method that caused it to be thrown 
	 *                    was not executed.This means the programmer should not 
	 *                    make any assumptions about the state of transactions based 
	 *                    on the exceptions.
	 *                    
	 *                    The getErrorCode() method returns a integer giving the 
	 *                    vendor specific error code for this SQLException Object
	 *                    
	 *                    (Refer JDBC 2.0 API Tutorial and Reference Section 36.1)
	 *                    
	 * @testStartegy:     The SQLException object is generated by executing an 
	 *                    incomplete SQL Statement and the getErrorCode() method 
	 *                    of that object is checked whether it returns an integer.
	 */
	public void testGetErrorCode() throws Fault 
	{
		try
		{
			String sErrorQuery = sqlp.getProperty("Error_Query");
			stmt.executeQuery(sErrorQuery);
		}
		catch(SQLException b)
		{
			isThrown = true ;
			maxVal = Integer.parseInt((rsSch.extractVal("Integer_Tab",1,sqlp,conn)).trim());
			minVal = Integer.parseInt((rsSch.extractVal("Integer_Tab",2,sqlp,conn)).trim());
			if((b.getErrorCode() <= maxVal) && (b.getErrorCode() >= minVal))
			{
				logMsg("getErrorCode() method returns integer value");
			}
			else
			{
				logErr("getErrorCode() Method does not returns integer value");
				throw new Fault("Call to getErrorCode() method fails");
			}
		}
		catch(Exception ex)
		{
			logErr("UnexpectedException " + ex.getMessage());
			throw new Fault("call to getErrorCode() method fails");
		}
		if(!isThrown)
		{
			logErr("getErrorCode() Method does not returns integer value");
			throw new Fault("Call to getErrorCode() method fails");
		}
	}


	/*
	 * @testName:         testGetSQLState
	 * @assertion:        The class SQLException provides information about errors 
	 *                    in accessing the database.When an SQLException is thrown it 
	 *                    does not always mean method that caused it to be thrown
	 *                    was not executed.This means the programmer should not make 
	 *                    any assumptions about the state of transactions based on 
	 *                    the exceptions.
	 *                    
	 *                    The getSQLState() method returns a String Object giving 
	 *                    the SQL State.
	 *                    
	 *                    (Refer JDBC 2.0 API Tutorial and Reference Section 36.1)
	 *                    
	 * @testStartegy:     The SQLException object is generated by executing an 
	 *                    incomplete SQL Statement and the getSQLState() method 
	 *                    of that object is checked whether it is an instance of 
	 *                    java.lang.String.
	 */

	public void testGetSQLState() throws Fault 
	{
		try
		{
			String sErrorQuery = sqlp.getProperty("Error_Query");
			stmt.executeQuery(sErrorQuery);
		}
		catch(SQLException b)
		{
			isThrown = true ;
			if((b.getSQLState() instanceof java.lang.String))
			{
				logMsg("getSQLState() method returns String value");
			}
			else
			{
				logErr("getSQLState() method does not returns String Value");
				throw new Fault("call to getSQLState() method fails");
			}
		}
		catch(Exception ex)
		{
			logErr("UnexpectedException " + ex.getMessage());
			throw new Fault("call to getSQLState() method fails");
		}
	
		if(!isThrown)
		{
			logErr("SQLException not thrown" );
			throw new Fault("call to getSQLState() method fails");
		}
	}


	/*
	 * @testName:         testGetNextException
	 * @assertion:        The class SQLException provides information about errors 
	 *                    in accessing the database.When an SQLException is thrown 
	 *                    it does not always mean method that caused it to be thrown 
	 *                    was not executed.This means the programmer should not 
	 *                    make any assumptions about the state of transactions based 
	 *                    on the exceptions.
	 *                    
	 *                    The getNextException() method returns the next SQLException 
	 *                    object chained to the exsiting SQLException Object and null 
	 *                    if no Object is chained
	 *                    
	 *                    (Refer JDBC 2.0 API Tutorial and Reference Section 36.1)
	 *                    
	 * @test_Strategy:    SQLException object is generated by executing an incomplete 
	 *                    SQL Statement and using setNextException method a SQLException 
	 *                    object is chained. This is checked using the getNextException 
	 *                    method which should return a instanceof SQLException object.
	 */
	public void testGetNextException() throws Fault 
	{
		try
		{
			String sErrorQuery = sqlp.getProperty("Error_Query");
			stmt.executeQuery(sErrorQuery);
		}
		catch(SQLException b)
		{
			isThrown = true;
			b.setNextException(new SQLException(sReason,sSqlState,vendorCode));
			if((b.getNextException() instanceof java.sql.SQLException))
			{
				logMsg("getNextException() method returns SQLException object");
				logMsg("String is " + b.getMessage());
			}
			else
			{
				logErr("getNextException() mMethod doesnot returns SQLException object");
				throw new Fault("call to getNextException() method fails");
			}
		}
		catch(Exception ex)
		{
			logErr("UnexpectedException " + ex.getMessage());
			throw new Fault("call to getNextException() method fails");
		}
	
		if(!isThrown)
		{
			logErr("SQLException not thrown" );
			throw new Fault("call to getNextException() method fails");
		}
	}


	/*
	 * @testName:         testSetNextException
	 * @assertion:        The class SQLException provides information about errors 
	 *                    in accessing the database.When an SQLException is thrown 
	 *                    it does not always mean method that caused it to be thrown 
	 *                    was not executed.This means the programmer should not make 
	 *                    any assumptions about the state of transactions based on 
	 *                    the exceptions.
	 *                    
	 *                    The setNextException(SQLException next) method sets the 
	 *                    next SQLException as the next element in the chain of 
	 *                    Exceptions.
	 *                    
	 *                    (Refer JDBC 2.0 API Tutorial and Reference Section 36.1)
	 *                    
	 * @test_Strategy:    SQLException object is obtained by executing a incomplete 
	 *                    SQLStatement and setNextException() method on the object 
	 *                    will set a chain of SQLException on that object which can 
	 *                    be checked by using getNextException() method.
	 *
	 */
	public void testSetNextException() throws Fault 
	{
		try
		{
			String sErrorQuery = sqlp.getProperty("Error_Query");
			stmt.executeQuery(sErrorQuery);
		}
		catch(SQLException b)
		{
			isThrown = true;
			b.setNextException(new SQLException(sReason,sSqlState,vendorCode));
			if((b.getNextException() instanceof java.sql.SQLException))
			{
				logMsg("setNextException() method sets SQLException object");
				logMsg("String is " + b.getMessage());
			}
			else
			{
				logErr("setNextException() Method doesnot sets SQLException object");
				throw new Fault("call to setNextException() method fails");
			}
		}
		catch(Exception ex)
		{
			logErr("UnexpectedException " + ex.getMessage());
			throw new Fault("call to setNextException() method fails");
		}
		if(!isThrown)
		{
			logErr("SQLException not thrown" );
			throw new Fault("call to setNextException() method fails");
		}
	}


	/* cleanup */
	public void  cleanup() throws Fault
	{
		try
		{
			//conn.setAutoCommit(true);
			stmt.close();
			dbSch.destroyData(conn);
			// Close the database 
			dbSch.dbUnConnect(conn);
			logMsg("Cleanup ok;");
		}
		catch (Exception e)
		{
			logErr("An error occurred while closing the database connection");
		}
	}
}
