require 'spec_helper' require 'puppet_spec/files' require 'puppet/pops' require 'puppet/loaders' describe 'dependency loader' do include PuppetSpec::Files let(:static_loader) { Puppet::Pops::Loader::StaticLoader.new() } let(:loaders) { Puppet::Pops::Loaders.new(Puppet::Node::Environment.create(:testing, [])) } describe 'FileBased module loader' do it 'prints a pretty name for itself when inspected' do module_dir = dir_containing('testmodule', { 'lib' => { 'puppet' => { 'functions' => { 'testmodule' => { 'foo.rb' => 'Puppet::Functions.create_function("foo") { def foo; end; }' }}}}}) loader = loader_for('testmodule', module_dir) expect(loader.inspect).to eq("(DependencyLoader 'test-dep' [(ModuleLoader::FileBased 'testmodule' 'testmodule')])") expect(loader.to_s).to eq("(DependencyLoader 'test-dep' [(ModuleLoader::FileBased 'testmodule' 'testmodule')])") end it 'load something in global name space raises an error' do module_dir = dir_containing('testmodule', { 'lib' => { 'puppet' => { 'functions' => { 'testmodule' => { 'foo.rb' => 'Puppet::Functions.create_function("foo") { def foo; end; }' }}}}}) loader = loader_for('testmodule', module_dir) expect do loader.load_typed(typed_name(:function, 'testmodule::foo')).value end.to raise_error(ArgumentError, /produced mis-matched name, expected 'testmodule::foo', got foo/) end it 'can load something in a qualified name space' do module_dir = dir_containing('testmodule', { 'lib' => { 'puppet' => { 'functions' => { 'testmodule' => { 'foo.rb' => 'Puppet::Functions.create_function("testmodule::foo") { def foo; end; }' }}}}}) loader = loader_for('testmodule', module_dir) function = loader.load_typed(typed_name(:function, 'testmodule::foo')).value expect(function.class.name).to eq('testmodule::foo') expect(function.is_a?(Puppet::Functions::Function)).to eq(true) end it 'can load something in a qualified name space more than once' do module_dir = dir_containing('testmodule', { 'lib' => { 'puppet' => { 'functions' => { 'testmodule' => { 'foo.rb' => 'Puppet::Functions.create_function("testmodule::foo") { def foo; end; }' }}}}}) loader = loader_for('testmodule', module_dir) function = loader.load_typed(typed_name(:function, 'testmodule::foo')).value expect(function.class.name).to eq('testmodule::foo') expect(function.is_a?(Puppet::Functions::Function)).to eq(true) function = loader.load_typed(typed_name(:function, 'testmodule::foo')).value expect(function.class.name).to eq('testmodule::foo') expect(function.is_a?(Puppet::Functions::Function)).to eq(true) end describe "when parsing files from disk" do # First line of Rune version of Rune poem at http://www.columbia.edu/~fdc/utf8/ # characters chosen since they will not parse on Windows with codepage 437 or 1252 # Section 3.2.1.3 of Ruby spec guarantees that \u strings are encoded as UTF-8 let (:node) { Puppet::Node.new('node') } let (:rune_utf8) { "\u16A0\u16C7\u16BB" } # ᚠᛇᚻ let (:code_utf8) do <<-CODE Puppet::Functions.create_function('testmodule::foo') { def foo return \"#{rune_utf8}\" end } CODE end context 'when loading files from disk' do it 'should always read files as UTF-8' do if Puppet::Util::Platform.windows? && Encoding.default_external == Encoding::UTF_8 raise 'This test must be run in a codepage other than 65001 to validate behavior' end module_dir = dir_containing('testmodule', { 'lib' => { 'puppet' => { 'functions' => { 'testmodule' => { 'foo.rb' => code_utf8 }}}}}) loader = loader_for('testmodule', module_dir) function = loader.load_typed(typed_name(:function, 'testmodule::foo')).value expect(function.call({})).to eq(rune_utf8) end it 'currently ignores the UTF-8 BOM (Byte Order Mark) when loading module files' do bom = "\uFEFF" if Puppet::Util::Platform.windows? && Encoding.default_external == Encoding::UTF_8 raise 'This test must be run in a codepage other than 65001 to validate behavior' end module_dir = dir_containing('testmodule', { 'lib' => { 'puppet' => { 'functions' => { 'testmodule' => { 'foo.rb' => "#{bom}#{code_utf8}" }}}}}) loader = loader_for('testmodule', module_dir) function = loader.load_typed(typed_name(:function, 'testmodule::foo')).value expect(function.call({})).to eq(rune_utf8) end end end end def loader_for(name, dir) module_loader = Puppet::Pops::Loader::ModuleLoaders.module_loader_from(static_loader, loaders, name, dir) Puppet::Pops::Loader::DependencyLoader.new(static_loader, 'test-dep', [module_loader], loaders.environment) end def typed_name(type, name) Puppet::Pops::Loader::TypedName.new(type, name) end end