groonga-client 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -27,8 +27,9 @@ module Groonga
27
27
 
28
28
  Response.register("column_list", self)
29
29
 
30
- def initialize(header, body)
31
- super(header, parse_body(body))
30
+ def body=(body)
31
+ super(body)
32
+ parse_body(body)
32
33
  end
33
34
 
34
35
  def each
@@ -1,3 +1,20 @@
1
+ # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
2
+ # Copyright (C) 2013 Kosuke Asami
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 as published by the Free Software Foundation; either
7
+ # version 2.1 of the License, or (at your option) any later version.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
+
1
18
  require "groonga/client/response/base"
2
19
 
3
20
  module Groonga
@@ -6,32 +23,45 @@ module Groonga
6
23
  class Select < Base
7
24
  Response.register("select", self)
8
25
 
9
- attr_accessor :records, :n_records
26
+ # @return [Integer] The number of records that match againt
27
+ # a search condition.
28
+ attr_accessor :n_hits
29
+ attr_accessor :records
10
30
  attr_accessor :drilldowns
11
31
 
12
- def initialize(header, body)
13
- super(header, parse_body(body))
32
+ def body=(body)
33
+ super(body)
34
+ parse_body(body)
14
35
  end
15
36
 
16
37
  private
17
38
  def parse_body(body)
18
- @n_records, @records = parse_match_records(body.first)
39
+ @n_hits, @records = parse_match_records(body.first)
19
40
  @drilldowns = parse_drilldowns(body[1..-1])
20
41
  body
21
42
  end
22
43
 
23
44
  def parse_result(raw_result)
24
- n_items = raw_result.first.first
45
+ n_hits = raw_result.first.first
25
46
  properties = raw_result[1]
26
- infos = raw_result[2..-1]
47
+ infos = raw_result[2..-1] || []
27
48
  items = infos.collect do |info|
28
49
  item = {}
29
- properties.each_with_index do |(name, _), i|
30
- item[name] = info[i]
50
+ properties.each_with_index do |(name, type), i|
51
+ item[name] = convert_value(info[i], type)
31
52
  end
32
53
  item
33
- end if infos
34
- [n_items, items]
54
+ end
55
+ [n_hits, items]
56
+ end
57
+
58
+ def convert_value(value, type)
59
+ case type
60
+ when "Time"
61
+ Time.at(value)
62
+ else
63
+ value
64
+ end
35
65
  end
36
66
 
37
67
  def parse_match_records(raw_records)
@@ -39,13 +69,15 @@ module Groonga
39
69
  end
40
70
 
41
71
  def parse_drilldowns(raw_drilldowns)
42
- raw_drilldowns.collect do |raw_drilldown|
72
+ (raw_drilldowns || []).collect.with_index do |raw_drilldown, i|
73
+ key = @command.drilldowns[i]
43
74
  n_hits, items = parse_result(raw_drilldown)
44
- Drilldown.new(n_hits, items)
45
- end if raw_drilldowns
75
+ Drilldown.new(key, n_hits, items)
76
+ end
46
77
  end
47
78
 
48
- Drilldown = Struct.new(:n_hits, :items)
79
+ class Drilldown < Struct.new(:key, :n_hits, :items)
80
+ end
49
81
  end
50
82
  end
51
83
  end
@@ -0,0 +1,12 @@
1
+ require "groonga/client/response/base"
2
+
3
+ module Groonga
4
+ class Client
5
+ module Response
6
+ class TableCreate < Base
7
+ Response.register("table_create", self)
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -27,8 +27,9 @@ module Groonga
27
27
 
28
28
  Response.register("table_list", self)
29
29
 
30
- def initialize(header, body)
31
- super(header, parse_body(body))
30
+ def body=(body)
31
+ super(body)
32
+ parse_body(body)
32
33
  end
33
34
 
34
35
  def each
@@ -1,5 +1,5 @@
1
1
  module Groonga
2
2
  class Client
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
@@ -0,0 +1,105 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+
19
+ require "socket"
20
+
21
+ require "groonga/client/connection/gqtp"
22
+
23
+ class TestConnectionGQTP < Test::Unit::TestCase
24
+ def setup
25
+ setup_server
26
+ setup_connection
27
+ end
28
+
29
+ def teardown
30
+ teardown_connection
31
+ teardown_server
32
+ end
33
+
34
+ def setup_server
35
+ @address = "127.0.0.1"
36
+ @server = TCPServer.new(@address, 0)
37
+ @port = @server.addr[1]
38
+ @protocol = :gqtp
39
+
40
+ @thread = Thread.new do
41
+ client = @server.accept
42
+ @server.close
43
+
44
+ process_client_close(client)
45
+
46
+ client.close
47
+ end
48
+ end
49
+
50
+ def teardown_server
51
+ @thread.kill
52
+ end
53
+
54
+ def setup_connection
55
+ @connection = nil
56
+ end
57
+
58
+ def teardown_connection
59
+ @connection.close {} if @connection
60
+ end
61
+
62
+ private
63
+ def connect(options={})
64
+ default_options = {
65
+ :host => @address,
66
+ :port => @port,
67
+ }
68
+ Groonga::Client::Connection::GQTP.new(default_options.merge(options))
69
+ end
70
+
71
+ def process_client_close(client)
72
+ response_body = [].to_json
73
+ 2.times do
74
+ header = GQTP::Header.parse(client.read(GQTP::Header.size))
75
+ client.read(header.size)
76
+
77
+ response_header = GQTP::Header.new
78
+ response_header.size = response_body.bytesize
79
+
80
+ client.write(response_header.pack)
81
+ client.write(response_body)
82
+ end
83
+ end
84
+
85
+ class TestConnected < self
86
+ def test_opened
87
+ @connection = connect
88
+ assert_true(@connection.connected?)
89
+ end
90
+
91
+ def test_closed
92
+ @connection = connect
93
+ @connection.close
94
+ assert_false(@connection.connected?)
95
+ end
96
+ end
97
+
98
+ class TestClose < self
99
+ def test_twice
100
+ @connection = connect
101
+ @connection.close
102
+ assert_false(@connection.close)
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,97 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+
19
+ require "socket"
20
+
21
+ require "groonga/client/connection/http"
22
+
23
+ class TestConnectionHTTP < Test::Unit::TestCase
24
+ def setup
25
+ setup_server
26
+ setup_connection
27
+ end
28
+
29
+ def teardown
30
+ teardown_connection
31
+ teardown_server
32
+ end
33
+
34
+ def setup_server
35
+ @address = "127.0.0.1"
36
+ @server = TCPServer.new(@address, 0)
37
+ @port = @server.addr[1]
38
+ @protocol = :http
39
+
40
+ @response_body = nil
41
+ @thread = Thread.new do
42
+ client = @server.accept
43
+ @server.close
44
+
45
+ status = 0
46
+ start = Time.now.to_f
47
+ elapsed = rand
48
+ header = "[#{status},#{start},#{elapsed}]"
49
+ body = "[#{header},#{@response_body}]"
50
+
51
+ http_header = <<-EOH
52
+ HTTP/1.1 200 OK
53
+ Connection: close
54
+ Content-Type: application/json
55
+ Content-Length: #{body.bytesize}
56
+
57
+ EOH
58
+
59
+ client.write(http_header)
60
+ client.write(body)
61
+ client.close
62
+ end
63
+ end
64
+
65
+ def teardown_server
66
+ @thread.kill
67
+ end
68
+
69
+ def setup_connection
70
+ @connection = nil
71
+ end
72
+
73
+ def teardown_connection
74
+ @connection.close if @connection
75
+ end
76
+
77
+ def connect(options={})
78
+ default_options = {
79
+ :host => @address,
80
+ :port => @port,
81
+ }
82
+ Groonga::Client::Connection::HTTP.new(default_options.merge(options))
83
+ end
84
+
85
+ def test_connected?
86
+ @connection = connect
87
+ assert_false(@connection.connected?)
88
+ end
89
+
90
+ class TestClose < self
91
+ def test_twice
92
+ @connection = connect
93
+ assert_false(@connection.close)
94
+ assert_false(@connection.close)
95
+ end
96
+ end
97
+ end
@@ -1,4 +1,8 @@
1
1
  module TestResponseHelper
2
+ def parse_raw_response(command_name, raw_response)
3
+ make_command(command_name).send(:parse_raw_response, raw_response)
4
+ end
5
+
2
6
  def make_command(command_name, parameters = {})
3
7
  command_class = Groonga::Command.find(command_name)
4
8
  command = command_class.new(command_name, parameters)
@@ -1,5 +1,3 @@
1
- require "test/unit/rr"
2
-
3
1
  require "response/helper"
4
2
 
5
3
  class TestResponseColumnList < Test::Unit::TestCase
@@ -9,16 +7,9 @@ class TestResponseColumnList < Test::Unit::TestCase
9
7
  header = [0,1372430096.70991,0.000522851943969727]
10
8
  body = [[["id","UInt32"],["name","ShortText"],["path","ShortText"],["type","ShortText"],["flags","ShortText"],["domain","ShortText"],["range","ShortText"],["source","ShortText"]],
11
9
  [256,"Text","/tmp/test.db.0000100","var","COLUMN_SCALAR|PERSISTENT","TestTable","ShortText",[]]]
10
+ raw_response = [header, body].to_json
12
11
 
13
- connection = Object.new
14
- stub(connection).send.with_any_args.yields([header, body].to_json) do
15
- request = Object.new
16
- stub(request).wait do
17
- true
18
- end
19
- end
20
-
21
- response = make_command("column_list").execute(connection)
12
+ response = parse_raw_response("column_list", raw_response)
22
13
  assert_equal(Groonga::Client::Response::ColumnList, response.class)
23
14
  end
24
15
  end
@@ -1,23 +1,138 @@
1
- require "test/unit/rr"
1
+ # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
2
+ # Copyright (C) 2013 Kosuke Asami
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 as published by the Free Software Foundation; either
7
+ # version 2.1 of the License, or (at your option) any later version.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2
17
 
3
18
  require "response/helper"
4
19
 
5
20
  class TestResponseSelect < Test::Unit::TestCase
6
- include TestResponseHelper
21
+ class TestParseRawResponse < self
22
+ include TestResponseHelper
7
23
 
8
- def test_select
9
- header = [0,1372430096.70991,0.000522851943969727]
10
- body = [[[1], [["_id", "UInt32"]], [1]]]
24
+ def test_select
25
+ header = [0,1372430096.70991,0.000522851943969727]
26
+ body = [[[1], [["_id", "UInt32"]], [1]]]
27
+ raw_response = [header, body].to_json
11
28
 
12
- connection = Object.new
13
- stub(connection).send.with_any_args.yields([header, body].to_json) do
14
- request = Object.new
15
- stub(request).wait do
16
- true
29
+ response = parse_raw_response("select", raw_response)
30
+ assert_equal(Groonga::Client::Response::Select, response.class)
31
+ end
32
+ end
33
+
34
+ class TestBody < self
35
+ def setup
36
+ @command = Groonga::Command::Select.new("select", {})
37
+ end
38
+
39
+ def test_n_hits
40
+ response = create_response([[[29], [["_id", "UInt32"]]]])
41
+ assert_equal(29, response.n_hits)
42
+ end
43
+
44
+ private
45
+ def create_response(body)
46
+ header = [0, 1372430096.70991, 0.000522851943969727]
47
+ Groonga::Client::Response::Select.new(@command, header, body)
48
+ end
49
+
50
+ class TestRecords < self
51
+ def test_time
52
+ updated_at = 1379040474
53
+ assert_equal([{"updated_at" => Time.at(updated_at)}],
54
+ records([[[1], [["updated_at", "Time"]], [updated_at]]]))
55
+ end
56
+
57
+ private
58
+ def records(body)
59
+ create_response(body).records
17
60
  end
18
61
  end
19
62
 
20
- response = make_command("select").execute(connection)
21
- assert_equal(Groonga::Client::Response::Select, response.class)
63
+ class TestDrilldowns < self
64
+ def setup
65
+ pair_arguments = {
66
+ "drilldown" => "_key",
67
+ "drilldown_output_columns" => "_key,_nsubrecs",
68
+ }
69
+ @command = Groonga::Command::Select.new("select", pair_arguments)
70
+ end
71
+
72
+ def test_key
73
+ body = [
74
+ [[0], []],
75
+ [
76
+ [29],
77
+ [
78
+ ["_key", "ShortText"],
79
+ ["_nsubrecs", "Int32"],
80
+ ],
81
+ ["groonga", 29],
82
+ ["Ruby", 19],
83
+ ["rroonga", 9],
84
+ ],
85
+ ]
86
+ assert_equal(["_key"],
87
+ drilldowns(body).collect(&:key))
88
+ end
89
+
90
+ def test_n_hits
91
+ body = [
92
+ [[0], []],
93
+ [
94
+ [29],
95
+ [
96
+ ["_key", "ShortText"],
97
+ ["_nsubrecs", "Int32"],
98
+ ],
99
+ ["groonga", 29],
100
+ ["Ruby", 19],
101
+ ["rroonga", 9],
102
+ ],
103
+ ]
104
+ assert_equal([29],
105
+ drilldowns(body).collect(&:n_hits))
106
+ end
107
+
108
+ def test_items
109
+ body = [
110
+ [[0], []],
111
+ [
112
+ [29],
113
+ [
114
+ ["_key", "ShortText"],
115
+ ["_nsubrecs", "Int32"],
116
+ ],
117
+ ["groonga", 29],
118
+ ["Ruby", 19],
119
+ ["rroonga", 9],
120
+ ],
121
+ ]
122
+ assert_equal([
123
+ [
124
+ {"_key" => "groonga", "_nsubrecs" => 29},
125
+ {"_key" => "Ruby", "_nsubrecs" => 19},
126
+ {"_key" => "rroonga", "_nsubrecs" => 9},
127
+ ],
128
+ ],
129
+ drilldowns(body).collect(&:items))
130
+ end
131
+
132
+ private
133
+ def drilldowns(body)
134
+ create_response(body).drilldowns
135
+ end
136
+ end
22
137
  end
23
138
  end