wsdirector-cli 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +49 -0
- data/README.md +39 -0
- data/lib/wsdirector/cli.rb +29 -7
- data/lib/wsdirector/client.rb +1 -1
- data/lib/wsdirector/configuration.rb +1 -2
- data/lib/wsdirector/ext/deep_dup.rb +6 -0
- data/lib/wsdirector/protocols/base.rb +2 -2
- data/lib/wsdirector/protocols.rb +2 -0
- data/lib/wsdirector/scenario_reader.rb +41 -3
- data/lib/wsdirector/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b02895fab166dd2d388f48dda802e02407e5b7866eb508f1b5787e1a4e1976d6
|
4
|
+
data.tar.gz: e0d5af5ae2de5caed7ccd151538e19ad3c49e08db1217e042f36540d69468314
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09af449361f79d80a4848b0851aa96ada36e363e997bba177e5d96b01005d1c241abee2a1a05781f3a5277de08732f3b1d8afaeaea467d2097050347d2ca295c'
|
7
|
+
data.tar.gz: 8deb112a900d7cdbc710be8b86d57aef8aeaa87bbec78595170bf309088bca9bb88fd58de503e2bcfb32b43df5e08903c322791eb10930aa0fb25f00e26afebb
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,53 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.5.0 (2021-10-13)
|
6
|
+
|
7
|
+
- Add JSON support. ([@wazzuper][])
|
8
|
+
|
9
|
+
- Add new commands to CLI.
|
10
|
+
|
11
|
+
You can pass a JSON scenario directly to the CLI without creating a file:
|
12
|
+
|
13
|
+
```bash
|
14
|
+
wsdirector -i '[{"receive": {"data":"welcome"}},{"send":{"data":"send message"}},{"receive":{"data":"receive message"}}]' -u ws://websocket.server:9876
|
15
|
+
```
|
16
|
+
|
17
|
+
or you can pass it as a JSON file:
|
18
|
+
|
19
|
+
```bash
|
20
|
+
wsdirector scenario.json -u ws://websocket.server:9876
|
21
|
+
```
|
22
|
+
|
23
|
+
- Add loop option support. ([@last-in-japan][])
|
24
|
+
|
25
|
+
You can specify a `loop` option to perform a similar set of actions multiple times:
|
26
|
+
|
27
|
+
```yml
|
28
|
+
# script.yml
|
29
|
+
- client:
|
30
|
+
name: "listeners"
|
31
|
+
loop:
|
32
|
+
multiplier: ":scale" # :scale take number from -s param, and run :scale number of clients in this group
|
33
|
+
actions:
|
34
|
+
- receive:
|
35
|
+
data:
|
36
|
+
type: "welcome"
|
37
|
+
- send:
|
38
|
+
data:
|
39
|
+
command: "subscribe"
|
40
|
+
identifier: "{\"channel\":\"Channel\"}"
|
41
|
+
- receive:
|
42
|
+
data:
|
43
|
+
identifier: "{\"channel\":\"Channel\"}"
|
44
|
+
type: "confirm_subscription"
|
45
|
+
- wait_all
|
46
|
+
- receive:
|
47
|
+
multiplier: ":scale + 1"
|
48
|
+
```
|
49
|
+
|
50
|
+
Useful in combination with `:scale`.
|
51
|
+
|
5
52
|
## 0.4.0 (2020-08-24)
|
6
53
|
|
7
54
|
- **Drop Ruby 2.4 support**. ([@palkan][])
|
@@ -64,3 +111,5 @@ Allows to handle multiple messages with unspecified order:
|
|
64
111
|
[@palkan]: https://github.com/palkan
|
65
112
|
[@Kirillvs]: https://github.com/Kirillvs
|
66
113
|
[@Grandman]: https://github.com/Grandman
|
114
|
+
[@wazzuper]: https://github.com/wazzuper
|
115
|
+
[@last-in-japan]: https://github.com/last-in-japan
|
data/README.md
CHANGED
@@ -77,6 +77,45 @@ The simpliest scenario is just checking that socket is succesfully connected:
|
|
77
77
|
# no actions
|
78
78
|
```
|
79
79
|
|
80
|
+
Run with loop option:
|
81
|
+
|
82
|
+
```yml
|
83
|
+
# script.yml
|
84
|
+
- client:
|
85
|
+
name: "listeners"
|
86
|
+
loop:
|
87
|
+
multiplier: ":scale" # :scale take number from -s param, and run :scale number of clients in this group
|
88
|
+
actions:
|
89
|
+
- receive:
|
90
|
+
data:
|
91
|
+
type: "welcome"
|
92
|
+
- send:
|
93
|
+
data:
|
94
|
+
command: "subscribe"
|
95
|
+
identifier: "{\"channel\":\"Channel\"}"
|
96
|
+
- receive:
|
97
|
+
data:
|
98
|
+
identifier: "{\"channel\":\"Channel\"}"
|
99
|
+
type: "confirm_subscription"
|
100
|
+
- wait_all
|
101
|
+
- receive:
|
102
|
+
multiplier: ":scale + 1"
|
103
|
+
```
|
104
|
+
|
105
|
+
Also you can pass a JSON file with some testing scripts:
|
106
|
+
|
107
|
+
```bash
|
108
|
+
wsdirector scenario.json ws://websocket.server:9876
|
109
|
+
```
|
110
|
+
|
111
|
+
or pass a JSON scenario directly to the CLI without creating a file:
|
112
|
+
|
113
|
+
```bash
|
114
|
+
wsdirector -i '[{"receive": {"data":"welcome"}},{"send":{"data":"send message"}},{"receive":{"data":"receive message"}}]' ws://websocket.server:9876
|
115
|
+
```
|
116
|
+
|
117
|
+
Type `wsdirector --help` to check all commands.
|
118
|
+
|
80
119
|
### Protocols
|
81
120
|
|
82
121
|
WSDirector uses protocols to handle different actions.
|
data/lib/wsdirector/cli.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "optparse"
|
4
|
+
require "uri"
|
4
5
|
|
5
6
|
require "wsdirector"
|
6
7
|
require "wsdirector/scenario_reader"
|
@@ -23,7 +24,7 @@ module WSDirector
|
|
23
24
|
end
|
24
25
|
|
25
26
|
scenario = WSDirector::ScenarioReader.parse(
|
26
|
-
WSDirector.config.scenario_path
|
27
|
+
WSDirector.config.scenario_path || WSDirector.config.json_scenario
|
27
28
|
)
|
28
29
|
|
29
30
|
if WSDirector::Runner.new(scenario).start
|
@@ -38,6 +39,9 @@ module WSDirector
|
|
38
39
|
|
39
40
|
private
|
40
41
|
|
42
|
+
FILE_FORMAT = /.+.(json|yml)\z/.freeze
|
43
|
+
private_constant :FILE_FORMAT
|
44
|
+
|
41
45
|
def parse_args!
|
42
46
|
# rubocop: disable Metrics/LineLength
|
43
47
|
parser = OptionParser.new do |opts|
|
@@ -51,6 +55,14 @@ module WSDirector
|
|
51
55
|
WSDirector.config.sync_timeout = v
|
52
56
|
end
|
53
57
|
|
58
|
+
opts.on("-i JSON", "--include=JSON", String, "Include JSON to parse") do |v|
|
59
|
+
WSDirector.config.json_scenario = v
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on("-u URL", "--url=URL", Object, "Websocket server URL") do |v|
|
63
|
+
WSDirector.config.ws_url = v
|
64
|
+
end
|
65
|
+
|
54
66
|
opts.on("-c", "--[no-]color", "Colorize output") do |v|
|
55
67
|
WSDirector.config.colorize = v
|
56
68
|
end
|
@@ -64,15 +76,25 @@ module WSDirector
|
|
64
76
|
|
65
77
|
parser.parse!
|
66
78
|
|
67
|
-
WSDirector.config.scenario_path = ARGV
|
68
|
-
WSDirector.config.ws_url = ARGV[1]
|
79
|
+
WSDirector.config.scenario_path = ARGV.grep(FILE_FORMAT).last
|
69
80
|
|
70
|
-
|
81
|
+
unless WSDirector.config.ws_url
|
82
|
+
WSDirector.config.ws_url = ARGV.grep(URI::DEFAULT_PARSER.make_regexp).last
|
83
|
+
end
|
71
84
|
|
72
|
-
|
73
|
-
|
85
|
+
check_for_errors
|
86
|
+
end
|
87
|
+
|
88
|
+
def check_for_errors
|
89
|
+
if WSDirector.config.json_scenario.nil?
|
90
|
+
raise(Error, "Scenario is missing") unless WSDirector.config.scenario_path
|
91
|
+
|
92
|
+
unless File.file?(WSDirector.config.scenario_path)
|
93
|
+
raise(Error, "File doesn't exist #{WSDirector.config.scenario_path}")
|
94
|
+
end
|
95
|
+
end
|
74
96
|
|
75
|
-
raise(Error, "Websocket server url is missing")
|
97
|
+
raise(Error, "Websocket server url is missing") unless WSDirector.config.ws_url
|
76
98
|
end
|
77
99
|
end
|
78
100
|
end
|
data/lib/wsdirector/client.rb
CHANGED
@@ -63,10 +63,10 @@ module WSDirector
|
|
63
63
|
messages.nil? || messages.empty?
|
64
64
|
|
65
65
|
expected =
|
66
|
-
|
66
|
+
messages.map do |msg|
|
67
67
|
multiplier = parse_multiplier(msg.delete("multiplier") || "1")
|
68
68
|
[msg["data"], multiplier]
|
69
|
-
end
|
69
|
+
end.to_h
|
70
70
|
|
71
71
|
total_expected = expected.values.sum
|
72
72
|
total_received = 0
|
data/lib/wsdirector/protocols.rb
CHANGED
@@ -12,8 +12,10 @@ module WSDirector
|
|
12
12
|
module Protocols # :nodoc:
|
13
13
|
# Raised when received not expected message
|
14
14
|
class UnmatchedExpectationError < WSDirector::Error; end
|
15
|
+
|
15
16
|
# Raised when received message is unexpected
|
16
17
|
class UnexpectedMessageError < WSDirector::Error; end
|
18
|
+
|
17
19
|
# Raised when nothing has been received
|
18
20
|
class NoMessageError < WSDirector::Error; end
|
19
21
|
|
@@ -1,25 +1,47 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "erb"
|
4
|
+
require "json"
|
5
|
+
require "wsdirector/ext/deep_dup"
|
4
6
|
|
5
7
|
module WSDirector
|
6
|
-
# Read and parse
|
8
|
+
# Read and parse different scenarios
|
7
9
|
class ScenarioReader
|
10
|
+
using WSDirector::Ext::DeepDup
|
11
|
+
|
8
12
|
class << self
|
9
13
|
include WSDirector::Utils
|
10
14
|
|
11
|
-
def parse(
|
12
|
-
contents =
|
15
|
+
def parse(scenario)
|
16
|
+
contents =
|
17
|
+
if File.file?(scenario)
|
18
|
+
parse_file(scenario)
|
19
|
+
else
|
20
|
+
[JSON.parse(scenario)]
|
21
|
+
end.flatten
|
13
22
|
|
14
23
|
if contents.first.key?("client")
|
24
|
+
contents = transform_with_loop(contents, multiple: true)
|
15
25
|
parse_multiple_scenarios(contents)
|
16
26
|
else
|
27
|
+
contents = transform_with_loop(contents)
|
17
28
|
{"total" => 1, "clients" => [parse_simple_scenario(contents)]}
|
18
29
|
end
|
19
30
|
end
|
20
31
|
|
21
32
|
private
|
22
33
|
|
34
|
+
JSON_FILE_FORMAT = /.+.(json)\z/.freeze
|
35
|
+
private_constant :JSON_FILE_FORMAT
|
36
|
+
|
37
|
+
def parse_file(file)
|
38
|
+
if file.match?(JSON_FILE_FORMAT)
|
39
|
+
JSON.parse(File.read(file))
|
40
|
+
else
|
41
|
+
::YAML.load(ERB.new(File.read(file)).result) # rubocop:disable Security/YAMLLoad
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
23
45
|
def handle_steps(steps)
|
24
46
|
steps.flat_map.with_index do |step, id|
|
25
47
|
if step.is_a?(Hash)
|
@@ -67,6 +89,22 @@ module WSDirector
|
|
67
89
|
{"total" => total_count, "clients" => clients}
|
68
90
|
end
|
69
91
|
|
92
|
+
def transform_with_loop(contents, multiple: false)
|
93
|
+
contents.flat_map do |content|
|
94
|
+
loop_data = content.dig("client", "loop") || content.dig("loop")
|
95
|
+
next content unless loop_data
|
96
|
+
|
97
|
+
loop_multiplier = parse_multiplier(loop_data["multiplier"] || "1")
|
98
|
+
|
99
|
+
if multiple
|
100
|
+
content["client"]["actions"] = (loop_data["actions"] * loop_multiplier).map(&:deep_dup)
|
101
|
+
content
|
102
|
+
else
|
103
|
+
loop_data["actions"] * loop_multiplier
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
70
108
|
def parse_ingore(str)
|
71
109
|
return unless str
|
72
110
|
|
data/lib/wsdirector/version.rb
CHANGED
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wsdirector-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kirill Arkhipov
|
8
8
|
- Grandman
|
9
9
|
- palkan
|
10
|
-
autorequire:
|
10
|
+
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2021-10-13 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: websocket-client-simple
|
@@ -202,7 +202,7 @@ homepage: https://github.com/palkan/wsdirector
|
|
202
202
|
licenses:
|
203
203
|
- MIT
|
204
204
|
metadata: {}
|
205
|
-
post_install_message:
|
205
|
+
post_install_message:
|
206
206
|
rdoc_options: []
|
207
207
|
require_paths:
|
208
208
|
- lib
|
@@ -217,8 +217,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
217
217
|
- !ruby/object:Gem::Version
|
218
218
|
version: '0'
|
219
219
|
requirements: []
|
220
|
-
rubygems_version: 3.
|
221
|
-
signing_key:
|
220
|
+
rubygems_version: 3.2.22
|
221
|
+
signing_key:
|
222
222
|
specification_version: 4
|
223
223
|
summary: Command line tool for testing websocket servers using scenarios.
|
224
224
|
test_files: []
|