/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


package	com.netscape.javascript.qa.liveconnect.datatypes;

import com.netscape.javascript.qa.liveconnect.*;

/**
 *	From JavaScript, call an instance Java method that takes arguments.	 The
 *	argument should	be correctly cast to the type expected by the Java
 *	method.
 *
 *	<p>
 *
 *	This test calls	a setter method.  The test is verified by calling the
 *	getter method, and verifying that the value	is the setter worked
 *	correctly.
 *
 *	<p>
 *
 *	This tests passing JavaScript values as	arguments of the following types:
 *	double,	byte, short, long, float, int.
 *
 *	<p>
 *	Still need tests for the following types:  String, Object, char, JSObject
 *
 *	@see com.netscape.javascript.qa.liveconnect.DataTypesClass
 *	@see netscape.javascript.JSObject
 *
 *	@author	christine m	begle
 */

public class DataTypes_017 extends LiveConnectTest {
	public DataTypes_017() {
		super();
	}

	public static void main( String[] args ) {
		DataTypes_017 test = new DataTypes_017();
		test.start();
	}

	public void	setupTestEnvironment() {
		super.setupTestEnvironment();
		
		global.eval( "var DT = "+
			"Packages.com.netscape.javascript.qa.liveconnect.DataTypeClass");
		global.eval( "var dt = new DT();" );
	}

	// XXX need	to add special cases:  NaN,	Infinity, -Infinity, but won't
	// work	in this	framework

	String jsVals[]	= {	"0", "3.14159",	"-1.159", "-0.01", "0.1",
						"4294967295", "4294967296",	"-4294967296",
						"2147483647", "2147483648",	 "-2147483648" };

    /**
     *  call the setter test with 5 values:
     *  <ul>
     *  <li>    string value to call setters / getters with
     *  <li>    method to set the value
     *  <li>    method to get the value
     *  <li>    field that returns the value
     *  <li>    expected result of getter, field
     *  <li>    whether or not an exception gets thrown
     *  </ul>
     *
     *  The rules for conversion:
     *  <ul>
     *  <li>    if the setter sets the value out of the range, return an exception
     *  <li>    if the value is in range, transform value to Math.floor( value )
     *  <li>    NaN returns 0.
     *  </ul>
     *  
     *
     *
     */
     
    public void	executeTest() {
        for ( int i = 0; i < jsVals.length; i++ ) {
            doSetterTest(jsVals[i],
                         "dt.setDouble", "dt.getDouble", "dt.PUB_DOUBLE",
                         (new Double(jsVals[i]).doubleValue() > Double.MAX_VALUE 
                          ? (Object) EXCEPTION
                          : (new Double(jsVals[i]).doubleValue() < Double.MIN_VALUE
                             ? (Object) EXCEPTION : new Double( jsVals[i] ))
                          ));
						  
/*
			doSetterTest( "dt.setByte",
						  jsVals[i],
						  "dt.getByte",
						  "dt.PUB_BYTE",
						  (Number) new Byte(new Float(jsVals[i]).byteValue()),
						  new Float	(Byte.MAX_VALUE),
						  new Float	(Byte.MIN_VALUE));
						  
			doSetterTest( "dt.setShort",
						  jsVals[i],
						  "dt.getShort",
						  "dt.PUB_SHORT",
						  (Number) new Short(new Double(jsVals[i]).shortValue()),
						  new Float	(Short.MAX_VALUE),
						  new Float	(Short.MIN_VALUE ));

			doSetterTest( "dt.setInteger",
						  jsVals[i],
						  "dt.getInteger",
						  "dt.PUB_INT",
						  (Number) new Integer(new Double(jsVals[i]).intValue()),
						  new Float	(Integer.MAX_VALUE),
						  new Float	(Integer.MIN_VALUE));

			doSetterTest( "dt.setFloat",
						  jsVals[i],
						  "dt.getFloat",
						  "dt.PUB_FLOAT",
						  (Number) new Float(new Double(jsVals[i]).floatValue()),
						  new Float	(Float.MAX_VALUE), 
						  new Float	(Float.MIN_VALUE));


			doSetterTest( "dt.setLong",
						  jsVals[i],
						  "dt.getLong",
						  "dt.PUB_LONG",
						  (Number) new Long(new	Double(jsVals[i]).longValue()),
						  new Float	(Long.MAX_VALUE),
						  new Float	(Long.MIN_VALUE));
*/						  
		}

	}
	/**
	 *	This tests calls a Java	setter method from JavaScript.	It verifies
	 *	that the setter	was	called properly	in two ways:  by checking the
	 *	return value of	the	getter method, and by checking the value of	the
	 *	public field that was set.
	 *
	 *	@param setter	java method	that takes an argument,	and	sets a value
	 *	@param jsValue	JavaScript value that is passed	to the setter
	 *	@param getter	java method	that returns the value set by setter
	 *	@param field	java field that	setter changed
	 *	@param eResult	expected result, which should be of	some Number	type
	 */

    public void	doSetterTest(String jsValue, String setter, String getter,
                             String field, Object eResult )
    {
        String setMethod = setter +"(" + jsValue +");";
        String getMethod = getter +	"();";
        String setterResult = "No exception thrown";
        Double getterResult = null;
        Double fieldResult = null;
        Object expectedResult = null;
        boolean eq = false;
        
        try {
            eq = eResult.getClass().equals(Class.forName("java.lang.String"));
        }
        catch (ClassNotFoundException e) {
            addTestCase (setMethod + " driver error.",
                         "very", "bad", file.exception);
        }
        
        if (eq) {
            try {
                global.eval( setMethod );
            } catch ( Exception e ) {
                setterResult = EXCEPTION;
                file.exception = e.toString();
                e.printStackTrace();
            } finally {
                addTestCase(setMethod +" should throw a JSException",
                            EXCEPTION,
                            setterResult,
                            file.exception );
            }
        } else {    
		
            try	{
                // From	JavaScript,	call the setter
                global.eval( setMethod );
                
                // From	JavaScript,	call the getter
                getterResult = (Double)	global.eval( getMethod );
                
                // From	JavaSript, access the field
                fieldResult	= (Double) global.eval(	field );
                
            } catch	( Exception	e )	{
                e.printStackTrace();
                file.exception = e.toString();
            } finally {
                addTestCase("[value: " + getterResult +"; expected:	" +
                            expectedResult +"] "+ setMethod + getMethod +
                            "( " + expectedResult + ").equals(" + 
                            getterResult +")", "true",
                            expectedResult.equals(getterResult)	+ "",
                            file.exception);

                addTestCase("[value: " + fieldResult + "; expected: " +
                            expectedResult + "] " + setMethod + field +
                            "; (" + expectedResult +").equals(" +
                            fieldResult +")", "true",
                            expectedResult.equals(fieldResult) +"",
                            file.exception );
            }
        }   
    }
	
    String EXCEPTION = "JSException expected";
}
