shared_examples "a debian-like host name change" do
  it "updates /etc/hostname on the machine" do
    communicator.expect_command(%q(echo 'newhostname' > /etc/hostname))
    described_class.change_host_name(machine, 'newhostname.newdomain.tld')
  end

  it "updates mailname to prevent problems with the default mailer" do
    communicator.expect_command(%q(hostname --fqdn > /etc/mailname))
    described_class.change_host_name(machine, 'newhostname.newdomain.tld')
  end

  it "does nothing when the provided hostname is not different" do
    described_class.change_host_name(machine, 'oldhostname.olddomain.tld')
    expect(communicator.received_commands).to eq(['hostname -f'])
  end

  describe "flipping out the old hostname in /etc/hosts" do
    let(:sed_command) do
      # Here we run the change_host_name through and extract the recorded sed
      # command from the dummy communicator
      described_class.change_host_name(machine, 'newhostname.newdomain.tld')
      communicator.received_commands.find { |cmd| cmd =~ /^sed/ }
    end

    # Now we extract the regexp from that sed command so we can do some
    # verification on it
    let(:expression) { sed_command.sub(%r{^sed -ri '\(.*\)' /etc/hosts$}, "\1") }
    let(:search)     { Regexp.new(expression.split('@')[1], Regexp::EXTENDED) }
    let(:replace)    { expression.split('@')[2] }

    it "works on an simple /etc/hosts file" do
      original_etc_hosts = <<-ETC_HOSTS.gsub(/^ */, '')
        127.0.0.1 localhost
        127.0.1.1 oldhostname.olddomain.tld oldhostname
      ETC_HOSTS

      modified_etc_hosts = original_etc_hosts.gsub(search, replace)

      expect(modified_etc_hosts).to eq <<-RESULT.gsub(/^ */, '')
        127.0.0.1 localhost
        127.0.1.1 newhostname.newdomain.tld newhostname
      RESULT
    end

    it "does not modify lines which contain similar hostnames" do
      original_etc_hosts = <<-ETC_HOSTS.gsub(/^ */, '')
        127.0.0.1 localhost
        127.0.1.1 oldhostname.olddomain.tld oldhostname

        # common prefix, but different fqdn
        192.168.12.34 oldhostname.olddomain.tld.different

        # different characters at the dot
        192.168.34.56 oldhostname-olddomain.tld
      ETC_HOSTS

      modified_etc_hosts = original_etc_hosts.gsub(search, replace)

      expect(modified_etc_hosts).to eq <<-RESULT.gsub(/^ */, '')
        127.0.0.1 localhost
        127.0.1.1 newhostname.newdomain.tld newhostname

        # common prefix, but different fqdn
        192.168.12.34 oldhostname.olddomain.tld.different

        # different characters at the dot
        192.168.34.56 oldhostname-olddomain.tld
      RESULT
    end

    context "when the old fqdn has a trailing dot" do
      let(:old_hostname) { 'oldhostname.withtrailing.dot.' }

      it "modifies /etc/hosts properly" do
        original_etc_hosts = <<-ETC_HOSTS.gsub(/^ */, '')
          127.0.0.1 localhost
          127.0.1.1 oldhostname.withtrailing.dot. oldhostname
        ETC_HOSTS

        modified_etc_hosts = original_etc_hosts.gsub(search, replace)

        expect(modified_etc_hosts).to eq <<-RESULT.gsub(/^ */, '')
          127.0.0.1 localhost
          127.0.1.1 newhostname.newdomain.tld newhostname
        RESULT
      end
    end
  end
end
