<commit_before>describe PglogicalSubscription do
  let(:remote_region1) { ApplicationRecord.my_region_number + 1 }
  let(:remote_region2) { ApplicationRecord.my_region_number + 2 }
  let(:subscriptions) do
    [
      {
        "subscription_name"      => "region_#{remote_region1}_subscription",
        "status"                 => "replicating",
        "provider_node"          => "region_#{remote_region1}",
        "provider_dsn"           => "dbname = 'vmdb\\'s_test' host='example.com' user='root' port='' password='p=as\\' s\\''",
        "slot_name"              => "pgl_vmdb_test_region_#{remote_region1}_subscripdb71d61",
        "replication_sets"       => ["miq"],
        "forward_origins"        => ["all"],
        "remote_replication_lsn" => "0/420D9A0",
        "local_replication_lsn"  => "18/72DE8268"
      },
      {
        "subscription_name"      => "region_#{remote_region2}_subscription",
        "status"                 => "disabled",
        "provider_node"          => "region_#{remote_region2}",
        "provider_dsn"           => "dbname = vmdb_test2 host=test.example.com user = postgres port=5432 fallback_application_name='bin/rails'",
        "slot_name"              => "pgl_vmdb_test_region_#{remote_region2}_subscripdb71d61",
        "replication_sets"       => ["miq"],
        "forward_origins"        => ["all"],
        "remote_replication_lsn" => "1/53E9A8",
        "local_replication_lsn"  => "20/72FF8369"
      }
    ]
  end

  let(:expected_attrs) do
    [
      {
        "id"                   => "region_#{remote_region1}_subscription",
        "status"               => "replicating",
        "dbname"               => "vmdb's_test",
        "host"                 => "example.com",
        "user"                 => "root",
        "provider_region"      => remote_region1,
        "provider_region_name" => "The region"
      },
      {
        "id"              => "region_#{remote_region2}_subscription",
        "status"          => "disabled",
        "dbname"          => "vmdb_test2",
        "host"            => "test.example.com",
        "user"            => "postgres",
        "port"            => 5432,
        "provider_region" => remote_region2
      }
    ]
  end

  let(:pglogical)      { double }
  let!(:remote_region) do
    FactoryBot.create(
      :miq_region,
      :id          => ApplicationRecord.id_in_region(remote_region1, 1),
      :region      => remote_region1,
      :description => "The region"
    )
  end

  before do
    allow(described_class).to receive(:pglogical).and_return(pglogical)
  end

  describe ".all" do
    it "retrieves all records with records" do
      with_records
      actual_attrs = described_class.all.map(&:attributes)
      expect(actual_attrs).to match_array(expected_attrs)
    end

    it "supports find(:all) with records" do
      with_records
      actual_attrs = described_class.find(:all).map(&:attributes)
      expect(actual_attrs).to match_array(expected_attrs)
    end

    it "retrieves no records with no records" do
      with_no_records
      expect(described_class.all).to be_empty
      expect(described_class.find(:all)).to be_empty
    end

    it "retrieves an empty array with pglogical disabled" do
      with_pglogical_disabled
      expect(described_class.all).to be_empty
    end
  end

  describe ".first" do
    it "retrieves the first record with records" do
      with_records
      rec = described_class.find(:first)
      expect(rec.attributes).to eq(expected_attrs.first)
    end

    it "returns nil with no records" do
      with_no_records
      expect(described_class.find(:first)).to be_nil
    end

    it "returns nil with pglogical disabled" do
      with_pglogical_disabled
      expect(described_class.find(:first)).to be_nil
    end
  end

  describe ".last" do
    it "retrieves the last record with :last" do
      with_records
      rec = described_class.find(:last)
      expect(rec.attributes).to eq(expected_attrs.last)
    end

    it "returns nil with :last" do
      with_no_records
      expect(described_class.find(:last)).to be_nil
    end

    it "returns nil with :last" do
      with_pglogical_disabled
      expect(described_class.find(:last)).to be_nil
    end
  end

  describe ".find" do
    it "retrieves the specified record with records" do
      with_records
      expected = expected_attrs.first
      rec = described_class.find(expected["id"])
      expect(rec.attributes).to eq(expected)
    end

    it "raises when no record is found" do
      with_no_records
      expect { described_class.find("doesnt_exist") }.to raise_error(ActiveRecord::RecordNotFound)
    end

    it "raises with pglogical disabled" do
      with_pglogical_disabled
      expect { described_class.find("doesnt_exist") }.to raise_error(ActiveRecord::RecordNotFound)
    end
  end

  describe ".find_by_id" do
    it "returns the specified record with records" do
      allow(pglogical).to receive(:subscriptions).and_return(subscriptions)
      allow(pglogical).to receive(:enabled?).and_return(true)

      expected = expected_attrs.first
      rec = described_class.find_by_id(expected["id"])
      expect(rec.attributes).to eq(expected)
    end

    it "returns nil without records" do
      allow(pglogical).to receive(:subscriptions).and_return([])
      allow(pglogical).to receive(:enabled?).and_return(true)

      expect(described_class.find_by_id("some_subscription")).to be_nil
    end

    it "returns nil with pglogical disabled" do
      allow(pglogical).to receive(:enabled?).and_return(false)
      expect(described_class.find_by_id("some_subscription")).to be_nil
    end
  end

  describe "#save!" do
    context "failover monitor reloading" do
      let(:sub) { described_class.new(:host => "test-2.example.com", :user => "root", :password => "<PASSWORD>") }
      before do
        allow(pglogical).to receive(:subscriptions).and_return([])
        allow(pglogical).to receive(:enabled?).and_return(true)
        allow(pglogical).to receive(:subscription_show_status).and_return(subscriptions.first)
        allow(pglogical).to receive(:subscription_create).and_return(double(:check => nil))
        allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))
        allow(sub).to receive(:remote_region_number).and_return(remote_region1)
        allow(sub).to receive(:ensure_node_created).and_return(true)
      end

      it "doesn't queue a message to restart the failover monitor service when passed 'false'" do
        sub.save!(false)
        expect(MiqQueue.where(:method_name => "restart_failover_monitor_service")).to be_empty
      end

      it "queues a message to restart the failover monitor when called without args" do
        sub.save!
        expect(MiqQueue.where(:method_name => "restart_failover_monitor_service").count).to eq(1)
      end
    end

    it "raises when subscribing to the same region" do
      allow(pglogical).to receive(:subscriptions).and_return([])
      allow(pglogical).to receive(:enabled?).and_return(true)
      allow(pglogical).to receive(:subscription_show_status).and_return(subscriptions.first)
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))

      sub = described_class.new(:host => "some.host.example.com")
      expect { sub.save! }.to raise_error(RuntimeError, "Subscriptions cannot be created to the same region as the current region")
    end

    it "does not raise when subscribing to a different region" do
      allow(pglogical).to receive(:subscriptions).and_return([])
      allow(pglogical).to receive(:enabled?).and_return(true)
      allow(pglogical).to receive(:subscription_show_status).and_return(subscriptions.first)
      allow(pglogical).to receive(:subscription_create).and_return(double(:check => nil))
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))

      sub = described_class.new(:host => "test-2.example.com", :user => "root", :password => "<PASSWORD>")
      allow(sub).to receive(:remote_region_number).and_return(remote_region1)
      allow(sub).to receive(:ensure_node_created).and_return(true)

      expect { sub.save! }.not_to raise_error
    end

    it "creates the node when there are no subscriptions" do
      allow(pglogical).to receive(:subscriptions).and_return([])
      allow(pglogical).to receive(:enabled?).and_return(true)
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))
      allow(MiqRegionRemote).to receive(:region_number_from_sequence).and_return(2)

      # node created if we are not already a node
      expect(MiqPglogical).to receive(:new).and_return(double(:node? => false))
      expect(pglogical).to receive(:enable)
      expect(pglogical).to receive(:node_create).and_return(double(:check => nil))

      # subscription is created
      expect(pglogical).to receive(:subscription_create) do |name, dsn, replication_sets, sync_structure|
        expect(name).to eq("region_2_subscription")
        expect(dsn).to include("host='test-2.example.com'")
        expect(dsn).to include("user='root'")
        expect(replication_sets).to eq(['miq'])
        expect(sync_structure).to be false
      end.and_return(double(:check => nil))

      sub = described_class.new(:host => "test-2.example.com", :user => "root", :password => "<PASSWORD>")
      allow(sub).to receive(:assert_different_region!)

      sub.save!
    end

    it "doesnt create the node when we are already a node" do
      allow(pglogical).to receive(:subscriptions).and_return([])
      allow(pglogical).to receive(:enabled?).and_return(true)
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))
      allow(MiqRegionRemote).to receive(:region_number_from_sequence).and_return(2)

      # node not created if we are already a node
      expect(MiqPglogical).to receive(:new).and_return(double(:node? => true))
      expect(pglogical).not_to receive(:enable)
      expect(pglogical).not_to receive(:node_create)

      # subscription is created
      expect(pglogical).to receive(:subscription_create) do |name, dsn, replication_sets, sync_structure|
        expect(name).to eq("region_2_subscription")
        expect(dsn).to include("host='test-2.example.com'")
        expect(dsn).to include("user='root'")
        expect(replication_sets).to eq(['miq'])
        expect(sync_structure).to be false
      end.and_return(double(:check => nil))

      sub = described_class.new(:host => "test-2.example.com", :password => "<PASSWORD>", :user => "root")
      allow(sub).to receive(:assert_different_region!)

      sub.save!
      expect(sub).to be_an_instance_of(described_class)
    end

    it "updates the dsn when an existing subscription is saved" do
      allow(pglogical).to receive(:subscriptions).and_return(subscriptions)
      allow(pglogical).to receive(:enabled?).and_return(true)
      allow(pglogical).to receive(:subscription_show_status).and_return(subscriptions.first)
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))

      sub = described_class.find(:first)
      sub.host = "other-host.example.com"
      allow(sub).to receive(:assert_different_region!)

      expect(pglogical).to receive(:subscription_disable).with(sub.id)
        .and_return(double(:check => nil))
      expect(pglogical).to receive(:node_dsn_update) do |provider_node_name, new_dsn|
        expect(provider_node_name).to eq("region_#{remote_region1}")
        expect(new_dsn).to include("host='other-host.example.com'")
        expect(new_dsn).to include("dbname='vmdb\\'s_test'")
        expect(new_dsn).to include("user='root'")
        expect(new_dsn).to include("password='<PASSWORD>\\' s\\''")
      end
      expect(pglogical).to receive(:subscription_enable).with(sub.id)
        .and_return(double(:check => nil))

      expect(sub.save!).to eq(sub)
    end

    it "reenables the subscription when the dsn fails to save" do
      allow(pglogical).to receive(:subscriptions).and_return(subscriptions)
      allow(pglogical).to receive(:enabled?).and_return(true)
      allow(pglogical).to receive(:subscription_show_status).and_return(subscriptions.first)
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))

      sub = described_class.find(:first)
      sub.host = "other-host.example.com"
      allow(sub).to receive(:assert_different_region!)

      expect(pglogical).to receive(:subscription_disable).with(sub.id)
        .and_return(double(:check => nil))
      expect(pglogical).to receive(:node_dsn_update).and_raise("Some Error")
      expect(pglogical).to receive(:subscription_enable).with(sub.id)
        .and_return(double(:check => nil))

      expect { sub.save! }.to raise_error(RuntimeError, "Some Error")
    end
  end

  describe ".delete_all" do
    let(:subscription1) { double }
    let(:subscription2) { double }

    after do
      expect(MiqQueue.where(:method_name => "restart_failover_monitor_service").count).to eq(1)
    end

    it "deletes all subscriptions if no parameter passed" do
      allow(described_class).to receive(:find).with(:all).and_return([subscription1, subscription2])
      expect(subscription1).to receive(:delete)
      expect(subscription2).to receive(:delete)
      described_class.delete_all
    end

    it "only deletes subscriptions listed in parameter if parameter passed" do
      expect(subscription1).to receive(:delete)
      expect(subscription2).not_to receive(:delete)
      described_class.delete_all([subscription1])
    end
  end

  describe ".save_all!" do
    after do
      expect(MiqQueue.where(:method_name => "restart_failover_monitor_service").count).to eq(1)
    end

    it "saves each of the objects" do
      allow(pglogical).to receive(:subscriptions).and_return([])
      allow(pglogical).to receive(:enabled?).and_return(true)
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))
      allow(MiqRegionRemote).to receive(:region_number_from_sequence).and_return(2, 2, 3, 3)

      # node created
      allow(pglogical).to receive(:enable)
      allow(pglogical).to receive(:node_create).and_return(double(:check => nil))

      # subscription is created
      expect(pglogical).to receive(:subscription_create) do |name, dsn, replication_sets, sync_structure|
        expect(name).to eq("region_2_subscription")
        expect(dsn).to include("host='test-2.example.com'")
        expect(dsn).to include("user='root'")
        expect(replication_sets).to eq(['miq'])
        expect(sync_structure).to be false
      end.and_return(double(:check => nil))

      expect(pglogical).to receive(:subscription_create) do |name, dsn, replication_sets, sync_structure|
        expect(name).to eq("region_3_subscription")
        expect(dsn).to include("host='test-3.example.com'")
        expect(dsn).to include("user='miq'")
        expect(replication_sets).to eq(['miq'])
        expect(sync_structure).to be false
      end.and_return(double(:check => nil))

      to_save = []
      to_save << described_class.new(:host => "test-2.example.com", :password => "<PASSWORD>4", :user => "root")
      to_save << described_class.new(:host => "test-3.example.com", :password => "<PASSWORD>", :user => "miq")
      to_save.each { |s| allow(s).to receive(:assert_different_region!) }

      described_class.save_all!(to_save)
    end

    it "raises a combined error when some saves fail" do
      allow(pglogical).to receive(:subscriptions).and_return([])
      allow(pglogical).to receive(:enabled?).and_return(true)
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))
      allow(MiqRegionRemote).to receive(:region_number_from_sequence).and_return(2, 2, 3, 3, 4, 4)

      # node created
      allow(pglogical).to receive(:enable)
      allow(pglogical).to receive(:node_create).and_return(double(:check => nil))

      # subscription is created
      expect(pglogical).to receive(:subscription_create).ordered.and_raise(PG::Error.new("Error one"))
      expect(pglogical).to receive(:subscription_create) do |name, dsn, replication_sets, sync_structure|
        expect(name).to eq("region_3_subscription")
        expect(dsn).to include("host='test-3.example.com'")
        expect(dsn).to include("user='miq'")
        expect(replication_sets).to eq(['miq'])
        expect(sync_structure).to be false
      end.ordered.and_return(double(:check => nil))
      expect(pglogical).to receive(:subscription_create).ordered.and_raise("Error two")

      to_save = []
      to_save << described_class.new(:host => "test-2.example.com", :user => "root", :password => "<PASSWORD>")
      to_save << described_class.new(:host => "test-3.example.com", :user => "miq", :password => "<PASSWORD>")<commit_msg>pull out with_records common concept in spec<commit_after>describe PglogicalSubscription do
  let(:remote_region1) { ApplicationRecord.my_region_number + 1 }
  let(:remote_region2) { ApplicationRecord.my_region_number + 2 }
  let(:subscriptions) do
    [
      {
        "subscription_name"      => "region_#{remote_region1}_subscription",
        "status"                 => "replicating",
        "provider_node"          => "region_#{remote_region1}",
        "provider_dsn"           => "dbname = 'vmdb\\'s_test' host='example.com' user='root' port='' password='<PASSWORD>\\' s\\''",
        "slot_name"              => "pgl_vmdb_test_region_#{remote_region1}_subscripdb71d61",
        "replication_sets"       => ["miq"],
        "forward_origins"        => ["all"],
        "remote_replication_lsn" => "0/420D9A0",
        "local_replication_lsn"  => "18/72DE8268"
      },
      {
        "subscription_name"      => "region_#{remote_region2}_subscription",
        "status"                 => "disabled",
        "provider_node"          => "region_#{remote_region2}",
        "provider_dsn"           => "dbname = vmdb_test2 host=test.example.com user = postgres port=5432 fallback_application_name='bin/rails'",
        "slot_name"              => "pgl_vmdb_test_region_#{remote_region2}_subscripdb71d61",
        "replication_sets"       => ["miq"],
        "forward_origins"        => ["all"],
        "remote_replication_lsn" => "1/53E9A8",
        "local_replication_lsn"  => "20/72FF8369"
      }
    ]
  end

  let(:expected_attrs) do
    [
      {
        "id"                   => "region_#{remote_region1}_subscription",
        "status"               => "replicating",
        "dbname"               => "vmdb's_test",
        "host"                 => "example.com",
        "user"                 => "root",
        "provider_region"      => remote_region1,
        "provider_region_name" => "The region"
      },
      {
        "id"              => "region_#{remote_region2}_subscription",
        "status"          => "disabled",
        "dbname"          => "vmdb_test2",
        "host"            => "test.example.com",
        "user"            => "postgres",
        "port"            => 5432,
        "provider_region" => remote_region2
      }
    ]
  end

  let(:pglogical)      { double }
  let!(:remote_region) do
    FactoryBot.create(
      :miq_region,
      :id          => ApplicationRecord.id_in_region(remote_region1, 1),
      :region      => remote_region1,
      :description => "The region"
    )
  end

  before do
    allow(described_class).to receive(:pglogical).and_return(pglogical)
  end

  describe ".all" do
    it "retrieves all records with records" do
      with_records
      actual_attrs = described_class.all.map(&:attributes)
      expect(actual_attrs).to match_array(expected_attrs)
    end

    it "supports find(:all) with records" do
      with_records
      actual_attrs = described_class.find(:all).map(&:attributes)
      expect(actual_attrs).to match_array(expected_attrs)
    end

    it "retrieves no records with no records" do
      with_no_records
      expect(described_class.all).to be_empty
      expect(described_class.find(:all)).to be_empty
    end

    it "retrieves an empty array with pglogical disabled" do
      with_pglogical_disabled
      expect(described_class.all).to be_empty
    end
  end

  describe ".first" do
    it "retrieves the first record with records" do
      with_records
      rec = described_class.find(:first)
      expect(rec.attributes).to eq(expected_attrs.first)
    end

    it "returns nil with no records" do
      with_no_records
      expect(described_class.find(:first)).to be_nil
    end

    it "returns nil with pglogical disabled" do
      with_pglogical_disabled
      expect(described_class.find(:first)).to be_nil
    end
  end

  describe ".last" do
    it "retrieves the last record with :last" do
      with_records
      rec = described_class.find(:last)
      expect(rec.attributes).to eq(expected_attrs.last)
    end

    it "returns nil with :last" do
      with_no_records
      expect(described_class.find(:last)).to be_nil
    end

    it "returns nil with :last" do
      with_pglogical_disabled
      expect(described_class.find(:last)).to be_nil
    end
  end

  describe ".find" do
    it "retrieves the specified record with records" do
      with_records
      expected = expected_attrs.first
      rec = described_class.find(expected["id"])
      expect(rec.attributes).to eq(expected)
    end

    it "raises when no record is found" do
      with_no_records
      expect { described_class.find("doesnt_exist") }.to raise_error(ActiveRecord::RecordNotFound)
    end

    it "raises with pglogical disabled" do
      with_pglogical_disabled
      expect { described_class.find("doesnt_exist") }.to raise_error(ActiveRecord::RecordNotFound)
    end
  end

  describe ".find_by_id" do
    it "returns the specified record with records" do
      with_records
      expected = expected_attrs.first
      rec = described_class.find_by_id(expected["id"])
      expect(rec.attributes).to eq(expected)
    end

    it "returns nil without records" do
      with_no_records
      expect(described_class.find_by_id("some_subscription")).to be_nil
    end

    it "returns nil with pglogical disabled" do
      with_pglogical_disabled
      expect(described_class.find_by_id("some_subscription")).to be_nil
    end
  end

  describe "#save!" do
    context "failover monitor reloading" do
      let(:sub) { described_class.new(:host => "test-2.example.com", :user => "root", :password => "<PASSWORD>") }
      before do
        with_no_records
        allow(pglogical).to receive(:subscription_show_status).and_return(subscriptions.first)
        allow(pglogical).to receive(:subscription_create).and_return(double(:check => nil))
        allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))
        allow(sub).to receive(:remote_region_number).and_return(remote_region1)
        allow(sub).to receive(:ensure_node_created).and_return(true)
      end

      it "doesn't queue a message to restart the failover monitor service when passed 'false'" do
        sub.save!(false)
        expect(MiqQueue.where(:method_name => "restart_failover_monitor_service")).to be_empty
      end

      it "queues a message to restart the failover monitor when called without args" do
        sub.save!
        expect(MiqQueue.where(:method_name => "restart_failover_monitor_service").count).to eq(1)
      end
    end

    it "raises when subscribing to the same region" do
      with_no_records
      allow(pglogical).to receive(:subscription_show_status).and_return(subscriptions.first)
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))

      sub = described_class.new(:host => "some.host.example.com")
      expect { sub.save! }.to raise_error(RuntimeError, "Subscriptions cannot be created to the same region as the current region")
    end

    it "does not raise when subscribing to a different region" do
      with_no_records
      allow(pglogical).to receive(:subscription_show_status).and_return(subscriptions.first)
      allow(pglogical).to receive(:subscription_create).and_return(double(:check => nil))
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))

      sub = described_class.new(:host => "test-2.example.com", :user => "root", :password => "<PASSWORD>")
      allow(sub).to receive(:remote_region_number).and_return(remote_region1)
      allow(sub).to receive(:ensure_node_created).and_return(true)

      expect { sub.save! }.not_to raise_error
    end

    it "creates the node when there are no subscriptions" do
      with_no_records
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))
      allow(MiqRegionRemote).to receive(:region_number_from_sequence).and_return(2)

      # node created if we are not already a node
      expect(MiqPglogical).to receive(:new).and_return(double(:node? => false))
      expect(pglogical).to receive(:enable)
      expect(pglogical).to receive(:node_create).and_return(double(:check => nil))

      # subscription is created
      expect(pglogical).to receive(:subscription_create) do |name, dsn, replication_sets, sync_structure|
        expect(name).to eq("region_2_subscription")
        expect(dsn).to include("host='test-2.example.com'")
        expect(dsn).to include("user='root'")
        expect(replication_sets).to eq(['miq'])
        expect(sync_structure).to be false
      end.and_return(double(:check => nil))

      sub = described_class.new(:host => "test-2.example.com", :user => "root", :password => "<PASSWORD>")
      allow(sub).to receive(:assert_different_region!)

      sub.save!
    end

    it "doesnt create the node when we are already a node" do
      with_no_records
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))
      allow(MiqRegionRemote).to receive(:region_number_from_sequence).and_return(2)

      # node not created if we are already a node
      expect(MiqPglogical).to receive(:new).and_return(double(:node? => true))
      expect(pglogical).not_to receive(:enable)
      expect(pglogical).not_to receive(:node_create)

      # subscription is created
      expect(pglogical).to receive(:subscription_create) do |name, dsn, replication_sets, sync_structure|
        expect(name).to eq("region_2_subscription")
        expect(dsn).to include("host='test-2.example.com'")
        expect(dsn).to include("user='root'")
        expect(replication_sets).to eq(['miq'])
        expect(sync_structure).to be false
      end.and_return(double(:check => nil))

      sub = described_class.new(:host => "test-2.example.com", :password => "<PASSWORD>", :user => "root")
      allow(sub).to receive(:assert_different_region!)

      sub.save!
      expect(sub).to be_an_instance_of(described_class)
    end

    it "updates the dsn when an existing subscription is saved" do
      with_records
      allow(pglogical).to receive(:subscription_show_status).and_return(subscriptions.first)
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))

      sub = described_class.find(:first)
      sub.host = "other-host.example.com"
      allow(sub).to receive(:assert_different_region!)

      expect(pglogical).to receive(:subscription_disable).with(sub.id)
        .and_return(double(:check => nil))
      expect(pglogical).to receive(:node_dsn_update) do |provider_node_name, new_dsn|
        expect(provider_node_name).to eq("region_#{remote_region1}")
        expect(new_dsn).to include("host='other-host.example.com'")
        expect(new_dsn).to include("dbname='vmdb\\'s_test'")
        expect(new_dsn).to include("user='root'")
        expect(new_dsn).to include("password='<PASSWORD>\\' s\\''")
      end
      expect(pglogical).to receive(:subscription_enable).with(sub.id)
        .and_return(double(:check => nil))

      expect(sub.save!).to eq(sub)
    end

    it "reenables the subscription when the dsn fails to save" do
      with_records
      allow(pglogical).to receive(:subscription_show_status).and_return(subscriptions.first)
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))

      sub = described_class.find(:first)
      sub.host = "other-host.example.com"
      allow(sub).to receive(:assert_different_region!)

      expect(pglogical).to receive(:subscription_disable).with(sub.id)
        .and_return(double(:check => nil))
      expect(pglogical).to receive(:node_dsn_update).and_raise("Some Error")
      expect(pglogical).to receive(:subscription_enable).with(sub.id)
        .and_return(double(:check => nil))

      expect { sub.save! }.to raise_error(RuntimeError, "Some Error")
    end
  end

  describe ".delete_all" do
    let(:subscription1) { double }
    let(:subscription2) { double }

    after do
      expect(MiqQueue.where(:method_name => "restart_failover_monitor_service").count).to eq(1)
    end

    it "deletes all subscriptions if no parameter passed" do
      allow(described_class).to receive(:find).with(:all).and_return([subscription1, subscription2])
      expect(subscription1).to receive(:delete)
      expect(subscription2).to receive(:delete)
      described_class.delete_all
    end

    it "only deletes subscriptions listed in parameter if parameter passed" do
      expect(subscription1).to receive(:delete)
      expect(subscription2).not_to receive(:delete)
      described_class.delete_all([subscription1])
    end
  end

  describe ".save_all!" do
    after do
      expect(MiqQueue.where(:method_name => "restart_failover_monitor_service").count).to eq(1)
    end

    it "saves each of the objects" do
      with_no_records
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))
      allow(MiqRegionRemote).to receive(:region_number_from_sequence).and_return(2, 2, 3, 3)

      # node created
      allow(pglogical).to receive(:enable)
      allow(pglogical).to receive(:node_create).and_return(double(:check => nil))

      # subscription is created
      expect(pglogical).to receive(:subscription_create) do |name, dsn, replication_sets, sync_structure|
        expect(name).to eq("region_2_subscription")
        expect(dsn).to include("host='test-2.example.com'")
        expect(dsn).to include("user='root'")
        expect(replication_sets).to eq(['miq'])
        expect(sync_structure).to be false
      end.and_return(double(:check => nil))

      expect(pglogical).to receive(:subscription_create) do |name, dsn, replication_sets, sync_structure|
        expect(name).to eq("region_3_subscription")
        expect(dsn).to include("host='test-3.example.com'")
        expect(dsn).to include("user='miq'")
        expect(replication_sets).to eq(['miq'])
        expect(sync_structure).to be false
      end.and_return(double(:check => nil))

      to_save = []
      to_save << described_class.new(:host => "test-2.example.com", :password => "<PASSWORD>", :user => "root")
      to_save << described_class.new(:host => "test-3.example.com", :password => "<PASSWORD>", :user => "miq")
      to_save.each { |s| allow(s).to receive(:assert_different_region!) }

      described_class.save_all!(to_save)
    end

    it "raises a combined error when some saves fail" do
      with_no_records
      allow(MiqRegionRemote).to receive(:with_remote_connection).and_yield(double(:connection))
      allow(MiqRegionRemote).to receive(:region_number_from_sequence).and_return(2, 2, 3, 3, 4, 4)

      # node created
      allow(pglogical).to receive(:enable)
      allow(pglogical).to receive(:node_create).and_return(double(:check => nil))

      # subscription is created
      expect(pglogical).to receive(:subscription_create).ordered.and_raise(PG::Error.new("Error one"))
      expect(pglogical).to receive(:subscription_create) do |name, dsn, replication_sets, sync_structure|
        expect(name).to eq("region_3_subscription")
        expect(dsn).to include("host='test-3.example.com'")
        expect(dsn).to include("user='miq'")
        expect(replication_sets).to eq(['miq'])
        expect(sync_structure).to be false
      end.ordered.and_return(double(:check => nil))
      expect(pglogical).to receive(:subscription_create).ordered.and_raise("Error two")

      to_save = []
      to_save << described_class.new(:host => "test-2.example.com", :user => "root", :password => "<PASSWORD>")
      to_save << described_class.new(:host => "test-3.example.com", :user => "miq", :password => "<PASSWORD>")
{'fraction_non_alphanumeric': 0.12670708555331006, 'fraction_numerical': 0.006583379263886338, 'mean_word_length': 3.410398379473329, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 182, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6708518', 'n_tokens_mistral': 10067, 'n_tokens_neox': 9886, 'n_words': 1867}