dns_mock 0.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e807a51b6ad704e5d7a20a311e20e76ad0f1319c649a990eb93512d1719b486f
4
- data.tar.gz: 2448fc6c17288aa8c359a4d6eaa0bc7a0cc3de3953c67940087984dfef327949
3
+ metadata.gz: da8634cd856df1f65afef1ba6f87f3b6118fc54525d00843da76c7b0e415dfc0
4
+ data.tar.gz: 45d0c5f55c9460d3d555ed26ae474fe7a7f30d614e172ec22d430d531f941c61
5
5
  SHA512:
6
- metadata.gz: efc57519f9ce59c1aa527cc316cf89eccbdc5b15c4c612bdf5c284a1af2874dfc52ed17d3125eed6435f1defc5338bbcfd0baafde4935448df639824084aab85
7
- data.tar.gz: 60a80d16dc4ec94ddfd6de6a093992db72e2e3960f6ca0f5f7d6d5974e776dc59395f3e75e5fb7913c804416e32a82a2fe842e6b3c8d954567876b6055451ada
6
+ metadata.gz: c4c7c08f00e98916c5d10580961bfa8518455d3323718327ca87767f699a78d4ceda1d2ea039150a8e05eec88dd50659519a46dadaf27c8f8c2504590951703c
7
+ data.tar.gz: 8fc55743a9ff129c5add8e1592b257046150c4267a621afc9bc0257901bfd3e72f4ac658fba03cde7f5608c1683584ebdf0e422af419e94f914eedcc465ed9e6
data/.codeclimate.yml CHANGED
@@ -7,7 +7,7 @@ checks:
7
7
  plugins:
8
8
  rubocop:
9
9
  enabled: true
10
- channel: rubocop-1-8
10
+ channel: rubocop-1-9
11
11
 
12
12
  reek:
13
13
  enabled: true
data/.reek.yml CHANGED
@@ -20,6 +20,9 @@ detectors:
20
20
  - DnsMock::RecordsDictionaryHelper#create_records_dictionary_by_records
21
21
  - DnsMock::ServerHelper#start_random_server
22
22
  - DnsMock::ServerHelper#stop_all_running_servers
23
+ - DnsMock::Server::RecordsDictionaryBuilder#rdns_lookup_prefix
24
+ - DnsMock::ContextGeneratorHelper#random_port_number
25
+ - DnsMock::TestFramework::RSpec::Helper#dns_mock_server
23
26
 
24
27
  ControlParameter:
25
28
  exclude:
@@ -44,3 +47,13 @@ detectors:
44
47
  LongParameterList:
45
48
  exclude:
46
49
  - DnsMock::Server#initialize
50
+ - DnsMock#start_server
51
+
52
+ BooleanParameter:
53
+ exclude:
54
+ - DnsMock::Server#initialize
55
+ - DnsMock#start_server
56
+
57
+ NilCheck:
58
+ exclude:
59
+ - DnsMock::Record::Builder::Mx#build
data/.rubocop.yml CHANGED
@@ -118,8 +118,11 @@ Style/EndlessMethod:
118
118
  Style/HashExcept:
119
119
  Enabled: true
120
120
 
121
+ Style/IfWithBooleanLiteralBranches:
122
+ Enabled: true
123
+
121
124
  Layout/LineLength:
122
- Max: 140
125
+ Max: 150
123
126
 
124
127
  Layout/EmptyLinesAroundAttributeAccessor:
125
128
  Enabled: true
@@ -203,6 +206,18 @@ Lint/RedundantDirGlobSort:
203
206
  Lint/UnmodifiedReduceAccumulator:
204
207
  Enabled: true
205
208
 
209
+ Lint/NumberedParameterAssignment:
210
+ Enabled: true
211
+
212
+ Lint/OrAssignmentToConstant:
213
+ Enabled: true
214
+
215
+ Lint/SymbolConversion:
216
+ Enabled: true
217
+
218
+ Lint/TripleQuotes:
219
+ Enabled: true
220
+
206
221
  Performance/AncestorsInclude:
207
222
  Enabled: true
208
223
 
data/CHANGELOG.md CHANGED
@@ -2,6 +2,161 @@
2
2
 
3
3
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
4
 
5
+ ## [1.2.0] - 2021-02-04
6
+
7
+ ### Ability to specify MX record priority
8
+
9
+ Added ability to specify custom priority of MX record if it needed. Now it impossible to define null or backup MX records. Please note, if you haven't specified a priority of MX record, it will be assigned automatically. MX records builder is assigning priority with step 10 from first item of defined MX records array.
10
+
11
+ ```ruby
12
+ records = {
13
+ 'example.com' => {
14
+ mx: %w[.:0 mx1.domain.com:10 mx2.domain.com:10 mx3.domain.com]
15
+ }
16
+ }
17
+
18
+ DnsMock.start_server(records: records)
19
+ ```
20
+
21
+ ```bash
22
+ dig @localhost -p 5300 MX example.com
23
+ ```
24
+
25
+ ```
26
+ ; <<>> DiG 9.10.6 <<>> @localhost -p 5300 MX example.com
27
+
28
+ ;; ANSWER SECTION:
29
+ example.com. 1 IN MX 0 .
30
+ example.com. 1 IN MX 10 mx1.domain.com.
31
+ example.com. 1 IN MX 10 mx2.domain.com.
32
+ example.com. 1 IN MX 40 mx3.domain.com.
33
+
34
+ ;; Query time: 0 msec
35
+ ;; SERVER: 127.0.0.1#5300(127.0.0.1)
36
+ ;; WHEN: Wed Feb 03 20:19:51 EET 2021
37
+ ;; MSG SIZE rcvd: 102
38
+ ```
39
+
40
+ ## [1.1.0] - 2021-02-01
41
+
42
+ ### RSpec native support
43
+
44
+ Added DnsMock helper which can simplify integration with RSpec.
45
+
46
+ ```ruby
47
+ # spec/support/config/dns_mock.rb
48
+ require 'dns_mock/test_framework/rspec'
49
+
50
+ RSpec.configure do |config|
51
+ config.include DnsMock::TestFramework::RSpec::Helper
52
+ end
53
+
54
+ # your awesome first_a_record_spec.rb
55
+ RSpec.describe FirstARecord do
56
+ subject(:service) do
57
+ described_class.call(
58
+ hostname,
59
+ dns_gateway_host: 'localhost',
60
+ dns_gateway_port: dns_mock_server.port
61
+ )
62
+ end
63
+
64
+ let(:hostname) { 'example.com' }
65
+ let(:first_a_record) { '1.2.3.4' }
66
+ let(:records) { { hostname => { a: [first_a_record] } } }
67
+
68
+ before { dns_mock_server.assign_mocks(records) }
69
+
70
+ it { is_expected.to eq(first_a_record) }
71
+ end
72
+ ```
73
+
74
+ ## [1.0.0] - 2021-01-29
75
+
76
+ ### Configurable record not found behaviour
77
+
78
+ Added configurable strategy for record not found case. By default it won't raise an exception when DNS record not found in mocked records dictionary:
79
+
80
+ ```ruby
81
+ DnsMock.start_server(port: 5300)
82
+ ```
83
+
84
+ ```bash
85
+ dig @localhost -p 5300 A example.com
86
+ ```
87
+
88
+ ```
89
+ ; <<>> DiG 9.10.6 <<>> @localhost -p 5300 A example.com
90
+ ;; Got answer:
91
+ ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38632
92
+ ;; flags: rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
93
+ ;; WARNING: recursion requested but not available
94
+
95
+ ;; OPT PSEUDOSECTION:
96
+ ; EDNS: version: 0, flags:; udp: 4096
97
+ ;; QUESTION SECTION:
98
+ ;example.com. IN A
99
+
100
+ ;; Query time: 0 msec
101
+ ;; SERVER: 127.0.0.1#5300(127.0.0.1)
102
+ ;; WHEN: Fri Jan 29 08:21:30 EET 2021
103
+ ;; MSG SIZE rcvd: 40
104
+ ```
105
+
106
+ If you want raise an exception when record not found, just start `DnsMock` with `exception_if_not_found: true` option:
107
+
108
+ ```ruby
109
+ DnsMock.start_server(exception_if_not_found: true)
110
+ ```
111
+
112
+ ### Changed
113
+
114
+ - Updated `DnsMock.start_server`
115
+ - Updated `DnsMock::Server`
116
+ - Updated `DnsMock::Response::Message`
117
+ - Updated `DnsMock::Response::Answer`
118
+ - Updated gem version, readme
119
+
120
+ ## [0.2.1] - 2021-01-27
121
+
122
+ ### Fixed RDNS lookup representation
123
+
124
+ Fixed RDNS lookup representatin for IP address in PTR record feature.
125
+
126
+ ## [0.2.0] - 2021-01-26
127
+
128
+ ### PTR record support
129
+
130
+ Added ability to mock PTR records. Please note, you can define host address without RDNS lookup prefix (`.in-addr.arpa`). `DnsMock` will do it for you.
131
+
132
+ ```ruby
133
+ records = {
134
+ '1.1.1.1' => {
135
+ ptr: %w[domain_1.com domain_2.com]
136
+ }
137
+ }
138
+
139
+ DnsMock.start_server(records: records)
140
+ ```
141
+
142
+ ```bash
143
+ dig @localhost -p 5300 -x 1.1.1.1
144
+ ```
145
+
146
+ ```
147
+ ; <<>> DiG 9.10.6 <<>> @localhost -p 5300 -x 1.1.1.1
148
+ ; (2 servers found)
149
+
150
+ ;; ANSWER SECTION:
151
+ 1.1.1.1.in-addr.arpa. 1 IN PTR domain_1.com.
152
+ 1.1.1.1.in-addr.arpa. 1 IN PTR domain_2.com.
153
+
154
+ ;; Query time: 0 msec
155
+ ;; SERVER: 127.0.0.1#5300(127.0.0.1)
156
+ ;; WHEN: Mon Jan 25 19:58:39 EET 2021
157
+ ;; MSG SIZE rcvd: 98
158
+ ```
159
+
5
160
  ## [0.1.0] - 2021-01-19
6
161
 
7
162
  ### First release
data/Gemfile.lock CHANGED
@@ -1,12 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dns_mock (0.1.0)
4
+ dns_mock (1.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- ast (2.4.1)
9
+ ast (2.4.2)
10
10
  bundler-audit (0.7.0.1)
11
11
  bundler (>= 1.2.0, < 3)
12
12
  thor (>= 0.18, < 2)
@@ -14,7 +14,7 @@ GEM
14
14
  childprocess (4.0.0)
15
15
  coderay (1.1.3)
16
16
  colorize (0.8.1)
17
- concurrent-ruby (1.1.7)
17
+ concurrent-ruby (1.1.8)
18
18
  diff-lcs (1.4.4)
19
19
  dnsruby (1.61.5)
20
20
  simpleidn (~> 0.1)
@@ -65,11 +65,11 @@ GEM
65
65
  rspec-expectations (3.10.1)
66
66
  diff-lcs (>= 1.2.0, < 2.0)
67
67
  rspec-support (~> 3.10.0)
68
- rspec-mocks (3.10.1)
68
+ rspec-mocks (3.10.2)
69
69
  diff-lcs (>= 1.2.0, < 2.0)
70
70
  rspec-support (~> 3.10.0)
71
- rspec-support (3.10.1)
72
- rubocop (1.8.1)
71
+ rspec-support (3.10.2)
72
+ rubocop (1.9.0)
73
73
  parallel (~> 1.10)
74
74
  parser (>= 3.0.0.0)
75
75
  rainbow (>= 2.2.2, < 4.0)
@@ -78,7 +78,7 @@ GEM
78
78
  rubocop-ast (>= 1.2.0, < 2.0)
79
79
  ruby-progressbar (~> 1.7)
80
80
  unicode-display_width (>= 1.4.0, < 3.0)
81
- rubocop-ast (1.4.0)
81
+ rubocop-ast (1.4.1)
82
82
  parser (>= 2.7.1.5)
83
83
  rubocop-performance (1.9.2)
84
84
  rubocop (>= 0.90.0, < 2.0)
@@ -97,7 +97,7 @@ GEM
97
97
  simplecov-html (0.10.2)
98
98
  simpleidn (0.2.1)
99
99
  unf (~> 0.1.4)
100
- thor (1.0.1)
100
+ thor (1.1.0)
101
101
  unf (0.1.4)
102
102
  unf_ext
103
103
  unf_ext (0.0.7.7)
@@ -118,7 +118,7 @@ DEPENDENCIES
118
118
  reek (~> 6.0, >= 6.0.3)
119
119
  rspec (~> 3.10)
120
120
  rspec-dns (~> 0.1.8)
121
- rubocop (~> 1.8, >= 1.8.1)
121
+ rubocop (~> 1.9)
122
122
  rubocop-performance (~> 1.9, >= 1.9.2)
123
123
  rubocop-rspec (~> 2.1)
124
124
  simplecov (~> 0.17.1)
data/README.md CHANGED
@@ -1,27 +1,40 @@
1
1
  # Ruby DnsMock
2
2
 
3
- [![CircleCI](https://circleci.com/gh/mocktools/ruby-dns-mock/tree/develop.svg?style=svg)](https://circleci.com/gh/mocktools/ruby-dns-mock/tree/develop)
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/5ea9da61ef468b8ad4c4/maintainability)](https://codeclimate.com/github/mocktools/ruby-dns-mock/maintainability)
4
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/5ea9da61ef468b8ad4c4/test_coverage)](https://codeclimate.com/github/mocktools/ruby-dns-mock/test_coverage)
5
+ [![CircleCI](https://circleci.com/gh/mocktools/ruby-dns-mock/tree/master.svg?style=svg)](https://circleci.com/gh/mocktools/ruby-dns-mock/tree/master)
4
6
  [![Gem Version](https://badge.fury.io/rb/dns_mock.svg)](https://badge.fury.io/rb/dns_mock)
5
7
  [![Downloads](https://img.shields.io/gem/dt/dns_mock.svg?colorA=004d99&colorB=0073e6)](https://rubygems.org/gems/dns_mock)
6
8
  [![GitHub](https://img.shields.io/github/license/mocktools/ruby-dns-mock)](LICENSE.txt)
7
9
  [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v1.4%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md)
8
10
 
11
+ 💎 Ruby DNS mock. Mimic any DNS records for your test environment and even more.
12
+
9
13
  ## Table of Contents
10
14
 
11
15
  - [Features](#features)
12
16
  - [Requirements](#requirements)
13
17
  - [Installation](#installation)
14
18
  - [Usage](#usage)
15
-
16
- ## Requirements
17
-
18
- Ruby MRI 2.5.0+
19
+ - [RSpec](#rspec)
20
+ - [Contributing](#contributing)
21
+ - [License](#license)
22
+ - [Code of Conduct](#code-of-conduct)
23
+ - [Credits](#credits)
24
+ - [Versioning](#versioning)
25
+ - [Changelog](CHANGELOG.md)
19
26
 
20
27
  ## Features
21
28
 
22
- - Ability to mimic any DNS records for your test environment
29
+ - Ability to mimic any DNS records (`A`, `AAAA`, `CNAME`, `MX`, `NS`, `PTR`, `SOA` and `TXT`)
23
30
  - Zero runtime dependencies
24
- - Test framework agnostic (`RSpec`, `Test::Unit`, `MiniTest`). Even can be used outside of test frameworks
31
+ - Lightweight UDP DNS mock server with dynamic/manual port assignment
32
+ - Test framework agnostic (it's PORO, so you can use it outside of `RSpec`, `Test::Unit` or `MiniTest`)
33
+ - Simple and intuitive DSL
34
+
35
+ ## Requirements
36
+
37
+ Ruby MRI 2.5.0+
25
38
 
26
39
  ## Installation
27
40
 
@@ -44,13 +57,13 @@ Or install it yourself as:
44
57
  ## Usage
45
58
 
46
59
  ```ruby
47
- # Example of mocked DNS records
60
+ # Example of mocked DNS records, please follow this data structure
48
61
  records = {
49
62
  'example.com' => {
50
- a: %w[1.1.1.1, 2.2.2.2],
63
+ a: %w[1.1.1.1 2.2.2.2],
51
64
  aaaa: %w[2a00:1450:4001:81e::200e],
52
65
  ns: %w[ns1.domain.com ns2.domain.com],
53
- mx: %w[mx1.domain.com mx2.domain.com],
66
+ mx: %w[mx1.domain.com mx2.domain.com:50], # you can specify host(s) or host(s) with priority
54
67
  txt: %w[txt_record_1 txt_record_2],
55
68
  cname: 'some.domain.com',
56
69
  soa: [
@@ -64,16 +77,119 @@ records = {
64
77
  minimum: 3_600
65
78
  }
66
79
  ]
80
+ },
81
+ '1.2.3.4' => {
82
+ ptr: %w[domain_1.com domain_2.com]
67
83
  }
68
84
  }
69
85
 
70
- # Main DnsMock interface:
71
- dns_mock_server = DnsMock.start_server(records: records) # records, port are an optional params
72
- dns_mock_server.port
73
- dns_mock_server.assign_mocks(records)
74
- dns_mock_server.reset_mocks!
75
- dns_mock_server.stop!
86
+ # Main DnsMock interface
87
+ # records:Hash, port:Integer, exception_if_not_found:Boolean
88
+ # are optional params. By default creates dns mock server with
89
+ # empty records. A free port for server will be randomly assigned
90
+ # in the range from 49152 to 65535, if record not found exception
91
+ # won't raises. Returns current dns mock server
92
+ dns_mock_server = DnsMock.start_server(records: records) # => DnsMock::Server instance
93
+
94
+ # returns current dns mock server port
95
+ dns_mock_server.port # => 49322
96
+
97
+ # interface to setup mock records.
98
+ # Available only in case when server mocked records is empty
99
+ dns_mock_server.assign_mocks(records) # => true/nil
100
+
101
+ # interface to reset current mocked records
102
+ dns_mock_server.reset_mocks! # => true
103
+
104
+ # interface to stop current dns mock server
105
+ dns_mock_server.stop! # => true
76
106
 
77
- DnsMock.running_servers
78
- DnsMock.stop_running_servers!
107
+ # returns list of running dns mock servers
108
+ DnsMock.running_servers # => [DnsMock::Server instance]
109
+
110
+ # interface to stop all running dns mock servers
111
+ DnsMock.stop_running_servers! # => true
112
+ ```
113
+
114
+ ### RSpec
115
+
116
+ Require this either in your Gemfile or in RSpec's support scripts. So either:
117
+
118
+ ```ruby
119
+ # Gemfile
120
+ group :test do
121
+ gem 'rspec'
122
+ gem 'dns_mock', require: 'dns_mock/test_framework/rspec'
123
+ end
124
+ ```
125
+
126
+ or
127
+
128
+ ```ruby
129
+ # spec/support/config/dns_mock.rb
130
+ require 'dns_mock/test_framework/rspec'
79
131
  ```
132
+
133
+ #### DnsMock RSpec helper
134
+
135
+ Just add `DnsMock::TestFramework::RSpec::Helper` if you wanna use shortcut `dns_mock_server` for DnsMock server instance into your `RSpec.describe` blocks:
136
+
137
+ ```ruby
138
+ # spec/support/config/dns_mock.rb
139
+ RSpec.configure do |config|
140
+ config.include DnsMock::TestFramework::RSpec::Helper
141
+ end
142
+ ```
143
+
144
+ ```ruby
145
+ # your awesome first_a_record_spec.rb
146
+ RSpec.describe FirstARecord do
147
+ subject(:service) do
148
+ described_class.call(
149
+ hostname,
150
+ dns_gateway_host: 'localhost',
151
+ dns_gateway_port: dns_mock_server.port
152
+ )
153
+ end
154
+
155
+ let(:hostname) { 'example.com' }
156
+ let(:first_a_record) { '1.2.3.4' }
157
+ let(:records) { { hostname => { a: [first_a_record] } } }
158
+
159
+ before { dns_mock_server.assign_mocks(records) }
160
+
161
+ it { is_expected.to eq(first_a_record) }
162
+ end
163
+ ```
164
+
165
+ #### DnsMock RSpec interface
166
+
167
+ If you won't use `DnsMock::TestFramework::RSpec::Helper` you can use `DnsMock::TestFramework::RSpec::Interface` directly instead:
168
+
169
+ ```ruby
170
+ DnsMock::TestFramework::RSpec::Interface.start_server # creates and runs DnsMock server instance
171
+ DnsMock::TestFramework::RSpec::Interface.stop_server! # stops current DnsMock server instance
172
+ DnsMock::TestFramework::RSpec::Interface.reset_mocks! # resets mocks in current DnsMock server instance
173
+ DnsMock::TestFramework::RSpec::Interface.clear_server! # stops and clears current DnsMock server instance
174
+ ```
175
+
176
+ ## Contributing
177
+
178
+ Bug reports and pull requests are welcome on GitHub at https://github.com/mocktools/ruby-dns-mock. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. Please check the [open tikets](https://github.com/mocktools/ruby-dns-mock/issues). Be shure to follow Contributor Code of Conduct below and our [Contributing Guidelines](CONTRIBUTING.md).
179
+
180
+ ## License
181
+
182
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
183
+
184
+ ## Code of Conduct
185
+
186
+ Everyone interacting in the DnsMock project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](CODE_OF_CONDUCT.md).
187
+
188
+ ## Credits
189
+
190
+ - [The Contributors](https://github.com/mocktools/ruby-dns-mock/graphs/contributors) for code and awesome suggestions
191
+ - [The Stargazers](https://github.com/mocktools/ruby-dns-mock/stargazers) for showing their support
192
+
193
+ ## Versioning
194
+
195
+ DnsMock uses [Semantic Versioning 2.0.0](https://semver.org)
data/dns_mock.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.email = ['admin@bestweb.com.ua']
12
12
 
13
13
  spec.summary = %(dns_mock)
14
- spec.description = %(Ruby DNS mock)
14
+ spec.description = %(💎 Ruby DNS mock. Mimic any DNS records for your test environment and even more.)
15
15
 
16
16
  spec.homepage = 'https://github.com/mocktools/ruby-dns-mock'
17
17
  spec.license = 'MIT'
@@ -41,7 +41,7 @@ Gem::Specification.new do |spec|
41
41
  spec.add_development_dependency 'reek', '~> 6.0', '>= 6.0.3'
42
42
  spec.add_development_dependency 'rspec', '~> 3.10'
43
43
  spec.add_development_dependency 'rspec-dns', '~> 0.1.8'
44
- spec.add_development_dependency 'rubocop', '~> 1.8', '>= 1.8.1'
44
+ spec.add_development_dependency 'rubocop', '~> 1.9'
45
45
  spec.add_development_dependency 'rubocop-performance', '~> 1.9', '>= 1.9.2'
46
46
  spec.add_development_dependency 'rubocop-rspec', '~> 2.1'
47
47
  spec.add_development_dependency 'simplecov', '~> 0.17.1'
data/lib/dns_mock.rb CHANGED
@@ -4,8 +4,8 @@ require_relative 'dns_mock/core'
4
4
 
5
5
  module DnsMock
6
6
  class << self
7
- def start_server(server = DnsMock::Server, records: {}, port: nil)
8
- server.new(records: records, port: port)
7
+ def start_server(server = DnsMock::Server, records: {}, port: nil, exception_if_not_found: false)
8
+ server.new(records: records, port: port, exception_if_not_found: exception_if_not_found)
9
9
  end
10
10
 
11
11
  def running_servers
data/lib/dns_mock/core.rb CHANGED
@@ -4,7 +4,7 @@ require 'resolv'
4
4
  require 'socket'
5
5
 
6
6
  module DnsMock
7
- AVAILABLE_DNS_RECORD_TYPES = %i[a aaaa cname mx ns soa txt].freeze
7
+ AVAILABLE_DNS_RECORD_TYPES = %i[a aaaa cname mx ns ptr soa txt].freeze
8
8
 
9
9
  module Error
10
10
  require_relative '../dns_mock/error/argument_type'
@@ -26,6 +26,7 @@ module DnsMock
26
26
  require_relative '../dns_mock/record/factory/cname'
27
27
  require_relative '../dns_mock/record/factory/mx'
28
28
  require_relative '../dns_mock/record/factory/ns'
29
+ require_relative '../dns_mock/record/factory/ptr'
29
30
  require_relative '../dns_mock/record/factory/soa'
30
31
  require_relative '../dns_mock/record/factory/txt'
31
32
  end
@@ -39,6 +40,7 @@ module DnsMock
39
40
  require_relative '../dns_mock/record/builder/cname'
40
41
  require_relative '../dns_mock/record/builder/mx'
41
42
  require_relative '../dns_mock/record/builder/ns'
43
+ require_relative '../dns_mock/record/builder/ptr'
42
44
  require_relative '../dns_mock/record/builder/soa'
43
45
  require_relative '../dns_mock/record/builder/txt'
44
46
  end
@@ -4,18 +4,29 @@ module DnsMock
4
4
  module Record
5
5
  module Builder
6
6
  class Mx < DnsMock::Record::Builder::Base
7
+ include DnsMock::Error::Helper
8
+
9
+ MX_RECORD_REGEX_PATTERN = /\A(.+):(\d+)|(.+)\z/.freeze
7
10
  RECORD_PREFERENCE_STEP = 10
8
11
 
9
12
  def build
10
13
  records_data.map.with_index(1) do |record_data, record_preference|
14
+ record_data, custom_record_preference = parse_mx_record_data(record_data)
11
15
  target_factory.new(
12
16
  record_data: [
13
- record_preference * DnsMock::Record::Builder::Mx::RECORD_PREFERENCE_STEP,
17
+ custom_record_preference&.to_i || record_preference * DnsMock::Record::Builder::Mx::RECORD_PREFERENCE_STEP,
14
18
  record_data
15
19
  ]
16
20
  ).create
17
21
  end
18
22
  end
23
+
24
+ private
25
+
26
+ def parse_mx_record_data(record_data)
27
+ raise_record_context_type_error(:mx, record_data, ::String)
28
+ record_data.scan(DnsMock::Record::Builder::Mx::MX_RECORD_REGEX_PATTERN).flatten.compact
29
+ end
19
30
  end
20
31
  end
21
32
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DnsMock
4
+ module Record
5
+ module Builder
6
+ Ptr = ::Class.new(DnsMock::Record::Builder::Base)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DnsMock
4
+ module Record
5
+ module Factory
6
+ Ptr = ::Class.new(DnsMock::Record::Factory::Base) do
7
+ record_type :ptr
8
+
9
+ def instance_params
10
+ [create_dns_name(record_data)]
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -8,8 +8,9 @@ module DnsMock
8
8
  hash[::Resolv::DNS::Resource::IN.const_get(record_type.upcase)] = record_type
9
9
  end.freeze
10
10
 
11
- def initialize(records)
11
+ def initialize(records, exception_if_not_found)
12
12
  @records = records
13
+ @exception_if_not_found = exception_if_not_found
13
14
  end
14
15
 
15
16
  def build(hostname, record_class)
@@ -19,13 +20,13 @@ module DnsMock
19
20
 
20
21
  private
21
22
 
22
- attr_reader :records, :hostname
23
+ attr_reader :records, :exception_if_not_found, :hostname
23
24
 
24
25
  def record_by_type(record_class)
25
26
  record_type = DnsMock::Response::Answer::REVERSE_TYPE_MAPPER[record_class]
26
27
  found_records = records.dig(hostname.to_s, record_type)
27
- raise DnsMock::Error::RecordNotFound.new(record_type, hostname) unless found_records
28
- found_records
28
+ raise DnsMock::Error::RecordNotFound.new(record_type, hostname) unless found_records || !exception_if_not_found
29
+ Array(found_records)
29
30
  end
30
31
  end
31
32
  end
@@ -3,8 +3,14 @@
3
3
  module DnsMock
4
4
  module Response
5
5
  class Message
6
- def initialize(packet, records, dns_answer = DnsMock::Response::Answer, dns_message = ::Resolv::DNS::Message)
7
- @dns_answer = dns_answer.new(records)
6
+ def initialize(
7
+ packet,
8
+ records,
9
+ exception_if_not_found,
10
+ dns_answer = DnsMock::Response::Answer,
11
+ dns_message = ::Resolv::DNS::Message
12
+ )
13
+ @dns_answer = dns_answer.new(records, exception_if_not_found)
8
14
  @dns_message = dns_message.decode(packet)
9
15
  end
10
16
 
@@ -15,13 +15,15 @@ module DnsMock
15
15
  random_available_port = DnsMock::Server::RandomAvailablePort,
16
16
  thread_class = ::Thread,
17
17
  records: nil,
18
- port: nil
18
+ port: nil,
19
+ exception_if_not_found: false
19
20
  )
20
21
  @socket = socket
21
22
  @records_dictionary_builder = records_dictionary_builder
22
23
  @thread_class = thread_class
23
24
  @records = records_dictionary_builder.call(records || {})
24
25
  @port = port || random_available_port.call
26
+ @exception_if_not_found = exception_if_not_found
25
27
  prepare_server_thread
26
28
  end
27
29
 
@@ -34,7 +36,7 @@ module DnsMock
34
36
  break if packet.size.zero?
35
37
 
36
38
  address, port = addr.values_at(3, 1)
37
- socket.send(DnsMock::Response::Message.new(packet, records).as_binary_string, 0, address, port)
39
+ socket.send(DnsMock::Response::Message.new(packet, records, exception_if_not_found).as_binary_string, 0, address, port)
38
40
  end
39
41
  ensure
40
42
  socket.close
@@ -63,7 +65,7 @@ module DnsMock
63
65
 
64
66
  private
65
67
 
66
- attr_reader :socket, :records_dictionary_builder, :thread_class
68
+ attr_reader :socket, :records_dictionary_builder, :thread_class, :exception_if_not_found
67
69
  attr_accessor :records, :thread
68
70
 
69
71
  def prepare_socket_for_session
@@ -5,6 +5,9 @@ module DnsMock
5
5
  class RecordsDictionaryBuilder
6
6
  include DnsMock::Error::Helper
7
7
 
8
+ IP_ADDRESS_PATTERN = /\A((1\d|[1-9]|2[0-4])?\d|25[0-5])(\.\g<1>){3}\z/.freeze
9
+ IP_OCTET_GROUPS = /(\d+).(\d+).(\d+).(\d+)/.freeze
10
+ RDNS_LOOKUP_REPRESENTATION = '\4.\3.\2.\1.in-addr.arpa'
8
11
  TYPE_MAPPER = DnsMock::AVAILABLE_DNS_RECORD_TYPES.zip(
9
12
  [
10
13
  [DnsMock::Record::Builder::A, DnsMock::Record::Factory::A, ::Array],
@@ -12,6 +15,7 @@ module DnsMock
12
15
  [DnsMock::Record::Builder::Cname, DnsMock::Record::Factory::Cname, ::String],
13
16
  [DnsMock::Record::Builder::Mx, DnsMock::Record::Factory::Mx, ::Array],
14
17
  [DnsMock::Record::Builder::Ns, DnsMock::Record::Factory::Ns, ::Array],
18
+ [DnsMock::Record::Builder::Ptr, DnsMock::Record::Factory::Ptr, ::Array],
15
19
  [DnsMock::Record::Builder::Soa, DnsMock::Record::Factory::Soa, ::Array],
16
20
  [DnsMock::Record::Builder::Txt, DnsMock::Record::Factory::Txt, ::Array]
17
21
  ]
@@ -31,7 +35,7 @@ module DnsMock
31
35
  raise_unless(DnsMock::Error::ArgumentType.new(records_to_build.class), records_to_build.is_a?(::Hash))
32
36
  records_to_build.each do |hostname, dns_records|
33
37
  raise_unless(DnsMock::Error::RecordHostType.new(hostname, hostname.class), hostname.is_a?(::String))
34
- records[hostname] = dns_records.each_with_object({}) do |(record_type, records_data), records_instances_by_type|
38
+ records[rdns_lookup_prefix(hostname)] = dns_records.each_with_object({}) do |(record_type, records_data), records_instances_by_type|
35
39
  records_instances_by_type[record_type] = build_records_instances_by_type(record_type, records_data)
36
40
  end
37
41
  end
@@ -41,6 +45,15 @@ module DnsMock
41
45
 
42
46
  private
43
47
 
48
+ def rdns_lookup_prefix(hostname)
49
+ return hostname unless hostname[DnsMock::Server::RecordsDictionaryBuilder::IP_ADDRESS_PATTERN]
50
+
51
+ hostname.gsub(
52
+ DnsMock::Server::RecordsDictionaryBuilder::IP_OCTET_GROUPS,
53
+ DnsMock::Server::RecordsDictionaryBuilder::RDNS_LOOKUP_REPRESENTATION
54
+ )
55
+ end
56
+
44
57
  def build_records_instances_by_type(record_type, records_to_build)
45
58
  target_builder, target_factory, expected_type = DnsMock::Server::RecordsDictionaryBuilder::TYPE_MAPPER[record_type]
46
59
  raise_record_type_error(record_type, target_builder)
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/core'
4
+ require_relative '../../dns_mock'
5
+ require_relative './rspec/interface'
6
+ require_relative './rspec/helper'
7
+
8
+ RSpec.configure do |config|
9
+ config.before(:suite) { DnsMock::TestFramework::RSpec::Interface.start_server }
10
+ config.after(:suite) { DnsMock::TestFramework::RSpec::Interface.stop_server! }
11
+ config.after { DnsMock::TestFramework::RSpec::Interface.reset_mocks! }
12
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './interface'
4
+
5
+ module DnsMock
6
+ module TestFramework
7
+ module RSpec
8
+ module Helper
9
+ def dns_mock_server(**options)
10
+ DnsMock::TestFramework::RSpec::Interface.start_server(**options)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DnsMock
4
+ module TestFramework
5
+ module RSpec
6
+ module Interface
7
+ class << self
8
+ def start_server(**options)
9
+ @dns_mock_server ||= DnsMock.start_server(**options) # rubocop:disable Naming/MemoizedInstanceVariableName
10
+ end
11
+
12
+ def stop_server!
13
+ return unless dns_mock_server
14
+
15
+ dns_mock_server.stop!
16
+ end
17
+
18
+ def reset_mocks!
19
+ return unless dns_mock_server
20
+
21
+ dns_mock_server.reset_mocks!
22
+ end
23
+
24
+ def clear_server!
25
+ @dns_mock_server = nil
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :dns_mock_server
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DnsMock
4
- VERSION = '0.1.0'
4
+ VERSION = '1.2.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dns_mock
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladislav Trotsenko
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-19 00:00:00.000000000 Z
11
+ date: 2021-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -174,20 +174,14 @@ dependencies:
174
174
  requirements:
175
175
  - - "~>"
176
176
  - !ruby/object:Gem::Version
177
- version: '1.8'
178
- - - ">="
179
- - !ruby/object:Gem::Version
180
- version: 1.8.1
177
+ version: '1.9'
181
178
  type: :development
182
179
  prerelease: false
183
180
  version_requirements: !ruby/object:Gem::Requirement
184
181
  requirements:
185
182
  - - "~>"
186
183
  - !ruby/object:Gem::Version
187
- version: '1.8'
188
- - - ">="
189
- - !ruby/object:Gem::Version
190
- version: 1.8.1
184
+ version: '1.9'
191
185
  - !ruby/object:Gem::Dependency
192
186
  name: rubocop-performance
193
187
  requirement: !ruby/object:Gem::Requirement
@@ -236,7 +230,8 @@ dependencies:
236
230
  - - "~>"
237
231
  - !ruby/object:Gem::Version
238
232
  version: 0.17.1
239
- description: Ruby DNS mock
233
+ description: "\U0001F48E Ruby DNS mock. Mimic any DNS records for your test environment
234
+ and even more."
240
235
  email:
241
236
  - admin@bestweb.com.ua
242
237
  executables: []
@@ -286,6 +281,7 @@ files:
286
281
  - lib/dns_mock/record/builder/cname.rb
287
282
  - lib/dns_mock/record/builder/mx.rb
288
283
  - lib/dns_mock/record/builder/ns.rb
284
+ - lib/dns_mock/record/builder/ptr.rb
289
285
  - lib/dns_mock/record/builder/soa.rb
290
286
  - lib/dns_mock/record/builder/txt.rb
291
287
  - lib/dns_mock/record/factory/a.rb
@@ -294,6 +290,7 @@ files:
294
290
  - lib/dns_mock/record/factory/cname.rb
295
291
  - lib/dns_mock/record/factory/mx.rb
296
292
  - lib/dns_mock/record/factory/ns.rb
293
+ - lib/dns_mock/record/factory/ptr.rb
297
294
  - lib/dns_mock/record/factory/soa.rb
298
295
  - lib/dns_mock/record/factory/txt.rb
299
296
  - lib/dns_mock/response/answer.rb
@@ -301,6 +298,9 @@ files:
301
298
  - lib/dns_mock/server.rb
302
299
  - lib/dns_mock/server/random_available_port.rb
303
300
  - lib/dns_mock/server/records_dictionary_builder.rb
301
+ - lib/dns_mock/test_framework/rspec.rb
302
+ - lib/dns_mock/test_framework/rspec/helper.rb
303
+ - lib/dns_mock/test_framework/rspec/interface.rb
304
304
  - lib/dns_mock/version.rb
305
305
  homepage: https://github.com/mocktools/ruby-dns-mock
306
306
  licenses: