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.
- checksums.yaml +4 -4
- data/.gitignore +44 -0
- data/.travis.yml +19 -0
- data/LICENSE +29 -0
- data/README.md +509 -0
- data/Rakefile +27 -0
- data/gemfiles/Gemfile.travis +5 -0
- data/lib/rdl/wrap.rb +1 -1
- data/lib/rdl_types.rb +4 -2
- data/rdl.gemspec +23 -0
- data/test/disabled_test_coverage.rb +156 -0
- data/test/disabled_test_rdoc.rb +116 -0
- data/test/test_alias.rb +66 -0
- data/test/test_contract.rb +70 -0
- data/test/test_dsl.rb +85 -0
- data/test/test_generic.rb +188 -0
- data/test/test_intersection.rb +41 -0
- data/test/test_le.rb +193 -0
- data/test/test_lib_types.rb +194 -0
- data/test/test_member.rb +148 -0
- data/test/test_parser.rb +196 -0
- data/test/test_rdl.rb +301 -0
- data/test/test_rdl_type.rb +70 -0
- data/test/test_type_contract.rb +187 -0
- data/test/test_types.rb +221 -0
- data/test/test_wrap.rb +46 -0
- data/types/{ruby-2.2.0 → ruby-2.x}/_aliases.rb +0 -0
- data/types/{ruby-2.2.0 → ruby-2.x}/abbrev.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/array.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/base64.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/basic_object.rb +2 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/benchmark.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/bigdecimal.rb +4 -4
- data/types/{ruby-2.2.0 → ruby-2.x}/bigmath.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/class.rb +3 -3
- data/types/{ruby-2.2.0 → ruby-2.x}/complex.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/coverage.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/csv.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/date.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/dir.rb +3 -3
- data/types/{ruby-2.2.0 → ruby-2.x}/encoding.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/enumerable.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/enumerator.rb +1 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/exception.rb +2 -0
- data/types/{ruby-2.2.0 → ruby-2.x}/file.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/fileutils.rb +1 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/fixnum.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/float.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/gem.rb +3 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/hash.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/integer.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/io.rb +1 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/kernel.rb +1 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/marshal.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/matchdata.rb +3 -3
- data/types/{ruby-2.2.0 → ruby-2.x}/math.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/numeric.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/object.rb +1 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/pathname.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/process.rb +8 -8
- data/types/{ruby-2.2.0 → ruby-2.x}/random.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/range.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/rational.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/regexp.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/set.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/string.rb +1 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/strscan.rb +3 -3
- data/types/{ruby-2.2.0 → ruby-2.x}/symbol.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/time.rb +2 -2
- data/types/ruby-2.x/uri.rb +20 -0
- data/types/{ruby-2.2.0 → ruby-2.x}/yaml.rb +3 -3
- metadata +70 -51
- data/lib/rdl/types/wild.rb +0 -26
- data/types/other/chronic.rb +0 -5
- data/types/other/paperclip_attachment.rb +0 -7
- data/types/other/securerandom.rb +0 -4
- data/types/ruby-2.2.0/uri.rb +0 -18
data/Rakefile
ADDED
@@ -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
|
data/lib/rdl/wrap.rb
CHANGED
data/lib/rdl_types.rb
CHANGED
@@ -1,2 +1,4 @@
|
|
1
|
-
|
2
|
-
|
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"
|
data/rdl.gemspec
ADDED
@@ -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
|
data/test/test_alias.rb
ADDED
@@ -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
|