# typed: false
# frozen_string_literal: true

require "extend/pathname"

RSpec.describe Pathname do
  let(:elf_dir) { ELFPathname.wrap("#{TEST_FIXTURE_DIR}/elf") }
  let(:sho) { ELFPathname.wrap(elf_dir/"libforty.so.0") }
  let(:sho_without_runpath_rpath) { ELFPathname.wrap(elf_dir/"libhello.so.0") }
  let(:exec) { ELFPathname.wrap(elf_dir/"hello_with_rpath") }

  def patch_elfs
    mktmpdir do |tmp_dir|
      %w[c.elf].each do |elf|
        FileUtils.cp(elf_dir/elf, tmp_dir/elf)
        yield ELFPathname.wrap(tmp_dir/elf)
      end
    end
  end

  describe "#interpreter" do
    it "returns interpreter" do
      expect(exec.interpreter).to eq "/lib64/ld-linux-x86-64.so.2"
      expect(sho.interpreter).to be_nil
    end
  end

  describe "#rpath" do
    it "returns rpath" do
      expect(sho.rpath).to eq "runpath"
      expect(exec.rpath).to eq "@@HOMEBREW_PREFIX@@/lib"
      expect(sho_without_runpath_rpath.rpath).to be_nil
    end
  end

  describe "#patch!" do
    let(:placeholder_prefix) { "@@HOMEBREW_PREFIX@@" }
    let(:short_prefix) { "/home/dwarf" }
    let(:standard_prefix) { "/home/linuxbrew/.linuxbrew" }
    let(:long_prefix) { "/home/organized/very organized/litter/more organized than/your words can describe" }
    let(:prefixes) { [short_prefix, standard_prefix, long_prefix].map { |prefix| ELFPathname.wrap(prefix) } }

    # file is copied as modified_elf to avoid caching issues
    it "only interpreter" do
      prefixes.each do |new_prefix|
        patch_elfs do |elf|
          interpreter = elf.interpreter.gsub(placeholder_prefix, new_prefix)
          elf.patch!(interpreter:)

          modified_elf = ELFPathname.wrap(elf.dirname/"mod.#{elf.basename}")
          FileUtils.cp(elf, modified_elf)
          expect(modified_elf.interpreter).to eq interpreter
          expect(modified_elf.rpath).to eq "@@HOMEBREW_PREFIX@@/lib"
        end
      end
    end

    it "only rpath" do
      prefixes.each do |new_prefix|
        patch_elfs do |elf|
          rpath = elf.rpath.gsub(placeholder_prefix, new_prefix)
          elf.patch!(rpath:)

          modified_elf = ELFPathname.wrap(elf.dirname/"mod.#{elf.basename}")
          FileUtils.cp(elf, modified_elf)
          expect(modified_elf.interpreter).to eq "@@HOMEBREW_PREFIX@@/lib/ld.so"
          expect(modified_elf.rpath).to eq rpath
        end
      end
    end

    it "both" do
      prefixes.each do |new_prefix|
        patch_elfs do |elf|
          interpreter = elf.interpreter.gsub(placeholder_prefix, new_prefix)
          rpath = elf.rpath.gsub(placeholder_prefix, new_prefix)
          elf.patch!(interpreter:, rpath:)

          modified_elf = ELFPathname.wrap(elf.dirname/"mod.#{elf.basename}")
          FileUtils.cp(elf, modified_elf)
          expect(modified_elf.interpreter).to eq interpreter
          expect(modified_elf.rpath).to eq rpath
        end
      end
    end
  end
end
