dns-zone2 0.3.2

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.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +2 -0
  3. data/HISTORY.md +45 -0
  4. data/README.md +151 -0
  5. data/Rakefile +15 -0
  6. data/dns-zone2.gemspec +41 -0
  7. data/lib/dns/zone.rb +207 -0
  8. data/lib/dns/zone/rr.rb +87 -0
  9. data/lib/dns/zone/rr/a.rb +21 -0
  10. data/lib/dns/zone/rr/aaaa.rb +5 -0
  11. data/lib/dns/zone/rr/cdnskey.rb +5 -0
  12. data/lib/dns/zone/rr/cds.rb +5 -0
  13. data/lib/dns/zone/rr/cname.rb +21 -0
  14. data/lib/dns/zone/rr/dlv.rb +5 -0
  15. data/lib/dns/zone/rr/dnskey.rb +38 -0
  16. data/lib/dns/zone/rr/ds.rb +38 -0
  17. data/lib/dns/zone/rr/hinfo.rb +31 -0
  18. data/lib/dns/zone/rr/mx.rb +33 -0
  19. data/lib/dns/zone/rr/naptr.rb +44 -0
  20. data/lib/dns/zone/rr/ns.rb +21 -0
  21. data/lib/dns/zone/rr/nsec.rb +32 -0
  22. data/lib/dns/zone/rr/nsec3.rb +45 -0
  23. data/lib/dns/zone/rr/nsec3param.rb +38 -0
  24. data/lib/dns/zone/rr/ptr.rb +21 -0
  25. data/lib/dns/zone/rr/record.rb +88 -0
  26. data/lib/dns/zone/rr/rrsig.rb +54 -0
  27. data/lib/dns/zone/rr/soa.rb +51 -0
  28. data/lib/dns/zone/rr/spf.rb +5 -0
  29. data/lib/dns/zone/rr/srv.rb +38 -0
  30. data/lib/dns/zone/rr/sshfp.rb +35 -0
  31. data/lib/dns/zone/rr/txt.rb +24 -0
  32. data/lib/dns/zone/test_case.rb +27 -0
  33. data/lib/dns/zone/version.rb +6 -0
  34. data/test/rr/a_test.rb +37 -0
  35. data/test/rr/aaaa_test.rb +27 -0
  36. data/test/rr/cdnskey_test.rb +31 -0
  37. data/test/rr/cds_test.rb +28 -0
  38. data/test/rr/cname_test.rb +19 -0
  39. data/test/rr/dlv_test.rb +28 -0
  40. data/test/rr/dnskey_test.rb +31 -0
  41. data/test/rr/ds_test.rb +28 -0
  42. data/test/rr/hinfo_test.rb +44 -0
  43. data/test/rr/mx_test.rb +26 -0
  44. data/test/rr/naptr_test.rb +60 -0
  45. data/test/rr/ns_test.rb +18 -0
  46. data/test/rr/nsec3_test.rb +33 -0
  47. data/test/rr/nsec3param_test.rb +29 -0
  48. data/test/rr/nsec_test.rb +24 -0
  49. data/test/rr/ptr_test.rb +19 -0
  50. data/test/rr/record_test.rb +37 -0
  51. data/test/rr/rrsig_test.rb +40 -0
  52. data/test/rr/soa_test.rb +34 -0
  53. data/test/rr/spf_test.rb +20 -0
  54. data/test/rr/srv_test.rb +24 -0
  55. data/test/rr/sshfp_test.rb +24 -0
  56. data/test/rr/txt_test.rb +44 -0
  57. data/test/rr_test.rb +50 -0
  58. data/test/version_test.rb +9 -0
  59. data/test/zone_test.rb +273 -0
  60. metadata +217 -0
@@ -0,0 +1,40 @@
1
+ require 'dns/zone/test_case'
2
+
3
+ class RR_RRSIG_Test < DNS::Zone::TestCase
4
+
5
+ TEST_SIGNATURE = 'oJB1W6WNGv+ldvQ3WDG0MQkg5IEhjRip8WTrPYGv07h108dUKGMeDPKijVCHX3DDKdfb+v6oB9wfuh3DTJXUAfI/M0zmO/zz8bW0Rznl8O3tGNazPwQKkRN20XPXV6nwwfoXmJQbsLNrLfkGJ5D6fwFm8nN+6pBzeDQfsS3Ap3o='
6
+
7
+ def test_build_rr__rrsig
8
+ rr = DNS::Zone::RR::RRSIG.new
9
+ rr.label = 'host.example.com.'
10
+ rr.type_covered = 'A'
11
+ rr.algorithm = 5
12
+ rr.labels = 3
13
+ rr.original_ttl = 86400
14
+ rr.signature_expiration = 20030322173103
15
+ rr.signature_inception = 20030220173103
16
+ rr.key_tag = 2642
17
+ rr.signer = 'example.com.'
18
+ rr.signature = TEST_SIGNATURE
19
+
20
+ assert_equal "host.example.com. IN RRSIG A 5 3 86400 20030322173103 20030220173103 2642 example.com. #{TEST_SIGNATURE}", rr.dump
21
+
22
+ end
23
+
24
+ def test_load_rr__rrsig
25
+ rr = DNS::Zone::RR::RRSIG.new.load("host.example.com. IN RRSIG A 5 3 86400 20030322173103 20030220173103 2642 example.com. #{TEST_SIGNATURE}")
26
+ assert_equal 'host.example.com.', rr.label
27
+ assert_equal 'RRSIG', rr.type
28
+
29
+ assert_equal 'A', rr.type_covered
30
+ assert_equal 5, rr.algorithm
31
+ assert_equal 3, rr.labels
32
+ assert_equal 86400, rr.original_ttl
33
+ assert_equal 20030322173103, rr.signature_expiration
34
+ assert_equal 20030220173103, rr.signature_inception
35
+ assert_equal 2642, rr.key_tag
36
+ assert_equal 'example.com.', rr.signer
37
+ assert_equal TEST_SIGNATURE, rr.signature
38
+ end
39
+
40
+ end
@@ -0,0 +1,34 @@
1
+ require 'dns/zone/test_case'
2
+
3
+ class RR_SOA_Test < DNS::Zone::TestCase
4
+
5
+ EXAMPLE_SOA_IN = '@ IN SOA ns0.lividpenguin.com. luke.lividpenguin.com. 2014021601 3h 15m 4w 30m'
6
+ EXAMPLE_SOA_OUT = '@ IN SOA ns0.lividpenguin.com. luke.lividpenguin.com. ( 2014021601 3h 15m 4w 30m )'
7
+
8
+ def test_build_rr__soa
9
+ rr = DNS::Zone::RR::SOA.new
10
+ rr.nameserver = 'ns0.lividpenguin.com.'
11
+ rr.email = 'luke.lividpenguin.com.'
12
+ rr.serial = 2014_02_16_01
13
+ rr.refresh_ttl = '3h'
14
+ rr.retry_ttl = '15m'
15
+ rr.expiry_ttl = '4w'
16
+ rr.minimum_ttl = '30m'
17
+ assert_equal EXAMPLE_SOA_OUT, rr.dump
18
+ end
19
+
20
+ def test_load_rr__soa
21
+ rr = DNS::Zone::RR::SOA.new.load(EXAMPLE_SOA_IN)
22
+ assert_equal '@', rr.label
23
+ assert_equal 'SOA', rr.type
24
+
25
+ assert_equal 'ns0.lividpenguin.com.', rr.nameserver
26
+ assert_equal 'luke.lividpenguin.com.', rr.email
27
+ assert_equal 2014_02_16_01, rr.serial
28
+ assert_equal '3h', rr.refresh_ttl
29
+ assert_equal '15m', rr.retry_ttl
30
+ assert_equal '4w', rr.expiry_ttl
31
+ assert_equal '30m', rr.minimum_ttl
32
+ end
33
+
34
+ end
@@ -0,0 +1,20 @@
1
+ require 'dns/zone/test_case'
2
+
3
+ class RR_SPF_Test < DNS::Zone::TestCase
4
+
5
+ def test_build_rr__spf
6
+ rr = DNS::Zone::RR::SPF.new
7
+ rr.ttl = '2w'
8
+ rr.text = '"v=spf1 +mx -all"'
9
+ assert_equal '@ 2w IN SPF "v=spf1 +mx -all"', rr.dump
10
+ end
11
+
12
+ def test_load_rr__spf
13
+ rr = DNS::Zone::RR::SPF.new.load('@ 2w IN SPF "v=spf1 +mx -all"')
14
+ assert_equal '@', rr.label
15
+ assert_equal 'IN', rr.klass
16
+ assert_equal 'SPF', rr.type
17
+ assert_equal '"v=spf1 +mx -all"', rr.text
18
+ end
19
+
20
+ end
@@ -0,0 +1,24 @@
1
+ require 'dns/zone/test_case'
2
+
3
+ class RR_SRV_Test < DNS::Zone::TestCase
4
+
5
+ def test_build_rr__srv
6
+ rr = DNS::Zone::RR::SRV.new
7
+ rr.priority = 5
8
+ rr.weight = 0
9
+ rr.port = 5269
10
+ rr.target = 'xmpp-server.l.google.com.'
11
+ assert_equal '@ IN SRV 5 0 5269 xmpp-server.l.google.com.', rr.dump
12
+ end
13
+
14
+ def test_load_rr__srv
15
+ rr = DNS::Zone::RR::SRV.new.load('@ IN SRV 5 0 5269 xmpp-server.l.google.com.')
16
+ assert_equal '@', rr.label
17
+ assert_equal 'SRV', rr.type
18
+ assert_equal 5, rr.priority
19
+ assert_equal 0, rr.weight
20
+ assert_equal 5269, rr.port
21
+ assert_equal 'xmpp-server.l.google.com.', rr.target
22
+ end
23
+
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'dns/zone/test_case'
2
+
3
+ class RR_SSHFP_Test < DNS::Zone::TestCase
4
+
5
+ def test_build_rr__sshfp
6
+ rr = DNS::Zone::RR::SSHFP.new
7
+ rr.label = 'host.example.'
8
+ rr.algorithm_number = 2
9
+ rr.fingerprint_type = 1
10
+ rr.fingerprint = '123456789abcdef67890123456789abcdef67890'
11
+
12
+ assert_equal 'host.example. IN SSHFP 2 1 123456789abcdef67890123456789abcdef67890', rr.dump
13
+ end
14
+
15
+ def test_load_rr__sshfp
16
+ rr = DNS::Zone::RR::SSHFP.new.load('host.example. IN SSHFP 2 1 123456789abcdef67890123456789abcdef67890')
17
+ assert_equal 'host.example.', rr.label
18
+ assert_equal 'SSHFP', rr.type
19
+ assert_equal 2, rr.algorithm_number
20
+ assert_equal 1, rr.fingerprint_type
21
+ assert_equal '123456789abcdef67890123456789abcdef67890', rr.fingerprint
22
+ end
23
+
24
+ end
@@ -0,0 +1,44 @@
1
+ require 'dns/zone/test_case'
2
+
3
+ class RR_TXT_Test < DNS::Zone::TestCase
4
+
5
+ def test_build_rr__txt
6
+ rr = DNS::Zone::RR::TXT.new
7
+
8
+ # ensure we can set text parameter
9
+ rr.text = '"test text"'
10
+ assert_equal '@ IN TXT "test text"', rr.dump
11
+
12
+ # with a label set
13
+ rr.label = 'labelname'
14
+ assert_equal 'labelname IN TXT "test text"', rr.dump
15
+
16
+ # with a ttl
17
+ rr.ttl = '2w'
18
+ assert_equal 'labelname 2w IN TXT "test text"', rr.dump
19
+ end
20
+
21
+ def test_load_rr__txt
22
+ rr = DNS::Zone::RR::TXT.new.load('txtrecord IN TXT "test text"')
23
+ assert_equal 'txtrecord', rr.label
24
+ assert_equal 'IN', rr.klass
25
+ assert_equal 'TXT', rr.type
26
+ assert_equal '"test text"', rr.text
27
+ end
28
+
29
+ def test_load_multiple_quoted_strings
30
+ rr = DNS::Zone::RR::TXT.new.load('txtrecord IN TXT "part1 yo" " part2 yo"')
31
+ assert_equal '"part1 yo" " part2 yo"', rr.text
32
+ end
33
+
34
+ def test_load_string_with_quotes
35
+ rr = DNS::Zone::RR::TXT.new.load('txtrecord IN TXT "we have \"double\" quotes"')
36
+ assert_equal %q{"we have \"double\" quotes"}, rr.text
37
+ end
38
+
39
+ def test_load_multiple_strings_with_quotes
40
+ rr = DNS::Zone::RR::TXT.new.load('txtrecord IN TXT "part1 " "we have \"double\" quotes" " part3"')
41
+ assert_equal %q{"part1 " "we have \"double\" quotes" " part3"}, rr.text
42
+ end
43
+
44
+ end
@@ -0,0 +1,50 @@
1
+ require 'dns/zone/test_case'
2
+
3
+ class RRTest < DNS::Zone::TestCase
4
+
5
+ def test_load_ignores_comments
6
+ rr = DNS::Zone::RR.load('; comment lines are ignored')
7
+ assert_nil rr, 'should be nil when its a comment line'
8
+ end
9
+
10
+ def test_load_ignores_unparsable_input
11
+ rr = DNS::Zone::RR.load('invalid input should not be parsed')
12
+ assert_nil rr, 'should be nil when input cant be parsed at all'
13
+ end
14
+
15
+ def test_load_a_rr
16
+ rr = DNS::Zone::RR.load('www IN A 10.2.3.1')
17
+ assert_instance_of DNS::Zone::RR::A, rr, 'should be instance of A RR'
18
+ assert_equal 'www', rr.label
19
+ assert_equal 'A', rr.type
20
+ assert_equal '10.2.3.1', rr.address
21
+ end
22
+
23
+ def test_load_txt_rr
24
+ rr = DNS::Zone::RR.load('mytxt IN TXT "test text"')
25
+ assert_instance_of DNS::Zone::RR::TXT, rr, 'should be instance of TXT RR'
26
+ assert_equal 'mytxt', rr.label
27
+ assert_equal 'TXT', rr.type
28
+ assert_equal '"test text"', rr.text
29
+ end
30
+
31
+ def test_load_txt_semicolon_rr
32
+ rr = DNS::Zone::RR.load('_domainkey IN TXT "t=y; o=~;"')
33
+ assert_instance_of DNS::Zone::RR::TXT, rr, 'should be instance of TXT RR'
34
+ assert_equal '_domainkey', rr.label
35
+ assert_equal 'TXT', rr.type
36
+ assert_equal '"t=y; o=~;"', rr.text
37
+ end
38
+
39
+ def test_load_a_rr_with_options_hash
40
+ rr = DNS::Zone::RR.load(' IN A 10.2.3.1', { last_label: 'www' })
41
+ assert_equal 'www', rr.label
42
+
43
+ rr = DNS::Zone::RR.load('blog IN A 10.2.3.1', { last_label: 'www' })
44
+ assert_equal 'blog', rr.label
45
+
46
+ rr = DNS::Zone::RR.load('@ IN A 10.2.3.1', { last_label: 'mail' })
47
+ assert_equal '@', rr.label
48
+ end
49
+
50
+ end
@@ -0,0 +1,9 @@
1
+ require 'dns/zone/test_case'
2
+
3
+ class VersionTest < DNS::Zone::TestCase
4
+
5
+ def test_should_have_a_version
6
+ assert DNS::Zone::Version, 'unable to access the version number'
7
+ end
8
+
9
+ end
@@ -0,0 +1,273 @@
1
+ require 'dns/zone/test_case'
2
+
3
+ class ZoneTest < DNS::Zone::TestCase
4
+
5
+ # example zone file, with a couple of things that could trip us up.
6
+ ZONE_FILE_EXAMPLE =<<-EOL
7
+ $ORIGIN lividpenguin.com.
8
+ $TTL 3d
9
+ @ IN SOA ns0.lividpenguin.com. luke.lividpenguin.com. (
10
+ 2013101406 ; zone serial number
11
+ 12h ; refresh ttl
12
+ 15m ; retry ttl
13
+ 3w ; expiry ttl
14
+ 3h ; minimum ttl
15
+ )
16
+
17
+ ; a more difficult ; comment ( that is trying to break things!
18
+
19
+ @ IN NS ns0.lividpenguin.com.
20
+ @ IN NS ns1.lividpenguin.com.
21
+ @ IN NS ns2.lividpenguin.com.
22
+
23
+ @ IN MX 10 mx0.lividpenguin.com.
24
+ @ IN MX 20 mx1.lividpenguin.com.
25
+
26
+ @ IN A 78.47.253.85
27
+ ns0 IN A 78.47.253.85
28
+ ns0 IN HINFO "Intel" "Ubuntu"
29
+
30
+ ns0 IN AAAA 2a01:4f8:d12:5ca::2
31
+
32
+ foo IN TXT "part1" "part2"
33
+ bar IN TXT ("part1 "
34
+ "part2 "
35
+ "part3")
36
+ _domainkey IN TXT "t=y; o=~;"
37
+
38
+ longttl 5d IN A 10.1.2.3
39
+
40
+ cake IN CNAME the.cake.is.a.lie.com.
41
+ xmpp IN SRV 5 0 5269 xmpp-server.google.com.
42
+ @ IN SPF "v=spf1 +mx -all"
43
+
44
+ ; a record to be expanded
45
+ @ IN NS ns3
46
+
47
+ ; a record that uses tab spaces
48
+ tabed IN A 10.1.2.3
49
+
50
+ EOL
51
+
52
+ # basic zone file example
53
+ ZONE_FILE_BASIC_EXAMPLE =<<-EOL
54
+ @ IN SOA ns0.lividpenguin.com. luke.lividpenguin.com. ( 2013101406 12h 15m 3w 3h )
55
+ @ IN NS ns0.lividpenguin.com.
56
+ @ IN MX 10 mail
57
+ @ IN MX 99 mx.fakemx.net.
58
+ @ IN A 78.47.253.85
59
+ mail IN A 78.47.253.85
60
+ foo IN TXT "part1" "part2"
61
+ EOL
62
+
63
+ # zone file with multiple zones
64
+ ZONE_FILE_MULTIPLE_ORIGINS_EXAMPLE =<<-EOL
65
+ $ORIGIN lividpenguin.com.
66
+ $TTL 3d
67
+ @ IN SOA ns0.lividpenguin.com. luke.lividpenguin.com. (
68
+ 2013101406 ; zone serial number
69
+ 12h ; refresh ttl
70
+ 15m ; retry ttl
71
+ 3w ; expiry ttl
72
+ 3h ; minimum ttl
73
+ )
74
+
75
+ @ IN NS ns0.lividpenguin.com.
76
+ @ IN NS ns1.lividpenguin.com.
77
+ @ IN NS ns2.lividpenguin.com.
78
+
79
+ @ IN A 78.47.253.85
80
+ www IN A 78.47.253.85
81
+
82
+ foo IN TXT "part1" "part2"
83
+
84
+ $ORIGIN sub.lividpenguin.com.
85
+ app1 60 A 1.2.3.4
86
+ app2 60 A 1.2.3.5
87
+ app3 60 A 1.2.3.6
88
+ $ORIGIN another.lividpenguin.com.
89
+ @ 3600 A 1.1.1.1
90
+ app1 60 A 4.3.2.1
91
+
92
+ EOL
93
+
94
+ def test_create_new_instance
95
+ assert DNS::Zone.new
96
+ end
97
+
98
+ def test_programmatic_readme_example
99
+ zone = DNS::Zone.new
100
+ zone.origin = 'example.com.'
101
+ zone.ttl = '1d'
102
+ # quick access to SOA RR
103
+ zone.soa.nameserver = 'ns0.lividpenguin.com.'
104
+ zone.soa.email = 'hostmaster.lividpenguin.com.'
105
+ # create and add new record
106
+ rec = DNS::Zone::RR::A.new
107
+ rec.address = '127.0.0.1'
108
+ zone.records << rec
109
+
110
+ assert_equal 2, zone.records.length, "were expecting 2 records, including the SOA"
111
+ end
112
+
113
+ def test_load_zone_basic
114
+ # load zone file.
115
+ zone = DNS::Zone.load(ZONE_FILE_BASIC_EXAMPLE)
116
+ # dump zone file.
117
+ dump = zone.dump
118
+ # check input matches output.
119
+ assert_equal ZONE_FILE_BASIC_EXAMPLE, dump, 'loaded zone file should match dumped zone file'
120
+ end
121
+
122
+ def test_load_zone_with_origin_param
123
+ # --- zone without $ORIGIN directive
124
+
125
+ zone = DNS::Zone.load(ZONE_FILE_BASIC_EXAMPLE, 'lividpenguin.com.')
126
+ dump = zone.dump
127
+ assert_equal ZONE_FILE_BASIC_EXAMPLE, dump, 'loaded zone file should match dumped zone file'
128
+ assert_equal 'lividpenguin.com.', zone.origin, 'check origin matches example input'
129
+
130
+ # --- zone with $ORIGIN directive
131
+
132
+ zone = DNS::Zone.load(ZONE_FILE_EXAMPLE, 'ignore.this.origin.favor.zone.com.')
133
+ assert_equal 'lividpenguin.com.', zone.origin, 'origin should come from test zone, not passed param'
134
+ end
135
+
136
+ def test_load_zone_labels_are_correct
137
+ zone = DNS::Zone.load(ZONE_FILE_BASIC_EXAMPLE, 'lividpenguin.com.')
138
+ assert_equal 'mail', zone.records[5].label, 'check label is correct'
139
+
140
+ zone = DNS::Zone.load(ZONE_FILE_EXAMPLE)
141
+ assert_equal 'ns0', zone.records[7].label, 'check label is correct'
142
+ end
143
+
144
+ def test_load_zone
145
+ # load example dns master zone file.
146
+ zone = DNS::Zone.load(ZONE_FILE_EXAMPLE)
147
+
148
+ # test attributes are correct.
149
+ assert_equal '3d', zone.ttl, 'check ttl matches example input'
150
+ assert_equal 'lividpenguin.com.', zone.origin, 'check origin matches example input'
151
+ assert_equal 19, zone.records.length, 'we should have multiple records (including SOA)'
152
+
153
+ #p ''
154
+ #zone.records.each do |rec|
155
+ # p rec
156
+ #end
157
+ end
158
+
159
+ def test_load_zone_with_empty_labels
160
+ # basic zone file that uses empty labels (ie. use previous)
161
+ zone_as_string =<<-EOL
162
+ @ IN A 78.47.253.85
163
+ IN AAAA 2a01:4f8:d12:5ca::2
164
+ www IN A 78.47.253.85
165
+ IN AAAA 2a01:4f8:d12:5ca::2
166
+ EOL
167
+
168
+ # load zone file.
169
+ zone = DNS::Zone.load(zone_as_string)
170
+
171
+ # test labels are 'inherited' from last used.
172
+ assert_equal '@', zone.records[0].label
173
+ assert_equal '@', zone.records[1].label, 'label should be inherited from last label used'
174
+ assert_equal 'www', zone.records[2].label
175
+ assert_equal 'www', zone.records[3].label, 'label should be inherited from last label used'
176
+ end
177
+
178
+ def test_load_zone_that_uses_tabs_rather_then_spaces
179
+ zone_as_string =<<-EOL
180
+ * IN A 78.47.253.85
181
+ EOL
182
+
183
+ # load zone file.
184
+ zone = DNS::Zone.load(zone_as_string)
185
+
186
+ record = zone.records[0]
187
+ assert_equal '*', record.label
188
+ assert_equal 'A', record.type
189
+ assert_equal '78.47.253.85', record.address
190
+ end
191
+
192
+ def test_load_multiple_origins
193
+ zone = DNS::Zone.load(ZONE_FILE_MULTIPLE_ORIGINS_EXAMPLE)
194
+ assert_equal 'lividpenguin.com.', zone.origin
195
+ assert_equal 12, zone.records.length, 'we should have multiple records (including SOA)'
196
+ assert_equal 'app1.sub', zone.records[7].label
197
+ assert_equal '1.2.3.4', zone.records[7].address
198
+ assert_equal 'another', zone.records[10].label
199
+ assert_equal '1.1.1.1', zone.records[10].address
200
+ assert_equal 'app1.another', zone.records[11].label
201
+ assert_equal '4.3.2.1', zone.records[11].address
202
+ end
203
+
204
+ def test_extract_entry_from_one_line
205
+ entries = DNS::Zone.extract_entries(%Q{maiow IN TXT "purr"})
206
+ assert_equal 1, entries.length, 'we should have 1 entry'
207
+ assert_equal 'maiow IN TXT "purr"', entries[0], 'entry should match expected'
208
+ end
209
+
210
+ def test_extract_entry_including_semicolon_within_quotes
211
+ entries = DNS::Zone.extract_entries(%Q{_domainkey IN TXT "t=y; o=~;"})
212
+ assert_equal 1, entries.length, 'we should have 1 entry'
213
+ assert_equal '_domainkey IN TXT "t=y; o=~;"', entries[0], 'entry should match expected'
214
+ end
215
+
216
+ def test_extract_entry_should_ignore_comments
217
+ entries = DNS::Zone.extract_entries(%Q{maiow IN TXT "purr"; this is a comment})
218
+ assert_equal 1, entries.length, 'we should have 1 entry'
219
+ assert_equal 'maiow IN TXT "purr"', entries[0], 'entry should match expected'
220
+ end
221
+
222
+ def test_extract_entry_should_ignore_empty_lines
223
+ entries = DNS::Zone.extract_entries(%Q{\n\nmaiow IN TXT "purr";\n\n})
224
+ assert_equal 1, entries.length, 'we should have 1 entry'
225
+ assert_equal 'maiow IN TXT "purr"', entries[0], 'entry should match expected'
226
+ end
227
+
228
+ def test_extract_entry_using_parentheses_but_not_crossing_line_boundary
229
+ entries = DNS::Zone.extract_entries(%Q{maiow IN TXT ("part1" "part2")})
230
+ assert_equal 1, entries.length, 'we should have 1 entry'
231
+ assert_equal 'maiow IN TXT "part1" "part2"', entries[0], 'entry should match expected'
232
+ end
233
+
234
+ def test_extract_entry_crossing_line_boundary
235
+ entries = DNS::Zone.extract_entries(%Q{maiow1 IN TXT ("part1"\n "part2" )})
236
+ assert_equal 1, entries.length, 'we should have 1 entry'
237
+ assert_equal 'maiow1 IN TXT "part1" "part2"', entries[0], 'entry should match expected'
238
+ end
239
+
240
+ def test_extract_entry_soa_crossing_line_boundary
241
+ entries = DNS::Zone.extract_entries(%Q{
242
+ @ IN SOA ns0.lividpenguin.com. luke.lividpenguin.com. (
243
+ 2013101406 ; zone serial number
244
+ 12h ; refresh ttl
245
+ 15m ; retry ttl
246
+ 3w ; expiry ttl
247
+ 3h ; minimum ttl
248
+ )})
249
+ assert_equal 1, entries.length, 'we should have 1 entry'
250
+
251
+ expected_soa = '@ IN SOA ns0.lividpenguin.com. luke.lividpenguin.com. 2013101406 12h 15m 3w 3h'
252
+ assert_equal expected_soa, entries[0], 'entry should match expected'
253
+ end
254
+
255
+ def test_extract_entries_with_parentheses_crossing_multiple_line_boundaries
256
+ entries = DNS::Zone.extract_entries(%Q{maiow1 IN TXT (\n"part1"\n "part2"\n)})
257
+ assert_equal 1, entries.length, 'we should have 1 entry'
258
+ assert_equal 'maiow1 IN TXT "part1" "part2"', entries[0], 'entry should match expected'
259
+ end
260
+
261
+ def test_extract_entries_with_legal_but_crazy_parentheses_used
262
+ entries = DNS::Zone.extract_entries(%Q{maiow IN TXT (\n(\n("part1")\n \n("part2" \n("part3"\n)\n)\n)\n)})
263
+ assert_equal 1, entries.length, 'we should have 1 entry'
264
+ assert_equal 'maiow IN TXT "part1" "part2" "part3"', entries[0], 'entry should match expected'
265
+ end
266
+
267
+ def test_extract_entry_with_parentheses_in_character_string
268
+ entries = DNS::Zone.extract_entries(%Q{maiow IN TXT ("purr((maiow)")})
269
+ assert_equal 1, entries.length, 'we should have 1 entry'
270
+ assert_equal 'maiow IN TXT "purr((maiow)"', entries[0], 'entry should match expected'
271
+ end
272
+
273
+ end