unbound 1.0.1 → 2.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: 268e920fce264b5a8fb5a60fc0f3b98d2648adde
4
- data.tar.gz: fabfee310e6715df1e05e7ba455ae9fc64ae8f47
3
+ metadata.gz: 3cc064fa99fcaf867d9474ede41d93ad258742e4
4
+ data.tar.gz: dd0dd181466af047705bb39f94db521141eaa752
5
5
  SHA512:
6
- metadata.gz: 634924d61b650aeba4ee82632b34d95040da7aec61ac8a0a632fc3c4b48aeb082c0aca829b0baac77d5647880b933bf711f24f87b88eecc740489f3361dec432
7
- data.tar.gz: 8029d61671926ea5874d9c2c4060cf788e11eae74e8c4d60228b9613263ee4ede4b39b20f04767a2565cea8141eb5291cf1289c55aaebeca75501dd02709560a
6
+ metadata.gz: 51c16931c919a0635208f7ec37f4820f5a7b53e9ec7de05d34f8f0c52d0496dd3e2be8684bf7ac3fedf0cb91565d8c9a14076885b789efd91eda13efbb708f81
7
+ data.tar.gz: b24c0751df53c3e44418db0c85de1b8678c9bd0f0a6180511316ba88adcf39bb17c499a458927661a38b6d5545b8fd9cc0bee76249a37ce59fdbdadbec9e67f1
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.1
1
+ 2.0.0
@@ -71,10 +71,17 @@ module Unbound
71
71
  raise_if_error!(Unbound::Bindings.ub_cancel(@ub_ctx, async_id))
72
72
  end
73
73
 
74
+ # Returns a brand new IO for the file descriptor that can be selected to
75
+ # determine if processing needs to be done.
76
+ # Warning: DO NOT CLOSE THIS IO OBJECT! Use Context#close, instead.
77
+ # @return [FFI::IO] a brand new IO for the context's file descriptor
74
78
  def io
75
- return ::FFI::IO.for_fd(self.fd)
79
+ ret = ::FFI::IO.for_fd(self.fd)
80
+ ret.autoclose = false
81
+ return ret
76
82
  end
77
83
 
84
+ # Returns the number for the file descriptor.
78
85
  def fd
79
86
  check_closed!
80
87
  Unbound::Bindings.ub_fd(@ub_ctx)
@@ -65,6 +65,7 @@ module Unbound
65
65
  private
66
66
  def finish!()
67
67
  @state = STATE_FINISHED
68
+ @async_id = nil
68
69
  @callbacks_finish.call(self)
69
70
  clear_callbacks!
70
71
  end
@@ -20,16 +20,18 @@ module Unbound
20
20
 
21
21
  init_callbacks
22
22
 
23
- on_cancel do |query|
24
- if query.async_id
25
- @ctx.cancel_async_query(query.async_id)
26
- end
27
- end
28
23
  on_finish do |query|
29
24
  @queries.delete_query(query)
30
25
  end
31
26
  end
32
27
 
28
+ # @param [Unbound::Query] query The query that will be canceled
29
+ def cancel_query(query)
30
+ return if query.async_id.nil?
31
+ @ctx.cancel_async_query(query.async_id)
32
+ query.cancel!
33
+ end
34
+
33
35
  # @return [Integer] the number of queries for which we are awaiting reply
34
36
  def outstanding_queries
35
37
  @queries.count
@@ -63,7 +65,7 @@ module Unbound
63
65
  # Cancel all outstanding queries.
64
66
  def cancel_all
65
67
  @queries.each do |query|
66
- query.cancel!
68
+ cancel_query(query)
67
69
  end
68
70
  @queries.clear
69
71
  end
@@ -98,7 +100,8 @@ module Unbound
98
100
  query.on_start(*@callbacks_start) unless @callbacks_start.empty?
99
101
  query.on_answer(*@callbacks_answer) unless @callbacks_answer.empty?
100
102
  query.on_error(*@callbacks_error) unless @callbacks_error.empty?
101
- query.on_cancel(*@callbacks_cancel)
103
+ query.on_cancel(*@callbacks_cancel) unless @callbacks_cancel.empty?
104
+
102
105
  query.on_finish(*@callbacks_finish)
103
106
  ptr = @queries.store(query)
104
107
  async_id = @ctx.resolve_async(
@@ -139,6 +139,33 @@ describe Unbound::Context do
139
139
  end
140
140
  end
141
141
 
142
+ describe "#io" do
143
+ it "should return an IO object" do
144
+ expect(@ctx.io).to be_a(::IO)
145
+ end
146
+
147
+ it "should return a new IO object for each call" do
148
+ expect(@ctx.io).not_to be(@ctx.io)
149
+ end
150
+
151
+ it "should not be set to autoclose" do
152
+ expect(@ctx.io.autoclose?).to be_false
153
+ end
154
+
155
+ it "should not autoclose when garbage collection occurs" do
156
+ do_gc = lambda { ObjectSpace.garbage_collect }
157
+
158
+ if Object.const_defined?(:JRuby)
159
+ # Try to get some GC under JRuby
160
+ do_gc = lambda { java.lang.System.gc() }
161
+ end
162
+ ::IO::select([@ctx.io], nil, nil, 0)
163
+ do_gc.call()
164
+ expect {
165
+ ::IO::select([@ctx.io], nil, nil, 0)
166
+ }.not_to raise_error
167
+ end
168
+ end
142
169
 
143
170
  describe "asynchronous query processing via select/process" do
144
171
  before :each do
@@ -33,6 +33,22 @@ describe Unbound::Query do
33
33
  end
34
34
  end
35
35
 
36
+ describe "#async_id" do
37
+ it "should be nil if the query hasn't been started" do
38
+ expect(@query.async_id).to be_nil
39
+ end
40
+ it "should be the proper value if it has been started" do
41
+ expect(@query.async_id).to be_nil
42
+ @query.start!(1234)
43
+ expect(@query.async_id).to eq(1234)
44
+ end
45
+ it "should be nil if the query has been finished" do
46
+ @query.start!(1234)
47
+ @query.cancel!
48
+ expect(@query.async_id).to be_nil
49
+ end
50
+ end
51
+
36
52
  describe "#start!" do
37
53
  it "should set the async_id" do
38
54
  expect(@query.async_id).to be_nil
@@ -66,6 +82,11 @@ describe Unbound::Query do
66
82
  end
67
83
 
68
84
  describe "#error!" do
85
+ before :each do
86
+ @async_id = 9999
87
+ @query.start!(@async_id)
88
+ end
89
+
69
90
  it "should require an error code as an argument" do
70
91
  expect {
71
92
  @query.error!
@@ -79,9 +100,19 @@ describe Unbound::Query do
79
100
  @query.error!(1234)
80
101
  expect(@query).to be_finished
81
102
  end
103
+
104
+ it "should have set async_id to nil" do
105
+ @query.error!(1234)
106
+ expect(@query.async_id).to be_nil
107
+ end
82
108
  end
83
109
 
84
110
  describe "#answer!" do
111
+ before :each do
112
+ @async_id = 9999
113
+ @query.start!(@async_id)
114
+ end
115
+
85
116
  it "should require a result as an argument" do
86
117
  expect {
87
118
  @query.answer!
@@ -97,9 +128,20 @@ describe Unbound::Query do
97
128
  @query.answer!(result)
98
129
  expect(@query).to be_finished
99
130
  end
131
+
132
+ it "should have set async_id to nil" do
133
+ result = double("Result")
134
+ @query.answer!(result)
135
+ expect(@query.async_id).to be_nil
136
+ end
100
137
  end
101
138
 
102
139
  describe "#cancel!" do
140
+ before :each do
141
+ @async_id = 9999
142
+ @query.start!(@async_id)
143
+ end
144
+
103
145
  it "should require that no arguments be specified" do
104
146
  expect {
105
147
  @query.cancel!(1234)
@@ -113,6 +155,11 @@ describe Unbound::Query do
113
155
  @query.cancel!
114
156
  expect(@query).to be_finished
115
157
  end
158
+
159
+ it "should have set async_id to nil" do
160
+ @query.cancel!
161
+ expect(@query.async_id).to be_nil
162
+ end
116
163
  end
117
164
 
118
165
 
@@ -29,6 +29,20 @@ describe Unbound::QueryStore do
29
29
  end
30
30
  expect(actual_queries).to match_array(expected_queries)
31
31
  end
32
+ it "should not yield deleted queries" do
33
+ q1 = new_query(1)
34
+ q2 = new_query(2)
35
+ q3 = new_query(3)
36
+ query_store.store(q1)
37
+ query_store.store(q2)
38
+ query_store.store(q3)
39
+ query_store.delete_query(q2)
40
+ remaining_queries = []
41
+ query_store.each do |query|
42
+ remaining_queries << query
43
+ end
44
+ expect(remaining_queries).to match_array([q1, q3])
45
+ end
32
46
  end
33
47
  describe "#clear" do
34
48
  it "should cause the count to drop to 0" do
@@ -9,29 +9,71 @@ describe Unbound::Resolver do
9
9
  after :each do
10
10
  @resolver.close unless @resolver.closed?
11
11
  end
12
+
13
+ let(:query) { Unbound::Query.new("localhost", 1, 1) }
12
14
 
13
15
  describe "#cancel_all" do
14
16
  it "should cancel all queries" do
15
- query1 = Unbound::Query.new("localhost", 1, 1)
16
17
  expect { |cb|
17
- query1.on_cancel(cb.to_proc)
18
- @resolver.send_query(query1)
18
+ query.on_cancel(cb.to_proc)
19
+ @resolver.send_query(query)
19
20
  @resolver.cancel_all
20
21
  }.to yield_control
21
22
  end
22
23
  end
23
24
 
24
25
  describe "#outstanding_queries" do
25
- it "should return the number of outstanding queries" do
26
+ it "should be zero if there are no queries" do
26
27
  expect(@resolver.outstanding_queries).to eq(0)
27
- 10.times do
28
- query = Unbound::Query.new("localhost", 1, 1)
29
- @resolver.send_query(query)
30
- end
31
- expect(@resolver.outstanding_queries).to eq(10)
32
- @resolver.cancel_all
28
+ end
29
+
30
+ it "should go up by one for each query added" do
31
+ q1 = Unbound::Query.new("localhost", 1, 1)
32
+ q2 = Unbound::Query.new("localhost", 1, 1)
33
+ q3 = Unbound::Query.new("localhost", 1, 1)
34
+ q4 = Unbound::Query.new("localhost", 1, 1)
35
+ expect(@resolver.outstanding_queries).to eq(0)
36
+ @resolver.send_query(q1)
37
+ expect(@resolver.outstanding_queries).to eq(1)
38
+ @resolver.send_query(q2)
39
+ expect(@resolver.outstanding_queries).to eq(2)
40
+ @resolver.send_query(q3)
41
+ expect(@resolver.outstanding_queries).to eq(3)
42
+ @resolver.send_query(q4)
43
+ expect(@resolver.outstanding_queries).to eq(4)
44
+ end
45
+
46
+ it "should drop by one for each query canceled" do
47
+ q1 = Unbound::Query.new("localhost", 1, 1)
48
+ q2 = Unbound::Query.new("localhost", 1, 1)
49
+ q3 = Unbound::Query.new("localhost", 1, 1)
50
+ q4 = Unbound::Query.new("localhost", 1, 1)
51
+ @resolver.send_query(q1)
52
+ @resolver.send_query(q2)
53
+ @resolver.send_query(q3)
54
+ @resolver.send_query(q4)
55
+ expect(@resolver.outstanding_queries).to eq(4)
56
+ @resolver.cancel_query(q1)
57
+ expect(@resolver.outstanding_queries).to eq(3)
58
+ @resolver.cancel_query(q2)
59
+ expect(@resolver.outstanding_queries).to eq(2)
60
+ @resolver.cancel_query(q3)
61
+ expect(@resolver.outstanding_queries).to eq(1)
62
+ @resolver.cancel_query(q4)
33
63
  expect(@resolver.outstanding_queries).to eq(0)
34
64
  end
65
+
66
+ it "should not reduce the count by more than one if the same query is canceled twice" do
67
+ q1 = Unbound::Query.new("localhost", 1, 1)
68
+ q2 = Unbound::Query.new("localhost", 1, 1)
69
+ @resolver.send_query(q1)
70
+ @resolver.send_query(q2)
71
+ expect(@resolver.outstanding_queries).to eq(2)
72
+ @resolver.cancel_query(q1)
73
+ expect(@resolver.outstanding_queries).to eq(1)
74
+ @resolver.cancel_query(q1)
75
+ expect(@resolver.outstanding_queries).to eq(1)
76
+ end
35
77
  end
36
78
 
37
79
  describe "#outstanding_queries?" do
@@ -40,7 +82,6 @@ describe Unbound::Resolver do
40
82
  end
41
83
 
42
84
  it "should be true if there are any outstanding queries" do
43
- query = Unbound::Query.new("localhost", 1, 1)
44
85
  @resolver.send_query(query)
45
86
  expect(@resolver.outstanding_queries?).to be_true
46
87
  end
@@ -69,17 +110,20 @@ describe Unbound::Resolver do
69
110
  end
70
111
 
71
112
  describe "#io" do
72
- it "should return an IO object" do
73
- expect(@resolver.io).to be_a(::IO)
113
+ it "should pass through to ctx.io" do
114
+ ctx = double("Context")
115
+ resolver = Unbound::Resolver.new(ctx)
116
+ expect(ctx).to receive(:io)
117
+ resolver.io
74
118
  end
119
+
75
120
  end
76
121
 
77
122
  describe "#process" do
78
123
  it "should call our callback" do
79
- query1 = Unbound::Query.new("localhost", 1, 1)
80
124
  expect { |cb|
81
- query1.on_answer(cb.to_proc)
82
- @resolver.send_query(query1)
125
+ query.on_answer(cb.to_proc)
126
+ @resolver.send_query(query)
83
127
  io = @resolver.io
84
128
  expect(::IO.select([io], nil, nil, 5)).to_not be_nil
85
129
  @resolver.process
@@ -87,17 +131,45 @@ describe Unbound::Resolver do
87
131
  end
88
132
  end
89
133
 
134
+ describe "#cancel_query" do
135
+ it "should all context#cancel_async_query" do
136
+ expect(@context).to receive(:cancel_async_query).and_call_original
137
+ @resolver.send_query(query)
138
+ @resolver.cancel_query(query)
139
+ end
140
+
141
+ it "should set query.async_id to nil" do
142
+ @resolver.send_query(query)
143
+ expect(query.async_id).not_to be_nil
144
+ @resolver.cancel_query(query)
145
+ expect(query.async_id).to be_nil
146
+ end
147
+
148
+ it "should call 'query#cancel!' only once" do
149
+ @resolver.send_query(query)
150
+ expect(query).to receive(:cancel!).exactly(1).times.and_call_original
151
+ @resolver.cancel_query(query)
152
+ @resolver.close
153
+ end
154
+
155
+ it "shouldn't try to cancel if the query hasn't been sent" do
156
+ query = double("Query")
157
+ allow(query).to receive(:async_id).and_return(nil)
158
+ ctx = double("Context")
159
+ resolver = Unbound::Resolver.new(ctx)
160
+ resolver.cancel_query(query)
161
+ end
162
+ end
163
+
90
164
  describe "#send_query" do
91
165
  it "should raise an exception if the same query object is submitted twice" do
92
- query1 = Unbound::Query.new("localhost", 1, 1)
93
- @resolver.send_query(query1)
94
- expect {@resolver.send_query(query1)}.to raise_error
166
+ @resolver.send_query(query)
167
+ expect {@resolver.send_query(query)}.to raise_error
95
168
  end
96
169
  end
97
170
 
98
171
  describe "#on_start" do
99
172
  specify "callbacks should be called when send_query is called" do
100
- query = Unbound::Query.new("localhost", 1, 1)
101
173
  expect { |cb|
102
174
  @resolver.on_start(&cb)
103
175
  @resolver.send_query(query)
@@ -107,7 +179,6 @@ describe Unbound::Resolver do
107
179
 
108
180
  describe "#on_answer" do
109
181
  specify "callbacks should be called if the query has been answered" do
110
- query = Unbound::Query.new("localhost", 1, 1)
111
182
  result = double("Result")
112
183
  expect { |cb|
113
184
  @resolver.on_answer(&cb)
@@ -119,7 +190,6 @@ describe Unbound::Resolver do
119
190
 
120
191
  describe "#on_error" do
121
192
  specify "callbacks should be called if the query has an error" do
122
- query = Unbound::Query.new("localhost", 1, 1)
123
193
  result = double("Result")
124
194
  expect { |cb|
125
195
  @resolver.on_error(&cb)
@@ -131,24 +201,22 @@ describe Unbound::Resolver do
131
201
 
132
202
  describe "#on_cancel" do
133
203
  specify "callbacks should be called if the query has been canceled" do
134
- query = Unbound::Query.new("localhost", 1, 1)
135
204
  result = double("Result")
136
205
  expect { |cb|
137
206
  @resolver.on_cancel(&cb)
138
207
  @resolver.send_query(query)
139
- query.cancel!()
208
+ @resolver.cancel_query(query)
140
209
  }.to yield_with_args(query)
141
210
  end
142
211
  end
143
212
 
144
213
  describe "#on_finish" do
145
214
  specify "callbacks should be called if the query is finished for any reason" do
146
- query = Unbound::Query.new("localhost", 1, 1)
147
215
  result = double("Result")
148
216
  expect { |cb|
149
217
  @resolver.on_finish(&cb)
150
218
  @resolver.send_query(query)
151
- query.cancel!()
219
+ @resolver.cancel_query(query)
152
220
  }.to yield_with_args(query)
153
221
  end
154
222
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unbound
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Ryan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-06 00:00:00.000000000 Z
11
+ date: 2014-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi