ubicloud/spec/model/private_subnet_spec.rb
Jeremy Evans 45a66b2195 Support testing with frozen Database and models
This makes the testing more like the production environment.

This renames the previous frozen_{,p}spec rake task to
frozen_core_{,p}spec, and adds:

* frozen_db_model_{,p}spec for running the specs with just a frozen
  Database and models
* frozen_{,p}spec for running the specs with a frozen core, Database,
  and models (the most similar to the production environment, but
  the most skipped tests).

This adds rspec and turbo_tests lambdas to DRY up the related rake
task code. It sets RAKE_ENV explicitly for turbo_tests, instead
of relying on the Rakefile setting it implicitly due to how the
spec tasks is currently defined.

This adds a skip_if_frozen_models method to the specs, which does
nothing when running without frozen Database and models, but skips
the spec if running with frozen Database and models.  It then
adds a call to skip_if_frozen_models to all specs that try to mock
DB or the models (109 callsites, 124 specs).

To avoid pages of output of skipped specs, this uses the approach
recommended by the rspec maintainers to suppress skipped specs.
The approach is stored in a separate spec/supress_pending file
so it is usable by both the normal and parallel specs.

I tested this with the implicit_subquery commit
(0085befc4a), and the frozen model
tests fail with it, showing that this approach would have caught
that failure before the change was put into production.
2024-10-28 14:31:00 -07:00

128 lines
4.4 KiB
Ruby

# frozen_string_literal: true
require_relative "spec_helper"
RSpec.describe PrivateSubnet do
subject(:private_subnet) {
described_class.new(
net6: NetAddr.parse_net("fd1b:9793:dcef:cd0a::/64"),
net4: NetAddr.parse_net("10.9.39.0/26"),
location: "hetzner-hel1",
state: "waiting",
name: "ps"
)
}
let(:nic) { instance_double(Nic, id: "0a9a166c-e7e7-4447-ab29-7ea442b5bb0e") }
let(:existing_nic) {
instance_double(Nic,
id: "46ca6ded-b056-4723-bd91-612959f52f6f",
private_ipv4: "10.9.39.5/32",
private_ipv6: "fd1b:9793:dcef:cd0a:c::/79")
}
describe "random ip generation" do
it "returns random private ipv4" do
expect(SecureRandom).to receive(:random_number).with(59).and_return(5)
expect(private_subnet.random_private_ipv4.to_s).to eq "10.9.39.9/32"
end
it "returns random private ipv6" do
expect(SecureRandom).to receive(:random_number).with(32766).and_return(5)
expect(private_subnet.random_private_ipv6.to_s).to eq "fd1b:9793:dcef:cd0a:c::/79"
end
it "returns random private ipv4 when ip exists" do
expect(SecureRandom).to receive(:random_number).with(59).and_return(1, 2)
expect(private_subnet).to receive(:nics).and_return([existing_nic]).twice
expect(private_subnet.random_private_ipv4.to_s).to eq "10.9.39.6/32"
end
it "returns random private ipv6 when ip exists" do
expect(SecureRandom).to receive(:random_number).with(32766).and_return(5, 6)
expect(private_subnet).to receive(:nics).and_return([existing_nic]).twice
expect(private_subnet.random_private_ipv6.to_s).to eq "fd1b:9793:dcef:cd0a:e::/79"
end
end
describe ".[]" do
let(:private_subnet) {
subnet = super()
subnet.net6 = subnet.net6.to_s
subnet.net4 = subnet.net4.to_s
subnet.id = described_class.generate_ubid.to_uuid.to_s
subnet.save_changes
}
it "looks up by ubid object" do
expect(described_class[UBID.parse(private_subnet.ubid)].id).to eq private_subnet.id
end
it "looks up by ubid string" do
expect(described_class[private_subnet.ubid].id).to eq private_subnet.id
end
it "looks up by uuid string" do
expect(described_class[private_subnet.id].id).to eq private_subnet.id
end
it "looks up by hash" do
expect(described_class[id: private_subnet.id].id).to eq private_subnet.id
end
it "doesn't raise if given something that looks like a ubid but isn't" do
expect(described_class["a" * 26]).to be_nil
end
end
describe "#inspect" do
it "includes ubid if id is available" do
ubid = described_class.generate_ubid
uuid = private_subnet.id = ubid.to_uuid.to_s
expect(private_subnet.inspect).to eq "#<PrivateSubnet[\"#{ubid}\"] @values={:net6=>\"fd1b:9793:dcef:cd0a::/64\", :net4=>\"10.9.39.0/26\", :location=>\"hetzner-hel1\", :state=>\"waiting\", :name=>\"ps\", :id=>\"#{uuid}\"}>"
end
it "does not includes ubid if id is missing" do
expect(private_subnet.inspect).to eq "#<PrivateSubnet @values={:net6=>\"fd1b:9793:dcef:cd0a::/64\", :net4=>\"10.9.39.0/26\", :location=>\"hetzner-hel1\", :state=>\"waiting\", :name=>\"ps\"}>"
end
end
describe "uuid to name" do
it "returns the name" do
expect(described_class.ubid_to_name("psetv2ff83xj6h3prt2jwavh0q")).to eq "psetv2ff"
end
end
describe "ui utility methods" do
it "returns path" do
expect(private_subnet.path).to eq "/location/eu-north-h1/private-subnet/ps"
end
it "returns tag name" do
pr = instance_double(Project, ubid: "prjubid")
expect(private_subnet.hyper_tag_name(pr)).to eq "project/prjubid/location/eu-north-h1/private-subnet/ps"
end
end
describe "display_state" do
it "returns available when waiting" do
expect(private_subnet.display_state).to eq "available"
end
it "returns state if not waiting" do
private_subnet.state = "failed"
expect(private_subnet.display_state).to eq "failed"
end
end
describe "destroy" do
it "destroys firewalls private subnets" do
skip_if_frozen_models
ps = described_class.create_with_id(name: "test-ps", location: "hetzner-hel1", net6: "2001:db8::/64", net4: "10.0.0.0/24")
fwps = instance_double(FirewallsPrivateSubnets)
expect(FirewallsPrivateSubnets).to receive(:where).with(private_subnet_id: ps.id).and_return(instance_double(Sequel::Dataset, all: [fwps]))
expect(fwps).to receive(:destroy).once
ps.destroy
end
end
end