rubydns 2.0.2 → 2.1.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.
@@ -1,121 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
-
4
- # Copyright, 2009, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
5
- #
6
- # Permission is hereby granted, free of charge, to any person obtaining a copy
7
- # of this software and associated documentation files (the "Software"), to deal
8
- # in the Software without restriction, including without limitation the rights
9
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- # copies of the Software, and to permit persons to whom the Software is
11
- # furnished to do so, subject to the following conditions:
12
- #
13
- # The above copyright notice and this permission notice shall be included in
14
- # all copies or substantial portions of the Software.
15
- #
16
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- # THE SOFTWARE.
23
-
24
- require 'rubydns'
25
-
26
- require 'cgi'
27
- require 'json'
28
-
29
- require 'digest/md5'
30
-
31
- require 'async/logger'
32
- require 'async/http/client'
33
- require 'async/dns/extensions/string'
34
- require 'async/http/url_endpoint'
35
-
36
- # Encapsulates the logic for fetching information from Wikipedia.
37
- module Wikipedia
38
- ENDPOINT = Async::HTTP::URLEndpoint.parse("https://en.wikipedia.org")
39
-
40
- def self.lookup(title, logger: nil)
41
- client = Async::HTTP::Client.new([ENDPOINT])
42
- url = self.summary_url(title)
43
-
44
- logger&.info "Making request to #{ENDPOINT} for #{url}."
45
- response = client.get(url, {'Host' => ENDPOINT.hostname})
46
- logger&.info "Got response #{response.inspect}."
47
-
48
- if response.status == 301
49
- return lookup(response.headers['HTTP_LOCATION'])
50
- else
51
- return self.extract_summary(response.body).force_encoding('ASCII-8BIT')
52
- end
53
- end
54
-
55
- def self.summary_url(title)
56
- "/api/rest_v1/page/summary/#{CGI.escape title}"
57
- end
58
-
59
- def self.extract_summary(json_text)
60
- document = JSON.parse(json_text)
61
-
62
- return document['extract']
63
- rescue
64
- return 'Invalid Article.'
65
- end
66
- end
67
-
68
- # A DNS server that queries Wikipedia and returns summaries for
69
- # specifically crafted queries.
70
- class WikipediaDNS
71
- Name = Resolv::DNS::Name
72
- IN = Resolv::DNS::Resource::IN
73
-
74
- INTERFACES = [
75
- [:udp, '::', 5300],
76
- [:tcp, '::', 5300],
77
- ]
78
-
79
- def startup
80
- # Don't buffer output (for debug purposes)
81
- $stderr.sync = true
82
-
83
- stats = { requested: 0 }
84
-
85
- # Start the RubyDNS server
86
- RubyDNS.run_server(INTERFACES) do
87
- on(:start) do
88
- # Process::Daemon::Privileges.change_user(RUN_AS)
89
-
90
- if ARGV.include?('--debug')
91
- @logger.level = Logger::DEBUG
92
- else
93
- @logger.level = Logger::WARN
94
- end
95
-
96
- @logger.info "Starting Wikipedia DNS..."
97
- end
98
-
99
- match(/stats\.wikipedia/, IN::TXT) do |transaction|
100
- transaction.respond!(*stats.inspect.chunked)
101
- end
102
-
103
- match(/(.+)\.wikipedia/, IN::TXT) do |transaction, match_data|
104
- title = match_data[1]
105
- stats[:requested] += 1
106
-
107
- summary = Wikipedia.lookup(title, logger: @logger)
108
-
109
- transaction.respond!(*summary.chunked)
110
- end
111
-
112
- # Default DNS handler
113
- otherwise do |transaction|
114
- transaction.fail!(:NXDomain)
115
- end
116
- end
117
- end
118
- end
119
-
120
- wikipedia_dns = WikipediaDNS.new
121
- wikipedia_dns.startup
@@ -1,180 +0,0 @@
1
- # Copyright, 2009, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'async/dns/server'
22
-
23
- module RubyDNS
24
- # Provides the core of the RubyDNS domain-specific language (DSL). It contains a list of rules which are used to match against incoming DNS questions. These rules are used to generate responses which are either DNS resource records or failures.
25
- class RuleBasedServer < Async::DNS::Server
26
- # Represents a single rule in the server.
27
- class Rule
28
- def initialize(pattern, callback)
29
- @pattern = pattern
30
- @callback = callback
31
- end
32
-
33
- # Returns true if the name and resource_class are sufficient:
34
- def match(name, resource_class)
35
- # If the pattern doesn't specify any resource classes, we implicitly pass this test:
36
- return true if @pattern.size < 2
37
-
38
- # Otherwise, we try to match against some specific resource classes:
39
- if Class === @pattern[1]
40
- @pattern[1] == resource_class
41
- else
42
- @pattern[1].include?(resource_class) rescue false
43
- end
44
- end
45
-
46
- # Invoke the rule, if it matches the incoming request, it is evaluated and returns `true`, otherwise returns `false`.
47
- def call(server, name, resource_class, transaction)
48
- unless match(name, resource_class)
49
- server.logger.debug "<#{transaction.query.id}> Resource class #{resource_class} failed to match #{@pattern[1].inspect}!"
50
-
51
- return false
52
- end
53
-
54
- # Does this rule match against the supplied name?
55
- case @pattern[0]
56
- when Regexp
57
- match_data = @pattern[0].match(name)
58
-
59
- if match_data
60
- server.logger.debug "<#{transaction.query.id}> Regexp pattern matched with #{match_data.inspect}."
61
-
62
- @callback[transaction, match_data]
63
-
64
- return true
65
- end
66
- when String
67
- if @pattern[0] == name
68
- server.logger.debug "<#{transaction.query.id}> String pattern matched."
69
-
70
- @callback[transaction]
71
-
72
- return true
73
- end
74
- else
75
- if (@pattern[0].call(name, resource_class) rescue false)
76
- server.logger.debug "<#{transaction.query.id}> Callable pattern matched."
77
-
78
- @callback[transaction]
79
-
80
- return true
81
- end
82
- end
83
-
84
- server.logger.debug "<#{transaction.query.id}> No pattern matched."
85
-
86
- # We failed to match the pattern.
87
- return false
88
- end
89
-
90
- def to_s
91
- @pattern.inspect
92
- end
93
- end
94
-
95
- # Instantiate a server with a block
96
- #
97
- # server = Server.new do
98
- # match(/server.mydomain.com/, IN::A) do |transaction|
99
- # transaction.respond!("1.2.3.4")
100
- # end
101
- # end
102
- #
103
- def initialize(*args, &block)
104
- super(*args)
105
-
106
- @events = {}
107
- @rules = []
108
- @otherwise = nil
109
-
110
- if block_given?
111
- instance_eval(&block)
112
- end
113
- end
114
-
115
- attr_accessor :logger
116
-
117
- # This function connects a pattern with a block. A pattern is either a String or a Regex instance. Optionally, a second argument can be provided which is either a String, Symbol or Array of resource record types which the rule matches against.
118
- #
119
- # match("www.google.com")
120
- # match("gmail.com", IN::MX)
121
- # match(/g?mail.(com|org|net)/, [IN::MX, IN::A])
122
- #
123
- def match(*pattern, &block)
124
- @rules << Rule.new(pattern, block)
125
- end
126
-
127
- # Register a named event which may be invoked later using #fire
128
- #
129
- # on(:start) do |server|
130
- # Process::Daemon::Permissions.change_user(RUN_AS)
131
- # end
132
- def on(event_name, &block)
133
- @events[event_name] = block
134
- end
135
-
136
- # Fire the named event, which must have been registered using on.
137
- def fire(event_name)
138
- callback = @events[event_name]
139
-
140
- if callback
141
- callback.call(self)
142
- end
143
- end
144
-
145
- # Specify a default block to execute if all other rules fail to match. This block is typially used to pass the request on to another server (i.e. recursive request).
146
- #
147
- # otherwise do |transaction|
148
- # transaction.passthrough!($R)
149
- # end
150
- #
151
- def otherwise(&block)
152
- @otherwise = block
153
- end
154
-
155
- # If you match a rule, but decide within the rule that it isn't the correct one to use, you can call `next!` to evaluate the next rule - in other words, to continue falling down through the list of rules.
156
- def next!
157
- throw :next
158
- end
159
-
160
- # Give a name and a record type, try to match a rule and use it for processing the given arguments.
161
- def process(name, resource_class, transaction)
162
- @logger.debug {"<#{transaction.query.id}> Searching for #{name} #{resource_class.name}"}
163
-
164
- @rules.each do |rule|
165
- @logger.debug {"<#{transaction.query.id}> Checking rule #{rule}..."}
166
-
167
- catch (:next) do
168
- # If the rule returns true, we assume that it was successful and no further rules need to be evaluated.
169
- return if rule.call(self, name, resource_class, transaction)
170
- end
171
- end
172
-
173
- if @otherwise
174
- @otherwise.call(transaction)
175
- else
176
- @logger.warn "<#{transaction.query.id}> Failed to handle #{name} #{resource_class.name}!"
177
- end
178
- end
179
- end
180
- end
data/rubydns.gemspec DELETED
@@ -1,28 +0,0 @@
1
-
2
- require_relative 'lib/rubydns/version'
3
-
4
- Gem::Specification.new do |spec|
5
- spec.name = "rubydns"
6
- spec.version = RubyDNS::VERSION
7
- spec.authors = ["Samuel Williams"]
8
- spec.email = ["samuel.williams@oriontransfer.co.nz"]
9
- spec.description = <<-EOF
10
- RubyDNS provides a rule-based DSL for implementing DNS servers, built on top of `Async::DNS`.
11
- EOF
12
- spec.summary = "An easy to use DNS server and resolver for Ruby."
13
- spec.homepage = "https://github.com/socketry/rubydns"
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
20
- spec.has_rdoc = "yard"
21
-
22
- spec.add_dependency("async-dns", "~> 1.0")
23
- spec.add_development_dependency("async-rspec", "~> 1.0")
24
-
25
- spec.add_development_dependency "bundler", "~> 1.3"
26
- spec.add_development_dependency "rspec", "~> 3.4"
27
- spec.add_development_dependency "rake"
28
- end
@@ -1,114 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
22
-
23
- require 'rubydns'
24
- require 'process/daemon'
25
-
26
- class BasicTestServer < Process::Daemon
27
- SERVER_PORTS = [[:udp, '127.0.0.1', 5350], [:tcp, '127.0.0.1', 5350]]
28
-
29
- IN = Resolv::DNS::Resource::IN
30
-
31
- def working_directory
32
- File.expand_path("../tmp", __FILE__)
33
- end
34
-
35
- def reactor
36
- Async::Reactor.new
37
- end
38
-
39
- def startup
40
- reactor.run do
41
- RubyDNS::run_server(SERVER_PORTS) do
42
- match("test.local", IN::A) do |transaction|
43
- transaction.respond!("192.168.1.1")
44
- end
45
-
46
- match(/foo.*/, IN::A) do |transaction|
47
- transaction.respond!("192.168.1.2")
48
- end
49
-
50
- match(/peername/, IN::A) do |transaction|
51
- transaction.respond!(transaction[:remote_address].ip_address)
52
- end
53
-
54
- # Default DNS handler
55
- otherwise do |transaction|
56
- transaction.fail!(:NXDomain)
57
- end
58
- end
59
- end
60
- end
61
-
62
- def shutdown
63
- @reactor.stop
64
- end
65
- end
66
-
67
- describe "RubyDNS Daemonized Server" do
68
- include_context Async::RSpec::Reactor
69
-
70
- before(:all) do
71
- # BasicTestServer.controller output: $stderr
72
- BasicTestServer.start
73
- end
74
-
75
- after(:all) do
76
- BasicTestServer.stop
77
- end
78
-
79
- it "should resolve local domain correctly" do
80
- expect(BasicTestServer.status).to be == :running
81
-
82
- resolver = RubyDNS::Resolver.new(BasicTestServer::SERVER_PORTS)
83
-
84
- response = resolver.query("test.local")
85
-
86
- answer = response.answer.first
87
-
88
- expect(answer[0].to_s).to be == "test.local."
89
- expect(answer[2].address.to_s).to be == "192.168.1.1"
90
- end
91
-
92
- it "should pattern match correctly" do
93
- expect(BasicTestServer.status).to be == :running
94
-
95
- resolver = RubyDNS::Resolver.new(BasicTestServer::SERVER_PORTS)
96
-
97
- response = resolver.query("foobar")
98
- answer = response.answer.first
99
-
100
- expect(answer[0]).to be == resolver.fully_qualified_name("foobar")
101
- expect(answer[2].address.to_s).to be == "192.168.1.2"
102
- end
103
-
104
- it "should give peer ip address" do
105
- expect(BasicTestServer.status).to be == :running
106
-
107
- resolver = RubyDNS::Resolver.new(BasicTestServer::SERVER_PORTS)
108
-
109
- response = resolver.query("peername")
110
- answer = response.answer.first
111
-
112
- expect(answer[2].address.to_s).to be == "127.0.0.1"
113
- end
114
- end
@@ -1,2 +0,0 @@
1
- # A testing host:
2
- 1.2.3.4 testing apples
@@ -1,64 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
22
-
23
- require 'rubydns'
24
- require 'async/dns/extensions/string'
25
-
26
- module RubyDNS::InjectedSupervisorSpec
27
- class TestServer < RubyDNS::RuleBasedServer
28
- def test_message
29
- 'Testing...'
30
- end
31
- end
32
-
33
- SERVER_PORTS = [[:udp, '127.0.0.1', 5520]]
34
- IN = Resolv::DNS::Resource::IN
35
-
36
- describe "RubyDNS::run_server(server_class: ...)" do
37
- include_context Async::RSpec::Reactor
38
-
39
- let(:server) do
40
- # Start the RubyDNS server
41
- RubyDNS::run_server(SERVER_PORTS, server_class: TestServer) do
42
- match("test_message", IN::TXT) do |transaction|
43
- transaction.respond!(*test_message.chunked)
44
- end
45
-
46
- # Default DNS handler
47
- otherwise do |transaction|
48
- transaction.fail!(:NXDomain)
49
- end
50
- end
51
- end
52
-
53
- it "should use the injected class" do
54
- task = server
55
-
56
- resolver = RubyDNS::Resolver.new(SERVER_PORTS)
57
- response = resolver.query("test_message", IN::TXT)
58
- text = response.answer.first
59
- expect(text[2].strings.join).to be == 'Testing...'
60
-
61
- task.stop
62
- end
63
- end
64
- end
@@ -1,85 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
22
-
23
- require 'rubydns'
24
-
25
- module RubyDNS::PassthroughSpec
26
- SERVER_PORTS = [[:udp, '127.0.0.1', 5340], [:tcp, '127.0.0.1', 5340]]
27
- Name = Resolv::DNS::Name
28
- IN = Resolv::DNS::Resource::IN
29
-
30
- describe "RubyDNS Passthrough Server" do
31
- include_context Async::RSpec::Reactor
32
-
33
- def run_server
34
- task = RubyDNS::run_server(listen: SERVER_PORTS) do
35
- resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
36
-
37
- match(/.*\.com/, IN::A) do |transaction|
38
- transaction.passthrough!(resolver)
39
- end
40
-
41
- match(/a-(.*\.org)/) do |transaction, match_data|
42
- transaction.passthrough!(resolver, :name => match_data[1])
43
- end
44
-
45
- # Default DNS handler
46
- otherwise do |transaction|
47
- transaction.fail!(:NXDomain)
48
- end
49
- end
50
-
51
- yield
52
-
53
- ensure
54
- task.stop
55
- end
56
-
57
- it "should resolve domain correctly" do
58
- run_server do
59
- resolver = RubyDNS::Resolver.new(SERVER_PORTS, timeout: 1)
60
-
61
- response = resolver.query("google.com")
62
- expect(response.ra).to be == 1
63
-
64
- answer = response.answer.first
65
- expect(answer).not_to be == nil
66
- expect(answer.count).to be > 0
67
-
68
- addresses = answer.select {|record| record.kind_of? Resolv::DNS::Resource::IN::A}
69
- expect(addresses.size).to be > 0
70
- end
71
- end
72
-
73
- it "should resolve prefixed domain correctly" do
74
- run_server do
75
- resolver = RubyDNS::Resolver.new(SERVER_PORTS)
76
-
77
- response = resolver.query("a-slashdot.org")
78
- answer = response.answer.first
79
-
80
- expect(answer).not_to be == nil
81
- expect(answer.count).to be > 0
82
- end
83
- end
84
- end
85
- end
@@ -1,74 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
22
-
23
- require 'rubydns'
24
-
25
- module RubyDNS::RulesSpec
26
- describe RubyDNS::RuleBasedServer do
27
- IN = Resolv::DNS::Resource::IN
28
-
29
- true_callback = Proc.new { true }
30
-
31
- it "should match string patterns correctly" do
32
- server = double(:logger => Logger.new("/dev/null"))
33
- transaction = double(:query => Resolv::DNS::Message.new(0))
34
-
35
- rule = RubyDNS::RuleBasedServer::Rule.new(["foobar", IN::A], true_callback)
36
-
37
- expect(rule.call(server, "foobar", IN::A, transaction)).to be == true
38
- expect(rule.call(server, "barfoo", IN::A, transaction)).to be == false
39
- expect(rule.call(server, "foobar", IN::TXT, transaction)).to be == false
40
- end
41
-
42
- it "should match regular expression patterns correctly" do
43
- server = double(:logger => Logger.new("/dev/null"))
44
- transaction = double(:query => Resolv::DNS::Message.new(0))
45
-
46
- rule = RubyDNS::RuleBasedServer::Rule.new([/foo/, IN::A], true_callback)
47
-
48
- expect(rule.call(server, "foobar", IN::A, transaction)).to be == true
49
- expect(rule.call(server, "barbaz", IN::A, transaction)).to be == false
50
- expect(rule.call(server, "foobar", IN::TXT, transaction)).to be == false
51
- end
52
-
53
- it "should match callback patterns correctly" do
54
- server = double(:logger => Logger.new("/dev/null"))
55
- transaction = double(:query => Resolv::DNS::Message.new(0))
56
-
57
- calls = 0
58
-
59
- callback = Proc.new do |name, resource_class|
60
- # A counter used to check the number of times this block was invoked.
61
- calls += 1
62
-
63
- name.size == 6
64
- end
65
-
66
- rule = RubyDNS::RuleBasedServer::Rule.new([callback], true_callback)
67
-
68
- expect(rule.call(server, "foobar", IN::A, transaction)).to be == true
69
- expect(rule.call(server, "foobarbaz", IN::A, transaction)).to be == false
70
-
71
- expect(calls).to be == 2
72
- end
73
- end
74
- end