Skip to content

Commit

Permalink
Merge branch 'jruby-1_7'
Browse files Browse the repository at this point in the history
* jruby-1_7: (27 commits)
  meh,  use the included hook instead to get a simple test skip on --1.8 mode
  some more --1.8 skip fixes (4 less future surprises)
  test skip 1.8.7 test-unit compatibility
  adding a skip-ed test-case for callin abstract (Ruby impl) method in constructor
  less intermediate strings on proxy class name generation
  some notes on Java proxy invocation handler class hierarchy + un-used import
  make generated Java proxy class fields final
  include_package spec no longer pending
  [ji] include package should work with a package instance (just like import)
  java_alias should not fail when no include_package called previously
  add a possible TODO note for proc-to-iface dispatch
  Fix VERSION so jruby-jars builds find the right jars.
  Update joda time to 2.8.2.
  Fixes #3286. Encoding of symbol literals does not respect the encoding of the source file (1.9 edition)
  Move psych to 1.9 lib so only 1.9 and 2.0 modes can see it.
  backport #3271, #3211, #3221
  [ji] improved more-specific type matching when matching Java methods
  another (pending) Java 8 JI spec - hitting the wall with Predicate#test(arg1)
  Exclude odd DateTime roundtrip failure in Psych.
  Update psych+tests to 2.0.15.
  ...

Conflicts:
	.travis.yml
	VERSION
	core/pom.xml
	core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java
	core/src/main/java/org/jruby/ext/psych/PsychLibrary.java
	core/src/main/java/org/jruby/ext/psych/PsychParser.java
	core/src/main/java/org/jruby/ext/psych/PsychToRuby.java
	core/src/main/java/org/jruby/parser/ParserSupport.java
	core/src/main/java/org/jruby/parser/Ruby19Parser.java
	core/src/main/java/org/jruby/parser/Ruby19Parser.y
	docs/man/pom.xml
	docs/pom.xml
	ext/pom.xml
	ext/readline/pom.xml
	ext/ripper/pom.xml
	lib/pom.rb
	lib/pom.xml
	lib/ruby/1.8/bigdecimal/math.rb
	lib/ruby/1.9/bigdecimal/math.rb
	lib/ruby/1.9/psych.rb
	lib/ruby/1.9/psych/coder.rb
	lib/ruby/1.9/psych/core_ext.rb
	lib/ruby/1.9/psych/deprecated.rb
	lib/ruby/1.9/psych/handler.rb
	lib/ruby/1.9/psych/handlers/document_stream.rb
	lib/ruby/1.9/psych/handlers/recorder.rb
	lib/ruby/1.9/psych/json/ruby_events.rb
	lib/ruby/1.9/psych/json/stream.rb
	lib/ruby/1.9/psych/json/tree_builder.rb
	lib/ruby/1.9/psych/json/yaml_events.rb
	lib/ruby/1.9/psych/nodes.rb
	lib/ruby/1.9/psych/nodes/alias.rb
	lib/ruby/1.9/psych/nodes/document.rb
	lib/ruby/1.9/psych/nodes/mapping.rb
	lib/ruby/1.9/psych/nodes/node.rb
	lib/ruby/1.9/psych/nodes/scalar.rb
	lib/ruby/1.9/psych/nodes/sequence.rb
	lib/ruby/1.9/psych/nodes/stream.rb
	lib/ruby/1.9/psych/omap.rb
	lib/ruby/1.9/psych/parser.rb
	lib/ruby/1.9/psych/scalar_scanner.rb
	lib/ruby/1.9/psych/set.rb
	lib/ruby/1.9/psych/stream.rb
	lib/ruby/1.9/psych/syntax_error.rb
	lib/ruby/1.9/psych/tree_builder.rb
	lib/ruby/1.9/psych/visitors.rb
	lib/ruby/1.9/psych/visitors/depth_first.rb
	lib/ruby/1.9/psych/visitors/emitter.rb
	lib/ruby/1.9/psych/visitors/json_tree.rb
	lib/ruby/1.9/psych/visitors/to_ruby.rb
	lib/ruby/1.9/psych/visitors/visitor.rb
	lib/ruby/1.9/psych/visitors/yaml_tree.rb
	lib/ruby/1.9/psych/y.rb
	lib/ruby/2.0/bigdecimal/math.rb
	maven/jruby-complete/pom.xml
	maven/jruby-dist/pom.xml
	maven/jruby-jars/pom.xml
	maven/jruby-noasm/pom.xml
	maven/jruby-rake-plugin/pom.xml
	maven/jruby-stdlib/pom.xml
	maven/jruby/pom.xml
	maven/pom.xml
	pom.xml
	spec/java_integration/packages/access_spec.rb
	test/externals/ruby1.9/psych/helper.rb
	test/externals/ruby1.9/psych/test_alias_and_anchor.rb
	test/externals/ruby1.9/psych/test_array.rb
	test/externals/ruby1.9/psych/test_boolean.rb
	test/externals/ruby1.9/psych/test_class.rb
	test/externals/ruby1.9/psych/test_coder.rb
	test/externals/ruby1.9/psych/test_date_time.rb
	test/externals/ruby1.9/psych/test_deprecated.rb
	test/externals/ruby1.9/psych/test_document.rb
	test/externals/ruby1.9/psych/test_emitter.rb
	test/externals/ruby1.9/psych/test_encoding.rb
	test/externals/ruby1.9/psych/test_exception.rb
	test/externals/ruby1.9/psych/test_hash.rb
	test/externals/ruby1.9/psych/test_json_tree.rb
	test/externals/ruby1.9/psych/test_merge_keys.rb
	test/externals/ruby1.9/psych/test_nil.rb
	test/externals/ruby1.9/psych/test_null.rb
	test/externals/ruby1.9/psych/test_numeric.rb
	test/externals/ruby1.9/psych/test_object.rb
	test/externals/ruby1.9/psych/test_object_references.rb
	test/externals/ruby1.9/psych/test_omap.rb
	test/externals/ruby1.9/psych/test_parser.rb
	test/externals/ruby1.9/psych/test_psych.rb
	test/externals/ruby1.9/psych/test_scalar.rb
	test/externals/ruby1.9/psych/test_scalar_scanner.rb
	test/externals/ruby1.9/psych/test_serialize_subclasses.rb
	test/externals/ruby1.9/psych/test_set.rb
	test/externals/ruby1.9/psych/test_stream.rb
	test/externals/ruby1.9/psych/test_string.rb
	test/externals/ruby1.9/psych/test_struct.rb
	test/externals/ruby1.9/psych/test_symbol.rb
	test/externals/ruby1.9/psych/test_tainted.rb
	test/externals/ruby1.9/psych/test_to_yaml_properties.rb
	test/externals/ruby1.9/psych/test_tree_builder.rb
	test/externals/ruby1.9/psych/test_yaml.rb
	test/externals/ruby1.9/psych/test_yamldbm.rb
	test/externals/ruby1.9/psych/test_yamlstore.rb
	test/externals/ruby1.9/psych/visitors/test_to_ruby.rb
	test/externals/ruby1.9/psych/visitors/test_yaml_tree.rb
	test/pom.xml
	test/test_command_line_switches.rb
	test/test_helper.rb
	test/test_higher_javasupport.rb
	test/test_load_gem_extensions.rb
	test/test_zlib.rb
kares committed Aug 25, 2015
2 parents fd7eefe + f0e2a9d commit 1889650
Showing 20 changed files with 378 additions and 118 deletions.
89 changes: 69 additions & 20 deletions core/src/main/java/org/jruby/java/dispatch/CallableSelector.java
Original file line number Diff line number Diff line change
@@ -172,7 +172,8 @@ private static <T extends ParameterTypes> T findMatchingCallableForArgs(final Ru
final int procArity;
if ( lastArg instanceof RubyProc ) {
final Method implMethod; final int last = msTypes.length - 1;
if ( last >= 0 && msTypes[last].isInterface() && ( implMethod = getFunctionalInterfaceMethod(msTypes[last]) ) != null ) {
if ( last >= 0 && msTypes[last].isInterface() &&
( implMethod = getFunctionalInterfaceMethod(msTypes[last]) ) != null ) {
mostSpecificArity = implMethod.getParameterTypes().length;
}
procArity = ((RubyProc) lastArg).getBlock().getSignature().arityValue();
@@ -181,34 +182,40 @@ private static <T extends ParameterTypes> T findMatchingCallableForArgs(final Ru
procArity = Integer.MIN_VALUE;
}

OUTER: for ( int c = 1; c < size; c++ ) {
/* OUTER: */
for ( int c = 1; c < size; c++ ) {
final T candidate = candidates.get(c);
final Class<?>[] cTypes = candidate.getParameterTypes();

// TODO still need to handle var-args better Class<?> lastType;
for ( int i = 0; i < msTypes.length; i++ ) {
final Class<?> msType = msTypes[i], cType = cTypes[i];
if ( msType != cType && msType.isAssignableFrom(cType) ) {
mostSpecific = candidate; msTypes = cTypes;
ambiguous = false; continue OUTER;
}

final boolean lastArgProc = procArity != Integer.MIN_VALUE;
final Boolean moreSpecific = moreSpecificTypes(msTypes, cTypes, lastArgProc);
if ( (Object) moreSpecific == Boolean.TRUE ) {
mostSpecific = candidate; msTypes = cTypes;
ambiguous = false; continue /* OUTER */;
}
// none more specific; check for ambiguities
for ( int i = 0; i < msTypes.length; i++ ) {
final Class<?> msType = msTypes[i], cType = cTypes[i];
if ( msType == cType || msType.isAssignableFrom(cType) || cType.isAssignableFrom(msType) ) {
ambiguous = false; continue OUTER;
}
else if ( cType.isPrimitive() && msType.isAssignableFrom(getBoxType(cType)) ) {
ambiguous = false; continue OUTER;
}
else {
ambiguous = true;
else { // if ( (Object) moreSpecific == Boolean.FALSE ) {
// none more specific; check for ambiguities
for ( int i = 0; i < msTypes.length; i++ ) {
// TODO if lastArgProc (and we're not dealing with RubyProc.class)
// then comparing last arg should not be needed, right?
// ... same applies for moreSpecificTypes method ...
final Class<?> msType = msTypes[i], cType = cTypes[i];
if ( msType == cType || msType.isAssignableFrom(cType) || cType.isAssignableFrom(msType) ) {
ambiguous = false; break; // continue OUTER;
}
else if ( cType.isPrimitive() && msType.isAssignableFrom(getBoxType(cType)) ) {
ambiguous = false; break; // continue OUTER;
}
else {
ambiguous = true;
}
}
}

// special handling if we're dealing with Proc#impl :
if ( procArity != Integer.MIN_VALUE ) { // lastArg instanceof RubyProc
if ( lastArgProc ) { // lastArg instanceof RubyProc
// cases such as (both ifaces - differ in arg count) :
// java.io.File#listFiles(java.io.FileFilter) ... accept(File)
// java.io.File#listFiles(java.io.FilenameFilter) ... accept(File, String)
@@ -287,6 +294,48 @@ else if ( procArity < 0 && methodArity >= -(procArity + 1) ) { // *splat that fi
return method;
}

private static Boolean moreSpecificTypes(final Class[] msTypes, final Class[] cTypes,
final boolean lastArgProc) {

final int last = msTypes.length - 1;
int moreSpecific = 0; Class<?> msType, cType;
for ( int i = 0; i < last; i++ ) {
msType = msTypes[i]; cType = cTypes[i];
if ( msType == cType ) ;
else if ( msType.isAssignableFrom(cType) ) {
moreSpecific++; /* continue; */
}
else if ( cType.isAssignableFrom(msType) ) {
moreSpecific--; /* continue; */
}
/* return false; */
}

if ( last >= 0 ) { // last argument :
msType = msTypes[last]; cType = cTypes[last];
if ( lastArgProc ) {
if ( cType.isAssignableFrom(RubyProc.class) ) {
if ( ! msType.isAssignableFrom(RubyProc.class) ) moreSpecific++;
// return moreSpecific > 0;
}
else {
// NOTE: maybe this needs some implMethod arity matching here?
return null; // interface matching logic (can not decide)
}
}
else {
if ( msType == cType ) ;
else if ( msType.isAssignableFrom(cType) ) {
moreSpecific++;
}
else if ( cType.isAssignableFrom(msType) ) {
moreSpecific--;
}
}
}
return moreSpecific > 0 ? Boolean.TRUE : Boolean.FALSE;
}

private static <T extends ParameterTypes> T findMatchingCallableForArgsFallback(final Ruby runtime,
final T[] methods, final IRubyObject... args) {
T method = findCallable(methods, Exact, args);
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
* rights and limitations under the License.
*
* Copyright (C) 2006 Kresten Krab Thorup <krab@gnu.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -27,7 +27,11 @@
***** END LICENSE BLOCK *****/
package org.jruby.javasupport.proxy;

/** this interface is implemented by proxies generated from a JavaProxyClass */
/**
* Interface is implemented by proxies generated from a JavaProxyClass.
*
* @see JavaProxyClassFactory
*/
public interface InternalJavaProxy {

/**
@@ -40,6 +44,8 @@ public interface InternalJavaProxy {
*/
JavaProxyInvocationHandler ___getInvocationHandler();

final Object[] NO_ARGS = new Object[0];
// NOTE: used in JavaProxyClassFactory indirectly
// ... getStatic(JAVA_PROXY_TYPE, "NO_ARGS", ...)
static final Object[] NO_ARGS = new Object[0];

}
Original file line number Diff line number Diff line change
@@ -197,23 +197,25 @@ private JavaProxyClass generate(ClassLoader loader, String targetClassName,
Field proxy_class = clazz.getDeclaredField(PROXY_CLASS_FIELD_NAME);
proxy_class.setAccessible(true);
return (JavaProxyClass) proxy_class.get(clazz);
} catch (Exception ex) {
}
catch (Exception ex) {
InternalError ie = new InternalError();
ie.initCause(ex);
throw ie;
}
}

private static String targetClassName(final Class clazz) {
private static String targetClassName(final Class<?> clazz) {
// We always prepend an org.jruby.proxy package to the beginning
// because java and javax packages are protected and signed
// jars prevent us generating new classes with those package
// names. See JRUBY-2439.
final String pkgName = proxyPackageName(clazz);
final String fullName = clazz.getName();
int ix = fullName.lastIndexOf('.');
String className = ix == -1 ? fullName : fullName.substring(ix + 1);
return pkgName + '.' + className + "$Proxy" + nextId();
final int idx = fullName.lastIndexOf('.');
String className = idx == -1 ? fullName : fullName.substring(idx + 1);
return proxyPackageName(fullName)
.append('.').append(className)
.append("$Proxy").append(nextId()).toString();
}

private static final Method defineClassMethod;
@@ -266,12 +268,17 @@ private ClassWriter beginProxyClass(final String className,
toInternalClassName(superClass),
interfaceNamesForProxyClass(interfaces));

cw.visitField(Opcodes.ACC_PRIVATE, INVOCATION_HANDLER_FIELD_NAME,
INVOCATION_HANDLER_TYPE.getDescriptor(), null, null).visitEnd();
// private final JavaProxyInvocationHandler __handler;
cw.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL,
INVOCATION_HANDLER_FIELD_NAME,
INVOCATION_HANDLER_TYPE.getDescriptor(), null, null
).visitEnd();

cw.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
PROXY_CLASS_FIELD_NAME, PROXY_CLASS_TYPE.getDescriptor(), null,
null).visitEnd();
// private static JavaProxyClass __proxy_class;
cw.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL,
PROXY_CLASS_FIELD_NAME,
PROXY_CLASS_TYPE.getDescriptor(), null, null
).visitEnd();

return cw;
}
@@ -282,6 +289,7 @@ private String[] interfaceNamesForProxyClass(final Class[] interfaces) {
for (int i = 0; i < interfaces.length; i++) {
interfaceNames[i] = toInternalClassName(interfaces[i]);
}
// all proxies implement our InternalJavaProxy interface :
interfaceNames[interfaces.length] = toInternalClassName(InternalJavaProxy.class);

return interfaceNames;
@@ -296,8 +304,11 @@ private void generateProxyMethods(Class superClass,
}
}

/**
* @see InternalJavaProxy
*/
private void generateGetInvocationHandler(Type selfType, ClassVisitor cw) {
// make getter for handler
// make getter for handler (due implements InternalJavaProxy)
GeneratorAdapter gh = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
new org.objectweb.asm.commons.Method("___getInvocationHandler",
INVOCATION_HANDLER_TYPE, EMPTY_TYPE_ARRAY), null,
@@ -309,8 +320,11 @@ private void generateGetInvocationHandler(Type selfType, ClassVisitor cw) {
gh.endMethod();
}

/**
* @see InternalJavaProxy
*/
private void generateGetProxyClass(Type selfType, ClassVisitor cw) {
// make getter for proxy class
// make getter for proxy class (due implements InternalJavaProxy)
GeneratorAdapter gpc = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
new org.objectweb.asm.commons.Method("___getProxyClass",
PROXY_CLASS_TYPE, EMPTY_TYPE_ARRAY), null,
@@ -486,6 +500,7 @@ private Class[] generateConstructor(Type selfType, Constructor constructor, Clas

ga.loadThis();
ga.loadArg(superConstructorParameterTypes.length);

ga.putField(selfType, INVOCATION_HANDLER_FIELD_NAME, INVOCATION_HANDLER_TYPE);

// do a void return
@@ -795,11 +810,12 @@ private static String packageName(String clazzName) {
return clazzName.substring(0, idx);
}

private static String proxyPackageName(Class clazz) {
String clazzName = clazz.getName();
int idx = clazzName.lastIndexOf('.');
if ( idx == -1 ) return "org.jruby.proxy";
return "org.jruby.proxy." + clazzName.substring(0, idx);
private static StringBuilder proxyPackageName(final String className) {
final String proxyPackagePrefix = "org.jruby.proxy";
final StringBuilder str = new StringBuilder(proxyPackagePrefix.length() + className.length() + 8);
final int idx = className.lastIndexOf('.');
str.append(proxyPackagePrefix);
return idx == -1 ? str : str.append('.').append(className.substring(0, idx));
}

/**
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
* rights and limitations under the License.
*
* Copyright (C) 2006 Kresten Krab Thorup <krab@gnu.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -28,17 +28,20 @@

package org.jruby.javasupport.proxy;

import java.lang.reflect.InvocationHandler;

import org.jruby.runtime.builtin.IRubyObject;

/**
* A proxy invocation handler for JRuby.
*
* @see java.lang.reflect.InvocationHandler
*/
public interface JavaProxyInvocationHandler {

IRubyObject getOrig();

/**
* Similar to java.lang.reflect.InvocationHandler
*
* Similar to {@link java.lang.reflect.InvocationHandler}
*
* @param receiver
* @param method
* @param args
26 changes: 14 additions & 12 deletions core/src/main/ruby/jruby/java/core_ext/module.rb
Original file line number Diff line number Diff line change
@@ -7,14 +7,17 @@ class Module
# package will become available in this class/module, unless a constant
# with the same name as a Java class is already defined.
#
def include_package(package_name)
def include_package(package)
package = package.package_name if package.respond_to?(:package_name)

if defined? @included_packages
@included_packages << package_name
@included_packages << package
return
end
@included_packages = [package_name]

@included_packages = [ package ]
@java_aliases ||= {}

def self.const_missing(constant)
real_name = @java_aliases[constant] || constant

@@ -23,7 +26,7 @@ def self.const_missing(constant)

@included_packages.each do |package|
begin
java_class = JavaUtilities.get_java_class(package + '.' + real_name.to_s)
java_class = JavaUtilities.get_java_class("#{package}.#{real_name}")
rescue NameError
# we only rescue NameError, since other errors should bubble out
last_error = $!
@@ -44,20 +47,19 @@ def self.const_missing(constant)
end
end
end

# Imports the package specified by +package_name+, first by trying to scan JAR resources
# for the file in question, and failing that by adding a const_missing hook
# to try that package when constants are missing.
def import(package_name, &b)
def import(package_name, &block)
if package_name.respond_to?(:java_class) || (String === package_name && package_name.split(/\./).last =~ /^[A-Z]/)
return super(package_name, &b)
return super(package_name, &block)
end

package_name = package_name.package_name if package_name.respond_to?(:package_name)
return include_package(package_name, &b)
include_package(package_name, &block)
end

def java_alias(new_id, old_id)
@java_aliases[new_id] = old_id
(@java_aliases ||= {})[new_id] = old_id
end

end
2 changes: 1 addition & 1 deletion lib/pom.rb
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ def version

default_gems =
[
ImportedGem.new( 'jruby-openssl', '0.9.8', true ),
ImportedGem.new( 'jruby-openssl', '0.9.10', true ),
ImportedGem.new( 'jruby-readline', '1.0', false ),
ImportedGem.new( 'rake', 'rake.version', true ),
ImportedGem.new( 'rdoc', 'rdoc.version', true ),
2 changes: 1 addition & 1 deletion lib/pom.xml
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ DO NOT MODIFIY - GENERATED CODE
<dependency>
<groupId>rubygems</groupId>
<artifactId>jruby-openssl</artifactId>
<version>0.9.8</version>
<version>0.9.10</version>
<type>gem</type>
<scope>provided</scope>
<exclusions>
91 changes: 91 additions & 0 deletions spec/java_integration/interfaces/java8_methods_spec.rb
Original file line number Diff line number Diff line change
@@ -20,6 +20,47 @@
src = <<-JAVA
public class Java8Implemtor implements Java8Interface {
public String bar() { return getClass().getSimpleName(); }
// re-using the same class for proc-impl testing
public static Object withConsumerCall(Integer i, java.util.function.IntConsumer c) {
c.accept(i * 10); return i + 1;
}
public static boolean withPredicateCall(Object obj, java.util.function.Predicate<Object> p) {
// TODO following line fails (obviously due test method in Ruby) :
// ArgumentError: wrong number of arguments (1 for 2)
// org/jruby/gen/InterfaceImpl817905333.gen:13:in `test'
return p.test(obj);
}
public static String ambiguousCall1(String str, java.util.Map<?, ?> map) {
return "ambiguousWithMap";
}
public static String ambiguousCall1(String str, java.util.function.Consumer<StringBuilder> c) {
StringBuilder builder = new StringBuilder(str);
c.accept(builder.append("ambiguousWithConsumer")); return builder.toString();
}
public static String ambiguousCall2(CharSequence str, java.util.function.Consumer<StringBuilder> c) {
StringBuilder builder = new StringBuilder(str);
c.accept(builder.append("ambiguousWithConsumer")); return builder.toString();
}
public static String ambiguousCall2(String str, java.util.Map<?, ?> map) {
return "ambiguousWithMap";
}
public static String ambiguousCall3(CharSequence str, java.util.function.Consumer<StringBuilder> c) {
StringBuilder builder = new StringBuilder(str);
c.accept(builder.append("ambiguousWithConsumer")); return builder.toString();
}
public static String ambiguousCall3(String str, java.util.Map<?, ?> map) {
return "ambiguousWithMap";
}
public static String ambiguousCall3(String str, java.util.function.DoubleBinaryOperator op) {
return "ambiguousWithBinaryOperator";
}
}
JAVA
files << (file = "#{@tmpdir}/Java8Implemtor.java"); File.open(file, 'w') { |f| f.print(src) }
@@ -67,6 +108,56 @@
expect(impl.java_send(:foo, [ java.lang.Object ], 11)).to eq("11foo Java8Implemtor")
end

it "works with java.util.function-al interface with proc impl" do
expect( Java::Java8Implemtor.withConsumerCall(1) do |i|
expect(i).to eql 10
end ).to eql 2

pending "TODO: Predicate#test won't work as it collides with Ruby method"

ret = Java::Java8Implemtor.withPredicateCall([ ]) { |obj| obj.empty? }
expect( ret ).to be true
ret = Java::Java8Implemtor.withPredicateCall('x') { |obj| obj.empty? }
expect( ret ).to be false
end

it "does not consider Map vs func-type Consumer ambiguous" do
output = with_stderr_captured do # exact match should not warn :
ret = Java::Java8Implemtor.ambiguousCall1('') do |c|
c.append('+proc')
end
expect( ret ).to eql "ambiguousWithConsumer+proc"
end
expect( output.index('ambiguous') ).to be nil

output = with_stderr_captured do # exact match should not warn :
ret = Java::Java8Implemtor.ambiguousCall2('') do |c|
c.append('+proc')
end
expect( ret ).to eql "ambiguousWithConsumer+proc"
end
expect( output.index('ambiguous') ).to be nil

output = with_stderr_captured do # exact match should not warn :
ret = Java::Java8Implemtor.ambiguousCall3('') do |c|
c.append('+proc')
end
expect( ret ).to eql "ambiguousWithConsumer+proc"
end
expect( output.index('ambiguous') ).to be nil
end

def with_stderr_captured
stderr = $stderr; require 'stringio'
begin
$stderr = StringIO.new
yield
$stderr.string
ensure
$stderr = stderr
end
end

def javac_compile(files)
compiler = javax.tools.ToolProvider.getSystemJavaCompiler
fmanager = compiler.getStandardFileManager(nil, nil, nil)
6 changes: 2 additions & 4 deletions spec/java_integration/packages/access_spec.rb
Original file line number Diff line number Diff line change
@@ -17,10 +17,8 @@
end

it "can be imported using 'include_package package.module" do
skip "does not work; probably should for consistency?" do
m = Module.new { include_package java.lang }
expect(m::System).to respond_to 'getProperty'
end
m = Module.new { include_package java.lang }
expect(m::System).to respond_to 'getProperty'
end

it "can be imported using 'include_package \"package.module\"'" do
1 change: 0 additions & 1 deletion test/externals/ruby1.9/excludes/OpenSSL/TestX509CRL.rb

This file was deleted.

2 changes: 0 additions & 2 deletions test/externals/ruby1.9/excludes/TestIntegration.rb

This file was deleted.

18 changes: 9 additions & 9 deletions test/jruby/test_command_line_switches.rb
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ def test_dash_little_c_checks_syntax_only
end
end
end

# TODO -l: no idea what line ending processing is
def test_dash_little_n_wraps_script_with_while_gets
# FIXME: currently fails on windows and IBM JDK
@@ -89,7 +89,7 @@ def test_dash_little_r_provides_program_name_to_loaded_library
end
end

# This test is difficult to indicate meaning with. I am calling
# This test is difficult to indicate meaning with. I am calling
# jgem, as it should not exist outside the jruby.bin directory.
def test_dash_big_S_executes_script_in_jruby_bin_dir
assert_match /^\d+\.\d+\.\d+/, `#{RUBY} -S jgem --version`
@@ -106,7 +106,7 @@ def test_dash_big_S_resolves_absolute___FILE___correctly
end

def test_dash_big_S_resolves_relative___FILE___correctly

with_temp_script(%q{puts __FILE__}) do |s|
Dir.chdir(Dir.tmpdir) do
relative_tmp = File.basename(s.path)
@@ -177,7 +177,7 @@ def test_dash_big_w_sets_warning_level
assert_match /warning/, jruby("-W2 #{s.path} 2>&1")
assert_equal 0, $?.exitstatus
end
end
end
end

def test_dash_big_x_sets_extended_options
@@ -221,7 +221,7 @@ def test_server_vm_option
end

# JRUBY-2648 [Note: Originally these tests had tests for default vm and
# also for -J options in addition to jruby options (-J-client versus
# also for -J options in addition to jruby options (-J-client versus
# --client). In other tests we test that -J works and passes thru and
# we should not assume to know what versions of Java will have as their
# default VM.
@@ -255,7 +255,7 @@ def test_args_with_rubyopt
ENV['RUBYOPT'] = rubyopt_org
end
end

# JRUBY-2821
def test_with_interesting_file_names
names = ["test-q", "test-d", "test--", "test-_", "test_U", "test_S_", "___D_",
@@ -306,7 +306,7 @@ def test_uppercase_exe
end
end
end

# JRUBY-4290
if (WINDOWS)
def test_uppercase_in_process
@@ -320,7 +320,7 @@ def test_uppercase_in_process
def test_rubyopts_with_require
rubyopt_org = ENV['RUBYOPT']
ENV['RUBYOPT'] = '-r rubygems'

args = "-e 'p 0'"
assert_nothing_raised { jruby(args) }
ensure
@@ -329,7 +329,7 @@ def test_rubyopts_with_require

# JRUBY-5517
def test_rubyopts_benchmark_cleared_in_child
return if IS_JAR_EXECUTION
return skip('jar execution') if IS_JAR_EXECUTION
rubyopt_org = ENV['RUBYOPT']
ENV['RUBYOPT'] = '-r benchmark'

23 changes: 21 additions & 2 deletions test/jruby/test_helper.rb
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ module TestHelper
# TODO: Consider how this should work if we have --windows or similiar
WINDOWS = RbConfig::CONFIG['host_os'] =~ /Windows|mswin/
SEPARATOR = WINDOWS ? '\\' : '/'
# using the classloader setup to determine whether it runs inside
# using the classloader setup to determine whether it runs inside
# ScriptingContainer or via commandline
IS_COMMAND_LINE_EXECUTION = JRuby.runtime.jruby_class_loader == java.lang.Thread.current_thread.context_class_loader
IS_JAR_EXECUTION = RbConfig::CONFIG['bindir'].match( /!\//) || RbConfig::CONFIG['bindir'].match( /:\//)
@@ -114,4 +114,23 @@ def run_in_sub_runtime(script)
def assert_in_sub_runtime(script)
assert run_in_sub_runtime(script)
end
end

# def self.included(base)
# if defined? Test::Unit::TestCase
# if base < Test::Unit::TestCase
# Test::Unit::TestCase.class_eval do
# unless method_defined?(:skip)
# if method_defined?(:omit)
# alias skip omit
# else
# def skip(msg = nil)
# warn "Skipped: #{caller[0]} #{msg}"
# end
# end
# end
# end
# end
# end
# end

end
17 changes: 17 additions & 0 deletions test/jruby/test_higher_javasupport.rb
Original file line number Diff line number Diff line change
@@ -56,6 +56,23 @@ def test_java_class_loading_and_class_name_collisions
assert_raises(NoMethodError) { Integer.new(10) }
end

def test_java_alias_prior_to_import
mod = Module.new do
java_alias :SYS, 'System'
import 'java.lang'
end
mod::SYS.currentTimeMillis # nothing raised
end

def test_include_package_with_package
mod = Module.new do
include_package java.util.concurrent
include_package Java::JavaUtilConcurrentAtomic
end
mod::ConcurrentSkipListMap.new
mod::AtomicInteger.new(666666)
end

Random = java.util.Random
Double = java.lang.Double
def test_constructors_and_instance_methods
20 changes: 17 additions & 3 deletions test/jruby/test_java_extension.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
require 'java'
require 'test/unit'
require 'test/jruby/test_helper'
require 'java'

class TestJavaExtension < Test::Unit::TestCase
include TestHelper

class TestParent < org.jruby.test.Parent
attr_accessor :result
@@ -272,21 +274,33 @@ def test_ruby_block_with_args_as_interface
assert listing.size >= 0
end

class ExtendedClass < org.jruby.test.Abstract
class RubyConcrete < org.jruby.test.Abstract
def protected_method
"Ruby overrides java!"
end
end

def test_overriding_protected_method
a = ExtendedClass.new
a = RubyConcrete.new
begin
assert_equal "Ruby overrides java!", a.call_protected
rescue Exception => e
flunk "Exception raised: #{e}"
end
end

class CallAbstractInConstructor < org.jruby.test.Abstract
def initialize; super("call protected method in constructor!") end

def protected_method; "HELLO!" end
end

def test_calling_abstract_method_in_java_constructor
return skip('this leaking in super constructor (calling Ruby implemented methods)')
a = CallAbstractInConstructor.new
assert_equal "HELLO!", a.result
end

def test_map_interface_to_array
hash = {"one"=>"two","three"=>"four"}
map = java.util.HashMap.new(hash)
34 changes: 19 additions & 15 deletions test/jruby/test_load_gem_extensions.rb
Original file line number Diff line number Diff line change
@@ -17,20 +17,24 @@ def teardown
$LOAD_PATH.concat(@prev_load_path)
end

# running this with embedded JRuby brings: NoMethodError: undefined method `skip' for #<TestLoad:0x28434905>
unless JRuby.runtime.instance_config.jruby_home =~ /META-INF/
def test_require_extension_file_via_uri_protocol
skip 'needs jruby-home from filesystem' if JRuby.runtime.instance_config.jruby_home =~ /META-INF/
require 'uri:file:./lib/ruby/stdlib/json/ext/parser'
# just check if extension class exists
JSON::Ext::Parser
end

def test_require_extension_file_via_uri_classloader_protocol
skip 'needs jruby-home from filesystem' if JRuby.runtime.instance_config.jruby_home =~ /META-INF/
require 'uri:classloader:/lib/ruby/stdlib/json/ext/generator'
# just check if extension class exists
JSON::Ext::Generator
end
def test_require_extension_file_via_uri_protocol
return skip 'needs jruby-home from filesystem' if inside_jar?
require 'uri:file:./lib/ruby/shared/json/ext/parser'
# just check if extension class exists
JSON::Ext::Parser
end

def test_require_extension_file_via_uri_classloader_protocol
return skip 'needs jruby-home from filesystem' if inside_jar?
require 'uri:classloader:/lib/ruby/shared/json/ext/generator'
# just check if extension class exists
JSON::Ext::Generator
end

private

def inside_jar?
JRuby.runtime.instance_config.jruby_home =~ /META-INF/
end

end
55 changes: 40 additions & 15 deletions test/jruby/test_zlib.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
require 'test/unit'
require 'test/jruby/test_helper'
require 'zlib'
require 'stringio'
require 'tempfile'

class TestZlib < Test::Unit::TestCase
include TestHelper

def teardown; File.unlink @filename if @filename; end

def test_inflate_deflate
@@ -12,7 +15,7 @@ def test_inflate_deflate
assert_equal(s, Zlib::Inflate.inflate(Zlib::Deflate.deflate(s, level)))
end
end

# Zlib::Inflate uses org.jruby.util.ZlibInflate for low-level decompression logic, which is built around
# java.util.zip.Inflater.
#
@@ -33,46 +36,46 @@ def test_inflate_should_be_finished_after_decompressing_full_unwrapped_stream
# This is not the ZIP archive itself; rather, it is the compressed representation
# of a deflated file inside the archive.
data = "K0ktLlFIzs8tKEotLs7Mz1MoLinKzEvnKqGxOABQSwECFwMUAAIACAAxKng3dpOMHR0AAAB4AAAACAANAAAAAAABAAAApIEAAAAAdGVzdC50eHRVVAUAAz76R0dVeAAAUEsFBgAAAAABAAEAQwAAAFgAAAAAAA=="

inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)

stream = StringIO.new(data.unpack('m*')[0])
assert_equal(actual, inflater.inflate(stream.read(nil, '')), "Unexpected result of decompression.")
assert(inflater.finished?, "Inflater should be finished after inflating all input.")
end

def test_gzip_reader_writer
@filename = "____temp_zlib_file";

Zlib::GzipWriter.open(@filename) { |z| z.puts 'HEH' }
Zlib::GzipReader.open(@filename) do |z|
assert_equal("HEH\n", z.gets)
assert_nil z.getc
assert z.eof?
end
File.unlink(@filename)

Zlib::GzipWriter.open(@filename) { |z| z.write "HEH\n" }
Zlib::GzipReader.open(@filename) do |z|
assert_equal("HEH\n", z.gets)
assert_nil z.getc
assert z.eof?
end
File.unlink(@filename)


z = Zlib::GzipWriter.open(@filename)
z.puts 'HOH'
z.puts 'foo|bar'
z.close

z = Zlib::GzipReader.open(@filename)
assert_equal("HOH\n", z.gets)
assert_equal("foo|", z.gets("|"))
assert_equal("bar\n", z.gets)
z.close
end

def test_native_exception_from_zlib_on_broken_header
corrupt = StringIO.new
corrupt.write('borkborkbork')
@@ -83,6 +86,21 @@ def test_native_exception_from_zlib_on_broken_header
end
end

# def test_deflate_positive_winbits
# d = Zlib::Deflate.new(Zlib::DEFAULT_COMPRESSION, Zlib::MAX_WBITS)
# d << 'hello'
# res = d.finish
# assert_equal("x\234\313H\315\311\311\a\000\006,\002\025", res)
# end
#
# # negative winbits means no header and no checksum.
# def test_deflate_negative_winbits
# d = Zlib::Deflate.new(Zlib::DEFAULT_COMPRESSION, -Zlib::MAX_WBITS)
# d << 'hello'
# res = d.finish
# assert_equal("\313H\315\311\311\a\000", res)
# end

# JRUBY-2228
def test_gzipreader_descriptor_leak
@filename = "____temp_zlib_file";
@@ -100,7 +118,7 @@ def test_gzipreader_descriptor_leak

def test_wrap
content = StringIO.new "", "r+"

Zlib::GzipWriter.wrap(content) do |io|
io.write "hello\nworld\n"
end
@@ -114,7 +132,7 @@ def test_wrap
assert gin.eof?
gin.close
end

def test_each_line_no_block
@filename = "____temp_zlib_file";
Zlib::GzipWriter.open(@filename) { |io| io.write "hello\nworld\n" }
@@ -124,12 +142,12 @@ def test_each_line_no_block
lines << line
end
z.close

assert_equal(2, lines.size, lines.inspect)
assert_equal("hello\n", lines.first)
assert_equal("world\n", lines.last)
end

def test_each_line_block
@filename = "____temp_zlib_file";
Zlib::GzipWriter.open(@filename) { |io| io.write "hello\nworld\n" }
@@ -141,7 +159,7 @@ def test_each_line_block
end
assert_equal(2, lines.size, lines.inspect)
end

def test_empty_line
@filename = "____temp_zlib_file";
Zlib::GzipWriter.open(@filename) { |io| io.write "hello\nworld\n\ngoodbye\n" }
@@ -417,7 +435,7 @@ def self.create_gzip_stream(string)
def test_dup
d1 = Zlib::Deflate.new

data = "foo" * 10
data = "foo" * 10
d1 << data
d2 = d1.dup

@@ -669,7 +687,7 @@ def test_deflate_sync_flush_inflate
i = Zlib::Inflate.new(15+16)
"a".upto("z") do |c|
assert_equal(c, i.inflate(d.deflate(c, Zlib::SYNC_FLUSH)))
end
end
i.inflate(d.finish)
i.close
d.close
@@ -886,4 +904,11 @@ def test_wrong_length_split_trailer
z.inflate("\x00")
end
end

# def test_deflate_full_flush
# z = Zlib::Deflate.new(8, 15)
# s = z.deflate("f", Zlib::FULL_FLUSH)
# s << z.deflate("b", Zlib::FINISH)
# assert_equal("x\332J\003\000\000\000\377\377K\002\000\0010\000\311", s)
# end
end
File renamed without changes.
2 changes: 1 addition & 1 deletion test/mri/psych/json/test_stream.rb
Original file line number Diff line number Diff line change
@@ -65,7 +65,7 @@ def test_list_to_json
@stream.push list

json = @io.string
assert_match(/]$/, json)
assert_match(/\]$/, json)
assert_match(/^--- \[/, json)
assert_match(/["]one["]/, json)
assert_match(/["]two["]/, json)
29 changes: 24 additions & 5 deletions test/org/jruby/test/Abstract.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
package org.jruby.test;

public abstract class Abstract {
public String call_protected() {
return protected_method();
}

abstract protected String protected_method();
}
public String result = null;

public Abstract() { super(); }

public Abstract(boolean callProtected) {
// NOTE: the leaking this anti-pattern :
if ( callProtected ) result = call_protected();
}

public Abstract(final String result) {
this(check(result));
//if ( this.result == null ) this.result = result;
}

private static boolean check(final String name) {
return name.replace('_', ' ').contains("call protected method");
}

public String call_protected() {
return protected_method();
}

protected abstract String protected_method() ;
}

0 comments on commit 1889650

Please sign in to comment.