unbound 1.0.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b9e071138d458da3ab632fd55f7208e686e55679
4
- data.tar.gz: ffebd0663a8fe538b933c21cb35bd9f876ec64eb
3
+ metadata.gz: 268e920fce264b5a8fb5a60fc0f3b98d2648adde
4
+ data.tar.gz: fabfee310e6715df1e05e7ba455ae9fc64ae8f47
5
5
  SHA512:
6
- metadata.gz: 3190a931ff0e491a2c772056b486cad1c35b0e54ade6c6b6cf9429dfdd154157921fac796e62b34d0ea6ae699056a968b02776723179224c337bad716de2809d
7
- data.tar.gz: c539edfe6095cf3dba1c51411782ee6dcfc5f8c73e611270ebcaaa39e855dd61256c650d1f79ca6f058133c3bdadba7f08d4f75271d0317fbf5643d2d71ed15a
6
+ metadata.gz: 634924d61b650aeba4ee82632b34d95040da7aec61ac8a0a632fc3c4b48aeb082c0aca829b0baac77d5647880b933bf711f24f87b88eecc740489f3361dec432
7
+ data.tar.gz: 8029d61671926ea5874d9c2c4060cf788e11eae74e8c4d60228b9613263ee4ede4b39b20f04767a2565cea8141eb5291cf1289c55aaebeca75501dd02709560a
data/Gemfile CHANGED
@@ -5,10 +5,10 @@ gem "ffi"
5
5
 
6
6
  group :development do
7
7
  gem "jeweler"
8
- gem "rake"
9
8
  end
10
9
 
11
10
  group :test do
12
11
  gem "rspec"
13
12
  gem "simplecov"
13
+ gem "rake"
14
14
  end
data/Rakefile CHANGED
@@ -9,28 +9,35 @@ rescue Bundler::BundlerError => e
9
9
  end
10
10
  require 'rake'
11
11
 
12
- require 'jeweler'
13
- Jeweler::Tasks.new do |gem|
14
- # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
- gem.name = "unbound"
16
- gem.homepage = "http://github.com/justfalter/unbound-ruby"
17
- gem.license = "MIT"
18
- gem.summary = %Q{Unbound DNS resolver bindings for Ruby}
19
- gem.description = %Q{Unbound DNS resolver bindings for Ruby}
20
- gem.email = "falter@gmail.com"
21
- gem.authors = ["Mike Ryan"]
22
- gem.files = Dir.glob("lib/**/*.rb") +
23
- Dir.glob("examples/*") +
24
- Dir.glob("spec/{*.rb}") +
25
- Dir.glob("spec/conf/{*.conf}") +
26
- %w(LICENSE.txt Gemfile README.md Rakefile VERSION)
12
+ begin
13
+ require 'jeweler'
14
+ rescue LoadError
15
+ else
16
+ Jeweler::Tasks.new do |gem|
17
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
18
+ gem.name = "unbound"
19
+ gem.homepage = "http://github.com/justfalter/unbound-ruby"
20
+ gem.license = "MIT"
21
+ gem.summary = %Q{Unbound DNS resolver bindings for Ruby}
22
+ gem.description = %Q{Unbound DNS resolver bindings for Ruby}
23
+ gem.email = "falter@gmail.com"
24
+ gem.authors = ["Mike Ryan"]
25
+ gem.files = Dir.glob("lib/**/*.rb") +
26
+ Dir.glob("examples/*") +
27
+ Dir.glob("spec/{*.rb}") +
28
+ Dir.glob("spec/conf/{*.conf}") +
29
+ %w(LICENSE.txt Gemfile README.md Rakefile VERSION)
27
30
 
31
+ end
32
+ Jeweler::RubygemsDotOrgTasks.new
28
33
  end
29
- Jeweler::RubygemsDotOrgTasks.new
30
34
 
31
- require 'rspec/core'
32
- require 'rspec/core/rake_task'
33
- RSpec::Core::RakeTask.new(:spec) do |spec|
34
- spec.pattern = FileList['spec/**/*_spec.rb']
35
+ begin
36
+ rescue LoadError
37
+ else
38
+ require 'rspec/core'
39
+ require 'rspec/core/rake_task'
40
+ RSpec::Core::RakeTask.new(:spec) do |spec|
41
+ spec.pattern = FileList['spec/**/*_spec.rb']
42
+ end
35
43
  end
36
-
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0
1
+ 1.0.1
@@ -0,0 +1,54 @@
1
+ require 'ffi'
2
+
3
+ module Unbound
4
+ # Tracks in-flight queries for Resolver
5
+ class QueryStore
6
+ def initialize
7
+ @pointer_to_query_map = {}
8
+ end
9
+
10
+ # Enumerates through each query.
11
+ def each
12
+ @pointer_to_query_map.each_value do |query|
13
+ yield(query)
14
+ end
15
+ end
16
+
17
+ # Clears all queries from the store. No special actions taken.
18
+ def clear
19
+ @pointer_to_query_map.clear
20
+ end
21
+
22
+ # @return [Integer] the number of queries in the store.
23
+ def count
24
+ @pointer_to_query_map.count
25
+ end
26
+
27
+ # Retreives the query from the store via the provided pointer.
28
+ # @param [FFI::Pointer] pointer
29
+ # @return [Unbound::Query, nil] The associated query, otherwise nil.
30
+ def get_by_pointer(pointer)
31
+ return nil if pointer.nil?
32
+ @pointer_to_query_map[pointer.address]
33
+ end
34
+
35
+ # Stores a query object, and returns a pointer suitable for passing through
36
+ # Unbound::Context#resolve_async.
37
+ # @param [Unbound::Query] query
38
+ # @return [FFI::Pointer] the pointer
39
+ def store(query)
40
+ oid_ptr = FFI::Pointer.new query.object_id
41
+ @pointer_to_query_map[oid_ptr.address] = query
42
+ oid_ptr
43
+ end
44
+
45
+ # Deletes a query object from the store, and frees any associated pointer
46
+ # (if nescessary).
47
+ # @param [Unbound::Query] query
48
+ # @return [Unbound::Query] the query, if it was found. Otherwise nil.
49
+ def delete_query(query)
50
+ @pointer_to_query_map.delete(FFI::Pointer.new(query.object_id).address)
51
+ end
52
+ end
53
+ end
54
+
@@ -2,6 +2,7 @@ require 'unbound/bindings'
2
2
  require 'unbound/result'
3
3
  require 'unbound/context'
4
4
  require 'unbound/callbacks_mixin'
5
+ require 'unbound/query_store'
5
6
 
6
7
  module Unbound
7
8
  # A simple asynchronous resolver
@@ -12,7 +13,7 @@ module Unbound
12
13
  # resolver.
13
14
  def initialize(ctx)
14
15
  @ctx = ctx
15
- @queries = {}
16
+ @queries = QueryStore.new
16
17
  @resolve_callback_func = FFI::Function.new(
17
18
  :void, [:pointer, :int, :pointer],
18
19
  self.method(:resolve_callback))
@@ -25,7 +26,7 @@ module Unbound
25
26
  end
26
27
  end
27
28
  on_finish do |query|
28
- @queries.delete(query.object_id)
29
+ @queries.delete_query(query)
29
30
  end
30
31
  end
31
32
 
@@ -41,9 +42,7 @@ module Unbound
41
42
  end
42
43
 
43
44
  def resolve_callback(oid_ptr, err, result_ptr)
44
- return if oid_ptr.nil?
45
- oid = oid_ptr.address
46
- query = @queries[oid]
45
+ query = @queries.get_by_pointer(oid_ptr)
47
46
  return if query.nil?
48
47
 
49
48
  if err == 0
@@ -63,7 +62,7 @@ module Unbound
63
62
 
64
63
  # Cancel all outstanding queries.
65
64
  def cancel_all
66
- @queries.each_value do |query|
65
+ @queries.each do |query|
67
66
  query.cancel!
68
67
  end
69
68
  @queries.clear
@@ -95,20 +94,19 @@ module Unbound
95
94
  if query.started?
96
95
  raise QueryAlreadyStarted.new
97
96
  end
98
- @queries[query.object_id] = query
99
97
  # Add all of our callbacks, if any have been registered.
100
98
  query.on_start(*@callbacks_start) unless @callbacks_start.empty?
101
99
  query.on_answer(*@callbacks_answer) unless @callbacks_answer.empty?
102
100
  query.on_error(*@callbacks_error) unless @callbacks_error.empty?
103
101
  query.on_cancel(*@callbacks_cancel)
104
102
  query.on_finish(*@callbacks_finish)
105
- oid_ptr = FFI::Pointer.new query.object_id
103
+ ptr = @queries.store(query)
106
104
  async_id = @ctx.resolve_async(
107
105
  query.name,
108
106
  query.rrtype,
109
107
  query.rrclass,
110
108
  @resolve_callback_func,
111
- oid_ptr)
109
+ ptr)
112
110
  query.start!(async_id)
113
111
  end
114
112
  end
@@ -0,0 +1,139 @@
1
+ require 'spec_helper'
2
+
3
+ describe Unbound::QueryStore do
4
+ let(:query_store) {
5
+ Unbound::QueryStore.new
6
+ }
7
+
8
+ def new_query(num)
9
+ Unbound::Query.new("somedomain#{num}.com", 1, 1)
10
+ end
11
+
12
+ describe "#each" do
13
+ it "should yield as many times as there are queries in the store" do
14
+ 5.times do |i|
15
+ query_store.store(new_query(i))
16
+ end
17
+ expect {|b| query_store.each(&b)}.to yield_control.exactly(5).times
18
+ end
19
+ it "should yield the set of query objects we put into it" do
20
+ expected_queries = []
21
+ actual_queries = []
22
+ 5.times do |i|
23
+ query = new_query(i)
24
+ expected_queries << query
25
+ query_store.store(query)
26
+ end
27
+ query_store.each do |query|
28
+ actual_queries << query
29
+ end
30
+ expect(actual_queries).to match_array(expected_queries)
31
+ end
32
+ end
33
+ describe "#clear" do
34
+ it "should cause the count to drop to 0" do
35
+ expect(query_store.count).to eq(0)
36
+ 5.times do |i|
37
+ query_store.store(new_query(i))
38
+ end
39
+ expect(query_store.count).to eq(5)
40
+ query_store.clear
41
+ expect(query_store.count).to eq(0)
42
+ end
43
+ it "should remove all queries from the store, making it so they cannot be retreived" do
44
+ queries = {}
45
+ 5.times do |i|
46
+ query = new_query(i)
47
+ ptr = query_store.store(query)
48
+ queries[ptr] = query
49
+ end
50
+
51
+ queries.each_pair do |ptr, query|
52
+ expect(query_store.get_by_pointer(ptr)).to be(query)
53
+ end
54
+
55
+ query_store.clear
56
+ queries.each_pair do |ptr, query|
57
+ expect(query_store.get_by_pointer(ptr)).to be_nil
58
+ end
59
+ end
60
+ end
61
+ describe "#count" do
62
+ it "should be 0 if there's nothing in there" do
63
+ expect(query_store.count).to eq(0)
64
+ end
65
+ it "should be 5 if five distinct queries have been added" do
66
+ 5.times do |i|
67
+ query_store.store(new_query(i))
68
+ end
69
+ expect(query_store.count).to eq(5)
70
+ end
71
+ it "should be 1 if the same query was added 5 times" do
72
+ query = new_query(1)
73
+ 5.times do |i|
74
+ query_store.store(query)
75
+ end
76
+ expect(query_store.count).to eq(1)
77
+ end
78
+ end
79
+ describe "#store" do
80
+ it "should return a pointer" do
81
+ expect(query_store.store(new_query(1))).to be_a(FFI::Pointer)
82
+ end
83
+ it "should increase the count" do
84
+ query = new_query(1)
85
+ expect(query_store.count).to eq(0)
86
+ query_store.store(query)
87
+ expect(query_store.count).to eq(1)
88
+ end
89
+ end
90
+ describe "#get_by_pointer" do
91
+ it "should return the query associated with the provided pointer" do
92
+ query1 = new_query(1)
93
+ query2 = new_query(2)
94
+ query3 = new_query(3)
95
+ query4 = new_query(4)
96
+ query5 = new_query(5)
97
+ ptr1 = query_store.store(query1)
98
+ ptr2 = query_store.store(query2)
99
+ ptr3 = query_store.store(query3)
100
+ ptr4 = query_store.store(query4)
101
+ ptr5 = query_store.store(query5)
102
+ expect(query_store.get_by_pointer(ptr1)).to be(query1)
103
+ expect(query_store.get_by_pointer(ptr2)).to be(query2)
104
+ expect(query_store.get_by_pointer(ptr3)).to be(query3)
105
+ expect(query_store.get_by_pointer(ptr4)).to be(query4)
106
+ expect(query_store.get_by_pointer(ptr5)).to be(query5)
107
+ end
108
+ it "should return nil if the provided pointer is not associated with a query" do
109
+ expect(query_store.get_by_pointer(FFI::Pointer.new(1234))).to be_nil
110
+ end
111
+ end
112
+ describe "#delete_query" do
113
+ it "should make it so the query can no longer be retreived from the store" do
114
+ query1 = new_query(1)
115
+ query2 = new_query(2)
116
+ ptr1 = query_store.store(query1)
117
+ ptr2 = query_store.store(query2)
118
+ expect(query_store.get_by_pointer(ptr1)).to be(query1)
119
+ expect(query_store.get_by_pointer(ptr2)).to be(query2)
120
+ query_store.delete_query(query1)
121
+ expect(query_store.get_by_pointer(ptr1)).to be_nil
122
+ expect(query_store.get_by_pointer(ptr2)).to be(query2)
123
+ query_store.delete_query(query2)
124
+ expect(query_store.get_by_pointer(ptr1)).to be_nil
125
+ expect(query_store.get_by_pointer(ptr2)).to be_nil
126
+ end
127
+ it "should return the query that was deleted" do
128
+ query1 = new_query(1)
129
+ ptr1 = query_store.store(query1)
130
+ expect(query_store.delete_query(query1)).to be(query1)
131
+ end
132
+ it "should return nil if the query was not in the store" do
133
+ query1 = new_query(1)
134
+ expect(query_store.delete_query(query1)).to be_nil
135
+ end
136
+ end
137
+ end
138
+
139
+
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.0
4
+ version: 1.0.1
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-01-31 00:00:00.000000000 Z
11
+ date: 2014-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: rake
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - '>='
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - '>='
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
41
  description: Unbound DNS resolver bindings for Ruby
56
42
  email: falter@gmail.com
57
43
  executables: []
@@ -73,6 +59,7 @@ files:
73
59
  - lib/unbound/context.rb
74
60
  - lib/unbound/exceptions.rb
75
61
  - lib/unbound/query.rb
62
+ - lib/unbound/query_store.rb
76
63
  - lib/unbound/resolver.rb
77
64
  - lib/unbound/result.rb
78
65
  - spec/callback_array_spec.rb
@@ -80,6 +67,7 @@ files:
80
67
  - spec/conf/test_config.conf
81
68
  - spec/context_spec.rb
82
69
  - spec/query_spec.rb
70
+ - spec/query_store_spec.rb
83
71
  - spec/resolver_spec.rb
84
72
  - spec/result_spec.rb
85
73
  - spec/spec_helper.rb