rdl 1.0.0.rc3 → 1.0.0.rc4

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +44 -0
  3. data/.travis.yml +19 -0
  4. data/LICENSE +29 -0
  5. data/README.md +509 -0
  6. data/Rakefile +27 -0
  7. data/gemfiles/Gemfile.travis +5 -0
  8. data/lib/rdl/wrap.rb +1 -1
  9. data/lib/rdl_types.rb +4 -2
  10. data/rdl.gemspec +23 -0
  11. data/test/disabled_test_coverage.rb +156 -0
  12. data/test/disabled_test_rdoc.rb +116 -0
  13. data/test/test_alias.rb +66 -0
  14. data/test/test_contract.rb +70 -0
  15. data/test/test_dsl.rb +85 -0
  16. data/test/test_generic.rb +188 -0
  17. data/test/test_intersection.rb +41 -0
  18. data/test/test_le.rb +193 -0
  19. data/test/test_lib_types.rb +194 -0
  20. data/test/test_member.rb +148 -0
  21. data/test/test_parser.rb +196 -0
  22. data/test/test_rdl.rb +301 -0
  23. data/test/test_rdl_type.rb +70 -0
  24. data/test/test_type_contract.rb +187 -0
  25. data/test/test_types.rb +221 -0
  26. data/test/test_wrap.rb +46 -0
  27. data/types/{ruby-2.2.0 → ruby-2.x}/_aliases.rb +0 -0
  28. data/types/{ruby-2.2.0 → ruby-2.x}/abbrev.rb +2 -2
  29. data/types/{ruby-2.2.0 → ruby-2.x}/array.rb +2 -2
  30. data/types/{ruby-2.2.0 → ruby-2.x}/base64.rb +2 -2
  31. data/types/{ruby-2.2.0 → ruby-2.x}/basic_object.rb +2 -1
  32. data/types/{ruby-2.2.0 → ruby-2.x}/benchmark.rb +2 -2
  33. data/types/{ruby-2.2.0 → ruby-2.x}/bigdecimal.rb +4 -4
  34. data/types/{ruby-2.2.0 → ruby-2.x}/bigmath.rb +2 -2
  35. data/types/{ruby-2.2.0 → ruby-2.x}/class.rb +3 -3
  36. data/types/{ruby-2.2.0 → ruby-2.x}/complex.rb +2 -2
  37. data/types/{ruby-2.2.0 → ruby-2.x}/coverage.rb +2 -2
  38. data/types/{ruby-2.2.0 → ruby-2.x}/csv.rb +2 -2
  39. data/types/{ruby-2.2.0 → ruby-2.x}/date.rb +2 -2
  40. data/types/{ruby-2.2.0 → ruby-2.x}/dir.rb +3 -3
  41. data/types/{ruby-2.2.0 → ruby-2.x}/encoding.rb +2 -2
  42. data/types/{ruby-2.2.0 → ruby-2.x}/enumerable.rb +2 -2
  43. data/types/{ruby-2.2.0 → ruby-2.x}/enumerator.rb +1 -1
  44. data/types/{ruby-2.2.0 → ruby-2.x}/exception.rb +2 -0
  45. data/types/{ruby-2.2.0 → ruby-2.x}/file.rb +2 -2
  46. data/types/{ruby-2.2.0 → ruby-2.x}/fileutils.rb +1 -1
  47. data/types/{ruby-2.2.0 → ruby-2.x}/fixnum.rb +2 -2
  48. data/types/{ruby-2.2.0 → ruby-2.x}/float.rb +2 -2
  49. data/types/{ruby-2.2.0 → ruby-2.x}/gem.rb +3 -1
  50. data/types/{ruby-2.2.0 → ruby-2.x}/hash.rb +2 -2
  51. data/types/{ruby-2.2.0 → ruby-2.x}/integer.rb +2 -2
  52. data/types/{ruby-2.2.0 → ruby-2.x}/io.rb +1 -1
  53. data/types/{ruby-2.2.0 → ruby-2.x}/kernel.rb +1 -1
  54. data/types/{ruby-2.2.0 → ruby-2.x}/marshal.rb +2 -2
  55. data/types/{ruby-2.2.0 → ruby-2.x}/matchdata.rb +3 -3
  56. data/types/{ruby-2.2.0 → ruby-2.x}/math.rb +2 -2
  57. data/types/{ruby-2.2.0 → ruby-2.x}/numeric.rb +2 -2
  58. data/types/{ruby-2.2.0 → ruby-2.x}/object.rb +1 -1
  59. data/types/{ruby-2.2.0 → ruby-2.x}/pathname.rb +2 -2
  60. data/types/{ruby-2.2.0 → ruby-2.x}/process.rb +8 -8
  61. data/types/{ruby-2.2.0 → ruby-2.x}/random.rb +2 -2
  62. data/types/{ruby-2.2.0 → ruby-2.x}/range.rb +2 -2
  63. data/types/{ruby-2.2.0 → ruby-2.x}/rational.rb +2 -2
  64. data/types/{ruby-2.2.0 → ruby-2.x}/regexp.rb +2 -2
  65. data/types/{ruby-2.2.0 → ruby-2.x}/set.rb +2 -2
  66. data/types/{ruby-2.2.0 → ruby-2.x}/string.rb +1 -1
  67. data/types/{ruby-2.2.0 → ruby-2.x}/strscan.rb +3 -3
  68. data/types/{ruby-2.2.0 → ruby-2.x}/symbol.rb +2 -2
  69. data/types/{ruby-2.2.0 → ruby-2.x}/time.rb +2 -2
  70. data/types/ruby-2.x/uri.rb +20 -0
  71. data/types/{ruby-2.2.0 → ruby-2.x}/yaml.rb +3 -3
  72. metadata +70 -51
  73. data/lib/rdl/types/wild.rb +0 -26
  74. data/types/other/chronic.rb +0 -5
  75. data/types/other/paperclip_attachment.rb +0 -7
  76. data/types/other/securerandom.rb +0 -4
  77. data/types/ruby-2.2.0/uri.rb +0 -18
@@ -0,0 +1,27 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
9
+
10
+ task :skel, [:cname,:prettyname] do |skel, varhash|
11
+ kls = eval "#{varhash[:cname]}.new"
12
+ mthds = kls.public_methods(false) + kls.private_methods(false) + kls.protected_methods(false)
13
+ mname = "types/ruby-2.2.3/#{varhash[:prettyname]}.rb"
14
+ touch mname
15
+ mthds.sort.each{ |m|
16
+ sh "echo \" type '#{m}', '() -> '\" >> #{mname}"
17
+ }
18
+ sh "echo \"end\" >> #{mname}"
19
+ end
20
+
21
+ task :stat, [:fname,:outpath] do |stat,varhash|
22
+ ruby "extras/rdlstat.rb #{varhash[:fname]} #{varhash[:outpath]}"
23
+ end
24
+
25
+ task :statrun, [:fname] do |statrun,varhash|
26
+ ruby "#{varhash[:fname]}"
27
+ end
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rake'
4
+ gem 'minitest'
5
+ gem 'require_all'
@@ -401,7 +401,7 @@ class Object
401
401
  }
402
402
  end
403
403
 
404
- def nowrap
404
+ def rdl_nowrap
405
405
  $__rdl_contract_switch.off {
406
406
  RDL.config { |config| config.add_nowrap(self, self.singleton_class) }
407
407
  }
@@ -1,2 +1,4 @@
1
- require_rel "../types/ruby-#{RUBY_VERSION}/_aliases.rb" # load type aliases first
2
- require_rel "../types/ruby-#{RUBY_VERSION}/*.rb"
1
+ dir = RUBY_VERSION.split('.')[0] + ".x"
2
+
3
+ require_rel "../types/ruby-#{dir}/_aliases.rb" # load type aliases first
4
+ require_rel "../types/ruby-#{dir}/*.rb"
@@ -0,0 +1,23 @@
1
+ # In the top directory
2
+ # gem build rdl.gemspec
3
+ # gem install rdl-1.0.0.beta.1.gem
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'rdl'
7
+ s.version = '1.0.0.rc4'
8
+ s.date = '2015-12-17'
9
+ s.summary = 'Ruby type and contract system'
10
+ s.description = <<-EOF
11
+ RDL is a gem that allows contracts (pre- and postconditions) to be added to methods.
12
+ Preconditions are checked at run time when the method is called, and
13
+ postconditions are checked at run time when the method returns.
14
+ RDL also includes extensive support for type contracts, which check the types of arguments and returns
15
+ when the method is called and when it returns, respectively.
16
+ EOF
17
+ s.authors = ['Jeffrey S. Foster', 'Brianna M. Ren', 'T. Stephen Strickland', 'Alexander T. Yu']
18
+ s.email = ['rdl-users@googlegroups.com']
19
+ s.files = `git ls-files`.split($/)
20
+ s.homepage = 'https://github.com/plum-umd/rdl'
21
+ s.license = 'BSD-3-Clause'
22
+ s.add_runtime_dependency 'require_all', '~> 1.3', '>= 1.3.3'
23
+ end
@@ -0,0 +1,156 @@
1
+ require 'set'
2
+ require 'abbrev'
3
+ require 'base64'
4
+ require 'benchmark'
5
+ require 'bigdecimal'
6
+ require 'bigdecimal/math'
7
+ require 'coverage.so'
8
+
9
+ require 'minitest/autorun'
10
+ require_relative '../lib/rdl.rb'
11
+ require_relative '../lib/rdl_types.rb'
12
+
13
+ RDL::Config.instance.profile_stats
14
+
15
+ class Dummy
16
+ def self.each
17
+ end
18
+ def each
19
+ end
20
+ end
21
+
22
+ class TestStdlibTypes < Minitest::Test
23
+
24
+ def test_abbrev
25
+ assert_raises(RDL::Type::TypeError) { s0 = Abbrev.abbrev 5}
26
+ # From the Ruby stdlib documentation
27
+ s1 = Abbrev.abbrev(['ruby']) # -> {"ruby"=>"ruby", "rub"=>"ruby", "ru"=>"ruby", "r"=>"ruby"}
28
+ ev = {"ruby"=>"ruby", "rub"=>"ruby", "ru"=>"ruby", "r"=>"ruby"}
29
+ assert_equal(s1,ev)
30
+ # Other tests
31
+ assert_raises(RDL::Type::TypeError) { s2 = Abbrev.abbrev Dummy.new }
32
+ end
33
+
34
+ def test_base64
35
+ # From the Ruby stdlib documentation
36
+ e0 = Base64.encode64('Send reinforcements') # -> "U2VuZCByZWluZm9yY2VtZW50cw==\n"
37
+ d0 = Base64.decode64(e0) # -> "Send reinforcements"
38
+ #assert_equal(e0,d0)
39
+ e1 = Base64.strict_encode64('Send reinforcements')
40
+ d1 = Base64.strict_decode64(e1)
41
+ #assert_equal(e1,d1)
42
+ e2 = Base64.urlsafe_encode64('Send reinforcements')
43
+ d2 = Base64.urlsafe_decode64(e2)
44
+ #assert_equal(e2,d2)
45
+ end
46
+
47
+ def test_benchmark
48
+ skip "Skip these because they print to stdout"
49
+ # From the Ruby stdlib documentation
50
+ Benchmark.measure { "a"*1_000_000_000 }
51
+ n = 5000000
52
+ Benchmark.bm do |x|
53
+ x.report { for i in 1..n; a = "1"; end }
54
+ x.report { n.times do ; a = "1"; end }
55
+ x.report { 1.upto(n) do ; a = "1"; end }
56
+ end
57
+ Benchmark.bm(7) do |x|
58
+ x.report("for:") { for i in 1..n; a = "1"; end }
59
+ x.report("times:") { n.times do ; a = "1"; end }
60
+ x.report("upto:") { 1.upto(n) do ; a = "1"; end }
61
+ end
62
+ array = (1..1000000).map { rand }
63
+ Benchmark.bmbm do |x|
64
+ #x.report("sort!") { array.dup.sort! } # TODO this causes a hang
65
+ #x.report("sort") { array.dup.sort }
66
+ end
67
+ Benchmark.benchmark(Benchmark::CAPTION, 7, Benchmark::FORMAT, ">total:", ">avg:") do |x|
68
+ tf = x.report("for:") { for i in 1..n; a = "1"; end }
69
+ tt = x.report("times:") { n.times do ; a = "1"; end }
70
+ tu = x.report("upto:") { 1.upto(n) do ; a = "1"; end }
71
+ [tf+tt+tu, (tf+tt+tu)/3]
72
+ end
73
+ end
74
+
75
+ def test_bigdecimal
76
+ # From the RUby stdlib documentation
77
+ BigDecimal.save_exception_mode do
78
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
79
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
80
+
81
+ BigDecimal.new(BigDecimal('Infinity'))
82
+ BigDecimal.new(BigDecimal('-Infinity'))
83
+ BigDecimal(BigDecimal.new('NaN'))
84
+ end
85
+ BigDecimal.save_limit do
86
+ BigDecimal.limit(200)
87
+ end
88
+ BigDecimal.save_rounding_mode do
89
+ BigDecimal.mode(BigDecimal::ROUND_MODE, :up)
90
+ end
91
+ # Additional test calls for coverage
92
+ BigDecimal.double_fig
93
+ BigDecimal.limit(5)
94
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true)
95
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
96
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN)
97
+ BigDecimal.ver
98
+
99
+ # TODO
100
+ end
101
+
102
+ def test_bigmath
103
+ # From the Ruby stdlib documentation
104
+ BigMath.E(10)
105
+ BigMath.PI(10)
106
+ BigMath.atan(BigDecimal.new('-1'), 16)
107
+ BigMath.cos(BigMath.PI(4), 16)
108
+ BigMath.sin(BigMath.PI(5)/4, 5)
109
+ BigMath.sqrt(BigDecimal.new('2'), 16)
110
+ end
111
+
112
+ def test_coverage
113
+ Coverage.start
114
+ Coverage.result
115
+ #Coverage.result # TODO This cannot be typechecked
116
+ end
117
+
118
+ def test_set
119
+ assert_raises(RDL::Type::TypeError) { s6 = Set.new(1,2) }
120
+ # From the Ruby stdlib documentation
121
+ s1 = Set.new [1, 2] # -> #<Set: {1, 2}>
122
+ s2 = [1, 2].to_set # -> #<Set: {1, 2}>
123
+ s1 == s2 # -> true
124
+ s1.add("foo") # -> #<Set: {1, 2, "foo"}>
125
+ s1.merge([2, 6]) # -> #<Set: {1, 2, "foo", 6}>
126
+ s1.subset? s2 # -> false
127
+ s2.subset? s1 # -> true
128
+ Set[1, 2, 3].disjoint? Set[3, 4] # => false
129
+ Set[1, 2, 3].disjoint? Set[4, 5] # => true
130
+ numbers = Set[1, 3, 4, 6, 9, 10, 11]
131
+ set = numbers.divide { |i,j| (i - j).abs == 1 }
132
+ Set[1, 2, 3].intersect? Set[4, 5] # => false
133
+ Set[1, 2, 3].intersect? Set[3, 4] # => true
134
+ # Some more tests, just to make sure type checking doesn't cause crashes
135
+ s3 = s1 - s2
136
+ s1.proper_subset? s2
137
+ s1.superset? s2
138
+ s1 ^ s2
139
+ s1.add?("bar")
140
+ h = s1.classify { |x| x.size }
141
+ s2.clear
142
+ s4 = s1.map { |x| 42 }
143
+ s1.delete "foo"
144
+ s1.delete? "bar"
145
+ s1.delete_if { |x| false }
146
+ s1.each { |x| nil }
147
+ s1.empty?
148
+ s1.member? 42
149
+ s1.intersection [1,2,3]
150
+ s1.keep_if { |x| true }
151
+ s1.size
152
+ s1.difference [1,2,3]
153
+ s1.to_a
154
+ s5 = s1 + s2
155
+ end
156
+ end
@@ -0,0 +1,116 @@
1
+ require 'minitest/autorun'
2
+ require 'rdoc'
3
+ require 'erb'
4
+ require 'fileutils'
5
+ require 'pathname'
6
+ require 'pp'
7
+ require 'tempfile'
8
+ require 'tmpdir'
9
+
10
+ require 'rdoc'
11
+ require_relative '../lib/rdl.rb'
12
+
13
+ class RdocTest < MiniTest::Test
14
+
15
+ class TestClass
16
+ extend RDL
17
+
18
+ typesig :size, "()->Fixnum"
19
+ typesig :bytesize, "()->Fixnum"
20
+ end
21
+
22
+ def test_rdoc_gen
23
+ skip "TEST WITH NO ASSERTIONS"
24
+ rdocTypesigFor(TestClass)
25
+ end
26
+ end
27
+
28
+ class TestRDLRDoc
29
+ =begin
30
+ @have_encoding = Object.const_defined? :Encoding
31
+ @RM = RDoc::Markup
32
+ RDoc::Markup::PreProcess.reset
33
+ @pwd = Dir.pwd
34
+ @store = RDoc::Store.new
35
+ @rdoc = RDoc::RDoc.new
36
+ @rdoc.store = @store
37
+ @rdoc.options = RDoc::Options.new
38
+
39
+ g = Object.new
40
+ def g.class_dir() end
41
+ def g.file_dir() end
42
+ @rdoc.generator = g
43
+
44
+ @lib_dir = "#{@pwd}/lib"
45
+ $LOAD_PATH.unshift @lib_dir # ensure we load from this RDoc
46
+
47
+ @options = RDoc::Options.new
48
+ @options.option_parser = OptionParser.new
49
+
50
+ p Dir.tmpdir
51
+ @tmpdir = File.join Dir.tmpdir, "test_rdoc_generator_darkfish_#{$$}"
52
+ FileUtils.mkdir_p @tmpdir
53
+ Dir.chdir @tmpdir
54
+ @options.op_dir = @tmpdir
55
+ @options.generator = RDoc::Generator::Darkfish
56
+
57
+ $LOAD_PATH.each do |path|
58
+ darkfish_dir = File.join path, 'rdoc/generator/template/darkfish/'
59
+ next unless File.directory? darkfish_dir
60
+ @options.template_dir = darkfish_dir
61
+ break
62
+ end
63
+
64
+ @rdoc.options = @options
65
+
66
+ @g = @options.generator.new @store, @options
67
+ @rdoc.generator = @g
68
+
69
+ @top_level = @store.add_file 'file.rb'
70
+ @top_level.parser = RDoc::Parser::Ruby
71
+ klass = @top_level.add_class RDoc::NormalClass, 'RDL_TEST_Klass(String)'
72
+
73
+ alis_constant = RDoc::Constant.new 'ABC', nil, ''
74
+ alis_constant.record_location @top_level
75
+
76
+ @top_level.add_constant alis_constant
77
+
78
+ klass.add_module_alias klass, 'AAA', @top_level
79
+
80
+ meth = RDoc::AnyMethod.new nil, 'Size'
81
+ tmthd = String.instance_variable_get(:@__typesigs)[:size]
82
+ msig = "()->#{tmthd.ret}"
83
+ eval "
84
+ def meth.param_seq
85
+ return \"%s\"
86
+ end
87
+ def meth.comment
88
+ true
89
+ end
90
+ def meth.description
91
+ return \"%s\"
92
+ end
93
+ " % [msig,"Takes input {Params} and outputs {Return}"]
94
+
95
+ meth_bang = RDoc::AnyMethod.new nil, 'method!'
96
+ attr = RDoc::Attr.new nil, 'attr', 'RW', ''
97
+
98
+ klass.add_method meth
99
+ klass.add_method meth_bang
100
+ klass.add_attribute attr
101
+
102
+ ignored = @top_level.add_class RDoc::NormalClass, 'Ignored'
103
+ ignored.ignore
104
+
105
+ #@store.complete :private
106
+
107
+ @object = @store.find_class_or_module 'Object'
108
+ klass_alias = @store.find_class_or_module 'Klass::A'
109
+
110
+ top_level = @store.add_file 'file.rb'
111
+ top_level.add_class klass.class, klass.name
112
+
113
+ @g.generate
114
+ p File.file?('index.html')
115
+ =end
116
+ end
@@ -0,0 +1,66 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../lib/rdl.rb'
3
+
4
+ class TestAlias < Minitest::Test
5
+
6
+ def test_alias_lookup
7
+ self.class.class_eval {
8
+ rdl_alias :foobar1, :foobar
9
+ rdl_alias :foobar2, :foobar
10
+ rdl_alias :foobar3, :foobar2
11
+ rdl_alias :foobar4, :foobar3
12
+ rdl_alias :foobar5, :foobar2
13
+ }
14
+ assert_equal :foobar, RDL::Wrap.resolve_alias(TestAlias, :foobar)
15
+ assert_equal :foobar, RDL::Wrap.resolve_alias(TestAlias, :foobar1)
16
+ assert_equal :foobar, RDL::Wrap.resolve_alias(TestAlias, :foobar2)
17
+ assert_equal :foobar, RDL::Wrap.resolve_alias(TestAlias, :foobar3)
18
+ assert_equal :foobar, RDL::Wrap.resolve_alias(TestAlias, :foobar4)
19
+ assert_equal :foobar, RDL::Wrap.resolve_alias(TestAlias, :foobar5)
20
+ end
21
+
22
+ def test_basic_alias_contract
23
+ self.class.class_eval {
24
+ pre { |x| x > 0 }
25
+ def m1(x) return x; end
26
+ alias_method :m2, :m1
27
+ }
28
+ assert_equal 3, m2(3)
29
+ assert_raises(RDL::Contract::ContractError) { m2(-1) }
30
+ self.class.class_eval { alias m3 m1 }
31
+ assert_equal 3, m3(3)
32
+ assert_raises(RDL::Contract::ContractError) { m3(-1) }
33
+ end
34
+
35
+ def test_existing_alias_contract
36
+ self.class.class_eval {
37
+ def m4(x) return x; end
38
+ alias_method :m5, :m4
39
+ rdl_alias :m5, :m4
40
+ pre(:m4) { |x| x > 0 }
41
+ }
42
+ assert_equal 3, m5(3)
43
+ assert_raises(RDL::Contract::ContractError) { m5(-1) }
44
+
45
+ def m6(x) return x; end
46
+ self.class.class_eval {
47
+ alias m7 m6
48
+ rdl_alias :m7, :m6
49
+ pre(:m6) { |x| x > 0 }
50
+ }
51
+ assert_equal 3, m7(3)
52
+ assert_raises(RDL::Contract::ContractError) { m7(-1) }
53
+
54
+ def m8(x) return x; end
55
+ self.class.class_eval {
56
+ alias_method :m9, :m8
57
+ rdl_alias :m9, :m8
58
+ alias_method :m10, :m9
59
+ rdl_alias :m10, :m9
60
+ pre(:m8) { |x| x > 0 }
61
+ }
62
+ assert_equal 3, m10(3)
63
+ assert_raises(RDL::Contract::ContractError) { m10(-1) }
64
+ end
65
+
66
+ end
@@ -0,0 +1,70 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../lib/rdl.rb'
3
+
4
+ class TestContract < Minitest::Test
5
+ include RDL::Contract
6
+
7
+ def test_flat
8
+ pos = FlatContract.new("Positive") { |x| x > 0 }
9
+ assert_equal "Positive", pos.to_s
10
+ assert_raises(ContractError) { pos.check self, 0 }
11
+ assert (pos.check self, 1)
12
+ gt = FlatContract.new("Greater Than") { |x, y| x > y }
13
+ assert (gt.check self, 4, 3)
14
+ assert_raises(ContractError) { gt.check self, 3, 4 }
15
+ end
16
+
17
+ def test_and
18
+ pos = FlatContract.new("Positive") { |x| x > 0 }
19
+ five = FlatContract.new("Five") { |x| x == 5 }
20
+ gt = FlatContract.new("Greater Than 3") { |x| x > 3 }
21
+ posfive = AndContract.new(pos, five)
22
+ assert_equal "Positive && Five", posfive.to_s
23
+ posfivegt = AndContract.new(pos, five, gt)
24
+ assert (posfive.check self, 5)
25
+ assert_raises(ContractError) { posfive.check self, 4 }
26
+ assert (posfivegt.check self, 5)
27
+ assert_raises(ContractError) { posfivegt.check self, 4 }
28
+ end
29
+
30
+ def test_or
31
+ pos = FlatContract.new("Positive") { |x| x > 0 }
32
+ zero = FlatContract.new("Zero") { |x| x == 0 }
33
+ neg = FlatContract.new("Neg") { |x| x < 0 }
34
+ poszero = OrContract.new(pos, zero)
35
+ assert_equal "Positive && Zero", poszero.to_s
36
+ poszeroneg = OrContract.new(pos, zero, neg)
37
+ assert (poszero.check self, 1)
38
+ assert (poszero.check self, 0)
39
+ assert_raises(ContractError) { poszero.check self, (-1) }
40
+ assert (poszeroneg.check self, (-1))
41
+ end
42
+
43
+ def test_proc
44
+ pos = FlatContract.new("Positive") { |x| x > 0 }
45
+ neg = FlatContract.new("Negative") { |ret, x| ret < 0 }
46
+ pc = ProcContract.new(pre_cond: pos, post_cond: neg)
47
+ proc1 = pc.wrap(self) { |x| -x }
48
+ assert (proc1.call(42))
49
+ assert_raises(ContractError) { proc1.call(-42) }
50
+ proc2 = pc.wrap(self) { |x| x }
51
+ assert_raises(ContractError) { proc2.call(42) }
52
+ end
53
+
54
+ def test_proc_with_block
55
+ skip "Not working yet."
56
+ pos = FlatContract.new("Positive") { |x| x > 0 }
57
+ pc = ProcContract.new(pre_cond: pos)
58
+ proc = pc.wrap(self) { |x, &blk| blk.call(x) }
59
+ assert_equal 42, (proc.call(42) { |y| y })
60
+ end
61
+
62
+ def test_turn_off
63
+ foo = FlatContract.new("Foo") {
64
+ pos = FlatContract.new("Positive") { |x| x > 0 }
65
+ pos.check self, -42
66
+ true
67
+ }
68
+ assert_equal true, foo.check(self)
69
+ end
70
+ end