rubydns 0.8.5 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -0
  3. data/Gemfile +0 -4
  4. data/README.md +16 -8
  5. data/Rakefile +6 -6
  6. data/{test/examples → examples}/dropping-dns.rb +0 -0
  7. data/lib/rubydns/handler.rb +133 -102
  8. data/lib/rubydns/message.rb +0 -1
  9. data/lib/rubydns/resolver.rb +135 -187
  10. data/lib/rubydns/server.rb +92 -86
  11. data/lib/rubydns/transaction.rb +24 -48
  12. data/lib/rubydns/{binary_string.rb → transport.rb} +38 -0
  13. data/lib/rubydns/version.rb +1 -1
  14. data/lib/rubydns.rb +15 -8
  15. data/rubydns.gemspec +5 -2
  16. data/{test/test_daemon.rb → spec/rubydns/daemon_spec.rb} +36 -48
  17. data/{test → spec/rubydns}/hosts.txt +0 -0
  18. data/{test/test_rules.rb → spec/rubydns/message_spec.rb} +26 -44
  19. data/spec/rubydns/passthrough_spec.rb +78 -0
  20. data/spec/rubydns/resolver_performance_spec.rb +110 -0
  21. data/spec/rubydns/resolver_spec.rb +144 -0
  22. data/spec/rubydns/rules_spec.rb +74 -0
  23. data/{test/performance → spec/rubydns/server}/benchmark.rb +0 -0
  24. data/{test/performance → spec/rubydns/server}/bind9/generate-local.rb +0 -0
  25. data/{test/performance → spec/rubydns/server}/bind9/local.zone +0 -0
  26. data/{test/performance → spec/rubydns/server}/bind9/named.conf +0 -0
  27. data/spec/rubydns/server/bind9/named.run +0 -0
  28. data/{test/performance → spec/rubydns/server}/million.rb +1 -3
  29. data/spec/rubydns/server/rubydns.stackprof +0 -0
  30. data/spec/rubydns/server_performance_spec.rb +136 -0
  31. data/spec/rubydns/slow_server_spec.rb +89 -0
  32. data/spec/rubydns/socket_spec.rb +77 -0
  33. data/{test/test_system.rb → spec/rubydns/system_spec.rb} +28 -22
  34. data/spec/rubydns/transaction_spec.rb +64 -0
  35. data/{test/test_truncation.rb → spec/rubydns/truncation_spec.rb} +22 -48
  36. metadata +91 -54
  37. data/test/examples/fortune-dns.rb +0 -107
  38. data/test/examples/geoip-dns.rb +0 -76
  39. data/test/examples/soa-dns.rb +0 -82
  40. data/test/examples/test-dns-1.rb +0 -77
  41. data/test/examples/test-dns-2.rb +0 -83
  42. data/test/examples/wikipedia-dns.rb +0 -112
  43. data/test/test_message.rb +0 -65
  44. data/test/test_passthrough.rb +0 -120
  45. data/test/test_resolver.rb +0 -106
  46. data/test/test_resolver_performance.rb +0 -123
  47. data/test/test_server_performance.rb +0 -134
  48. data/test/test_slow_server.rb +0 -125
@@ -0,0 +1,144 @@
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::ResolverSpec
26
+ describe RubyDNS::Resolver do
27
+ class JunkUDPServer
28
+ include Celluloid::IO
29
+
30
+ def initialize
31
+ @socket = UDPSocket.new
32
+ @socket.bind("0.0.0.0", 6060)
33
+
34
+ async.run
35
+ end
36
+
37
+ finalizer :shutdown
38
+
39
+ def finalize
40
+ @socket.close if @socket
41
+ end
42
+
43
+ def run
44
+ data, (_, port, host) = @socket.recvfrom(1024)
45
+
46
+ @socket.send("Foobar", 0, host, port)
47
+ end
48
+ end
49
+
50
+ class JunkTCPServer
51
+ include Celluloid::IO
52
+
53
+ def initialize
54
+ @socket = TCPServer.new("0.0.0.0", 6060)
55
+
56
+ async.run
57
+ end
58
+
59
+ finalizer :shutdown
60
+
61
+ def finalize
62
+ @socket.close if @socket
63
+ end
64
+
65
+ def run
66
+ # @logger.debug "Waiting for incoming TCP connections #{@socket.inspect}..."
67
+ loop { async.handle_connection @socket.accept }
68
+ end
69
+
70
+ def handle_connection(socket)
71
+ socket.write("\0\0obar")
72
+ ensure
73
+ socket.close
74
+ end
75
+ end
76
+
77
+ before(:all) do
78
+ Celluloid.shutdown
79
+ Celluloid.boot
80
+
81
+ JunkUDPServer.supervise
82
+ JunkTCPServer.supervise
83
+ end
84
+
85
+ it "should result in non-existent domain" do
86
+ resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
87
+
88
+ response = resolver.query('foobar.oriontransfer.org')
89
+
90
+ expect(response.rcode).to be == Resolv::DNS::RCode::NXDomain
91
+ end
92
+
93
+ it "should result in some answers" do
94
+ resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
95
+
96
+ response = resolver.query('google.com')
97
+
98
+ expect(response.class).to be == RubyDNS::Message
99
+ expect(response.answer.size).to be > 0
100
+ end
101
+
102
+ it "should return no results" do
103
+ resolver = RubyDNS::Resolver.new([])
104
+
105
+ response = resolver.query('google.com')
106
+
107
+ expect(response).to be == nil
108
+ end
109
+
110
+ it "should fail to get addresses" do
111
+ resolver = RubyDNS::Resolver.new([])
112
+
113
+ expect{resolver.addresses_for('google.com')}.to raise_error(RubyDNS::ResolutionFailure)
114
+ end
115
+
116
+ it "should fail with decode error from bad udp server" do
117
+ resolver = RubyDNS::Resolver.new([[:udp, "0.0.0.0", 6060]])
118
+
119
+ response = resolver.query('google.com')
120
+
121
+ expect(response).to be == nil
122
+ end
123
+
124
+ it "should fail with decode error from bad tcp server" do
125
+ resolver = RubyDNS::Resolver.new([[:tcp, "0.0.0.0", 6060]])
126
+
127
+ response = resolver.query('google.com')
128
+
129
+ expect(response).to be == nil
130
+ end
131
+
132
+ it "should return some IPv4 and IPv6 addresses" do
133
+ resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
134
+
135
+ addresses = resolver.addresses_for("www.google.com.")
136
+
137
+ expect(addresses.size).to be > 0
138
+
139
+ addresses.each do |address|
140
+ expect(address).to be_kind_of(Resolv::IPv4) | be_kind_of(Resolv::IPv6)
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,74 @@
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
File without changes
@@ -56,8 +56,6 @@ StackProf.run(mode: :cpu, out: 'rubydns.stackprof') do
56
56
  otherwise do |transaction|
57
57
  logger.info "Passing DNS request upstream..."
58
58
  transaction.fail!(:NXDomain)
59
-
60
- EventMachine::stop
61
59
  end
62
60
  end
63
61
  end
@@ -84,4 +82,4 @@ end
84
82
  # ;; SERVER: 127.0.0.1#5300(127.0.0.1)
85
83
  # ;; WHEN: Fri May 16 19:17:48 2014
86
84
  # ;; MSG SIZE rcvd: 47
87
- #
85
+ #
@@ -0,0 +1,136 @@
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 'benchmark'
25
+ require 'process/daemon'
26
+
27
+ module RubyDNS::ServerPerformanceSpec
28
+ describe RubyDNS::Server do
29
+ context 'benchmark' do
30
+ class ServerPerformanceRubyDNS < Process::Daemon
31
+ IN = Resolv::DNS::Resource::IN
32
+
33
+ def working_directory
34
+ File.expand_path("../tmp", __FILE__)
35
+ end
36
+
37
+ def startup
38
+ puts "Booting celluloid..."
39
+ Celluloid.boot
40
+
41
+ million = {}
42
+
43
+ puts "Generating domains..."
44
+ (1..5_000).each do |i|
45
+ domain = "domain#{i}.local"
46
+
47
+ million[domain] = "#{69}.#{(i >> 16)%256}.#{(i >> 8)%256}.#{i%256}"
48
+ end
49
+
50
+ puts "Starting DNS server..."
51
+ RubyDNS::run_server(:listen => [[:udp, '0.0.0.0', 5300]]) do
52
+ @logger.level = Logger::WARN
53
+
54
+ match(//, IN::A) do |transaction|
55
+ puts "Responding to #{transaction.name}"
56
+ transaction.respond!(million[transaction.name])
57
+ end
58
+
59
+ # Default DNS handler
60
+ otherwise do |transaction|
61
+ transaction.fail!(:NXDomain)
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ class ServerPerformanceBind9 < Process::Daemon
68
+ def working_directory
69
+ File.expand_path("../server/bind9", __FILE__)
70
+ end
71
+
72
+ def startup
73
+ exec(self.class.named_executable, "-c", "named.conf", "-f", "-p", "5400", "-g")
74
+ end
75
+
76
+ def self.named_executable
77
+ # Check if named executable is available:
78
+ @named ||= `which named`.chomp
79
+ end
80
+ end
81
+
82
+ before do
83
+ Celluloid.shutdown
84
+
85
+ @servers = []
86
+ @servers << ["RubyDNS::Server", 5300]
87
+
88
+ @domains = (1..1000).collect do |i|
89
+ "domain#{i}.local"
90
+ end
91
+
92
+ ServerPerformanceRubyDNS.start
93
+
94
+ unless ServerPerformanceBind9.named_executable.empty?
95
+ ServerPerformanceBind9.start
96
+ @servers << ["Bind9", 5400]
97
+ end
98
+
99
+ sleep 2
100
+
101
+ Celluloid.boot
102
+ end
103
+
104
+ after do
105
+ ServerPerformanceRubyDNS.stop
106
+
107
+ unless ServerPerformanceBind9.named_executable.empty?
108
+ ServerPerformanceBind9.stop
109
+ end
110
+ end
111
+
112
+ it 'it takes time' do
113
+ Celluloid.logger.level = Logger::ERROR
114
+
115
+ Benchmark.bm(20) do |x|
116
+ @servers.each do |name, port|
117
+ resolver = RubyDNS::Resolver.new([[:udp, '127.0.0.1', port]])
118
+
119
+ x.report(name) do
120
+ # Number of requests remaining since this is an asynchronous event loop:
121
+ 5.times do
122
+ pending = @domains.size
123
+
124
+ futures = @domains.collect{|domain| resolver.future.addresses_for(domain)}
125
+
126
+ futures.collect do |future|
127
+ expect(future.value).to_not be nil
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,89 @@
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::SlowServerSpec
26
+ SERVER_PORTS = [[:udp, '127.0.0.1', 5330], [:tcp, '127.0.0.1', 5330]]
27
+ IN = Resolv::DNS::Resource::IN
28
+
29
+ describe "RubyDNS Slow Server" do
30
+ before(:all) do
31
+ Celluloid.shutdown
32
+ Celluloid.boot
33
+
34
+ @server = RubyDNS::run_server(:listen => SERVER_PORTS, asynchronous: true) do
35
+ match(/\.*.com/, IN::A) do |transaction|
36
+ sleep 2
37
+
38
+ transaction.fail!(:NXDomain)
39
+ end
40
+
41
+ otherwise do |transaction|
42
+ transaction.fail!(:NXDomain)
43
+ end
44
+ end
45
+ end
46
+
47
+ it "get no answer after 2 seconds" do
48
+ start_time = Time.now
49
+
50
+ resolver = RubyDNS::Resolver.new(SERVER_PORTS, :timeout => 10)
51
+
52
+ response = resolver.query("apple.com", IN::A)
53
+
54
+ expect(response.answer.length).to be == 0
55
+
56
+ end_time = Time.now
57
+
58
+ expect(end_time - start_time).to be_within(0.1).of(2.0)
59
+ end
60
+
61
+ it "times out after 1 second" do
62
+ start_time = Time.now
63
+
64
+ resolver = RubyDNS::Resolver.new(SERVER_PORTS, :timeout => 0.5)
65
+
66
+ response = resolver.query("apple.com", IN::A)
67
+
68
+ expect(response).to be nil
69
+
70
+ end_time = Time.now
71
+
72
+ expect(end_time - start_time).to be_within(0.1).of(1.0)
73
+ end
74
+
75
+ it "gets no answer immediately" do
76
+ start_time = Time.now
77
+
78
+ resolver = RubyDNS::Resolver.new(SERVER_PORTS, :timeout => 0.5)
79
+
80
+ response = resolver.query("oriontransfer.org", IN::A)
81
+
82
+ expect(response.answer.length).to be 0
83
+
84
+ end_time = Time.now
85
+
86
+ expect(end_time - start_time).to be_within(0.1).of(0.0)
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright, 2014, 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 'rubydns/system'
25
+
26
+ module RubyDNS::SocketSpec
27
+ IN = Resolv::DNS::Resource::IN
28
+
29
+ describe RubyDNS::TCPSocketHandler do
30
+ before(:all) do
31
+ Celluloid.shutdown
32
+ Celluloid.boot
33
+ end
34
+
35
+ it "should create server with existing TCP socket" do
36
+ socket = TCPServer.new('127.0.0.1', 2002)
37
+
38
+ # Start the RubyDNS server
39
+ @server = RubyDNS::run_server(:listen => [socket], asynchronous: true) do
40
+ resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
41
+
42
+ match(/.*\.com/, IN::A) do |transaction|
43
+ transaction.passthrough!(resolver)
44
+ end
45
+ end
46
+
47
+ resolver = RubyDNS::Resolver.new([[:tcp, '127.0.0.1', 2002]])
48
+ response = resolver.query('google.com')
49
+ expect(response.class).to be == RubyDNS::Message
50
+ end
51
+ end
52
+
53
+ describe RubyDNS::UDPSocketHandler do
54
+ before(:all) do
55
+ Celluloid.shutdown
56
+ Celluloid.boot
57
+ end
58
+
59
+ it "should create server with existing UDP socket" do
60
+ socket = UDPSocket.new
61
+ socket.bind('127.0.0.1', 2002)
62
+
63
+ # Start the RubyDNS server
64
+ @server = RubyDNS::run_server(:listen => [socket], asynchronous: true) do
65
+ resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
66
+
67
+ match(/.*\.com/, IN::A) do |transaction|
68
+ transaction.passthrough!(resolver)
69
+ end
70
+ end
71
+
72
+ resolver = RubyDNS::Resolver.new([[:udp, '127.0.0.1', 2002]])
73
+ response = resolver.query('google.com')
74
+ expect(response.class).to be == RubyDNS::Message
75
+ end
76
+ end
77
+ end
@@ -20,35 +20,41 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'minitest/autorun'
24
-
25
23
  require 'rubydns'
26
24
  require 'rubydns/system'
27
25
 
28
- class SystemTest < MiniTest::Test
29
- def test_system_nameservers
30
- # There technically should be at least one nameserver:
31
- resolver = RubyDNS::Resolver.new(RubyDNS::System::nameservers)
32
-
33
- EventMachine::run do
34
- resolver.query('google.com') do |response|
35
- assert_equal RubyDNS::Message, response.class
36
- assert_equal Resolv::DNS::RCode::NoError, response.rcode
37
-
38
- EventMachine::stop
39
- end
26
+ module RubyDNS::SystemSpec
27
+ describe RubyDNS::System do
28
+ before(:all) do
29
+ Celluloid.shutdown
30
+ Celluloid.boot
31
+ end
32
+
33
+ it "should have at least one namesever" do
34
+ expect(RubyDNS::System::nameservers.length).to be > 0
40
35
  end
41
- end
42
36
 
43
- def test_hosts
44
- hosts = RubyDNS::System::Hosts.new
37
+ it "should respond to query for google.com" do
38
+ resolver = RubyDNS::Resolver.new(RubyDNS::System::nameservers)
45
39
 
46
- # Load the test hosts data:
47
- File.open(File.expand_path("../hosts.txt", __FILE__)) do |file|
48
- hosts.parse_hosts(file)
40
+ response = resolver.query('google.com')
41
+
42
+ expect(response.class).to be == RubyDNS::Message
43
+ expect(response.rcode).to be == Resolv::DNS::RCode::NoError
49
44
  end
45
+ end
46
+
47
+ describe RubyDNS::System::Hosts do
48
+ it "should parse the hosts file" do
49
+ hosts = RubyDNS::System::Hosts.new
50
50
 
51
- assert hosts.call('testing')
52
- assert_equal '1.2.3.4', hosts['testing']
51
+ # Load the test hosts data:
52
+ File.open(File.expand_path("../hosts.txt", __FILE__)) do |file|
53
+ hosts.parse_hosts(file)
54
+ end
55
+
56
+ expect(hosts.call('testing')).to be == true
57
+ expect(hosts['testing']).to be == '1.2.3.4'
58
+ end
53
59
  end
54
60
  end
@@ -0,0 +1,64 @@
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 'yaml'
25
+
26
+ module RubyDNS::TransactionSpec
27
+ SERVER_PORTS = [[:udp, '8.8.8.8', 53], [:tcp, '8.8.8.8', 53]]
28
+ IN = Resolv::DNS::Resource::IN
29
+
30
+ describe RubyDNS::Transaction do
31
+ let(:server) { RubyDNS::Server.new }
32
+ let(:query) { RubyDNS::Message.new(0) }
33
+ let(:question) { Resolv::DNS::Name.create("www.google.com") }
34
+ let(:response) { RubyDNS::Message.new(0) }
35
+ let(:resolver) { RubyDNS::Resolver.new([[:udp, '8.8.8.8', 53], [:tcp, '8.8.8.8', 53]])}
36
+
37
+ it "should append an address" do
38
+ transaction = RubyDNS::Transaction.new(server, query, question, IN::A, response)
39
+
40
+ transaction.respond!("1.2.3.4")
41
+
42
+ expect(transaction.response.answer[0][0].to_s).to be == question.to_s
43
+ expect(transaction.response.answer[0][2].address.to_s).to be == "1.2.3.4"
44
+ end
45
+
46
+ it "should passthrough the request" do
47
+ transaction = RubyDNS::Transaction.new(server, query, question, IN::A, response)
48
+
49
+ expect(transaction.response.answer.size).to be 0
50
+
51
+ transaction.passthrough!(resolver)
52
+
53
+ expect(transaction.response.answer.size).to be > 0
54
+ end
55
+
56
+ it "should fail the request" do
57
+ transaction = RubyDNS::Transaction.new(server, query, question, IN::A, response)
58
+
59
+ transaction.fail! :NXDomain
60
+
61
+ expect(transaction.response.rcode).to be Resolv::DNS::RCode::NXDomain
62
+ end
63
+ end
64
+ end