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.
Files changed (141) hide show
  1. data/CHANGELOG +9 -0
  2. data/Rakefile +51 -25
  3. data/ext/analysis.c +553 -0
  4. data/ext/analysis.h +76 -0
  5. data/ext/array.c +83 -0
  6. data/ext/array.h +19 -0
  7. data/ext/bitvector.c +164 -0
  8. data/ext/bitvector.h +29 -0
  9. data/ext/compound_io.c +335 -0
  10. data/ext/document.c +336 -0
  11. data/ext/document.h +87 -0
  12. data/ext/ferret.c +88 -47
  13. data/ext/ferret.h +43 -109
  14. data/ext/field.c +395 -0
  15. data/ext/filter.c +103 -0
  16. data/ext/fs_store.c +352 -0
  17. data/ext/global.c +219 -0
  18. data/ext/global.h +73 -0
  19. data/ext/hash.c +446 -0
  20. data/ext/hash.h +80 -0
  21. data/ext/hashset.c +141 -0
  22. data/ext/hashset.h +37 -0
  23. data/ext/helper.c +11 -0
  24. data/ext/helper.h +5 -0
  25. data/ext/inc/lang.h +41 -0
  26. data/ext/ind.c +389 -0
  27. data/ext/index.h +884 -0
  28. data/ext/index_io.c +269 -415
  29. data/ext/index_rw.c +2543 -0
  30. data/ext/lang.c +31 -0
  31. data/ext/lang.h +41 -0
  32. data/ext/priorityqueue.c +228 -0
  33. data/ext/priorityqueue.h +44 -0
  34. data/ext/q_boolean.c +1331 -0
  35. data/ext/q_const_score.c +154 -0
  36. data/ext/q_fuzzy.c +287 -0
  37. data/ext/q_match_all.c +142 -0
  38. data/ext/q_multi_phrase.c +343 -0
  39. data/ext/q_parser.c +2180 -0
  40. data/ext/q_phrase.c +657 -0
  41. data/ext/q_prefix.c +75 -0
  42. data/ext/q_range.c +247 -0
  43. data/ext/q_span.c +1566 -0
  44. data/ext/q_term.c +308 -0
  45. data/ext/q_wildcard.c +146 -0
  46. data/ext/r_analysis.c +255 -0
  47. data/ext/r_doc.c +578 -0
  48. data/ext/r_index_io.c +996 -0
  49. data/ext/r_qparser.c +158 -0
  50. data/ext/r_search.c +2321 -0
  51. data/ext/r_store.c +263 -0
  52. data/ext/r_term.c +219 -0
  53. data/ext/ram_store.c +447 -0
  54. data/ext/search.c +524 -0
  55. data/ext/search.h +1065 -0
  56. data/ext/similarity.c +143 -39
  57. data/ext/sort.c +661 -0
  58. data/ext/store.c +35 -0
  59. data/ext/store.h +152 -0
  60. data/ext/term.c +704 -143
  61. data/ext/termdocs.c +599 -0
  62. data/ext/vector.c +594 -0
  63. data/lib/ferret.rb +9 -10
  64. data/lib/ferret/analysis/analyzers.rb +2 -2
  65. data/lib/ferret/analysis/standard_tokenizer.rb +1 -1
  66. data/lib/ferret/analysis/token.rb +14 -14
  67. data/lib/ferret/analysis/token_filters.rb +3 -3
  68. data/lib/ferret/document/field.rb +16 -17
  69. data/lib/ferret/index/document_writer.rb +4 -4
  70. data/lib/ferret/index/index.rb +39 -23
  71. data/lib/ferret/index/index_writer.rb +2 -2
  72. data/lib/ferret/index/multiple_term_doc_pos_enum.rb +1 -8
  73. data/lib/ferret/index/segment_term_vector.rb +4 -4
  74. data/lib/ferret/index/term.rb +5 -1
  75. data/lib/ferret/index/term_vector_offset_info.rb +6 -6
  76. data/lib/ferret/index/term_vectors_io.rb +5 -5
  77. data/lib/ferret/query_parser/query_parser.tab.rb +81 -77
  78. data/lib/ferret/search.rb +1 -1
  79. data/lib/ferret/search/boolean_query.rb +2 -1
  80. data/lib/ferret/search/field_sorted_hit_queue.rb +3 -3
  81. data/lib/ferret/search/fuzzy_query.rb +2 -1
  82. data/lib/ferret/search/index_searcher.rb +3 -0
  83. data/lib/ferret/search/{match_all_docs_query.rb → match_all_query.rb} +7 -7
  84. data/lib/ferret/search/multi_phrase_query.rb +6 -5
  85. data/lib/ferret/search/phrase_query.rb +3 -6
  86. data/lib/ferret/search/prefix_query.rb +4 -4
  87. data/lib/ferret/search/sort.rb +3 -1
  88. data/lib/ferret/search/sort_field.rb +9 -9
  89. data/lib/ferret/search/spans/near_spans_enum.rb +1 -1
  90. data/lib/ferret/search/spans/span_near_query.rb +1 -1
  91. data/lib/ferret/search/spans/span_weight.rb +1 -1
  92. data/lib/ferret/search/spans/spans_enum.rb +7 -7
  93. data/lib/ferret/store/fs_store.rb +10 -6
  94. data/lib/ferret/store/ram_store.rb +3 -3
  95. data/lib/rferret.rb +36 -0
  96. data/test/functional/thread_safety_index_test.rb +2 -2
  97. data/test/test_helper.rb +16 -2
  98. data/test/unit/analysis/c_token.rb +25 -0
  99. data/test/unit/analysis/tc_per_field_analyzer_wrapper.rb +1 -1
  100. data/test/unit/analysis/tc_standard_analyzer.rb +1 -1
  101. data/test/unit/document/{tc_document.rb → c_document.rb} +0 -0
  102. data/test/unit/document/c_field.rb +98 -0
  103. data/test/unit/document/tc_field.rb +0 -66
  104. data/test/unit/index/{tc_index.rb → c_index.rb} +62 -6
  105. data/test/unit/index/{tc_index_reader.rb → c_index_reader.rb} +51 -10
  106. data/test/unit/index/{tc_index_writer.rb → c_index_writer.rb} +0 -4
  107. data/test/unit/index/{tc_term.rb → c_term.rb} +1 -3
  108. data/test/unit/index/{tc_term_vector_offset_info.rb → c_term_voi.rb} +5 -5
  109. data/test/unit/index/tc_segment_term_vector.rb +2 -2
  110. data/test/unit/index/tc_term_vectors_io.rb +4 -4
  111. data/test/unit/query_parser/c_query_parser.rb +138 -0
  112. data/test/unit/search/{tc_filter.rb → c_filter.rb} +24 -24
  113. data/test/unit/search/{tc_fuzzy_query.rb → c_fuzzy_query.rb} +0 -0
  114. data/test/unit/search/{tc_index_searcher.rb → c_index_searcher.rb} +9 -26
  115. data/test/unit/search/{tc_search_and_sort.rb → c_search_and_sort.rb} +15 -15
  116. data/test/unit/search/{tc_sort.rb → c_sort.rb} +2 -1
  117. data/test/unit/search/c_sort_field.rb +27 -0
  118. data/test/unit/search/{tc_spans.rb → c_spans.rb} +0 -0
  119. data/test/unit/search/tc_sort_field.rb +7 -20
  120. data/test/unit/store/c_fs_store.rb +76 -0
  121. data/test/unit/store/c_ram_store.rb +35 -0
  122. data/test/unit/store/m_store.rb +34 -0
  123. data/test/unit/store/m_store_lock.rb +68 -0
  124. data/test/unit/store/tc_fs_store.rb +0 -53
  125. data/test/unit/store/tc_ram_store.rb +0 -20
  126. data/test/unit/store/tm_store.rb +0 -30
  127. data/test/unit/store/tm_store_lock.rb +0 -66
  128. metadata +84 -31
  129. data/ext/Makefile +0 -140
  130. data/ext/ferret_ext.so +0 -0
  131. data/ext/priority_queue.c +0 -232
  132. data/ext/ram_directory.c +0 -321
  133. data/ext/segment_merge_queue.c +0 -37
  134. data/ext/segment_term_enum.c +0 -326
  135. data/ext/string_helper.c +0 -42
  136. data/ext/tags +0 -344
  137. data/ext/term_buffer.c +0 -230
  138. data/ext/term_infos_reader.c +0 -54
  139. data/ext/terminfo.c +0 -160
  140. data/ext/token.c +0 -93
  141. 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 = MatchAllDocsQuery.new()
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 = MatchAllDocsQuery.new()
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 test_caching_wrapper_filter
92
- is = IndexSearcher.new(@dir)
93
- q = MatchAllDocsQuery.new()
94
- rf = RangeFilter.new("int", "2", "6", true, true)
95
- cf = CachingWrapperFilter.new(rf)
96
- #puts "about to test cache"
97
- do_test_top_docs(is, q, [2,3,4,5,6], cf)
98
- do_test_top_docs(is, q, [2,3,4,5,6], cf)
99
- #puts "finished_testing_cache"
100
- end
101
-
102
- def test_filtered_query
103
- is = IndexSearcher.new(@dir)
104
- q = MatchAllDocsQuery.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
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
@@ -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 |score_doc|
93
- expected << score_doc.doc
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 test_prefix_query()
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
- 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
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(3, s.fields.size)
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 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
- }
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