golly-utils 0.0.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. data/.corvid/Gemfile +28 -0
  2. data/.corvid/features.yml +4 -0
  3. data/.corvid/plugins.yml +4 -0
  4. data/.corvid/stats_cfg.rb +13 -0
  5. data/.corvid/todo_cfg.rb +15 -0
  6. data/.corvid/versions.yml +2 -0
  7. data/.simplecov +6 -3
  8. data/CHANGELOG.md +45 -2
  9. data/Gemfile +6 -3
  10. data/Gemfile.lock +34 -37
  11. data/Guardfile +10 -4
  12. data/RELEASE.md +2 -0
  13. data/Rakefile +1 -1
  14. data/golly-utils.gemspec +19 -10
  15. data/lib/golly-utils/attr_declarative.rb +120 -49
  16. data/lib/golly-utils/callbacks.rb +211 -19
  17. data/lib/golly-utils/child_process.rb +28 -8
  18. data/lib/golly-utils/delegator.rb +14 -3
  19. data/lib/golly-utils/ruby_ext/classes_and_types.rb +120 -0
  20. data/lib/golly-utils/ruby_ext/enumerable.rb +16 -0
  21. data/lib/golly-utils/ruby_ext/env_helpers.rb +17 -0
  22. data/lib/golly-utils/ruby_ext/kernel.rb +18 -0
  23. data/lib/golly-utils/ruby_ext/options.rb +28 -0
  24. data/lib/golly-utils/ruby_ext/pretty_error_messages.rb +1 -1
  25. data/lib/golly-utils/singleton.rb +130 -0
  26. data/lib/golly-utils/testing/dynamic_fixtures.rb +268 -0
  27. data/lib/golly-utils/testing/file_helpers.rb +117 -0
  28. data/lib/golly-utils/testing/helpers_base.rb +20 -0
  29. data/lib/golly-utils/testing/rspec/arrays.rb +85 -0
  30. data/lib/golly-utils/testing/rspec/base.rb +9 -0
  31. data/lib/golly-utils/testing/rspec/deferrable_specs.rb +111 -0
  32. data/lib/golly-utils/testing/rspec/files.rb +262 -0
  33. data/lib/golly-utils/{test/spec → testing/rspec}/within_time.rb +17 -7
  34. data/lib/golly-utils/version.rb +2 -1
  35. data/test/bootstrap/all.rb +8 -1
  36. data/test/bootstrap/spec.rb +1 -1
  37. data/test/bootstrap/unit.rb +1 -1
  38. data/test/spec/child_process_spec.rb +1 -1
  39. data/test/spec/testing/dynamic_fixtures_spec.rb +131 -0
  40. data/test/spec/testing/rspec/arrays_spec.rb +33 -0
  41. data/test/spec/testing/rspec/files_spec.rb +300 -0
  42. data/test/unit/attr_declarative_test.rb +79 -13
  43. data/test/unit/callbacks_test.rb +103 -5
  44. data/test/unit/delegator_test.rb +25 -1
  45. data/test/unit/ruby_ext/classes_and_types_test.rb +103 -0
  46. data/test/unit/ruby_ext/enumerable_test.rb +12 -0
  47. data/test/unit/ruby_ext/options_test.rb +29 -0
  48. data/test/unit/singleton_test.rb +59 -0
  49. metadata +100 -10
  50. data/Gemfile.corvid +0 -27
  51. data/lib/golly-utils/ruby_ext.rb +0 -2
  52. data/lib/golly-utils/ruby_ext/subclasses.rb +0 -17
  53. data/lib/golly-utils/test/spec/deferrable_specs.rb +0 -85
  54. data/test/unit/ruby_ext/subclasses_test.rb +0 -24
@@ -5,32 +5,63 @@ require 'golly-utils/attr_declarative'
5
5
  class AttrDeclarativeTest < MiniTest::Unit::TestCase
6
6
 
7
7
  class Abc
8
- include GollyUtils::AttrDeclarative
9
8
  attr_declarative :cow
10
- attr_declarative :horse, default: 246
9
+ attr_declarative :horse, :horse2, default: 246
10
+ attr_declarative :important, required: true
11
+ attr_declarative :boolean_style?
12
+ attr_declarative :bang_style!
11
13
  end
12
14
 
13
15
  def test_acts_like_attribute
14
16
  a= Abc.new
15
17
  assert_nil a.cow
16
- a.cow{ 12 }
18
+ a.cow= 12
17
19
  assert_equal 12, a.cow
18
20
  end
19
21
 
20
22
  def test_default
21
23
  a= Abc.new
22
24
  assert_equal 246, a.horse
23
- a.horse{ 'hehe' }
25
+ assert_equal 246, a.horse2
26
+ a.horse= 'hehe'
24
27
  assert_equal 'hehe', a.horse
28
+ assert_equal 246, a.horse2
29
+ end
30
+
31
+ def test_boolean_style_attribute
32
+ a= Abc.new
33
+ a.boolean_style= true
34
+ assert_equal true, a.boolean_style?
35
+ a.boolean_style= false
36
+ assert_equal false, a.boolean_style?
37
+ refute a.respond_to? :boolean_style # reader has ?, writer has =
38
+ end
39
+
40
+ def test_bang_style_attribute
41
+ a= Abc.new
42
+ a.bang_style= 123
43
+ assert_equal 123, a.bang_style!
44
+ refute a.respond_to? :bang_style # reader has !, writer has =
45
+ end
46
+
47
+ class SpecialNames < Abc
48
+ boolean_style? true
49
+ bang_style! 987
50
+ end
51
+ def test_boolean_style_declared_at_class_level
52
+ assert_equal true, SpecialNames.new.boolean_style?
53
+ end
54
+ def test_bang_style_declared_at_class_level
55
+ assert_equal 987, SpecialNames.new.bang_style!
25
56
  end
26
57
 
27
58
  class Abc2 < Abc
28
- cow{ 777 }
59
+ cow 777
29
60
  end
30
61
  def test_subclasses_can_change_defaults
31
62
  a= Abc2.new
32
63
  assert_equal 777, a.cow
33
- a.cow{ 12 }
64
+ a.cow= 12
34
65
  assert_equal 12, a.cow
35
66
  assert_equal 777, Abc2.new.cow
36
67
  assert_nil Abc.new.cow
@@ -39,16 +70,51 @@ class AttrDeclarativeTest < MiniTest::Unit::TestCase
39
70
  class Abc3 < Abc2; end
40
71
  def test_subclasses_inherit_parents_declarations
41
72
  assert_equal 777, Abc3.new.cow
73
+ assert_nil Abc.new.cow
42
74
  end
43
75
 
44
- class Dynamic < Abc
45
- $cow= 123
46
- cow{ $cow }
76
+ def test_instances_setting_to_nil
77
+ assert_nil Abc.new.tap{|x| x.cow= nil}.cow
78
+ assert_nil Abc2.new.tap{|x| x.cow= nil}.cow
79
+ assert_nil Abc3.new.tap{|x| x.cow= nil}.cow
47
80
  end
48
- def test_class_declarations_arent_evaluated_until_needed
49
- a= Dynamic.new
50
- $cow= 456
51
- assert_equal 456, a.cow
81
+
82
+ class Abc4 < Abc
83
+ cow nil
84
+ important 666
85
+ end
86
+ def test_subclass_with_nil_default
87
+ assert_nil Abc.new.cow
88
+ assert_equal 777, Abc3.new.cow
89
+ assert_nil Abc4.new.cow
90
+ end
91
+
92
+ class Seikima
93
+ attr_declarative ok: 'sweet'
94
+ end
95
+ def test_quik_syntax
96
+ assert_equal 'sweet', Seikima.new.ok
97
+ end
98
+
99
+ def test_required_fields_fail_when_undefined
100
+ e= assert_raises(RuntimeError){ Abc.new.important }
101
+ end
102
+
103
+ def test_error_msg_when_required_field_missing_mentions_subclass_name
104
+ e= assert_raises(RuntimeError){ Abc2.new.important }
105
+ assert_match /Abc2/, e.message
52
106
  end
53
107
 
108
+ def test_required_fields_works_as_normal_once_defined
109
+ assert_equal 666, Abc4.new.important
110
+ x= Abc.new
111
+ x.important= 135
112
+ assert_equal 135, x.important
113
+ end
114
+
115
+ def test_required_fields_can_be_set_to_nil
116
+ x= Abc.new
117
+ x.important= nil
118
+ assert_nil x.important
119
+ end
54
120
  end
@@ -14,18 +14,16 @@ class CallbacksTest < MiniTest::Unit::TestCase
14
14
  include GollyUtils::Callbacks
15
15
  define_callback :base
16
16
  def self.record(v); CallbacksTest::VALUES << v end
17
- def self.run
17
+ def self.run(*args)
18
18
  o= self.new
19
- o.run
19
+ o.run(*args)
20
20
  CallbacksTest::VALUES
21
21
  end
22
22
  end
23
23
 
24
24
  class Omg < Base
25
25
  define_callback :wow
26
- def run
27
- run_callback :wow
28
- end
26
+ def run; run_callback :wow end
29
27
  end
30
28
  def test_none; assert_equal [], Omg.run; end
31
29
 
@@ -73,4 +71,104 @@ class CallbacksTest < MiniTest::Unit::TestCase
73
71
  assert_equal 135, Fail.what
74
72
  end
75
73
 
74
+ class Args < Base
75
+ base{ |i| record (i || 0)+5 }
76
+ end
77
+
78
+ def test_run_callback_with_args
79
+ Args.new.run_callback :base, args: [4]
80
+ assert_equal [9], VALUES
81
+ end
82
+
83
+ def test_run_callbacks_with_args_array
84
+ Args.new.run_callbacks :base, args: [3]
85
+ assert_equal [8], VALUES
86
+ end
87
+
88
+ def test_run_callbacks_with_args_nonarray
89
+ Args.new.run_callbacks :base, args: 13
90
+ flunk "Failure expected."
91
+ rescue => e
92
+ assert_match /array/i, e.to_s
93
+ end
94
+
95
+ def test_run_callback_fails_with_unrecognisable_options
96
+ Args.new.run_callback :base, stuff: [3]
97
+ flunk "Failure expected."
98
+ rescue => e
99
+ assert_match /stuff/, e.to_s
100
+ end
101
+
102
+ def test_run_callbacks_fails_with_unrecognisable_options
103
+ Args.new.run_callbacks :base, stuff: [3]
104
+ flunk "Failure expected."
105
+ rescue => e
106
+ assert_match /stuff/, e.to_s
107
+ end
108
+
109
+ module TestModule
110
+ include GollyUtils::Callbacks
111
+ define_callback :from_mod
112
+ end
113
+
114
+ module TestModule2
115
+ include TestModule
116
+ define_callback :from_mod2
117
+ end
118
+
119
+ class WithMod
120
+ include TestModule
121
+ define_callback :bru
122
+ def self.record(v); CallbacksTest::VALUES << v end
123
+ def self.run(*args)
124
+ o= self.new
125
+ o.run_callback :from_mod
126
+ CallbacksTest::VALUES
127
+ end
128
+ from_mod{ record 357 }
129
+ end
130
+ def test_with_module; assert_equal [357], WithMod.run; end
131
+
132
+ def test_callbacks_class_method
133
+ assert_equal [:base], Base.callbacks
134
+ assert_equal [:base, :wow], Omg.callbacks
135
+ assert_equal [:base, :wow], Omg2.callbacks
136
+ assert_equal [:base, :dude, :sweet, :wow], Sweet.callbacks
137
+ end
138
+ def test_callbacks_module_method
139
+ assert_equal [:from_mod], TestModule.callbacks
140
+ assert_equal [:from_mod, :from_mod2], TestModule2.callbacks
141
+ end
142
+ def test_callbacks_class_with_module
143
+ assert_equal [:bru, :from_mod], WithMod.callbacks
144
+ end
145
+
146
+ class Context
147
+ attr_reader :good
148
+ def make_good; @good= 'good' end
149
+ end
150
+ class ContextCallback
151
+ include GollyUtils::Callbacks
152
+ define_callback :go
153
+ go { make_good }
154
+ end
155
+ def test_callback_with_context
156
+ ctx= Context.new
157
+ cc= ContextCallback.new
158
+ cc.run_callback :go, context: ctx
159
+ assert_equal 'good', ctx.good
160
+ end
161
+
162
+ class ContextCallback2 < ContextCallback
163
+ attr_reader :local_too
164
+ def hit_local_too; @local_too= 'yes' end
165
+ go { hit_local_too }
166
+ end
167
+ def test_callback_with_context_can_access_local_too
168
+ ctx= Context.new
169
+ cc= ContextCallback2.new
170
+ cc.run_callback :go, context: ctx
171
+ assert_equal 'good', ctx.good
172
+ assert_equal 'yes', cc.local_too
173
+ end
76
174
  end
@@ -8,6 +8,10 @@ class DelegatorTest < MiniTest::Unit::TestCase
8
8
  def a; 1; end
9
9
  def c; 10; end
10
10
  def add(a,b,c) a+b+c end
11
+ protected
12
+ def prot; 666; end
13
+ private
14
+ def pri; -1; end
11
15
  end
12
16
 
13
17
  class B
@@ -37,7 +41,7 @@ class DelegatorTest < MiniTest::Unit::TestCase
37
41
  assert_equal [10,20], nd(na,nb,delegate_to: :all).c
38
42
  end
39
43
 
40
- def test_respond_to
44
+ def test_respond_to_checks_delegatable
41
45
  d= nd(na,nb)
42
46
  assert d.respond_to?(:a)
43
47
  assert d.respond_to?(:b)
@@ -45,6 +49,13 @@ class DelegatorTest < MiniTest::Unit::TestCase
45
49
  assert !d.respond_to?(:x)
46
50
  end
47
51
 
52
+ def test_respond_to_checks_internal
53
+ d= nd(na,nb)
54
+ refute d.respond_to?(:xxx)
55
+ d.instance_eval 'def xxx; end'
56
+ assert d.respond_to?(:xxx)
57
+ end
58
+
48
59
  def test_caching
49
60
  [true,false].each do |cache|
50
61
  a= na
@@ -96,4 +107,17 @@ class DelegatorTest < MiniTest::Unit::TestCase
96
107
  assert_raises(NoMethodError){ d.b }
97
108
  assert_raises(NoMethodError){ d.add }
98
109
  end
110
+
111
+ def test_protected_methods_not_allowed_by_default
112
+ assert_raises(NoMethodError){ nd(na).prot }
113
+ end
114
+
115
+ def test_protected_methods_allowed_when_enabled
116
+ assert_equal 666, nd(na, allow_protected: true).prot
117
+ end
118
+
119
+ def test_private_methods_not_allowed
120
+ assert_raises(NoMethodError){ nd(na).pri }
121
+ assert_raises(NoMethodError){ nd(na, allow_protected: true).pri }
122
+ end
99
123
  end
@@ -0,0 +1,103 @@
1
+ # encoding: utf-8
2
+ require_relative '../../bootstrap/unit'
3
+ require 'golly-utils/ruby_ext/classes_and_types'
4
+
5
+ class ClassesAndTypesTest < MiniTest::Unit::TestCase
6
+ class A; end
7
+ class B < A; end
8
+ class C < A; end
9
+ class B1 < B; end
10
+ class B2 < B; end
11
+
12
+ def assert_arrays(exp,act)
13
+ v= [exp,act].map{|a| a.sort_by(&:to_s) }
14
+ assert_equal *v
15
+ end
16
+
17
+ def test_subclasses_all
18
+ assert_arrays [B,C,B1,B2], A.subclasses(true)
19
+ end
20
+
21
+ def test_subclasses_leaf_nodes_only
22
+ assert_arrays [C,B1,B2], A.subclasses
23
+ end
24
+
25
+ #---------------------------------------------------------------------------------------------------------------------
26
+
27
+ def test_superclasses_on_instance
28
+ assert_equal [B1,B,A,Object,BasicObject], B1.new.superclasses
29
+ end
30
+
31
+ def test_superclasses_on_class
32
+ assert_equal [B1,B,A,Object,BasicObject], B1.superclasses
33
+ end
34
+
35
+ def test_superclasses_on_ruby_internals
36
+ assert_equal [NilClass,Object,BasicObject], nil.superclasses
37
+ assert_equal [TrueClass,Object,BasicObject], true.superclasses
38
+ end
39
+
40
+ class BO < BasicObject; end
41
+ def test_superclasses_on_basic_object_subclass
42
+ assert_equal [BO,BasicObject], BO.superclasses
43
+ #assert_equal [BO,BasicObject], BO.new.superclasses
44
+ end
45
+
46
+ #---------------------------------------------------------------------------------------------------------------------
47
+
48
+ def test_validate_type_passes_when_exact_match
49
+ B.new.validate_type! B
50
+ B.new.validate_type! A
51
+ end
52
+
53
+ def test_validate_type_passes_with_name
54
+ B.new.validate_type! 'hehe', B
55
+ B.new.validate_type! :hehe, A
56
+ end
57
+
58
+ def test_validate_type_passes_when_any_match
59
+ B.new.validate_type! B, String
60
+ B.new.validate_type! String, A
61
+ end
62
+
63
+ def test_validate_type_allows_primatives
64
+ true.validate_type! true
65
+ false.validate_type! false
66
+ nil.validate_type! nil
67
+ nil.validate_type! NilClass
68
+ nil.validate_type! nil, B
69
+ end
70
+
71
+ def test_validate_type_fail
72
+ assert_raises(TypeValidationError){ B.new.validate_type! String }
73
+ end
74
+
75
+ def test_validate_type_fail_with_name
76
+ assert_raises(TypeValidationError){ B.new.validate_type! 'hehe', String }
77
+ assert_raises(TypeValidationError){ B.new.validate_type! :hehe, String }
78
+ end
79
+
80
+ def test_validate_type_fail_uses_name_in_errmsg
81
+ 3.validate_type! 'hehe', String
82
+ raise "Error expected."
83
+ rescue => e
84
+ assert_match /for hehe/, e.to_s
85
+ end
86
+
87
+ #---------------------------------------------------------------------------------------------------------------------
88
+
89
+ def test_validate_lvar_type!
90
+ hehe= 123
91
+ :hehe.validate_lvar_type!{ Fixnum }
92
+ :hehe.validate_lvar_type!{ [nil,Fixnum] }
93
+ assert_raises(TypeValidationError){ :hehe.validate_lvar_type!{ String }}
94
+ end
95
+
96
+ def test_validate_lvar_type_uses_name_in_errmsg
97
+ hehe= 'no'
98
+ :hehe.validate_lvar_type!{ Fixnum }
99
+ raise "Error expected."
100
+ rescue => e
101
+ assert_match /for hehe/, e.to_s
102
+ end
103
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+ require_relative '../../bootstrap/unit'
3
+ require 'golly-utils/ruby_ext/enumerable'
4
+
5
+ class EnumerableTest < MiniTest::Unit::TestCase
6
+
7
+ def test_frequency_map
8
+ x= [1, 4, 'a', 4, :b, :b, :b].frequency_map
9
+ assert_equal({1=>1, 4=>2, 'a'=>1, b:3}, x)
10
+ end
11
+
12
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+ require_relative '../../bootstrap/unit'
3
+ require 'golly-utils/ruby_ext/options'
4
+
5
+ class OptionsTest < MiniTest::Unit::TestCase
6
+
7
+ def test_nop_when_all_keys_valid
8
+ {a:1,b:2}.validate_option_keys :a, :b
9
+ {a:1,b:2}.validate_option_keys :a, :b, :c
10
+ end
11
+
12
+ def test_nop_when_hash_empty
13
+ {}.validate_option_keys :a, :b
14
+ end
15
+
16
+ def test_error_when_extra_keys
17
+ assert_raises(RuntimeError){ {a:1,b:2}.validate_option_keys :a }
18
+ end
19
+
20
+ def test_error_msg_contains_all_invalid_key_names
21
+ {aaa:1,'bbb' => 2, x:5}.validate_option_keys :x
22
+ flunk 'Error expected.'
23
+ rescue => e
24
+ assert_match /:aaa/, e.to_s
25
+ assert_match /"bbb"/, e.to_s
26
+ refute_match /x/, e.to_s
27
+ end
28
+
29
+ end