Skip to content

Commit

Permalink
Showing 42 changed files with 1,705 additions and 1,139 deletions.
63 changes: 49 additions & 14 deletions core/src/main/java/org/jruby/Main.java
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@
package org.jruby;

import org.jruby.exceptions.MainExitException;
import org.jruby.exceptions.JumpException;
import org.jruby.exceptions.RaiseException;
import org.jruby.exceptions.ThreadKill;
import org.jruby.main.DripMain;
@@ -205,9 +206,14 @@ public static void main(String[] args) {
if (status.isExit()) {
System.exit(status.getStatus());
}
} catch (RaiseException rj) {
System.exit(handleRaiseException(rj));
} catch (Throwable t) {
}
catch (RaiseException ex) {
System.exit( handleRaiseException(ex) );
}
catch (JumpException ex) {
System.exit( handleUnexpectedJump(ex) );
}
catch (Throwable t) {
// If a Truffle exception gets this far it's a hard failure - don't try and dress it up as a Ruby exception

if (main.config.getCompileMode() == RubyInstanceConfig.CompileMode.TRUFFLE) {
@@ -516,25 +522,54 @@ private void doCheckSecurityManager() {
* run should be System.err. In order to avoid the Ruby err being closed and unable
* to write, we use System.err unconditionally.
*
* @param rj
* @param ex
* @return
*/
protected static int handleRaiseException(RaiseException rj) {
RubyException raisedException = rj.getException();
Ruby runtime = raisedException.getRuntime();
if (runtime.getSystemExit().isInstance(raisedException)) {
protected static int handleRaiseException(final RaiseException ex) {
RubyException raisedException = ex.getException();
final Ruby runtime = raisedException.getRuntime();
if ( runtime.getSystemExit().isInstance(raisedException) ) {
IRubyObject status = raisedException.callMethod(runtime.getCurrentContext(), "status");
if (status != null && !status.isNil()) {
if (status != null && ! status.isNil()) {
return RubyNumeric.fix2int(status);
} else {
return 0;
}
} else {
System.err.print(runtime.getInstanceConfig().getTraceType().printBacktrace(raisedException, runtime.getPosix().isatty(FileDescriptor.err)));
return 1;
return 0;
}
System.err.print(runtime.getInstanceConfig().getTraceType().printBacktrace(raisedException, runtime.getPosix().isatty(FileDescriptor.err)));
return 1;
}

private static int handleUnexpectedJump(final JumpException ex) {
if ( ex instanceof JumpException.SpecialJump ) { // ex == JumpException.SPECIAL_JUMP
System.err.println("Unexpected break: " + ex);
}
else if ( ex instanceof JumpException.FlowControlException ) {
// NOTE: assuming a single global runtime main(args) should have :
if ( Ruby.isGlobalRuntimeReady() ) {
final Ruby runtime = Ruby.getGlobalRuntime();
RaiseException raise = ((JumpException.FlowControlException) ex).buildException(runtime);
if ( raise != null ) handleRaiseException(raise);
}
else {
System.err.println("Unexpected jump: " + ex);
}
}
else {
System.err.println("Unexpected: " + ex);
}

final StackTraceElement[] trace = ex.getStackTrace();
if ( trace != null && trace.length > 0 ) {
System.err.println( ThreadContext.createRawBacktraceStringFromThrowable(ex, false) );
}
else {
System.err.println("HINT: to get backtrace for jump exceptions run with -Xjump.backtrace=true");
}

// TODO: should match MRI (>= 2.2.3) exit status - @see ruby/test_enum.rb#test_first
return 2;
}

public static void printTruffleTimeMetric(String id) {
if (Options.TRUFFLE_METRICS_TIME.load()) {
final long millis = System.currentTimeMillis();
34 changes: 19 additions & 15 deletions core/src/main/java/org/jruby/RubyFloat.java
Original file line number Diff line number Diff line change
@@ -651,34 +651,38 @@ public IRubyObject op_le(ThreadContext context, double other) {
@JRubyMethod(name = "eql?", required = 1)
@Override
public IRubyObject eql_p(IRubyObject other) {
if (other instanceof RubyFloat) {
double b = ((RubyFloat) other).value;
if (Double.isNaN(value) || Double.isNaN(b)) {
return getRuntime().getFalse();
}
if (value == b) {
return getRuntime().getTrue();
}
}
return getRuntime().getFalse();
return getRuntime().newBoolean( equals(other) );
}

@Override
public boolean equals(Object other) {
return (other instanceof RubyFloat) && equals((RubyFloat) other);
}

private boolean equals(RubyFloat that) {
if ( Double.isNaN(this.value) || Double.isNaN(that.value) ) return false;
final double val1 = this.value == -0.0 ? 0.0 : this.value;
final double val2 = that.value == -0.0 ? 0.0 : that.value;
return Double.doubleToLongBits(val1) == Double.doubleToLongBits(val2);
}

/** flo_hash
*
*/
@JRubyMethod(name = "hash")
@Override
public RubyFixnum hash() {
return getRuntime().newFixnum(hashCode());
return getRuntime().newFixnum( hashCode() );
}

@Override
public final int hashCode() {
long l = Double.doubleToLongBits(value);
return (int)(l ^ l >>> 32);
}
final double val = value == 0.0 ? -0.0 : value;
final long l = Double.doubleToLongBits(val);
return (int) ( l ^ l >>> 32 );
}

/** flo_fo
/** flo_fo
*
*/
@JRubyMethod(name = "to_f")
23 changes: 16 additions & 7 deletions core/src/main/java/org/jruby/RubyTime.java
Original file line number Diff line number Diff line change
@@ -60,6 +60,7 @@

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
@@ -81,9 +82,10 @@
@JRubyClass(name="Time", include="Comparable")
public class RubyTime extends RubyObject {
public static final String UTC = "UTC";
public static final BigDecimal ONE_MILLION_BD = new BigDecimal(1000000);
@Deprecated // no longer used
public static final BigDecimal ONE_MILLION_BD = BigDecimal.valueOf(1000000);
public static final BigInteger ONE_MILLION_BI = BigInteger.valueOf(1000000);
public static final BigDecimal ONE_THOUSAND_BD = new BigDecimal(1000);
public static final BigDecimal ONE_THOUSAND_BD = BigDecimal.valueOf(1000);
private DateTime dt;
private long nsec;

@@ -1058,12 +1060,19 @@ public static IRubyObject at(ThreadContext context, IRubyObject recv, IRubyObjec
long numerator = rational.numerator(context).convertToInteger().getLongValue();
long denominator = rational.denominator(context).convertToInteger().getLongValue();

BigDecimal accurateSeconds = new BigDecimal(numerator).divide(new BigDecimal(denominator));
BigDecimal accurateMillis = accurateSeconds.multiply(ONE_THOUSAND_BD);
BigInteger integralMillis = accurateMillis.toBigInteger();
BigInteger remainingNanos = accurateMillis.multiply(ONE_MILLION_BD).toBigInteger().subtract(integralMillis.multiply(ONE_MILLION_BI));
final BigDecimal secs;
if ( numerator <= Integer.MAX_VALUE ) {
secs = new BigDecimal(numerator * 1000);
}
else {
secs = BigDecimal.valueOf(numerator).multiply(ONE_THOUSAND_BD);
}
final BigDecimal millis = secs.divide(BigDecimal.valueOf(denominator), 12, RoundingMode.DOWN);

final BigInteger roundMillis = millis.toBigInteger();
BigInteger remainingNanos = millis.movePointRight(6).toBigInteger().subtract( roundMillis.multiply(ONE_MILLION_BI) );

millisecs = integralMillis.longValue();
millisecs = roundMillis.longValue();
nanosecs = remainingNanos.longValue();
}
} else {
1 change: 1 addition & 0 deletions test/mri/excludes/TestEnumerable.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
exclude :test_slice_before, "needs investigation"
exclude :test_callcc, "Continuations are not supported"
exclude :test_zip, "needs investigation"
exclude :test_first, "works - but output is not exactly 'unexpected break' as in MRI"
5 changes: 4 additions & 1 deletion test/mri/excludes/TestIO.rb
Original file line number Diff line number Diff line change
@@ -31,4 +31,7 @@
exclude :test_sysread_locktmp, "requires string locking we do not support"
exclude :test_warn, "needs investigation"
exclude :test_flush_in_finalizer1, "uses ObjectSpace"
exclude :test_flush_in_finalizer2, "uses ObjectSpace"
exclude :test_flush_in_finalizer2, "uses ObjectSpace"
exclude :test_reopen_stdio, "needs investigation"
exclude :test_set_stdout, "needs investigation"
exclude :test_threaded_flush, "needs investigation"
1 change: 1 addition & 0 deletions test/mri/excludes/TestKeywordArguments.rb
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
exclude :test_required_keyword_with_reserved, "needs investigation"
exclude :test_nonsymbol_key, "needs investigation"
3 changes: 3 additions & 0 deletions test/mri/excludes/TestMethod.rb
Original file line number Diff line number Diff line change
@@ -12,3 +12,6 @@
exclude :test_super_in_proc_from_define_method, "needs investigation"
exclude :test_super_method_removed, "finds super method when super method has been undef (#2155)"
exclude :test_visibility, "fails in compiler"
exclude :test_splat_long_array, "hangs when run"
exclude :test_insecure_method, "does not raise expected SecurityError"
exclude :test_to_proc_binding, "needs investigation"
20 changes: 11 additions & 9 deletions test/mri/excludes/TestProcess.rb
Original file line number Diff line number Diff line change
@@ -16,16 +16,18 @@
exclude :test_execopts_env, "needs investigation"
exclude :test_execopts_env_popen_string, "needs investigation"
exclude :test_execopts_env_popen_vector, "needs investigation"
exclude :test_execopts_env_single_word, "out of memory error"
exclude :test_execopts_exec, "needs investigation"
exclude :test_execopts_gid, "needs investigation"
exclude :test_execopts_open_chdir, "out of memory error"
exclude :test_execopts_pgroup, "needs investigation"
exclude :test_execopts_env_single_word, "Errno::ENOENT: No such file or directory - test_execopts_env_single_word.out"
exclude :test_execopts_exec, "TypeError: wrong exec option: #<IO:<STDOUT>>"
exclude :test_execopts_gid, "#<ArgumentError: wrong exec option symbol: gid>"
exclude :test_execopts_open_chdir, "sh: 1: cd: can't cd to foo"
exclude :test_execopts_pgroup, "#<TypeError: no implicit conversion of false into Integer>"
exclude :test_execopts_popen, "needs investigation"
exclude :test_execopts_preserve_env_on_exec_failure, "needs investigation"
exclude :test_execopts_redirect, "out of memory error"
exclude :test_execopts_redirect_dup2_child, "out of memory error"
exclude :test_execopts_redirect_nonascii_path, "out of memory error"
exclude :test_execopts_redirect_fd, "Errno::ENOENT: No such file or directory - out"
exclude :test_execopts_redirect_dup2_child, "Errno::ENOENT: No such file or directory - out"
exclude :test_execopts_redirect_nonascii_path, "needs investigation"
exclude :test_execopts_redirect_pipe, "Java::JavaLang::ArrayIndexOutOfBoundsException: -11"
exclude :test_execopts_redirect_symbol, "Errno::ENOENT: No such file or directory - out"
exclude :test_execopts_redirect_to_out_and_err, "out of memory error"
exclude :test_execopts_uid, "needs investigation"
exclude :test_execopts_umask, "unsupported"
@@ -34,7 +36,6 @@
exclude :test_fd_inheritance, "needs investigation"
exclude :test_gid_re_exchangeable_p, "unimplemented"
exclude :test_gid_sid_available?, "unimplemented"
exclude :test_no_curdir, "out of memory error"
exclude :test_popen_cloexec, "unsupported"
exclude :test_popen_noshell, "fails on linux (Travis)"
exclude :test_popen_wordsplit, "needs investigation"
@@ -51,3 +52,4 @@
exclude :test_system_wordsplit, "needs investigation"
exclude :test_uid_re_exchangeable_p, "unimplemented"
exclude :test_uid_sid_available?, "unimplemented"
exclude :test_wait_exception, "Interrupt expected but nothing was raised."
1 change: 1 addition & 0 deletions test/mri/excludes/TestRange.rb
Original file line number Diff line number Diff line change
@@ -2,3 +2,4 @@
exclude :test_bsearch_for_other_numerics, "needs investigation"
exclude :test_comparison_when_recursive, "needs investigation"
exclude :test_range_bsearch_for_floats, "needs investigation"
exclude :test_eqq_time, "TypeError: can't iterate from Time"
3 changes: 2 additions & 1 deletion test/mri/excludes/TestSymbol.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
exclude :test_ascii_incomat_inspect, "needs investigation"
exclude :test_inspect, "needs investigation"
exclude :test_inspect_dollar, "needs investigation"
#exclude :test_inspect_dollar, "needs investigation"
exclude :test_symbol_encoding, "needs investigation"
exclude :test_symbol_fstr_leak, "assert_no_memory_leak fails due an unexpected nil"
13 changes: 6 additions & 7 deletions test/mri/excludes/TestSyntax.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
exclude :test__END___cr, "needs investigation"
exclude :test_cmd_symbol_after_keyword, "needs investigation"
exclude :test_cmd_symbol_in_string, "needs investigation"
exclude :test_cmd_symbol_singleton_class, "needs investigation"
exclude :test_cmd_symbol_superclass, "needs investigation"
exclude :test_constant_reassignment_nested, "needs investigation"
exclude :test_constant_reassignment_toplevel, "needs investigation"
exclude :test_defined_empty_argument, "needs investigation"
exclude :test_do_block_after_blockcall_colon_no_arg, "NPE in parser"
exclude :test_do_block_after_blockcall_dot_no_arg, "NPE in parser"
exclude :test_do_block_in_call_args, "needs investigation"
exclude :test_do_block_in_cmdarg, "needs investigation"
exclude :test_do_block_in_cmdarg_begin, "needs investigation"
@@ -28,4 +22,9 @@
exclude :test_warn_balanced, "needs investigation"
exclude :test_warn_grouped_expression, "needs investigation"
exclude :test_warn_unreachable, "needs investigation"
exclude :test_warning_for_cr, "needs investigation"
exclude :test_warning_for_cr, "needs investigation"
exclude :test_bad_kwarg, "needs investigation"
exclude :test_do_block_in_lambda, "needs investigation"
exclude :test_invalid_next, "needs investigation"
exclude :test_null_range_cmdarg, "needs investigation"
exclude :test_too_big_nth_ref, "needs investigation"
3 changes: 3 additions & 0 deletions test/mri/excludes/TestTimeExtension.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
exclude :test_completion_with_different_timezone, "needs investigation"
exclude :test_encode_xmlschema, "needs investigation"
exclude :test_zone_0000, "needs investigation"
exclude :test_strptime_s_N, "1/1000000000000 subsec precision not supported"
exclude :test_iso8601_encode, "works except that we only have nano-sec precision up to 6-decimal values"
exclude :test_xmlschema_encode, "works except that we only have nano-sec precision up to 6-decimal values"
1 change: 1 addition & 0 deletions test/mri/excludes/TestTimeout.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
exclude :test_cannot_convert_into_time_interval, "needs investigation"
exclude :test_enumerator_next, "hangs"
exclude :test_skip_rescue, "needs investigation"
exclude :test_handle_interrupt, "since 2.2.2 - needs investigation"
49 changes: 43 additions & 6 deletions test/mri/ruby/envutil.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# -*- coding: us-ascii -*-
require "open3"
require "timeout"
require "test/unit"
require_relative "find_executable"

module EnvUtil
@@ -69,8 +68,14 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr =
stderr = th_stderr.value if capture_stderr && capture_stderr != :merge_to_stdout
else
signal = /mswin|mingw/ =~ RUBY_PLATFORM ? :KILL : :TERM
case pgroup = opt[:pgroup]
when 0, true
pgroup = -pid
when nil, false
pgroup = pid
end
begin
Process.kill signal, pid
Process.kill signal, pgroup
Timeout.timeout((reprieve unless signal == :KILL)) do
Process.wait(pid)
end
@@ -357,10 +362,8 @@ def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **o
line -= 5 # lines until src
src = <<eom
# -*- coding: #{src.encoding}; -*-
require #{__dir__.dump}'/envutil';include Test::Unit::Assertions
END {
puts [Marshal.dump($!)].pack('m'), "assertions=\#{self._assertions}"
}
require #{__dir__.dump}'/envutil'; require 'test/unit'; include Test::Unit::Assertions
END { puts [Marshal.dump($!)].pack('m'), "assertions=\#{self._assertions}" }
#{src}
class Test::Unit::Runner
@@stop_auto_run = true
@@ -467,6 +470,8 @@ def assert_no_memory_leak(args, prepare, code, message=nil, limit: 1.5, rss: fal
next unless a > 0 and b > 0
assert_operator(a.fdiv(b), :<, limit, message(message) {"#{n}: #{b} => #{a}"})
end
rescue LoadError
skip
end

def assert_is_minus_zero(f)
@@ -520,6 +525,38 @@ def assert_pattern_list(pattern_list, actual, message=nil)
end
end

# threads should respond to shift method.
# Array can be used.
def assert_join_threads(threads, message = nil)
errs = []
values = []
while th = threads.shift
begin
values << th.value
rescue Exception
errs << [th, $!]
end
end
if !errs.empty?
msg = "exceptions on #{errs.length} threads:\n" +
errs.map {|t, err|
"#{t.inspect}:\n" +
err.backtrace.map.with_index {|line, i|
if i == 0
"#{line}: #{err.message} (#{err.class})"
else
"\tfrom #{line}"
end
}.join("\n")
}.join("\n---\n")
if message
msg = "#{message}\n#{msg}"
end
raise MiniTest::Assertion, msg
end
values
end

class << (AssertFile = Struct.new(:failure_message).new)
include Assertions
def assert_file_predicate(predicate, *args)
Loading

0 comments on commit 0e90461

Please sign in to comment.