dns_mock 0.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  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: