coppertone 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +34 -0
  3. data/.travis.yml +7 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE +201 -0
  6. data/README.md +58 -0
  7. data/Rakefile +140 -0
  8. data/coppertone.gemspec +27 -0
  9. data/lib/coppertone/class_builder.rb +20 -0
  10. data/lib/coppertone/directive.rb +38 -0
  11. data/lib/coppertone/dns/error.rb +9 -0
  12. data/lib/coppertone/dns/mock_client.rb +106 -0
  13. data/lib/coppertone/dns/resolv_client.rb +110 -0
  14. data/lib/coppertone/dns.rb +3 -0
  15. data/lib/coppertone/domain_spec.rb +45 -0
  16. data/lib/coppertone/error.rb +29 -0
  17. data/lib/coppertone/ip_address_wrapper.rb +75 -0
  18. data/lib/coppertone/macro_context.rb +67 -0
  19. data/lib/coppertone/macro_string/macro_expand.rb +84 -0
  20. data/lib/coppertone/macro_string/macro_literal.rb +24 -0
  21. data/lib/coppertone/macro_string/macro_parser.rb +62 -0
  22. data/lib/coppertone/macro_string/macro_static_expand.rb +52 -0
  23. data/lib/coppertone/macro_string.rb +31 -0
  24. data/lib/coppertone/mechanism/a.rb +16 -0
  25. data/lib/coppertone/mechanism/all.rb +24 -0
  26. data/lib/coppertone/mechanism/cidr_parser.rb +14 -0
  27. data/lib/coppertone/mechanism/domain_spec_mechanism.rb +18 -0
  28. data/lib/coppertone/mechanism/domain_spec_optional.rb +46 -0
  29. data/lib/coppertone/mechanism/domain_spec_required.rb +37 -0
  30. data/lib/coppertone/mechanism/domain_spec_with_dual_cidr.rb +114 -0
  31. data/lib/coppertone/mechanism/exists.rb +14 -0
  32. data/lib/coppertone/mechanism/include.rb +18 -0
  33. data/lib/coppertone/mechanism/include_matcher.rb +34 -0
  34. data/lib/coppertone/mechanism/ip4.rb +13 -0
  35. data/lib/coppertone/mechanism/ip6.rb +13 -0
  36. data/lib/coppertone/mechanism/ip_mechanism.rb +48 -0
  37. data/lib/coppertone/mechanism/mx.rb +40 -0
  38. data/lib/coppertone/mechanism/ptr.rb +17 -0
  39. data/lib/coppertone/mechanism.rb +32 -0
  40. data/lib/coppertone/modifier/base.rb +24 -0
  41. data/lib/coppertone/modifier/exp.rb +34 -0
  42. data/lib/coppertone/modifier/redirect.rb +17 -0
  43. data/lib/coppertone/modifier/unknown.rb +16 -0
  44. data/lib/coppertone/modifier.rb +30 -0
  45. data/lib/coppertone/qualifier.rb +45 -0
  46. data/lib/coppertone/record.rb +86 -0
  47. data/lib/coppertone/record_evaluator.rb +63 -0
  48. data/lib/coppertone/record_finder.rb +34 -0
  49. data/lib/coppertone/request.rb +68 -0
  50. data/lib/coppertone/request_context.rb +67 -0
  51. data/lib/coppertone/request_count_limiter.rb +36 -0
  52. data/lib/coppertone/result.rb +50 -0
  53. data/lib/coppertone/sender_identity.rb +39 -0
  54. data/lib/coppertone/spf_service.rb +9 -0
  55. data/lib/coppertone/term.rb +13 -0
  56. data/lib/coppertone/utils/domain_utils.rb +59 -0
  57. data/lib/coppertone/utils/host_utils.rb +22 -0
  58. data/lib/coppertone/utils/ip_in_domain_checker.rb +53 -0
  59. data/lib/coppertone/utils/validated_domain_finder.rb +40 -0
  60. data/lib/coppertone/utils.rb +4 -0
  61. data/lib/coppertone/version.rb +3 -0
  62. data/lib/coppertone.rb +48 -0
  63. data/lib/resolv/dns/resource/in/spf.rb +15 -0
  64. data/spec/directive_spec.rb +41 -0
  65. data/spec/dns/resolv_client_spec.rb +307 -0
  66. data/spec/domain_spec_spec.rb +35 -0
  67. data/spec/ip_address_wrapper_spec.rb +67 -0
  68. data/spec/macro_context_spec.rb +69 -0
  69. data/spec/macro_string/macro_expand_spec.rb +79 -0
  70. data/spec/macro_string/macro_literal_spec.rb +27 -0
  71. data/spec/macro_string/macro_static_expand_spec.rb +67 -0
  72. data/spec/macro_string_spec.rb +20 -0
  73. data/spec/mechanism/a_spec.rb +198 -0
  74. data/spec/mechanism/all_spec.rb +22 -0
  75. data/spec/mechanism/exists_spec.rb +91 -0
  76. data/spec/mechanism/include_spec.rb +43 -0
  77. data/spec/mechanism/ip4_spec.rb +110 -0
  78. data/spec/mechanism/ip6_spec.rb +104 -0
  79. data/spec/mechanism/mx_spec.rb +51 -0
  80. data/spec/mechanism/ptr_spec.rb +43 -0
  81. data/spec/mechanism_spec.rb +4 -0
  82. data/spec/modifier_spec.rb +4 -0
  83. data/spec/open_spf/ALL_mechanism_syntax_spec.rb +38 -0
  84. data/spec/open_spf/A_mechanism_syntax_spec.rb +159 -0
  85. data/spec/open_spf/EXISTS_mechanism_syntax_spec.rb +46 -0
  86. data/spec/open_spf/IP4_mechanism_syntax_spec.rb +59 -0
  87. data/spec/open_spf/IP6_mechanism_syntax_spec.rb +60 -0
  88. data/spec/open_spf/Include_mechanism_semantics_and_syntax_spec.rb +56 -0
  89. data/spec/open_spf/Initial_processing_spec.rb +77 -0
  90. data/spec/open_spf/MX_mechanism_syntax_spec.rb +119 -0
  91. data/spec/open_spf/Macro_expansion_rules_spec.rb +154 -0
  92. data/spec/open_spf/PTR_mechanism_syntax_spec.rb +42 -0
  93. data/spec/open_spf/Processing_limits_spec.rb +72 -0
  94. data/spec/open_spf/Record_evaluation_spec.rb +75 -0
  95. data/spec/open_spf/Record_lookup_spec.rb +48 -0
  96. data/spec/open_spf/Selecting_records_spec.rb +61 -0
  97. data/spec/open_spf/Semantics_of_exp_and_other_modifiers_spec.rb +167 -0
  98. data/spec/open_spf/Test_cases_from_implementation_bugs_spec.rb +17 -0
  99. data/spec/qualifier_spec.rb +54 -0
  100. data/spec/record_evaluator_spec.rb +4 -0
  101. data/spec/record_finder_spec.rb +4 -0
  102. data/spec/record_spec.rb +100 -0
  103. data/spec/request_context_spec.rb +43 -0
  104. data/spec/request_count_limiter_spec.rb +28 -0
  105. data/spec/result_spec.rb +4 -0
  106. data/spec/rfc7208-tests.yml +2548 -0
  107. data/spec/sender_identity_spec.rb +69 -0
  108. data/spec/spec_helper.rb +8 -0
  109. data/spec/term_spec.rb +38 -0
  110. data/spec/utils/domain_utils_spec.rb +60 -0
  111. data/spec/utils/host_utils_spec.rb +32 -0
  112. data/spec/utils/ip_in_domain_checker_spec.rb +4 -0
  113. data/spec/utils/validated_domain_finder_spec.rb +4 -0
  114. metadata +306 -0
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coppertone::MacroString::MacroLiteral do
4
+ let(:arg) { SecureRandom.hex(10) }
5
+ let(:macro) { Coppertone::MacroString::MacroLiteral.new(arg) }
6
+
7
+ it 'should expand to the argument' do
8
+ expect(macro.expand(double)).to eq(arg)
9
+ end
10
+
11
+ it 'should reduce to the argument in the macro form' do
12
+ expect(macro.to_s).to eq(arg)
13
+ end
14
+
15
+ context 'equality' do
16
+ it 'should treat different MacroLiterals with the same value as equal' do
17
+ expect(macro == Coppertone::MacroString::MacroLiteral.new(arg))
18
+ .to eql(true)
19
+ end
20
+
21
+ it 'otherwise should treat different MacroLiterals as unequal' do
22
+ other_arg = SecureRandom.hex(10)
23
+ expect(macro == Coppertone::MacroString::MacroLiteral.new(other_arg))
24
+ .to eql(false)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coppertone::MacroString::MacroStaticExpand do
4
+ context '#exists_for?' do
5
+ %w(%% %_ %-).each do |x|
6
+ it "should resolve a macro for the key #{x}" do
7
+ expect(Coppertone::MacroString::MacroStaticExpand.exists_for?(x))
8
+ .to eq(true)
9
+ end
10
+ end
11
+
12
+ it 'should return false for invalid keys' do
13
+ expect(Coppertone::MacroString::MacroStaticExpand.exists_for?('%a'))
14
+ .to eq(false)
15
+ end
16
+ end
17
+
18
+ context 'macro_for' do
19
+ %w(%% %_ %-).each do |x|
20
+ it "should resolve a macro for the key #{x}" do
21
+ expect(Coppertone::MacroString::MacroStaticExpand.macro_for(x))
22
+ .not_to be_nil
23
+ end
24
+ end
25
+
26
+ it 'should raise an error for invalid keys' do
27
+ expect do
28
+ Coppertone::MacroString::MacroStaticExpand.macro_for('%a')
29
+ end.to raise_error(Coppertone::MacroStringParsingError)
30
+ end
31
+ end
32
+
33
+ it 'should not allow creation of new macros' do
34
+ expect do
35
+ Coppertone::MacroString::MacroStaticExpand.new('a', 'b')
36
+ end.to raise_error(NoMethodError)
37
+ end
38
+
39
+ context 'percent macro' do
40
+ let(:macro) { Coppertone::MacroString::MacroStaticExpand::PERCENT_MACRO }
41
+
42
+ it 'should return the expected values' do
43
+ expect(macro.expand(nil)).to eq('%')
44
+ expect(macro.to_s).to eq('%%')
45
+ end
46
+ end
47
+
48
+ context 'space macro' do
49
+ let(:macro) { Coppertone::MacroString::MacroStaticExpand::SPACE_MACRO }
50
+
51
+ it 'should return the expected values' do
52
+ expect(macro.expand(nil)).to eq(' ')
53
+ expect(macro.to_s).to eq('%_')
54
+ end
55
+ end
56
+
57
+ context 'url encoded space macro' do
58
+ let(:macro) do
59
+ Coppertone::MacroString::MacroStaticExpand::URL_ENCODED_SPACE_MACRO
60
+ end
61
+
62
+ it 'should return the expected values' do
63
+ expect(macro.expand(nil)).to eq('%20')
64
+ expect(macro.to_s).to eq('%-')
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coppertone::MacroString do
4
+ context 'equality' do
5
+ it 'should treat different MacroStrings with the same value as equal' do
6
+ arg = 'abc.%{dr-}.%%.test.com'
7
+ macro_string = Coppertone::MacroString.new(arg)
8
+ expect(macro_string == Coppertone::MacroString.new(arg))
9
+ .to eql(true)
10
+ end
11
+
12
+ it 'should otherwise treat different MacroStrings as unequal' do
13
+ arg = 'abc.%{dr-}.%%.test.com'
14
+ macro_string = Coppertone::MacroString.new(arg)
15
+ other_arg = 'eabc.%{dr-}.%%.test.com'
16
+ expect(macro_string == Coppertone::MacroString.new(other_arg))
17
+ .to eql(false)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,198 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coppertone::Mechanism::A do
4
+ context '#new' do
5
+ it 'should not fail if called with a nil argument' do
6
+ mech = Coppertone::Mechanism::A.new(nil)
7
+ expect(mech).not_to be_nil
8
+ expect(mech.domain_spec).to be_nil
9
+ expect(mech.ip_v4_cidr_length).to eq(32)
10
+ expect(mech.ip_v6_cidr_length).to eq(128)
11
+ end
12
+
13
+ it 'should not fail if called with a blank argument' do
14
+ mech = Coppertone::Mechanism::A.new('')
15
+ expect(mech).not_to be_nil
16
+ expect(mech.domain_spec).to be_nil
17
+ expect(mech.ip_v4_cidr_length).to eq(32)
18
+ expect(mech.ip_v6_cidr_length).to eq(128)
19
+ end
20
+
21
+ it 'should fail if called with an invalid macrostring' do
22
+ expect do
23
+ Coppertone::Mechanism::A.new(':abc%:def')
24
+ end.to raise_error(Coppertone::InvalidMechanismError)
25
+ end
26
+
27
+ it 'should parse a domain spec' do
28
+ mech = Coppertone::Mechanism::A.new(':_spf.%{d}.example.com')
29
+ expect(mech).not_to be_nil
30
+ expect(mech.domain_spec)
31
+ .to eq(Coppertone::DomainSpec.new('_spf.%{d}.example.com'))
32
+ expect(mech.ip_v4_cidr_length).to eq(32)
33
+ expect(mech.ip_v6_cidr_length).to eq(128)
34
+ end
35
+
36
+ it 'should parse a valid IP v4 CIDR length with a domain spec' do
37
+ mech = Coppertone::Mechanism::A.new(':_spf.%{d}.example.com/28')
38
+ expect(mech).not_to be_nil
39
+ expect(mech.domain_spec)
40
+ .to eq(Coppertone::DomainSpec.new('_spf.%{d}.example.com'))
41
+ expect(mech.ip_v4_cidr_length).to eq('28')
42
+ expect(mech.ip_v6_cidr_length).to eq(128)
43
+ end
44
+
45
+ it 'should fail if called with an invalid macrostring and IPv4 CIDR' do
46
+ expect do
47
+ Coppertone::Mechanism::A.new(':abc%:def/28')
48
+ end.to raise_error(Coppertone::InvalidMechanismError)
49
+ end
50
+
51
+ it 'should parse a valid IP v4 CIDR length' do
52
+ mech = Coppertone::Mechanism::A.new('/28')
53
+ expect(mech).not_to be_nil
54
+ expect(mech.domain_spec).to be_nil
55
+ expect(mech.ip_v4_cidr_length).to eq('28')
56
+ expect(mech.ip_v6_cidr_length).to eq(128)
57
+ end
58
+
59
+ it 'should not parse an invalid IP v4 CIDR length' do
60
+ expect do
61
+ Coppertone::Mechanism::A.new('/36')
62
+ end.to raise_error(Coppertone::InvalidMechanismError)
63
+
64
+ expect do
65
+ Coppertone::Mechanism::A.new('/a')
66
+ end.to raise_error(Coppertone::InvalidMechanismError)
67
+ end
68
+
69
+ it 'should parse a valid IP v6 CIDR length with a domain spec' do
70
+ mech = Coppertone::Mechanism::A.new(':_spf.%{d}.example.com//64')
71
+ expect(mech).not_to be_nil
72
+ expect(mech.domain_spec)
73
+ .to eq(Coppertone::DomainSpec.new('_spf.%{d}.example.com'))
74
+ expect(mech.ip_v4_cidr_length).to eq(32)
75
+ expect(mech.ip_v6_cidr_length).to eq('64')
76
+ end
77
+
78
+ it 'should fail if called with an invalid macrostring and IPv6 CIDR' do
79
+ expect do
80
+ Coppertone::Mechanism::A.new(':abc%:def//64')
81
+ end.to raise_error(Coppertone::InvalidMechanismError)
82
+ end
83
+
84
+ it 'should parse a valid IP v6 CIDR length' do
85
+ mech = Coppertone::Mechanism::A.new('//64')
86
+ expect(mech).not_to be_nil
87
+ expect(mech.domain_spec).to be_nil
88
+ expect(mech.ip_v4_cidr_length).to eq(32)
89
+ expect(mech.ip_v6_cidr_length).to eq('64')
90
+ end
91
+
92
+ it 'should not parse an invalid IP v6 CIDR length' do
93
+ expect do
94
+ Coppertone::Mechanism::A.new('//133')
95
+ end.to raise_error(Coppertone::InvalidMechanismError)
96
+
97
+ expect do
98
+ Coppertone::Mechanism::A.new('//a')
99
+ end.to raise_error(Coppertone::InvalidMechanismError)
100
+ end
101
+
102
+ it 'should parse a valid dual CIDR length with a domain spec' do
103
+ mech = Coppertone::Mechanism::A.new(':_spf.%{d}.example.com/28//64')
104
+ expect(mech).not_to be_nil
105
+ expect(mech.domain_spec)
106
+ .to eq(Coppertone::DomainSpec.new('_spf.%{d}.example.com'))
107
+ expect(mech.ip_v4_cidr_length).to eq('28')
108
+ expect(mech.ip_v6_cidr_length).to eq('64')
109
+ end
110
+
111
+ it 'should not parse a invalid dual CIDR length with a domain spec' do
112
+ expect do
113
+ Coppertone::Mechanism::A.new('_spf.%{d}.example.com/28//133')
114
+ end.to raise_error(Coppertone::InvalidMechanismError)
115
+ expect do
116
+ Coppertone::Mechanism::A.new('_spf.%{d}.example.com/44//64')
117
+ end.to raise_error(Coppertone::InvalidMechanismError)
118
+ end
119
+
120
+ it 'should fail if called with an invalid macrostring and dual CIDR' do
121
+ expect do
122
+ Coppertone::Mechanism::A.new('abc%:def/28//64')
123
+ end.to raise_error(Coppertone::InvalidMechanismError)
124
+ end
125
+ end
126
+
127
+ context '#create' do
128
+ it 'should fail if called with a nil argument' do
129
+ mech = Coppertone::Mechanism::A.create(nil)
130
+ expect(mech).not_to be_nil
131
+ expect(mech.domain_spec).to be_nil
132
+ expect(mech.ip_v4_cidr_length).to eq(32)
133
+ expect(mech.ip_v6_cidr_length).to eq(128)
134
+ end
135
+
136
+ it 'should fail if called with a blank argument' do
137
+ mech = Coppertone::Mechanism::A.create('')
138
+ expect(mech).not_to be_nil
139
+ expect(mech.domain_spec).to be_nil
140
+ expect(mech.ip_v4_cidr_length).to eq(32)
141
+ expect(mech.ip_v6_cidr_length).to eq(128)
142
+ end
143
+
144
+ it 'should fail if called with an argument invalid macrostring' do
145
+ expect do
146
+ Coppertone::Mechanism::A.create('abc%:def')
147
+ end.to raise_error(Coppertone::InvalidMechanismError)
148
+ end
149
+ end
150
+
151
+ context '#match?' do
152
+ context 'simple' do
153
+ let(:mech_domain) { 'gmail.com' }
154
+ let(:mech_arg) { ":#{mech_domain}" }
155
+ let(:gmail_dns_client) do
156
+ dc = double(:dns_client)
157
+ allow(dc).to receive(:fetch_a_records)
158
+ .with(mech_domain).and_return([
159
+ {
160
+ type: 'A',
161
+ address: '74.125.239.117'
162
+ },
163
+ {
164
+ type: 'A',
165
+ address: '74.125.239.118'
166
+ }
167
+ ])
168
+ dc
169
+ end
170
+
171
+ let(:domain) { 'yahoo.com' }
172
+ let(:matching_context) do
173
+ Coppertone::MacroContext.new(domain, '74.125.239.118', 'bob@gmail.com')
174
+ end
175
+
176
+ let(:not_matching_context) do
177
+ Coppertone::MacroContext.new(domain, '74.125.249.118', 'bob@gmail.com')
178
+ end
179
+
180
+ before do
181
+ allow(Coppertone::DNS::ResolvClient)
182
+ .to receive(:new).and_return(gmail_dns_client)
183
+ end
184
+
185
+ it 'should match when the IP matches the record' do
186
+ mech = Coppertone::Mechanism::A.create(mech_arg)
187
+ expect(mech.match?(matching_context, Coppertone::RequestContext.new))
188
+ .to eq(true)
189
+ end
190
+
191
+ it 'should not match when the IP does not match the record' do
192
+ mech = Coppertone::Mechanism::A.create(mech_arg)
193
+ expect(mech.match?(not_matching_context, Coppertone::RequestContext.new))
194
+ .to eq(false)
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coppertone::Mechanism::All do
4
+ subject { Coppertone::Mechanism::All.instance }
5
+ it 'should always return true regardless of argument' do
6
+ expect(subject.match?(double, double)).to eq(true)
7
+ end
8
+
9
+ it 'should not allow creation of new instances' do
10
+ expect do
11
+ Coppertone::Mechanism::All.new('')
12
+ end.to raise_error(NoMethodError)
13
+ end
14
+
15
+ context '#create' do
16
+ it 'should fail if any arguments are passed that are not blank' do
17
+ expect do
18
+ Coppertone::Mechanism::All.create('abcd')
19
+ end.to raise_error(Coppertone::RecordParsingError)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coppertone::Mechanism::Exists do
4
+ context '#new' do
5
+ it 'should fail if called with a nil argument' do
6
+ expect do
7
+ Coppertone::Mechanism::Exists.new(nil)
8
+ end.to raise_error(Coppertone::InvalidMechanismError)
9
+ end
10
+
11
+ it 'should fail if called with a blank argument' do
12
+ expect do
13
+ Coppertone::Mechanism::Exists.new('')
14
+ end.to raise_error(Coppertone::InvalidMechanismError)
15
+ end
16
+
17
+ it 'should fail if called with an invalid macrostring' do
18
+ expect do
19
+ Coppertone::Mechanism::Exists.new(':abc%:def')
20
+ end.to raise_error(Coppertone::InvalidMechanismError)
21
+ end
22
+ end
23
+
24
+ context '#create' do
25
+ it 'should fail if called with a nil argument' do
26
+ expect do
27
+ Coppertone::Mechanism::Exists.create(nil)
28
+ end.to raise_error(Coppertone::InvalidMechanismError)
29
+ end
30
+
31
+ it 'should fail if called with a blank argument' do
32
+ expect do
33
+ Coppertone::Mechanism::Exists.create('')
34
+ end.to raise_error(Coppertone::InvalidMechanismError)
35
+ end
36
+
37
+ it 'should fail if called with an invalid macrostring' do
38
+ expect do
39
+ Coppertone::Mechanism::Exists.create(':abc%:def')
40
+ end.to raise_error(Coppertone::InvalidMechanismError)
41
+ end
42
+ end
43
+
44
+ context '#match?' do
45
+ context 'simple' do
46
+ let(:mech_domain) { 'iexist.com' }
47
+ let(:mech_arg) { ":#{mech_domain}" }
48
+ let(:bad_domain) { 'idontexist.com' }
49
+ let(:bad_arg) { ":#{bad_domain}" }
50
+ let(:dns_client) do
51
+ dc = double(:dns_client)
52
+ allow(dc).to receive(:fetch_a_records)
53
+ .with(mech_domain).and_return([
54
+ {
55
+ type: 'A',
56
+ address: '74.125.234.117'
57
+ }
58
+ ])
59
+ allow(dc).to receive(:fetch_a_records)
60
+ .with(bad_domain).and_return([])
61
+ dc
62
+ end
63
+
64
+ let(:domain) { 'yahoo.com' }
65
+ let(:matching_context) do
66
+ Coppertone::MacroContext.new(domain, '74.125.239.118', 'bob@gmail.com')
67
+ end
68
+
69
+ let(:not_matching_context) do
70
+ Coppertone::MacroContext.new(domain, '74.125.249.118', 'bob@gmail.com')
71
+ end
72
+
73
+ before do
74
+ allow(Coppertone::DNS::ResolvClient)
75
+ .to receive(:new).and_return(dns_client)
76
+ end
77
+
78
+ it 'should match when the domain record for the target name exists' do
79
+ mech = Coppertone::Mechanism::Exists.create(mech_arg)
80
+ expect(mech.match?(matching_context, Coppertone::RequestContext.new))
81
+ .to eq(true)
82
+ end
83
+
84
+ it 'should match when the domain record for the target name exists' do
85
+ mech = Coppertone::Mechanism::Exists.create(bad_arg)
86
+ expect(mech.match?(matching_context, Coppertone::RequestContext.new))
87
+ .to eq(false)
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coppertone::Mechanism::Include do
4
+ context '#new' do
5
+ it 'should fail if called with a nil argument' do
6
+ expect do
7
+ Coppertone::Mechanism::Include.new(nil)
8
+ end.to raise_error(Coppertone::InvalidMechanismError)
9
+ end
10
+
11
+ it 'should fail if called with a blank argument' do
12
+ expect do
13
+ Coppertone::Mechanism::Include.new('')
14
+ end.to raise_error(Coppertone::InvalidMechanismError)
15
+ end
16
+
17
+ it 'should fail if called with an invalid macrostring' do
18
+ expect do
19
+ Coppertone::Mechanism::Include.new('abc%:def')
20
+ end.to raise_error(Coppertone::InvalidMechanismError)
21
+ end
22
+ end
23
+
24
+ context '#create' do
25
+ it 'should fail if called with a nil argument' do
26
+ expect do
27
+ Coppertone::Mechanism::Include.create(nil)
28
+ end.to raise_error(Coppertone::InvalidMechanismError)
29
+ end
30
+
31
+ it 'should fail if called with a blank argument' do
32
+ expect do
33
+ Coppertone::Mechanism::Include.create('')
34
+ end.to raise_error(Coppertone::InvalidMechanismError)
35
+ end
36
+
37
+ it 'should fail if called with an argument invalid macrostring' do
38
+ expect do
39
+ Coppertone::Mechanism::Include.create('abc%:def')
40
+ end.to raise_error(Coppertone::InvalidMechanismError)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coppertone::Mechanism::IP4 do
4
+ context '#new' do
5
+ it 'should fail if called with a nil argument' do
6
+ expect do
7
+ Coppertone::Mechanism::IP4.new(nil)
8
+ end.to raise_error(Coppertone::InvalidMechanismError)
9
+ end
10
+
11
+ it 'should fail if called with a blank argument' do
12
+ expect do
13
+ Coppertone::Mechanism::IP4.new('')
14
+ end.to raise_error(Coppertone::InvalidMechanismError)
15
+ end
16
+
17
+ it 'should fail if called with an invalid IP' do
18
+ expect do
19
+ Coppertone::Mechanism::IP4.new(':not_an_ip')
20
+ end.to raise_error(Coppertone::InvalidMechanismError)
21
+ end
22
+
23
+ it 'should not fail if called with an IP v6' do
24
+ mech = Coppertone::Mechanism::IP4.new(':fe80::202:b3ff:fe1e:8329')
25
+ expect(mech.ip_network).to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329'))
26
+ end
27
+
28
+ it 'should work if called with an IP4' do
29
+ mech = Coppertone::Mechanism::IP4.new(':1.2.3.4')
30
+ expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4'))
31
+ end
32
+
33
+ it 'should work if called with an IP4 with a pfxlen' do
34
+ mech = Coppertone::Mechanism::IP4.new(':1.2.3.4/4')
35
+ expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4/4'))
36
+ end
37
+ end
38
+
39
+ context '#create' do
40
+ it 'should fail if called with a nil argument' do
41
+ expect do
42
+ Coppertone::Mechanism::IP4.create(nil)
43
+ end.to raise_error(Coppertone::InvalidMechanismError)
44
+ end
45
+
46
+ it 'should fail if called with a blank argument' do
47
+ expect do
48
+ Coppertone::Mechanism::IP4.create('')
49
+ end.to raise_error(Coppertone::InvalidMechanismError)
50
+ end
51
+
52
+ it 'should fail if called with an invalid IP' do
53
+ expect do
54
+ Coppertone::Mechanism::IP4.create(':not_an_ip')
55
+ end.to raise_error(Coppertone::InvalidMechanismError)
56
+ end
57
+
58
+ it 'should not fail if called with an IP v6' do
59
+ mech = Coppertone::Mechanism::IP4.create(':fe80::202:b3ff:fe1e:8329')
60
+ expect(mech.ip_network).to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329'))
61
+ end
62
+
63
+ it 'should work if called with an IP4' do
64
+ mech = Coppertone::Mechanism::IP4.create(':1.2.3.4')
65
+ expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4'))
66
+ end
67
+
68
+ it 'should work if called with an IP4 with a pfxlen' do
69
+ mech = Coppertone::Mechanism::IP4.create('1.2.3.4/4')
70
+ expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4/4'))
71
+ end
72
+
73
+ it 'should fail if called with an invalid pfxlen' do
74
+ expect do
75
+ Coppertone::Mechanism::IP4.new('1.2.3.4/127')
76
+ end.to raise_error(Coppertone::InvalidMechanismError)
77
+ end
78
+ end
79
+
80
+ context '.match' do
81
+ let(:client_ip) { IPAddr.new('4.5.6.7') }
82
+
83
+ let(:macro_context) do
84
+ mc = double(:macro_context)
85
+ allow(mc).to receive(:ip_v4).and_return(client_ip)
86
+ mc
87
+ end
88
+
89
+ let(:ip_v6_macro_context) do
90
+ mc = double(:macro_context)
91
+ allow(mc).to receive(:ip_v4).and_return(nil)
92
+ mc
93
+ end
94
+
95
+ it 'should return true if the client IP is in the network' do
96
+ mech = Coppertone::Mechanism::IP4.create('4.5.6.0/29')
97
+ expect(mech.match?(macro_context, double)).to eq(true)
98
+ end
99
+
100
+ it 'should return false if the client IP is not in the network' do
101
+ mech = Coppertone::Mechanism::IP4.create('4.5.6.0/30')
102
+ expect(mech.match?(macro_context, double)).to eq(false)
103
+ end
104
+
105
+ it 'should return false if the client IP is v6 only' do
106
+ mech = Coppertone::Mechanism::IP4.create('4.5.6.0/29')
107
+ expect(mech.match?(ip_v6_macro_context, double)).to eq(false)
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coppertone::Mechanism::IP6 do
4
+ context '#new' do
5
+ it 'should fail if called with a nil argument' do
6
+ expect do
7
+ Coppertone::Mechanism::IP6.new(nil)
8
+ end.to raise_error(Coppertone::InvalidMechanismError)
9
+ end
10
+
11
+ it 'should fail if called with a blank argument' do
12
+ expect do
13
+ Coppertone::Mechanism::IP6.new('')
14
+ end.to raise_error(Coppertone::InvalidMechanismError)
15
+ end
16
+
17
+ it 'should fail if called with an invalid IP' do
18
+ expect do
19
+ Coppertone::Mechanism::IP6.new('not_an_ip')
20
+ end.to raise_error(Coppertone::InvalidMechanismError)
21
+ end
22
+
23
+ it 'should not fail if called with an IP v4' do
24
+ mech = Coppertone::Mechanism::IP6.new('1.2.3.4')
25
+ expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4'))
26
+ end
27
+
28
+ it 'should work if called with an IP6' do
29
+ mech = Coppertone::Mechanism::IP6.new('fe80::202:b3ff:fe1e:8329')
30
+ expect(mech.ip_network)
31
+ .to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329'))
32
+ end
33
+
34
+ it 'should work if called with an IP6 with a pfxlen' do
35
+ mech = Coppertone::Mechanism::IP6.new('fe80::202:b3ff:fe1e:8329/64')
36
+ expect(mech.ip_network)
37
+ .to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329/64'))
38
+ end
39
+
40
+ it 'should fail if called with an invalid pfxlen' do
41
+ expect do
42
+ Coppertone::Mechanism::IP6.new('fe80::202:b3ff:fe1e:8329/384')
43
+ end.to raise_error(Coppertone::InvalidMechanismError)
44
+ end
45
+
46
+ end
47
+
48
+ context '#create' do
49
+ it 'should fail if called with a nil argument' do
50
+ expect do
51
+ Coppertone::Mechanism::IP6.create(nil)
52
+ end.to raise_error(Coppertone::InvalidMechanismError)
53
+ end
54
+
55
+ it 'should fail if called with a blank argument' do
56
+ expect do
57
+ Coppertone::Mechanism::IP6.create('')
58
+ end.to raise_error(Coppertone::InvalidMechanismError)
59
+ end
60
+
61
+ it 'should fail if called with an invalid IP' do
62
+ expect do
63
+ Coppertone::Mechanism::IP6.create('not_an_ip')
64
+ end.to raise_error(Coppertone::InvalidMechanismError)
65
+ end
66
+
67
+ it 'should not fail if called with an IP v4' do
68
+ mech = Coppertone::Mechanism::IP6.create('1.2.3.4')
69
+ expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4'))
70
+ end
71
+
72
+ it 'should work if called with an IP6' do
73
+ mech = Coppertone::Mechanism::IP6.create('fe80::202:b3ff:fe1e:8329')
74
+ expect(mech.ip_network)
75
+ .to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329'))
76
+ end
77
+
78
+ it 'should work if called with an IP6 with a pfxlen' do
79
+ mech = Coppertone::Mechanism::IP6.create('fe80::202:b3ff:fe1e:8329/64')
80
+ expect(mech.ip_network)
81
+ .to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329/64'))
82
+ end
83
+ end
84
+
85
+ context '.match' do
86
+ let(:client_ip) { IPAddr.new('fe80::202:b3ff:fe1e:8329') }
87
+
88
+ let(:macro_context) do
89
+ mc = double(:macro_context)
90
+ allow(mc).to receive(:ip_v6).and_return(client_ip)
91
+ mc
92
+ end
93
+
94
+ it 'should return true if the client IP is in the network' do
95
+ mech = Coppertone::Mechanism::IP6.create('fe80:0:0:0:202:b3ff:fe1e:8300/120')
96
+ expect(mech.match?(macro_context, double)).to eq(true)
97
+ end
98
+
99
+ it 'should return false if the client IP is not in the network' do
100
+ mech = Coppertone::Mechanism::IP6.create('fe80:0:0:0:202:b3ff:fe1e:8300/126')
101
+ expect(mech.match?(macro_context, double)).to eq(false)
102
+ end
103
+ end
104
+ end