Skip to content

Commit ca232bf

Browse files
committed
(CAT-1258) puppet_x unit tests
Unit test coverage for utility functions found within the puppet_x namespace
1 parent 6a06d60 commit ca232bf

File tree

2 files changed

+351
-0
lines changed

2 files changed

+351
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# frozen_string_literal: true
2+
3+
require 'puppet_x'
4+
require 'spec_helper'
5+
require 'puppet_x/puppetlabs/firewall/ipcidr'
6+
7+
RSpec.describe PuppetX::Firewall::IPCidr do # rubocop:disable RSpec/FilePath
8+
let(:ipcidr) { described_class }
9+
10+
describe 'ipv4 address' do
11+
subject(:host) { ipaddr }
12+
13+
let(:ipaddr) { ipcidr.new('96.126.112.51') }
14+
15+
it { expect(host.cidr).to eql '96.126.112.51/32' }
16+
it { expect(host.prefixlen).to be 32 }
17+
it { expect(host.netmask).to eql '255.255.255.255' }
18+
end
19+
20+
describe 'single ipv4 address with cidr' do
21+
subject(:host) { ipaddr }
22+
23+
let(:ipaddr) { ipcidr.new('96.126.112.51/32') }
24+
25+
it { expect(host.cidr).to eql '96.126.112.51/32' }
26+
it { expect(host.prefixlen).to be 32 }
27+
it { expect(host.netmask).to eql '255.255.255.255' }
28+
end
29+
30+
describe 'ipv4 address range with cidr' do
31+
subject(:host) { ipaddr }
32+
33+
let(:ipaddr) { ipcidr.new('96.126.112.0/24') }
34+
35+
it { expect(host.cidr).to eql '96.126.112.0/24' }
36+
it { expect(host.prefixlen).to be 24 }
37+
it { expect(host.netmask).to eql '255.255.255.0' }
38+
end
39+
40+
# https://tickets.puppetlabs.com/browse/MODULES-3215
41+
describe 'ipv4 address range with invalid cidr' do
42+
subject(:host) { ipaddr }
43+
44+
let(:ipaddr) { ipcidr.new('96.126.112.20/24') }
45+
46+
it { expect(host.cidr).to eq '96.126.112.0/24' } # .20 is expected to be silently dropped.
47+
it { expect(host.prefixlen).to be 24 }
48+
it { expect(host.netmask).to eql '255.255.255.0' }
49+
end
50+
51+
describe 'ipv4 open range with cidr' do
52+
subject(:host) { ipaddr }
53+
54+
let(:ipaddr) { ipcidr.new('0.0.0.0/0') }
55+
56+
it { expect(host.cidr).to eql '0.0.0.0/0' }
57+
it { expect(host.prefixlen).to be 0 }
58+
it { expect(host.netmask).to eql '0.0.0.0' }
59+
end
60+
61+
describe 'ipv4 invalid address' do
62+
subject(:host) { ipcidr.new('256.168.2.0/24') }
63+
64+
it { expect { host }.to raise_error ArgumentError, %r{256.168.2.0/24} }
65+
end
66+
67+
describe 'ipv6 address' do
68+
subject(:host) { ipaddr }
69+
70+
let(:ipaddr) { ipcidr.new('2001:db8:85a3:0:0:8a2e:370:7334') }
71+
72+
it { expect(host.cidr).to eql '2001:db8:85a3::8a2e:370:7334/128' }
73+
it { expect(host.prefixlen).to be 128 }
74+
it { expect(host.netmask).to eql 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' }
75+
end
76+
77+
describe 'single ipv6 addr with cidr' do
78+
subject(:host) { ipaddr }
79+
80+
let(:ipaddr) { ipcidr.new('2001:db8:85a3:0:0:8a2e:370:7334/128') }
81+
82+
it { expect(host.cidr).to eql '2001:db8:85a3::8a2e:370:7334/128' }
83+
it { expect(host.prefixlen).to be 128 }
84+
it { expect(host.netmask).to eql 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' }
85+
end
86+
87+
describe 'ipv6 addr range with cidr' do
88+
subject(:host) { ipaddr }
89+
90+
let(:ipaddr) { ipcidr.new('2001:db8:1234::/48') }
91+
92+
it { expect(host.cidr).to eql '2001:db8:1234::/48' }
93+
it { expect(host.prefixlen).to be 48 }
94+
it { expect(host.netmask).to eql 'ffff:ffff:ffff:0000:0000:0000:0000:0000' }
95+
end
96+
97+
describe 'ipv6 open range with cidr' do
98+
subject(:host) { ipaddr }
99+
100+
let(:ipaddr) { ipcidr.new('::/0') }
101+
102+
it { expect(host.cidr).to eql '::/0' }
103+
it { expect(host.prefixlen).to be 0 }
104+
it { expect(host.netmask).to eql '0000:0000:0000:0000:0000:0000:0000:0000' }
105+
end
106+
end
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
# frozen_string_literal: true
2+
3+
require 'puppet_x'
4+
require 'spec_helper'
5+
require 'puppet/resource_api'
6+
require 'puppet_x/puppetlabs/firewall/utility'
7+
8+
RSpec.describe PuppetX::Firewall::Utility do # rubocop:disable RSpec/FilePath
9+
let(:utility) { described_class }
10+
11+
describe '#persist_iptables' do
12+
before(:each) { Facter.clear }
13+
14+
let(:context) { Puppet::ResourceApi::PuppetContext.new(Puppet::Type.type('firewall').type_definition.definition) }
15+
16+
context 'when proto is IPv4' do
17+
let(:proto) { 'IPv4' }
18+
19+
it 'and OS family is RedHat' do
20+
allow(Facter.fact('os')).to receive(:value).and_return({ 'family' => 'RedHat' })
21+
expect(Puppet::Provider).to receive(:execute).with(['/usr/libexec/iptables/iptables.init', 'save'])
22+
23+
utility.persist_iptables(context, 'test', proto)
24+
end
25+
26+
it 'and OS family is Debian' do
27+
allow(Facter.fact('os')).to receive(:value).and_return({ 'family' => 'Debian' })
28+
allow(Facter.fact(:iptables_persistent_version)).to receive(:value).and_return('0.4')
29+
expect(Puppet::Provider).to receive(:execute).with(['/usr/sbin/service', 'iptables-persistent', 'save'])
30+
31+
utility.persist_iptables(context, 'test', proto)
32+
end
33+
34+
it 'and OS family is Archlinux' do
35+
allow(Facter.fact('os')).to receive(:value).and_return({ 'family' => 'Archlinux' })
36+
expect(Puppet::Provider).to receive(:execute).with(['/bin/sh', '-c', '/usr/sbin/iptables-save > /etc/iptables/iptables.rules'])
37+
38+
utility.persist_iptables(context, 'test', proto)
39+
end
40+
41+
it 'and OS family is Suse' do
42+
allow(Facter.fact('os')).to receive(:value).and_return({ 'family' => 'Suse' })
43+
expect(Puppet::Provider).to receive(:execute).with(['/bin/sh', '-c', '/usr/sbin/iptables-save > /etc/sysconfig/iptables'])
44+
45+
utility.persist_iptables(context, 'test', proto)
46+
end
47+
end
48+
49+
context 'when proto is IPv6' do
50+
let(:proto) { 'IPv6' }
51+
52+
it 'and OS family is RedHat' do
53+
allow(Facter.fact('os')).to receive(:value).and_return({ 'family' => 'RedHat' })
54+
expect(Puppet::Provider).to receive(:execute).with(['/usr/libexec/iptables/ip6tables.init', 'save'])
55+
56+
utility.persist_iptables(context, 'test', proto)
57+
end
58+
59+
it 'and OS family is Debian' do
60+
allow(Facter.fact('os')).to receive(:value).and_return({ 'family' => 'Debian' })
61+
allow(Facter.fact(:iptables_persistent_version)).to receive(:value).and_return('1.2')
62+
expect(Puppet::Provider).to receive(:execute).with(['/usr/sbin/service', 'netfilter-persistent', 'save'])
63+
64+
utility.persist_iptables(context, 'test', proto)
65+
end
66+
67+
it 'and OS family is Archlinux' do
68+
allow(Facter.fact('os')).to receive(:value).and_return({ 'family' => 'Archlinux' })
69+
expect(Puppet::Provider).to receive(:execute).with(['/bin/sh', '-c', '/usr/sbin/ip6tables-save > /etc/iptables/ip6tables.rules'])
70+
71+
utility.persist_iptables(context, 'test', proto)
72+
end
73+
end
74+
end
75+
76+
describe '#create_absent' do
77+
it {
78+
expect(utility.create_absent(:name, { chain: 'INPUT', table: 'filter', protocol: 'IPv4' })).to eql({ chain: 'INPUT', table: 'filter', protocol: 'IPv4', ensure: 'absent' })
79+
}
80+
81+
it { expect(utility.create_absent(:name, 'test')).to eql({ name: 'test', ensure: 'absent' }) }
82+
end
83+
84+
describe '#host_to_ip' do
85+
it {
86+
allow(Resolv).to receive(:each_address).at_least(:once).with('puppetlabs.com').and_yield('96.126.112.51').and_yield('2001:DB8:4650::13:8A')
87+
expect(utility.host_to_ip('puppetlabs.com', 'IPv4')).to eql '96.126.112.51/32'
88+
expect(utility.host_to_ip('puppetlabs.com', 'IPv6')).to eql '2001:db8:4650::13:8a/128'
89+
}
90+
91+
it { expect(utility.host_to_ip('96.126.112.51')).to eql '96.126.112.51/32' }
92+
it { expect(utility.host_to_ip('96.126.112.51/32')).to eql '96.126.112.51/32' }
93+
it { expect(utility.host_to_ip('2001:db8:85a3:0:0:8a2e:370:7334')).to eql '2001:db8:85a3::8a2e:370:7334/128' }
94+
it { expect(utility.host_to_ip('2001:db8:1234::/48')).to eql '2001:db8:1234::/48' }
95+
it { expect(utility.host_to_ip('0.0.0.0/0')).to be_nil }
96+
it { expect(utility.host_to_ip('::/0')).to be_nil }
97+
end
98+
99+
describe '#host_to_mask' do
100+
it {
101+
allow(Resolv).to receive(:each_address).at_least(:once).with('puppetlabs.com').and_yield('96.126.112.51').and_yield('2001:DB8:4650::13:8A')
102+
expect(utility.host_to_mask('puppetlabs.com', 'IPv4')).to eql '96.126.112.51/32'
103+
expect(utility.host_to_mask('! puppetlabs.com', 'IPv6')).to eql '! 2001:db8:4650::13:8a/128'
104+
}
105+
106+
it { expect(utility.host_to_mask('96.126.112.51', 'IPv4')).to eql '96.126.112.51/32' }
107+
it { expect(utility.host_to_mask('!96.126.112.51', 'IPv4')).to eql '! 96.126.112.51/32' }
108+
it { expect(utility.host_to_mask('96.126.112.51/32', 'IPv4')).to eql '96.126.112.51/32' }
109+
it { expect(utility.host_to_mask('! 96.126.112.51/32', 'IPv4')).to eql '! 96.126.112.51/32' }
110+
it { expect(utility.host_to_mask('2001:db8:85a3:0:0:8a2e:370:7334', 'IPv6')).to eql '2001:db8:85a3::8a2e:370:7334/128' }
111+
it { expect(utility.host_to_mask('!2001:db8:85a3:0:0:8a2e:370:7334', 'IPv6')).to eql '! 2001:db8:85a3::8a2e:370:7334/128' }
112+
it { expect(utility.host_to_mask('2001:db8:1234::/48', 'IPv6')).to eql '2001:db8:1234::/48' }
113+
it { expect(utility.host_to_mask('! 2001:db8:1234::/48', 'IPv6')).to eql '! 2001:db8:1234::/48' }
114+
it { expect(utility.host_to_mask('0.0.0.0/0', 'IPv4')).to be_nil }
115+
it { expect(utility.host_to_mask('!0.0.0.0/0', 'IPv4')).to be_nil }
116+
it { expect(utility.host_to_mask('::/0', 'IPv6')).to be_nil }
117+
it { expect(utility.host_to_mask('! ::/0', 'IPv6')).to be_nil }
118+
end
119+
120+
describe '#icmp_name_to_number' do
121+
context 'with proto unsupported' do
122+
['inet5', 'inet8', 'foo'].each do |proto|
123+
it "rejects invalid proto #{proto}" do
124+
expect { utility.icmp_name_to_number('echo-reply', proto) }
125+
.to raise_error(ArgumentError, "unsupported protocol family '#{proto}'")
126+
end
127+
end
128+
end
129+
130+
context 'with proto IPv4' do
131+
let(:proto) { 'IPv4' }
132+
133+
it { expect(utility.icmp_name_to_number('echo-reply', proto)).to eql '0' }
134+
it { expect(utility.icmp_name_to_number('destination-unreachable', proto)).to eql '3' }
135+
it { expect(utility.icmp_name_to_number('source-quench', proto)).to eql '4' }
136+
it { expect(utility.icmp_name_to_number('redirect', proto)).to eql '6' }
137+
it { expect(utility.icmp_name_to_number('echo-request', proto)).to eql '8' }
138+
it { expect(utility.icmp_name_to_number('router-advertisement', proto)).to eql '9' }
139+
it { expect(utility.icmp_name_to_number('router-solicitation', proto)).to eql '10' }
140+
it { expect(utility.icmp_name_to_number('time-exceeded', proto)).to eql '11' }
141+
it { expect(utility.icmp_name_to_number('parameter-problem', proto)).to eql '12' }
142+
it { expect(utility.icmp_name_to_number('timestamp-request', proto)).to eql '13' }
143+
it { expect(utility.icmp_name_to_number('timestamp-reply', proto)).to eql '14' }
144+
it { expect(utility.icmp_name_to_number('address-mask-request', proto)).to eql '17' }
145+
it { expect(utility.icmp_name_to_number('address-mask-reply', proto)).to eql '18' }
146+
end
147+
148+
context 'with proto IPv6' do
149+
let(:proto) { 'IPv6' }
150+
151+
it { expect(utility.icmp_name_to_number('destination-unreachable', proto)).to eql '1' }
152+
it { expect(utility.icmp_name_to_number('time-exceeded', proto)).to eql '3' }
153+
it { expect(utility.icmp_name_to_number('parameter-problem', proto)).to eql '4' }
154+
it { expect(utility.icmp_name_to_number('echo-request', proto)).to eql '128' }
155+
it { expect(utility.icmp_name_to_number('echo-reply', proto)).to eql '129' }
156+
it { expect(utility.icmp_name_to_number('router-solicitation', proto)).to eql '133' }
157+
it { expect(utility.icmp_name_to_number('router-advertisement', proto)).to eql '134' }
158+
it { expect(utility.icmp_name_to_number('neighbour-solicitation', proto)).to eql '135' }
159+
it { expect(utility.icmp_name_to_number('neighbour-advertisement', proto)).to eql '136' }
160+
it { expect(utility.icmp_name_to_number('redirect', proto)).to eql '137' }
161+
end
162+
end
163+
164+
describe '#log_level_name_to_number' do
165+
it { expect(utility.log_level_name_to_number('2')).to eql '2' }
166+
it { expect(utility.log_level_name_to_number('4')).to eql '4' }
167+
it { expect(utility.log_level_name_to_number('panic')).to eql '0' }
168+
it { expect(utility.log_level_name_to_number('alert')).to eql '1' }
169+
it { expect(utility.log_level_name_to_number('crit')).to eql '2' }
170+
it { expect(utility.log_level_name_to_number('err')).to eql '3' }
171+
it { expect(utility.log_level_name_to_number('warn')).to eql '4' }
172+
it { expect(utility.log_level_name_to_number('not')).to eql '5' }
173+
it { expect(utility.log_level_name_to_number('info')).to eql '6' }
174+
it { expect(utility.log_level_name_to_number('debug')).to eql '7' }
175+
it { expect(utility.log_level_name_to_number('fail')).to be_nil }
176+
end
177+
178+
describe '#to_hex32' do
179+
it { expect(utility.to_hex32('0')).to eql '0x0' }
180+
it { expect(utility.to_hex32('0x32')).to eql '0x32' }
181+
it { expect(utility.to_hex32('42')).to eql '0x2a' }
182+
it { expect(utility.to_hex32('4294967295')).to eql '0xffffffff' }
183+
it { expect(utility.to_hex32('4294967296')).to be_nil }
184+
it { expect(utility.to_hex32('-1')).to be_nil }
185+
it { expect(utility.to_hex32('bananas')).to be_nil }
186+
end
187+
188+
describe '#mark_mask_to_hex' do
189+
it { expect(utility.mark_mask_to_hex('0')).to eql '0x0/0xffffffff' }
190+
it { expect(utility.mark_mask_to_hex('0x32/0')).to eql '0x32/0x0' }
191+
it { expect(utility.mark_mask_to_hex('42')).to eql '0x2a/0xffffffff' }
192+
it { expect(utility.mark_mask_to_hex('4294967295/42')).to eql '0xffffffff/0x2a' }
193+
end
194+
195+
describe '#mark_to_hex' do
196+
it { expect(utility.mark_to_hex('0')).to eql '0x0' }
197+
it { expect(utility.mark_to_hex('! 0x32')).to eql '! 0x32' }
198+
it { expect(utility.mark_to_hex('42')).to eql '0x2a' }
199+
it { expect(utility.mark_to_hex('! 4294967295')).to eql '! 0xffffffff' }
200+
end
201+
202+
describe '#proto_number_to_name' do
203+
it { expect(utility.proto_number_to_name('1')).to eql 'icmp' }
204+
it { expect(utility.proto_number_to_name('2')).to eql 'igmp' }
205+
it { expect(utility.proto_number_to_name('4')).to eql 'ipencap' }
206+
it { expect(utility.proto_number_to_name('6')).to eql 'tcp' }
207+
it { expect(utility.proto_number_to_name('7')).to eql 'cbt' }
208+
it { expect(utility.proto_number_to_name('17')).to eql 'udp' }
209+
it { expect(utility.proto_number_to_name('47')).to eql 'gre' }
210+
it { expect(utility.proto_number_to_name('50')).to eql 'esp' }
211+
it { expect(utility.proto_number_to_name('51')).to eql 'ah' }
212+
it { expect(utility.proto_number_to_name('89')).to eql 'ospf' }
213+
it { expect(utility.proto_number_to_name('103')).to eql 'pim' }
214+
it { expect(utility.proto_number_to_name('112')).to eql 'vrrp' }
215+
it { expect(utility.proto_number_to_name('132')).to eql 'sctp' }
216+
217+
it 'rejects invalid number 619' do
218+
expect { utility.proto_number_to_name('619') }.to raise_error(ArgumentError, 'Unsupported proto number: 619')
219+
end
220+
end
221+
222+
describe '#dscp_number_to_class' do
223+
it { expect(utility.dscp_number_to_class('0x0a')).to eql 'af11' }
224+
it { expect(utility.dscp_number_to_class('0x0c')).to eql 'af12' }
225+
it { expect(utility.dscp_number_to_class('0x0e')).to eql 'af13' }
226+
it { expect(utility.dscp_number_to_class('0x12')).to eql 'af21' }
227+
it { expect(utility.dscp_number_to_class('0x14')).to eql 'af22' }
228+
it { expect(utility.dscp_number_to_class('0x16')).to eql 'af23' }
229+
it { expect(utility.dscp_number_to_class('0x1a')).to eql 'af31' }
230+
it { expect(utility.dscp_number_to_class('0x1c')).to eql 'af32' }
231+
it { expect(utility.dscp_number_to_class('0x1e')).to eql 'af33' }
232+
it { expect(utility.dscp_number_to_class('0x22')).to eql 'af41' }
233+
it { expect(utility.dscp_number_to_class('0x24')).to eql 'af42' }
234+
it { expect(utility.dscp_number_to_class('0x26')).to eql 'af43' }
235+
it { expect(utility.dscp_number_to_class('0x08')).to eql 'cs1' }
236+
it { expect(utility.dscp_number_to_class('0x10')).to eql 'cs2' }
237+
it { expect(utility.dscp_number_to_class('0x18')).to eql 'cs3' }
238+
it { expect(utility.dscp_number_to_class('0x20')).to eql 'cs4' }
239+
it { expect(utility.dscp_number_to_class('0x28')).to eql 'cs5' }
240+
it { expect(utility.dscp_number_to_class('0x30')).to eql 'cs6' }
241+
it { expect(utility.dscp_number_to_class('0x38')).to eql 'cs7' }
242+
it { expect(utility.dscp_number_to_class('0x2e')).to eql 'ef' }
243+
it { expect(utility.dscp_number_to_class('0x66')).to be_nil }
244+
end
245+
end

0 commit comments

Comments
 (0)