Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 023d74d8e8ae
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f6f3591f639b
Choose a head ref

Commits on Jul 6, 2015

  1. adds rmvn command since it comes with ruby-maven and make regular bin…

    …/mvn inside the gem executable
    mkristian committed Jul 6, 2015
    Copy the full SHA
    d0a2955 View commit details
  2. use user.dir as CWD when code is inside a jar on backquote execution

    when inside a jar the CWD is uri:classloader:/ and executing a system
    command can not change into this CWD. use java system property user.dir
    in such a case
    
    Sponsored by Lookout Inc.
    mkristian committed Jul 6, 2015
    Copy the full SHA
    1fd27e6 View commit details
  3. Copy the full SHA
    08ecc3c View commit details

Commits on Jul 7, 2015

  1. Bump for 1.7.21

    enebo committed Jul 7, 2015
    Copy the full SHA
    e5955c8 View commit details
  2. Off by one error in proc to interface optimization for 2 and 3 arity …

    …paths (still missing test)
    enebo committed Jul 7, 2015
    1
    Copy the full SHA
    a741a82 View commit details
  3. Copy the full SHA
    424661f View commit details

Commits on Jul 8, 2015

  1. Copy the full SHA
    d51c9bf View commit details
  2. Update for next dev cycle

    enebo committed Jul 8, 2015
    Copy the full SHA
    bcc9b29 View commit details
  3. Copy the full SHA
    8e4b0bd View commit details

Commits on Jul 9, 2015

  1. Copy the full SHA
    6182486 View commit details

Commits on Jul 10, 2015

  1. Copy the full SHA
    207b8be View commit details

Commits on Jul 14, 2015

  1. Copy the full SHA
    3b68bdb View commit details
  2. Copy the full SHA
    2a6a6f5 View commit details
  3. Copy the full SHA
    cef1af3 View commit details
  4. make sure -Dorg.jruby.embed.compat.version=1.8 works

    with (JSR223) scripting-container (fixes #1365)
    kares committed Jul 14, 2015
    Copy the full SHA
    05531ea View commit details
  5. Copy the full SHA
    fe236a6 View commit details
  6. Copy the full SHA
    30cfff8 View commit details
  7. Copy the full SHA
    935553d View commit details

Commits on Jul 15, 2015

  1. spec for regression in proc to iface optimization

    complements commit a741a82
    kares committed Jul 15, 2015
    Copy the full SHA
    c79610c View commit details
  2. Copy the full SHA
    1d90f9f View commit details
  3. Copy the full SHA
    84a2051 View commit details
  4. Copy the full SHA
    27dc383 View commit details
  5. Copy the full SHA
    db7c111 View commit details
  6. Copy the full SHA
    6a9f22e View commit details
  7. Fixes #3135. Provide sha256 sums

    enebo committed Jul 15, 2015
    Copy the full SHA
    eaaa4f0 View commit details
  8. Copy the full SHA
    772bbcc View commit details
  9. Copy the full SHA
    106cdeb View commit details

Commits on Jul 16, 2015

  1. Copy the full SHA
    3264692 View commit details
  2. Copy the full SHA
    e893bb1 View commit details
  3. Copy the full SHA
    6c7320b View commit details
  4. avoid reflection in getFunctionalInterface

    ... while checking whether method.isDefault()
    kares committed Jul 16, 2015
    Copy the full SHA
    ddbed4b View commit details
  5. improve resolving functional-interfaces

    if there's an abstract method implemented by the Object.class
    (e.g. equals) continue looking for the "real" single method
    kares committed Jul 16, 2015
    Copy the full SHA
    f1353e3 View commit details
  6. support for matching proc-to-iface methods by arity

    ... of the block (see #3136) when there are 2 method with different
    interface type signature we can improve current (unpredictable) logic
    
    state prior to this commit is printing a ambiguous warning, the picked
    method depends on returned getMethods order
    kares committed Jul 16, 2015
    Copy the full SHA
    c054d50 View commit details
  7. method cache hash calc needs to acount for Proc

    so that we cache correctly cases with proc-to-iface dispatch
    (per Proc's arity)
    
    as a side effect redundant null checks were removed
    and the calculation should now compute the same when using args[]
    or the overloaded version (with args splatted)
    
    (closing #3136)
    kares committed Jul 16, 2015
    Copy the full SHA
    bd50c26 View commit details
  8. Copy the full SHA
    950cf3f View commit details
  9. no need for "" + ...

    kares committed Jul 16, 2015
    Copy the full SHA
    aedbf26 View commit details

Commits on Jul 17, 2015

  1. Merge branch 'jruby-1_7' into master

    * jruby-1_7: (36 commits)
      no need for "" + ...
      keep the test Java 6 compilable + more asserts
      method cache hash calc needs to acount for Proc
      support for matching proc-to-iface methods by arity
      improve resolving functional-interfaces
      avoid reflection in getFunctionalInterface
      some Java.getFunctionalInterfaceMethod asserts
      introduce a getFunctionalInterfaceMethod helper
      generix-ize some of JavaUtil's static helpers
      Make sure windows files generate signatures as part of post_process_artifacts
      Doh...how did this not get added
      Fixes #3135. Provide sha256 sums
      yet another multiple args proc-to-iface spec
      less deprecation warnings from implementation_spec
      clean + avoid deprecation warn in executor_spec
      less rspec deprecation warnings from ant spec
      avoid File#listFiles in spec since it's ambiguous
      spec for regression in proc to iface optimization
      Fix references to old mailing lists.
      Return nil when waitpid returns 0. Fixes #3117.
      ...
    
    Conflicts:
    	VERSION
    	antlib/extra.xml
    	core/pom.xml
    	core/src/main/java/org/jruby/RubyProcess.java
    	core/src/main/java/org/jruby/embed/util/SystemPropertyCatcher.java
    	core/src/test/java/org/jruby/embed/ScriptingContainerTest.java
    	docs/man/pom.xml
    	docs/pom.xml
    	ext/pom.xml
    	ext/readline/pom.xml
    	ext/ripper/pom.xml
    	lib/pom.xml
    	maven/jruby-complete/pom.xml
    	maven/jruby-dist/pom.xml
    	maven/jruby-dist/src/main/assembly/jruby.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
    	test/pom.xml
    	test/test_backquote.rb
    	test/test_kernel.rb
    kares committed Jul 17, 2015
    Copy the full SHA
    bfb6c91 View commit details
  2. Merge branch 'master' of github.com:jruby/jruby

    * 'master' of github.com:jruby/jruby:
      split tests for jruby-jars and see if they are more stable on travis
      fix permission of lib/ruby/maven-home/bin/mvn
    kares committed Jul 17, 2015
    Copy the full SHA
    f6f3591 View commit details
152 changes: 77 additions & 75 deletions core/src/main/java/org/jruby/RubyProcess.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -45,7 +45,8 @@
* @author Yoko Harada <yokolet@gmail.com>
*/
public class EmbedRubyInterfaceAdapterImpl implements EmbedRubyInterfaceAdapter {
private ScriptingContainer container;

private final ScriptingContainer container;

public EmbedRubyInterfaceAdapterImpl(ScriptingContainer container) {
this.container = container;
@@ -62,21 +63,24 @@ public <T> T getInstance(Object receiver, Class<T> clazz) {
if (clazz == null || !clazz.isInterface()) {
return null;
}
Ruby runtime = container.getProvider().getRuntime();
Object o;
final Ruby runtime = container.getProvider().getRuntime();
final Object obj;
if (receiver == null || receiver instanceof RubyNil) {
o = JavaEmbedUtils.rubyToJava(runtime, runtime.getTopSelf(), clazz);
obj = JavaEmbedUtils.rubyToJava(runtime, runtime.getTopSelf(), clazz);
} else if (receiver instanceof IRubyObject) {
o = JavaEmbedUtils.rubyToJava(runtime, (IRubyObject) receiver, clazz);
obj = JavaEmbedUtils.rubyToJava(runtime, (IRubyObject) receiver, clazz);
} else {
IRubyObject rubyReceiver = JavaUtil.convertJavaToRuby(runtime, receiver);
o = JavaEmbedUtils.rubyToJava(runtime, rubyReceiver, clazz);
obj = JavaEmbedUtils.rubyToJava(runtime, rubyReceiver, clazz);
}
String name = clazz.getName();
final String name = clazz.getName();
final ClassLoader loader = obj.getClass().getClassLoader();
try {
Class<T> c = (Class<T>) Class.forName(name, true, o.getClass().getClassLoader());
return c.cast(o);
} catch (ClassNotFoundException e) {
@SuppressWarnings("unchecked")
Class<T> klass = (Class<T>) Class.forName(name, true, loader);
return klass.cast(obj);
}
catch (ClassNotFoundException e) {
throw new InvokeFailedException(e);
}
}
Original file line number Diff line number Diff line change
@@ -61,10 +61,11 @@
* @author Yoko Harada <yokolet@gmail.com>
*/
public class EmbedRubyObjectAdapterImpl implements EmbedRubyObjectAdapter {
private RubyObjectAdapter adapter = JavaEmbedUtils.newObjectAdapter();
private ScriptingContainer container;

public enum MethodType {
private final RubyObjectAdapter adapter = JavaEmbedUtils.newObjectAdapter();
private final ScriptingContainer container;

public static enum MethodType {
CALLMETHOD_NOARG,
CALLMETHOD,
CALLMETHOD_WITHBLOCK,
@@ -79,15 +80,15 @@ public EmbedRubyObjectAdapterImpl(ScriptingContainer container) {
public boolean isKindOf(IRubyObject value, RubyModule rubyModule) {
return adapter.isKindOf(value, rubyModule);
}

public IRubyObject[] convertToJavaArray(IRubyObject array) {
return adapter.convertToJavaArray(array);
}

public RubyInteger convertToRubyInteger(IRubyObject obj) {
return adapter.convertToRubyInteger(obj);
}

public RubyString convertToRubyString(IRubyObject obj) {
return adapter.convertToRubyString(obj);
}
@@ -195,7 +196,7 @@ public <T> T callMethod(Object receiver, String methodName, Class<T> returnType,
throw new InvokeFailedException(e);
}
}

public <T> T callMethod(Object receiver, String methodName, Object[] args, Class<T> returnType, EmbedEvalUnit unit) {
try {
RubyObject rubyReceiver = getReceiverObject(receiver);
@@ -268,7 +269,7 @@ public Object callMethod(Object receiver, String methodName, Block block, Object
throw new InvokeFailedException(e);
}
}

public <T> T runRubyMethod(Class<T> returnType, Object receiver, String methodName, Block block, Object... args) {
try {
RubyObject rubyReceiver = (RubyObject)JavaEmbedUtils.javaToRuby(container.getProvider().getRuntime(), receiver);
@@ -289,7 +290,7 @@ private <T> T call(MethodType type, Class<T> returnType, RubyObject rubyReceiver
return null;
}
Ruby runtime = container.getProvider().getRuntime();

boolean sharing_variables = true;
Object obj = container.getAttribute(AttributeName.SHARING_VARIABLES);
if (obj != null && obj instanceof Boolean && ((Boolean) obj) == false) {
@@ -325,7 +326,7 @@ private <T> T call(MethodType type, Class<T> returnType, RubyObject rubyReceiver
}
}
}

private RubyObject getReceiverObject(Object receiver) {
Ruby runtime = container.getProvider().getRuntime();
if (receiver == null || !(receiver instanceof IRubyObject)) {
Original file line number Diff line number Diff line change
@@ -36,7 +36,6 @@
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.net.URL;

import org.jruby.Ruby;
@@ -71,8 +70,9 @@
* @author Yoko Harada <yokolet@gmail.com>
*/
public class EmbedRubyRuntimeAdapterImpl implements EmbedRubyRuntimeAdapter {
private RubyRuntimeAdapter adapter = JavaEmbedUtils.newRuntimeAdapter();
private ScriptingContainer container;

private final RubyRuntimeAdapter adapter = JavaEmbedUtils.newRuntimeAdapter();
private final ScriptingContainer container;

public EmbedRubyRuntimeAdapterImpl(ScriptingContainer container) {
this.container = container;
@@ -164,10 +164,10 @@ private EmbedEvalUnit runParser(Object input, String filename, int... lines) {
if (filename == null || filename.length() == 0) {
filename = container.getScriptFilename();
}
Ruby runtime = container.getProvider().getRuntime();
IAccessor d = new ValueAccessor(RubyString.newString(runtime, filename));
runtime.getGlobalVariables().define("$PROGRAM_NAME", d, GlobalVariable.Scope.GLOBAL);
runtime.getGlobalVariables().define("$0", d, GlobalVariable.Scope.GLOBAL);
final Ruby runtime = container.getProvider().getRuntime();
IAccessor $0 = new ValueAccessor(RubyString.newString(runtime, filename));
runtime.getGlobalVariables().define("$PROGRAM_NAME", $0, GlobalVariable.Scope.GLOBAL);
runtime.getGlobalVariables().define("$0", $0, GlobalVariable.Scope.GLOBAL);

int line = 0;
if (lines != null && lines.length > 0) {
@@ -183,7 +183,7 @@ private EmbedEvalUnit runParser(Object input, String filename, int... lines) {
if (sharing_variables) {
scope = getManyVarsDynamicScope(container, 0);
}
Node node = null;
final Node node;
if (input instanceof String) {
node = runtime.parseEval((String)input, filename, scope, line);
} else {
@@ -233,7 +233,7 @@ static ManyVarsDynamicScope getManyVarsDynamicScope(ScriptingContainer container

// JRUBY-5501: ensure we've set up a cref for the scope too
scope.getStaticScope().determineModule();

return scope;
}

87 changes: 39 additions & 48 deletions core/src/main/java/org/jruby/embed/util/SystemPropertyCatcher.java
Original file line number Diff line number Diff line change
@@ -65,18 +65,12 @@ public class SystemPropertyCatcher {
public static LocalContextScope getScope(LocalContextScope defaultScope) {
LocalContextScope scope = defaultScope;
String s = SafePropertyAccessor.getProperty(PropertyName.LOCALCONTEXT_SCOPE.toString());
if (s == null) {
return scope;
}
if ("singlethread".equalsIgnoreCase(s)) {
return LocalContextScope.SINGLETHREAD;
} else if ("singleton".equalsIgnoreCase(s)) {
return LocalContextScope.SINGLETON;
} else if ("threadsafe".equalsIgnoreCase(s)) {
return LocalContextScope.THREADSAFE;
} else if ("concurrent".equalsIgnoreCase(s)) {
return LocalContextScope.CONCURRENT;
}
if (s == null) return scope;

if ("singlethread".equalsIgnoreCase(s)) return LocalContextScope.SINGLETHREAD;
if ("singleton".equalsIgnoreCase(s)) return LocalContextScope.SINGLETON;
if ("threadsafe".equalsIgnoreCase(s)) return LocalContextScope.THREADSAFE;
if ("concurrent".equalsIgnoreCase(s)) return LocalContextScope.CONCURRENT;
return scope;
}

@@ -90,18 +84,12 @@ public static LocalContextScope getScope(LocalContextScope defaultScope) {
public static LocalVariableBehavior getBehavior(LocalVariableBehavior defaultBehavior) {
LocalVariableBehavior behavior = defaultBehavior;
String s = SafePropertyAccessor.getProperty(PropertyName.LOCALVARIABLE_BEHAVIOR.toString());
if (s == null) {
return behavior;
}
if ("global".equalsIgnoreCase(s)) {
return LocalVariableBehavior.GLOBAL;
} else if ("persistent".equalsIgnoreCase(s)) {
return LocalVariableBehavior.PERSISTENT;
} else if ("transient".equalsIgnoreCase(s)) {
return LocalVariableBehavior.TRANSIENT;
} else if ("bsf".equalsIgnoreCase(s)) {
return LocalVariableBehavior.BSF;
}
if (s == null) return behavior;

if ("global".equalsIgnoreCase(s)) return LocalVariableBehavior.GLOBAL;
if ("persistent".equalsIgnoreCase(s)) return LocalVariableBehavior.PERSISTENT;
if ("transient".equalsIgnoreCase(s)) return LocalVariableBehavior.TRANSIENT;
if ("bsf".equalsIgnoreCase(s)) return LocalVariableBehavior.BSF;
return behavior;
}

@@ -115,9 +103,7 @@ public static LocalVariableBehavior getBehavior(LocalVariableBehavior defaultBeh
public static boolean isLazy(boolean defaultLaziness) {
boolean lazy = defaultLaziness;
String s = SafePropertyAccessor.getProperty(PropertyName.LAZINESS.toString());
if (s == null) {
return lazy;
}
if (s == null) return lazy;
return Boolean.parseBoolean(s);
}

@@ -129,16 +115,18 @@ public static boolean isLazy(boolean defaultLaziness) {
*/

public static void setClassLoader(ScriptingContainer container) {
String s = SafePropertyAccessor.getProperty(PropertyName.CLASSLOADER.toString());
String loader = SafePropertyAccessor.getProperty(PropertyName.CLASSLOADER.toString());

// current should be removed later
if (s == null || "container".equals(s) || "current".equals(s)) { // default
if (loader == null || "container".equals(loader) || "current".equals(loader)) { // default
container.setClassLoader(container.getClass().getClassLoader());
return;
} else if ("context".equals(s)) {
}
if ("context".equals(loader)) {
container.setClassLoader(Thread.currentThread().getContextClassLoader());
return;
} else if ("none".equals(s)) {
}
if ("none".equals(loader)) {
return;
}
// if incorrect value is set, no classloader will set by ScriptingContainer.
@@ -154,16 +142,20 @@ public static void setClassLoader(ScriptingContainer container) {
public static void setConfiguration(ScriptingContainer container) {
LocalContextProvider provider = container.getProvider();
RubyInstanceConfig config = provider.getRubyInstanceConfig();
String s = SafePropertyAccessor.getProperty(PropertyName.COMPILEMODE.toString());
if (s != null) {
if ("jit".equalsIgnoreCase(s)) {
String mode = SafePropertyAccessor.getProperty(PropertyName.COMPILEMODE.toString());
if (mode != null) {
if ("jit".equalsIgnoreCase(mode)) {
config.setCompileMode(CompileMode.JIT);
} else if ("force".equalsIgnoreCase(s)) {
}
else if ("force".equalsIgnoreCase(mode)) {
config.setCompileMode(CompileMode.FORCE);
} else {
}
else {
config.setCompileMode(CompileMode.OFF);
}
}
// NOTE: no JRuby COMPAT version setting, since it no longer makes sense in 9K !
// String compat = SafePropertyAccessor.getProperty(PropertyName.COMPATVERSION.toString());
}

/**
@@ -192,11 +184,11 @@ public static String findJRubyHome(Object instance) {
String jrubyhome;
if ((jrubyhome = SafePropertyAccessor.getenv("JRUBY_HOME")) != null) {
return jrubyhome;
} else if ((jrubyhome = SafePropertyAccessor.getProperty("jruby.home")) != null) {
}
if ((jrubyhome = SafePropertyAccessor.getProperty("jruby.home")) != null) {
return jrubyhome;
} else {
return "uri:classloader://META-INF/jruby.home";
}
return "uri:classloader://META-INF/jruby.home";
}

public static String findFromJar(Object instance) {
@@ -209,7 +201,7 @@ public static String findFromJar(Object instance) {
if (resource == null) return null;
}

String location = null;
String location;
if (resource.getProtocol().equals("jar")) {
location = getPath(resource);
if (!location.startsWith("file:")) {
@@ -269,15 +261,14 @@ public static List<String> findLoadPaths() {
* @return true is the given name is correct to choose Ruby 1.9 version. Otherwise,
* returns false.
*/
@Deprecated
public static boolean isRuby19(String name) {
String n = name.toLowerCase();
Pattern p = Pattern.compile("j?ruby1[\\._]?9");
Matcher m = p.matcher(n);
if (m.matches()) {
return true;
} else {
return false;
}
return matches(name.toLowerCase(), "j?ruby1[\\._]?9");
}

private static boolean matches(final String name, final String pattern) {
Matcher matcher = Pattern.compile(pattern).matcher( name );
return matcher.matches();
}

/**
97 changes: 76 additions & 21 deletions core/src/main/java/org/jruby/java/dispatch/CallableSelector.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jruby.java.dispatch;

import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
@@ -13,6 +14,7 @@
import org.jruby.RubyFixnum;
import org.jruby.RubyFloat;
import org.jruby.RubyInteger;
import org.jruby.RubyProc;
import org.jruby.RubyString;
import org.jruby.javasupport.JavaCallable;
import org.jruby.javasupport.JavaClass;
@@ -22,6 +24,7 @@
import org.jruby.util.collections.IntHashMap;
import static org.jruby.util.CodegenUtils.getBoxType;
import static org.jruby.util.CodegenUtils.prettyParams;
import static org.jruby.javasupport.Java.getFunctionalInterfaceMethod;

/**
* Method selection logic for calling from Ruby to Java.
@@ -188,18 +191,27 @@ else if ( cType.isPrimitive() && msType.isAssignableFrom(getBoxType(cType)) ) {
ambiguous = true;
}
}

// somehow we can still decide e.g. if we got a RubyFixnum
// then (int) constructor shoudl be preffered over (float)
// then (int) constructor should be preferred over (float)
if ( ambiguous ) {
int msPref = 0, cPref = 0;
for ( int i = 0; i < msTypes.length; i++ ) {
final Class<?> msType = msTypes[i], cType = cTypes[i];
msPref += calcTypePreference(msType, args[i]);
cPref += calcTypePreference(cType, args[i]);
// special handling if we're dealing with Proc#impl :
final IRubyObject lastArg = args.length > 0 ? args[ args.length - 1 ] : null;
final T procToIfaceMatch = matchProcToInterfaceCandidate(lastArg, candidates);
if ( procToIfaceMatch != null ) {
mostSpecific = procToIfaceMatch; ambiguous = false;
}
else {
int msPref = 0, cPref = 0;
for ( int i = 0; i < msTypes.length; i++ ) {
final Class<?> msType = msTypes[i], cType = cTypes[i];
msPref += calcTypePreference(msType, args[i]);
cPref += calcTypePreference(cType, args[i]);
}
// for backwards compatibility we do not switch to cType as
// the better fit - we seem to lack tests on this front ...
if ( msPref > cPref ) ambiguous = false; // continue OUTER;
}
// for backwards compatibility we do not switch to cType as
// the better fit - we seem to lack tests on this front ...
if ( msPref > cPref ) ambiguous = false; // continue OUTER;
}
}
method = mostSpecific;
@@ -230,6 +242,39 @@ else if ( cType.isPrimitive() && msType.isAssignableFrom(getBoxType(cType)) ) {
return method;
}

private static <T extends ParameterTypes> T matchProcToInterfaceCandidate(
final IRubyObject lastArg, final List<T> candidates) {
if ( 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)
final int arity = ((RubyProc) lastArg).getBlock().arity().getValue();
T match = null;
for ( int i = 0; i < candidates.size(); i++ ) {
final T method = candidates.get(i);

final Class<?>[] params = method.getParameterTypes();

if ( params.length == 0 ) return null; // can not match (no args)
final Class<?> lastParam = params[ params.length - 1 ];

if ( ! lastParam.isInterface() ) return null; // can not match

final Method implMethod = getFunctionalInterfaceMethod(lastParam);
if ( implMethod != null ) {
// we're sure to have an interface in the end - match arg count :
// NOTE: implMethod.getParameterCount() on Java 8 would do ...
if ( implMethod.getParameterTypes().length == arity ) {
if ( match != null ) return null; // 2 with same arity (can not match)
match = method; // do not break here we want to check all
}
}
}
return match;
}
return null;
}

private static <T extends ParameterTypes> T findCallable(T[] callables, CallableAcceptor acceptor, IRubyObject[] args) {
T bestCallable = null;
int bestScore = -1;
@@ -551,35 +596,45 @@ private static boolean duckable(final Class<?> type, final IRubyObject arg) {
}

private static int argsHashCode(IRubyObject a0) {
return 31 + javaClassHashCode(a0);
return 31 + javaClassOrProcHashCode(a0);
}

private static int argsHashCode(IRubyObject a0, IRubyObject a1) {
return 31 * argsHashCode(a0) + javaClassHashCode(a1);
return 17 * ( 31 + javaClassHashCode(a0) ) +
javaClassOrProcHashCode(a1);
}

private static int argsHashCode(IRubyObject a0, IRubyObject a1, IRubyObject a2) {
return 31 * argsHashCode(a0, a1) + javaClassHashCode(a2);
return 17 * ( 17 * ( 31 + javaClassHashCode(a0) ) + javaClassHashCode(a1) ) +
javaClassOrProcHashCode(a2);
}

private static int argsHashCode(IRubyObject a0, IRubyObject a1, IRubyObject a2, IRubyObject a3) {
return 31 * argsHashCode(a0, a1, a2) + javaClassHashCode(a3);
return 17 * ( 17 * ( 17 * ( 31 + javaClassHashCode(a0) ) + javaClassHashCode(a1) ) + javaClassHashCode(a2) ) +
javaClassOrProcHashCode(a3);
}

private static int argsHashCode(IRubyObject[] args) {
if ( args == null ) return 0;
private static int argsHashCode(final IRubyObject[] args) {
final int last = args.length - 1;
if ( last == -1 ) return 0;

int result = 1;

for ( int i = 0; i < args.length; i++ ) {
result = 31 * result + javaClassHashCode(args[i]);
int result = 31;
for ( int i = 0; i < last; i++ ) {
result = 17 * ( result + javaClassHashCode( args[i] ) );
}

return result;
return result + javaClassOrProcHashCode( args[last] );
}

private static int javaClassHashCode(final IRubyObject arg) {
return arg == null ? 0 : arg.getJavaClass().hashCode();
// if ( arg == null ) return 0;
return arg.getJavaClass().hashCode();
}

private static int javaClassOrProcHashCode(final IRubyObject arg) {
// if ( arg == null ) return 0;
final Class<?> javaClass = arg.getJavaClass();
return javaClass == RubyProc.class ? arg.hashCode() : javaClass.hashCode();
}

private static Class<?> getJavaClass(final IRubyObject arg) {
62 changes: 61 additions & 1 deletion core/src/main/java/org/jruby/javasupport/Java.java
Original file line number Diff line number Diff line change
@@ -76,7 +76,6 @@
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
import static org.jruby.runtime.Visibility.*;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.Library;
import org.jruby.anno.JRubyMethod;
@@ -107,10 +106,13 @@
import org.jruby.util.ClassProvider;
import org.jruby.util.CodegenUtils;
import org.jruby.util.IdUtil;
import org.jruby.util.SafePropertyAccessor;
import org.jruby.util.cli.Options;
import org.jruby.util.collections.IntHashMap;

import static org.jruby.java.dispatch.CallableSelector.newCallableCache;
import static org.jruby.java.invokers.RubyToJavaInvoker.convertArguments;
import static org.jruby.runtime.Visibility.*;

@JRubyModule(name = "Java")
public class Java implements Library {
@@ -1475,4 +1477,62 @@ private static RubyClass createProxyClass(final Ruby runtime,
final RubyClass baseType, final JavaClass javaClass, boolean invokeInherited) {
return createProxyClass(runtime, RubyClass.newClass(runtime, baseType), javaClass, invokeInherited);
}

/**
* @param iface
* @return the sole un-implemented method for a functional-style interface or null
* @note This method is internal and might be subject to change, do not assume its part of JRuby's API!
*/
public static Method getFunctionalInterfaceMethod(final Class<?> iface) {
assert iface.isInterface();
Method single = null;
for ( final Method method : iface.getMethods() ) {
final int mod = method.getModifiers();
if ( Modifier.isStatic(mod) ) continue;
if ( Modifier.isAbstract(mod) ) {
try { // check if it's equals, hashCode etc. :
Object.class.getMethod(method.getName(), method.getParameterTypes());
continue; // abstract but implemented by java.lang.Object
}
catch (NoSuchMethodException e) { /* fall-thorough */ }
catch (SecurityException e) {
// NOTE: we could try check for FunctionalInterface on Java 8
}
}
else continue; // not-abstract ... default method
if ( single == null ) single = method;
else return null; // not a functional iface
}
return single;
}

static final boolean JAVA8;
static {
boolean java8 = false;
final String version = SafePropertyAccessor.getProperty("java.version", "0.0");
if ( version.length() > 2 ) {
int v = Character.getNumericValue( version.charAt(0) );
if ( v > 8 ) java8 = true; // 9.0
else if ( v == 1 ) {
v = Character.getNumericValue( version.charAt(2) ); // 1.8
if ( v < 10 && v >= 8 ) java8 = true;
}
// seems as no Java 10 support ... yet :)
}
JAVA8 = java8;
}

// TODO if about to compile against Java 8 this does not need to be reflective
static boolean isDefaultMethod(final Method method) {
if ( JAVA8 ) {
try {
return (Boolean) Method.class.getMethod("isDefault").invoke(method);
}
catch (NoSuchMethodException ex) { throw new RuntimeException(ex); }
catch (IllegalAccessException ex) { throw new RuntimeException(ex); }
catch (Exception ex) { /* noop */ }
}
return false;
}

}
24 changes: 12 additions & 12 deletions core/src/main/java/org/jruby/javasupport/JavaUtil.java
Original file line number Diff line number Diff line change
@@ -219,21 +219,21 @@ public static Class<?> primitiveToWrapper(final Class<?> type) {
return type.isPrimitive() ? CodegenUtils.getBoxType(type) : type;
}

@SuppressWarnings("unchecked")
public static boolean isDuckTypeConvertable(Class providedArgumentType, Class parameterType) {
return parameterType.isInterface() &&
! parameterType.isAssignableFrom(providedArgumentType) &&
RubyObject.class.isAssignableFrom(providedArgumentType);
public static boolean isDuckTypeConvertable(final Class<?> argumentType, final Class<?> targetType) {
return targetType.isInterface() &&
! targetType.isAssignableFrom(argumentType) &&
RubyObject.class.isAssignableFrom(argumentType);
}

public static Object convertProcToInterface(ThreadContext context, RubyObject rubyObject, Class target) {
return convertProcToInterface(context, (RubyBasicObject) rubyObject, target);
public static <T> T convertProcToInterface(ThreadContext context, RubyObject rubyObject, Class<T> targetType) {
return convertProcToInterface(context, (RubyBasicObject) rubyObject, targetType);
}

public static Object convertProcToInterface(ThreadContext context, RubyBasicObject rubyObject, Class target) {
@SuppressWarnings("unchecked")
public static <T> T convertProcToInterface(ThreadContext context, RubyBasicObject rubyObject, Class<T> targetType) {
final Ruby runtime = context.runtime;

final RubyModule ifaceModule = Java.getInterfaceModule(runtime, JavaClass.get(runtime, target));
final RubyModule ifaceModule = Java.getInterfaceModule(runtime, JavaClass.get(runtime, targetType));
if ( ! ifaceModule.isInstance(rubyObject) ) {
ifaceModule.callMethod(context, "extend_object", rubyObject);
ifaceModule.callMethod(context, "extended", rubyObject);
@@ -246,7 +246,7 @@ public static Object convertProcToInterface(ThreadContext context, RubyBasicObje
singletonClass.addMethod("method_missing", new Java.ProcToInterface(singletonClass));
}
JavaObject javaObject = (JavaObject) Helpers.invoke(context, rubyObject, "__jcreate_meta!");
return javaObject.getValue();
return (T) javaObject.getValue();
}

public static NumericConverter getNumericConverter(Class target) {
@@ -325,13 +325,13 @@ public static String getJavaPropertyName(final String beanMethodName) {
if ( maybeGetOrSet && ( beanMethodName.startsWith("get") || beanMethodName.startsWith("set") ) ) {
if (isUpperDigit(ch = beanMethodName.charAt(3))) {
if ( length == 4 ) return Character.toString(toLowerCase(ch));
return "" + toLowerCase(ch) + beanMethodName.substring(4);
return toLowerCase(ch) + beanMethodName.substring(4);
}
}
else if ( beanMethodName.startsWith("is") && length > 2 ) {
if (isUpperDigit(ch = beanMethodName.charAt(2))) {
if ( length == 3 ) return Character.toString( toLowerCase(ch) );
return "" + toLowerCase(ch) + beanMethodName.substring(3);
return toLowerCase(ch) + beanMethodName.substring(3);
}
}
return null;
3 changes: 2 additions & 1 deletion core/src/main/ruby/jruby/kernel/jruby/process_manager.rb
Original file line number Diff line number Diff line change
@@ -32,7 +32,8 @@ def self.`(command)
pb.redirect_input(Redirect::INHERIT)
pb.redirect_error(Redirect::INHERIT)
pb.environment(ShellLauncher.get_current_env(JRuby.runtime))
pb.directory(JFile.new(JRuby.runtime.current_directory))
cwd = JRuby.runtime.current_directory.start_with?('uri:classloader:/') ? ENV_JAVA['user.dir'] : JRuby.runtime.current_directory
pb.directory(JFile.new(cwd))
process = pb.start

pid = ShellLauncher.reflect_pid_from_process(process)
235 changes: 144 additions & 91 deletions core/src/test/java/org/jruby/embed/ScriptingContainerTest.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -2,38 +2,34 @@

import org.jruby.embed.LocalContextScope;
import org.jruby.embed.PropertyName;
import org.junit.After;

import org.junit.AfterClass;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.*;

/**
*
* @author yoko
*/
public class SystemPropertyCatcherTest {

public SystemPropertyCatcherTest() {
}


private static String LOCALCONTEXT_PROPERTY;

@BeforeClass
public static void setUpClass() {
LOCALCONTEXT_PROPERTY = System.getProperty(PropertyName.LOCALCONTEXT_SCOPE.toString());
}

@AfterClass
public static void tearDownClass() {
}

@Before
public void setUp() {

}

@After
public void tearDown() {

if ( LOCALCONTEXT_PROPERTY == null ) {
System.clearProperty(PropertyName.LOCALCONTEXT_SCOPE.toString());
}
else {
System.setProperty(PropertyName.LOCALCONTEXT_SCOPE.toString(), LOCALCONTEXT_PROPERTY);
}
}

/**
@@ -42,29 +38,29 @@ public void tearDown() {
@Test
public void testGetScope() {
System.setProperty(PropertyName.LOCALCONTEXT_SCOPE.toString(), "");

LocalContextScope defaultScope = LocalContextScope.SINGLETON;

// no setting
LocalContextScope result = SystemPropertyCatcher.getScope(defaultScope);
assertEquals(defaultScope, result);

System.setProperty(PropertyName.LOCALCONTEXT_SCOPE.toString(), "singleton");
result = SystemPropertyCatcher.getScope(defaultScope);
assertEquals(LocalContextScope.SINGLETON, result);

System.setProperty(PropertyName.LOCALCONTEXT_SCOPE.toString(), "singlethread");
result = SystemPropertyCatcher.getScope(defaultScope);
assertEquals(LocalContextScope.SINGLETHREAD, result);

System.setProperty(PropertyName.LOCALCONTEXT_SCOPE.toString(), "threadsafe");
result = SystemPropertyCatcher.getScope(defaultScope);
assertEquals(LocalContextScope.THREADSAFE, result);

System.setProperty(PropertyName.LOCALCONTEXT_SCOPE.toString(), "concurrent");
result = SystemPropertyCatcher.getScope(defaultScope);
assertEquals(LocalContextScope.CONCURRENT, result);

System.setProperty(PropertyName.LOCALCONTEXT_SCOPE.toString(), "");
}
}
58 changes: 54 additions & 4 deletions core/src/test/java/org/jruby/javasupport/TestJava.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jruby.javasupport;

import junit.framework.TestCase;
import java.lang.reflect.Method;
import org.junit.Test;

import org.jruby.Ruby;

@@ -10,11 +11,11 @@ public static class C extends B {}

class B extends A {}

public class TestJava extends junit.framework.TestCase {

public class TestJava extends TestCase {

@Test
public void testProxyCreation() {
Ruby runtime = Ruby.newInstance();
final Ruby runtime = Ruby.newInstance();
try {
Java.getProxyClass(runtime, B.class);
assert(true);
@@ -23,4 +24,53 @@ public void testProxyCreation() {
fail(ae.toString());
}
}

@Test
public void testGetFunctionInterface() {
Method method;
method = Java.getFunctionalInterfaceMethod(java.lang.Runnable.class);
assertNotNull(method);
assertEquals("run", method.getName());

method = Java.getFunctionalInterfaceMethod(java.io.Serializable.class);
assertNull(method);

//if ( Java.JAVA8 ) { // compare and equals both abstract
method = Java.getFunctionalInterfaceMethod(java.util.Comparator.class);
assertNotNull(method);
assertEquals("compare", method.getName());
//}

method = Java.getFunctionalInterfaceMethod(java.lang.Comparable.class);
assertNotNull(method);
assertEquals("compareTo", method.getName());

method = Java.getFunctionalInterfaceMethod(java.lang.Iterable.class);
assertNotNull(method);
assertEquals("iterator", method.getName());

method = Java.getFunctionalInterfaceMethod(java.util.concurrent.ThreadFactory.class);
assertNotNull(method);

method = Java.getFunctionalInterfaceMethod(java.util.Enumeration.class);
assertNull(method);

method = Java.getFunctionalInterfaceMethod(FxRunnable1.class);
assertNotNull(method);
assertEquals("run", method.getName());

method = Java.getFunctionalInterfaceMethod(FxRunnable2.class);
assertNotNull(method);
assertEquals("run", method.getName());

method = Java.getFunctionalInterfaceMethod(NonFxRunnable.class);
assertNull(method);
}

private static interface FxRunnable1 extends Runnable { abstract void run() ; }

private static interface FxRunnable2 extends Runnable { /* inherited run() */ }

private static interface NonFxRunnable extends Runnable { public void doRun() ; }

}
16 changes: 11 additions & 5 deletions core/src/test/java/org/jruby/javasupport/TestJavaClass.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
package org.jruby.javasupport;

import junit.framework.TestCase;
import org.junit.Test;

import org.jruby.Ruby;

public class TestJavaClass extends junit.framework.TestCase {

public class TestJavaClass extends TestCase {

public void test() {
@Test
public void testGet() {
Ruby runtime = Ruby.newInstance();
// This is now needed, since module Java
// isn't in by default
runtime.getModule("Kernel").callMethod(runtime.getCurrentContext(),"require",runtime.newString("java"));
requireJava(runtime);

JavaClass javaClass = JavaClass.get(runtime, String.class);
assertSame(javaClass, JavaClass.get(runtime, String.class));
}

static void requireJava(final Ruby runtime) {
runtime.getModule("Kernel").callMethod(runtime.getCurrentContext(), "require", runtime.newString("java"));
}

}
8 changes: 4 additions & 4 deletions spec/java_integration/ant/ant_spec.rb
Original file line number Diff line number Diff line change
@@ -28,19 +28,19 @@
end

it "adds tools.jar to the CLASSPATH when JAVA_HOME is set and it exists" do
stubs_file!
stub_File!
Ant.load
$CLASSPATH.should include("file:#{@tools_jar}")
end

it "adds classes.zip to the CLASSPATH when JAVA_HOME is set and it exists" do
stubs_file!
stub_File!
Ant.load
$CLASSPATH.should include("file:#{@classes_zip}")
end

def stubs_file!
File.stub!(:exist?).and_return false
def stub_File!
File.stub(:exist?).and_return false
File.should_receive(:exist?).with(ENV['JAVA_HOME']).and_return true
File.should_receive(:exist?).with(@tools_jar).and_return true
File.should_receive(:exist?).with(@classes_zip).and_return true
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package java_integration.fixtures.iface;

public interface SingleMethodInterfaceWith4Args {
public static class Caller {
public static Object[] call(SingleMethodInterfaceWith4Args iface) {
return iface.doIt(Caller.class, "hello", "world", 42);
}
}

<T> Object[] doIt(final T arg1, String arg2, Object arg3, int arg4) ;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package java_integration.fixtures.iface;

public interface SingleMethodInterfaceWithArg {
public static class Caller {
public static void call(SingleMethodInterfaceWithArg iface) {
call(42, iface);
}
public static <V> void call(V arg, SingleMethodInterfaceWithArg iface) {
iface.doSome(arg);
}
}

<V> void doSome(final V arg) ;
}
20 changes: 10 additions & 10 deletions spec/java_integration/interfaces/executor_spec.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
require File.dirname(__FILE__) + "/../spec_helper"

EXECUTOR_TEST_VALUE = 101

describe "java.util.concurrent.Executors" do

EXECUTOR_TEST_VALUE = 101

before do
@executor = java.util.concurrent.Executors.newSingleThreadExecutor
end


after { @executor.shutdown }

it "accepts a class that implements Callable interface" do
cls = Class.new do
include java.util.concurrent.Callable
@@ -15,12 +18,9 @@ def call
EXECUTOR_TEST_VALUE
end
end
lambda { @future = @executor.submit(cls.new) }.should_not raise_error(TypeError)
@future.get.should == EXECUTOR_TEST_VALUE
end

after do
@executor.shutdown
future = nil
lambda { future = @executor.submit(cls.new) }.should_not raise_error
future.get.should == EXECUTOR_TEST_VALUE
end

end
67 changes: 49 additions & 18 deletions spec/java_integration/interfaces/implementation_spec.rb
Original file line number Diff line number Diff line change
@@ -174,30 +174,61 @@ def callIt
end

it "should be implementable with .impl" do
impl = SingleMethodInterface.impl {|name| name}
impl = SingleMethodInterface.impl { |name| name }
impl.should be_kind_of(SingleMethodInterface)
SingleMethodInterface.should === impl

UsesSingleMethodInterface.callIt(impl).should == :callIt
end

it "should allow assignable equivalents to be passed to a method" do
impl = DescendantOfSingleMethodInterface.impl {|name| name}
impl = DescendantOfSingleMethodInterface.impl { |name| name }
impl.should be_kind_of(SingleMethodInterface)
DescendantOfSingleMethodInterface.should === impl
UsesSingleMethodInterface.callIt(impl).should == :callIt
UsesSingleMethodInterface.new.callIt2(impl).should == :callIt
end

it "passes correct arguments to proc .impl" do
Java::java.io.File.new('.').list do |dir, name| # FilenameFilter
dir.should be_kind_of(java.io.File)
name.should be_kind_of(String)
true # boolean accept(File dir, String name)
end

caller = Java::java_integration.fixtures.iface.SingleMethodInterfaceWithArg::Caller

caller.call { |arg| arg.should == 42 }
caller.call('x') { |arg| arg.should == 'x' }

Java::java_integration.fixtures.iface.SingleMethodInterfaceWith4Args::Caller.call do
|arg1, arg2, arg3, arg4|
arg2.should == 'hello'
arg3.should == 'world'
arg4.should == 42
[ arg2, arg3, arg4 ] # return Object[]
end
end

it "resolves 'ambiguous' method by proc argument count (with .impl)" do
java.io.File.new('.').listFiles do |pathname| # FileFilter#accept(File)
pathname.should be_kind_of(java.io.File)
end
java.io.File.new('.').listFiles do |dir, name| # FilenameFilter#accept(File, String)
dir.should be_kind_of(java.io.File)
name.should be_kind_of(String)
end
end

it "should maintain Ruby object equality when passed through Java and back" do
result = SingleMethodInterface.impl {|name| name}
callable = mock "callable"
result = SingleMethodInterface.impl { |name| name }
callable = double "callable"
callable.should_receive(:call).and_return result
UsesSingleMethodInterface.new.callIt3(callable).should == result
end

it "coerces to that interface after duck-typed implementation has happened" do
callable = mock "SingleMethodInterfaceImpl"
callable = double "SingleMethodInterfaceImpl"
callable.should_receive(:callIt).and_return :callIt
UsesSingleMethodInterface.callIt(callable).should == :callIt

@@ -210,7 +241,7 @@ def callIt
interfaces.concat(cls.interfaces)
cls = cls.superclass
end

interfaces.should include(SingleMethodInterface.java_class)
end
end
@@ -538,15 +569,15 @@ def value; 1; end

describe "Coercion of normal ruby objects" do
it "should allow an object passed to a java method to be coerced to the interface" do
ri = mock "returns interface"
ri = double "returns interface"
consumer = ReturnsInterfaceConsumer.new
consumer.set_returns_interface ri
ri.should be_kind_of(ReturnsInterface)
end


it "should return the original ruby object when returned back to Ruby" do
obj = mock "ruby object"
obj = double "ruby object"
cti = CoerceToInterface.new
result = cti.returnArgumentBackToRuby(JRuby.runtime, obj)
obj.should be_kind_of(Java::JavaLang::Runnable)
@@ -555,32 +586,32 @@ def value; 1; end
end

it "should return the original ruby object when converted back to Ruby" do
obj = mock "ruby object"
obj = double "ruby object"
cti = CoerceToInterface.new
result = cti.coerceArgumentBackToRuby(JRuby.runtime, obj)
obj.should be_kind_of(Java::JavaLang::Runnable)
result.should == obj
end

it "should pass the original ruby object when converted back to Ruby and used as an argument to another Ruby object" do
obj = mock "ruby object"
callable = mock "callable"
obj = double "ruby object"
callable = double "callable"
callable.should_receive(:call).with(obj)
cti = CoerceToInterface.new
cti.passArgumentToInvokableRubyObject(callable, obj)
obj.should be_kind_of(Java::JavaLang::Runnable)
end

it "should allow an object passed to a java constructor to be coerced to the interface" do
ri = mock "returns interface"
ri = double "returns interface"
ReturnsInterfaceConsumer.new(ri)
ri.should be_kind_of(ReturnsInterface)
end

it "should allow an object to be coerced as a return type of a java method" do
ri = mock "returns interface"
value = mock "return value runnable"
ri.stub!(:getRunnable).and_return value
ri = double "returns interface"
value = double "return value runnable"
ri.stub(:getRunnable).and_return value

consumer = ReturnsInterfaceConsumer.new(ri)
runnable = consumer.getRunnable
@@ -688,15 +719,15 @@ def bar
lambda {c2.new}.should_not raise_error
end
end

it "returns the Java class implementing the interface for .java_class" do
cls = Class.new do
include java.lang.Runnable
end
obj = cls.new

java_cls = obj.java_class

java_cls.interfaces.should include(java.lang.Runnable.java_class)
end
end
19 changes: 17 additions & 2 deletions test/jruby/test_backquote.rb
Original file line number Diff line number Diff line change
@@ -13,6 +13,21 @@ def test_backquote_special_commands
end
end

def test_backquote_special_commands_and_cwd_inside_classloader
# not sure why it fails with java-1.6 - assume it is rare feature
# and works for java-1.7+
if File.exists?("/bin/echo") and not ENV_JAVA['java.version'].start_with?("1.6.")
begin
cwd = Dir.pwd
Dir.chdir('uri:classloader:/')
output = `/bin/echo hello`
assert_equal("hello\n", output)
ensure
Dir.chdir(cwd)
end
end
end

def test_system_special_commands
if File.exists?("/bin/true")
assert(system("/bin/true"))
@@ -28,8 +43,8 @@ def test_system_special_commands
#JRUBY-2251
def test_empty_backquotes
if (!WINDOWS and IS_COMMAND_LINE_EXECUTION)
assert_raise(Errno::ENOENT) {``}
assert_raise(Errno::ENOENT) {` `}
assert_raise(Errno::ENOENT) {``}
assert_raise(Errno::ENOENT) {` `}
assert_raise(Errno::ENOENT) {`\n`}
# pend "#{__method__}: `\\n` does not raise Errno::ENOENT as expected"
else # we just check that empty backquotes won't blow up JRuby
15 changes: 0 additions & 15 deletions test/jruby/test_kernel.rb
Original file line number Diff line number Diff line change
@@ -98,21 +98,6 @@ def test_Float
assert_raises(ArgumentError) { Kernel.Float("xxxx10000000000000000000000000000000000000000000000000000") }
end

# String
# URI
# `
# abort
# at_exit
# binding
# block_given?
class CheckBlockGiven; def self.go() block_given? end; end
def test_block_given?
assert !(Kernel.block_given?)
assert(CheckBlockGiven.go { true })
assert(!CheckBlockGiven.go)
assert(CheckBlockGiven.go(&Proc.new{}))
end

# callcc
# caller