Skip to content

Commit 61632bd

Browse files
committed
🚧 Check if the Data implementation is sufficient
This should _not_ be merged into main. 😉 It's only temporary, until bugs in TruffleRuby and JRuby are addressed: * jruby/jruby#8829 * oracle/truffleruby#3846 * oracle/truffleruby#3847 The JRuby bug is a showstopper. The TruffleRuby bugs are cosmetic (inspect "nil" vs "") or academic (we never create recursive Data).
1 parent 440e01e commit 61632bd

File tree

3 files changed

+94
-8
lines changed

3 files changed

+94
-8
lines changed

lib/net/imap/data_lite.rb

+48-8
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,54 @@
2626

2727
module Net
2828
class IMAP
29-
data_or_object =
30-
if RUBY_VERSION >= "3.2.0" && defined?(::Data) && ::Data.respond_to?(:define)
31-
::Data
32-
else
33-
Object
29+
30+
# :nocov:
31+
# Skip coverage: how much of the file runs depends on the engine version.
32+
33+
# Test whether RUBY_ENGINE has sufficient support for ::Data.
34+
# TODO: golf this down to the bare minimum that's failing.
35+
data_or_object = ::Object
36+
if defined?(::Data) && ::Data.respond_to?(:define)
37+
begin
38+
class TestData < ::Data
39+
def self.YAML(data)
40+
coder = Struct.new(:map).new(data)
41+
data = self.allocate
42+
data.init_with(coder)
43+
data
44+
end
45+
def init_with(coder) initialize(**coder.map.transform_keys(&:to_sym)) end
46+
def deconstruct; [:ok, *super] end
47+
end
48+
49+
class TestDataDefine < TestData.define(:str, :bool)
50+
def initialize(str: nil, bool: nil)
51+
str => String | nil; str = -str if str
52+
bool => true | false | nil; bool = !!bool
53+
super
54+
end
55+
end
56+
57+
test_init = TestDataDefine.YAML({"str" => "str"})
58+
test_empty = TestData.define[]
59+
60+
if test_init.deconstruct != [:ok, "str", false]
61+
raise "subclassing misbehaves"
62+
elsif test_empty.deconstruct != [:ok]
63+
raise "can't define empty"
64+
end
65+
data_or_object = ::Data
66+
rescue => ex
67+
warn "Insufficient implementation of Data: %s (%s) for %s %s" % [
68+
ex, ex.class, RUBY_ENGINE, RUBY_ENGINE_VERSION,
69+
]
70+
data_or_object = ::Object
71+
ensure
72+
remove_const :TestData if const_defined?(:TestData)
73+
remove_const :TestDataDefine if const_defined?(:TestDataDefine)
3474
end
75+
end
76+
3577
class DataLite < data_or_object
3678
def encode_with(coder) coder.map = to_h.transform_keys(&:to_s) end
3779
def init_with(coder) initialize(**coder.map.transform_keys(&:to_sym)) end
@@ -41,9 +83,7 @@ def init_with(coder) initialize(**coder.map.transform_keys(&:to_sym)) end
4183
end
4284
end
4385

44-
# :nocov:
45-
# Need to skip test coverage for the rest, because it isn't loaded by ruby 3.2+.
46-
return if RUBY_VERSION >= "3.2.0" && defined?(::Data) && ::Data.respond_to?(:define)
86+
return unless Net::IMAP::DataLite.superclass == Object
4787

4888
module Net
4989
class IMAP

test/net/imap/test_data_lite.rb

+44
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ def test_inspect
154154
end
155155

156156
def test_recursive_inspect
157+
# TODO: TruffleRuby's Data fails this test with a StackOverflowError
157158
klass = Data.define(:value, :head, :tail) do
158159
def initialize(value:, head: nil, tail: nil)
159160
case tail
@@ -183,6 +184,7 @@ def initialize(value:, head: nil, tail: nil)
183184
" tail=#<data value=3, head=#{seen}," \
184185
" tail=#<data value=4, head=#{seen}," \
185186
" tail=nil>>>>",
187+
# TODO: JRuby's Data fails on the next line
186188
list.inspect
187189
)
188190

@@ -196,6 +198,7 @@ def initialize(value:, head: nil, tail: nil)
196198
" tail=#<data DoubleLinkList value=3, head=#{seen}," \
197199
" tail=#<data DoubleLinkList value=4, head=#{seen}," \
198200
" tail=nil>>>>",
201+
# TODO: JRuby's Data fails on the next line
199202
list.inspect
200203
)
201204
ensure
@@ -340,6 +343,47 @@ def other
340343
assert_equal("test", data.name)
341344
assert_equal("other", data.other)
342345
end
346+
347+
class Abstract < Data
348+
end
349+
350+
class Inherited < Abstract.define(:foo)
351+
end
352+
353+
def test_subclass_can_create
354+
# TODO: JRuby's Data fails all of these
355+
assert_equal 1, Inherited[1] .foo
356+
assert_equal 2, Inherited[foo: 2].foo
357+
assert_equal 3, Inherited.new(3).foo
358+
assert_equal 4, Inherited.new(foo: 4).foo
359+
end
360+
361+
class AbstractWithClassMethod < Data
362+
def self.inherited_class_method; :ok end
363+
end
364+
365+
class InheritsClassMethod < AbstractWithClassMethod.define(:foo)
366+
end
367+
368+
def test_subclass_class_method
369+
# TODO: JRuby's Data fails on the next line
370+
assert_equal :ok, InheritsClassMethod.inherited_class_method
371+
end
372+
373+
class AbstractWithOverride < Data
374+
def deconstruct; [:ok, *super] end
375+
end
376+
377+
class InheritsOverride < AbstractWithOverride.define(:foo)
378+
end
379+
380+
def test_subclass_override_deconstruct
381+
# TODO: JRuby's Data fails on the next line
382+
data = InheritsOverride[:foo]
383+
# TODO: TruffleRuby's Data fails on the next line
384+
assert_equal %i[ok foo], data.deconstruct
385+
end
386+
343387
end
344388
end
345389
end

test/net/imap/test_imap_connection_state.rb

+2
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ class ConnectionStateTest < Test::Unit::TestCase
2626
end
2727

2828
test "#deconstruct" do
29+
# TODO: TruffleRuby's Data fails these
2930
assert_equal [:not_authenticated], NotAuthenticated[].deconstruct
3031
assert_equal [:authenticated], Authenticated[] .deconstruct
3132
assert_equal [:selected], Selected[] .deconstruct
3233
assert_equal [:logout], Logout[] .deconstruct
3334
end
3435

3536
test "#deconstruct_keys" do
37+
# TODO: TruffleRuby's Data fails these
3638
assert_equal({symbol: :not_authenticated}, NotAuthenticated[].deconstruct_keys([:symbol]))
3739
assert_equal({symbol: :authenticated}, Authenticated[] .deconstruct_keys([:symbol]))
3840
assert_equal({symbol: :selected}, Selected[] .deconstruct_keys([:symbol]))

0 commit comments

Comments
 (0)