wrong 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +114 -25
- data/lib/predicated/Gemfile +15 -0
- data/lib/predicated/LICENSE +20 -0
- data/lib/predicated/README.markdown +191 -0
- data/lib/predicated/Rakefile +51 -0
- data/lib/predicated/lib/predicated.rb +4 -0
- data/lib/predicated/lib/predicated/autogen_call.rb +37 -0
- data/lib/predicated/lib/predicated/constrain.rb +66 -0
- data/lib/predicated/lib/predicated/evaluate.rb +94 -0
- data/lib/predicated/lib/predicated/from/callable_object.rb +108 -0
- data/lib/predicated/lib/predicated/from/json.rb +59 -0
- data/lib/predicated/lib/predicated/from/ruby_code_string.rb +73 -0
- data/lib/predicated/lib/predicated/from/url_part.rb +104 -0
- data/lib/predicated/lib/predicated/from/xml.rb +61 -0
- data/lib/predicated/lib/predicated/gem_check.rb +34 -0
- data/lib/predicated/lib/predicated/predicate.rb +111 -0
- data/lib/predicated/lib/predicated/print.rb +62 -0
- data/lib/predicated/lib/predicated/selectable.rb +102 -0
- data/lib/predicated/lib/predicated/simple_templated_predicate.rb +79 -0
- data/lib/predicated/lib/predicated/string_utils.rb +20 -0
- data/lib/predicated/lib/predicated/to/arel.rb +41 -0
- data/lib/predicated/lib/predicated/to/json.rb +48 -0
- data/lib/predicated/lib/predicated/to/sentence.rb +94 -0
- data/lib/predicated/lib/predicated/to/solr.rb +15 -0
- data/lib/predicated/lib/predicated/to/xml.rb +67 -0
- data/lib/predicated/lib/predicated/version.rb +3 -0
- data/lib/predicated/predicated.gemspec +22 -0
- data/lib/predicated/test/autogen_call_test.rb +40 -0
- data/lib/predicated/test/canonical_transform_cases.rb +63 -0
- data/lib/predicated/test/constrain_test.rb +86 -0
- data/lib/predicated/test/enumerable_test.rb +32 -0
- data/lib/predicated/test/equality_test.rb +32 -0
- data/lib/predicated/test/evaluate_test.rb +149 -0
- data/lib/predicated/test/from/callable_object_canonical_test.rb +43 -0
- data/lib/predicated/test/from/callable_object_test.rb +78 -0
- data/lib/predicated/test/from/json_test.rb +83 -0
- data/lib/predicated/test/from/ruby_code_string_canonical_test.rb +37 -0
- data/lib/predicated/test/from/ruby_code_string_test.rb +103 -0
- data/lib/predicated/test/from/url_part_parser_test.rb +123 -0
- data/lib/predicated/test/from/url_part_test.rb +48 -0
- data/lib/predicated/test/from/xml_test.rb +57 -0
- data/lib/predicated/test/json_conversion_test.rb +33 -0
- data/lib/predicated/test/print_test.rb +66 -0
- data/lib/predicated/test/selectable_test.rb +123 -0
- data/lib/predicated/test/simple_templated_predicate_test.rb +39 -0
- data/lib/predicated/test/suite.rb +2 -0
- data/lib/predicated/test/test_helper.rb +64 -0
- data/lib/predicated/test/test_helper_with_wrong.rb +6 -0
- data/lib/predicated/test/to/arel_test.rb +85 -0
- data/lib/predicated/test/to/json_test.rb +74 -0
- data/lib/predicated/test/to/sentence_test.rb +90 -0
- data/lib/predicated/test/to/solr_test.rb +39 -0
- data/lib/predicated/test/to/xml_test.rb +72 -0
- data/lib/predicated/test/xml_conversion_test.rb +34 -0
- data/lib/predicated/test_integration/arel_integration_test.rb +52 -0
- data/lib/predicated/test_integration/canonical_integration_cases.rb +66 -0
- data/lib/predicated/test_integration/schema.xml +83 -0
- data/lib/predicated/test_integration/solr_integration_test.rb +71 -0
- data/lib/predicated/test_integration/sqlite_db +0 -0
- data/lib/predicated/test_integration/suite.rb +2 -0
- data/lib/predicated/test_integration/usage_test.rb +252 -0
- data/lib/wrong.rb +3 -1
- data/lib/wrong/adapters/test_unit.rb +1 -3
- data/lib/wrong/assert.rb +81 -24
- data/lib/wrong/chunk.rb +145 -0
- data/lib/wrong/message/string_diff.rb +2 -4
- data/lib/wrong/message/test_context.rb +2 -2
- data/lib/wrong/version.rb +2 -2
- data/test/adapters/minitest_test.rb +16 -9
- data/test/adapters/test_unit_test.rb +1 -1
- data/test/assert_test.rb +90 -0
- data/test/catch_raise_test.rb +2 -2
- data/test/chunk_test.rb +236 -0
- data/test/failures_test.rb +109 -74
- data/test/message/array_diff_test.rb +35 -19
- data/test/message/string_diff_test.rb +39 -15
- data/test/message/test_context_text.rb +2 -2
- data/test/test_helper.rb +25 -7
- metadata +86 -33
- data/test/basic_assert_test.rb +0 -38
@@ -0,0 +1,39 @@
|
|
1
|
+
require "./test/test_helper_with_wrong"
|
2
|
+
require "./test/canonical_transform_cases"
|
3
|
+
|
4
|
+
require "predicated/to/solr"
|
5
|
+
include Predicated
|
6
|
+
|
7
|
+
regarding "convert a predicate to a solr query" do
|
8
|
+
include CanonicalTransformCases
|
9
|
+
|
10
|
+
@to_expectations = {
|
11
|
+
"simple operations" => {
|
12
|
+
"eq" => "a:3",
|
13
|
+
"gt" => "a:[4 TO *]",
|
14
|
+
"lt" => "a:[* TO 2]",
|
15
|
+
"gte" => "a:[3 TO *]",
|
16
|
+
"lte" => "a:[* TO 3]"
|
17
|
+
},
|
18
|
+
"primitive types" => {
|
19
|
+
"false" => "a:false",
|
20
|
+
"true" => "a:true",
|
21
|
+
"string" => "a:yyy"
|
22
|
+
},
|
23
|
+
"not" => {
|
24
|
+
"simple" => "NOT(a:true)"
|
25
|
+
},
|
26
|
+
"simple and / or" => {
|
27
|
+
"and" => "(a:1 AND b:2)", #parens are necessary around AND's in solr in order to force precedence
|
28
|
+
"or" => "(a:1 OR b:2)",
|
29
|
+
},
|
30
|
+
"complex and / or" => {
|
31
|
+
"or and" => "((a:1 AND b:2) OR c:3)"
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
create_canonical_tests(@to_expectations) do |predicate|
|
36
|
+
predicate.to_solr
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require "./test/test_helper_with_wrong"
|
2
|
+
require "./test/canonical_transform_cases"
|
3
|
+
|
4
|
+
require "predicated/to/xml"
|
5
|
+
include Predicated
|
6
|
+
|
7
|
+
regarding "convert a predicate to an xml string" do
|
8
|
+
include CanonicalTransformCases
|
9
|
+
|
10
|
+
@to_expectations = {
|
11
|
+
"simple operations" => {
|
12
|
+
"eq" => "<equal><left>a</left><right>3</right></equal>",
|
13
|
+
"gt" => "<greaterThan><left>a</left><right>3</right></greaterThan>",
|
14
|
+
"lt" => "<lessThan><left>a</left><right>3</right></lessThan>",
|
15
|
+
"gte" => "<greaterThanOrEqualTo><left>a</left><right>3</right></greaterThanOrEqualTo>",
|
16
|
+
"lte" => "<lessThanOrEqualTo><left>a</left><right>3</right></lessThanOrEqualTo>"
|
17
|
+
},
|
18
|
+
"primitive types" => {
|
19
|
+
"false" => "<equal><left>a</left><right>false</right></equal>",
|
20
|
+
"true" => "<equal><left>a</left><right>true</right></equal>",
|
21
|
+
"string" => "<equal><left>a</left><right>yyy</right></equal>"
|
22
|
+
},
|
23
|
+
"not" => {
|
24
|
+
"simple" => "<not><equal><left>a</left><right>true</right></equal></not>"
|
25
|
+
},
|
26
|
+
"simple and / or" => {
|
27
|
+
"and" => %{<and>
|
28
|
+
<equal><left>a</left><right>1</right></equal>
|
29
|
+
<equal><left>b</left><right>2</right></equal>
|
30
|
+
</and>}.gsub("\n", "").gsub(" ", ""),
|
31
|
+
"or" => %{<or>
|
32
|
+
<equal><left>a</left><right>1</right></equal>
|
33
|
+
<equal><left>b</left><right>2</right></equal>
|
34
|
+
</or>}.gsub("\n", "").gsub(" ", "")
|
35
|
+
},
|
36
|
+
"complex and / or" => {
|
37
|
+
"or and" => %{<or>
|
38
|
+
<and>
|
39
|
+
<equal><left>a</left><right>1</right></equal>
|
40
|
+
<equal><left>b</left><right>2</right></equal>
|
41
|
+
</and>
|
42
|
+
<equal><left>c</left><right>3</right></equal>
|
43
|
+
</or>}.gsub("\n", "").gsub(" ", "")
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
create_canonical_tests(@to_expectations) do |predicate|
|
48
|
+
predicate.to_xml.gsub("\n", "").gsub(" ", "")
|
49
|
+
end
|
50
|
+
|
51
|
+
test "pretty printing" do
|
52
|
+
assert{
|
53
|
+
Predicate{ Or(And(Eq("a", 1),Eq("b", 2)), Not(Eq("c",3))) }.to_xml ==
|
54
|
+
%{<or>
|
55
|
+
<and>
|
56
|
+
<equal><left>a</left><right>1</right></equal>
|
57
|
+
<equal><left>b</left><right>2</right></equal>
|
58
|
+
</and>
|
59
|
+
<not>
|
60
|
+
<equal><left>c</left><right>3</right></equal>
|
61
|
+
</not>
|
62
|
+
</or>}
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
test "characters that need to be encoded" do
|
67
|
+
assert{
|
68
|
+
Predicate{ Eq(%{'"&<>}, %{'"&<>}) }.to_xml ==
|
69
|
+
%{<equal><left>'"&<></left><right>'"&<></right></equal>}
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "./test/test_helper_with_wrong"
|
2
|
+
|
3
|
+
require "predicated/from/xml"
|
4
|
+
require "predicated/to/xml"
|
5
|
+
include Predicated
|
6
|
+
|
7
|
+
regarding "convert xml back and forth" do
|
8
|
+
|
9
|
+
test "string to predicate to string" do
|
10
|
+
assert{ Predicate.from_xml("<equal><left>a</left><right>3</right></equal>").to_xml ==
|
11
|
+
"<equal><left>a</left><right>3</right></equal>" }
|
12
|
+
|
13
|
+
complex_xml = %{
|
14
|
+
<or>
|
15
|
+
<and>
|
16
|
+
<equal><left>a</left><right>1</right></equal>
|
17
|
+
<equal><left>b</left><right>2</right></equal>
|
18
|
+
</and>
|
19
|
+
<equal><left>c</left><right>3</right></equal>
|
20
|
+
</or>
|
21
|
+
}
|
22
|
+
|
23
|
+
assert{ Predicate.from_xml(complex_xml).to_xml.gsub(/\s/, "") ==
|
24
|
+
complex_xml.gsub(/\s/, "") }
|
25
|
+
end
|
26
|
+
|
27
|
+
test "predicate to string to predicate. note the loss of type fidelity." do
|
28
|
+
assert{ Predicate.from_xml(Predicate{ Eq("a",3) }.to_xml) == Predicate{ Eq("a",'3') } }
|
29
|
+
|
30
|
+
assert{ Predicate.from_xml(Predicate{ Or(And(Eq("a",1),Eq("b",2)), Eq("c",3)) }.to_xml) ==
|
31
|
+
Predicate{ Or(And(Eq("a",'1'),Eq("b",'2')), Eq("c",'3')) } }
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "./test/test_helper_with_wrong"
|
2
|
+
require "./test_integration/canonical_integration_cases"
|
3
|
+
|
4
|
+
require "predicated/predicate"
|
5
|
+
require "predicated/to/arel"
|
6
|
+
include Predicated
|
7
|
+
|
8
|
+
require "sqlite3-ruby"
|
9
|
+
require "active_record"
|
10
|
+
|
11
|
+
|
12
|
+
def get_from_db_using_predicate(predicate)
|
13
|
+
Table(:widget).where(predicate.to_arel(Table(:widget))).select.
|
14
|
+
collect{|r|r.tuple}.
|
15
|
+
collect{|d|d.first}
|
16
|
+
end
|
17
|
+
|
18
|
+
regarding "predicates run against a real db" do
|
19
|
+
include CanonicalIntegrationCases
|
20
|
+
|
21
|
+
|
22
|
+
before do
|
23
|
+
unless @created
|
24
|
+
db_file = "/tmp/sqlite_db"
|
25
|
+
FileUtils.rm_f(db_file)
|
26
|
+
@db = SQLite3::Database.new(db_file)
|
27
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3-ruby", :database => db_file)
|
28
|
+
@db.execute(%{
|
29
|
+
create table widget (
|
30
|
+
id INTEGER PRIMARY KEY,
|
31
|
+
eye_color VARCHAR(25),
|
32
|
+
height VARCHAR(25),
|
33
|
+
age VARCHAR(25),
|
34
|
+
cats NUMERIC);
|
35
|
+
})
|
36
|
+
|
37
|
+
self.fixtures.each do |row|
|
38
|
+
@db.execute("insert into widget values (#{row[:id]}, '#{row[:eye_color]}', '#{row[:height]}', '#{row[:age]}', #{row[:cats]})")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
@created = true
|
42
|
+
end
|
43
|
+
|
44
|
+
create_canonical_tests(
|
45
|
+
:id => "id",
|
46
|
+
:eye_color => "eye_color",
|
47
|
+
:height => "height",
|
48
|
+
:age => "age",
|
49
|
+
:cats => "cats") do |predicate|
|
50
|
+
get_from_db_using_predicate(predicate)
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module CanonicalIntegrationCases
|
2
|
+
|
3
|
+
def fixtures
|
4
|
+
[
|
5
|
+
{:id => 101, :eye_color => "red", :height => "short", :age => "old", :cats => 0},
|
6
|
+
{:id => 102, :eye_color => "blue", :height => "tall", :age => "old", :cats => 2},
|
7
|
+
{:id => 103, :eye_color => "green", :height => "short", :age => "young", :cats => 3}
|
8
|
+
]
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
|
14
|
+
def create_canonical_tests(attrs)
|
15
|
+
tests = {
|
16
|
+
"simple eq" => { Predicate{ Eq(attrs[:id], 101) } => [101] },
|
17
|
+
"string eq" => { Predicate{ Eq(attrs[:eye_color],"blue") } => [102] },
|
18
|
+
"simple gt" => { Predicate{ Gt(attrs[:cats], 1) } => [102, 103] },
|
19
|
+
"simple lt" => { Predicate{ Lt(attrs[:cats], 3) } => [101, 102] },
|
20
|
+
"simple gte" => { Predicate{ Gte(attrs[:cats], 2) } => [102, 103] },
|
21
|
+
"simple lte" => { Predicate{ Lte(attrs[:cats], 2) } => [101, 102] },
|
22
|
+
"simple not" => { Predicate{ Not(Eq(attrs[:eye_color],"blue")) } => [101, 103] },
|
23
|
+
"simple and / or" => {
|
24
|
+
Predicate{And(Eq(attrs[:height],"tall"),Eq(attrs[:age],"old"))} => [102],
|
25
|
+
Predicate{And(Eq(attrs[:height],"short"),Eq(attrs[:age],"old"))} => [101],
|
26
|
+
Predicate{Or(Eq(attrs[:height],"short"),Eq(attrs[:age],"young")) } => [101, 103]
|
27
|
+
},
|
28
|
+
"complex and / or" => {
|
29
|
+
|
30
|
+
Predicate{
|
31
|
+
Or(
|
32
|
+
And(
|
33
|
+
Eq(attrs[:height],"short"),
|
34
|
+
Eq(attrs[:age],"young")
|
35
|
+
),
|
36
|
+
Eq(attrs[:eye_color],"red")
|
37
|
+
)
|
38
|
+
} => [101, 103],
|
39
|
+
|
40
|
+
Predicate{
|
41
|
+
Or(
|
42
|
+
And(
|
43
|
+
Eq(attrs[:height],"tall"),
|
44
|
+
Eq(attrs[:age],"old")
|
45
|
+
),
|
46
|
+
Eq(attrs[:eye_color],"green")
|
47
|
+
)
|
48
|
+
} => [102, 103]
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
tests.each do |test_name, cases|
|
53
|
+
test test_name do
|
54
|
+
cases.each do |predicate, expected_ids|
|
55
|
+
actual_ids = yield(predicate).sort
|
56
|
+
assert { actual_ids == expected_ids }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.included(other)
|
64
|
+
other.extend(ClassMethods)
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
2
|
+
<schema name="example" version="1.2">
|
3
|
+
<types>
|
4
|
+
<fieldType name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
|
5
|
+
|
6
|
+
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true" omitNorms="true"/>
|
7
|
+
|
8
|
+
<fieldtype name="binary" class="solr.BinaryField"/>
|
9
|
+
|
10
|
+
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
|
11
|
+
<fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
|
12
|
+
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
|
13
|
+
<fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
|
14
|
+
|
15
|
+
<fieldType name="tint" class="solr.TrieIntField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
|
16
|
+
<fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
|
17
|
+
<fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
|
18
|
+
<fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
|
19
|
+
|
20
|
+
<fieldType name="date" class="solr.TrieDateField" omitNorms="true" precisionStep="0" positionIncrementGap="0"/>
|
21
|
+
|
22
|
+
<fieldType name="tdate" class="solr.TrieDateField" omitNorms="true" precisionStep="6" positionIncrementGap="0"/>
|
23
|
+
|
24
|
+
<fieldType name="pint" class="solr.IntField" omitNorms="true"/>
|
25
|
+
<fieldType name="plong" class="solr.LongField" omitNorms="true"/>
|
26
|
+
<fieldType name="pfloat" class="solr.FloatField" omitNorms="true"/>
|
27
|
+
<fieldType name="pdouble" class="solr.DoubleField" omitNorms="true"/>
|
28
|
+
<fieldType name="pdate" class="solr.DateField" sortMissingLast="true" omitNorms="true"/>
|
29
|
+
|
30
|
+
<fieldType name="sint" class="solr.SortableIntField" sortMissingLast="true" omitNorms="true"/>
|
31
|
+
<fieldType name="slong" class="solr.SortableLongField" sortMissingLast="true" omitNorms="true"/>
|
32
|
+
<fieldType name="sfloat" class="solr.SortableFloatField" sortMissingLast="true" omitNorms="true"/>
|
33
|
+
<fieldType name="sdouble" class="solr.SortableDoubleField" sortMissingLast="true" omitNorms="true"/>
|
34
|
+
|
35
|
+
<fieldType name="random" class="solr.RandomSortField" indexed="true" />
|
36
|
+
|
37
|
+
<fieldType name="text" class="solr.TextField" positionIncrementGap="100">
|
38
|
+
<analyzer type="index">
|
39
|
+
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
|
40
|
+
<filter class="solr.StopFilterFactory"
|
41
|
+
ignoreCase="true"
|
42
|
+
words="stopwords.txt"
|
43
|
+
enablePositionIncrements="true"
|
44
|
+
/>
|
45
|
+
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
|
46
|
+
<filter class="solr.LowerCaseFilterFactory"/>
|
47
|
+
<filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/>
|
48
|
+
</analyzer>
|
49
|
+
<analyzer type="query">
|
50
|
+
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
|
51
|
+
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
|
52
|
+
<filter class="solr.StopFilterFactory"
|
53
|
+
ignoreCase="true"
|
54
|
+
words="stopwords.txt"
|
55
|
+
enablePositionIncrements="true"
|
56
|
+
/>
|
57
|
+
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
|
58
|
+
<filter class="solr.LowerCaseFilterFactory"/>
|
59
|
+
<filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/>
|
60
|
+
</analyzer>
|
61
|
+
</fieldType>
|
62
|
+
|
63
|
+
</types>
|
64
|
+
|
65
|
+
|
66
|
+
<fields>
|
67
|
+
<field name="id" type="string" indexed="true" stored="true" required="true" />
|
68
|
+
<dynamicField name="*_i" type="sint" indexed="true" stored="true"/>
|
69
|
+
<dynamicField name="*_s" type="string" indexed="true" stored="true"/>
|
70
|
+
<dynamicField name="*_l" type="slong" indexed="true" stored="true"/>
|
71
|
+
<dynamicField name="*_t" type="text" indexed="true" stored="true"/>
|
72
|
+
<dynamicField name="*_b" type="boolean" indexed="true" stored="true"/>
|
73
|
+
<dynamicField name="*_f" type="sfloat" indexed="true" stored="true"/>
|
74
|
+
<dynamicField name="*_d" type="sdouble" indexed="true" stored="true"/>
|
75
|
+
<dynamicField name="*_dt" type="date" indexed="true" stored="true"/>
|
76
|
+
<dynamicField name="*_multi" type="string" indexed="true" stored="true" multiValued="true" />
|
77
|
+
</fields>
|
78
|
+
|
79
|
+
<uniqueKey>id</uniqueKey>
|
80
|
+
<defaultSearchField>id</defaultSearchField>
|
81
|
+
<solrQueryParser defaultOperator="OR"/>
|
82
|
+
|
83
|
+
</schema>
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require "./test/test_helper_with_wrong"
|
2
|
+
require "./test_integration/canonical_integration_cases"
|
3
|
+
require "net/http"
|
4
|
+
require "open-uri"
|
5
|
+
|
6
|
+
require "predicated/predicate"
|
7
|
+
require "predicated/to/solr"
|
8
|
+
include Predicated
|
9
|
+
|
10
|
+
#download and unpack solr
|
11
|
+
#place (overwrite) schema.xml in the solr conf directory
|
12
|
+
#start solr (java -jar start.jar)
|
13
|
+
|
14
|
+
def get_from_solr_using_predicate(predicate)
|
15
|
+
eval(get_from_solr("/solr/select?q=#{URI.escape(predicate.to_solr)}&wt=ruby"))
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_from_solr(path)
|
19
|
+
open("http://localhost:8983#{path}").read
|
20
|
+
end
|
21
|
+
|
22
|
+
def post_to_solr(body)
|
23
|
+
request = Net::HTTP::Post.new("/solr/update", {'Content-Type' =>'text/xml'})
|
24
|
+
request.body = body
|
25
|
+
response = Net::HTTP.new("localhost", 8983).start {|http| http.request(request) }
|
26
|
+
raise "Response #{response.code}\n#{response.body}" unless response.code=="200"
|
27
|
+
end
|
28
|
+
|
29
|
+
regarding "solr is running properly" do
|
30
|
+
test "solr schema is the one from this project" do
|
31
|
+
assert{ get_from_solr("/solr/admin/file/?file=schema.xml") == File.read("test_integration/schema.xml") }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
regarding "predicates run against real solr" do
|
37
|
+
include CanonicalIntegrationCases
|
38
|
+
|
39
|
+
before do
|
40
|
+
unless @posted
|
41
|
+
post_to_solr("<delete><query>*:*</query></delete>")
|
42
|
+
post_to_solr("<commit/>")
|
43
|
+
|
44
|
+
docs_str =
|
45
|
+
self.fixtures.collect do |row|
|
46
|
+
%{
|
47
|
+
<doc>
|
48
|
+
<field name="id">#{row[:id]}</field>
|
49
|
+
<field name="eye_color_s">#{row[:eye_color]}</field>
|
50
|
+
<field name="height_s">#{row[:height]}</field>
|
51
|
+
<field name="age_s">#{row[:age]}</field>
|
52
|
+
<field name="cats_i">#{row[:cats]}</field>
|
53
|
+
</doc>
|
54
|
+
}
|
55
|
+
end.join("\n")
|
56
|
+
|
57
|
+
post_to_solr("<add>#{docs_str}</add>")
|
58
|
+
post_to_solr("<commit/>")
|
59
|
+
end
|
60
|
+
@posted = true
|
61
|
+
end
|
62
|
+
|
63
|
+
create_canonical_tests(
|
64
|
+
:id => "id",
|
65
|
+
:eye_color => "eye_color_s",
|
66
|
+
:height => "height_s",
|
67
|
+
:age => "age_s",
|
68
|
+
:cats => "cats_i") do |predicate|
|
69
|
+
get_from_solr_using_predicate(predicate)["response"]["docs"].collect{|d|d["id"].to_i}
|
70
|
+
end
|
71
|
+
end
|
Binary file
|
@@ -0,0 +1,252 @@
|
|
1
|
+
require "./test/test_helper_with_wrong"
|
2
|
+
|
3
|
+
require "predicated/to/arel"
|
4
|
+
require "sqlite3-ruby"
|
5
|
+
require "active_record"
|
6
|
+
require "fileutils"
|
7
|
+
|
8
|
+
regarding "prove out examples used in the README" do
|
9
|
+
|
10
|
+
before do
|
11
|
+
unless @created
|
12
|
+
db_file = "/tmp/sqlite_db"
|
13
|
+
FileUtils.rm_f(db_file)
|
14
|
+
@db = SQLite3::Database.new(db_file)
|
15
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3-ruby", :database => db_file)
|
16
|
+
@db.execute(%{
|
17
|
+
create table shirt (
|
18
|
+
id INTEGER PRIMARY KEY,
|
19
|
+
color VARCHAR(25),
|
20
|
+
size VARCHAR(25)
|
21
|
+
);
|
22
|
+
})
|
23
|
+
end
|
24
|
+
@created = true
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
test "Evaluate a predicate" do
|
29
|
+
|
30
|
+
require "predicated/evaluate"
|
31
|
+
extend Predicated #include Predicated
|
32
|
+
|
33
|
+
assert{
|
34
|
+
Predicate { Eq(1, 2) }.evaluate == false
|
35
|
+
}
|
36
|
+
assert{
|
37
|
+
Predicate { Lt(1, 2) }.evaluate == true
|
38
|
+
}
|
39
|
+
assert{
|
40
|
+
Predicate { Or(Lt(1, 2),Eq(1, 2)) }.evaluate == true
|
41
|
+
}
|
42
|
+
|
43
|
+
assert{
|
44
|
+
x = 1
|
45
|
+
Predicate { Lt(x, 2) }.evaluate == true
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
test "Parse a predicate from part of a url and then turn it into a sql where clause" do
|
51
|
+
|
52
|
+
require "predicated/from/url_part"
|
53
|
+
require "predicated/to/arel"
|
54
|
+
|
55
|
+
predicate = Predicated::Predicate.from_url_part("(color=red|color=green)&size=large")
|
56
|
+
|
57
|
+
assert{
|
58
|
+
predicate.inspect ==
|
59
|
+
"And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
|
60
|
+
}
|
61
|
+
|
62
|
+
assert{
|
63
|
+
predicate.to_arel(Table(:shirt)).to_sql ==
|
64
|
+
%{(("shirt"."color" = 'red' OR "shirt"."color" = 'green') AND "shirt"."size" = 'large')}
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
test "Parse a predicate from json and then turn it into a solr query string" do
|
70
|
+
|
71
|
+
require "predicated/from/json"
|
72
|
+
require "predicated/to/solr"
|
73
|
+
|
74
|
+
predicate = Predicated::Predicate.from_json_str(%{
|
75
|
+
{"and":[{"or":[["color","==","red"],["color","==","green"]]},["size","==","large"]]}
|
76
|
+
})
|
77
|
+
|
78
|
+
assert{
|
79
|
+
predicate.inspect == "And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
|
80
|
+
}
|
81
|
+
|
82
|
+
assert{
|
83
|
+
predicate.to_solr == "((color:red OR color:green) AND size:large)"
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
test "From json" do
|
89
|
+
|
90
|
+
require "predicated/from/json"
|
91
|
+
|
92
|
+
assert{
|
93
|
+
Predicated::Predicate.from_json_str(%{
|
94
|
+
{"and":[
|
95
|
+
{"or":[
|
96
|
+
["color","==","red"],
|
97
|
+
["color","==","green"]
|
98
|
+
]},
|
99
|
+
["size","==","large"]
|
100
|
+
]}
|
101
|
+
}).inspect == "And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
test "From xml" do
|
107
|
+
|
108
|
+
require "predicated/from/xml"
|
109
|
+
|
110
|
+
assert{
|
111
|
+
Predicated::Predicate.from_xml(%{
|
112
|
+
<and>
|
113
|
+
<or>
|
114
|
+
<equal><left>color</left><right>red</right></equal>
|
115
|
+
<equal><left>color</left><right>green</right></equal>
|
116
|
+
</or>
|
117
|
+
<equal><left>size</left><right>large</right></equal>
|
118
|
+
</and>
|
119
|
+
}).inspect == "And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
test "From url part" do
|
125
|
+
|
126
|
+
require "predicated/from/url_part"
|
127
|
+
|
128
|
+
assert{
|
129
|
+
Predicated::Predicate.from_url_part("(color=red|color=green)&size=large").inspect ==
|
130
|
+
"And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
|
131
|
+
}
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
test "From callable object" do
|
136
|
+
|
137
|
+
require "predicated/from/callable_object"
|
138
|
+
|
139
|
+
assert{
|
140
|
+
Predicated::Predicate.from_callable_object{('color'=='red' || 'color'=='green') && 'size'=='large'}.inspect ==
|
141
|
+
"And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
test "From ruby code string" do
|
147
|
+
|
148
|
+
require "predicated/from/ruby_code_string"
|
149
|
+
|
150
|
+
assert{
|
151
|
+
Predicated::Predicate.from_ruby_code_string("('color'=='red' || 'color'=='green') && 'size'=='large'").inspect ==
|
152
|
+
"And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
|
153
|
+
}
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
test "To json" do
|
158
|
+
|
159
|
+
require "predicated/to/json"
|
160
|
+
extend Predicated #include Predicated
|
161
|
+
|
162
|
+
assert{
|
163
|
+
Predicate{And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))}.to_json_str.gsub(/\s/, "") ==
|
164
|
+
%{
|
165
|
+
{"and":[
|
166
|
+
{"or":[
|
167
|
+
["color","==","red"],
|
168
|
+
["color","==","green"]
|
169
|
+
]},
|
170
|
+
["size","==","large"]
|
171
|
+
]}
|
172
|
+
}.gsub(/\s/, "")
|
173
|
+
}
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
test "To xml" do
|
178
|
+
|
179
|
+
require "predicated/to/xml"
|
180
|
+
extend Predicated #include Predicated
|
181
|
+
|
182
|
+
assert{
|
183
|
+
Predicate{And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))}.to_xml.gsub(/\s/, "") ==
|
184
|
+
%{
|
185
|
+
<and>
|
186
|
+
<or>
|
187
|
+
<equal><left>color</left><right>red</right></equal>
|
188
|
+
<equal><left>color</left><right>green</right></equal>
|
189
|
+
</or>
|
190
|
+
<equal><left>size</left><right>large</right></equal>
|
191
|
+
</and>
|
192
|
+
}.gsub(/\s/, "")
|
193
|
+
}
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
test "To arel (sql where clause)" do
|
198
|
+
|
199
|
+
require "predicated/to/arel"
|
200
|
+
extend Predicated #include Predicated
|
201
|
+
|
202
|
+
assert{
|
203
|
+
Predicate{And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))}.to_arel(Table(:shirt)).to_sql ==
|
204
|
+
%{(("shirt"."color" = 'red' OR "shirt"."color" = 'green') AND "shirt"."size" = 'large')}
|
205
|
+
}
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
test "To solr query string" do
|
210
|
+
|
211
|
+
require "predicated/to/solr"
|
212
|
+
extend Predicated #include Predicated
|
213
|
+
|
214
|
+
assert{
|
215
|
+
Predicate{And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))}.to_solr ==
|
216
|
+
"((color:red OR color:green) AND size:large)"
|
217
|
+
}
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
test "To sentence" do
|
222
|
+
|
223
|
+
require "predicated/to/sentence"
|
224
|
+
extend Predicated #include Predicated
|
225
|
+
|
226
|
+
assert{
|
227
|
+
Predicate{ And(Eq("a",1),Eq("b",2)) }.to_sentence ==
|
228
|
+
"'a' is equal to 1 and 'b' is equal to 2"
|
229
|
+
}
|
230
|
+
|
231
|
+
assert {
|
232
|
+
Predicate{ Gt("a",1) }.to_negative_sentence ==
|
233
|
+
"'a' is not greater than 1"
|
234
|
+
}
|
235
|
+
end
|
236
|
+
|
237
|
+
xtest "format and puts me" do
|
238
|
+
lines = File.read(__FILE__).split("\n")
|
239
|
+
lines =
|
240
|
+
lines.reject do |line|
|
241
|
+
line.include?("assert") || line =~ /^[ ]*\}[ ]*$/ || line =~ /^[ ]*end[ ]*$/
|
242
|
+
end
|
243
|
+
str = lines.join("\n")
|
244
|
+
|
245
|
+
puts str.
|
246
|
+
gsub(" test \"", "").
|
247
|
+
gsub("\" do", ":").
|
248
|
+
gsub("extend Predicated #include Predicated", "include Predicated").
|
249
|
+
gsub(%{.gsub(/\\s/, "")}, "")
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|