/* Part of SWI-Prolog Author: Jan Wielemaker E-mail: J.Wielemaker@vu.nl WWW: http://www.swi-prolog.org Copyright (c) 2006-2018, Paul Singleton VU University Amsterdam 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 OWNER 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. */ :- module(test_jpl, [ test_jpl/0, run_tests/0, run_tests/1 ]). % ensure we get the local copies :- asserta(user:file_search_path(foreign, '.')). :- asserta(user:file_search_path(jpl_examples, 'examples/prolog')). :- asserta(user:file_search_path(jar, '.')). :- asserta(user:file_search_path(jar, foreign('src/main/java'))). :- asserta(user:file_search_path(jar, foreign('.'))). :- asserta(user:file_search_path(library, '.')). :- asserta(user:file_search_path(library, '../plunit')). % paths for Prolog embedded in Java under CTest :- asserta(user:file_search_path(library, '../../../packages/jpl')). :- asserta(user:file_search_path(library, '../../../packages/plunit')). :- use_module(library(jpl)). :- use_module(library(plunit)). % Using cmake location :- jpl:add_search_path('CLASSPATH', 'src/test/java/jpltest.jar'). % For before cmake :- jpl:add_search_path('CLASSPATH', 'jpltest.jar'). test_jpl :- run_tests( [ jpl ,identifier_chars ,java_id ,java_type_id ,messy_dollar_split ,jpl_classname_without_dollar ,jpl_classname_with_dollar ,jpl_entityname ,jpl_findclass_descriptor ,jpl_method_descriptor ,compare_old_and_new_entityname ,compare_old_and_new_findclass_descriptor ,compare_both_field_descriptors ,jpl_type_to_classname ,jpl_classname_to_type ,safe_type_to_classname ]). % --- % Switch these on for some output in the logfile (build/Testing/Temporary/LastTest.log) % --- % :- debug(identifier_chars). % :- debug(java_id). % :- debug(run_both). % :- debug(dcg_mangle). :- begin_tests(jpl). test( exception_jref_1, [ true(( E = error(java_exception(JRef), 'java.lang.IllegalArgumentException'), blob(JRef, jref) )) ] ) :- catch(jpl_new('java.util.Date', [never], _), E, true). test( array_to_from_terms_1, [ true( Terms1 == Terms2 ) ] ) :- Terms1 = [x,[1,a,7,[y,z]],k,[]], jpl_terms_to_array(Terms1, JRef), jpl_array_to_terms(JRef, Terms2). test( ancestor_types_1, [ true( Ts == [class([org,jpl7],['Term']),class([java,lang],['Object'])] ) ] ) :- jpl:jpl_type_to_ancestor_types(class([org,jpl7],['Atom']), Ts). test( call_array_equals_1, [ setup(( jpl_new(array(byte), [4,5,6], A1), jpl_new(array(byte), [4,5,6], A2) )) ] ) :- jpl_call(A1, equals, [A2], @(false)). test( call_array_equals_2, [ setup(( jpl_new(array(byte), [4,5,6], A1) )) ] ) :- jpl_call(A1, equals, [A1], @(true)). test( call_array_hashcode_1, [ setup(( jpl_new(array(byte), [4,5,6], A) )), true(( integer(H) )) ] ) :- jpl_call(A, hashCode, [], H). test( call_array_hashcode_2, [ setup(( jpl_new(array(byte), [4,5,6], A1), jpl_new(array(byte), [4,5,6], A2) )), true(( H1 \== H2 )) ] ) :- jpl_call(A1, hashCode, [], H1), jpl_call(A2, hashCode, [], H2). test( call_array_to_string_1, [ setup(( jpl_new(array(byte), [4,5,6], A) )), true(( atom_codes(S, [0'[, 0'B | _]) )) ] ) :- jpl_call(A, toString, [], S). test( call_instance_param_cyclic_term_1, [ setup(( T = f(T), jpl_new('org.jpl7.Test', [], Test) )), throws( error(type_error(acyclic,T),context(jpl_call/4,_)) ) ] ) :- jpl_call(Test, methodInstanceTerm, [{T}], @(true)). testX( call_instance_param_cyclic_term_2, [ setup(( T = f(T), jpl_new('org.jpl7.Test', [], Test) )), throws( error(type_error(acyclic,_),context(jpl_call/4,_)) ) ] ) :- jpl_call(Test, methodInstanceTerm, [{T}], @(true)). test( call_method_static_array_1, [ setup(( jpl_new(array(int), [3,4,5], IntArray) )) ] ) :- jpl_call('org.jpl7.Test', methodStaticArray, [IntArray], 'int[]'). test( call_method_static_array_2, [ setup(( jpl_new(array(byte), [3,4,5], ByteArray) )), throws( error( type_error(method_params,[ByteArray]), context(jpl_call/4,_) ) ) ] ) :- jpl_call('org.jpl7.Test', methodStaticArray, [ByteArray], _). test( call_static_param_cyclic_term_1, [ setup(( T = f(T) )), throws( error(type_error(acyclic,T),context(jpl_call/4,_)) ) ] ) :- jpl_call('org.jpl7.Test', methodStaticTerm, [{T}], @(true)). test( call_class_get_name_1, [ setup(( ClassName = 'java.lang.Integer', jpl_classname_to_class(ClassName, ClassObject) )), true(( ClassName == ClassName2 )) ] ) :- jpl_call(ClassObject, getName, [], ClassName2). test( call_get_array_bad_field_name_1, [ setup(( jpl_new(array(byte), 5, A), FieldName = colour )), throws( error(domain_error(array_field_name,FieldName),context(jpl_get/3,_)) ) ] ) :- jpl_get(A, FieldName, _). test( call_get_array_bad_fspec_1, [ setup(( jpl_new(array(byte), 5, A), Fspec = poo(77) )), throws( error(type_error(array_lookup_spec,Fspec),context(jpl_get/3,_)) ) ] ) :- jpl_get(A, Fspec, _). test( call_get_array_bad_index_range_1, [ setup(( jpl_new(array(byte), 5, A) )), throws( error(domain_error(array_index_range,(-1)-2),context(jpl_get/3,_)) ) ] ) :- jpl_get(A, (-1)-2, _). test( call_get_array_bad_index_range_2, [ setup(( jpl_new(array(byte), 5, A) )), throws( error(domain_error(array_index_range,10-12),context(jpl_get/3,_)) ) ] ) :- jpl_get(A, 10-12, _). test( call_get_array_bad_index_range_3, [ setup(( jpl_new(array(byte), 5, A) )), throws( error(domain_error(array_index_range,3-33),context(jpl_get/3,_)) ) ] ) :- jpl_get(A, 3-33, _). test( call_get_array_bad_index_range_4, [ setup(( jpl_new(array(byte), 5, A) )), throws( error(type_error(array_index_range,this-that),context(jpl_get/3,_)) ) ] ) :- jpl_get(A, this-that, _). test( get_array_element_1, [ setup(( jpl_new(array(byte), [4,5,6,7,8], A) )), true(( 7 == V )) ] ) :- jpl_get(A, 3, V). % should bind V = 7 i.e. a[3] i.e. the fourth array element counting from zero test( get_array_elements_1, [ setup(( jpl_new(array(byte), [4,5,6,7,8], A) )), true(( [5,6] == V )) ] ) :- jpl_get(A, 1-2, V). % should bind V = [5,6] i.e. a[1-2] i.e. the 2nd to 3rd array elements counting from zero test( get_array_length_1, [ setup(( Len1 is 5, jpl_new(array(byte), Len1, A) )), true(( Len1 == Len2 )) ] ) :- jpl_get(A, length, Len2). % should bind Len2 to the (integer) value of Len1 test( get_array_negative_index_1, [ setup(( BadIndex is -1, jpl_new(array(byte), 5, A) )), throws( error(domain_error(array_index,BadIndex), context(jpl_get/3,_)) ) ] ) :- jpl_get(A, BadIndex, _). test( get_array_unbound_fspec_1, [ setup(( jpl_new(array(byte), 5, A) )), throws( error(instantiation_error,context(jpl_get/3,_)) ) ] ) :- jpl_get(A, _, _). test( get_field_static_boolean_1, [ true(( V == @(false) )) ] ) :- jpl_get('org.jpl7.Test', fieldStaticBoolean1, V). test( get_field_static_boolean_2, [ true(( V == @(true) )) ] ) :- jpl_get('org.jpl7.Test', fieldStaticBoolean2, V). test( get_field_static_char_1, [ true(( V == 0 )) ] ) :- jpl_get('org.jpl7.Test', fieldStaticChar1, V). test( get_field_static_char_2, [ true(( V == 65535 )) ] ) :- jpl_get('org.jpl7.Test', fieldStaticChar2, V). test( get_field_instance_byte_2, [ setup(( jpl_new('org.jpl7.Test', [], Test) )), true(( V == -1 )) ] ) :- jpl_get(Test, fieldInstanceByte2, V). test( list_to_array_1, [ true(( Type == array(byte) )) ] ) :- jpl_list_to_array([1,2,3], A), jpl_object_to_type(A, Type). test( method_static_byte_1, [ throws( error( type_error(method_params,[-129]), context(jpl_call/4,_) ) ) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoByte, [-129], _). test( method_static_echo_boolean_1, [ setup(( jpl_false(V1) )), true(( V1 == V2 )) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoBoolean, [V1], V2). test( method_static_echo_boolean_2, [ setup(( jpl_true(V1) )), true(( V1 == V2 )) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoBoolean, [V1], V2). test( method_static_echo_char_1, [ setup(( V1 = 0 )), true(( V1 == V2 )) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoChar, [V1], V2). test( method_static_echo_char_2, [ setup(( V1 = 65535 )), true(( V1 == V2 )) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoChar, [V1], V2). test( method_static_char_3, [ setup(( V1 = -1 )), throws( error( type_error(method_params,[V1]), context(jpl_call/4,_) ) ) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoChar, [V1], _). test( method_static_char_4, [ setup(( V1 = 1.0 )), throws( error( type_error(method_params,[V1]), context(jpl_call/4,_) ) ) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoChar, [V1], _). test( method_static_char_5, [ setup(( V1 = a )), throws( error( type_error(method_params,[V1]), context(jpl_call/4,_) ) ) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoChar, [V1], _). test( method_static_echo_double_1, [ setup(( V1 = 1.5 )), true(( V1 == V2 )) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoDouble, [V1], V2). test( method_static_echo_double_2, [ setup(( V1 = 2 )), true(( V2 =:= float(V1) )) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoDouble, [V1], V2). test( method_static_echo_double_3, [ setup(( ( current_prolog_flag(bounded, true) -> current_prolog_flag(max_integer, V1) ; V1 is 2**63-1 ), V2b is float(V1) )), true(( V2 == V2b )) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoDouble, [V1], V2). test( method_static_echo_float_1, [ setup(( V1 = 1.5 )), true(( V1 == V2 )) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoFloat, [V1], V2). test( method_static_echo_float_2, [ setup(( V1 is 2, V2b is float(V1) )), true(( V2 == V2b )) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoFloat, [V1], V2). test( method_static_echo_float_3, [ setup(( ( current_prolog_flag(bounded, true) -> current_prolog_flag(max_integer, V1) ; V1 is 2**63-1 % was 2**99 ), V2b is float(V1) )), true(( V2 == V2b )) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoFloat, [V1], V2). test( method_static_echo_float_4, [ blocked('we do not yet widen unbounded integers to floats or doubles'), setup(( ( current_prolog_flag(bounded, true) -> current_prolog_flag(max_integer, V1) ; V1 is 2**99 % an unbounded integer ), V2b is float(V1) )), true(( V2 == V2b )) ] ) :- jpl_call('org.jpl7.Test', methodStaticEchoFloat, [V1], V2). test( new_abstract_class_1, [ setup(( Classname = 'java.util.Dictionary' )), throws( error( type_error(concrete_class,Classname), context(jpl_new/3,_) ) ) ] ) :- jpl_new(Classname, [], _). test( new_array_boolean_from_val_1, [ setup(( jpl_false(V) )), true(( V == V2 )) ] ) :- jpl_call('org.jpl7.Test', newArrayBooleanFromValue, [V], A), jpl_get(A, 0, V2). test( new_array_double_from_val_1, [ setup(( V is 1.5 )), true(( V == V2 )) ] ) :- jpl_call('org.jpl7.Test', newArrayDoubleFromValue, [V], A), jpl_get(A, 0, V2). test( new_array_float_from_val_1, [ setup(( V is 1.5 )), true(( V == V2 )) ] ) :- jpl_call('org.jpl7.Test', newArrayFloatFromValue, [V], A), jpl_get(A, 0, V2). test( new_interface_1, [ setup(( Classname = 'java.util.Enumeration' )), throws( error( type_error(concrete_class,Classname), context(jpl_new/3,_) ) ) ] ) :- jpl_new(Classname, [], _). test( new_param_cyclic_term_1, [ setup(( T = f(T) )), throws( error( type_error(acyclic,T), context(jpl_new/3,_) ) ) ] ) :- jpl_new('org.jpl7.Test', [{T}], _). test( prolog_calls_java_calls_prolog_1, [ true(( V == @(true) )) ] ) :- jpl_new('org.jpl7.Query', ['4 is 2+2'], Q), jpl_call(Q, hasSolution, [], V). test( set_array_element_cyclic_term_1, [ setup(( T = f(T), jpl_new(array(class([org,jpl7],['Test'])), 5, A) )), throws( error( type_error(acyclic,T), context(jpl_set/3,_) ) ) ] ) :- jpl_set(A, 0, {T}). test( set_array_elements_bad_type_1, [ setup(( jpl_new(array(byte), 3, A) )), throws( error( type_error(array(byte),[128]), context(jpl_set/3,_) ) ) ] ) :- jpl_set(A, 0, 128). test( set_array_length_1, [ setup(( jpl_new(array(byte), 6, A) )), throws( error( permission_error(modify,final_field,length), context(jpl_set/3,_) ) ) ] ) :- jpl_set(A, length, 13). test( set_field_bad_field_spec_1, [ setup(( BadFieldName = 3.7 )), throws( error( type_error(field_name,BadFieldName), context(jpl_set/3,_) ) ) ] ) :- jpl_set('org.jpl7.Test', BadFieldName, a). test( set_field_instance_cyclic_term_1, [ setup(( T = f(T), jpl_new('org.jpl7.Test', [], Test) )), throws( error( type_error(acyclic,T), context(jpl_set/3,_) ) ) ] ) :- jpl_set(Test, instanceTerm, {T}). test( set_field_long_array_1, [ setup(( jpl_new(array(long), [1,2,3], LongArray) )) ] ) :- jpl_set('org.jpl7.Test', fieldStaticLongArray, LongArray). test( set_field_long_array_2, [ setup(( jpl_new(array(int), [1,2,3], IntArray) )), throws( error( type_error('[J',IntArray), % NB '[J' is *not* how the type was specified in the failing goal context( jpl_set/3, 'the value is not assignable to the named field of the class' ) ) ) ] ) :- jpl_set('org.jpl7.Test', fieldStaticLongArray, IntArray). test( set_field_object_array_1, [ setup(( jpl_new('java.util.Date', [], Date), jpl_new(array(class([java,lang],['Object'])), [Date,Date], ObjArray) )) ] ) :- jpl_set('org.jpl7.Test', fieldStaticObjectArray, ObjArray). test( set_field_static_bad_type_1, [ setup(( BadVal = 27 )), throws( error( type_error(boolean,BadVal), context(jpl_set/3,_) ) ) ] ) :- jpl_set('org.jpl7.Test', fieldStaticBoolean, BadVal). test( set_field_static_boolean_1, [ setup(( jpl_true(V) )) ] ) :- jpl_set('org.jpl7.Test', fieldStaticBoolean, V). test( set_field_static_boolean_2, [ setup(( jpl_false(V) )) ] ) :- jpl_set('org.jpl7.Test', fieldStaticBoolean, V). test( set_field_static_boolean_bad_1, [ setup(( BadVal = foo(bar) )), throws( error( type_error(field_value,BadVal), context(jpl_set/3,_) ) ) ] ) :- jpl_set('org.jpl7.Test', fieldStaticBoolean, BadVal). test( set_field_static_cyclic_term_1, [ setup(( T = f(T) )), throws( error( type_error(acyclic,T), context(jpl_set/3,_) ) ) ] ) :- jpl_set('org.jpl7.Test', staticTerm, {T}). test( set_field_static_final_int_1, [ setup(( FieldName = fieldStaticFinalInt, Value = 6 )), throws( error( permission_error(modify,final_field,FieldName), context(jpl_set/3,_) ) ) ] ) :- jpl_set('org.jpl7.Test', FieldName, Value). test( set_field_static_shadow_1, [ blocked('we do not yet resolve same-named shadowed fields') ] ) :- jpl_set('org.jpl7.ShadowB', fieldStaticInt, 3). test( set_field_static_term_1, [ setup(( T1 = foo(bar,33), T2 = bar(77,bing) )), true(( T1 == T1a, T2 == T2a )) ] ) :- jpl_set('org.jpl7.Test', fieldStaticTerm, {T1}), jpl_get('org.jpl7.Test', fieldStaticTerm, {T1a}), jpl_set('org.jpl7.Test', fieldStaticTerm, {T2}), jpl_get('org.jpl7.Test', fieldStaticTerm, {T2a}). test( set_field_static_term_2, [ setup(( T1 = foo(bar,33), T2 = bar(77,bing) )) ] ) :- jpl_set('org.jpl7.Test', fieldStaticTerm, {T1}), jpl_get('org.jpl7.Test', fieldStaticTerm, {T1}), jpl_set('org.jpl7.Test', fieldStaticTerm, {T2}), jpl_get('org.jpl7.Test', fieldStaticTerm, {T2}). test( set_get_array_element_boolean_1, [ setup(( jpl_new(array(boolean), 3, A), V = @(false) )), true(( V == Vr )) ] ) :- jpl_set(A, 2, V), jpl_get(A, 2, Vr). test( set_get_array_element_boolean_2, [ setup(( jpl_new(array(boolean), 3, A), V = @(true) )), true(( V == Vr )) ] ) :- jpl_set(A, 2, V), jpl_get(A, 2, Vr). test( set_get_array_element_boolean_3, [ setup(( jpl_new(array(boolean), 3, A), V = bogus )), throws( error( type_error(array(boolean),[V]), context(jpl_set/3,_) ) ) ] ) :- jpl_set(A, 2, V). test( set_get_array_element_byte_1, [ setup(( jpl_new(array(byte), 3, A), V = 33 )), true(( V == Vr )) ] ) :- jpl_set(A, 2, V), jpl_get(A, 2, Vr). test( set_get_array_element_byte_2, [ setup(( jpl_new(array(byte), 3, A), V = 128 )), throws( error( type_error(array(byte),[V]), context(jpl_set/3,_) ) ) ] ) :- jpl_set(A, 2, V). test( set_get_array_element_char_1, [ setup(( jpl_new(array(char), 3, A), V = 65535 )), true(( V == Vr )) ] ) :- jpl_set(A, 2, V), jpl_get(A, 2, Vr). test( set_get_array_element_double_1, [ setup(( jpl_new(array(double), 3, A), V = 2.5 )), true(( V == Vr )) ] ) :- jpl_set(A, 2, V), jpl_get(A, 2, Vr). test( set_get_array_element_float_1, [ setup(( jpl_new(array(float), 3, A), V = 7.5 )), true(( V == Vr )) ] ) :- jpl_set(A, 2, V), jpl_get(A, 2, Vr). test( set_get_array_element_float_2, [ setup(( jpl_new(array(float), 3, A), V is 2, VrX is float(V) )), true(( VrX == Vr )) ] ) :- jpl_set(A, 2, V), jpl_get(A, 2, Vr). test( set_get_array_element_float_3, [ setup(( jpl_new(array(float), 3, A), ( current_prolog_flag(bounded, true) -> current_prolog_flag(max_integer, Imax) ; Imax is 2**63-1 ), VrX is float(Imax) )), true(( VrX == Vr )) ] ) :- jpl_set(A, 2, Imax), jpl_get(A, 2, Vr). test( set_get_array_element_long_1, [ setup(( jpl_new(array(long), 3, A), ( current_prolog_flag(bounded, true) -> current_prolog_flag(max_integer, V) ; V is 2**63-1 ) )), true(( V == Vr )) ] ) :- jpl_set(A, 2, V), jpl_get(A, 2, Vr). test( set_get_array_element_long_2, [ condition(current_prolog_flag(bounded, false)), setup(( jpl_new(array(long), 3, A), V is 2**63 )), throws( error( type_error(array(long),[V]), context(jpl_set/3,_) ) ) ] ) :- jpl_set(A, 2, V). test( set_get_array_elements_boolean_1, [ setup(( jpl_new(array(boolean), 3, A), Vf = @(false), Vt = @(true) )), true(( Vf+Vt+Vf == Vr0+Vr1+Vr2 )) ] ) :- jpl_set(A, 0, Vf), jpl_set(A, 1, Vt), jpl_set(A, 2, Vf), jpl_get(A, 0, Vr0), jpl_get(A, 1, Vr1), jpl_get(A, 2, Vr2). test( set_get_field_static_long_1, [ setup(( ( current_prolog_flag(bounded, true) -> current_prolog_flag(max_integer, V) ; V is 2**63-1 ) )), true(( V == V2 )) ] ) :- jpl_set('org.jpl7.Test', fieldStaticLong, V), jpl_get('org.jpl7.Test', fieldStaticLong, V2). test( set_non_accessible_field_1, [ throws( error( existence_error(field,gagaga), context(jpl_set/3,_) ) ) ] ) :- jpl_set('org.jpl7.Test', gagaga, 4). test( terms_to_array_1, [] ) :- jpl_terms_to_array([foo(bar)], A), jpl_object_to_type(A, array(class([org,jpl7],['Term']))), jpl_get(A, length, 1), jpl_get(A, 0, T), jpl_call(T, toString, [], 'foo(bar)'). test( throw_java_exception_1, [ blocked('part of the error term is nondeterministic: we need to match with _'), throws( error( java_exception(@(_)), 'java.lang.NumberFormatException' ) ) ] ) :- jpl_call('java.lang.Integer', decode, [q], _). test( versions_1, [ true(( Vpl == Vc, Vc == Vjava )) ] ) :- jpl_pl_lib_version(Vpl), jpl_c_lib_version(Vc), jpl_call('org.jpl7.JPL', version_string, [], Vjava). % JW: Mutual recursion check. Moved from jpl.pl to here. As the % callback is in module user, we define it there. user:jpl_test_fac(N, F) :- ( N == 1 -> F = 1 ; N > 1 -> N2 is N-1, jpl_call('org.jpl7.Test', fac, [N2], F2), % call its Java counterpart, which does vice versa F is N*F2 ; F = 0 ). test(fac10, [ true(N==3628800) ] ) :- user:jpl_test_fac(10, N). test(threads1, [ true(( thread_create(jpl_call('java.lang.System', currentTimeMillis, [], _), ThreadId, []), thread_join(ThreadId, true) )) ] ) :- jpl_call('java.lang.System', currentTimeMillis, [], _). test(threads2, [ true(X==true) ] ) :- jpl_call('java.lang.System', currentTimeMillis, [], _), thread_create(jpl_call('java.lang.System', currentTimeMillis, [], _), ThreadId, []), thread_join(ThreadId, X). test(threads3, [ true(( length(Ss, N), sort(Ss, [true]) )) ] ) :- N is 100, % was 1000 (ok in V6); in V7 traditional, fails with 200 jpl_call('java.lang.System', currentTimeMillis, [], _), findall( Status, ( between(1, N, _), thread_create(jpl_call('java.lang.System', currentTimeMillis, [], _), ThreadId, []), thread_join(ThreadId, Status) ), Ss ). test(jref1, [ true(( Term1 \== Term2 )) ] ) :- length(Term1, 5), jpl:jni_term_to_jref(Term1, JRef), jpl:jni_jref_to_term(JRef, Term2). test(jref2, [ true(( Term1 =@= Term2 )) ] ) :- length(Term1, 5), jpl:jni_term_to_jref(Term1, JRef), jpl:jni_jref_to_term(JRef, Term2). :- end_tests(jpl). /******************************* * Testing recognizing/parsing * *******************************/ % =========================================================================== % Some helper functions % =========================================================================== andify_rightwards(true,true,true). andify_rightwards(true,false,false). andify_rightwards(false,true,false). andify_rightwards(false,false,false). all_true(List) :- foldl([E,FromLeft,ToRight]>>once(andify_rightwards(FromLeft,E,ToRight)),List,true,Out), Out == true. % --- % An implementation of ->/2. Pass three goals. % (How do I transform this into a proper metacall?) % --- if_then_else(Condition,Then,Else) :- call(Condition) -> call(Then) ; call(Else). % --- % Reification of truth value % (How do I transform this into a proper metacall?) % --- reify(Goal,Truth) :- if_then_else(call(Goal),(Truth=true),(Truth=false)). % --- % An implementation of ->/2 with an "else" that's true. Pass two goals. % (How do I transform this into a proper metacall?) % --- if_then(Condition,Then) :- call(Condition) -> call(Then) ; true. % --- % Add/Remove the module from an atomic goal "M:G" (a compound), giving separate "M" and "G", % if the goal is qualified. If not, nothing happens, "M" remains a freshvar. % Runs in "both directions" % --- module_name_on_off(:(ModuleName,UnqualifiedGoal),ModuleName,UnqualifiedGoal) :- atomic(ModuleName),!,nonvar(UnqualifiedGoal). module_name_on_off(Goal,UnusedModuleName,Goal) :- var(UnusedModuleName),nonvar(Goal). % --- % Dynamically call a DCG, "DcgGoal", parsing "In" into (a structure) "Out", % with "Rest" remaining. We are parsing some Java class names or descriptors % and "Mode" indicates what we really expect: "slashy", "dotty" as input. % Note that "DcgGoal" is augmented with the two arguments "Out" % (generally a freshvar that captures the result of recognition) and "Mode" % (one of slashy or dotty). % --- dcg_parse_moded(In,Rest,DcgGoal,Out,Mode) :- assertion(nonvar(In)), assertion(memberchk(Mode,[slashy,dotty])), module_name_on_off(DcgGoal,ModuleName,UnqualifiedGoal), compound_name_arguments( UnqualifiedGoalExtended, UnqualifiedGoal, [Out,Mode]), module_name_on_off(DcgGoalNew,ModuleName,UnqualifiedGoalExtended), atom_codes(In,InCodes), phrase(DcgGoalNew,InCodes,RestCodes), atom_codes(Rest,RestCodes). % --- % Dynamically call a DCG, "DcgGoal", parsing "In" into (a structure) "Out", % with "Rest" remaining (or the converse). We are parsing some Java class names % or descriptors. There is no mode, as "DcgGoal" is assumed to not be mode-dependent. % --- dcg_mangle(JavaSide,Rest,DcgGoal,JplSide) :- assertion(nonvar(JavaSide);nonvar(JplSide)), assertion(nonvar(DcgGoal)), % extend DcgGoal with the "JplSide" argument module_name_on_off(DcgGoal,ModuleName,UnqualifiedGoal), compound_name_arguments( UnqualifiedGoalExtended, UnqualifiedGoal, [JplSide]), module_name_on_off(DcgGoalNew,ModuleName,UnqualifiedGoalExtended), % Branch on whether it's Java->Jpl or Jpl->Java (nonvar(JavaSide) -> (dcg_parse_from_java(JavaSide,Rest,DcgGoalNew), debug(dcg_mangle,"~q => ~q",[JavaSide,JplSide])) ; (dcg_generate_from_jpl(JavaSide,DcgGoalNew), debug(dcg_mangle,"~q => ~q",[JplSide,JavaSide]))). dcg_parse_from_java(JavaSide,Rest,DcgGoal) :- % JplSide has been buried in DcgGoal atom_codes(JavaSide,JavaSideCodes), phrase(DcgGoal,JavaSideCodes,RestCodes), atom_codes(Rest,RestCodes). dcg_generate_from_jpl(JavaSide,DcgGoal) :- % JplSide has been buried in DcgGoal phrase(DcgGoal,JavaSideCodes), atom_codes(JavaSide,JavaSideCodes). % =========================================================================== % Calling jpl_field_descriptor//2 in dotty or slashy mode % =========================================================================== jpl_field_descriptor_dotty(T) --> jpl:jpl_field_descriptor(T,dotty). jpl_field_descriptor_slashy(T) --> jpl:jpl_field_descriptor(T,slashy). % =========================================================================== % Code used to compare the results of the old calls and the new calls % =========================================================================== % --- % Construct the returnable term % --- outcome(true ,X,success(X)). outcome(false,_,failure). % --- % Run the old call and the new call with input "JavaSide". % The NewDcg and OldDcg are names of 1-arg DCGs.a % ReifNew : output from new 1-arg DCG: success(JplType) on success, otherwise the atom 'failure' % ReifOld : output from old 1-arg DCG: success(JplType) on success, otherwise the atom 'failure' % --- run_both(JavaSide,NewDcg,OldDcg,ReifNew,ReifOld) :- reify( dcg_mangle(JavaSide,'',NewDcg,JplSideNew), SuccessNew), reify( dcg_mangle(JavaSide,'',OldDcg,JplSideOld), SuccessOld), outcome(SuccessNew,JplSideNew,ReifNew), outcome(SuccessOld,JplSideOld,ReifOld), if_then_else( call(SuccessNew), debug(run_both,"~q : New : ~q",[JavaSide,JplSideNew]), debug(run_both,"~q : New failed",[JavaSide])), if_then_else( call(SuccessOld), debug(run_both,"~q : Old : ~q",[JavaSide,JplSideOld]), debug(run_both,"~q : Old failed",[JavaSide])), call(once(SuccessNew;SuccessOld)). % at least one must have succeeded! % =========================================================================== % Testing characters of Java identifiers % =========================================================================== % --- % Helper % Create a list of true/false atoms, one for each position of the input list % of character codes, as the results of applying the predicates under test % --- maplist_java_id_start_char(ListIn,ListOut) :- maplist([C,T]>> reify(jpl:jpl_java_id_start_char(C),T), ListIn,ListOut). maplist_java_id_part_char(ListIn,ListOut) :- maplist([C,T]>> reify(jpl:jpl_java_id_part_char(C),T), ListIn,ListOut). maplist_java_id_disallowed_char(ListIn,ListOut) :- maplist([C,T]>> reify( ((\+ jpl:jpl_java_id_part_char(C)), (\+ jpl:jpl_java_id_start_char(C))),T), ListIn,ListOut). maplist_java_id_part_char_but_not_start_char(ListIn,ListOut) :- maplist([C,T]>> reify( (( jpl:jpl_java_id_part_char(C)), (\+ jpl:jpl_java_id_start_char(C))),T), ListIn,ListOut). :- begin_tests(identifier_chars). test("characters allowed at start of an identifier", [blocked('awaits understanding')]) :- maplist_java_id_start_char(`abcdefghijklöüä`,R), debug(identifier_chars,"Result for 'characters allowed at start of an identifier': ~q",[R]), all_true(R). test("more characters allowed at start of an identifier") :- maplist_java_id_start_char(`$\u3047_`,R), % \u3047 Hiragana letter small e debug(identifier_chars,"Result for 'more characters allowed at the start of an identifier': ~q",[R]), all_true(R). test("characters disallowed in identifiers") :- maplist_java_id_disallowed_char(`-.`,R), debug(identifier_chars,"Result for 'characters disallowed in identifiers': ~q",[R]), all_true(R). test("characters allowed as part but not as start of identifiers") :- maplist_java_id_part_char_but_not_start_char(`0123456789`,R), debug(identifier_chars,"Result for 'characters allowed as part but not as start of identifiers': ~q",[R]), all_true(R). :- end_tests(identifier_chars). % =========================================================================== % Testing Java identifiers via "jpl:jpl_java_id//1" % =========================================================================== :- begin_tests(java_id). the_dcg(jpl:jpl_java_id). test("recognize Java identifier (unconstrained Out), no rest", true([Out,Rest] == [my_identifier,''])) :- the_dcg(DCG), dcg_mangle('my_identifier',Rest,DCG,Out), debug(java_id,"Recognized: ~q with rest: ~q",[Out,Rest]). test("recognize Java identifier (unconstrained Out), with rest", true([Out,Rest] == [my_identifier,'.dodododo'])) :- the_dcg(DCG), dcg_mangle('my_identifier.dodododo',Rest,DCG,Out), debug(java_id,"Recognized: ~q with rest: ~q",[Out,Rest]). test("recognize Java identifier of length 1, no rest", true([Out,Rest] == [m,''])) :- the_dcg(DCG), dcg_mangle('m',Rest,DCG,Out). test("recognize Java identifier (Out already set to result), no rest", true(Rest == '')) :- the_dcg(DCG), dcg_mangle('my_identifier',Rest,DCG,'my_identifier'). test("recognize Java identifier (Out already set to result), with rest", true(Rest == '.dodododo')) :- the_dcg(DCG), dcg_mangle('my_identifier.dodododo',Rest,DCG,'my_identifier'). test("starts with dash: not a Java identifier", fail) :- the_dcg(DCG), dcg_mangle('-my',_,DCG,_). test("contains dash and thus is broken up", true([Out,Rest] == ['my','-my'])) :- the_dcg(DCG), dcg_mangle('my-my',Rest,DCG,Out). test("empty atom is not a Java identifier", fail) :- the_dcg(DCG), dcg_mangle('',_,DCG,_). test("valid identifier with differing Out", fail) :- the_dcg(DCG), dcg_mangle('my',_,DCG,'notmy'). :- end_tests(java_id). % =========================================================================== % Testing Java type identifiers via "jpl_java_type_id//1" % This is practically the same as testing "jpl_java_id"; % here only the keywords "var" and "yield" are additionally disallowed. % =========================================================================== :- begin_tests(java_type_id). the_dcg(jpl:jpl_java_type_id). test("recognize Java type identifier",true([Out,Rest] == [my_identifier,''])) :- the_dcg(DCG), dcg_mangle('my_identifier',Rest,DCG,Out). test("reject bad Java type identifier 'var'",fail) :- the_dcg(DCG), dcg_mangle('var',_,DCG,_). test("java type identifier DOES NOT stop at '$'",true([Out,Rest] == ['foo$bar',''])) :- the_dcg(DCG), dcg_mangle('foo$bar',Rest,DCG,Out). :- end_tests(java_type_id). % =========================================================================== % Testing the "messy dollar split" which is used to split Java classnames % but is actually of dubious value % =========================================================================== :- begin_tests(messy_dollar_split). test(1,true(Runs == [alfa])) :- jpl:messy_dollar_split(alfa,Runs). test(2,true(Runs == [a])) :- jpl:messy_dollar_split(a,Runs). test(3,true(Runs == ['$'])) :- jpl:messy_dollar_split('$',Runs). test(4,true(Runs == ['alfa$'])) :- jpl:messy_dollar_split('alfa$',Runs). test(5,true(Runs == [alfa,bravo])) :- jpl:messy_dollar_split('alfa$bravo',Runs). test(6,true(Runs == ['$alfa'])) :- jpl:messy_dollar_split('$alfa',Runs). test(7,true(Runs == ['alfa','$bravo'])) :- jpl:messy_dollar_split('alfa$$bravo',Runs). test(8,true(Runs == ['$alfa','bravo','charlie$'])) :- jpl:messy_dollar_split('$alfa$bravo$charlie$',Runs). test(9,true(Runs == ['$$alfa','$bravo','$$charlie','$$$'])) :- jpl:messy_dollar_split('$$alfa$$bravo$$$charlie$$$$',Runs). :- end_tests(messy_dollar_split). % =========================================================================== % Testing recognition of the "binary classname", i.e. the classname % as it appears in binaries (in its 'dotty' form) % This calls the actual DCG parsing the binary classname, not the predicate % eventually calling it. % =========================================================================== :- begin_tests(jpl_classname_without_dollar). the_dcg(jpl:jpl_classname). test("simple classname",true(Out == class([],[foo]))) :- the_dcg(DCG), dcg_parse_moded('foo','',DCG,Out,dotty). test("qualified classname",true(Out == class([alfa,bravo,charlie],[foo]))) :- the_dcg(DCG), dcg_parse_moded('alfa.bravo.charlie.foo','',DCG,Out,dotty). :- end_tests(jpl_classname_without_dollar). % =========================================================================== % Testing recognition of the "binary classname" with "$" inside. % Note that "splitting at a dollar is ill-defined and should eventually disappear. % =========================================================================== :- begin_tests(jpl_classname_with_dollar). the_dcg(jpl:jpl_classname). test("qualified inner member type",true(Out == class([alfa,bravo,charlie],[foo,bar]))) :- the_dcg(DCG), dcg_parse_moded('alfa.bravo.charlie.foo$bar','',DCG,Out,dotty). test("qualified inner anonymous type",true(Out == class([alfa,bravo,charlie],[foo,'01234']))) :- the_dcg(DCG), dcg_parse_moded('alfa.bravo.charlie.foo$01234','',DCG,Out,dotty). test("qualified inner local class",true(Out == class([alfa,bravo,charlie],[foo,'01234bar']))) :- the_dcg(DCG), dcg_parse_moded('alfa.bravo.charlie.foo$01234bar','',DCG,Out,dotty). test("qualified inner member type, deep",true(Out == class([alfa,bravo,charlie],[foo,bar,baz,quux]))) :- the_dcg(DCG), dcg_parse_moded('alfa.bravo.charlie.foo$bar$baz$quux','',DCG,Out,dotty). :- end_tests(jpl_classname_with_dollar). % =========================================================================== % Testing Java entityname <-> JPL type (success) % Use assertion magic: on assertion failure, the unit test does not fail % immediately. % =========================================================================== :- begin_tests(jpl_entityname). the_dcg(jpl:jpl_entityname). the_tests([ q( int , int ), q( integer , class([],[integer]) ), q( void , void ), q( char , char ), q( double , double ), q( '[D' , array(double) ), q( '[[I' , array(array(int)) ), q( 'java.lang.String' , class([java,lang],['String'])), q( '[Ljava.lang.String;' , array(class([java,lang],['String']))), q( '[[Ljava.lang.String;' , array(array(class([java, lang], ['String']))) ), q( '[[[Ljava.util.Calendar;' , array(array(array(class([java,util],['Calendar']))))) ]). test("Java entity name to JPL type") :- the_tests(L), the_dcg(DCG), maplist({DCG}/[q(EN,T)]>>assertion((dcg_mangle(EN,'',DCG,Out),Out == T)),L). test("JPL type to Java entity name") :- the_tests(L), the_dcg(DCG), maplist({DCG}/[q(EN,T)]>>assertion((dcg_mangle(Out,'',DCG,T),Out == EN)),L). test("array of void",fail) :- the_dcg(DCG), dcg_mangle('[[V','',DCG,_). test("yield",fail) :- the_dcg(DCG), dcg_mangle('yield','',DCG,_). test("var",fail) :- the_dcg(DCG), dcg_mangle('var','',DCG,_). test("bad id with dash", fail) :- the_dcg(DCG), dcg_mangle(_,'',DCG,array(array(array(class([foo,bared],['-hello']))))). :- end_tests(jpl_entityname). % =========================================================================== % Testing Java findclass descriptor <-> JPL type % Use assertion magic: on assertion failure, the unit test does not fail % immediately. % =========================================================================== :- begin_tests(jpl_findclass_descriptor). the_dcg(jpl:jpl_findclass_descriptor). the_tests([ q( '[D' , array(double) ), q( '[[I' , array(array(int)) ), q( 'java/lang/String' , class([java,lang],['String'])), q( '[Ljava/lang/String;' , array(class([java,lang],['String']))), q( '[[Ljava/lang/String;' , array(array(class([java, lang], ['String']))) ), q( '[[[Ljava/util/Calendar;' , array(array(array(class([java,util],['Calendar'])))) ) ]). test("Java findclass descriptor to JPL type") :- the_tests(L), the_dcg(DCG), maplist({DCG}/[q(FCD,T)]>>assertion((dcg_mangle(FCD,'',DCG,Out),Out == T)),L). test("JPL type to Java findclass descriptor") :- the_tests(L), the_dcg(DCG), maplist({DCG}/[q(FCD,T)]>>assertion((dcg_mangle(Out,'',DCG,T),Out == FCD)),L). test("no primitive in Java",fail) :- the_dcg(DCG), dcg_mangle(int,'',DCG,_). test("no primitive in JPL",fail) :- the_dcg(DCG), dcg_mangle(_,'',DCG,int). test("no void in Java",fail) :- the_dcg(DCG), dcg_mangle(void,'',DCG,_). test("no void in JPL",fail) :- the_dcg(DCG), dcg_mangle(_,'',DCG,void). test("no primitive descriptor (like I) in Java; in fact, it's a class name",true(T==class([],['I']))) :- the_dcg(DCG), dcg_mangle('I','',DCG,T). :- end_tests(jpl_findclass_descriptor). % =========================================================================== % Testing Java field descriptor <-> JPL type % Use assertion magic: on assertion failure, the unit test does not fail % immediately. % =========================================================================== :- begin_tests(jpl_field_descriptor). the_dcg(jpl_field_descriptor_dotty). the_tests([ q( 'D' , double ), q( 'I' , int ), q( '[D' , array(double) ), q( '[[I' , array(array(int)) ), q( 'Ljava.lang.String;' , class([java,lang],['String'])), q( '[Ljava.lang.String;' , array(class([java,lang],['String']))), q( '[[Ljava.lang.String;' , array(array(class([java, lang], ['String']))) ), q( '[[[Ljava.util.Calendar;' , array(array(array(class([java,util],['Calendar'])))) ) ]). test("Java field descriptor to JPL type") :- the_tests(L), the_dcg(DCG), maplist({DCG}/[q(FD,T)]>>assertion((dcg_mangle(FD,'',DCG,Out),Out == T)),L). test("JPL type to Java field descriptor") :- the_tests(L), the_dcg(DCG), maplist({DCG}/[q(FD,T)]>>assertion((dcg_mangle(Out,'',DCG,T),Out == FD)),L). test("no void on the left", [blocked('awaits understanding')]) :- the_dcg(DCG), dcg_mangle(void,_,DCG,_). test("no void on the right", [blocked('awaits understanding')]) :- the_dcg(DCG), dcg_mangle(v_,_,DCG,void). :- end_tests(jpl_field_descriptor). % =========================================================================== % Testing Java method descriptor <-> JPL type % Use assertion magic: on assertion failure, the unit test does not fail % immediately. % =========================================================================== :- begin_tests(jpl_method_descriptor). the_dcg(jpl:jpl_method_descriptor). the_tests([ q( '()V', method([],void) ), q( '(Ljava/lang/String;DD[Ljava/util/Calendar;)[[F', method([class([java,lang],['String']),double,double,array(class([java,util],['Calendar']))],array(array(float))) ) ]). test("Java method descriptor to JPL type") :- the_tests(L), the_dcg(DCG), maplist({DCG}/[q(MD,T)]>>assertion((dcg_mangle(MD,'',DCG,Out),Out == T)),L). test("JPL type to Java method descriptor") :- the_tests(L), the_dcg(DCG), maplist({DCG}/[q(MD,T)]>>assertion((dcg_mangle(Out,'',DCG,T),Out == MD)),L). test("not a method descriptor",fail) :- the_dcg(DCG), dcg_mangle('(void)void',_,DCG,_). :- end_tests(jpl_method_descriptor). % =========================================================================== % Directly comparing old and new Java entityname <-> JPL type mapping % =========================================================================== :- begin_tests(compare_old_and_new_entityname). help_run_both(JavaSide,ReifNew,ReifOld) :- run_both( JavaSide, % input jpl:jpl_entityname, % name of new 1-arg DCG (in module jpl) jpl_type_classname_1, % name of old 1-arg DCG (included further below) ReifNew, % output from new 1-arg DCG: success(JplType) on success, otherwise the atom 'failure' ReifOld). % output from old 1-arg DCG: success(JplType) on success, otherwise the atom 'failure' test("comparing #1" ,[blocked("Old response bad"),true(ReifNew == ReifOld)]) :- help_run_both('int',ReifNew,ReifOld). % Old: class([],[int]) ??? test("comparing #2" ,[blocked("Old response bad"),true(ReifNew == ReifOld)]) :- help_run_both('float',ReifNew,ReifOld). % Old: class([],[float]) ??? test("comparing #3" ,[blocked("Old response bad"),true(ReifNew == ReifOld)]) :- help_run_both('void',ReifNew,ReifOld). % Old: class([],[void]) ??? test("old call gives wrong result #1") :- help_run_both('foo.bar.baz.Foo$',success(OutNew),success(OutOld)), OutNew == class([foo,bar,baz],['Foo$']), OutOld == class([foo,bar,baz],['Foo','']). % OLD IS WRONG test("failure on old call #2") :- help_run_both('foo.bar.baz.$Foo',success(OutNew),failure), % OLD FAILS OutNew == class([foo,bar,baz],['$Foo']). the_tests([ 'java.lang.Integer', 'integer', '[D', '[[[[[I', '[[J', '[[Ljava.lang.String;', 'java.lang.String', 'Foo', 'foo.bar.baz.Foo', 'foo.bar.baz.Foo$Quux' ]). test("comparing several examples") :- the_tests(L), maplist([EN]>>assertion((help_run_both(EN,success(OutNew),success(OutOld)),OutNew == OutOld)),L). :- end_tests(compare_old_and_new_entityname). % =========================================================================== % Directly comparing old and new Java findclass descriptor <-> JPL type mapping % =========================================================================== :- begin_tests(compare_old_and_new_findclass_descriptor). help_run_both(JavaSide,ReifNew,ReifOld) :- run_both( JavaSide, % input jpl:jpl_findclass_descriptor, % name of new 1-arg DCG (in module jpl) jpl_type_findclassname, % name of old 1-arg DCG (included further below) ReifNew, % output from new 1-arg DCG: success(JplType) on success, otherwise the atom 'failure' ReifOld). % output from old 1-arg DCG: success(JplType) on success, otherwise the atom 'failure' the_tests([ 'java/lang/Integer', 'integer', '[D', '[[[[[I', '[[J', '[[Ljava/lang/String;', 'java/lang/String', 'Foo', 'foo/bar/baz/Foo', 'foo/bar/baz/Foo$Quux' ]). test("comparing several examples") :- the_tests(L), maplist([FCD]>>assertion((help_run_both(FCD,success(OutNew),success(OutOld)),OutNew == OutOld)),L). :- end_tests(compare_old_and_new_findclass_descriptor). % =========================================================================== % Directly comparing old and new % =========================================================================== :- begin_tests(compare_both_field_descriptors). help_run_both(JavaSide,ReifNew,ReifOld) :- run_both( JavaSide, % input jpl_field_descriptor_slashy, % name of new 1-arg DCG (an indirection to one in module JPL) jpl_type_descriptor_1, % name of old 1-arg DCG (included further below) ReifNew, % output from new 1-arg DCG: success(JplType) on success, otherwise the atom 'failure' ReifOld). % output from old 1-arg DCG: success(JplType) on success, otherwise the atom 'failure' the_tests([ '[D', '[[[[[I', '[[J', '[[Ljava/lang/String;', 'Ljava/lang/String;', 'LFoo;', 'Lfoo/bar/baz/Foo;', 'Lfoo/bar/baz/Foo$Quux;' ]). test("comparing several examples") :- the_tests(L), maplist([FD]>>assertion((help_run_both(FD,success(OutNew),success(OutOld)),OutNew == OutOld)),L). :- end_tests(compare_both_field_descriptors). % =========================================================================== % Testing jpl_type_to_classname/2, the exported predicate. % This internally actually calls jpl_entityname//2 % =========================================================================== :- begin_tests(jpl_type_to_classname). test("jpl_type_to_classname: class", CN == 'java.util.String') :- jpl_type_to_classname(class([java,util],['String']),CN). test("jpl_type_to_classname: class in default package", CN == 'String') :- jpl_type_to_classname(class([],['String']),CN). test("jpl_type_to_classname: class name separated along '$'", CN == 'foo.bar.Bling$Blong') :- jpl_type_to_classname(class([foo,bar],['Bling','Blong']),CN). test("jpl_type_to_classname: array of class", CN == '[Ljava.util.String;') :- jpl_type_to_classname(array(class([java,util],['String'])),CN). test("jpl_type_to_classname: array of primtive", CN == '[B') :- jpl_type_to_classname(array(byte),CN). test("jpl_type_to_classname: unboxed primitive", CN == byte) :- jpl_type_to_classname(byte,CN). test("jpl_type_to_classname: void", CN == void) :- jpl_type_to_classname(void,CN). test("jpl_type_to_classname: unrecognized primitive", fail) :- jpl_type_to_classname(bar,_). :- end_tests(jpl_type_to_classname). % =========================================================================== % Testing jpl_classname_to_type/2, the exported predicate. % This internally actually calls jpl_entityname//2 and performs caching % =========================================================================== :- begin_tests(jpl_classname_to_type). test("jpl_classname_to_type: class", T == class([java,util],['String'])) :- jpl_classname_to_type('java.util.String',T). test("jpl_classname_to_type: class in default package", T == class([],['String'])) :- jpl_classname_to_type('String',T). test("jpl_classname_to_type: class name separated along '$'", T == class([foo,bar],['Bling','Blong'])) :- jpl_classname_to_type('foo.bar.Bling$Blong',T). test("jpl_classname_to_type: array of class", T == array(class([java,util],['String']))) :- jpl_classname_to_type('[Ljava.util.String;',T). test("jpl_classname_to_type: array of primtive", T == array(byte)) :- jpl_classname_to_type('[B',T). test("jpl_classname_to_type: unboxed primitive 1", T == byte) :- jpl_classname_to_type(byte,T). test("jpl_classname_to_type: unboxed primitive 2", T == int) :- jpl_classname_to_type(int,T). test("jpl_classname_to_type: not an integer", T == class([],[integer])) :- jpl_classname_to_type(integer,T). test("jpl_classname_to_type: void", T == void) :- jpl_classname_to_type(void,T). :- end_tests(jpl_classname_to_type). % =========================================================================== % Testing safe_type_to_classname, used in exceptions % =========================================================================== :- begin_tests(safe_type_to_classname). test("safe_type_to_classname: class", CN == 'java.util.String') :- jpl:safe_type_to_classname(class([java,util],['String']),CN). test("safe_type_to_classname: class in default package", CN == 'String') :- jpl:safe_type_to_classname(class([],['String']),CN). test("safe_type_to_classname: class name separated along '$'", CN == 'foo.bar.Bling$Blong') :- jpl:safe_type_to_classname(class([foo,bar],['Bling','Blong']),CN). test("safe_type_to_classname: array of class", CN == '[Ljava.util.String;') :- jpl:safe_type_to_classname(array(class([java,util],['String'])),CN). test("safe_type_to_classname: array of primtive", CN == '[B') :- jpl:safe_type_to_classname(array(byte),CN). test("safe_type_to_classname: unboxed primitive", CN == byte) :- jpl:safe_type_to_classname(byte,CN). test("safe_type_to_classname: void", CN == void) :- jpl:safe_type_to_classname(void,CN). test("safe_type_to_classname: unrecognized primitive", CN == 'bar') :- jpl:safe_type_to_classname(bar,CN). test("safe_type_to_classname: unrecognized structure", CN == 'foo(bar(baz))') :- jpl:safe_type_to_classname(foo(bar(baz)),CN). :- end_tests(safe_type_to_classname). % =========================================================================== % The original jpl code for recognizing entity names etc. % Added here because we want to run direct comparisons % =========================================================================== % jpl_type_alfa(0'$) --> % presumably not allowed % "$". % given the "inner class" syntax? jpl_type_alfa(0'_) --> "_", !. jpl_type_alfa(C) --> [C], { C>=0'a, C=<0'z }, !. jpl_type_alfa(C) --> [C], { C>=0'A, C=<0'Z }. jpl_type_alfa_num(C) --> jpl_type_alfa(C), !. jpl_type_alfa_num(C) --> [C], { C>=0'0, C=<0'9 }. jpl_type_array_classname(array(T)) --> "[", jpl_type_classname_2(T). jpl_type_array_descriptor(array(T)) --> "[", jpl_type_descriptor_1(T). jpl_type_bare_class_descriptor(class(Ps,Cs)) --> jpl_type_slashed_package_parts(Ps), jpl_type_class_parts(Cs). jpl_type_bare_classname(class(Ps,Cs)) --> jpl_type_dotted_package_parts(Ps), jpl_type_class_parts(Cs). jpl_type_class_descriptor(class(Ps,Cs)) --> "L", jpl_type_bare_class_descriptor(class(Ps,Cs)), ";". jpl_type_class_part(N) --> jpl_type_id(N). jpl_type_class_parts([C|Cs]) --> jpl_type_class_part(C), jpl_type_inner_class_parts(Cs). jpl_type_classname_1(T) --> jpl_type_bare_classname(T), !. jpl_type_classname_1(T) --> jpl_type_array_classname(T), !. jpl_type_classname_1(T) --> jpl_type_primitive(T). jpl_type_classname_2(T) --> jpl_type_delimited_classname(T). jpl_type_classname_2(T) --> jpl_type_array_classname(T). jpl_type_classname_2(T) --> jpl_type_primitive(T). jpl_type_delimited_classname(Class) --> "L", jpl_type_bare_classname(Class), ";". jpl_type_descriptor_1(T) --> jpl_type_primitive(T), !. jpl_type_descriptor_1(T) --> jpl_type_class_descriptor(T), !. jpl_type_descriptor_1(T) --> jpl_type_array_descriptor(T), !. jpl_type_descriptor_1(T) --> jpl_type_method_descriptor(T). jpl_type_dotted_package_parts([P|Ps]) --> jpl_type_package_part(P), ".", !, jpl_type_dotted_package_parts(Ps). jpl_type_dotted_package_parts([]) --> []. jpl_type_findclassname(T) --> jpl_type_bare_class_descriptor(T). jpl_type_findclassname(T) --> jpl_type_array_descriptor(T). jpl_type_id(A) --> { nonvar(A) -> atom_codes(A,[C|Cs]) ; true }, jpl_type_alfa(C), jpl_type_id_rest(Cs), { atom_codes(A, [C|Cs]) }. jpl_type_id_rest([C|Cs]) --> jpl_type_alfa_num(C), !, jpl_type_id_rest(Cs). jpl_type_id_rest([]) --> []. jpl_type_id_v2(A) --> % inner class name parts (empirically) { nonvar(A) -> atom_codes(A,Cs) ; true }, jpl_type_id_rest(Cs), { atom_codes(A, Cs) }. jpl_type_inner_class_part(N) --> jpl_type_id_v2(N). jpl_type_inner_class_parts([C|Cs]) --> "$", jpl_type_inner_class_part(C), !, jpl_type_inner_class_parts(Cs). jpl_type_inner_class_parts([]) --> []. jpl_type_method_descriptor(method(Ts,T)) --> "(", jpl_type_method_descriptor_args(Ts), ")", jpl_type_method_descriptor_return(T). jpl_type_method_descriptor_args([T|Ts]) --> jpl_type_descriptor_1(T), !, jpl_type_method_descriptor_args(Ts). jpl_type_method_descriptor_args([]) --> []. jpl_type_method_descriptor_return(T) --> jpl_type_void(T). jpl_type_method_descriptor_return(T) --> jpl_type_descriptor_1(T). jpl_type_package_part(N) --> jpl_type_id(N). jpl_type_primitive(boolean) --> "Z", !. jpl_type_primitive(byte) --> "B", !. jpl_type_primitive(char) --> "C", !. jpl_type_primitive(short) --> "S", !. jpl_type_primitive(int) --> "I", !. jpl_type_primitive(long) --> "J", !. jpl_type_primitive(float) --> "F", !. jpl_type_primitive(double) --> "D". jpl_type_slashed_package_parts([P|Ps]) --> jpl_type_package_part(P), "/", !, jpl_type_slashed_package_parts(Ps). jpl_type_slashed_package_parts([]) --> []. jpl_type_void(void) --> "V".