ferret 0.3.2 → 0.9.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.
- data/CHANGELOG +9 -0
- data/Rakefile +51 -25
- data/ext/analysis.c +553 -0
- data/ext/analysis.h +76 -0
- data/ext/array.c +83 -0
- data/ext/array.h +19 -0
- data/ext/bitvector.c +164 -0
- data/ext/bitvector.h +29 -0
- data/ext/compound_io.c +335 -0
- data/ext/document.c +336 -0
- data/ext/document.h +87 -0
- data/ext/ferret.c +88 -47
- data/ext/ferret.h +43 -109
- data/ext/field.c +395 -0
- data/ext/filter.c +103 -0
- data/ext/fs_store.c +352 -0
- data/ext/global.c +219 -0
- data/ext/global.h +73 -0
- data/ext/hash.c +446 -0
- data/ext/hash.h +80 -0
- data/ext/hashset.c +141 -0
- data/ext/hashset.h +37 -0
- data/ext/helper.c +11 -0
- data/ext/helper.h +5 -0
- data/ext/inc/lang.h +41 -0
- data/ext/ind.c +389 -0
- data/ext/index.h +884 -0
- data/ext/index_io.c +269 -415
- data/ext/index_rw.c +2543 -0
- data/ext/lang.c +31 -0
- data/ext/lang.h +41 -0
- data/ext/priorityqueue.c +228 -0
- data/ext/priorityqueue.h +44 -0
- data/ext/q_boolean.c +1331 -0
- data/ext/q_const_score.c +154 -0
- data/ext/q_fuzzy.c +287 -0
- data/ext/q_match_all.c +142 -0
- data/ext/q_multi_phrase.c +343 -0
- data/ext/q_parser.c +2180 -0
- data/ext/q_phrase.c +657 -0
- data/ext/q_prefix.c +75 -0
- data/ext/q_range.c +247 -0
- data/ext/q_span.c +1566 -0
- data/ext/q_term.c +308 -0
- data/ext/q_wildcard.c +146 -0
- data/ext/r_analysis.c +255 -0
- data/ext/r_doc.c +578 -0
- data/ext/r_index_io.c +996 -0
- data/ext/r_qparser.c +158 -0
- data/ext/r_search.c +2321 -0
- data/ext/r_store.c +263 -0
- data/ext/r_term.c +219 -0
- data/ext/ram_store.c +447 -0
- data/ext/search.c +524 -0
- data/ext/search.h +1065 -0
- data/ext/similarity.c +143 -39
- data/ext/sort.c +661 -0
- data/ext/store.c +35 -0
- data/ext/store.h +152 -0
- data/ext/term.c +704 -143
- data/ext/termdocs.c +599 -0
- data/ext/vector.c +594 -0
- data/lib/ferret.rb +9 -10
- data/lib/ferret/analysis/analyzers.rb +2 -2
- data/lib/ferret/analysis/standard_tokenizer.rb +1 -1
- data/lib/ferret/analysis/token.rb +14 -14
- data/lib/ferret/analysis/token_filters.rb +3 -3
- data/lib/ferret/document/field.rb +16 -17
- data/lib/ferret/index/document_writer.rb +4 -4
- data/lib/ferret/index/index.rb +39 -23
- data/lib/ferret/index/index_writer.rb +2 -2
- data/lib/ferret/index/multiple_term_doc_pos_enum.rb +1 -8
- data/lib/ferret/index/segment_term_vector.rb +4 -4
- data/lib/ferret/index/term.rb +5 -1
- data/lib/ferret/index/term_vector_offset_info.rb +6 -6
- data/lib/ferret/index/term_vectors_io.rb +5 -5
- data/lib/ferret/query_parser/query_parser.tab.rb +81 -77
- data/lib/ferret/search.rb +1 -1
- data/lib/ferret/search/boolean_query.rb +2 -1
- data/lib/ferret/search/field_sorted_hit_queue.rb +3 -3
- data/lib/ferret/search/fuzzy_query.rb +2 -1
- data/lib/ferret/search/index_searcher.rb +3 -0
- data/lib/ferret/search/{match_all_docs_query.rb → match_all_query.rb} +7 -7
- data/lib/ferret/search/multi_phrase_query.rb +6 -5
- data/lib/ferret/search/phrase_query.rb +3 -6
- data/lib/ferret/search/prefix_query.rb +4 -4
- data/lib/ferret/search/sort.rb +3 -1
- data/lib/ferret/search/sort_field.rb +9 -9
- data/lib/ferret/search/spans/near_spans_enum.rb +1 -1
- data/lib/ferret/search/spans/span_near_query.rb +1 -1
- data/lib/ferret/search/spans/span_weight.rb +1 -1
- data/lib/ferret/search/spans/spans_enum.rb +7 -7
- data/lib/ferret/store/fs_store.rb +10 -6
- data/lib/ferret/store/ram_store.rb +3 -3
- data/lib/rferret.rb +36 -0
- data/test/functional/thread_safety_index_test.rb +2 -2
- data/test/test_helper.rb +16 -2
- data/test/unit/analysis/c_token.rb +25 -0
- data/test/unit/analysis/tc_per_field_analyzer_wrapper.rb +1 -1
- data/test/unit/analysis/tc_standard_analyzer.rb +1 -1
- data/test/unit/document/{tc_document.rb → c_document.rb} +0 -0
- data/test/unit/document/c_field.rb +98 -0
- data/test/unit/document/tc_field.rb +0 -66
- data/test/unit/index/{tc_index.rb → c_index.rb} +62 -6
- data/test/unit/index/{tc_index_reader.rb → c_index_reader.rb} +51 -10
- data/test/unit/index/{tc_index_writer.rb → c_index_writer.rb} +0 -4
- data/test/unit/index/{tc_term.rb → c_term.rb} +1 -3
- data/test/unit/index/{tc_term_vector_offset_info.rb → c_term_voi.rb} +5 -5
- data/test/unit/index/tc_segment_term_vector.rb +2 -2
- data/test/unit/index/tc_term_vectors_io.rb +4 -4
- data/test/unit/query_parser/c_query_parser.rb +138 -0
- data/test/unit/search/{tc_filter.rb → c_filter.rb} +24 -24
- data/test/unit/search/{tc_fuzzy_query.rb → c_fuzzy_query.rb} +0 -0
- data/test/unit/search/{tc_index_searcher.rb → c_index_searcher.rb} +9 -26
- data/test/unit/search/{tc_search_and_sort.rb → c_search_and_sort.rb} +15 -15
- data/test/unit/search/{tc_sort.rb → c_sort.rb} +2 -1
- data/test/unit/search/c_sort_field.rb +27 -0
- data/test/unit/search/{tc_spans.rb → c_spans.rb} +0 -0
- data/test/unit/search/tc_sort_field.rb +7 -20
- data/test/unit/store/c_fs_store.rb +76 -0
- data/test/unit/store/c_ram_store.rb +35 -0
- data/test/unit/store/m_store.rb +34 -0
- data/test/unit/store/m_store_lock.rb +68 -0
- data/test/unit/store/tc_fs_store.rb +0 -53
- data/test/unit/store/tc_ram_store.rb +0 -20
- data/test/unit/store/tm_store.rb +0 -30
- data/test/unit/store/tm_store_lock.rb +0 -66
- metadata +84 -31
- data/ext/Makefile +0 -140
- data/ext/ferret_ext.so +0 -0
- data/ext/priority_queue.c +0 -232
- data/ext/ram_directory.c +0 -321
- data/ext/segment_merge_queue.c +0 -37
- data/ext/segment_term_enum.c +0 -326
- data/ext/string_helper.c +0 -42
- data/ext/tags +0 -344
- data/ext/term_buffer.c +0 -230
- data/ext/term_infos_reader.c +0 -54
- data/ext/terminfo.c +0 -160
- data/ext/token.c +0 -93
- data/ext/util.c +0 -12
@@ -51,7 +51,7 @@ class FilterTest < Test::Unit::TestCase
|
|
51
51
|
|
52
52
|
def test_range_filter
|
53
53
|
is = IndexSearcher.new(@dir)
|
54
|
-
q =
|
54
|
+
q = MatchAllQuery.new()
|
55
55
|
rf = RangeFilter.new("int", "2", "6", true, true)
|
56
56
|
do_test_top_docs(is, q, [2,3,4,5,6], rf)
|
57
57
|
rf = RangeFilter.new("int", "2", "6", true, false)
|
@@ -79,7 +79,7 @@ class FilterTest < Test::Unit::TestCase
|
|
79
79
|
|
80
80
|
def test_query_filter()
|
81
81
|
is = IndexSearcher.new(@dir)
|
82
|
-
q =
|
82
|
+
q = MatchAllQuery.new()
|
83
83
|
qf = QueryFilter.new(TermQuery.new(Term.new("switch", "on")))
|
84
84
|
do_test_top_docs(is, q, [0,2,4,6,8], qf)
|
85
85
|
# test again to test caching doesn't break it
|
@@ -88,26 +88,26 @@ class FilterTest < Test::Unit::TestCase
|
|
88
88
|
do_test_top_docs(is, q, [1,3,5,7,9], qf)
|
89
89
|
end
|
90
90
|
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
def test_filtered_query
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
end
|
91
|
+
#def test_filtered_query
|
92
|
+
# is = IndexSearcher.new(@dir)
|
93
|
+
# q = MatchAllQuery.new()
|
94
|
+
# rf = RangeFilter.new("int", "2", "6", true, true)
|
95
|
+
# rq = FilteredQuery.new(q, rf)
|
96
|
+
# qf = QueryFilter.new(TermQuery.new(Term.new("switch", "on")))
|
97
|
+
# do_test_top_docs(is, rq, [2,4,6], qf)
|
98
|
+
# query = FilteredQuery.new(rq, qf)
|
99
|
+
# rf2 = RangeFilter.new_more("int", "3")
|
100
|
+
# do_test_top_docs(is, query, [4,6], rf2)
|
101
|
+
#end
|
102
|
+
#def test_filtered_query
|
103
|
+
# is = IndexSearcher.new(@dir)
|
104
|
+
# q = MatchAllQuery.new()
|
105
|
+
# rf = RangeFilter.new("int", "2", "6", true, true)
|
106
|
+
# rq = FilteredQuery.new(q, rf)
|
107
|
+
# qf = QueryFilter.new(TermQuery.new(Term.new("switch", "on")))
|
108
|
+
# do_test_top_docs(is, rq, [2,4,6], qf)
|
109
|
+
# query = FilteredQuery.new(rq, qf)
|
110
|
+
# rf2 = RangeFilter.new_more("int", "3")
|
111
|
+
# do_test_top_docs(is, query, [4,6], rf2)
|
112
|
+
#end
|
113
113
|
end
|
File without changes
|
@@ -11,7 +11,7 @@ class IndexSearcherTest < Test::Unit::TestCase
|
|
11
11
|
@dir = RAMDirectory.new()
|
12
12
|
iw = IndexWriter.new(@dir, :analyzer => WhiteSpaceAnalyzer.new(), :create => true)
|
13
13
|
@documents = IndexTestHelper.prepare_search_docs()
|
14
|
-
@documents.each { |doc| iw << doc
|
14
|
+
@documents.each { |doc| iw << doc }
|
15
15
|
iw.close()
|
16
16
|
@is = IndexSearcher.new(@dir)
|
17
17
|
end
|
@@ -62,20 +62,20 @@ class IndexSearcherTest < Test::Unit::TestCase
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def test_term_query
|
65
|
-
tq = TermQuery.new(Term.new("field", "word2"))
|
65
|
+
tq = TermQuery.new(Term.new("field", "word2"))
|
66
66
|
tq.boost = 100
|
67
67
|
check_hits(tq, [1,4,8])
|
68
68
|
#puts @is.explain(tq, 1)
|
69
69
|
#puts @is.explain(tq, 4)
|
70
70
|
#puts @is.explain(tq, 8)
|
71
71
|
|
72
|
-
tq = TermQuery.new(Term.new("field", "2342"))
|
72
|
+
tq = TermQuery.new(Term.new("field", "2342"))
|
73
73
|
check_hits(tq, [])
|
74
74
|
|
75
|
-
tq = TermQuery.new(Term.new("field", ""))
|
75
|
+
tq = TermQuery.new(Term.new("field", ""))
|
76
76
|
check_hits(tq, [])
|
77
77
|
|
78
|
-
tq = TermQuery.new(Term.new("field", "word1"))
|
78
|
+
tq = TermQuery.new(Term.new("field", "word1"))
|
79
79
|
top_docs = @is.search(tq)
|
80
80
|
assert_equal(@documents.size, top_docs.total_hits)
|
81
81
|
assert_equal(10, top_docs.score_docs.size)
|
@@ -85,12 +85,12 @@ class IndexSearcherTest < Test::Unit::TestCase
|
|
85
85
|
|
86
86
|
|
87
87
|
def test_first_doc
|
88
|
-
tq = TermQuery.new(Term.new("field", "word1"))
|
88
|
+
tq = TermQuery.new(Term.new("field", "word1"))
|
89
89
|
tq.boost = 100
|
90
90
|
top_docs = @is.search(tq, {:num_docs => 100})
|
91
91
|
expected = []
|
92
|
-
top_docs.score_docs.each do |
|
93
|
-
expected <<
|
92
|
+
top_docs.score_docs.each do |sd|
|
93
|
+
expected << sd.doc
|
94
94
|
end
|
95
95
|
|
96
96
|
assert_raise(ArgumentError) { @is.search(tq, {:first_doc => -1}) }
|
@@ -151,23 +151,6 @@ class IndexSearcherTest < Test::Unit::TestCase
|
|
151
151
|
check_hits(pq, [1,11,14,16,17])
|
152
152
|
end
|
153
153
|
|
154
|
-
def test_multi_phrase_query()
|
155
|
-
pq = MultiPhraseQuery.new()
|
156
|
-
t1 = Term.new("field", "quick")
|
157
|
-
t2 = Term.new("field", "brown")
|
158
|
-
t3 = Term.new("field", "fox")
|
159
|
-
pq << t1
|
160
|
-
pq << t2
|
161
|
-
pq << t3
|
162
|
-
check_hits(pq, [1])
|
163
|
-
|
164
|
-
t1b = Term.new("field", "fast")
|
165
|
-
pq.add(t1b, 0)
|
166
|
-
check_hits(pq, [1, 8])
|
167
|
-
end
|
168
|
-
|
169
|
-
|
170
|
-
|
171
154
|
def test_range_query()
|
172
155
|
rq = RangeQuery.new("date", "20051006", "20051010", true, true)
|
173
156
|
check_hits(rq, [6,7,8,9,10])
|
@@ -226,7 +209,7 @@ class IndexSearcherTest < Test::Unit::TestCase
|
|
226
209
|
check_hits(wq, [4, 16])
|
227
210
|
end
|
228
211
|
|
229
|
-
def
|
212
|
+
def test_multi_phrase_query()
|
230
213
|
t11 = Term.new("field", "quick")
|
231
214
|
t12 = Term.new("field", "fast")
|
232
215
|
t21 = Term.new("field", "brown")
|
@@ -81,19 +81,19 @@ class SearchAndSortTest < Test::Unit::TestCase
|
|
81
81
|
do_test_top_docs(is, q, [3,2,7,8,4,9,5,1,6,0], Sort.new(["int", "string"]))
|
82
82
|
end
|
83
83
|
|
84
|
-
LENGTH = SortField::SortType.new("length", lambda{|str| str.length})
|
85
|
-
LENGTH_MODULO = SortField::SortType.new("length_mod", lambda{|str| str.length},
|
86
|
-
|
87
|
-
def test_special_sorts
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
end
|
84
|
+
#LENGTH = SortField::SortType.new("length", lambda{|str| str.length})
|
85
|
+
#LENGTH_MODULO = SortField::SortType.new("length_mod", lambda{|str| str.length},
|
86
|
+
# lambda{|i, j| (i%4) <=> (j%4)})
|
87
|
+
#def test_special_sorts
|
88
|
+
# is = IndexSearcher.new(@dir)
|
89
|
+
# q = TermQuery.new(Term.new("search", "findall"))
|
90
|
+
# sf = SortField.new("float", {:sort_type => LENGTH, :reverse => true})
|
91
|
+
# do_test_top_docs(is, q, [9,6,4,8,2,7,0,5,1,3], [sf])
|
92
|
+
# sf = SortField.new("float", {:sort_type => LENGTH_MODULO, :reverse => true})
|
93
|
+
# do_test_top_docs(is, q, [1,3,6,4,8,2,7,0,5,9], [sf])
|
94
|
+
# sf = SortField.new("float", {:sort_type => LENGTH,
|
95
|
+
# :reverse => true,
|
96
|
+
# :comparator => lambda{|i,j| (j%4) <=> (i%4)}})
|
97
|
+
# do_test_top_docs(is, q, [0,5,9,2,7,4,8,1,3,6], [sf])
|
98
|
+
#end
|
99
99
|
end
|
@@ -22,13 +22,14 @@ class SortTest < Test::Unit::TestCase
|
|
22
22
|
assert_equal(SortField::FIELD_DOC, s.fields[1])
|
23
23
|
|
24
24
|
s = Sort.new(["field1", "field2", "field3"])
|
25
|
-
assert_equal(
|
25
|
+
assert_equal(4, s.fields.size)
|
26
26
|
assert_equal(SortField::SortType::AUTO, s.fields[0].sort_type)
|
27
27
|
assert_equal("field1", s.fields[0].name)
|
28
28
|
assert_equal(SortField::SortType::AUTO, s.fields[1].sort_type)
|
29
29
|
assert_equal("field2", s.fields[1].name)
|
30
30
|
assert_equal(SortField::SortType::AUTO, s.fields[2].sort_type)
|
31
31
|
assert_equal("field3", s.fields[2].name)
|
32
|
+
assert_equal(SortField::FIELD_DOC, s.fields[3])
|
32
33
|
end
|
33
34
|
|
34
35
|
def test_multi_fields()
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../../test_helper"
|
2
|
+
|
3
|
+
class SortFieldTest < Test::Unit::TestCase
|
4
|
+
include Ferret::Search
|
5
|
+
|
6
|
+
def test_field_score()
|
7
|
+
fs = SortField::FIELD_SCORE
|
8
|
+
assert_equal(SortField::SortType::SCORE, fs.sort_type)
|
9
|
+
assert_nil(fs.name)
|
10
|
+
assert(!fs.reverse?, "FIELD_SCORE should not be reverse")
|
11
|
+
assert_nil(fs.comparator)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_field_doc()
|
15
|
+
fs = SortField::FIELD_DOC
|
16
|
+
assert_equal(SortField::SortType::DOC, fs.sort_type)
|
17
|
+
assert_nil(fs.name)
|
18
|
+
assert(!fs.reverse?, "FIELD_DOC should not be reverse")
|
19
|
+
assert_nil(fs.comparator)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_error_raised()
|
23
|
+
assert_raise(ArgumentError) {
|
24
|
+
fs = SortField.new(nil, {:sort_type => SortField::SortType::INTEGER})
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
File without changes
|
@@ -3,25 +3,12 @@ require File.dirname(__FILE__) + "/../../test_helper"
|
|
3
3
|
class SortFieldTest < Test::Unit::TestCase
|
4
4
|
include Ferret::Search
|
5
5
|
|
6
|
-
def
|
7
|
-
|
8
|
-
assert_equal(SortField::SortType::
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def test_field_doc()
|
15
|
-
fs = SortField::FIELD_DOC
|
16
|
-
assert_equal(SortField::SortType::DOC, fs.sort_type)
|
17
|
-
assert_nil(fs.name)
|
18
|
-
assert(!fs.reverse?, "FIELD_DOC should not be reverse")
|
19
|
-
assert_nil(fs.comparator)
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_error_raised()
|
23
|
-
assert_raise(ArgumentError) {
|
24
|
-
fs = SortField.new(nil, {:sort_type => SortField::SortType::INTEGER})
|
25
|
-
}
|
6
|
+
def test_params()
|
7
|
+
assert_equal("score", SortField::SortType::SCORE.to_s)
|
8
|
+
assert_equal("doc", SortField::SortType::DOC.to_s)
|
9
|
+
assert_equal("auto", SortField::SortType::AUTO.to_s)
|
10
|
+
assert_equal("string", SortField::SortType::STRING.to_s)
|
11
|
+
assert_equal("int", SortField::SortType::INTEGER.to_s)
|
12
|
+
assert_equal("float", SortField::SortType::FLOAT.to_s)
|
26
13
|
end
|
27
14
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../../test_helper"
|
2
|
+
require File.dirname(__FILE__) + "/m_store"
|
3
|
+
require File.dirname(__FILE__) + "/m_store_lock"
|
4
|
+
|
5
|
+
class FSStoreTest < Test::Unit::TestCase
|
6
|
+
include Ferret::Store
|
7
|
+
include StoreTest
|
8
|
+
include StoreLockTest
|
9
|
+
def setup
|
10
|
+
@dpath = File.join(File.dirname(__FILE__),
|
11
|
+
'../../temp/fsdir')
|
12
|
+
@dir = FSDirectory.new(@dpath, true)
|
13
|
+
@dir1 = FSDirectory.new(@dpath, true)
|
14
|
+
@dir2 = FSDirectory.new(@dpath, true)
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
@dir.refresh()
|
19
|
+
@dir.close()
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_fslock
|
23
|
+
lock_name = "lfile"
|
24
|
+
lock_file_path = make_lock_file_path(lock_name)
|
25
|
+
assert(! File.exists?(lock_file_path), "There should be no lock file")
|
26
|
+
lock = @dir.make_lock(lock_name)
|
27
|
+
assert(! File.exists?(lock_file_path), "There should still be no lock file")
|
28
|
+
assert(! lock.locked?, "lock shouldn't be locked yet")
|
29
|
+
|
30
|
+
lock.obtain
|
31
|
+
|
32
|
+
assert(lock.locked?, "lock should now be locked")
|
33
|
+
|
34
|
+
assert(File.exists?(lock_file_path), "A lock file should have been created")
|
35
|
+
|
36
|
+
assert(! @dir.exists?(lock_file_path),
|
37
|
+
"The lock should be hidden by the FSDirectories directory scan")
|
38
|
+
|
39
|
+
lock.release
|
40
|
+
|
41
|
+
assert(! lock.locked?, "lock should be freed again")
|
42
|
+
assert(! File.exists?(lock_file_path), "The lock file should have been deleted")
|
43
|
+
end
|
44
|
+
|
45
|
+
# def make_and_loose_lock
|
46
|
+
# lock = @dir.make_lock("finalizer_lock")
|
47
|
+
# lock.obtain
|
48
|
+
# lock = nil
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# def test_fslock_finalizer
|
52
|
+
# lock_name = "finalizer_lock"
|
53
|
+
# lock_file_path = make_lock_file_path(lock_name)
|
54
|
+
# assert(! File.exists?(lock_file_path), "There should be no lock file")
|
55
|
+
#
|
56
|
+
# make_and_loose_lock
|
57
|
+
#
|
58
|
+
# #assert(File.exists?(lock_file_path), "There should now be a lock file")
|
59
|
+
#
|
60
|
+
# lock = @dir.make_lock(lock_name)
|
61
|
+
# assert(lock.locked?, "lock should now be locked")
|
62
|
+
#
|
63
|
+
# GC.start
|
64
|
+
#
|
65
|
+
# assert(! lock.locked?, "lock should be freed again")
|
66
|
+
# assert(! File.exists?(lock_file_path), "The lock file should have been deleted")
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
def make_lock_file_path(name)
|
70
|
+
lock_file_path = File.join(@dpath, "ferret-#{name}.lck")
|
71
|
+
if File.exists?(lock_file_path) then
|
72
|
+
File.delete(lock_file_path)
|
73
|
+
end
|
74
|
+
return lock_file_path
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../../test_helper"
|
2
|
+
require File.dirname(__FILE__) + "/m_store"
|
3
|
+
require File.dirname(__FILE__) + "/m_store_lock"
|
4
|
+
|
5
|
+
class RAMStoreTest < Test::Unit::TestCase
|
6
|
+
include StoreTest
|
7
|
+
include StoreLockTest
|
8
|
+
def setup
|
9
|
+
@dir = Ferret::Store::RAMDirectory.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
@dir.close()
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_ramlock
|
17
|
+
name = "lfile"
|
18
|
+
lfile = Ferret::Store::Directory::LOCK_PREFIX + name + ".lck"
|
19
|
+
assert(! @dir.exists?(lfile),
|
20
|
+
"There should be no lock file")
|
21
|
+
lock = @dir.make_lock(name)
|
22
|
+
assert(! @dir.exists?(lfile),
|
23
|
+
"There should still be no lock file")
|
24
|
+
assert(! @dir.exists?(lfile),
|
25
|
+
"The lock should be hidden by the FSDirectories directory scan")
|
26
|
+
assert(! lock.locked?, "lock shouldn't be locked yet")
|
27
|
+
lock.obtain
|
28
|
+
assert(lock.locked?, "lock should now be locked")
|
29
|
+
assert(@dir.exists?(lfile), "A lock file should have been created")
|
30
|
+
lock.release
|
31
|
+
assert(! lock.locked?, "lock should be freed again")
|
32
|
+
assert(! @dir.exists?(lfile),
|
33
|
+
"The lock file should have been deleted")
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module StoreTest
|
2
|
+
# declare dir so inheritors can access it.
|
3
|
+
attr_accessor :dir
|
4
|
+
|
5
|
+
# test the basic file manipulation methods;
|
6
|
+
# - exists?
|
7
|
+
# - touch
|
8
|
+
# - delete
|
9
|
+
# - file_count
|
10
|
+
def test_basic_file_ops
|
11
|
+
assert_equal(0, @dir.file_count(), "directory should be empty")
|
12
|
+
assert(! @dir.exists?('filename'), "File should not exist")
|
13
|
+
@dir.touch('tmpfile1')
|
14
|
+
assert_equal(1, @dir.file_count(), "directory should have one file")
|
15
|
+
@dir.touch('tmpfile2')
|
16
|
+
assert_equal(2, @dir.file_count(), "directory should have two files")
|
17
|
+
assert(@dir.exists?('tmpfile1'), "'tmpfile1' should exist")
|
18
|
+
@dir.delete('tmpfile1')
|
19
|
+
assert(! @dir.exists?('tmpfile1'), "'tmpfile1' should no longer exist")
|
20
|
+
assert_equal(1, @dir.file_count(), "directory should have one file")
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_rename
|
24
|
+
@dir.touch("from")
|
25
|
+
assert(@dir.exists?('from'), "File should exist")
|
26
|
+
assert(! @dir.exists?('to'), "File should not exist")
|
27
|
+
cnt_before = @dir.file_count()
|
28
|
+
@dir.rename('from', 'to')
|
29
|
+
cnt_after = @dir.file_count()
|
30
|
+
assert_equal(cnt_before, cnt_after, "the number of files shouldn't have changed")
|
31
|
+
assert(@dir.exists?('to'), "File should now exist")
|
32
|
+
assert(! @dir.exists?('from'), "File should no longer exist")
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module StoreLockTest
|
2
|
+
class Switch
|
3
|
+
@@counter = 0
|
4
|
+
def Switch.counter() return @@counter end
|
5
|
+
def Switch.counter=(counter) @@counter = counter end
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_locking()
|
9
|
+
lock_time_out = 0.001 # we want this test to run quickly
|
10
|
+
lock1 = @dir.make_lock("l.lck")
|
11
|
+
lock2 = @dir.make_lock("l.lck")
|
12
|
+
|
13
|
+
assert(!lock2.locked?)
|
14
|
+
assert(lock1.obtain(lock_time_out))
|
15
|
+
assert(lock2.locked?)
|
16
|
+
|
17
|
+
assert(! obtain_lock_true_false(lock2))
|
18
|
+
|
19
|
+
exception_thrown = false
|
20
|
+
begin
|
21
|
+
lock2.while_locked(lock_time_out) do
|
22
|
+
assert(false, "lock should not have been obtained")
|
23
|
+
end
|
24
|
+
rescue
|
25
|
+
exception_thrown = true
|
26
|
+
ensure
|
27
|
+
assert(exception_thrown)
|
28
|
+
end
|
29
|
+
|
30
|
+
lock1.release()
|
31
|
+
assert(lock2.obtain(lock_time_out))
|
32
|
+
lock2.release()
|
33
|
+
|
34
|
+
t = Thread.new() do
|
35
|
+
lock1.while_locked(lock_time_out) do
|
36
|
+
Switch.counter = 1
|
37
|
+
# make sure lock2 obtain test was run
|
38
|
+
while Switch.counter < 2
|
39
|
+
end
|
40
|
+
Switch.counter = 3
|
41
|
+
end
|
42
|
+
end
|
43
|
+
t.run()
|
44
|
+
|
45
|
+
#make sure thread has started and lock been obtained
|
46
|
+
while Switch.counter < 1
|
47
|
+
end
|
48
|
+
|
49
|
+
assert(! obtain_lock_true_false(lock2))
|
50
|
+
|
51
|
+
Switch.counter = 2
|
52
|
+
while Switch.counter < 3
|
53
|
+
end
|
54
|
+
|
55
|
+
assert(lock2.obtain(lock_time_out))
|
56
|
+
lock2.release()
|
57
|
+
end
|
58
|
+
|
59
|
+
def obtain_lock_true_false(lock)
|
60
|
+
lock_time_out = 0.001 # we want this test to run quickly
|
61
|
+
begin
|
62
|
+
lock.obtain(lock_time_out)
|
63
|
+
return true
|
64
|
+
rescue
|
65
|
+
end
|
66
|
+
return false
|
67
|
+
end
|
68
|
+
end
|