/* 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.*;
import netscape.javascript.*;

/**
 *  From JavaScript, call a static 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.
 *
 *  If JavaScript passes a value that is larger than th MAX_VALUE of that type,
 *  expect a JSException.
 *
 *  <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_016 extends LiveConnectTest {
    public DataTypes_016() {
        super();
    }

    public static void main( String[] args ) {
        DataTypes_016 test = new DataTypes_016();
        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.0", "3.14159", "-1.159", "-0.01", "0.1",
                        "4294967295", "4294967296", "-4294967296", 
                        "2147483647", "2147483648",  "-2147483648" };

    public boolean checkByte( String v ) {
        double max = new Double( Byte.MAX_VALUE ).doubleValue();
        double min = new Double( Byte.MIN_VALUE ).doubleValue();
        double value = new Double(v).doubleValue();
        
        if ( value >= min && value <= max )
            return true;
        return false;
    }
    public boolean checkInteger( String v ) {
        double max = new Double(Integer.MAX_VALUE ).doubleValue();
        double min = new Double( Integer.MIN_VALUE ).doubleValue();
        double value = new Double(v).doubleValue();
        
        if ( value >= min && value <= max )
            return true;
        return false;
    }
    public boolean checkShort( String v ) {
        double max = new Double( Short.MAX_VALUE ).doubleValue();
        double min = new Double( Short.MIN_VALUE ).doubleValue();
        double value = new Double(v).doubleValue();
        if ( value >= min && value <= max )
            return true;
        return false;
    }
    public boolean checkFloat( String v ) {
        double max = new Double( Float.MAX_VALUE ).doubleValue();
        double min = new Double( Float.MIN_VALUE ).doubleValue();
        double value = new Double(v).doubleValue();        
        if ( value >= min && value <= max )
            return true;
        return false;
    }
    public boolean checkLong( String v ) {
        double max = new Double( Long.MAX_VALUE ).doubleValue();
        double min = new Double( Long.MIN_VALUE ).doubleValue();
        double value = new Double(v).doubleValue();        
        if ( value >= min && value <= max )
            return true;
        return false;
    }
    public boolean checkDouble( String v ) {
        double max = new Double( Double.MAX_VALUE ).doubleValue();
        double min = new Double( Double.MIN_VALUE ).doubleValue();
        double value = new Double(v).doubleValue();        
        if ( value >= min && value <= max )
            return true;
        return false;
    }

    public void    executeTest() {
        for ( int i = 0; i < jsVals.length; i++ ) {
            doSetterTest( "DT.staticSetDouble", 
                          jsVals[i], 
                          "DT.staticGetDouble", 
                          "DT.PUB_STATIC_DOUBLE",
                          (Number) new Double(jsVals[i]),
                          (Number) new Double(DataTypeClass.PUB_STATIC_DOUBLE),
                          true );

            doSetterTest( "DT.staticSetByte", 
                          jsVals[i], 
                          "DT.staticGetByte", 
                          "DT.PUB_STATIC_BYTE",
                          (Number) new Byte(new Double(jsVals[i]).byteValue()),
                          (Number) new Byte(DataTypeClass.PUB_STATIC_BYTE),
                          checkByte( jsVals[i]) );
                      
            doSetterTest( "DT.staticSetShort",
                          jsVals[i], 
                          "DT.staticGetShort", 
                          "DT.PUB_STATIC_SHORT",
                          (Number) new Short(new Double(jsVals[i]).shortValue()),
                          (Number) new Short(DataTypeClass.PUB_STATIC_SHORT),
                          checkShort( jsVals[i]) );

            doSetterTest( "DT.staticSetInteger",
                          jsVals[i], 
                          "DT.staticGetInteger", 
                          "DT.PUB_STATIC_INT",
                          (Number) new Integer(new Double(jsVals[i]).intValue()),
                          (Number) new Integer(DataTypeClass.PUB_STATIC_INT),
                          checkInteger( jsVals[i]) );

            doSetterTest( "DT.staticSetFloat",
                          jsVals[i], 
                          "DT.staticGetFloat", 
                          "DT.PUB_STATIC_FLOAT",
                          (Number) new Float(new Double(jsVals[i]).floatValue()),
                          (Number) new Float(DataTypeClass.PUB_STATIC_FLOAT),
                          true );

            doSetterTest( "DT.staticSetLong",
                          jsVals[i], 
                          "DT.staticGetLong", 
                          "DT.PUB_STATIC_LONG",
                          (Number) new Long(new Double(jsVals[i]).longValue()),
                          (Number) new Long(DataTypeClass.PUB_STATIC_LONG),
                          checkLong( jsVals[i]) );
        }                                      
    }
    /**
     *  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
     *  @param inRange  whether or not the value is in range for the particular 
     *  type.  if not, expect a JSExcedeption
     */
    public void    doSetterTest( String setter, String jsValue, String getter, 
                                String field, Number eResult, Number fieldValue,
                                boolean inRange ) 
    {
        String setMethod = setter +"(" + jsValue +");";
        String getMethod = getter + "();";
        
        Double expectedResult = (inRange) ? 
                                new Double( eResult.doubleValue() ) : 
                                new Double(fieldValue.doubleValue());
        Double getterResult=null;
        Object fieldResult=null;
        
        
        String setResult = "no exception";
        String expectedSetResult = setResult;
        
        try    {
            expectedSetResult = (inRange) ? "no exception" :
                Class.forName("netscape.javascript.JSException").getName();
        
            // From JavaScript, call the setter.  will throw exception if
            // ! inRange
            global.eval( setMethod );
        } catch ( Exception e ) {
            setResult = e.getClass().getName();
            file.exception = e.toString();
        } finally {
            addTestCase(
                setMethod,
                expectedSetResult,
                setResult,
                file.exception );
        }
        
        try {
            // 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();
            fieldResult = e.getClass().getName();
        } finally {
            addTestCase(
                "[value: " + getterResult +"; expected: " + expectedResult +"] "+        
                setMethod + "( " + expectedResult +").equals(" + getterResult +")",
                "true",
                expectedResult.equals(getterResult) +"",
                file.exception );
            
            addTestCase(
                "[value: " + fieldResult +"; expected: " + expectedResult +"] "+
                setMethod + "(" + expectedResult +").equals(" + fieldResult +")",
                "true",
                expectedResult.equals(fieldResult) +"",
                file.exception );
        }            
    }
 }
 