<commit_before>module RSpec::Puppet
  module Support

    @@cache = {}

    def subject
      lambda { catalogue }
    end

    def environment
      'rp_env'
    end

    def load_catalogue(type)
      vardir = setup_puppet

      if Puppet.version.to_f >= 4.0 or Puppet[:parser] == 'future'
        code = [pre_cond, test_manifest(type)].compact.join("\n")
      else
        code = [import_str, pre_cond, test_manifest(type)].compact.join("\n")
      end

      node_name = nodename(type)

      hiera_config_value = self.respond_to?(:hiera_config) ? hiera_config : nil

      catalogue = build_catalog(node_name, facts_hash(node_name), hiera_config_value, code)

      test_module = class_name.split('::').first
      RSpec::Puppet::Coverage.add_filter(type.to_s, self.class.description)
      RSpec::Puppet::Coverage.add_from_catalog(catalogue, test_module)

      FileUtils.rm_rf(vardir) if File.directory?(vardir)
      catalogue
    end

    def import_str
      if File.exists?(File.join(Puppet[:modulepath], 'manifests', 'init.pp'))
        path_to_manifest = File.join([
          Puppet[:modulepath],
          'manifests',
          class_name.split('::')[1..-1]
        ].flatten)
        import_str = [
          "import '#{Puppet[:modulepath]}/manifests/init.pp'",
          "import '#{path_to_manifest}.pp'",
          '',
        ].join("\n")
      elsif File.exists?(Puppet[:modulepath])
        import_str = "import '#{Puppet[:manifest]}'\n"
      else
        import_str = ""
      end

      import_str
    end

    def test_manifest(type)
      if type == :class
        if !self.respond_to?(:params) || params == {}
          "include #{class_name}"
        else
          "class { '#{class_name}': #{param_str} }"
        end
      elsif type == :define
        if self.respond_to? :params
          "#{class_name} { '#{title}': #{param_str} }"
        else
          "#{class_name} { '#{title}': }"
        end
      elsif type == :host
        nil
      end
    end

    def nodename(type)
      return node if self.respond_to?(:node)
      if [:class, :define, :function].include? type
        Puppet[:certname]
      else
        class_name
      end
    end

    def class_name
      self.class.top_level_description.downcase
    end

    def pre_cond
      if self.respond_to?(:pre_condition) && !pre_condition.nil?
        if pre_condition.is_a? Array
          pre_condition.compact.join("\n")
        else
          pre_condition
        end
      else
        nil
      end
    end

    def facts_hash(node)
      facts_val = {
        'clientversion' => Puppet::PUPPETVERSION,
        'environment'   => environment,
        'hostname'      => node.split('.').first,
        'fqdn'          => node,
        'domain'        => node.split('.', 2).last,
        'clientcert'    => node
      }

      if RSpec.configuration.default_facts.any?
        facts_val.merge!(munge_facts(RSpec.configuration.default_facts))
      end

      facts_val.merge!(munge_facts(facts)) if self.respond_to?(:facts)
      facts_val
    end

    def param_str
      params.keys.map do |r|
        param_val = escape_special_chars(params[r].inspect)
        "#{r.to_s} => #{param_val}"
      end.join(', ')
    end

    def setup_puppet
      vardir = Dir.mktmpdir
      Puppet[:vardir] = vardir

      if Puppet.version.to_f >= 4.0
        settings = [
          [:modulepath, :module_path],
          [:environmentpath, :environmentpath],
          [:config, :config],
          [:confdir, :confdir],
          [:hiera_config, :hiera_config],
          [:strict_variables, :strict_variables],
        ]
      elsif Puppet.version.to_f >= 3.0
        settings = [
          [:modulepath, :module_path],
          [:manifestdir, :manifest_dir],
          [:manifest, :manifest],
          [:templatedir, :template_dir],
          [:config, :config],
          [:confdir, :confdir],
          [:hiera_config, :hiera_config],
          [:parser, :parser],
          [:trusted_node_data, :trusted_node_data],
          [:ordering, :ordering],
          [:stringify_facts, :stringify_facts],
          [:strict_variables, :strict_variables],
        ]
      else
        settings = [
          [:modulepath, :module_path],
          [:manifestdir, :manifest_dir],
          [:manifest, :manifest],
          [:templatedir, :template_dir],
          [:config, :config],
          [:confdir, :confdir],
        ]
      end
      settings.each do |a,b|
        value = self.respond_to?(b) ? self.send(b) : RSpec.configuration.send(b)
        begin
          Puppet[a] = value
        rescue ArgumentError
          Puppet.settings.setdefaults(:main, {a => {:default => value, :desc => a.to_s}})
        end
      end

      Dir["#{Puppet[:modulepath]}/*/lib"].entries.each do |lib|
        $LOAD_PATH << lib
      end

      vardir
    end

    def build_catalog_without_cache(nodename, facts_val, hiera_config_val, code)

      # If we're going to rebuild the catalog, we should clear the cached instance
      # of Hiera that Puppet is using.  This opens the possibility of the catalog
      # now being rebuilt against a differently configured Hiera (i.e. :hiera_config
      # set differently in one example group vs. another).
      # It would be nice if Puppet offered a public API for invalidating their
      # cached instance of Hiera, but que sera sera.  We will go directly against
      # the implementation out of absolute necessity.
      HieraPuppet.instance_variable_set('@hiera', nil) if defined? HieraPuppet

      Puppet[:code] = code

      stub_facts! facts_val

      node_obj = Puppet::Node.new(nodename)

      node_obj.merge(facts_val)
<commit_msg>Fix import_str for multiple module paths<commit_after>module RSpec::Puppet
  module Support

    @@cache = {}

    def subject
      lambda { catalogue }
    end

    def environment
      'rp_env'
    end

    def load_catalogue(type)
      vardir = setup_puppet

      if Puppet.version.to_f >= 4.0 or Puppet[:parser] == 'future'
        code = [pre_cond, test_manifest(type)].compact.join("\n")
      else
        code = [import_str, pre_cond, test_manifest(type)].compact.join("\n")
      end

      node_name = nodename(type)

      hiera_config_value = self.respond_to?(:hiera_config) ? hiera_config : nil

      catalogue = build_catalog(node_name, facts_hash(node_name), hiera_config_value, code)

      test_module = class_name.split('::').first
      RSpec::Puppet::Coverage.add_filter(type.to_s, self.class.description)
      RSpec::Puppet::Coverage.add_from_catalog(catalogue, test_module)

      FileUtils.rm_rf(vardir) if File.directory?(vardir)
      catalogue
    end

    def import_str
      import_str = ""
      Puppet[:modulepath].split(File::PATH_SEPARATOR).each { |d|
        if File.exists?(File.join(d, 'manifests', 'init.pp'))
          path_to_manifest = File.join([
            d,
            'manifests',
            class_name.split('::')[1..-1]
          ].flatten)
          import_str = [
            "import '#{d}/manifests/init.pp'",
            "import '#{path_to_manifest}.pp'",
            '',
          ].join("\n")
          break
        elsif File.exists?(d)
          import_str = "import '#{Puppet[:manifest]}'\n"
          break
        end
      }

      import_str
    end

    def test_manifest(type)
      if type == :class
        if !self.respond_to?(:params) || params == {}
          "include #{class_name}"
        else
          "class { '#{class_name}': #{param_str} }"
        end
      elsif type == :define
        if self.respond_to? :params
          "#{class_name} { '#{title}': #{param_str} }"
        else
          "#{class_name} { '#{title}': }"
        end
      elsif type == :host
        nil
      end
    end

    def nodename(type)
      return node if self.respond_to?(:node)
      if [:class, :define, :function].include? type
        Puppet[:certname]
      else
        class_name
      end
    end

    def class_name
      self.class.top_level_description.downcase
    end

    def pre_cond
      if self.respond_to?(:pre_condition) && !pre_condition.nil?
        if pre_condition.is_a? Array
          pre_condition.compact.join("\n")
        else
          pre_condition
        end
      else
        nil
      end
    end

    def facts_hash(node)
      facts_val = {
        'clientversion' => Puppet::PUPPETVERSION,
        'environment'   => environment,
        'hostname'      => node.split('.').first,
        'fqdn'          => node,
        'domain'        => node.split('.', 2).last,
        'clientcert'    => node
      }

      if RSpec.configuration.default_facts.any?
        facts_val.merge!(munge_facts(RSpec.configuration.default_facts))
      end

      facts_val.merge!(munge_facts(facts)) if self.respond_to?(:facts)
      facts_val
    end

    def param_str
      params.keys.map do |r|
        param_val = escape_special_chars(params[r].inspect)
        "#{r.to_s} => #{param_val}"
      end.join(', ')
    end

    def setup_puppet
      vardir = Dir.mktmpdir
      Puppet[:vardir] = vardir

      if Puppet.version.to_f >= 4.0
        settings = [
          [:modulepath, :module_path],
          [:environmentpath, :environmentpath],
          [:config, :config],
          [:confdir, :confdir],
          [:hiera_config, :hiera_config],
          [:strict_variables, :strict_variables],
        ]
      elsif Puppet.version.to_f >= 3.0
        settings = [
          [:modulepath, :module_path],
          [:manifestdir, :manifest_dir],
          [:manifest, :manifest],
          [:templatedir, :template_dir],
          [:config, :config],
          [:confdir, :confdir],
          [:hiera_config, :hiera_config],
          [:parser, :parser],
          [:trusted_node_data, :trusted_node_data],
          [:ordering, :ordering],
          [:stringify_facts, :stringify_facts],
          [:strict_variables, :strict_variables],
        ]
      else
        settings = [
          [:modulepath, :module_path],
          [:manifestdir, :manifest_dir],
          [:manifest, :manifest],
          [:templatedir, :template_dir],
          [:config, :config],
          [:confdir, :confdir],
        ]
      end
      settings.each do |a,b|
        value = self.respond_to?(b) ? self.send(b) : RSpec.configuration.send(b)
        begin
          Puppet[a] = value
        rescue ArgumentError
          Puppet.settings.setdefaults(:main, {a => {:default => value, :desc => a.to_s}})
        end
      end

      Puppet[:modulepath].split(File::PATH_SEPARATOR).map do |d|
        Dir["#{d}/*/lib"].entries
      end.flatten.each do |lib|
        $LOAD_PATH << lib
      end

      vardir
    end

    def build_catalog_without_cache(nodename, facts_val, hiera_config_val, code)

      # If we're going to rebuild the catalog, we should clear the cached instance
      # of Hiera that Puppet is using.  This opens the possibility of the catalog
      # now being rebuilt against a differently configured Hiera (i.e. :hiera_config
      # set differently in one example group vs. another).
      # It would be nice if Puppet offered a public API for invalidating their
      # cached instance of Hiera, but que sera sera.  We will go directly against
      # the implementation out of absolute necessity.
      HieraPuppet.instance_variable_set('@hiera', nil) if defined? HieraPuppet

      Puppet[:code] = code

      stub_facts! facts_val

      node_obj = Puppet::Node.new(nodename)

      node_obj.merge(facts_val)

{'fraction_non_alphanumeric': 0.12293514171448444, 'fraction_numerical': 0.001564945226917058, 'mean_word_length': 2.146334792122538, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 29, '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': '5080295', 'n_tokens_mistral': 3759, 'n_tokens_neox': 3583, 'n_words': 762}