/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2016 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
package org.pentaho.di.core.util;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Undefined;
import org.pentaho.di.compatibility.Value;
import org.pentaho.di.core.row.ValueMetaInterface;
import java.math.BigDecimal;
import java.util.Date;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*;
/**
* A set of tests for {@linkplain JavaScriptUtils} class.
*
* @author Andrey Khayrutdinov
*/
public class JavaScriptUtilsTest {
private static final String UNDEFINED = Undefined.class.getName();
private static final String JAVA_OBJECT = NativeJavaObject.class.getName();
private static final String NATIVE_NUMBER = "org.mozilla.javascript.NativeNumber";
private static Context ctx;
private static ScriptableObject scope;
@BeforeClass
public static void setUp() throws Exception {
ctx = Context.enter();
scope = ctx.initStandardObjects();
}
@AfterClass
public static void tearDown() throws Exception {
scope = null;
ctx = null;
Context.exit();
}
private static Scriptable getIntValue() {
Value value = new Value();
value.setValue( 1 );
return Context.toObject( value, scope );
}
private static Scriptable getDoubleValue() {
Value value = new Value();
value.setValue( 1.0 );
return Context.toObject( value, scope );
}
// jsToNumber tests
@Test
public void jsToNumber_Undefined() throws Exception {
assertNull( JavaScriptUtils.jsToNumber( null, UNDEFINED ) );
}
@Test
public void jsToNumber_NativeJavaObject_Double() throws Exception {
Scriptable value = getDoubleValue();
Number number = JavaScriptUtils.jsToNumber( value, JAVA_OBJECT );
assertEquals( 1.0, number.doubleValue(), 1e-6 );
}
@Test
public void jsToNumber_NativeJavaObject_Int() throws Exception {
Scriptable value = getIntValue();
Number number = JavaScriptUtils.jsToNumber( value, JAVA_OBJECT );
assertEquals( 1.0, number.doubleValue(), 1e-6 );
}
@Test
public void jsToNumber_NativeNumber() throws Exception {
Scriptable value = Context.toObject( 1.0, scope );
Number number = JavaScriptUtils.jsToNumber( value, NATIVE_NUMBER );
assertEquals( 1.0, number.doubleValue(), 1e-6 );
}
@Test
public void jsToNumber_JavaNumber() throws Exception {
Number number = JavaScriptUtils.jsToNumber( 1.0, Double.class.getName() );
assertEquals( 1.0, number.doubleValue(), 1e-6 );
}
// jsToInteger tests
@Test
public void jsToInteger_Undefined() throws Exception {
assertNull( JavaScriptUtils.jsToInteger( null, Undefined.class ) );
}
@Test
public void jsToInteger_NaturalNumbers() throws Exception {
Number[] naturalNumbers = new Number[] { (byte) 1, (short) 1, 1, (long) 1 };
for ( Number number : naturalNumbers ) {
assertEquals( Long.valueOf( 1 ), JavaScriptUtils.jsToInteger( number, number.getClass() ) );
}
}
@Test
public void jsToInteger_String() throws Exception {
assertEquals( Long.valueOf( 1 ), JavaScriptUtils.jsToInteger( "1", String.class ) );
}
@Test( expected = NumberFormatException.class )
public void jsToInteger_String_Unparseable() throws Exception {
JavaScriptUtils.jsToInteger( "q", String.class );
}
@Test
public void jsToInteger_Double() throws Exception {
assertEquals( Long.valueOf( 1 ), JavaScriptUtils.jsToInteger( 1.0, Double.class ) );
}
@Test
public void jsToInteger_NativeJavaObject_Int() throws Exception {
Scriptable value = getIntValue();
assertEquals( Long.valueOf( 1 ), JavaScriptUtils.jsToInteger( value, NativeJavaObject.class ) );
}
@Test
public void jsToInteger_NativeJavaObject_Double() throws Exception {
Scriptable value = getDoubleValue();
assertEquals( Long.valueOf( 1 ), JavaScriptUtils.jsToInteger( value, NativeJavaObject.class ) );
}
@Test
public void jsToInteger_Other_Int() throws Exception {
assertEquals( Long.valueOf( 1 ), JavaScriptUtils.jsToInteger( 1, getClass() ) );
}
@Test( expected = NumberFormatException.class )
public void jsToInteger_Other_String() throws Exception {
JavaScriptUtils.jsToInteger( "qwerty", getClass() );
}
// jsToString tests
@Test
public void jsToString_Undefined() throws Exception {
assertEquals( "null", JavaScriptUtils.jsToString( null, UNDEFINED ) );
}
@Test
public void jsToString_NativeJavaObject_Int() throws Exception {
assertEquals( "1", JavaScriptUtils.jsToString( getIntValue(), JAVA_OBJECT ).trim() );
}
@Test
public void jsToString_NativeJavaObject_Double() throws Exception {
assertEquals( "1.0", JavaScriptUtils.jsToString( getDoubleValue(), JAVA_OBJECT ).trim() );
}
@Test
public void jsToString_String() throws Exception {
assertEquals( "qwerty", JavaScriptUtils.jsToString( "qwerty", String.class.getName() ) );
}
// jsToDate tests
@Test
public void jsToDate_Undefined() throws Exception {
assertNull( JavaScriptUtils.jsToDate( null, UNDEFINED ) );
}
@Test
public void jsToDate_NativeDate() throws Exception {
Date date = new Date( 1 );
Scriptable value = ctx.newObject( scope, "Date", new Object[] { date.getTime() } );
assertEquals( date, JavaScriptUtils.jsToDate( value, "org.mozilla.javascript.NativeDate" ) );
}
@Test
public void jsToDate_NativeJavaObject() throws Exception {
Scriptable value = getIntValue();
assertEquals( new Date( 1 ), JavaScriptUtils.jsToDate( value, JAVA_OBJECT ) );
}
@Test
public void jsToDate_Double() throws Exception {
assertEquals( new Date( 1 ), JavaScriptUtils.jsToDate( 1.0, Double.class.getName() ) );
}
@Test
public void jsToDate_String() throws Exception {
assertEquals( new Date( 1 ), JavaScriptUtils.jsToDate( "1.0", String.class.getName() ) );
}
@Test( expected = NumberFormatException.class )
public void jsToDate_String_Unparseable() throws Exception {
JavaScriptUtils.jsToDate( "qwerty", String.class.getName() );
}
// jsToBigNumber tests
@Test
public void jsToBigNumber_Undefined() throws Exception {
assertNull( JavaScriptUtils.jsToBigNumber( null, UNDEFINED ) );
}
@Test
public void jsToBigNumber_NativeNumber() throws Exception {
Scriptable value = Context.toObject( 1.0, scope );
BigDecimal number = JavaScriptUtils.jsToBigNumber( value, NATIVE_NUMBER );
assertEquals( 1.0, number.doubleValue(), 1e-6 );
}
@Test
public void jsToBigNumber_NativeJavaObject_Int() throws Exception {
assertEquals( 1.0, JavaScriptUtils.jsToBigNumber( getIntValue(), JAVA_OBJECT ).doubleValue(), 1e-6 );
}
@Test
public void jsToBigNumber_NativeJavaObject_Double() throws Exception {
assertEquals( 1.0, JavaScriptUtils.jsToBigNumber( getDoubleValue(), JAVA_OBJECT ).doubleValue(), 1e-6 );
}
@Test
public void jsToBigNumber_NativeJavaObject_BigDecimal() throws Exception {
Value value = new Value();
value.setValue( BigDecimal.ONE );
Scriptable object = Context.toObject( value, scope );
assertEquals( 1.0, JavaScriptUtils.jsToBigNumber( object, JAVA_OBJECT ).doubleValue(), 1e-6 );
}
@Test
public void jsToBigNumber_NaturalNumbers() throws Exception {
Number[] naturalNumbers = new Number[] { (byte) 1, (short) 1, 1, (long) 1 };
for ( Number number : naturalNumbers ) {
assertEquals( 1.0, JavaScriptUtils.jsToBigNumber( number, number.getClass().getName() ).doubleValue(), 1e-6 );
}
}
@Test
public void jsToBigNumber_Double() throws Exception {
assertEquals( 1.0, JavaScriptUtils.jsToBigNumber( 1.0, Double.class.getName() ).doubleValue(), 1e-6 );
}
@Test
public void jsToBigNumber_String() throws Exception {
assertEquals( 1.0, JavaScriptUtils.jsToBigNumber( "1", String.class.getName() ).doubleValue(), 1e-6 );
}
@Test( expected = RuntimeException.class )
public void jsToBigNumber_UnknownClass() throws Exception {
JavaScriptUtils.jsToBigNumber( "1", "qwerty" );
}
// convertFromJs tests
@Test( expected = RuntimeException.class )
public void convertFromJs_TypeNone() throws Exception {
JavaScriptUtils.convertFromJs( null, ValueMetaInterface.TYPE_NONE, "qwerty" );
}
@Test
public void convertFromJs_TypeBoolean() throws Exception {
Object o = new Object();
Object o2 = JavaScriptUtils.convertFromJs( o, ValueMetaInterface.TYPE_BOOLEAN, "qwerty" );
assertEquals( o, o2 );
}
@Test
public void convertFromJs_TypeBinary() throws Exception {
byte[] bytes = new byte[] { 0, 1 };
Object converted = JavaScriptUtils.convertFromJs( bytes, ValueMetaInterface.TYPE_BINARY, "qwerty" );
assertThat( converted, is( instanceOf( byte[].class ) ) );
assertArrayEquals( bytes, (byte[]) converted );
}
}