drnbench 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
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: