<commit_before>#
# Author:: <NAME> (<EMAIL>)
#
# Copyright:: Copyright 2009-2016, <NAME>
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

module GemspecBackcompatCreator
  def gemspec(name, version)
    if Gem::Specification.new.method(:initialize).arity == 0
      Gem::Specification.new { |s| s.name = name; s.version = version }
    else
      Gem::Specification.new(name, version)
    end
  end
end

# this is a global variable we construct of the highest rspec-core version which is installed, using APIs which
# will break out of the bundle -- and done this way so that we can mock all these internal Gem APIs later...
class RspecVersionString
  def self.rspec_version_string
    @rspec_version_string ||= begin
                                stubs = Gem::Specification.send(:installed_stubs, Gem::Specification.dirs, "rspec-core-*.gemspec")
                                stubs.select! { |stub| stub.name == "rspec-core" && Gem::Dependency.new("rspec-core", ">= 0").requirement.satisfied_by?(stub.version) }
                                stubs.max_by(&:version).version.to_s
                              end
  end
end
RspecVersionString.rspec_version_string

require "spec_helper"
require "ostruct"

describe Chef::Provider::Package::Rubygems::CurrentGemEnvironment do
  include GemspecBackcompatCreator

  let(:logger) { double("Mixlib::Log::Child").as_null_object }
  before do
    @gem_env = Chef::Provider::Package::Rubygems::CurrentGemEnvironment.new
    allow(@gem_env).to receive(:logger).and_return(logger)
  end

  it "determines the gem paths from the in memory rubygems" do
    expect(@gem_env.gem_paths).to eq(Gem.path)
  end

  it "determines the installed versions of gems from Gem.source_index" do
    gems = [gemspec("rspec-core", Gem::Version.new("1.2.9")), gemspec("rspec-core", Gem::Version.new("1.3.0"))]
    if Gem::Version.new(Gem::VERSION) >= Gem::Version.new("2.7")
      expect(Gem::Specification).to receive(:dirs).and_return(["/path/to/gems/specifications", "/another/path/to/gems/specifications"])
      expect(Gem::Specification).to receive(:installed_stubs).with(["/path/to/gems/specifications", "/another/path/to/gems/specifications"], "rspec-core-*.gemspec").and_return(gems)
    elsif Gem::Version.new(Gem::VERSION) >= Gem::Version.new("1.8.0")
      expect(Gem::Specification).to receive(:find_all_by_name).with("rspec-core", Gem::Dependency.new("rspec-core").requirement).and_return(gems)
    else
      expect(Gem.source_index).to receive(:search).with(Gem::Dependency.new("rspec-core", nil)).and_return(gems)
    end
    expect(@gem_env.installed_versions(Gem::Dependency.new("rspec-core", nil))).to eq(gems)
  end

  it "determines the installed versions of gems from the source index (part2: the unmockening)" do
    expected = ["rspec-core", Gem::Version.new( RspecVersionString.rspec_version_string )]
    actual = @gem_env.installed_versions(Gem::Dependency.new("rspec-core", nil)).map { |spec| [spec.name, spec.version] }
    expect(actual).to include(expected)
  end

  it "yields to a block with an alternate source list set" do
    sources_in_block = nil
    normal_sources = Gem.sources
    begin
      @gem_env.with_gem_sources("http://gems.example.org") do
        sources_in_block = Gem.sources
        raise "sources should be reset even in case of an error"
      end
    rescue RuntimeError
    end
    expect(sources_in_block).to eq(%w{http://gems.example.org})
    expect(Gem.sources).to eq(normal_sources)
  end

  it "it doesnt alter the gem sources if none are set" do
    sources_in_block = nil
    normal_sources = Gem.sources
    begin
      @gem_env.with_gem_sources(nil) do
        sources_in_block = Gem.sources
        raise "sources should be reset even in case of an error"
      end
    rescue RuntimeError
    end
    expect(sources_in_block).to eq(normal_sources)
    expect(Gem.sources).to eq(normal_sources)
  end

  context "new default rubygems behavior" do
    around do |example|
      original_value = Gem.configuration.ssl_verify_mode
      Gem.configuration.instance_variable_set("@ssl_verify_mode", OpenSSL::SSL::VERIFY_NONE)

      example.run

      Gem.configuration.instance_variable_set("@ssl_verify_mode", original_value)
    end

    before do
      Chef::Config[:rubygems_cache_enabled] = false

      dep_installer = Gem::DependencyInstaller.new
      expect(dep_installer).not_to receive(:find_gems_with_sources)
      allow(@gem_env).to receive(:dependency_installer).and_return(dep_installer)
    end

    it "finds a matching gem candidate version on rubygems 2.0.0+" do
      dep = Gem::Dependency.new("rspec", ">= 0")
      expect(@gem_env.candidate_version_from_remote(dep)).to be_kind_of(Gem::Version)
    end

    it "gives the candidate version as nil if none is found" do
      dep = Gem::Dependency.new("lksdjflksdjflsdkfj", ">= 0")
      expect(@gem_env.candidate_version_from_remote(dep)).to be_nil
    end

    it "finds a matching gem from a specific gemserver when explicit sources are given (to a server that doesn't respond to api requests)" do
      dep = Gem::Dependency.new("rspec", ">= 0")
      expect(@gem_env.candidate_version_from_remote(dep, "http://production.cf.rubygems.org")).to be_kind_of(Gem::Version)
    end<commit_msg>Workaround SSL cert verification failure in test.<commit_after>#
# Author:: <NAME> (<EMAIL>)
#
# Copyright:: Copyright 2009-2016, <NAME>
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

module GemspecBackcompatCreator
  def gemspec(name, version)
    if Gem::Specification.new.method(:initialize).arity == 0
      Gem::Specification.new { |s| s.name = name; s.version = version }
    else
      Gem::Specification.new(name, version)
    end
  end
end

# this is a global variable we construct of the highest rspec-core version which is installed, using APIs which
# will break out of the bundle -- and done this way so that we can mock all these internal Gem APIs later...
class RspecVersionString
  def self.rspec_version_string
    @rspec_version_string ||= begin
                                stubs = Gem::Specification.send(:installed_stubs, Gem::Specification.dirs, "rspec-core-*.gemspec")
                                stubs.select! { |stub| stub.name == "rspec-core" && Gem::Dependency.new("rspec-core", ">= 0").requirement.satisfied_by?(stub.version) }
                                stubs.max_by(&:version).version.to_s
                              end
  end
end
RspecVersionString.rspec_version_string

require "spec_helper"
require "ostruct"

describe Chef::Provider::Package::Rubygems::CurrentGemEnvironment do
  include GemspecBackcompatCreator

  let(:logger) { double("Mixlib::Log::Child").as_null_object }
  before do
    @gem_env = Chef::Provider::Package::Rubygems::CurrentGemEnvironment.new
    allow(@gem_env).to receive(:logger).and_return(logger)
  end

  it "determines the gem paths from the in memory rubygems" do
    expect(@gem_env.gem_paths).to eq(Gem.path)
  end

  it "determines the installed versions of gems from Gem.source_index" do
    gems = [gemspec("rspec-core", Gem::Version.new("1.2.9")), gemspec("rspec-core", Gem::Version.new("1.3.0"))]
    if Gem::Version.new(Gem::VERSION) >= Gem::Version.new("2.7")
      expect(Gem::Specification).to receive(:dirs).and_return(["/path/to/gems/specifications", "/another/path/to/gems/specifications"])
      expect(Gem::Specification).to receive(:installed_stubs).with(["/path/to/gems/specifications", "/another/path/to/gems/specifications"], "rspec-core-*.gemspec").and_return(gems)
    elsif Gem::Version.new(Gem::VERSION) >= Gem::Version.new("1.8.0")
      expect(Gem::Specification).to receive(:find_all_by_name).with("rspec-core", Gem::Dependency.new("rspec-core").requirement).and_return(gems)
    else
      expect(Gem.source_index).to receive(:search).with(Gem::Dependency.new("rspec-core", nil)).and_return(gems)
    end
    expect(@gem_env.installed_versions(Gem::Dependency.new("rspec-core", nil))).to eq(gems)
  end

  it "determines the installed versions of gems from the source index (part2: the unmockening)" do
    expected = ["rspec-core", Gem::Version.new( RspecVersionString.rspec_version_string )]
    actual = @gem_env.installed_versions(Gem::Dependency.new("rspec-core", nil)).map { |spec| [spec.name, spec.version] }
    expect(actual).to include(expected)
  end

  it "yields to a block with an alternate source list set" do
    sources_in_block = nil
    normal_sources = Gem.sources
    begin
      @gem_env.with_gem_sources("http://gems.example.org") do
        sources_in_block = Gem.sources
        raise "sources should be reset even in case of an error"
      end
    rescue RuntimeError
    end
    expect(sources_in_block).to eq(%w{http://gems.example.org})
    expect(Gem.sources).to eq(normal_sources)
  end

  it "it doesnt alter the gem sources if none are set" do
    sources_in_block = nil
    normal_sources = Gem.sources
    begin
      @gem_env.with_gem_sources(nil) do
        sources_in_block = Gem.sources
        raise "sources should be reset even in case of an error"
      end
    rescue RuntimeError
    end
    expect(sources_in_block).to eq(normal_sources)
    expect(Gem.sources).to eq(normal_sources)
  end

  context "new default rubygems behavior" do
    # Workaround an SSL failure that came up connecting to "http://production.cf.rubygems.org"
    # Gem::RemoteFetcher::FetchError:
    #   SSL_connect returned=1 errno=0 state=error: certificate verify failed (certificate rejected) (https://production.cf.rubygems.org/api/v1/dependencies?gems=rspec)
    #
    around do |example|
      original_value = Gem.configuration.ssl_verify_mode
      Gem.configuration.instance_variable_set("@ssl_verify_mode", OpenSSL::SSL::VERIFY_NONE)

      example.run

      Gem.configuration.instance_variable_set("@ssl_verify_mode", original_value)
    end

    before do
      Chef::Config[:rubygems_cache_enabled] = false

      dep_installer = Gem::DependencyInstaller.new
      expect(dep_installer).not_to receive(:find_gems_with_sources)
      allow(@gem_env).to receive(:dependency_installer).and_return(dep_installer)
    end

    it "finds a matching gem candidate version on rubygems 2.0.0+" do
      dep = Gem::Dependency.new("rspec", ">= 0")
      expect(@gem_env.candidate_version_from_remote(dep)).to be_kind_of(Gem::Version)
    end

    it "gives the candidate version as nil if none is found" do
      dep = Gem::Dependency.new("lksdjflksdjflsdkfj", ">= 0")
      expect(@gem_env.candidate_version_from_remote(dep)).to be_nil
    end

    it "finds a matching gem from a specific gemserver when explicit sources are given (to a server that doesn't respond to api requests)" do
      dep = Gem::Dependency.new("rspec", ">= 0")
      expect(@gem_env.candidate_version_from_remote(dep, "http://production.cf.rubygems.org")).to be_kind_of(Gem::Version)
    end
{'fraction_non_alphanumeric': 0.11704088471849866, 'fraction_numerical': 0.005948391420911528, 'mean_word_length': 3.8682707993474716, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 21, 'https://': 1, 'lorem ipsum': 0, 'www.': 2, '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': '3509938', 'n_tokens_mistral': 3762, 'n_tokens_neox': 3635, 'n_words': 920}