rroonga 2.0.4 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/Rakefile +21 -2
  2. data/bin/grndump +3 -2
  3. data/ext/groonga/extconf.rb +1 -6
  4. data/ext/groonga/rb-grn-array.c +58 -31
  5. data/ext/groonga/rb-grn-column.c +220 -148
  6. data/ext/groonga/rb-grn-context.c +46 -32
  7. data/ext/groonga/rb-grn-database.c +102 -90
  8. data/ext/groonga/rb-grn-double-array-trie.c +205 -163
  9. data/ext/groonga/rb-grn-encoding-support.c +2 -3
  10. data/ext/groonga/rb-grn-encoding.c +13 -8
  11. data/ext/groonga/rb-grn-exception.c +1 -1
  12. data/ext/groonga/rb-grn-expression.c +110 -133
  13. data/ext/groonga/rb-grn-fix-size-column.c +5 -4
  14. data/ext/groonga/rb-grn-geo-point.c +55 -0
  15. data/ext/groonga/rb-grn-hash.c +120 -82
  16. data/ext/groonga/rb-grn-index-column.c +66 -70
  17. data/ext/groonga/rb-grn-index-cursor.c +3 -0
  18. data/ext/groonga/rb-grn-logger.c +33 -51
  19. data/ext/groonga/rb-grn-object.c +2 -0
  20. data/ext/groonga/rb-grn-operator.c +1 -1
  21. data/ext/groonga/rb-grn-patricia-trie.c +287 -232
  22. data/ext/groonga/rb-grn-plugin.c +11 -14
  23. data/ext/groonga/rb-grn-snippet.c +37 -54
  24. data/ext/groonga/rb-grn-table-cursor-key-support.c +3 -3
  25. data/ext/groonga/rb-grn-table-cursor.c +8 -6
  26. data/ext/groonga/rb-grn-table-key-support.c +22 -29
  27. data/ext/groonga/rb-grn-table.c +355 -279
  28. data/ext/groonga/rb-grn-type.c +18 -25
  29. data/ext/groonga/rb-grn-utils.c +77 -7
  30. data/ext/groonga/rb-grn-variable-size-column.c +12 -20
  31. data/ext/groonga/rb-grn-view.c +56 -51
  32. data/ext/groonga/rb-grn.h +28 -1
  33. data/ext/groonga/rb-groonga.c +1 -0
  34. data/lib/groonga.rb +2 -0
  35. data/lib/groonga/command.rb +3 -1
  36. data/lib/groonga/database.rb +27 -0
  37. data/lib/groonga/dumper.rb +96 -17
  38. data/lib/groonga/geo-point.rb +216 -0
  39. data/lib/groonga/schema.rb +29 -46
  40. data/rroonga-build.rb +1 -1
  41. data/rroonga.gemspec +90 -0
  42. data/test/groonga-test-utils.rb +168 -0
  43. data/test/run-test.rb +60 -0
  44. data/test/test-accessor.rb +36 -0
  45. data/test/test-array.rb +146 -0
  46. data/test/test-column.rb +350 -0
  47. data/test/test-command-select.rb +181 -0
  48. data/test/test-context.rb +130 -0
  49. data/test/test-database-dumper.rb +259 -0
  50. data/test/test-database.rb +173 -0
  51. data/test/test-double-array-trie.rb +189 -0
  52. data/test/test-encoding.rb +33 -0
  53. data/test/test-exception.rb +230 -0
  54. data/test/test-expression-builder.rb +602 -0
  55. data/test/test-expression.rb +134 -0
  56. data/test/test-fix-size-column.rb +77 -0
  57. data/test/test-geo-point.rb +190 -0
  58. data/test/test-gqtp.rb +70 -0
  59. data/test/test-hash.rb +367 -0
  60. data/test/test-index-column.rb +180 -0
  61. data/test/test-index-cursor.rb +123 -0
  62. data/test/test-logger.rb +37 -0
  63. data/test/test-pagination.rb +249 -0
  64. data/test/test-patricia-trie.rb +440 -0
  65. data/test/test-plugin.rb +35 -0
  66. data/test/test-procedure.rb +37 -0
  67. data/test/test-query-log.rb +258 -0
  68. data/test/test-record.rb +577 -0
  69. data/test/test-remote.rb +63 -0
  70. data/test/test-schema-create-table.rb +267 -0
  71. data/test/test-schema-dumper.rb +235 -0
  72. data/test/test-schema-type.rb +208 -0
  73. data/test/test-schema-view.rb +90 -0
  74. data/test/test-schema.rb +886 -0
  75. data/test/test-snippet.rb +130 -0
  76. data/test/test-table-dumper.rb +353 -0
  77. data/test/test-table-offset-and-limit.rb +100 -0
  78. data/test/test-table-select-mecab.rb +80 -0
  79. data/test/test-table-select-normalize.rb +57 -0
  80. data/test/test-table-select-weight.rb +123 -0
  81. data/test/test-table-select.rb +191 -0
  82. data/test/test-table-traverse.rb +304 -0
  83. data/test/test-table.rb +711 -0
  84. data/test/test-type.rb +79 -0
  85. data/test/test-variable-size-column.rb +147 -0
  86. data/test/test-variable.rb +28 -0
  87. data/test/test-vector-column.rb +76 -0
  88. data/test/test-version.rb +61 -0
  89. data/test/test-view.rb +72 -0
  90. metadata +330 -202
@@ -0,0 +1,35 @@
1
+ # Copyright (C) 2011 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ class PluginTest < Test::Unit::TestCase
17
+ include GroongaTestUtils
18
+
19
+ setup :setup_sandbox
20
+ setup :setup_database
21
+ teardown :teardown_sandbox
22
+
23
+ def test_register
24
+ context = Groonga::Context.default
25
+ assert_nil(context["suggest"])
26
+ context.register_plugin("suggest/suggest")
27
+ assert_not_nil(context["suggest"])
28
+ end
29
+
30
+ def test_system_plugins_dir
31
+ suggest_plugin_path = "#{Groonga::Plugin.system_plugins_dir}/"
32
+ suggest_plugin_path << "suggest/suggest#{Groonga::Plugin.suffix}"
33
+ assert_send([File, :exist?, suggest_plugin_path])
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright (C) 2009 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ class ProcedureTest < Test::Unit::TestCase
17
+ include GroongaTestUtils
18
+
19
+ setup :setup_database
20
+
21
+ def test_builtins
22
+ assert_equal_procedure("TokenDelimit", Groonga::Procedure::DELIMIT)
23
+ assert_equal_procedure("TokenUnigram", Groonga::Procedure::UNIGRAM)
24
+ assert_equal_procedure("TokenBigram", Groonga::Procedure::BIGRAM)
25
+ assert_equal_procedure("TokenTrigram", Groonga::Procedure::TRIGRAM)
26
+ assert_equal_procedure("TokenMecab", Groonga::Procedure::MECAB,
27
+ :accept_nil => true)
28
+ end
29
+
30
+ private
31
+ def assert_equal_procedure(expected_name, id, options={})
32
+ procedure = Groonga::Context.default[id]
33
+ expected_name = nil if procedure.nil? and options[:accept_nil]
34
+ assert_equal(expected_name,
35
+ procedure ? procedure.name : procedure)
36
+ end
37
+ end
@@ -0,0 +1,258 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2011 Kouhei Sutou <kou@clear-code.com>
3
+ #
4
+ # This library is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU Lesser General Public
6
+ # License version 2.1 as published by the Free Software Foundation.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
+
17
+ require "cgi"
18
+
19
+ module QueryLogTest
20
+ module CommandParseTestUtils
21
+ private
22
+ def command(name, parameters)
23
+ Groonga::QueryLog::Command.new(name, parameters)
24
+ end
25
+
26
+ def parse_http_path(command, parameters)
27
+ path = "/d/#{command}.json"
28
+ unless parameters.empty?
29
+ uri_parameters = parameters.collect do |key, value|
30
+ [CGI.escape(key.to_s), CGI.escape(value.to_s)].join("=")
31
+ end
32
+ path << "?"
33
+ path << uri_parameters.join("&")
34
+ end
35
+ Groonga::QueryLog::Command.parse(path)
36
+ end
37
+
38
+ def parse_command_line(command, parameters)
39
+ command_line = "#{command} --output_type json"
40
+ parameters.each do |key, value|
41
+ if /"| / =~ value
42
+ escaped_value = '"' + value.gsub(/"/, '\"') + '"'
43
+ else
44
+ escaped_value = value
45
+ end
46
+ command_line << " --#{key} #{escaped_value}"
47
+ end
48
+ Groonga::QueryLog::Command.parse(command_line)
49
+ end
50
+ end
51
+
52
+ module HTTPCommandParseTestUtils
53
+ private
54
+ def parse(command, parameters={})
55
+ parse_http_path(command, parameters)
56
+ end
57
+ end
58
+
59
+ module CommandLineCommandParseTestUtils
60
+ private
61
+ def parse(command, parameters={})
62
+ parse_command_line(command, parameters)
63
+ end
64
+ end
65
+
66
+ module SelectCommandParseTests
67
+ include CommandParseTestUtils
68
+
69
+ def test_parameters
70
+ select = parse("select",
71
+ :table => "Users",
72
+ :filter => "age<=30")
73
+ assert_equal(command("select",
74
+ "table" => "Users",
75
+ "filter" => "age<=30",
76
+ "output_type" => "json"),
77
+ select)
78
+ end
79
+
80
+ def test_scorer
81
+ select = parse("select",
82
+ :table => "Users",
83
+ :filter => "age<=30",
84
+ :scorer => "_score = random()")
85
+ assert_equal("_score = random()", select.scorer)
86
+ end
87
+
88
+ def test_to_uri_format
89
+ select = parse("select",
90
+ :table => "Users",
91
+ :filter => "age<=30")
92
+ assert_equal("/d/select.json?filter=age%3C%3D30&table=Users",
93
+ select.to_uri_format)
94
+ end
95
+
96
+ def test_to_command_format
97
+ select = parse("select",
98
+ :table => "Users",
99
+ :filter => "age<=30")
100
+ assert_equal("select --filter \"age<=30\" " +
101
+ "--output_type \"json\" --table \"Users\"",
102
+ select.to_command_format)
103
+ end
104
+ end
105
+
106
+ module SelectCommandParseFilterTests
107
+ include CommandParseTestUtils
108
+
109
+ def test_parenthesis
110
+ filter = 'geo_in_rectangle(location,' +
111
+ '"35.73360x139.7394","62614x139.7714") && ' +
112
+ '((type == "たいやき" || type == "和菓子")) && ' +
113
+ 'keyword @ "たいやき" &! keyword @ "白" &! keyword @ "養殖"'
114
+ select = parse("select",
115
+ :table => "Users",
116
+ :filter => filter)
117
+ assert_equal(['geo_in_rectangle(location,' +
118
+ '"35.73360x139.7394","62614x139.7714")',
119
+ 'type == "たいやき"',
120
+ 'type == "和菓子"',
121
+ 'keyword @ "たいやき"',
122
+ 'keyword @ "白"',
123
+ 'keyword @ "養殖"'],
124
+ select.conditions)
125
+ end
126
+
127
+ def test_to_uri_format
128
+ filter = 'geo_in_rectangle(location,' +
129
+ '"35.73360x139.7394","62614x139.7714") && ' +
130
+ '((type == "たいやき" || type == "和菓子")) && ' +
131
+ 'keyword @ "たいやき" &! keyword @ "白" &! keyword @ "養殖"'
132
+ select = parse("select",
133
+ :table => "Users",
134
+ :filter => filter)
135
+ assert_equal("/d/select.json?filter=geo_in_rectangle%28location%2C" +
136
+ "%2235.73360x139.7394%22%2C%2262614x139.7714%22%29+" +
137
+ "%26%26+%28%28type+" +
138
+ "%3D%3D+%22%E3%81%9F%E3%81%84%E3%82%84%E3%81%8D%22+" +
139
+ "%7C%7C+type+%3D%3D+" +
140
+ "%22%E5%92%8C%E8%8F%93%E5%AD%90%22%29%29+" +
141
+ "%26%26+keyword+%40+" +
142
+ "%22%E3%81%9F%E3%81%84%E3%82%84%E3%81%8D%22+%26%21+" +
143
+ "keyword+%40+%22%E7%99%BD%22+%26%21+" +
144
+ "keyword+%40+%22%E9%A4%8A%E6%AE%96%22&table=Users",
145
+ select.to_uri_format)
146
+ end
147
+
148
+ def test_to_command_format
149
+ filter = 'geo_in_rectangle(location,' +
150
+ '"35.73360x139.7394","62614x139.7714") && ' +
151
+ '((type == "たいやき" || type == "和菓子")) && ' +
152
+ 'keyword @ "たいやき" &! keyword @ "白" &! keyword @ "養殖"'
153
+ select = parse("select",
154
+ :table => "Users",
155
+ :filter => filter)
156
+ assert_equal("select " +
157
+ "--filter " +
158
+ "\"geo_in_rectangle(location," +
159
+ "\\\"35.73360x139.7394\\\",\\\"62614x139.7714\\\") && " +
160
+ "((type == \\\"たいやき\\\" || " +
161
+ "type == \\\"和菓子\\\")) && " +
162
+ "keyword @ \\\"たいやき\\\" &! keyword @ \\\"白\\\" &! " +
163
+ "keyword @ \\\"養殖\\\"\" " +
164
+ "--output_type \"json\" --table \"Users\"",
165
+ select.to_command_format)
166
+ end
167
+ end
168
+
169
+ class HTTPSelectCommandParseTest < Test::Unit::TestCase
170
+ include SelectCommandParseTests
171
+ include SelectCommandParseFilterTests
172
+ include HTTPCommandParseTestUtils
173
+
174
+ def test_uri_format?
175
+ command = parse("status")
176
+ assert_predicate(command, :uri_format?)
177
+ end
178
+
179
+ def test_command_format?
180
+ command = parse("status")
181
+ assert_not_predicate(command, :command_format?)
182
+ end
183
+ end
184
+
185
+ class CommandLineSelecCommandParseTest < Test::Unit::TestCase
186
+ include SelectCommandParseTests
187
+ include SelectCommandParseFilterTests
188
+ include CommandLineCommandParseTestUtils
189
+
190
+ def test_uri_format?
191
+ command = parse("status")
192
+ assert_not_predicate(command, :uri_format?)
193
+ end
194
+
195
+ def test_command_format?
196
+ command = parse("status")
197
+ assert_predicate(command, :command_format?)
198
+ end
199
+ end
200
+
201
+ class StatisticOperationParseTest < Test::Unit::TestCase
202
+ def test_context
203
+ operations = statistics.first.operations.collect do |operation|
204
+ [operation[:name], operation[:context]]
205
+ end
206
+ expected = [
207
+ ["filter", "local_name @ \"gsub\""],
208
+ ["filter", "description @ \"string\""],
209
+ ["select", nil],
210
+ ["sort", "_score"],
211
+ ["output", "_key"],
212
+ ["drilldown", "name"],
213
+ ["drilldown", "class"],
214
+ ]
215
+ assert_equal(expected, operations)
216
+ end
217
+
218
+ def test_n_records
219
+ operations = statistics.first.operations.collect do |operation|
220
+ [operation[:name], operation[:n_records]]
221
+ end
222
+ expected = [
223
+ ["filter", 15],
224
+ ["filter", 13],
225
+ ["select", 13],
226
+ ["sort", 10],
227
+ ["output", 10],
228
+ ["drilldown", 3],
229
+ ["drilldown", 2],
230
+ ]
231
+ assert_equal(expected, operations)
232
+ end
233
+
234
+ private
235
+ def log
236
+ <<-EOL
237
+ 2011-06-02 16:27:04.731685|5091e5c0|>/d/select.join?table=Entries&filter=local_name+%40+%22gsub%22+%26%26+description+%40+%22string%22&sortby=_score&output_columns=_key&drilldown=name,class
238
+ 2011-06-02 16:27:04.733539|5091e5c0|:000000001849451 filter(15)
239
+ 2011-06-02 16:27:04.734978|5091e5c0|:000000003293459 filter(13)
240
+ 2011-06-02 16:27:04.735012|5091e5c0|:000000003327415 select(13)
241
+ 2011-06-02 16:27:04.735096|5091e5c0|:000000003411824 sort(10)
242
+ 2011-06-02 16:27:04.735232|5091e5c0|:000000003547265 output(10)
243
+ 2011-06-02 16:27:04.735606|5091e5c0|:000000003921419 drilldown(3)
244
+ 2011-06-02 16:27:04.735762|5091e5c0|:000000004077552 drilldown(2)
245
+ 2011-06-02 16:27:04.735808|5091e5c0|<000000004123726 rc=0
246
+ EOL
247
+ end
248
+
249
+ def statistics
250
+ statistics = []
251
+ parser = Groonga::QueryLog::Parser.new
252
+ parser.parse(StringIO.new(log)) do |statistic|
253
+ statistics << statistic
254
+ end
255
+ statistics
256
+ end
257
+ end
258
+ end
@@ -0,0 +1,577 @@
1
+ # Copyright (C) 2009-2012 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ class RecordTest < Test::Unit::TestCase
17
+ include GroongaTestUtils
18
+
19
+ def setup
20
+ setup_database
21
+
22
+ setup_addresses_table
23
+ setup_users_table
24
+ setup_bookmarks_table
25
+ setup_indexes
26
+ end
27
+
28
+ def setup_addresses_table
29
+ @addresses = Groonga::Array.create(:name => "Addresses")
30
+ @addresses.define_column("mail", "ShortText")
31
+ end
32
+
33
+ def setup_users_table
34
+ @users = Groonga::Hash.create(:name => "Users",
35
+ :key_type => "ShortText")
36
+ @users.define_column("addresses", @addresses, :type => "vector")
37
+ end
38
+
39
+ def setup_bookmarks_table
40
+ @bookmarks = Groonga::Array.create(:name => "Bookmarks",
41
+ :value_type => "Int32")
42
+ @bookmarks.define_column("uri", "ShortText")
43
+ @bookmarks.define_column("rate", "Int32")
44
+ @bookmarks.define_column("comment", "Text")
45
+ @bookmarks.define_column("content", "LongText")
46
+ @bookmarks.define_column("user", @users)
47
+ end
48
+
49
+ def setup_indexes
50
+ @bookmarks_index = Groonga::PatriciaTrie.create(:name => "BookmarksIndex")
51
+ @bookmarks_index.default_tokenizer = "TokenBigram"
52
+
53
+ @bookmarks_content_index =
54
+ @bookmarks_index.define_index_column("content", @bookmarks,
55
+ :with_section => true,
56
+ :with_weight => true,
57
+ :with_position => true,
58
+ :source => "Bookmarks.content")
59
+ @bookmarks_index.define_index_column("uri", @bookmarks,
60
+ :with_position => true,
61
+ :source => "Bookmarks.uri")
62
+ end
63
+
64
+ def test_column_accessor
65
+ groonga = @bookmarks.add
66
+
67
+ groonga["uri"] = "http://groonga.org/"
68
+ assert_equal("http://groonga.org/", groonga["uri"])
69
+
70
+ groonga["comment"] = "fulltext search engine"
71
+ assert_equal("fulltext search engine", groonga["comment"])
72
+ end
73
+
74
+ def test_have_column?
75
+ groonga = @bookmarks.add
76
+ assert_true(groonga.have_column?(:uri))
77
+ assert_false(groonga.have_column?(:nonexistent))
78
+ end
79
+
80
+ def test_have_column_id
81
+ groonga = @bookmarks.add
82
+ assert_true(groonga.have_column?(:_id))
83
+ end
84
+
85
+ def test_have_column_key_hash
86
+ mori = @users.add("mori")
87
+ assert_true(mori.have_column?(:_key))
88
+ end
89
+
90
+ def test_have_column_key_array_with_value_type
91
+ groonga = @bookmarks.add
92
+ assert_true(groonga.have_column?(:_key))
93
+ end
94
+
95
+ def test_have_column_key_array_without_value_type
96
+ groonga_ml = @addresses.add
97
+ assert_false(groonga_ml.have_column?(:_key))
98
+ end
99
+
100
+ def test_have_column_nsubrecs_existent
101
+ @users.add("mori")
102
+ bookmarks = @users.select do |record|
103
+ record.key == "mori"
104
+ end
105
+ assert_true(bookmarks.to_a.first.have_column?(:_nsubrecs))
106
+ end
107
+
108
+ def test_have_column_nsubrecs_nonexistent
109
+ groonga = @bookmarks.add
110
+ assert_false(groonga.have_column?(:_nsubrecs))
111
+ end
112
+
113
+ def test_get_nonexistent_column
114
+ groonga = @bookmarks.add
115
+ assert_raise(Groonga::NoSuchColumn) do
116
+ groonga["nonexistent"]
117
+ end
118
+ end
119
+
120
+ def test_set_nonexistent_column
121
+ groonga = @bookmarks.add
122
+ assert_raise(Groonga::NoSuchColumn) do
123
+ groonga["nonexistent"] = "value"
124
+ end
125
+ end
126
+
127
+ def test_set_object_id
128
+ groonga = @bookmarks.add
129
+ daijiro = @users.add("daijiro")
130
+ assert_nil(groonga["user"])
131
+ groonga["user"] = daijiro
132
+ assert_equal(daijiro, groonga["user"])
133
+ end
134
+
135
+ def test_set_nil
136
+ groonga = @bookmarks.add(:content => "groonga")
137
+ assert_equal("groonga", groonga["content"])
138
+ groonga["content"] = nil
139
+ assert_nil(groonga["content"])
140
+ end
141
+
142
+ def test_set_empty_string
143
+ groonga = @bookmarks.add(:content => "groonga")
144
+ assert_equal("groonga", groonga["content"])
145
+ groonga["content"] = ""
146
+ assert_nil(groonga["content"])
147
+ end
148
+
149
+ def test_set_nil_reference
150
+ groonga = @bookmarks.add(:user => "daijiro",
151
+ :uri => "http://groonga.org/")
152
+ groonga.user = nil
153
+ assert_nil(groonga.user)
154
+ end
155
+
156
+ def test_set_empty_key_reference
157
+ groonga = @bookmarks.add(:user => "daijiro",
158
+ :uri => "http://groonga.org/")
159
+ assert_equal(@users["daijiro"], groonga.user)
160
+ groonga["user"] = ""
161
+ assert_nil(groonga.user)
162
+ end
163
+
164
+ def test_set_string_to_integer_column
165
+ groonga = @bookmarks.add(:content => "groonga")
166
+ groonga.rate = "100"
167
+ assert_equal(100, groonga.rate)
168
+ end
169
+
170
+ def test_delete
171
+ bookmark_records = []
172
+ bookmark_records << @bookmarks.add
173
+ bookmark_records << @bookmarks.add
174
+ bookmark_records << @bookmarks.add
175
+
176
+ assert_equal(3, @bookmarks.size)
177
+ bookmark_records[1].delete
178
+ assert_equal(2, @bookmarks.size)
179
+ end
180
+
181
+ def test_key
182
+ documents = Groonga::PatriciaTrie.create(:name => "Documents",
183
+ :key_type => "ShortText")
184
+ reference = documents.add("reference")
185
+ assert_equal("reference", reference.key)
186
+ end
187
+
188
+ def test_value
189
+ bookmark = @bookmarks.add
190
+ assert_equal(0, bookmark.value)
191
+ bookmark.value = 100
192
+ assert_equal(100, bookmark.value)
193
+ end
194
+
195
+ def test_reference_column?
196
+ bookmark = @bookmarks.add
197
+ assert_false(bookmark.reference_column?("uri"))
198
+ assert_true(bookmark.reference_column?("user"))
199
+ end
200
+
201
+ def test_index_column?
202
+ bookmark = @bookmarks.add
203
+ assert_false(bookmark.index_column?("uri"))
204
+ index = @bookmarks_index.add("token")
205
+ assert_true(index.index_column?("content"))
206
+ end
207
+
208
+ def test_vector_column?
209
+ bookmark = @bookmarks.add
210
+ assert_false(bookmark.vector_column?("uri"))
211
+ morita = @users.add("morita")
212
+ assert_true(morita.vector_column?("addresses"))
213
+ end
214
+
215
+ def test_scalar_column?
216
+ bookmark = @bookmarks.add
217
+ assert_true(bookmark.scalar_column?("uri"))
218
+ morita = @users.add("morita")
219
+ assert_false(morita.scalar_column?("addresses"))
220
+ end
221
+
222
+ def test_score
223
+ groonga = @bookmarks.add
224
+ groonga["content"] = "full text search search search engine."
225
+
226
+ google = @bookmarks.add
227
+ google["content"] = "Web search engine."
228
+
229
+ results = @bookmarks_content_index.search("search")
230
+ assert_equal([[groonga.id, 3], [google.id, 1]],
231
+ results.collect do |record|
232
+ [record.id, record.score]
233
+ end)
234
+ end
235
+
236
+ def test_score=
237
+ groonga = @bookmarks.add
238
+ groonga["content"] = "full text search search search engine."
239
+
240
+ google = @bookmarks.add
241
+ google["content"] = "Web search engine."
242
+
243
+ results = @bookmarks_content_index.search("search")
244
+ results.each do |record|
245
+ record.score *= 10
246
+ end
247
+ assert_equal([[groonga.id, 30], [google.id, 10]],
248
+ results.collect do |record|
249
+ [record.id, record.score]
250
+ end)
251
+ end
252
+
253
+ def test_increment!
254
+ groonga = @bookmarks.add
255
+ assert_equal(0, groonga["rate"])
256
+ groonga.increment!("rate")
257
+ assert_equal(1, groonga["rate"])
258
+ groonga.increment!("rate", 2)
259
+ assert_equal(3, groonga["rate"])
260
+ groonga.increment!("rate", -2)
261
+ assert_equal(1, groonga["rate"])
262
+ end
263
+
264
+ def test_decrement!
265
+ groonga = @bookmarks.add
266
+ assert_equal(0, groonga["rate"])
267
+ groonga.decrement!("rate")
268
+ assert_equal(-1, groonga["rate"])
269
+ groonga.decrement!("rate", 2)
270
+ assert_equal(-3, groonga["rate"])
271
+ groonga.decrement!("rate", -2)
272
+ assert_equal(-1, groonga["rate"])
273
+ end
274
+
275
+ def test_lock
276
+ groonga = @bookmarks.add
277
+
278
+ assert_not_predicate(groonga, :locked?)
279
+ groonga.lock
280
+ assert_predicate(groonga, :locked?)
281
+ groonga.unlock
282
+ assert_not_predicate(groonga, :locked?)
283
+ end
284
+
285
+ def test_lock_failed
286
+ groonga = @bookmarks.add
287
+
288
+ groonga.lock
289
+ assert_raise(Groonga::ResourceDeadlockAvoided) do
290
+ groonga.lock
291
+ end
292
+ end
293
+
294
+ def test_lock_block
295
+ groonga = @bookmarks.add
296
+
297
+ assert_not_predicate(groonga, :locked?)
298
+ groonga.lock do
299
+ assert_predicate(groonga, :locked?)
300
+ end
301
+ assert_not_predicate(groonga, :locked?)
302
+ end
303
+
304
+ def test_clear_lock
305
+ groonga = @bookmarks.add
306
+
307
+ assert_not_predicate(groonga, :locked?)
308
+ groonga.lock
309
+ assert_predicate(groonga, :locked?)
310
+ groonga.clear_lock
311
+ assert_not_predicate(groonga, :locked?)
312
+ end
313
+
314
+ def test_attributes
315
+ values = {
316
+ "uri" => "http://groonga.org/",
317
+ "rate" => 5,
318
+ "comment" => "Great!"
319
+ }
320
+ groonga = @bookmarks.add(values)
321
+ assert_equal(values.merge("_id" => groonga.id,
322
+ "content" => nil,
323
+ "user" => nil),
324
+ groonga.attributes)
325
+ end
326
+
327
+ def test_recursive_attributes
328
+ need_self_recursive_equal
329
+
330
+ @bookmarks.define_column("next", @bookmarks)
331
+
332
+ top_page_record = @bookmarks.add(top_page)
333
+ doc_page_record = @bookmarks.add(doc_page)
334
+
335
+ top_page_record["next"] = doc_page_record
336
+ doc_page_record["next"] = top_page_record
337
+
338
+ expected = {
339
+ "_id" => 1,
340
+ "user" => nil,
341
+ "uri" => "http://groonga.org/",
342
+ "rate" => 5,
343
+ "next" => {
344
+ "_id" => 2,
345
+ "user" => nil,
346
+ "uri" => "http://groonga.org/document.html",
347
+ "rate" => 8,
348
+ "content" => nil,
349
+ "comment" => "Informative"
350
+ },
351
+ "content" => nil,
352
+ "comment" => "Great!"
353
+ }
354
+ expected["next"]["next"] = expected
355
+
356
+ assert_equal(expected, top_page_record.attributes)
357
+ end
358
+
359
+ def test_duplicate_records_attributes
360
+ need_self_recursive_equal
361
+
362
+ @bookmarks.define_column("next1", @bookmarks)
363
+ @bookmarks.define_column("next2", @bookmarks)
364
+
365
+ top_page_record = @bookmarks.add(top_page)
366
+ doc_page_record = @bookmarks.add(doc_page)
367
+
368
+ top_page_record["next1"] = doc_page_record
369
+ top_page_record["next2"] = doc_page_record
370
+ doc_page_record["next1"] = top_page_record
371
+
372
+ doc_page_attributes = {
373
+ "_id" => 2,
374
+ "user" => nil,
375
+ "uri" => "http://groonga.org/document.html",
376
+ "rate" => 8,
377
+ "content" => nil,
378
+ "comment" => "Informative",
379
+ "next2" => nil
380
+ }
381
+ top_page_attributes = {
382
+ "_id" => 1,
383
+ "user" => nil,
384
+ "uri" => "http://groonga.org/",
385
+ "rate" => 5,
386
+ "next1" => doc_page_attributes,
387
+ "next2" => doc_page_attributes,
388
+ "content" => nil,
389
+ "comment" => "Great!"
390
+ }
391
+ doc_page_attributes["next1"] = top_page_attributes
392
+
393
+ actual_records = top_page_record.attributes
394
+ assert_equal(top_page_attributes, actual_records)
395
+ assert_equal(actual_records["next1"].object_id,
396
+ actual_records["next2"].object_id)
397
+ end
398
+
399
+ def test_select_result_attributes
400
+ @bookmarks.add(top_page)
401
+ select_result = @bookmarks.select
402
+ select_result_result = select_result.first
403
+
404
+ expected_attributes = {
405
+ "_id" => 1,
406
+ "_key" => {
407
+ "comment" => "Great!",
408
+ "content" => nil,
409
+ "_id" => 1,
410
+ "rate" => 5,
411
+ "uri" => "http://groonga.org/",
412
+ "user" => nil
413
+ },
414
+ "_nsubrecs" => 1,
415
+ "_score" => 1,
416
+ }
417
+
418
+ assert_equal(expected_attributes, select_result_result.attributes)
419
+ end
420
+
421
+ def test_self_referencing_attributes
422
+ need_self_recursive_equal
423
+
424
+ @bookmarks.define_column("next", @bookmarks)
425
+
426
+ top_page_record = @bookmarks.add(top_page)
427
+ top_page_record["next"] = top_page_record
428
+
429
+ expected = {
430
+ "_id" => 1,
431
+ "user" => nil,
432
+ "uri" => "http://groonga.org/",
433
+ "rate" => 5,
434
+ "content" => nil,
435
+ "comment" => "Great!"
436
+ }
437
+ expected["next"] = expected
438
+
439
+ assert_equal(expected, top_page_record.attributes)
440
+ end
441
+
442
+ def test_vector_attributes
443
+ @bookmarks.define_column("related_bookmarks", @bookmarks, :type => :vector)
444
+
445
+ top_page_record = @bookmarks.add(top_page)
446
+ doc_page_record = @bookmarks.add(doc_page)
447
+ top_page_record["related_bookmarks"] = [doc_page_record]
448
+
449
+ expected = {
450
+ "_id" => 1,
451
+ "user" => nil,
452
+ "uri" => "http://groonga.org/",
453
+ "rate" => 5,
454
+ "related_bookmarks" => [
455
+ {
456
+ "_id" => 2,
457
+ "comment" => "Informative",
458
+ "content" => nil,
459
+ "rate" => 8,
460
+ "related_bookmarks" => [],
461
+ "uri" => "http://groonga.org/document.html",
462
+ "user" => nil,
463
+ }
464
+ ],
465
+ "content" => nil,
466
+ "comment" => "Great!"
467
+ }
468
+
469
+ assert_equal(expected, top_page_record.attributes)
470
+ end
471
+
472
+ def test_self_referencing_vector_attributes
473
+ need_self_recursive_equal
474
+
475
+ @bookmarks.define_column("related_bookmarks", @bookmarks, :type => :vector)
476
+
477
+ top_page_record = @bookmarks.add(top_page)
478
+ doc_page_record = @bookmarks.add(doc_page)
479
+ top_page_record["related_bookmarks"] = [
480
+ top_page_record,
481
+ doc_page_record
482
+ ]
483
+
484
+ top_page_attributes = {
485
+ "_id" => 1,
486
+ "user" => nil,
487
+ "uri" => "http://groonga.org/",
488
+ "rate" => 5,
489
+ "content" => nil,
490
+ "comment" => "Great!"
491
+ }
492
+ doc_page_attributes = {
493
+ "_id" => 2,
494
+ "comment" => "Informative",
495
+ "content" => nil,
496
+ "rate" => 8,
497
+ "related_bookmarks" => [],
498
+ "uri" => "http://groonga.org/document.html",
499
+ "user" => nil,
500
+ }
501
+ top_page_attributes["related_bookmarks"] = [
502
+ top_page_attributes,
503
+ doc_page_attributes
504
+ ]
505
+ assert_equal(top_page_attributes, top_page_record.attributes)
506
+ end
507
+
508
+ def test_dynamic_accessor
509
+ groonga = @bookmarks.add
510
+ assert_equal([],
511
+ ["uri", "uri="] - groonga.methods.collect {|name| name.to_s})
512
+ assert_equal([true, true],
513
+ [groonga.respond_to?(:uri),
514
+ groonga.respond_to?(:uri=)])
515
+ groonga.uri = "http://groonga.org/"
516
+ assert_equal("http://groonga.org/", groonga.uri)
517
+ end
518
+
519
+ def test_method_chain
520
+ morita = @users.add("morita")
521
+ groonga = @bookmarks.add(:user => morita, :uri => "http://groonga.org")
522
+ assert_equal("morita", groonga.user.key)
523
+ end
524
+
525
+ def test_support_sub_records
526
+ morita = @users.add("morita")
527
+ assert_not_predicate(morita, :support_sub_records?)
528
+ users = @users.select {|record| record.key == "morita"}
529
+ assert_predicate(users.to_a[0], :support_sub_records?)
530
+ end
531
+
532
+ def test_set_record_like_object
533
+ kou_at_clear_code = @addresses.add(:mail => "kou@clear-code.com")
534
+ record_like_class = Class.new do
535
+ attr_reader :record_raw_id
536
+ def initialize(record_raw_id)
537
+ @record_raw_id = record_raw_id
538
+ end
539
+ end
540
+ record_like_object = record_like_class.new(kou_at_clear_code.record_raw_id)
541
+ kou = @users.add("kou")
542
+ kou.addresses = [record_like_object]
543
+ end
544
+
545
+ def test_set_array_like_records
546
+ kou_at_clear_code = @addresses.add(:mail => "kou@clear-code.com")
547
+ array_like_class = Class.new do
548
+ def initialize(records)
549
+ @records = records
550
+ end
551
+
552
+ def to_ary
553
+ @records
554
+ end
555
+ end
556
+ array_like_object = array_like_class.new([kou_at_clear_code])
557
+ kou = @users.add("kou")
558
+ kou.addresses = array_like_object
559
+ end
560
+
561
+ private
562
+ def top_page
563
+ {
564
+ "uri" => "http://groonga.org/",
565
+ "rate" => 5,
566
+ "comment" => "Great!",
567
+ }
568
+ end
569
+
570
+ def doc_page
571
+ {
572
+ "uri" => "http://groonga.org/document.html",
573
+ "rate" => 8,
574
+ "comment" => "Informative"
575
+ }
576
+ end
577
+ end