anyt 1.0.1 → 1.1.1
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/README.md +0 -1
- data/lib/anyt/cli.rb +50 -9
- data/lib/anyt/command.rb +2 -0
- data/lib/anyt/config.rb +3 -0
- data/lib/anyt/dummy/application.rb +23 -0
- data/lib/anyt/ext/minitest.rb +2 -2
- data/lib/anyt/rpc.rb +2 -3
- data/lib/anyt/tests/features/channel_state_test.rb +35 -1
- data/lib/anyt/tests/request/disconnection_test.rb +3 -3
- data/lib/anyt/tests/streams/broadcast_test.rb +1 -1
- data/lib/anyt/tests/streams/multiple_clients_test.rb +3 -3
- data/lib/anyt/tests/streams/multiple_test.rb +5 -5
- data/lib/anyt/tests/streams/single_test.rb +5 -5
- data/lib/anyt/tests/streams/stop_test.rb +4 -4
- data/lib/anyt/tests/subscriptions/perform_test.rb +1 -1
- data/lib/anyt/version.rb +1 -1
- metadata +32 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c9c827378c7eb12bd020314e569289176896a6c2ea3c08ea649e9ec8674590f
|
4
|
+
data.tar.gz: 62da136e9594732d956f1113797209dd7853f929cbd2301b17c79d97836b2934
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c5c1cef4a681e2814941391092dde7e72709072ec0a5c5f3db63c57ce961255fafdee3524458ba286abe3c85b31a456e0d834e3b921efc6b4480fa963b966741
|
7
|
+
data.tar.gz: 4dd4cc71eab70762f8bd1f3d1c16b710d41cf660d58b333012309419d6c8433393612600a70c456fc87f2239d9c3ee5c645aaa3ed72391c6bcc6d3881c290ba7
|
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
[](https://cultofmartians.com/tasks/anycable-conformance-tool.html#task)
|
2
2
|
[](https://rubygems.org/gems/anyt)
|
3
3
|

|
4
|
-
[](https://gitter.im/anycable/anycablebility)
|
5
4
|
|
6
5
|
# AnyCable Conformance Testing Tool
|
7
6
|
|
data/lib/anyt/cli.rb
CHANGED
@@ -32,7 +32,7 @@ module Anyt
|
|
32
32
|
end
|
33
33
|
|
34
34
|
# Load all test scenarios
|
35
|
-
Tests.load_tests
|
35
|
+
Tests.load_tests unless @skip_tests
|
36
36
|
|
37
37
|
Rails.application.initialize!
|
38
38
|
|
@@ -50,8 +50,14 @@ module Anyt
|
|
50
50
|
# Start webosocket server under test
|
51
51
|
Command.run
|
52
52
|
|
53
|
-
|
54
|
-
|
53
|
+
unless @skip_tests
|
54
|
+
# Run tests
|
55
|
+
result = Tests.run ? 0 : 1
|
56
|
+
end
|
57
|
+
|
58
|
+
wait_till_terminated if @only_rails
|
59
|
+
rescue Interrupt => e
|
60
|
+
$stdout.puts "#{e.message}. Good-bye!"
|
55
61
|
ensure
|
56
62
|
RPC.stop unless @skip_rpc
|
57
63
|
Command.stop
|
@@ -91,16 +97,21 @@ module Anyt
|
|
91
97
|
|
92
98
|
cli.on("--only-rpc", TrueClass, "Run only RPC server") do |flag|
|
93
99
|
@only_rpc = flag
|
100
|
+
@skip_tests = true
|
101
|
+
end
|
102
|
+
|
103
|
+
cli.on("--only-rails", TrueClass, "Run only Rails server") do
|
104
|
+
@skip_rpc = true
|
105
|
+
@only_rails = true
|
106
|
+
@skip_tests = true
|
107
|
+
|
108
|
+
configure_rails_command!
|
94
109
|
end
|
95
110
|
|
96
111
|
cli.on("--self-check", "Run tests again Action Cable itself") do
|
97
112
|
@skip_rpc = true
|
98
|
-
|
99
|
-
|
100
|
-
::File.join(::File.dirname(__FILE__), "dummy")
|
101
|
-
)
|
102
|
-
Anyt.config.command = "bundle exec puma #{dummy_path}"
|
103
|
-
Anyt.config.use_action_cable = true
|
113
|
+
|
114
|
+
configure_rails_command!
|
104
115
|
end
|
105
116
|
|
106
117
|
cli.on("--only test1,test2,test3", Array, "Run only specified tests") do |only_tests|
|
@@ -149,6 +160,36 @@ module Anyt
|
|
149
160
|
puts "Use `anyt --help` to list all available options."
|
150
161
|
exit 1
|
151
162
|
end
|
163
|
+
|
164
|
+
def configure_rails_command!
|
165
|
+
dummy_path = ::File.expand_path(
|
166
|
+
"config.ru",
|
167
|
+
::File.join(::File.dirname(__FILE__), "dummy")
|
168
|
+
)
|
169
|
+
Anyt.config.command = "bundle exec puma #{dummy_path}"
|
170
|
+
Anyt.config.use_action_cable = true
|
171
|
+
end
|
172
|
+
|
173
|
+
def wait_till_terminated
|
174
|
+
self_read = setup_signals
|
175
|
+
|
176
|
+
while readable_io = IO.select([self_read]) # rubocop:disable Lint/AssignmentInCondition
|
177
|
+
signal = readable_io.first[0].gets.strip
|
178
|
+
raise Interrupt, "SIG#{signal} received"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def setup_signals
|
183
|
+
self_read, self_write = IO.pipe
|
184
|
+
|
185
|
+
%w[INT TERM].each do |signal|
|
186
|
+
trap signal do
|
187
|
+
self_write.puts signal
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
self_read
|
192
|
+
end
|
152
193
|
end
|
153
194
|
end
|
154
195
|
end
|
data/lib/anyt/command.rb
CHANGED
data/lib/anyt/config.rb
CHANGED
@@ -42,6 +42,29 @@ module ApplicationCable
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
# BenchmarkChannel is useful when running Rails app only or RPC only
|
46
|
+
class BenchmarkChannel < ApplicationCable::Channel
|
47
|
+
def subscribed
|
48
|
+
stream_from "all#{stream_id}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def echo(data)
|
52
|
+
transmit data
|
53
|
+
end
|
54
|
+
|
55
|
+
def broadcast(data)
|
56
|
+
ActionCable.server.broadcast "all#{stream_id}", data
|
57
|
+
data["action"] = "broadcastResult"
|
58
|
+
transmit data
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def stream_id
|
64
|
+
params[:id] || ""
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
45
68
|
ActionCable.server.config.cable = {"adapter" => "redis"}
|
46
69
|
ActionCable.server.config.connection_class = -> { ApplicationCable::Connection }
|
47
70
|
ActionCable.server.config.disable_request_forgery_protection = true
|
data/lib/anyt/ext/minitest.rb
CHANGED
@@ -12,9 +12,9 @@ module Anyt
|
|
12
12
|
base.after { @clients&.each { |client| client.close(allow_messages: true) } }
|
13
13
|
end
|
14
14
|
|
15
|
-
def build_client(
|
15
|
+
def build_client(**args)
|
16
16
|
@clients ||= []
|
17
|
-
Anyt::Client.new(
|
17
|
+
Anyt::Client.new(**args).tap do |client|
|
18
18
|
@clients << client
|
19
19
|
end
|
20
20
|
end
|
data/lib/anyt/rpc.rb
CHANGED
@@ -19,10 +19,9 @@ module Anyt # :nodoc:
|
|
19
19
|
|
20
20
|
AnyCable.server_callbacks.each(&:call)
|
21
21
|
|
22
|
-
@server = AnyCable::Server.new(
|
22
|
+
@server = AnyCable::GRPC::Server.new(
|
23
23
|
host: AnyCable.config.rpc_host,
|
24
|
-
**AnyCable.config.to_grpc_params
|
25
|
-
interceptors: AnyCable.middleware.to_a
|
24
|
+
**AnyCable.config.to_grpc_params
|
26
25
|
)
|
27
26
|
|
28
27
|
AnyCable.middleware.freeze
|
@@ -7,16 +7,27 @@ feature "Channel state" do
|
|
7
7
|
def subscribed
|
8
8
|
self.user = {name: params["name"]}
|
9
9
|
self.count = 1
|
10
|
+
|
11
|
+
stream_from "state_counts"
|
10
12
|
end
|
11
13
|
|
12
14
|
def tick
|
13
15
|
self.count += 2
|
14
|
-
transmit(count: count, name: user[:name])
|
16
|
+
transmit({count: count, name: user[:name]})
|
17
|
+
end
|
18
|
+
|
19
|
+
def unsubscribed
|
20
|
+
return unless params["notify_disconnect"]
|
21
|
+
|
22
|
+
ActionCable.server.broadcast("state_counts", {data: "user left: #{user[:name]}"})
|
15
23
|
end
|
16
24
|
end
|
17
25
|
|
18
26
|
let(:identifier) { {channel: channel, name: "chipolino"}.to_json }
|
19
27
|
|
28
|
+
let(:client2) { build_client(ignore: %w[ping welcome]) }
|
29
|
+
let(:identifier2) { {channel: channel, name: "chipollone", notify_disconnect: true}.to_json }
|
30
|
+
|
20
31
|
before do
|
21
32
|
subscribe_request = {command: "subscribe", identifier: identifier}
|
22
33
|
|
@@ -44,4 +55,27 @@ feature "Channel state" do
|
|
44
55
|
|
45
56
|
assert_equal msg, client.receive
|
46
57
|
end
|
58
|
+
|
59
|
+
scenario %(
|
60
|
+
Channel state is available in #unsubscribe callbacks
|
61
|
+
) do
|
62
|
+
subscribe_request = {command: "subscribe", identifier: identifier2}
|
63
|
+
|
64
|
+
client2.send(subscribe_request)
|
65
|
+
|
66
|
+
ack = {
|
67
|
+
"identifier" => identifier2, "type" => "confirm_subscription"
|
68
|
+
}
|
69
|
+
|
70
|
+
assert_equal ack, client2.receive
|
71
|
+
|
72
|
+
client2.close
|
73
|
+
|
74
|
+
msg = {
|
75
|
+
"identifier" => identifier,
|
76
|
+
"message" => {"data" => "user left: chipollone"}
|
77
|
+
}
|
78
|
+
|
79
|
+
assert_equal msg, client.receive
|
80
|
+
end
|
47
81
|
end
|
@@ -7,7 +7,7 @@ feature "Request" do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def unsubscribed
|
10
|
-
ActionCable.server.broadcast("request_a", data: "user left")
|
10
|
+
ActionCable.server.broadcast("request_a", {data: "user left"})
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -17,7 +17,7 @@ feature "Request" do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def unsubscribed
|
20
|
-
ActionCable.server.broadcast("request_b", data: "user left")
|
20
|
+
ActionCable.server.broadcast("request_b", {data: "user left"})
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -27,7 +27,7 @@ feature "Request" do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def unsubscribed
|
30
|
-
ActionCable.server.broadcast("request_c", data: "user left#{params[:id].presence}")
|
30
|
+
ActionCable.server.broadcast("request_c", {data: "user left#{params[:id].presence}"})
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -26,7 +26,7 @@ feature "Streams with many clients" do
|
|
26
26
|
scenario %(
|
27
27
|
Multiple clients receive messages from stream
|
28
28
|
) do
|
29
|
-
ActionCable.server.broadcast("a", data: "X")
|
29
|
+
ActionCable.server.broadcast("a", {data: "X"})
|
30
30
|
|
31
31
|
msg = {"identifier" => {channel: channel}.to_json, "message" => {"data" => "X"}}
|
32
32
|
|
@@ -37,7 +37,7 @@ feature "Streams with many clients" do
|
|
37
37
|
scenario %(
|
38
38
|
Client receive messages when another client removes subscription
|
39
39
|
) do
|
40
|
-
ActionCable.server.broadcast("a", data: "X")
|
40
|
+
ActionCable.server.broadcast("a", {data: "X"})
|
41
41
|
|
42
42
|
msg = {"identifier" => {channel: channel}.to_json, "message" => {"data" => "X"}}
|
43
43
|
|
@@ -51,7 +51,7 @@ feature "Streams with many clients" do
|
|
51
51
|
# ActionCable doesn't provide an unsubscription ack :(
|
52
52
|
sleep 1
|
53
53
|
|
54
|
-
ActionCable.server.broadcast("a", data: "Y")
|
54
|
+
ActionCable.server.broadcast("a", {data: "Y"})
|
55
55
|
|
56
56
|
msg2 = {"identifier" => {channel: channel}.to_json, "message" => {"data" => "Y"}}
|
57
57
|
|
@@ -23,13 +23,13 @@ feature "Multiple streams" do
|
|
23
23
|
scenario %(
|
24
24
|
Client receives messages from both streams
|
25
25
|
) do
|
26
|
-
ActionCable.server.broadcast("a", data: "X")
|
26
|
+
ActionCable.server.broadcast("a", {data: "X"})
|
27
27
|
|
28
28
|
msg = {"identifier" => {channel: channel}.to_json, "message" => {"data" => "X"}}
|
29
29
|
|
30
30
|
assert_equal msg, client.receive
|
31
31
|
|
32
|
-
ActionCable.server.broadcast("b", data: "Y")
|
32
|
+
ActionCable.server.broadcast("b", {data: "Y"})
|
33
33
|
|
34
34
|
msg = {"identifier" => {channel: channel}.to_json, "message" => {"data" => "Y"}}
|
35
35
|
|
@@ -39,7 +39,7 @@ feature "Multiple streams" do
|
|
39
39
|
scenario %(
|
40
40
|
Client does not receive messages from any stream after removing subscription
|
41
41
|
) do
|
42
|
-
ActionCable.server.broadcast("a", data: "X")
|
42
|
+
ActionCable.server.broadcast("a", {data: "X"})
|
43
43
|
|
44
44
|
msg = {"identifier" => {channel: channel}.to_json, "message" => {"data" => "X"}}
|
45
45
|
|
@@ -52,8 +52,8 @@ feature "Multiple streams" do
|
|
52
52
|
# ActionCable doesn't provide an unsubscription ack :(
|
53
53
|
sleep 1
|
54
54
|
|
55
|
-
ActionCable.server.broadcast("a", data: "Y")
|
56
|
-
ActionCable.server.broadcast("b", data: "Z")
|
55
|
+
ActionCable.server.broadcast("a", {data: "Y"})
|
56
|
+
ActionCable.server.broadcast("b", {data: "Z"})
|
57
57
|
|
58
58
|
assert_raises(Anyt::Client::TimeoutError) { client.receive(timeout: 0.5) }
|
59
59
|
end
|
@@ -22,13 +22,13 @@ feature "Single stream" do
|
|
22
22
|
scenario %(
|
23
23
|
Client receives messages from the stream
|
24
24
|
) do
|
25
|
-
ActionCable.server.broadcast("a", data: "X")
|
25
|
+
ActionCable.server.broadcast("a", {data: "X"})
|
26
26
|
|
27
27
|
msg = {"identifier" => {channel: channel}.to_json, "message" => {"data" => "X"}}
|
28
28
|
|
29
29
|
assert_equal msg, client.receive
|
30
30
|
|
31
|
-
ActionCable.server.broadcast("a", data: "Y")
|
31
|
+
ActionCable.server.broadcast("a", {data: "Y"})
|
32
32
|
|
33
33
|
msg = {"identifier" => {channel: channel}.to_json, "message" => {"data" => "Y"}}
|
34
34
|
|
@@ -38,7 +38,7 @@ feature "Single stream" do
|
|
38
38
|
scenario %(
|
39
39
|
Client does not receive messages from the stream after removing subscription
|
40
40
|
) do
|
41
|
-
ActionCable.server.broadcast("a", data: "X")
|
41
|
+
ActionCable.server.broadcast("a", {data: "X"})
|
42
42
|
|
43
43
|
msg = {"identifier" => {channel: channel}.to_json, "message" => {"data" => "X"}}
|
44
44
|
|
@@ -51,7 +51,7 @@ feature "Single stream" do
|
|
51
51
|
# ActionCable doesn't provide an unsubscription ack :(
|
52
52
|
sleep 1
|
53
53
|
|
54
|
-
ActionCable.server.broadcast("a", data: "Y")
|
54
|
+
ActionCable.server.broadcast("a", {data: "Y"})
|
55
55
|
|
56
56
|
assert_raises(Anyt::Client::TimeoutError) { client.receive(timeout: 0.5) }
|
57
57
|
end
|
@@ -70,7 +70,7 @@ feature "Single stream" do
|
|
70
70
|
|
71
71
|
assert_equal ack, client.receive
|
72
72
|
|
73
|
-
ActionCable.server.broadcast("a", data: "XX")
|
73
|
+
ActionCable.server.broadcast("a", {data: "XX"})
|
74
74
|
|
75
75
|
msg = {"identifier" => {channel: channel}.to_json, "message" => {"data" => "XX"}}
|
76
76
|
msg2 = {"identifier" => {channel: channel, some_param: "test"}.to_json, "message" => {"data" => "XX"}}
|
@@ -8,7 +8,7 @@ feature "Stop streams" do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def ping(data)
|
11
|
-
ActionCable.server.broadcast data["name"], reply: "pong"
|
11
|
+
ActionCable.server.broadcast data["name"], {reply: "pong"}
|
12
12
|
end
|
13
13
|
|
14
14
|
def unfollow(data)
|
@@ -33,7 +33,7 @@ feature "Stop streams" do
|
|
33
33
|
) do
|
34
34
|
skip if Anyt.config.use_action_cable && (::ActionCable::VERSION::MAJOR < 6 || ::ActionCable::VERSION::MINOR < 1)
|
35
35
|
|
36
|
-
ActionCable.server.broadcast("a", data: "X")
|
36
|
+
ActionCable.server.broadcast("a", {data: "X"})
|
37
37
|
|
38
38
|
msg = {"identifier" => {channel: channel}.to_json, "message" => {"data" => "X"}}
|
39
39
|
|
@@ -47,9 +47,9 @@ feature "Stop streams" do
|
|
47
47
|
client.send(perform_request)
|
48
48
|
sleep 0.2 # give some time to commit unsubscribe
|
49
49
|
|
50
|
-
ActionCable.server.broadcast("a", data: "Y")
|
50
|
+
ActionCable.server.broadcast("a", {data: "Y"})
|
51
51
|
sleep 0.2 # "a" should be broadcasted first
|
52
|
-
ActionCable.server.broadcast("b", data: "Z")
|
52
|
+
ActionCable.server.broadcast("b", {data: "Z"})
|
53
53
|
|
54
54
|
msg = {"identifier" => {channel: channel}.to_json, "message" => {"data" => "Z"}}
|
55
55
|
assert_equal msg, client.receive
|
data/lib/anyt/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: anyt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- palkan
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -58,28 +58,48 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '6.0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '6.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: anyway_config
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.2.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.2.0
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: anycable-rails
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
|
-
- - "
|
87
|
+
- - ">"
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version: 1.0.
|
89
|
+
version: 1.0.99
|
90
|
+
- - "<"
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '2.0'
|
76
93
|
type: :runtime
|
77
94
|
prerelease: false
|
78
95
|
version_requirements: !ruby/object:Gem::Requirement
|
79
96
|
requirements:
|
80
|
-
- - "
|
97
|
+
- - ">"
|
81
98
|
- !ruby/object:Gem::Version
|
82
|
-
version: 1.0.
|
99
|
+
version: 1.0.99
|
100
|
+
- - "<"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '2.0'
|
83
103
|
- !ruby/object:Gem::Dependency
|
84
104
|
name: redis
|
85
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -243,7 +263,7 @@ homepage: http://github.com/anycable/anyt
|
|
243
263
|
licenses:
|
244
264
|
- MIT
|
245
265
|
metadata: {}
|
246
|
-
post_install_message:
|
266
|
+
post_install_message:
|
247
267
|
rdoc_options: []
|
248
268
|
require_paths:
|
249
269
|
- lib
|
@@ -258,8 +278,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
258
278
|
- !ruby/object:Gem::Version
|
259
279
|
version: '0'
|
260
280
|
requirements: []
|
261
|
-
rubygems_version: 3.
|
262
|
-
signing_key:
|
281
|
+
rubygems_version: 3.2.22
|
282
|
+
signing_key:
|
263
283
|
specification_version: 4
|
264
284
|
summary: Anycable conformance testing tool
|
265
285
|
test_files: []
|