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: 2ce8f3fac559^
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 09a504dca516
Choose a head ref
  • 17 commits
  • 13 files changed
  • 1 contributor

Commits on Jun 26, 2017

  1. Copy the full SHA
    2ce8f3f View commit details
  2. Copy the full SHA
    7ecc71f View commit details
  3. Copy the full SHA
    df27212 View commit details
  4. Copy the full SHA
    4cff6ad View commit details
  5. Copy the full SHA
    93eeb38 View commit details
  6. Ruby's Set/SortedSet implements java.util.Set/java.util.SortedSet

    ... with auto (magic) toJava conversions (like RubyArray does)
    kares committed Jun 26, 2017
    Copy the full SHA
    9cbaa9e View commit details
  7. Copy the full SHA
    68ab2aa View commit details
  8. Copy the full SHA
    90b24ed View commit details
  9. Copy the full SHA
    26d322c View commit details
  10. SortedSet is (always) expected to process its elements ordered

    ... wouldn't care really but this is spec-ed by RubySpecs
    kares committed Jun 26, 2017
    Copy the full SHA
    18cd400 View commit details
  11. comparator already preforms a cmp compatibility check

    (and raises an ArgumentError with a more useful message)
    kares committed Jun 26, 2017
    Copy the full SHA
    b327bd3 View commit details
  12. [spec] SortedSet argument error on adding 'incompatible' elements

    ... relaxed the respond_to?(:<=>) expectation as it seems less important
    kares committed Jun 26, 2017
    Copy the full SHA
    6a9469c View commit details
  13. Copy the full SHA
    0b28aa7 View commit details
  14. final frontier for MRI compat - make sure marshal-ing works

    ... necessary since we use some Java internal structures
    
    its been implemented in Java, could have been done with _load/_dump
    although would require exposing some of the Set/SortedSet internals
    kares committed Jun 26, 2017
    Copy the full SHA
    8867a6c View commit details

Commits on Jun 27, 2017

  1. assure Set marshal-ing is compatible at the binary level with previous

    ... and thus MRI's (pure Ruby) set.rb implementation as well
    important with Rails using Sprockets at its marshalling Set instances
    kares committed Jun 27, 2017
    Copy the full SHA
    54774d0 View commit details
  2. Copy the full SHA
    1ced7ec View commit details
  3. [travis-ci] core-complete jar has grown over 13m

    *expected smaller then 13*1024*1024 but got 13676870*
    kares committed Jun 27, 2017
    Copy the full SHA
    09a504d View commit details
1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -1699,6 +1699,7 @@ private void initBuiltins() {
addLazyBuiltin("tempfile.jar", "tempfile", "org.jruby.ext.tempfile.TempfileLibrary");
addLazyBuiltin("fcntl.rb", "fcntl", "org.jruby.ext.fcntl.FcntlLibrary");
addLazyBuiltin("pathname.jar", "pathname", "org.jruby.ext.pathname.PathnameLibrary");
addLazyBuiltin("set.rb", "set", "org.jruby.ext.set.SetLibrary");

addLazyBuiltin("mathn/complex.jar", "mathn/complex", "org.jruby.ext.mathn.Complex");
addLazyBuiltin("mathn/rational.jar", "mathn/rational", "org.jruby.ext.mathn.Rational");
154 changes: 122 additions & 32 deletions core/src/main/java/org/jruby/RubyArray.java
Original file line number Diff line number Diff line change
@@ -3465,42 +3465,134 @@ public IRubyObject sort_bang19(ThreadContext context, Block block) {
return sort_bang(context, block);
}

protected IRubyObject sortInternal(final ThreadContext context, boolean honorOverride) {
Ruby runtime = context.runtime;

// One check per specialized fast-path to make the check invariant.
final boolean fixnumBypass = !honorOverride || runtime.getFixnum().isMethodBuiltin("<=>");
final boolean stringBypass = !honorOverride || runtime.getString().isMethodBuiltin("<=>");

protected IRubyObject sortInternal(final ThreadContext context, final boolean honorOverride) {
try {
Arrays.sort(values, begin, begin + realLength, new Comparator() {
public int compare(Object o1, Object o2) {
if (fixnumBypass && o1 instanceof RubyFixnum && o2 instanceof RubyFixnum) {
return compareFixnums((RubyFixnum) o1, (RubyFixnum) o2);
}
if (stringBypass && o1 instanceof RubyString && o2 instanceof RubyString) {
return ((RubyString) o1).op_cmp((RubyString) o2);
}
return compareOthers(context, (IRubyObject)o1, (IRubyObject)o2);
Arrays.sort(values, begin, begin + realLength, new DefaultComparator(context, honorOverride) {
protected int compareGeneric(IRubyObject o1, IRubyObject o2) {
//TODO: ary_sort_check should be done here
return super.compareGeneric(o1, o2);
}
});
} catch (ArrayIndexOutOfBoundsException ex) {
}
catch (ArrayIndexOutOfBoundsException ex) {
throw concurrentModification(context.runtime, ex);
}
return this;
}

// @Deprecated
protected static int compareFixnums(RubyFixnum o1, RubyFixnum o2) {
long a = o1.getLongValue();
long b = o2.getLongValue();
return a > b ? 1 : a == b ? 0 : -1;
return DefaultComparator.compareInteger(o1, o2);
}

// @Deprecated
protected static int compareOthers(ThreadContext context, IRubyObject o1, IRubyObject o2) {
IRubyObject ret = sites(context).op_cmp_sort.call(context, o1, o1, o2);
int n = RubyComparable.cmpint(context, ret, o1, o2);
//TODO: ary_sort_check should be done here
return n;
return DefaultComparator.compareGeneric(context, o1, o2);
}

public static class DefaultComparator implements Comparator<IRubyObject> {

final ThreadContext context;

private final boolean fixnumBypass;
private final boolean stringBypass;

public DefaultComparator(ThreadContext context) {
this(context, true);
}

DefaultComparator(ThreadContext context, final boolean honorOverride) {
this.context = context;
if ( honorOverride && context != null ) {
this.fixnumBypass = !honorOverride || context.runtime.getFixnum().isMethodBuiltin("<=>");
this.stringBypass = !honorOverride || context.runtime.getString().isMethodBuiltin("<=>");
}
else { // no-opt
this.fixnumBypass = false;
this.stringBypass = false;
}
}

/*
DefaultComparator(ThreadContext context, final boolean fixnumBypass, final boolean stringBypass) {
this.context = context;
this.fixnumBypass = fixnumBypass;
this.stringBypass = stringBypass;
} */

public int compare(IRubyObject obj1, IRubyObject obj2) {
if (fixnumBypass && obj1 instanceof RubyFixnum && obj2 instanceof RubyFixnum) {
return compareInteger((RubyFixnum) obj1, (RubyFixnum) obj2);
}
if (stringBypass && obj1 instanceof RubyString && obj2 instanceof RubyString) {
return compareString((RubyString) obj1, (RubyString) obj2);
}
return compareGeneric(obj1, obj2);
}

protected int compareGeneric(IRubyObject o1, IRubyObject o2) {
final ThreadContext context = context();
return compareGeneric(context, sites(context).op_cmp_sort, o1, o2);
}

protected ThreadContext context() {
return context;
}

public static int compareInteger(RubyFixnum o1, RubyFixnum o2) {
long a = o1.getLongValue();
long b = o2.getLongValue();
return a > b ? 1 : a == b ? 0 : -1;
}

public static int compareString(RubyString o1, RubyString o2) {
return o1.op_cmp(o2);
}

public static int compareGeneric(ThreadContext context, IRubyObject o1, IRubyObject o2) {
return compareGeneric(context, sites(context).op_cmp_sort, o1, o2);
}

public static int compareGeneric(ThreadContext context, CallSite op_cmp_sort, IRubyObject o1, IRubyObject o2) {
IRubyObject ret = op_cmp_sort.call(context, o1, o1, o2);
return RubyComparable.cmpint(context, ret, o1, o2);
}

}

static class BlockComparator implements Comparator<IRubyObject> {

final ThreadContext context;

protected final Block block;
protected final IRubyObject self;

private final CallSite gt;
private final CallSite lt;

BlockComparator(ThreadContext context, Block block, CallSite gt, CallSite lt) {
this(context, block, null, gt, lt);
}

BlockComparator(ThreadContext context, Block block, IRubyObject self, CallSite gt, CallSite lt) {
this.context = context == null ? self.getRuntime().getCurrentContext() : context;
this.block = block; this.self = self;
this.gt = gt; this.lt = lt;
}

public int compare(IRubyObject obj1, IRubyObject obj2) {
return RubyComparable.cmpint(context, gt, lt, yieldBlock(obj1, obj2), obj1, obj2);
}

protected final IRubyObject yieldBlock(IRubyObject obj1, IRubyObject obj2) {
final ThreadContext context = context();
return block.yieldArray(context, context.runtime.newArray(obj1, obj2), self);
}

protected final ThreadContext context() {
return context;
}

}

protected IRubyObject sortInternal(final ThreadContext context, final Block block) {
@@ -3510,15 +3602,13 @@ protected IRubyObject sortInternal(final ThreadContext context, final Block bloc
int length = realLength;

copyInto(newValues, 0);
Arrays.sort(newValues, 0, length, new Comparator() {
CallSite gt = sites(context).op_gt_sort;
CallSite lt = sites(context).op_lt_sort;
public int compare(Object o1, Object o2) {
IRubyObject obj1 = (IRubyObject) o1;
IRubyObject obj2 = (IRubyObject) o2;
IRubyObject ret = block.yieldArray(context, getRuntime().newArray(obj1, obj2), null);
CallSite gt = sites(context).op_gt_sort;
CallSite lt = sites(context).op_lt_sort;
Arrays.sort(newValues, 0, length, new BlockComparator(context, block, gt, lt) {
@Override
public int compare(IRubyObject obj1, IRubyObject obj2) {
//TODO: ary_sort_check should be done here
return RubyComparable.cmpint(context, gt, lt, ret, obj1, obj2);
return super.compare(obj1, obj2);
}
});

3 changes: 2 additions & 1 deletion core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
@@ -3489,7 +3489,8 @@ public IRubyObject prepended(ThreadContext context, IRubyObject other) {
return context.nil;
}

private void setConstantVisibility(ThreadContext context, String name, boolean hidden) {
// NOTE: internal API
public final void setConstantVisibility(ThreadContext context, String name, boolean hidden) {
ConstantEntry entry = getConstantMap().get(name);

if (entry == null) {
63 changes: 63 additions & 0 deletions core/src/main/java/org/jruby/ext/set/EnumerableExt.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/***** BEGIN LICENSE BLOCK *****
* Version: EPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.eclipse.org/legal/epl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2016 Karol Bucek
*
* 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"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/
package org.jruby.ext.set;

import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

/**
* Enumerable#to_set (from require 'set')
*
* @author kares
*/
public abstract class EnumerableExt {

//@JRubyMethod
public static IRubyObject to_set(final ThreadContext context, final IRubyObject self, final Block block) {
final Ruby runtime = context.runtime;

RubySet set = new RubySet(runtime, runtime.getClass("Set"));
set.initialize(context, self, block);
return set; // return runtime.getClass("Set").newInstance(context, self, block);
}

@JRubyMethod(rest = true) // to_set(klass = Set, *args, &block)
public static IRubyObject to_set(final ThreadContext context, final IRubyObject self,
final IRubyObject[] args, final Block block) {

if ( args.length == 0 ) return to_set(context, self, block);

final IRubyObject klass = args[0]; args[0] = self;
return ((RubyClass) klass).newInstance(context, args, block);
}

}
1,253 changes: 1,253 additions & 0 deletions core/src/main/java/org/jruby/ext/set/RubySet.java

Large diffs are not rendered by default.

227 changes: 227 additions & 0 deletions core/src/main/java/org/jruby/ext/set/RubySortedSet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
/*
**** BEGIN LICENSE BLOCK *****
* Version: EPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.eclipse.org/legal/epl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2016 Karol Bucek
*
* 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"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/
package org.jruby.ext.set;

import org.jruby.*;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.*;
import org.jruby.runtime.builtin.IRubyObject;

import java.util.*;

import static org.jruby.RubyArray.DefaultComparator;

/**
* Native implementation of Ruby's SortedSet (set.rb replacement).
*
* @author kares
*/
@org.jruby.anno.JRubyClass(name="SortedSet", parent = "Set")
public class RubySortedSet extends RubySet implements SortedSet {

static RubyClass createSortedSetClass(final Ruby runtime) {
RubyClass SortedSet = runtime.defineClass("SortedSet", runtime.getClass("Set"), ALLOCATOR);

SortedSet.setReifiedClass(RubySortedSet.class);
SortedSet.defineAnnotatedMethods(RubySortedSet.class);

return SortedSet;
}

private static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
public RubySortedSet allocate(Ruby runtime, RubyClass klass) {
return new RubySortedSet(runtime, klass);
}
};

private static class OrderComparator extends DefaultComparator {

private final Ruby runtime;

OrderComparator(final Ruby runtime) {
super(null); this.runtime = runtime;
}

@Override
protected ThreadContext context() {
return runtime.getCurrentContext();
}
}

private final TreeSet<IRubyObject> order;

protected RubySortedSet(Ruby runtime, RubyClass klass) {
super(runtime, klass);
order = new TreeSet<>(new OrderComparator(runtime));
}

@Override
void unmarshal() {
super.unmarshal();
IRubyObject[] elems = hash.keys().toJavaArrayMaybeUnsafe();
for ( int i=0; i<elems.length; i++ ) order.add( elems[i] );
}

@JRubyMethod(name = "[]", rest = true, meta = true) // re-def Set[] for SortedSet
public static RubySortedSet create(final ThreadContext context, IRubyObject self, IRubyObject... ary) {
final Ruby runtime = context.runtime;

RubySortedSet set = new RubySortedSet(runtime, (RubyClass) self);
return (RubySortedSet) set.initSet(context, ary, 0, ary.length);
}

@Override
protected void addImpl(final Ruby runtime, final IRubyObject obj) {
// NOTE: we're able to function without the check - comparator will raise ArgumentError
//if ( ! obj.respondsTo("<=>") ) {
// throw runtime.newArgumentError("value must respond to <=>");
//}
super.addImpl(runtime, obj); // @hash[obj] = true
order.add(obj);
}

@Override
protected void addImplSet(final ThreadContext context, final RubySet set) {
super.addImplSet(context, set);
order.addAll(set.elements());
}

@Override
protected boolean deleteImpl(final IRubyObject obj) {
if ( super.deleteImpl(obj) ) {
order.remove(obj); return true;
}
return false;
}

@Override
protected void deleteImplIterator(final IRubyObject obj, final Iterator it) {
super.deleteImpl(obj);
// iterator over elementsOrdered()
it.remove(); // order.remove(obj)
}

@Override
protected void clearImpl() {
hash.rb_clear();
order.clear();
}

@JRubyMethod(name = "sort") // re-def Enumerable#sort
public RubyArray sort(final ThreadContext context) {
return RubyArray.newArray(context.runtime, order); // instead of this.hash.keys();
}

@Override
public RubyArray to_a(final ThreadContext context) {
return sort(context); // instead of this.hash.keys();
}

// NOTE: weirdly Set/SortedSet in Ruby do not have sort!

@Override
protected Set<IRubyObject> elementsOrdered() { return order; }

@Override
public Iterator<Object> iterator() {
return new JavaIterator();
}

// java.util.SortedSet :

public Comparator<? super IRubyObject> comparator() {
return order.comparator();
}

public Object first() {
return firstValue().toJava(Object.class);
}

public IRubyObject firstValue() {
return order.first();
}

public Object last() {
return lastValue().toJava(Object.class);
}

public IRubyObject lastValue() {
return order.last();
}

public SortedSet headSet(Object toElement) {
throw new UnsupportedOperationException("NOT IMPLEMENTED");
}

public SortedSet subSet(Object fromElement, Object toElement) {
throw new UnsupportedOperationException("NOT IMPLEMENTED");
}

public SortedSet tailSet(Object fromElement) {
throw new UnsupportedOperationException("NOT IMPLEMENTED");
}

public SortedSet<IRubyObject> rawHeadSet(IRubyObject toElement) {
return order.headSet(toElement);
}

public SortedSet<IRubyObject> rawSubSet(IRubyObject fromElement, IRubyObject toElement) {
return order.subSet(fromElement, toElement);
}

public SortedSet<IRubyObject> rawTailSet(IRubyObject fromElement) {
return order.tailSet(fromElement);
}

private class JavaIterator implements Iterator<Object> {

private final Iterator<IRubyObject> rawIterator;

JavaIterator() {
rawIterator = RubySortedSet.this.order.iterator();
}

@Override
public boolean hasNext() {
return rawIterator.hasNext();
}

@Override
public Object next() {
return rawIterator.next().toJava(Object.class);
}

@Override
public void remove() {
rawIterator.remove();
}

}

}
45 changes: 45 additions & 0 deletions core/src/main/java/org/jruby/ext/set/SetLibrary.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/***** BEGIN LICENSE BLOCK *****
* Version: EPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.eclipse.org/legal/epl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2016 Karol Bucek
*
* 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"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/
package org.jruby.ext.set;

import org.jruby.Ruby;
import org.jruby.runtime.load.Library;

public final class SetLibrary implements Library {

public void load(Ruby runtime, boolean wrap) {
SetLibrary.load(runtime);
}

public static void load(Ruby runtime) {
RubySet.createSetClass(runtime);
RubySortedSet.createSortedSetClass(runtime);
runtime.getModule("Enumerable").defineAnnotatedMethods(EnumerableExt.class);
}

}
21 changes: 21 additions & 0 deletions core/src/main/ruby/jruby/set.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true
#
# .rb part for JRuby's native Set impl (taken from set.rb)

class Set

def pretty_print(pp) # :nodoc:
pp.text sprintf('#<%s: {', self.class.name)
pp.nest(1) {
pp.seplist(self) { |o|
pp.pp o
}
}
pp.text '}>'
end

def pretty_print_cycle(pp) # :nodoc:
pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...')
end

end
6 changes: 5 additions & 1 deletion spec/ruby/library/set/sortedset/add_spec.rb
Original file line number Diff line number Diff line change
@@ -7,9 +7,13 @@

it "takes only values which responds <=>" do
obj = mock('no_comparison_operator')
obj.should_receive(:respond_to?).with(:<=>).and_return(false)
obj.stub!(:respond_to?).with(:<=>).and_return(false)
lambda { SortedSet["hello"].add(obj) }.should raise_error(ArgumentError)
end

it "raises on incompatible <=> comparison" do
lambda { SortedSet['1', '2'].add(3) }.should raise_error(ArgumentError)
end
end

describe "SortedSet#add?" do
4 changes: 4 additions & 0 deletions spec/ruby/library/set/sortedset/initialize_spec.rb
Original file line number Diff line number Diff line change
@@ -21,4 +21,8 @@
s.should include(4)
s.should include(9)
end

it "raises on incompatible <=> comparison" do
lambda { SortedSet.new(['00', nil]) }.should raise_error(ArgumentError)
end
end
13 changes: 11 additions & 2 deletions spec/ruby/library/set/sortedset/to_a_spec.rb
Original file line number Diff line number Diff line change
@@ -2,7 +2,16 @@
require 'set'

describe "SortedSet#to_a" do
it "returns an array containing elements of self" do
SortedSet[1, 2, 3].to_a.sort.should == [1, 2, 3]
it "returns an array containing elements" do
set = SortedSet.new [1, 2, 3]
set.to_a.should == [1, 2, 3]
end

it "returns a sorted array containing elements" do
set = SortedSet[2, 3, 1]
set.to_a.should == [1, 2, 3]

set = SortedSet.new [5, 6, 4, 4]
set.to_a.should == [4, 5, 6]
end
end
2 changes: 1 addition & 1 deletion test/check_versions.sh
Original file line number Diff line number Diff line change
@@ -64,7 +64,7 @@ function check {
# extended from 9 to 11 to accommodate temporary copy of stdlib 2.3
check lib/target/jruby-stdlib-$jar_version.jar 11
check maven/jruby-jars/pkg/jruby-jars-$gem_version.gem 30
check maven/jruby-jars/lib/jruby-core-$jar_version-complete.jar 13
check maven/jruby-jars/lib/jruby-core-$jar_version-complete.jar 14
# extended from 9 to 11 to accommodate temporary copy of stdlib 2.3
check maven/jruby-jars/lib/jruby-stdlib-$jar_version.jar 11
check maven/jruby-complete/target/jruby-complete-$jar_version.jar 27
121 changes: 121 additions & 0 deletions test/jruby/test_set.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
require 'test/unit'
require 'set.rb'

# JRuby's Set impl specific or low-level details.
class TestSet < Test::Unit::TestCase

class SubSet < Set ; end
class SubSortedSet < SortedSet ; end

def test_sub_set
set = SubSet.new
assert_same SubSet, set.class
assert set.is_a?(SubSet)
assert set.is_a?(Set)
assert hash = set.instance_variable_get(:@hash)
assert hash.is_a?(Hash)
assert_equal Hash.new, hash
assert_equal '#<TestSet::SubSet: {}>', set.inspect

assert_false Set.new.equal?(SubSet.new)
assert_true Set.new.eql?(SubSet.new)
assert_true ( SubSet.new == Set.new )

assert_false SortedSet.new.equal?(SubSortedSet.new)
assert_true SortedSet.new.eql?(SubSortedSet.new)
assert_true ( SubSortedSet.new == Set.new )
assert_true ( SubSortedSet.new == SortedSet.new )
assert_true ( SortedSet.new == SubSortedSet.new )
end

def test_allocate
set = Set.allocate
assert_same Set, set.class
assert_nil set.instance_variable_get(:@hash) # same on MRI

# set not really usable :
begin
set << 1 ; fail 'set << 1 did not fail!'
rescue # NoMethodError # JRuby: NPE
# NoMethodError: undefined method `[]=' for nil:NilClass
# from /opt/local/rvm/rubies/ruby-2.3.3/lib/ruby/2.3.0/set.rb:313:in `add'
end
end

def test_marshal_dump
assert_equal "\x04\b{\x00".force_encoding('ASCII-8BIT'), Marshal.dump(Hash.new)

# MRI internally uses a @hash with a default: `Hash.new(false)'
empty_set = "\x04\bo:\bSet\x06:\n@hash}\x00F".force_encoding('ASCII-8BIT')
assert_equal empty_set, Marshal.dump(Set.new)

dump = Marshal.dump(Set.new)
assert_equal Set.new, Marshal.load(dump)

set = Marshal.load Marshal.dump(Set.new([1, 2]))
assert_same Set, set.class
assert_equal Set.new([1, 2]), set
set << 3
assert_equal 3, set.size

set = Marshal.load Marshal.dump(Set.new([1, 2]).dup)
assert_same Set, set.class
assert_equal Set.new([1, 2]), set
end

def test_sorted_marshal_dump
dump = Marshal.dump(SortedSet.new)
assert_equal SortedSet.new, Marshal.load(dump)

set = Marshal.load Marshal.dump(SortedSet.new([2, 1]))
assert_same SortedSet, set.class
assert_equal SortedSet.new([1, 2]), set
assert_equal [1, 2], set.sort
set << 3
assert_equal 3, set.size
assert_equal [1, 2, 3], set.sort

set = Marshal.load Marshal.dump(SortedSet.new([2, 1]).dup)
assert_same SortedSet, set.class
assert_equal SortedSet.new([1, 2]), set
assert_equal [1, 2], set.to_a

set = Marshal.load Marshal.dump(SortedSet.new([2, 3, 1]))
each = []; set.each { |e| each << e }
assert_equal [1, 2, 3], each
end

def test_dup
set = Set.new [1, 2]
assert_same Set, set.dup.class
assert_equal set, set.dup
dup = set.dup
set << 3
assert_equal 3, set.size
assert_equal 2, dup.size

set = SortedSet.new [1, 2]
assert_same SortedSet, set.dup.class
assert_equal set, set.dup
dup = set.dup
set << 0
assert_equal 3, set.size
assert_equal 2, dup.size
end

def test_to_java
assert set = Set.new.to_java
assert set.toString.start_with?('#<Set:0x')
assert_equal org.jruby.ext.set.RubySet, set.class
assert set.is_a?(java.util.Set)
assert_equal java.util.HashSet.new, set

assert set = SortedSet.new([2, 1]).to_java
assert set.toString.start_with?('#<SortedSet:0x')
assert_equal org.jruby.ext.set.RubySortedSet, set.class
assert set.is_a?(java.util.Set)
assert set.is_a?(java.util.SortedSet)
assert_equal java.util.TreeSet.new([1, 2]), set
end if defined? JRUBY_VERSION

end