unification_assertion 0.0.1
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 +7 -0
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +133 -0
- data/Rakefile +8 -0
- data/lib/unification_assertion.rb +170 -0
- data/lib/unification_assertion/version.rb +3 -0
- data/test/unification_assertion_test.rb +127 -0
- data/unification_assertion.gemspec +25 -0
- metadata +68 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: abb844553faec0df87b8ea925f00f879c5a3edbf
|
4
|
+
data.tar.gz: 978765d0faff2c84ad1396f793a6cf301227104a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c7d1f786d3f0e877266551e1adf80fe6ad2f9311d2d05c621635a9f150b37306afb7afd23721442099d213ad9dc13213edaba82ebf07fce7b50ff6b8e1fecf69
|
7
|
+
data.tar.gz: f28f1453b2ac77bda020c183c4f082c285eda0c0a1b1e555c3cd54c24aa5bd47de2b49f90f593c0c40cd0060f48be286072eff55b70557cf91348c9bba32939b
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# UnificationAssertion
|
2
|
+
|
3
|
+
UnificationAssertion provides powerful and simple way to compare two
|
4
|
+
structures which may be different partialy. The comparison is based on
|
5
|
+
unification algorithm, which is used in Prolog implementations and
|
6
|
+
type inference algorithms.
|
7
|
+
|
8
|
+
The assertion will be like the following:
|
9
|
+
|
10
|
+
assert_unifiable({ "timestamp" => :_,
|
11
|
+
"person" => {
|
12
|
+
"id" => :_,
|
13
|
+
"name" => "John",
|
14
|
+
"email" => "john@example.com",
|
15
|
+
"created_at" => :_a,
|
16
|
+
"updated_at" => :_a
|
17
|
+
}
|
18
|
+
}, JSON.parse(@response.body))
|
19
|
+
|
20
|
+
It compares two hash objects, but it does not care the exact value of
|
21
|
+
`"timestamp"`, `"id"`, `"created_at"`, and `"updated_at"`. The meta
|
22
|
+
variable `:_a` is not a black hole but test the equality between
|
23
|
+
`"created_at"` and `"updated_at"`.
|
24
|
+
|
25
|
+
## Introduction
|
26
|
+
|
27
|
+
I have been writing some tests like the following Rails functional
|
28
|
+
tests.
|
29
|
+
|
30
|
+
# Testing a web api which create a person data and send the created person object as JSON
|
31
|
+
post(:create_person, { :person => { :name => "John", :email => "john@example.com" } })
|
32
|
+
|
33
|
+
# Compare expected hash and actual result parsed by JSON parser
|
34
|
+
assert_equal({ "timestamp" => Time.now,
|
35
|
+
"person" => {
|
36
|
+
"id" => 13,
|
37
|
+
"name" => "John",
|
38
|
+
"email" => "john@example.com",
|
39
|
+
"created_at" => Time.now,
|
40
|
+
"updated_at" => Time.now
|
41
|
+
}
|
42
|
+
}, JSON.parse(@response.body))
|
43
|
+
|
44
|
+
You may point out some problems on the test.
|
45
|
+
|
46
|
+
* The ID of the result may be different from 13
|
47
|
+
* It is not sure to assume `result["timestamp"]` is equal to `Time.now`
|
48
|
+
* It is not sure to assume `result["person"]["created_at"]` is equal to `Time.now`
|
49
|
+
|
50
|
+
The root of the problems is that the comparison is too strict. The
|
51
|
+
properties I would like to test is only its `name` and `email`
|
52
|
+
fields. So I should test like the following:
|
53
|
+
|
54
|
+
assert_equal "John", result["person"]["name"]
|
55
|
+
assert_equal "john@example.com", result["person"]["email"]
|
56
|
+
|
57
|
+
It looks too complicated, and we need some way to compare structures.
|
58
|
+
This library, UnificationAssertion, provides the primitive for the
|
59
|
+
comparison called `assert_unifiable`.
|
60
|
+
|
61
|
+
assert_unifiable({ "timestamp" => :_,
|
62
|
+
"person" => {
|
63
|
+
"id" => :_,
|
64
|
+
"name" => "John",
|
65
|
+
"email" => "john@example.com",
|
66
|
+
"created_at" => :_a,
|
67
|
+
"updated_at" => :_a
|
68
|
+
}
|
69
|
+
}, JSON.parse(@response.body))
|
70
|
+
|
71
|
+
Symbols `:_a` for example, where its name starts with `_` is
|
72
|
+
interpreted as a meta variable. `assert_unifiable` does not care their
|
73
|
+
exact value is, but only the existence (can be `nil`) and equalities
|
74
|
+
for each occurance will be tested. The special symbol `:_` is a
|
75
|
+
wildcard. It can appear many times, but it will not be bound with any
|
76
|
+
value.
|
77
|
+
|
78
|
+
## Examples
|
79
|
+
|
80
|
+
assert_unifiable(:_a, 1) # pass, :_a will be 1
|
81
|
+
assert_unifiable([:_a, 1], [1, 1]) # pass, :_a will be 1
|
82
|
+
assert_unifiable([:_, :_], [1, 2]) # pass, :_ can not be bound with any value
|
83
|
+
assert_unifiable([:_a, :_a], [1, 2]) # fail, :_a can not be either 1 and 2
|
84
|
+
assert_unifiable([:_a], [1,2,3]) # fail, :_a can be a value but can not be a sequence
|
85
|
+
|
86
|
+
assert_unifiable({ :x => :_a }, { :x => 1 }) # pass, :_a will be 1
|
87
|
+
assert_unifiable({ :y => :_a }, { }) # fail, a key :y should be present
|
88
|
+
assert_unifiable({ :y => :_a }, { :y => nil }) # pass, :_a will be nil
|
89
|
+
assert_unifiable({ :_a => 1 }, { :x => 1 }) # fail, meta variable can not appear as a key
|
90
|
+
|
91
|
+
# assert_unifiable can receive a block, which will be yielded with the result of unification.
|
92
|
+
assert_unifiable([:_a, :_b], [1, 2]) do |unifier|
|
93
|
+
assert unifier[:_a] < unifier[:_b]
|
94
|
+
end
|
95
|
+
|
96
|
+
## Installation
|
97
|
+
|
98
|
+
Update your `Gemfile`.
|
99
|
+
|
100
|
+
gem "unification_assertion", :git => "git://github.com/soutaro/unification_assertion.git"
|
101
|
+
|
102
|
+
Write your test case.
|
103
|
+
|
104
|
+
require "minitest/autorun"
|
105
|
+
require "unification_assertion"
|
106
|
+
|
107
|
+
class GreatTest < MiniTest::Unit::TestCase
|
108
|
+
include UnificationAssertion
|
109
|
+
|
110
|
+
def test_something
|
111
|
+
assert_unifiable([:_a, :_b], [1, 2])
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
## Known Issues
|
116
|
+
|
117
|
+
### It skips occur check
|
118
|
+
|
119
|
+
The recursive pattern can not be processed well.
|
120
|
+
|
121
|
+
assert_unifiable(:_a, { :x => :_a })
|
122
|
+
|
123
|
+
Usual unification algorithm rejects such input by *occur check*. This
|
124
|
+
library is expected to be used for testing, so that I omit the
|
125
|
+
checking. (Who in the world will write such comparison?)
|
126
|
+
|
127
|
+
## Author
|
128
|
+
|
129
|
+
Written by Soutaro Matsumoto. (matsumoto at soutaro dot com)
|
130
|
+
|
131
|
+
Released under the MIT License: www.opensource.org/licenses/mit-license.php
|
132
|
+
|
133
|
+
github.com/soutaro/unification_assertion
|
data/Rakefile
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
require "unification_assertion/version"
|
2
|
+
|
3
|
+
require "minitest/unit"
|
4
|
+
|
5
|
+
module UnificationAssertion
|
6
|
+
include MiniTest::Assertions
|
7
|
+
|
8
|
+
module_function
|
9
|
+
|
10
|
+
@@comparators = {}
|
11
|
+
|
12
|
+
@@comparators[Array] = lambda {|a, b, eqs, unifier, path, block|
|
13
|
+
block.call(a.length, b.length, path + ".length")
|
14
|
+
a.zip(b).each.with_index do |pair, index|
|
15
|
+
pair << path + "[#{index}]"
|
16
|
+
eqs << pair
|
17
|
+
end
|
18
|
+
eqs
|
19
|
+
}
|
20
|
+
|
21
|
+
@@comparators[Hash] = lambda {|a, b, eqs, unifier, path, block|
|
22
|
+
block.call(a.keys.sort, b.keys.sort, path + ".keys.sort")
|
23
|
+
eqs.concat(a.keys.map {|key| [a[key], b[key], path+"[#{key.inspect}]"] })
|
24
|
+
}
|
25
|
+
|
26
|
+
# Comparators are hash from a class to its comparator.
|
27
|
+
# It is used to check unifiability of two object of the given hash.
|
28
|
+
#
|
29
|
+
# There are two comparators defined by default; for |Array| and |Hash|.
|
30
|
+
#
|
31
|
+
# == Example ==
|
32
|
+
# UnificationAssertion.comparators[Array] = lambda do |a, b, message, eqs, unifier, &block|
|
33
|
+
# block.call(a.length, bl.ength, message + " (Array length mismatch)")
|
34
|
+
# eqs.concat(a.zip(b))
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# This is our comparator for |Array|. It first tests if the length of the two arrays are equal.
|
38
|
+
# And then, it pushes the equations of each components of the arrays.
|
39
|
+
# The components of the arrays will be tested unifiability later.
|
40
|
+
#
|
41
|
+
# == Comparator ==
|
42
|
+
#
|
43
|
+
# Comparator is a lambda which takes 5 arguments and block and checks the unifiability
|
44
|
+
# of the first two arguments.
|
45
|
+
#
|
46
|
+
# * |a|, |b| Objects they are compared.
|
47
|
+
# * |message| Message given to |unify|.
|
48
|
+
# * |eqs| Equations array. This is for output.
|
49
|
+
# * |unifier| Current unifier. This is just for reference.
|
50
|
+
# * |&block| Block given to |unify|, which can be used to check the equality of two values.
|
51
|
+
#
|
52
|
+
def comparators
|
53
|
+
@@comparators
|
54
|
+
end
|
55
|
+
|
56
|
+
# Run unification algorithm for given equations.
|
57
|
+
# If all equations in |eqs| are unifiable, |unify| returns (the most-general) unifier.
|
58
|
+
#
|
59
|
+
# Which identifies an symbol as a meta variable if the name matches with |options[:meta_pattern]|.
|
60
|
+
# The default of the meta variable pattern is |/^_/|.
|
61
|
+
# For example, |:_a| and |:_xyz| are meta variable, but |:a| and |:hello_world| are not.
|
62
|
+
#
|
63
|
+
# It also accepts wildcard variable. Which matches with any value, but does not introduce new equational constraints.
|
64
|
+
# The default wildcard is |:_|.
|
65
|
+
#
|
66
|
+
# |unify| takes a block to test equation of two values.
|
67
|
+
# The simplest form should be using |assert_equal|, however it can be customized as you like.
|
68
|
+
#
|
69
|
+
# == Example ==
|
70
|
+
# unify([[:_a, 1], [{ :x => :_b, :y => 1 }, { :x => 3, :y => 1 }]], "Example!!") do |x, y, message|
|
71
|
+
# assert_equal(x,y,message)
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# The |unify| call will return an hash |{ :_a => 1, :_b => 3 }|.
|
75
|
+
# The block will be used to test equality between 1 and 1 (it will pass.)
|
76
|
+
#
|
77
|
+
def unify(eqs, unifier = {}, options = {}, &block)
|
78
|
+
options = { :meta_pattern => /^_/, :wildcard => :_ }.merge!(options)
|
79
|
+
|
80
|
+
pattern = options[:meta_pattern]
|
81
|
+
wildcard = options[:wildcard]
|
82
|
+
|
83
|
+
while eq = eqs.shift
|
84
|
+
a,b,path = eq
|
85
|
+
case
|
86
|
+
when (Symbol === a and a.to_s =~ pattern)
|
87
|
+
unless a == wildcard
|
88
|
+
eqs = substitute({ a => b }, eqs)
|
89
|
+
unifier = substitute({ a => b }, unifier).merge!(a => b)
|
90
|
+
end
|
91
|
+
when (Symbol === b and b.to_s =~ pattern)
|
92
|
+
unless b == wildcard
|
93
|
+
eqs = substitute({ b => a }, eqs)
|
94
|
+
unifier = substitute({ b => a }, unifier).merge!(b => a)
|
95
|
+
end
|
96
|
+
when (a.class == b.class and @@comparators[a.class])
|
97
|
+
@@comparators[a.class].call(a, b, eqs, unifier, path, block)
|
98
|
+
else
|
99
|
+
yield(a, b, path)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
unifier.inject({}) {|acc, (key, value)|
|
104
|
+
if key == value
|
105
|
+
acc
|
106
|
+
else
|
107
|
+
acc.merge!(key => value)
|
108
|
+
end
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
@@substituters = {}
|
113
|
+
@@substituters[Hash] = lambda {|unifier, hash|
|
114
|
+
hash.inject({}) {|acc, (key, val)|
|
115
|
+
if unifier[val]
|
116
|
+
acc.merge!(key => unifier[val])
|
117
|
+
else
|
118
|
+
acc.merge!(key => substitute(unifier, val))
|
119
|
+
end
|
120
|
+
}
|
121
|
+
}
|
122
|
+
@@substituters[Symbol] = lambda {|unifier, symbol| unifier[symbol] or symbol }
|
123
|
+
@@substituters[Array] = lambda {|unifier, array|
|
124
|
+
array.map {|x| substitute(unifier, x) }
|
125
|
+
}
|
126
|
+
|
127
|
+
def substitutions
|
128
|
+
@@substituters
|
129
|
+
end
|
130
|
+
|
131
|
+
def substitute(unifier, a)
|
132
|
+
subst = @@substituters[a.class]
|
133
|
+
if subst
|
134
|
+
subst.call(unifier, a)
|
135
|
+
else
|
136
|
+
a
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Run unification between |a| and |b|, and fails if they are not unifiable.
|
141
|
+
# |assert_unifiable| can have block, which yields the unifier for |a| and |b| if exists.
|
142
|
+
#
|
143
|
+
def assert_unifiable(a, b, original_message = "", options = {}, &block)
|
144
|
+
msg = proc {|eq, path|
|
145
|
+
header = if original_message == nil or original_message.length == 0
|
146
|
+
original_message
|
147
|
+
else
|
148
|
+
"No unification"
|
149
|
+
end
|
150
|
+
|
151
|
+
footer = "\nCould not find a solution of equation at it#{path}.\n=> #{mu_pp(eq[0])} == #{mu_pp(eq[1])}"
|
152
|
+
|
153
|
+
message(header, footer) {
|
154
|
+
a_pp = mu_pp(a)
|
155
|
+
b_pp = mu_pp(b)
|
156
|
+
|
157
|
+
"=> #{a_pp}\n=> #{b_pp}"
|
158
|
+
}
|
159
|
+
}
|
160
|
+
|
161
|
+
unifier = unify([[a, b, ""]], {}, options) do |x, y, path|
|
162
|
+
assert(x==y, msg.call([x, y], path))
|
163
|
+
end
|
164
|
+
|
165
|
+
if block
|
166
|
+
yield(unifier)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require "unification_assertion"
|
3
|
+
|
4
|
+
class UnificationAssertionTest < Minitest::Test
|
5
|
+
include UnificationAssertion
|
6
|
+
|
7
|
+
def call_unify(a, b)
|
8
|
+
begin
|
9
|
+
unifier = unify([[a,b,""]]) do |a, b|
|
10
|
+
unless a == b
|
11
|
+
raise "Failure"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
return unifier
|
15
|
+
rescue
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_substitution
|
21
|
+
subst = { :a => 1 }
|
22
|
+
|
23
|
+
assert_equal 1, substitute(subst, :a)
|
24
|
+
assert_equal :b, substitute(subst, :b)
|
25
|
+
|
26
|
+
assert_equal "a", substitute(subst, "a")
|
27
|
+
|
28
|
+
assert_equal [], substitute(subst, [])
|
29
|
+
assert_equal [1], substitute(subst, [:a])
|
30
|
+
assert_equal [:b], substitute(subst, [:b])
|
31
|
+
|
32
|
+
assert_equal [[1]], substitute(subst, [[:a]])
|
33
|
+
assert_equal [[:b]], substitute(subst, [[:b]])
|
34
|
+
|
35
|
+
assert_equal({}, substitute(subst, {}))
|
36
|
+
assert_equal({ x: 1 }, substitute(subst, { x: :a }))
|
37
|
+
assert_equal({ x: :b}, substitute(subst, { x: :b }))
|
38
|
+
|
39
|
+
assert_equal({ x: { y: 1 } }, substitute(subst, { x: { y: :a } }))
|
40
|
+
assert_equal({ x: { y: :b } }, substitute(subst, { x: { y: :b } }))
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_unify
|
44
|
+
assert_nil call_unify(:a, :b)
|
45
|
+
|
46
|
+
assert_equal({}, call_unify(:a, :a))
|
47
|
+
|
48
|
+
assert_equal({ :_a => 1 }, call_unify(:_a, 1))
|
49
|
+
assert_equal({ :_b => :a }, call_unify(:a, :_b))
|
50
|
+
|
51
|
+
assert_equal({ :_a => [1,:_b,3] }, call_unify([1,:_b,3], :_a))
|
52
|
+
assert_equal({}, call_unify([1,2,3], [1,2,3]))
|
53
|
+
assert_nil call_unify([1,2,3], [1,3])
|
54
|
+
assert_equal({ :_b => 2 }, call_unify([1,2,3], [1,:_b, 3]))
|
55
|
+
assert_nil call_unify([1,2,3], [:_a, 2, :_a])
|
56
|
+
|
57
|
+
assert_equal({}, call_unify({ a:1, b:2 }, { b:2, a:1 }))
|
58
|
+
assert_equal({ :_a => 2 }, call_unify({ a:1, b: :_a }, { b:2, a:1 }))
|
59
|
+
assert_equal({ :_b => :_a }, call_unify({ a: :_b, b: :_a }, { b: :_b, a: :_a }))
|
60
|
+
assert_equal({ :_a => 1 }, call_unify([1, { :x => :_a }], [:_a, { :x => 1 }]))
|
61
|
+
assert_nil call_unify([1, { :x => :_a }], [:_a, { :x => 2 }])
|
62
|
+
assert_equal({ :_a => 1, :_b => 1}, call_unify([1, :_b], [:_a, :_a]))
|
63
|
+
|
64
|
+
assert_equal({}, call_unify([:_, :_], [1,2]))
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_assertion
|
68
|
+
assert_unifiable(:_a, [1,2,3])
|
69
|
+
|
70
|
+
assert_unifiable(:_a, 1) do |unifier|
|
71
|
+
assert_equal 1, unifier[:_a]
|
72
|
+
end
|
73
|
+
|
74
|
+
# :_ is wildcard
|
75
|
+
assert_unifiable([:_, :_, :_], [1,2,3])
|
76
|
+
|
77
|
+
assert_unifiable({ :created_at => :_a,
|
78
|
+
:updated_at => :_b },
|
79
|
+
{ :created_at => Time.now,
|
80
|
+
:updated_at => Time.now + 1 }) do |unifier|
|
81
|
+
assert unifier[:_a] <= unifier[:_b]
|
82
|
+
end
|
83
|
+
|
84
|
+
# Meta variable pattern can be changed (ML type variable style)
|
85
|
+
assert_unifiable([:"'a", :"'b", :"'_"],
|
86
|
+
[1, 2, 3],
|
87
|
+
"Test message",
|
88
|
+
:meta_pattern => /^'/,
|
89
|
+
:wildcard => :"'_")
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_assertion_failure
|
93
|
+
# 1 and 3 is incompatible
|
94
|
+
assert_raises(MiniTest::Assertion) do
|
95
|
+
assert_unifiable([:_a, :_a], [1, 3])
|
96
|
+
end
|
97
|
+
|
98
|
+
# Time.now and Time.now+1 is incompatible
|
99
|
+
assert_raises(MiniTest::Assertion) do
|
100
|
+
assert_unifiable({ :created_at => :_a,
|
101
|
+
:updated_at => :_a },
|
102
|
+
{ :created_at => Time.now,
|
103
|
+
:updated_at => Time.now + 1 })
|
104
|
+
end
|
105
|
+
|
106
|
+
# There is no ``row'' variable
|
107
|
+
assert_raises(MiniTest::Assertion) do
|
108
|
+
assert_unifiable([:_a, :_b], [1,2,3])
|
109
|
+
end
|
110
|
+
|
111
|
+
# There is no ``row'' variable
|
112
|
+
assert_raises(MiniTest::Assertion) do
|
113
|
+
assert_unifiable({ :_a => 3 }, { :x => :_b })
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_occur_check_skipped
|
118
|
+
# This should be nil because of (absent) occur check will fail.
|
119
|
+
# :_a \in FV( { :x => :_a } ) => cyclic!!
|
120
|
+
#
|
121
|
+
# However, I have not implement it.
|
122
|
+
# This unification implementation is only for testing.
|
123
|
+
# Who on the earth write this kind of test? (meaningless and it will result different from what the programmer expects)
|
124
|
+
#
|
125
|
+
assert_equal({ :_a => { :x => :_a }}, call_unify(:_a, { :x => :_a }))
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "unification_assertion/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "unification_assertion"
|
7
|
+
s.version = UnificationAssertion::VERSION
|
8
|
+
s.authors = ["Soutaro Matsumoto"]
|
9
|
+
s.email = ["matsumoto@soutaro.com"]
|
10
|
+
s.homepage = "https://github.com/soutaro/unification_assertion"
|
11
|
+
s.summary = "Assertion to test unifiability of two structures"
|
12
|
+
s.description = "UnificationAssertion defines +assert_unifiable+ assertion to test if given two values are unifiable."
|
13
|
+
s.licenses = ["MIT"]
|
14
|
+
|
15
|
+
s.rubyforge_project = "unification_assertion"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
# specify any dependencies here; for example:
|
23
|
+
# s.add_development_dependency "rspec"
|
24
|
+
s.add_runtime_dependency "minitest", '~> 5'
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: unification_assertion
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Soutaro Matsumoto
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5'
|
27
|
+
description: UnificationAssertion defines +assert_unifiable+ assertion to test if
|
28
|
+
given two values are unifiable.
|
29
|
+
email:
|
30
|
+
- matsumoto@soutaro.com
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- ".gitignore"
|
36
|
+
- Gemfile
|
37
|
+
- README.md
|
38
|
+
- Rakefile
|
39
|
+
- lib/unification_assertion.rb
|
40
|
+
- lib/unification_assertion/version.rb
|
41
|
+
- test/unification_assertion_test.rb
|
42
|
+
- unification_assertion.gemspec
|
43
|
+
homepage: https://github.com/soutaro/unification_assertion
|
44
|
+
licenses:
|
45
|
+
- MIT
|
46
|
+
metadata: {}
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project: unification_assertion
|
63
|
+
rubygems_version: 2.2.0
|
64
|
+
signing_key:
|
65
|
+
specification_version: 4
|
66
|
+
summary: Assertion to test unifiability of two structures
|
67
|
+
test_files:
|
68
|
+
- test/unification_assertion_test.rb
|