drnbench 1.0.2 → 1.0.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bc7f61f1275e4e48a15492d197552728429a7272
4
- data.tar.gz: fa6bd343d6a874c165dd95ae77bdc1ca7df730b1
3
+ metadata.gz: 3b10736f18dbeaf958fe4b9bd29c0a6788b69f3c
4
+ data.tar.gz: bc4363d42fd30a955a70f4d2241052486e121635
5
5
  SHA512:
6
- metadata.gz: 226d64e8c67139749313e265c3c6be5ac369b2c03f38dfc269dc2f9a105d682aad9830639e86ebef914306027fbf9ae64001773d4058983a14a307a101b352be
7
- data.tar.gz: a97fea6987677e63f4f6511148cec0c30b98646042d5603c9dc61c10cf81325c117cea3ac5f82b794916ef69a6cc7309276fc90657cc7ce60f5b09d71f8b88ae
6
+ metadata.gz: c7d68baea7789ca3a4a803fa7a4b5d2ff3c24252a7cf49c89d0f33a5eb598f9c0f064dc64c6eb35251abe6a0de4fe910d554e562a5151e18eb00d43973e3ea37
7
+ data.tar.gz: 4dad01b34e627c89618827e67f2f070c6cdb229f208d65214361b76477b6d91b10f6be69bf62ed2695078356341714f64fd4007277e674a8f8f8f3a0f4d8f527
data/README.md CHANGED
@@ -7,7 +7,7 @@ Drnbench is a benchmark tool for Droonga.
7
7
  It may be used for other HTTP servers.
8
8
 
9
9
  Drnbench provides features to send multiple random requests with different settings periodically.
10
- Number of clients (requests) in each period will be automatically increased gradually.
10
+ Number of clients (requests) in each period will be automatically increased progressively.
11
11
  So you'll be able to guess the limit performance of the throughput of a server, via the report like following:
12
12
 
13
13
  n_clients,total_n_requests,queries_per_second,min_elapsed_time,max_elapsed_time,average_elapsed_time,200
@@ -35,39 +35,7 @@ In this scenario, you have to do:
35
35
 
36
36
  Drnbench will start multiple clients and send many requests based on the patterns file.
37
37
 
38
- 1. Create a patterns file in the format:
39
-
40
- {
41
- "(pattern type 1 name)": {
42
- "frequency": (appearance ratio in all requests),
43
- "path": "(path to the endpoint)",
44
- "method": "(HTTP method)",
45
- "patterns": [
46
- { "body": (request body 1 sent by POST method) },
47
- { "body": (request body 2 sent by POST method) },
48
- ...
49
- ]
50
- }
51
- "(patterns type 2 name)": {
52
- "frequency": (appearance ratio in all requests),
53
- "patterns": [
54
- {
55
- "path": "(path to the endpoint 1)",
56
- "method": "(HTTP method)",
57
- "body": (request body 1 sent by POST method)
58
- },
59
- {
60
- "path": "(path to the endpoint 2)",
61
- "method": "(HTTP method)",
62
- "body": (request body 2 sent by POST method)
63
- },
64
- ...
65
- ]
66
- },
67
- ...
68
- }
69
-
70
- For example, a file "patterns.json" like:
38
+ 1. Create a patterns file "patterns.json", like:
71
39
 
72
40
  {
73
41
  "user search": {
@@ -108,6 +76,81 @@ Drnbench will start multiple clients and send many requests based on the pattern
108
76
 
109
77
  4. You'll get a report.
110
78
 
79
+ #### Detailed format of the patterns file
80
+
81
+ ##### Abstract
82
+
83
+ Abstract type A, grouped patterns with names:
84
+
85
+ ~~~
86
+ {
87
+ "group name 1": (patterns group),
88
+ "group name 2": (patterns group),
89
+ ...
90
+ }
91
+ ~~~
92
+
93
+ Abstract type B, grouped patterns without names:
94
+
95
+ ~~~
96
+ [
97
+ (patterns group),
98
+ (patterns group),
99
+ ...
100
+ ]
101
+ ~~~
102
+
103
+ Abstract type C, non-grouped patterns:
104
+
105
+ ~~~
106
+ (patterns group)
107
+ ~~~
108
+
109
+ ##### Patterns group
110
+
111
+ Patterns group type A, without options:
112
+
113
+ ~~~
114
+ [
115
+ (pattern1),
116
+ (pattern2),
117
+ ...
118
+ ]
119
+ ~~~
120
+
121
+ Patterns group type B, with options:
122
+
123
+ ~~~
124
+ {
125
+ "frequency": (appearance ratio in all requests, optional),
126
+ "path": "(path to the endpoint, optional)",
127
+ "method": "(HTTP method, optional)",
128
+ "patterns": [
129
+ (pattern1),
130
+ (pattern2),
131
+ ...
132
+ ]
133
+ }
134
+ ~~~
135
+
136
+ ##### Pattern
137
+
138
+ Pattern type A, simple path string:
139
+
140
+ ~~~
141
+ "/path/to/the/API/or/page"
142
+ ~~~
143
+
144
+ Pattern B, detailed object:
145
+
146
+ ~~~
147
+ {
148
+ "path": "/path/to/the/API/or/page",
149
+ "method": "(HTTP method)",
150
+ "body": (request body sent by POST method)
151
+ }
152
+ ~~~
153
+
111
154
 
112
155
  ### Benchmarking of request-responsne style commands, with a Droonga-based search system
113
156
 
data/Rakefile CHANGED
@@ -15,6 +15,8 @@
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
+ task :default => :test
19
+
18
20
  require "bundler/gem_helper"
19
21
  require "packnga"
20
22
 
@@ -31,3 +33,8 @@ Packnga::DocumentTask.new(spec) do |task|
31
33
  task.original_language = "en"
32
34
  task.translate_languages = ["ja"]
33
35
  end
36
+
37
+ desc "Run tests"
38
+ task :test do
39
+ ruby("test/run-test.rb")
40
+ end
@@ -19,38 +19,50 @@ require "drnbench"
19
19
  require "ostruct"
20
20
  require "optparse"
21
21
  require "json"
22
+ require "cgi"
22
23
 
23
24
  options = OpenStruct.new
24
25
  options.column_index = 0
26
+ options.escape = false
25
27
 
26
28
  option_parser = OptionParser.new do |parser|
27
29
  parser.version = Drnbench::VERSION
28
30
 
29
31
  parser.on("--column-index=INDEX", Integer,
30
32
  "Index number of the column to be extracted.",
31
- "(#{options.output_column_index})") do |index|
33
+ "(#{options.column_index})") do |index|
32
34
  options.column_index = index
33
35
  end
36
+ parser.on("--escape",
37
+ "Escape output for URL parameter") do
38
+ options.escape = true
39
+ end
34
40
  end
35
41
 
36
42
  groonga_select_result_files = option_parser.parse!(ARGV)
37
43
 
38
- def output_column_value(select_result, column_index)
44
+ def escape_for_param(value)
45
+ CGI.escape(value.to_s)
46
+ end
47
+
48
+ def output_column_value(select_result, options)
39
49
  select_result = JSON.parse(select_result)
40
50
  body = select_result[1]
41
51
  search_result = body.first
42
52
  records = search_result[2..-1]
43
53
  records.each do |record|
44
- puts record[column_index]
54
+ value = record[options.column_index]
55
+ value = escape_for_param(value) if options.escape
56
+ puts(value)
45
57
  end
46
58
  end
47
59
 
48
60
  if groonga_select_result_files.empty?
49
- output_column_value($stdin.read, options.column_index)
61
+ output_column_value($stdin.read, options)
50
62
  else
51
63
  groonga_select_result_files.each do |select_result_file|
52
64
  File.open(select_result_file) do |input|
53
- output_column_value(input.read, options.column_index)
65
+ output_column_value(input.read, options)
54
66
  end
55
67
  end
56
68
  end
@@ -94,7 +94,7 @@ args = option_parser.parse!(ARGV)
94
94
 
95
95
  config.validate
96
96
 
97
- runner = Drnbench::PublishSubscribe::GradualRunner.new(config)
97
+ runner = Drnbench::PublishSubscribe::ProgressiveRunner.new(config)
98
98
  runner.run
99
99
 
100
100
  File.open(config.output_path, "w") do |file|
@@ -23,70 +23,97 @@ config = Drnbench::RequestResponse::Configuration.new
23
23
  option_parser = OptionParser.new do |parser|
24
24
  parser.version = Drnbench::VERSION
25
25
 
26
+ parser.separator("")
26
27
  parser.on("--duration=SECONDS", Float,
27
- "duration of the benmark") do |duration|
28
+ "Duration of each benchmark.",
29
+ "(#{config.duration})") do |duration|
28
30
  config.duration = duration
29
31
  end
30
32
  parser.on("--wait=SECONDS", Float,
31
- "wait for each request") do |wait|
33
+ "Interval of each request sent by a client.",
34
+ "(#{config.wait})") do |wait|
32
35
  config.wait = wait
33
36
  end
37
+ parser.on("--n-slow-requests=N", Integer,
38
+ "Number of slow requests to be reported.",
39
+ "(#{config.n_slow_requests})") do |n_slow_requests|
40
+ config.n_slow_requests = n_slow_requests
41
+ end
42
+
43
+ parser.separator("")
44
+ parser.separator("Progressive benchmark:")
34
45
  parser.on("--interval=SECONDS", Float,
35
- "interval for each gradual case") do |interval|
46
+ "Interval between each benchmark.",
47
+ "(#{config.interval})") do |interval|
36
48
  config.interval = interval
37
49
  end
38
50
  parser.on("--start-n-clients=N", Integer,
39
- "initial number of clients (optional)") do |n_clients|
51
+ "Initial number of clients.",
52
+ "(#{config.start_n_clients})") do |n_clients|
40
53
  config.start_n_clients = n_clients
41
54
  end
42
55
  parser.on("--end-n-clients=N", Integer,
43
- "final number of clients (optional)") do |n_clients|
56
+ "Maximum number of clients.",
57
+ "(#{config.end_n_clients})") do |n_clients|
44
58
  config.end_n_clients = n_clients
45
59
  end
46
60
  parser.on("--step=COUNT", Integer,
47
- "step to increase number of clients (optional)") do |step|
61
+ "Number of clients increased on each",
62
+ "progress.",
63
+ "(#{config.step})") do |step|
48
64
  config.step = step
49
65
  end
50
- parser.on("--n-slow-requests=N", Integer,
51
- "number of reporting slow requests (optional)") do |n_slow_requests|
52
- config.n_slow_requests = n_slow_requests
53
- end
54
66
 
67
+ parser.separator("")
68
+ parser.separator("Request:")
55
69
  parser.on("--mode=MODE", String,
56
- "mode of benchmark (optional)",
70
+ "Request mode.",
57
71
  "available modes:",
58
- " http",
72
+ " http (default)",
59
73
  " http-droonga-search") do |mode|
60
74
  config.mode = mode.gsub(/-/, "_")
61
75
  end
62
76
  parser.on("--request-patterns-file=PATH",
63
- "path to request patterns JSON file") do |path|
77
+ "Path to request patterns file.") do |path|
64
78
  config.request_patterns_file = File.expand_path(path)
65
79
  end
66
80
 
67
- parser.on("--default-host=HOST", String,
68
- "default host name (optional)") do |host|
69
- config.default_host = host
81
+ parser.on("--default-hosts=HOST1,HOST2,...", Array,
82
+ "Default host names for each request.",
83
+ "(#{config.default_hosts.join(",")})") do |hosts|
84
+ config.default_hosts = hosts
70
85
  end
71
86
  parser.on("--default-port=PORT", Integer,
72
- "default port number (optional)") do |port|
87
+ "Default port number for each request.",
88
+ "(#{config.default_port})") do |port|
73
89
  config.default_port = port
74
90
  end
75
91
  parser.on("--default-path=PATH", String,
76
- "default path (optional)") do |path|
92
+ "Default path for each request",
93
+ "(#{config.default_path})") do |path|
77
94
  config.default_path = path
78
95
  end
79
96
  parser.on("--default-method=METHOD", String,
80
- "default HTTP method (optional)") do |method|
97
+ "Default HTTP method for each request.",
98
+ "(#{config.default_method})") do |method|
81
99
  config.default_method = method
82
100
  end
83
101
  parser.on("--default-timeout=SECONDS", Float,
84
- "default timeout (optional)") do |timeout|
102
+ "Default timeout for each request.",
103
+ "(#{config.default_timeout})") do |timeout|
85
104
  config.default_timeout = timeout
86
105
  end
106
+ parser.on("--default-host=HOST1,HOST2,...", Array,
107
+ "An alias to \"--default-hosts\"",
108
+ "for backward compatibility.") do |hosts|
109
+ config.default_hosts = hosts
110
+ end
87
111
 
112
+ parser.separator("")
113
+ parser.separator("Output:")
88
114
  parser.on("--output-path=PATH",
89
- "path to output statistics as a CSV file (optional)") do |path|
115
+ "Path to output statistics as a CSV file.",
116
+ "(#{config.output_path})") do |path|
90
117
  config.output_path = File.expand_path(path)
91
118
  end
92
119
  end
@@ -94,7 +121,7 @@ args = option_parser.parse!(ARGV)
94
121
 
95
122
  config.validate
96
123
 
97
- runner = Drnbench::RequestResponse::GradualRunner.new(config)
124
+ runner = Drnbench::RequestResponse::ProgressiveRunner.new(config)
98
125
  runner.run
99
126
 
100
127
  File.open(config.output_path, "w") do |file|
data/doc/text/news.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # News
2
2
 
3
+ ## 1.0.3: 2014-10-29 (planned)
4
+
5
+ * `drnbench-request-response`
6
+ * Accept multiple hosts as a comma separated list via the `--default-hosts` option.
7
+ You can simulate load balancing for multiple endpoints easily.
8
+ * Accept plain text file of a list of paths as the patterns file.
9
+ * `drnbench-extract-searchterms`
10
+ * New `--escape` option is introduced to escape URI-incompatible characters.
11
+
3
12
  ## 1.0.2: 2014-07-30
4
13
 
5
14
  * 'drnbench-request-response'
data/drnbench.gemspec CHANGED
@@ -56,4 +56,5 @@ Gem::Specification.new do |spec|
56
56
  spec.add_development_dependency("rake")
57
57
  spec.add_development_dependency("packnga")
58
58
  spec.add_development_dependency("kramdown")
59
+ spec.add_development_dependency("test-unit")
59
60
  end
data/lib/drnbench.rb CHANGED
@@ -16,7 +16,7 @@
16
16
  require "drnbench/version"
17
17
  require "drnbench/request-response/configuration"
18
18
  require "drnbench/request-response/runner"
19
- require "drnbench/request-response/gradual-runner"
19
+ require "drnbench/request-response/progressive-runner"
20
20
  require "drnbench/publish-subscribe/configuration"
21
21
  require "drnbench/publish-subscribe/runner"
22
- require "drnbench/publish-subscribe/gradual-runner"
22
+ require "drnbench/publish-subscribe/progressive-runner"
@@ -18,7 +18,7 @@ require "csv"
18
18
 
19
19
  module Drnbench
20
20
  module PublishSubscribe
21
- class GradualRunner
21
+ class ProgressiveRunner
22
22
  attr_reader :total_results
23
23
 
24
24
  def initialize(config)
@@ -21,23 +21,25 @@ module Drnbench
21
21
  attr_accessor :duration, :wait, :interval, :request_patterns_file
22
22
  attr_accessor :start_n_clients, :end_n_clients, :step, :n_requests, :n_slow_requests
23
23
  attr_accessor :mode
24
- attr_accessor :default_host, :default_port, :default_path, :default_method, :default_timeout
24
+ attr_reader :default_hosts
25
+ attr_accessor :default_port, :default_path, :default_method, :default_timeout
25
26
  attr_accessor :report_progressively, :output_path
26
27
 
27
28
  MIN_DURATION = 1
28
29
  MIN_WAIT = 0
29
30
 
30
31
  def initialize
31
- @wait = 1
32
- @interval = 5
33
- @start_n_clients = 1
32
+ @duration = 30
33
+ @wait = 0.01
34
+ @interval = 10
35
+ @start_n_clients = 0
34
36
  @end_n_clients = 1
35
37
  @step = 1
36
38
  @n_requests = 1000
37
39
  @mode = :http
38
40
  @n_slow_requests = 5
39
41
 
40
- @default_host = "localhost"
42
+ @default_hosts = ["localhost"]
41
43
  @default_port = 80
42
44
  @default_path = "/"
43
45
  @default_method = "GET"
@@ -45,6 +47,8 @@ module Drnbench
45
47
 
46
48
  @report_progressively = true
47
49
  @output_path = "/tmp/drnbench-result.csv"
50
+
51
+ @last_default_host_index = 0
48
52
  end
49
53
 
50
54
  def validate
@@ -72,10 +76,29 @@ module Drnbench
72
76
  @request_patterns ||= prepare_request_patterns
73
77
  end
74
78
 
79
+ def default_hosts=(hosts)
80
+ @last_default_host_index = 0
81
+ @default_hosts = hosts
82
+ end
83
+
84
+ def default_host
85
+ host = @default_hosts[@last_default_host_index]
86
+ @last_default_host_index += 1
87
+ if @last_default_host_index == @default_hosts.size
88
+ @last_default_host_index = 0
89
+ end
90
+ host
91
+ end
92
+
75
93
  private
76
94
  def prepare_request_patterns
77
95
  request_patterns = File.read(@request_patterns_file)
78
- request_patterns = JSON.parse(request_patterns)
96
+ begin
97
+ request_patterns = JSON.parse(request_patterns)
98
+ rescue JSON::ParserError
99
+ # it's a simple text file, list of paths
100
+ request_patterns = request_patterns.strip.split(/\r?\n/)
101
+ end
79
102
  end
80
103
  end
81
104
  end
@@ -18,7 +18,7 @@ require "csv"
18
18
 
19
19
  module Drnbench
20
20
  module RequestResponse
21
- class GradualRunner
21
+ class ProgressiveRunner
22
22
  attr_reader :report_progressively, :result
23
23
 
24
24
  def initialize(config)
@@ -0,0 +1,194 @@
1
+ # Copyright (C) 2013-2014 Droonga Project
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program 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
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ module Drnbench
17
+ module RequestResponse
18
+ module RequestPattern
19
+ class Abstract
20
+ def initialize(source, config)
21
+ @source = source
22
+ @config = config
23
+ end
24
+
25
+ def groups
26
+ @groups ||= prepare_groups
27
+ end
28
+
29
+ def default_group_frequency
30
+ 1.0 / groups.size
31
+ end
32
+
33
+ def requests
34
+ @requests ||= populate_requests
35
+ end
36
+
37
+ private
38
+ def prepare_groups
39
+ if @source.is_a?(Array)
40
+ if PatternsGroup.valid_source?(@source.first)
41
+ return @source.collect do |group|
42
+ PatternsGroup.new(group, self)
43
+ end
44
+ end
45
+ if PatternsGroup.valid_source?(@source)
46
+ return [
47
+ PatternsGroup.new(@source, self),
48
+ ]
49
+ end
50
+ elsif @source.is_a?(Hash)
51
+ if PatternsGroup.valid_source?(@source)
52
+ return [
53
+ PatternsGroup.new(@source, self),
54
+ ]
55
+ end
56
+ return @source.values.collect do |group|
57
+ PatternsGroup.new(group, self)
58
+ end
59
+ end
60
+
61
+ []
62
+ end
63
+
64
+ def populate_requests
65
+ requests = []
66
+ groups.each do |group|
67
+ n_requests = @config.n_requests * @config.end_n_clients * group.frequency
68
+ base_patterns = group.patterns.shuffle
69
+ n_requests.round.times do |count|
70
+ pattern = base_patterns[count % base_patterns.size]
71
+ requests << pattern.to_request
72
+ end
73
+ end
74
+ requests
75
+ end
76
+ end
77
+
78
+ class PatternsGroup
79
+ class << self
80
+ def valid_source?(source)
81
+ if source.is_a?(Array)
82
+ return Pattern.valid_source?(source.first)
83
+ end
84
+ if source.is_a?(Hash)
85
+ return source.has_key?("patterns")
86
+ end
87
+ false
88
+ end
89
+ end
90
+
91
+ attr_reader :abstract
92
+
93
+ def initialize(source, abstract)
94
+ @source = source
95
+ @abstract = abstract
96
+ end
97
+
98
+ def frequency
99
+ if @source.is_a?(Hash) and @source.has_key?("frequency")
100
+ return @source["frequency"].to_f
101
+ end
102
+ @abstract.default_group_frequency
103
+ end
104
+
105
+ def host
106
+ return nil unless @source.is_a?(Hash)
107
+ @source["host"]
108
+ end
109
+
110
+ def port
111
+ return nil unless @source.is_a?(Hash)
112
+ @source["port"]
113
+ end
114
+
115
+ def method
116
+ return nil unless @source.is_a?(Hash)
117
+ @source["method"]
118
+ end
119
+
120
+ def timeout
121
+ return nil unless @source.is_a?(Hash)
122
+ @source["timeout"]
123
+ end
124
+
125
+ def patterns
126
+ @patterns ||= prepare_patterns
127
+ end
128
+
129
+ private
130
+ def prepare_patterns
131
+ if @source.is_a?(Hash)
132
+ if @source.has_key?("pattern")
133
+ return [
134
+ Pattern.new(@source["pattern"], self),
135
+ ]
136
+ else
137
+ return @source["patterns"].collect do |pattern|
138
+ Pattern.new(pattern, self)
139
+ end
140
+ end
141
+ elsif @source.is_a?(Array)
142
+ return @source.collect do |pattern|
143
+ Pattern.new(pattern, self)
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ class Pattern
150
+ class << self
151
+ def valid_source?(source)
152
+ return true if source.is_a?(String)
153
+ return false if source.is_a?(Array)
154
+ return !source.has_key?("patterns") if source.is_a?(Hash)
155
+ false
156
+ end
157
+ end
158
+
159
+ attr_reader :source, :group
160
+
161
+ def initialize(source, group)
162
+ @source = source
163
+ @group = group
164
+ end
165
+
166
+ def path
167
+ if @source.is_a?(String)
168
+ @source
169
+ else
170
+ @source["path"]
171
+ end
172
+ end
173
+
174
+ def to_request
175
+ @populated ||= populate
176
+ end
177
+
178
+ private
179
+ def populate
180
+ if @source.is_a?(String)
181
+ request = { "path" => @source }
182
+ else
183
+ request = @source
184
+ end
185
+ request["host"] ||= @group.host
186
+ request["port"] ||= @group.port
187
+ request["method"] ||= @group.method
188
+ request["timeout"] ||= @group.timeout
189
+ request
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end
@@ -16,6 +16,7 @@
16
16
  require "drnbench/client/http"
17
17
  require "drnbench/client/http-droonga"
18
18
  require "drnbench/request-response/result"
19
+ require "drnbench/request-response/request-pattern"
19
20
 
20
21
  module Drnbench
21
22
  module RequestResponse
@@ -26,7 +27,9 @@ module Drnbench
26
27
  n_clients = 1 if n_clients.zero?
27
28
  @n_clients = n_clients
28
29
  @config = config
29
- populate_requests
30
+
31
+ abstract = RequestPattern::Abstract.new(@config.request_patterns, @config)
32
+ @requests = abstract.requests.shuffle
30
33
  end
31
34
 
32
35
  def run
@@ -79,44 +82,6 @@ module Drnbench
79
82
 
80
83
  @result
81
84
  end
82
-
83
- def populate_requests
84
- @requests = []
85
-
86
- if @config.request_patterns.is_a?(Array)
87
- @config.request_patterns.each do |request_pattern|
88
- populate_request_pattern(request_pattern)
89
- end
90
- else
91
- @config.request_patterns.each do |key, request_pattern|
92
- populate_request_pattern(request_pattern)
93
- end
94
- end
95
-
96
- @requests.shuffle!
97
- end
98
-
99
- def populate_request_pattern(request_pattern)
100
- frequency = request_pattern["frequency"].to_f
101
- n_requests = @config.n_requests * @config.end_n_clients * frequency
102
-
103
- base_patterns = nil
104
- if request_pattern["pattern"]
105
- base_patterns = [request_pattern["pattern"]]
106
- else
107
- base_patterns = request_pattern["patterns"]
108
- end
109
- base_patterns = base_patterns.shuffle
110
-
111
- n_requests.round.times do |count|
112
- pattern = base_patterns[count % base_patterns.size]
113
- pattern["host"] ||= request_pattern["host"]
114
- pattern["port"] ||= request_pattern["port"]
115
- pattern["method"] ||= request_pattern["method"]
116
- pattern["timeout"] ||= request_pattern["timeout"]
117
- @requests << pattern
118
- end
119
- end
120
85
  end
121
86
  end
122
87
  end
@@ -14,5 +14,5 @@
14
14
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
15
 
16
16
  module Drnbench
17
- VERSION = "1.0.2"
17
+ VERSION = "1.0.3"
18
18
  end
@@ -0,0 +1,111 @@
1
+ # Copyright (C) 2014 Droonga Project
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
+ require "ostruct"
17
+ require "drnbench/request-response/request-pattern"
18
+
19
+ module Drnbench::RequestResponse::RequestPattern
20
+ class RequestResponsePatternsTest < Test::Unit::TestCase
21
+ CONFIG = OpenStruct.new
22
+ CONFIG.n_requests = 1
23
+ CONFIG.end_n_clients = 1
24
+
25
+ PATH_STRING = "/path/to/endpoint"
26
+ PATTERN_HASH = { "path" => PATH_STRING }
27
+
28
+ class PatternTest < self
29
+ data("path string" => PATH_STRING,
30
+ "hash" => PATTERN_HASH)
31
+ def test_validation(source)
32
+ Pattern.valid_source?(source)
33
+ end
34
+ end
35
+
36
+ class PatternsGroupTest < self
37
+ data("path string array" => [
38
+ PATH_STRING,
39
+ ],
40
+ "hash array" => [
41
+ PATTERN_HASH,
42
+ ],
43
+ "hash with path string array" => {
44
+ "patterns" => [
45
+ PATH_STRING,
46
+ ],
47
+ },
48
+ "hash with hash array" => {
49
+ "patterns" => [
50
+ PATTERN_HASH,
51
+ ],
52
+ })
53
+ def test_validation(source)
54
+ PatternsGroup.valid_source?(source)
55
+ end
56
+ end
57
+
58
+ class AbstractTest < self
59
+ data("path string array" => [
60
+ PATH_STRING,
61
+ ],
62
+ "pattern hash array" => [
63
+ PATTERN_HASH,
64
+ ],
65
+
66
+ "group, hash with path string array" => {
67
+ "patterns" => [
68
+ PATH_STRING,
69
+ ],
70
+ },
71
+ "group, hash with hash array" => {
72
+ "patterns" => [
73
+ PATTERN_HASH,
74
+ ],
75
+ },
76
+
77
+ "array of groups, path string array" => [
78
+ [PATH_STRING],
79
+ ],
80
+ "array of groups, hash array" => [
81
+ [PATTERN_HASH],
82
+ ],
83
+ "array of groups, hash with path string array" => [
84
+ { "patterns" => [PATH_STRING] },
85
+ ],
86
+ "array of groups, hash with hash array" => [
87
+ { "patterns" => [PATTERN_HASH] },
88
+ ],
89
+
90
+ "named groups, path string array" => {
91
+ "group" => [PATH_STRING],
92
+ },
93
+ "named groups, hash array" => {
94
+ "group" => [PATTERN_HASH],
95
+ },
96
+ "named groups, hash with path string array" => {
97
+ "group" => { "patterns" => [PATH_STRING] },
98
+ },
99
+ "named groups, hash with hash array" => {
100
+ "group" => { "patterns" => [PATTERN_HASH] },
101
+ })
102
+ def test_parse(source)
103
+ abstract = Abstract.new(source, CONFIG)
104
+ assert_equal(PATH_STRING,
105
+ abstract.groups.first.patterns.first.path)
106
+ assert_equal(1.0,
107
+ abstract.groups.first.frequency)
108
+ end
109
+ end
110
+ end
111
+ end
data/test/run-test.rb ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # Copyright (C) 2013 Droonga Project
5
+ #
6
+ # This library is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU Lesser General Public
8
+ # License version 2.1 as published by the Free Software Foundation.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+
19
+ require "pathname"
20
+
21
+ require "rubygems"
22
+ require "bundler"
23
+ begin
24
+ Bundler.setup(:default, :development)
25
+ rescue Bundler::BundlerError => e
26
+ $stderr.puts e.message
27
+ $stderr.puts "Run `bundle install` to install missing gems"
28
+ exit e.status_code
29
+ end
30
+
31
+ require "test-unit"
32
+
33
+ base_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
34
+ lib_dir = File.join(base_dir, "lib")
35
+ test_dir = File.join(base_dir, "test")
36
+
37
+ $LOAD_PATH.unshift(lib_dir)
38
+ $LOAD_PATH.unshift(test_dir)
39
+
40
+ ARGV.unshift("--max-diff-target-string-size=10000")
41
+
42
+ exit Test::Unit::AutoRunner.run(true, test_dir)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: drnbench
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - YUKI Hiroshi
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-07-31 00:00:00.000000000 Z
12
+ date: 2014-10-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
@@ -109,6 +109,20 @@ dependencies:
109
109
  - - '>='
110
110
  - !ruby/object:Gem::Version
111
111
  version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: test-unit
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
112
126
  description: It may be used for other HTTP servers.
113
127
  email:
114
128
  - yuki@clear-code.com
@@ -121,33 +135,36 @@ executables:
121
135
  extensions: []
122
136
  extra_rdoc_files: []
123
137
  files:
124
- - README.md
125
- - Rakefile
126
138
  - Gemfile
127
- - drnbench.gemspec
128
139
  - LICENSE.txt
140
+ - README.md
141
+ - Rakefile
142
+ - bin/drnbench-extract-searchterms
143
+ - bin/drnbench-generate-select-patterns
144
+ - bin/drnbench-publish-subscribe
145
+ - bin/drnbench-request-response
129
146
  - doc/text/news.md
130
- - lib/drnbench/client/http.rb
147
+ - drnbench.gemspec
148
+ - lib/drnbench.rb
149
+ - lib/drnbench/chart/gnuplot.rb
131
150
  - lib/drnbench/client/http-droonga.rb
132
- - lib/drnbench/request-response/gradual-runner.rb
151
+ - lib/drnbench/client/http.rb
152
+ - lib/drnbench/publish-subscribe/configuration.rb
153
+ - lib/drnbench/publish-subscribe/progressive-runner.rb
154
+ - lib/drnbench/publish-subscribe/runner.rb
155
+ - lib/drnbench/publish-subscribe/watch.rb
156
+ - lib/drnbench/reporters/throughput-reporter.rb
133
157
  - lib/drnbench/request-response/configuration.rb
158
+ - lib/drnbench/request-response/progressive-runner.rb
159
+ - lib/drnbench/request-response/request-pattern.rb
134
160
  - lib/drnbench/request-response/result.rb
135
161
  - lib/drnbench/request-response/runner.rb
136
- - lib/drnbench/reporters/throughput-reporter.rb
137
- - lib/drnbench/version.rb
138
- - lib/drnbench/chart/gnuplot.rb
139
- - lib/drnbench/publish-subscribe/watch.rb
140
- - lib/drnbench/publish-subscribe/gradual-runner.rb
141
- - lib/drnbench/publish-subscribe/configuration.rb
142
- - lib/drnbench/publish-subscribe/runner.rb
143
- - lib/drnbench/server/protocol-adapter.rb
144
- - lib/drnbench/server/engine.rb
145
162
  - lib/drnbench/server/configuration.rb
146
- - lib/drnbench.rb
147
- - bin/drnbench-extract-searchterms
148
- - bin/drnbench-generate-select-patterns
149
- - bin/drnbench-request-response
150
- - bin/drnbench-publish-subscribe
163
+ - lib/drnbench/server/engine.rb
164
+ - lib/drnbench/server/protocol-adapter.rb
165
+ - lib/drnbench/version.rb
166
+ - test/request-response/test-request-pattern.rb
167
+ - test/run-test.rb
151
168
  homepage: https://github.com/groonga/grntest
152
169
  licenses:
153
170
  - GPLv3 or later
@@ -168,9 +185,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
168
185
  version: '0'
169
186
  requirements: []
170
187
  rubyforge_project:
171
- rubygems_version: 2.0.14
188
+ rubygems_version: 2.4.1
172
189
  signing_key:
173
190
  specification_version: 4
174
191
  summary: Drnbench is a benchmark tool for Droonga.
175
- test_files: []
192
+ test_files:
193
+ - test/run-test.rb
194
+ - test/request-response/test-request-pattern.rb
176
195
  has_rdoc: