async-dns 0.12.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0302e920c59ef8d4ce72eaa34c0a442536304590
4
- data.tar.gz: eede22f4c518bfa0dcf094933083aeda33bc82a1
3
+ metadata.gz: a69c3e892e1022681eb81ec89cf6953b27f2dd65
4
+ data.tar.gz: f4b1bbfe1e36b9bae37681343c4eb1bc71f5b621
5
5
  SHA512:
6
- metadata.gz: 60687d211cdcee0afecee281daa5ae79322713b0adff0baf78f2c82ef700ebe99e056dc5f40d14a059f3a0d5a18c5741091b2a20cfe61bb8efd184b201c789a3
7
- data.tar.gz: '052292c7a58dcbfa650d902a7c7b15097fe1d7e1dd2b06ebda5d5009f68c7fc3ed130cbaeb36be26ee0a8f04b0099d7be080e028bcbe35016661e75c4d76f6cb'
6
+ metadata.gz: 0dc107b7e33810d8a45fdb660dfc7421ad95383d8e14db6006175a335b0cc80500065e2c78c3d80ef53291a2ae8f3617a5cdb081475009ddff5c0edf3ff06576
7
+ data.tar.gz: 3209d74dc8a3ae956acb687da50ac5049f5c5a4be820ae8e5f1ca88c3c02b1bcd077e02ba33a23a498d90f8cd86b2ad52b2582907c734ccfee45f4372487cb42
data/.rspec CHANGED
@@ -1,4 +1,3 @@
1
- --color
2
1
  --format documentation
3
2
  --warnings
4
3
  --require spec_helper
@@ -6,14 +6,17 @@ addons:
6
6
  apt:
7
7
  packages:
8
8
  - bind9
9
- rvm:
10
- - 2.1
11
- - 2.2
12
- - 2.3
13
- - 2.4
14
- - ruby-head
15
- - jruby-head
9
+
16
10
  matrix:
11
+ include:
12
+ - rvm: 2.1
13
+ - rvm: 2.2
14
+ - rvm: 2.3
15
+ - rvm: 2.4
16
+ - rvm: ruby-head
17
+ - rvm: jruby-head
18
+ env:
19
+ - JRUBY_OPTS="--debug -X+O"
17
20
  allow_failures:
18
21
  - rvm: ruby-head
19
- - rvm: jruby-head
22
+ - rvm: jruby-head
data/Gemfile CHANGED
@@ -7,6 +7,12 @@ group :development do
7
7
  end
8
8
 
9
9
  group :test do
10
+ gem 'ruby-prof', platforms: [:mri]
11
+ gem "benchmark-ips"
12
+
10
13
  gem 'simplecov'
11
14
  gem 'coveralls', require: false
15
+
16
+ # For comparisons:
17
+ gem "nokogiri"
12
18
  end
data/README.md CHANGED
@@ -28,6 +28,7 @@ Or install it yourself as:
28
28
 
29
29
  Here is a simple example showing how to use the resolver:
30
30
 
31
+ ```ruby
31
32
  Async::Reactor.run do
32
33
  resolver = Async::DNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
33
34
 
@@ -36,11 +37,13 @@ Here is a simple example showing how to use the resolver:
36
37
  puts addresses.inspect
37
38
  end
38
39
  => [#<Resolv::IPv4 202.124.127.240>, #<Resolv::IPv4 202.124.127.216>, #<Resolv::IPv4 202.124.127.223>, #<Resolv::IPv4 202.124.127.227>, #<Resolv::IPv4 202.124.127.234>, #<Resolv::IPv4 202.124.127.230>, #<Resolv::IPv4 202.124.127.208>, #<Resolv::IPv4 202.124.127.249>, #<Resolv::IPv4 202.124.127.219>, #<Resolv::IPv4 202.124.127.218>, #<Resolv::IPv4 202.124.127.212>, #<Resolv::IPv4 202.124.127.241>, #<Resolv::IPv4 202.124.127.238>, #<Resolv::IPv4 202.124.127.245>, #<Resolv::IPv4 202.124.127.251>, #<Resolv::IPv4 202.124.127.229>]
40
+ ```
39
41
 
40
42
  ### Server
41
43
 
42
44
  Here is a simple example showing how to use the server:
43
45
 
46
+ ```ruby
44
47
  require 'async/dns'
45
48
 
46
49
  class TestServer < Async::DNS::Server
@@ -51,9 +54,10 @@ Here is a simple example showing how to use the server:
51
54
  end
52
55
  end
53
56
 
54
- server = TestServer.new(listen: [[:udp, '127.0.0.1', 2346]])
57
+ server = TestServer.new([[:udp, '127.0.0.1', 2346]])
55
58
 
56
59
  server.run
60
+ ```
57
61
 
58
62
  Then to test you could use `dig` like so:
59
63
 
data/Rakefile CHANGED
@@ -24,7 +24,7 @@ task :server do
24
24
  end
25
25
  end
26
26
 
27
- server = TestServer.new(listen: [[:udp, '127.0.0.1', 2346]])
27
+ server = TestServer.new([[:udp, '127.0.0.1', 2346]])
28
28
 
29
29
  Async::Reactor.run do
30
30
  server.run
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.require_paths = ["lib"]
22
22
  spec.has_rdoc = "yard"
23
23
 
24
- spec.add_dependency("async-io", "~> 0.1")
24
+ spec.add_dependency("async-io", "~> 1.0")
25
25
 
26
26
  spec.add_development_dependency "async-rspec", "~> 1.0"
27
27
  spec.add_development_dependency "process-daemon", "~> 1.0"
@@ -22,15 +22,15 @@ require_relative 'transport'
22
22
 
23
23
  module Async::DNS
24
24
  class GenericHandler
25
- def initialize(server, address)
25
+ def initialize(server, endpoint)
26
26
  @server = server
27
- @address = address
27
+ @endpoint = endpoint
28
28
 
29
29
  @logger = @server.logger || Async.logger
30
30
  end
31
31
 
32
32
  attr :server
33
- attr :address
33
+ attr :endpoint
34
34
 
35
35
  def error_response(query = nil, code = Resolv::DNS::RCode::ServFail)
36
36
  # Encoding may fail, so we need to handle this particular case:
@@ -68,7 +68,7 @@ module Async::DNS
68
68
  # Handling incoming UDP requests, which are single data packets, and pass them on to the given server.
69
69
  class DatagramHandler < GenericHandler
70
70
  def run(task: Async::Task.current)
71
- @address.bind do |socket|
71
+ @endpoint.bind do |socket|
72
72
  while true
73
73
  Async.logger.debug(self.class.name) {"-> socket.recvfrom"}
74
74
  input_data, remote_address = socket.recvmsg(UDP_TRUNCATION_SIZE)
@@ -110,7 +110,7 @@ module Async::DNS
110
110
 
111
111
  class StreamHandler < GenericHandler
112
112
  def run(task: Async::Task.current)
113
- @address.accept do |client, address|
113
+ @endpoint.accept do |client, address|
114
114
  handle_connection(client)
115
115
  end
116
116
  end
@@ -24,7 +24,7 @@ require 'resolv-replace'
24
24
  module Async::DNS
25
25
  module Replace
26
26
  class << self
27
- attr :resolver, true
27
+ attr_accessor :resolver
28
28
 
29
29
  def resolver?
30
30
  resolver != nil
@@ -46,8 +46,8 @@ module Async::DNS
46
46
  # Servers are specified in the same manor as options[:listen], e.g.
47
47
  # [:tcp/:udp, address, port]
48
48
  # In the case of multiple servers, they will be checked in sequence.
49
- def initialize(servers, origin: nil, logger: Async.logger, timeout: DEFAULT_TIMEOUT)
50
- @servers = servers
49
+ def initialize(endpoints, origin: nil, logger: Async.logger, timeout: DEFAULT_TIMEOUT)
50
+ @endpoints = endpoints
51
51
 
52
52
  @origin = origin
53
53
  @logger = logger
@@ -97,14 +97,14 @@ module Async::DNS
97
97
  retries = options.fetch(:retries, DEFAULT_RETRIES)
98
98
  delay = options.fetch(:delay, DEFAULT_DELAY)
99
99
 
100
- records = lookup(name, resource_class, cache) do |name, resource_class|
100
+ records = lookup(name, resource_class, cache) do |lookup_name, lookup_resource_class|
101
101
  response = nil
102
102
 
103
103
  retries.times do |i|
104
104
  # Wait 10ms before trying again:
105
105
  sleep delay if delay and i > 0
106
106
 
107
- response = query(name, resource_class)
107
+ response = query(lookup_name, lookup_resource_class)
108
108
 
109
109
  break if response
110
110
  end
@@ -134,18 +134,18 @@ module Async::DNS
134
134
 
135
135
  # Send the message to available servers. If no servers respond correctly, nil is returned. This result indicates a failure of the resolver to correctly contact any server and get a valid response.
136
136
  def dispatch_request(message, task: Async::Task.current)
137
- request = Request.new(message, @servers)
137
+ request = Request.new(message, @endpoints)
138
138
 
139
- request.each do |address|
140
- @logger.debug "[#{message.id}] Sending request #{message.question.inspect} to address #{address.inspect}" if @logger
139
+ request.each do |endpoint|
140
+ @logger.debug "[#{message.id}] Sending request #{message.question.inspect} to address #{endpoint.inspect}" if @logger
141
141
 
142
142
  begin
143
143
  response = nil
144
144
 
145
145
  task.timeout(@timeout) do
146
- @logger.debug "[#{message.id}] -> Try address #{address}" if @logger
147
- response = try_server(request, address)
148
- @logger.debug "[#{message.id}] <- Try address #{address} = #{response}" if @logger
146
+ @logger.debug "[#{message.id}] -> Try address #{endpoint}" if @logger
147
+ response = try_server(request, endpoint)
148
+ @logger.debug "[#{message.id}] <- Try address #{endpoint} = #{response}" if @logger
149
149
  end
150
150
 
151
151
  if valid_response(message, response)
@@ -175,8 +175,8 @@ module Async::DNS
175
175
  response = yield(name, resource_class)
176
176
 
177
177
  if response
178
- response.answer.each do |name, ttl, record|
179
- (records[name] ||= []) << record
178
+ response.answer.each do |name_in_answer, ttl, record|
179
+ (records[name_in_answer] ||= []) << record
180
180
  end
181
181
  end
182
182
 
@@ -184,14 +184,14 @@ module Async::DNS
184
184
  end
185
185
  end
186
186
 
187
- def try_server(request, address)
188
- case address.type
187
+ def try_server(request, endpoint)
188
+ case endpoint.socket_type
189
189
  when Socket::SOCK_DGRAM
190
- try_datagram_server(request, address)
190
+ try_datagram_server(request, endpoint)
191
191
  when Socket::SOCK_STREAM
192
- try_stream_server(request, address)
192
+ try_stream_server(request, endpoint)
193
193
  else
194
- raise InvalidProtocolError.new(address)
194
+ raise InvalidProtocolError.new(endpoint)
195
195
  end
196
196
  end
197
197
 
@@ -209,8 +209,8 @@ module Async::DNS
209
209
  return false
210
210
  end
211
211
 
212
- def try_datagram_server(request, address, task: Async::Task.current)
213
- address.connect do |socket|
212
+ def try_datagram_server(request, endpoint, task: Async::Task.current)
213
+ endpoint.connect do |socket|
214
214
  socket.sendmsg(request.packet, 0)
215
215
 
216
216
  data, peer = socket.recvmsg(UDP_TRUNCATION_SIZE)
@@ -219,10 +219,10 @@ module Async::DNS
219
219
  end
220
220
  end
221
221
 
222
- def try_stream_server(request, address)
222
+ def try_stream_server(request, endpoint)
223
223
  context = Async::Task.current
224
224
 
225
- address.connect do |socket|
225
+ endpoint.connect do |socket|
226
226
  StreamTransport.write_chunk(socket, request.packet)
227
227
 
228
228
  input_data = StreamTransport.read_chunk(socket)
@@ -233,15 +233,15 @@ module Async::DNS
233
233
 
234
234
  # Manages a single DNS question message across one or more servers.
235
235
  class Request
236
- def initialize(message, servers)
236
+ def initialize(message, endpoints)
237
237
  @message = message
238
238
  @packet = message.encode
239
239
 
240
- @servers = servers.dup
240
+ @endpoints = endpoints.dup
241
241
 
242
242
  # We select the protocol based on the size of the data:
243
243
  if @packet.bytesize > UDP_TRUNCATION_SIZE
244
- @servers.delete_if{|server| server[0] == :udp}
244
+ @endpoints.delete_if{|server| server[0] == :udp}
245
245
  end
246
246
  end
247
247
 
@@ -250,7 +250,7 @@ module Async::DNS
250
250
  attr :logger
251
251
 
252
252
  def each(&block)
253
- Async::IO::Address.each(@servers, &block)
253
+ Async::IO::Endpoint.each(@endpoints, &block)
254
254
  end
255
255
 
256
256
  def update_id!(id)
@@ -19,7 +19,7 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  require 'async'
22
- require 'async/io/address'
22
+ require 'async/io/endpoint'
23
23
 
24
24
  require_relative 'transaction'
25
25
  require_relative 'logger'
@@ -27,7 +27,7 @@ require_relative 'logger'
27
27
  module Async::DNS
28
28
  class Server
29
29
  # The default server interfaces
30
- DEFAULT_INTERFACES = [[:udp, "0.0.0.0", 53], [:tcp, "0.0.0.0", 53]]
30
+ DEFAULT_ENDPOINTS = [[:udp, "0.0.0.0", 53], [:tcp, "0.0.0.0", 53]]
31
31
 
32
32
  # Instantiate a server with a block
33
33
  #
@@ -37,8 +37,8 @@ module Async::DNS
37
37
  # end
38
38
  # end
39
39
  #
40
- def initialize(listen: DEFAULT_INTERFACES, origin: '.', logger: Async.logger)
41
- @interfaces = listen
40
+ def initialize(endpoints = DEFAULT_ENDPOINTS, origin: '.', logger: Async.logger)
41
+ @endpoints = endpoints
42
42
  @origin = origin
43
43
  @logger = logger
44
44
 
@@ -124,14 +124,14 @@ module Async::DNS
124
124
  def setup_handlers
125
125
  fire(:setup)
126
126
 
127
- Async::IO::Address.each(@interfaces) do |address|
128
- case address.type
127
+ Async::IO::Endpoint.each(@endpoints) do |endpoint|
128
+ case endpoint.socket_type
129
129
  when Socket::SOCK_DGRAM
130
- @logger.info "<> Listening for datagrams on #{address.inspect}"
131
- @handlers << DatagramHandler.new(self, address)
130
+ @logger.info "<> Listening for datagrams on #{endpoint.inspect}"
131
+ @handlers << DatagramHandler.new(self, endpoint)
132
132
  when Socket::SOCK_STREAM
133
- @logger.info "<> Listening for connections on #{address.inspect}"
134
- @handlers << StreamHandler.new(self, address)
133
+ @logger.info "<> Listening for connections on #{endpoint.inspect}"
134
+ @handlers << StreamHandler.new(self, endpoint)
135
135
  else
136
136
  raise ArgumentError.new("Don't know how to handle #{address}")
137
137
  end
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Async
22
22
  module DNS
23
- VERSION = '0.12.0'
23
+ VERSION = '1.0.0'
24
24
  end
25
25
  end
@@ -25,7 +25,7 @@ describe Async::DNS::StreamHandler do
25
25
  include_context Async::RSpec::Reactor
26
26
 
27
27
  let(:server) {Async::DNS::Server.new}
28
- let(:address) {Async::IO::Address.tcp('127.0.0.1', 6666)}
28
+ let(:address) {Async::IO::Endpoint.tcp('127.0.0.1', 6666)}
29
29
 
30
30
  subject {described_class.new(server, address)}
31
31
 
@@ -44,7 +44,7 @@ describe Async::DNS::DatagramHandler do
44
44
  include_context Async::RSpec::Reactor
45
45
 
46
46
  let(:server) {Async::DNS::Server.new}
47
- let(:address) {Async::IO::Address.udp('127.0.0.1', 6666)}
47
+ let(:address) {Async::IO::Endpoint.udp('127.0.0.1', 6666)}
48
48
 
49
49
  subject {described_class.new(server, address)}
50
50
 
@@ -38,7 +38,7 @@ module Async::DNS::IPv6Spec
38
38
  include_context Async::RSpec::Reactor
39
39
 
40
40
  let(:server_interfaces) {[[:tcp, '::', 2004]]}
41
- let(:server) {TestServer.new(listen: server_interfaces)}
41
+ let(:server) {TestServer.new(server_interfaces)}
42
42
 
43
43
  it "should connect to the server using TCP via IPv6" do
44
44
  task = server.run
@@ -59,7 +59,7 @@ module Async::DNS::IPv6Spec
59
59
  include_context Async::RSpec::Reactor
60
60
 
61
61
  let(:server_interfaces) {[[:udp, '::', 2006]]}
62
- let(:server) {TestServer.new(listen: server_interfaces)}
62
+ let(:server) {TestServer.new(server_interfaces)}
63
63
 
64
64
  it "should connect to the server using UDP via IPv6" do
65
65
  task = server.run
@@ -25,28 +25,49 @@ require 'benchmark'
25
25
  require 'process/daemon'
26
26
 
27
27
  module Async::DNS::ServerPerformanceSpec
28
- describe Async::DNS::Server do
29
- include_context Async::RSpec::Reactor
28
+ class MillionServer < Async::DNS::Server
29
+ def initialize(*)
30
+ super
31
+
32
+ @domains = {}
33
+
34
+ (1..5_000).each do |i|
35
+ domain = "domain#{i}.local"
36
+
37
+ @domains[domain] = "#{69}.#{(i >> 16)%256}.#{(i >> 8)%256}.#{i%256}"
38
+ end
39
+ end
30
40
 
31
- context 'benchmark' do
32
- class MillionServer < Async::DNS::Server
33
- def initialize(*)
34
- super
35
-
36
- @million = {}
37
-
38
- (1..5_000).each do |i|
39
- domain = "domain#{i}.local"
41
+ attr :domains
42
+
43
+ def process(name, resource_class, transaction)
44
+ transaction.respond!(@domains[name])
45
+ end
46
+ end
40
47
 
41
- @million[domain] = "#{69}.#{(i >> 16)%256}.#{(i >> 8)%256}.#{i%256}"
42
- end
43
- end
44
-
45
- def process(name, resource_class, transaction)
46
- transaction.respond!(@million[name])
47
- end
48
+ RSpec.describe MillionServer do
49
+ # include_context "profile"
50
+ include_context Async::RSpec::Reactor
51
+
52
+ let(:interfaces) {[[:udp, '127.0.0.1', 8899]]}
53
+ let(:server) {MillionServer.new(interfaces)}
54
+ let(:resolver) {Async::DNS::Resolver.new(interfaces)}
55
+
56
+ it "should be fast" do
57
+ task = server.run
58
+
59
+ server.domains.each do |name, address|
60
+ resolved = resolver.addresses_for(name)
48
61
  end
49
62
 
63
+ task.stop
64
+ end
65
+ end
66
+
67
+ RSpec.describe Async::DNS::Server do
68
+ include_context Async::RSpec::Reactor
69
+
70
+ context 'benchmark' do
50
71
  class AsyncServerDaemon < Process::Daemon
51
72
  def working_directory
52
73
  File.expand_path("../tmp", __FILE__)
@@ -58,7 +79,7 @@ module Async::DNS::ServerPerformanceSpec
58
79
 
59
80
  def startup
60
81
  puts "Starting DNS server..."
61
- @server = MillionServer.new(listen: [[:udp, '0.0.0.0', 5300]])
82
+ @server = MillionServer.new([[:udp, '0.0.0.0', 5300]])
62
83
 
63
84
  reactor.async do
64
85
  @task = @server.run
@@ -121,13 +142,15 @@ module Async::DNS::ServerPerformanceSpec
121
142
  resolver = Async::DNS::Resolver.new([[:udp, '127.0.0.1', port]])
122
143
 
123
144
  x.report(name) do
124
- # Number of requests remaining since this is an asynchronous event loop:
125
- 5.times do
126
- pending = @domains.size
127
-
128
- resolved = @domains.collect{|domain| resolver.addresses_for(domain)}
145
+ Async::Reactor.run do
146
+ # Number of requests remaining since this is an asynchronous event loop:
147
+ 5.times do
148
+ pending = @domains.size
129
149
 
130
- expect(resolved).to_not include(nil)
150
+ resolved = @domains.collect{|domain| resolver.addresses_for(domain)}
151
+
152
+ expect(resolved).to_not include(nil)
153
+ end
131
154
  end
132
155
  end
133
156
  end
@@ -39,7 +39,7 @@ module Async::DNS::SlowServerSpec
39
39
  include_context Async::RSpec::Reactor
40
40
 
41
41
  let(:server_interfaces) {[[:udp, '0.0.0.0', 5330], [:tcp, '0.0.0.0', 5330]]}
42
- let(:server) {SlowServer.new(listen: server_interfaces)}
42
+ let(:server) {SlowServer.new(server_interfaces)}
43
43
 
44
44
  around(:each) do |example|
45
45
  begin
@@ -38,7 +38,7 @@ module Async::DNS::SocketSpec
38
38
  include_context Async::RSpec::Reactor
39
39
 
40
40
  let(:server_interfaces) {[TCPServer.new('127.0.0.1', 2002)]}
41
- let(:server) {TestServer.new(listen: server_interfaces)}
41
+ let(:server) {TestServer.new(server_interfaces)}
42
42
 
43
43
  it "should create server with existing TCP socket" do
44
44
  task = server.run
@@ -56,7 +56,7 @@ module Async::DNS::SocketSpec
56
56
  include_context Async::RSpec::Reactor
57
57
 
58
58
  let(:server_interfaces) {[UDPSocket.new.tap{|socket| socket.bind('127.0.0.1', 2002)}]}
59
- let(:server) {TestServer.new(listen: server_interfaces)}
59
+ let(:server) {TestServer.new(server_interfaces)}
60
60
 
61
61
  it "should create server with existing UDP socket" do
62
62
  task = server.run
@@ -42,7 +42,7 @@ module Async::DNS::TruncationSpec
42
42
  describe "Async::DNS Truncation Server" do
43
43
  include_context Async::RSpec::Reactor
44
44
 
45
- let(:server) {TestServer.new(listen: SERVER_PORTS)}
45
+ let(:server) {TestServer.new(SERVER_PORTS)}
46
46
 
47
47
  it "should use tcp because of large response" do
48
48
  task = server.run
@@ -26,7 +26,26 @@ require "bundler/setup"
26
26
  require "async/rspec"
27
27
  require "async/dns"
28
28
 
29
- # abort "Warning, ulimit is too low!" if `ulimit -n`.to_i < 10000
29
+ begin
30
+ require 'ruby-prof'
31
+
32
+ RSpec.shared_context "profile" do
33
+ around(:each) do |example|
34
+ profile = RubyProf.profile(merge_fibers: true) do
35
+ example.run
36
+ end
37
+
38
+ printer = RubyProf::FlatPrinter.new(profile)
39
+ printer.print(STDOUT)
40
+ end
41
+ end
42
+ rescue LoadError
43
+ RSpec.shared_context "profile" do
44
+ before(:all) do
45
+ puts "Profiling not supported on this platform."
46
+ end
47
+ end
48
+ end
30
49
 
31
50
  RSpec.configure do |config|
32
51
  # Enable flags like --only-failures and --next-failure
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-dns
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-25 00:00:00.000000000 Z
11
+ date: 2017-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-io
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.1'
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.1'
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: async-rspec
29
29
  requirement: !ruby/object:Gem::Requirement