puppet 5.1.0-x64-mingw32 → 5.2.0-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/lib/puppet.rb +6 -53
- data/lib/puppet/application.rb +14 -7
- data/lib/puppet/application/agent.rb +6 -2
- data/lib/puppet/application/apply.rb +6 -2
- data/lib/puppet/application/cert.rb +6 -2
- data/lib/puppet/application/describe.rb +6 -2
- data/lib/puppet/application/device.rb +40 -29
- data/lib/puppet/application/doc.rb +6 -2
- data/lib/puppet/application/filebucket.rb +6 -2
- data/lib/puppet/application/lookup.rb +6 -2
- data/lib/puppet/application/master.rb +6 -2
- data/lib/puppet/application/resource.rb +6 -2
- data/lib/puppet/face/catalog.rb +1 -1
- data/lib/puppet/face/certificate_request.rb +1 -1
- data/lib/puppet/face/certificate_revocation_list.rb +1 -1
- data/lib/puppet/face/help.rb +17 -13
- data/lib/puppet/file_serving/configuration.rb +3 -0
- data/lib/puppet/file_serving/configuration/parser.rb +2 -0
- data/lib/puppet/file_serving/mount/tasks.rb +21 -0
- data/lib/puppet/functions/epp.rb +3 -0
- data/lib/puppet/functions/lookup.rb +2 -1
- data/lib/puppet/generate/models/type/property.rb +1 -1
- data/lib/puppet/gettext/config.rb +70 -0
- data/lib/puppet/gettext/stubs.rb +11 -0
- data/lib/puppet/indirector/request.rb +4 -4
- data/lib/puppet/info_service.rb +10 -0
- data/lib/puppet/info_service/task_information_service.rb +32 -0
- data/lib/puppet/module.rb +43 -12
- data/lib/puppet/module/task.rb +90 -0
- data/lib/puppet/parser/ast/leaf.rb +1 -1
- data/lib/puppet/parser/functions/dig.rb +11 -2
- data/lib/puppet/parser/functions/epp.rb +3 -0
- data/lib/puppet/parser/functions/new.rb +8 -8
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +1 -1
- data/lib/puppet/pops/evaluator/runtime3_support.rb +1 -0
- data/lib/puppet/pops/issues.rb +11 -5
- data/lib/puppet/pops/loader/static_loader.rb +1 -1
- data/lib/puppet/pops/model/factory.rb +42 -2
- data/lib/puppet/pops/model/model_tree_dumper.rb +1 -1
- data/lib/puppet/pops/parser/egrammar.ra +30 -9
- data/lib/puppet/pops/parser/eparser.rb +1094 -1043
- data/lib/puppet/pops/patterns.rb +1 -1
- data/lib/puppet/pops/serialization/from_data_converter.rb +1 -1
- data/lib/puppet/pops/serialization/json_path.rb +1 -1
- data/lib/puppet/pops/serialization/to_data_converter.rb +12 -3
- data/lib/puppet/pops/types/p_object_type.rb +31 -3
- data/lib/puppet/pops/types/p_sem_ver_range_type.rb +3 -3
- data/lib/puppet/pops/types/p_timespan_type.rb +1 -1
- data/lib/puppet/pops/types/p_timestamp_type.rb +1 -1
- data/lib/puppet/pops/types/string_converter.rb +15 -12
- data/lib/puppet/pops/types/type_calculator.rb +1 -1
- data/lib/puppet/pops/types/type_factory.rb +7 -0
- data/lib/puppet/pops/types/type_formatter.rb +1 -1
- data/lib/puppet/pops/types/type_mismatch_describer.rb +86 -130
- data/lib/puppet/pops/types/type_parser.rb +10 -4
- data/lib/puppet/pops/types/types.rb +81 -22
- data/lib/puppet/provider/package/aix.rb +4 -4
- data/lib/puppet/provider/package/yum.rb +1 -0
- data/lib/puppet/type.rb +1 -1
- data/lib/puppet/type/mount.rb +1 -1
- data/lib/puppet/type/sshkey.rb +9 -1
- data/lib/puppet/util.rb +1 -1
- data/lib/puppet/util/command_line.rb +1 -1
- data/lib/puppet/util/log.rb +15 -10
- data/lib/puppet/util/windows/api_types.rb +9 -5
- data/lib/puppet/util/windows/process.rb +9 -1
- data/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet.rb +1 -3
- data/lib/puppet/version.rb +1 -1
- data/locales/ja/puppet.po +9270 -0
- data/locales/puppet.pot +272 -212
- data/spec/fixtures/unit/provider/package/yum/yum-check-update-plugin-output.txt +36 -0
- data/spec/integration/indirector/file_content/file_server_spec.rb +17 -0
- data/spec/integration/indirector/file_metadata/file_server_spec.rb +10 -0
- data/spec/integration/util/windows/process_spec.rb +45 -0
- data/spec/lib/puppet_spec/modules.rb +10 -0
- data/spec/shared_contexts/types_setup.rb +19 -4
- data/spec/spec_helper.rb +6 -7
- data/spec/unit/face/help_spec.rb +2 -2
- data/spec/unit/file_serving/configuration_spec.rb +14 -4
- data/spec/unit/file_serving/mount/modules_spec.rb +1 -1
- data/spec/unit/file_serving/mount/tasks_spec.rb +72 -0
- data/spec/unit/functions/epp_spec.rb +5 -0
- data/spec/unit/functions/regsubst_spec.rb +1 -1
- data/spec/unit/gettext_config_spec.rb +57 -0
- data/spec/unit/indirector/request_spec.rb +41 -0
- data/spec/unit/info_service_spec.rb +66 -2
- data/spec/unit/module_spec.rb +81 -1
- data/spec/unit/parser/ast/leaf_spec.rb +3 -4
- data/spec/unit/pops/evaluator/access_ops_spec.rb +5 -0
- data/spec/unit/pops/factory_spec.rb +5 -1
- data/spec/unit/pops/parser/parser_spec.rb +138 -0
- data/spec/unit/pops/serialization/to_from_hr_spec.rb +74 -1
- data/spec/unit/pops/types/p_init_type_spec.rb +1 -1
- data/spec/unit/pops/types/p_object_type_spec.rb +217 -33
- data/spec/unit/pops/types/p_timespan_type_spec.rb +7 -0
- data/spec/unit/pops/types/p_timestamp_type_spec.rb +7 -0
- data/spec/unit/pops/types/string_converter_spec.rb +48 -11
- data/spec/unit/pops/types/type_calculator_spec.rb +37 -5
- data/spec/unit/pops/types/type_mismatch_describer_spec.rb +12 -0
- data/spec/unit/pops/types/type_parser_spec.rb +25 -0
- data/spec/unit/pops/validator/validator_spec.rb +2 -2
- data/spec/unit/provider/package/aix_spec.rb +26 -1
- data/spec/unit/provider/package/yum_spec.rb +10 -0
- data/spec/unit/task_spec.rb +102 -0
- data/spec/unit/util/log_spec.rb +32 -3
- data/spec/unit/util/windows/api_types_spec.rb +51 -0
- metadata +3488 -3452
- checksums.yaml +0 -7
@@ -862,22 +862,53 @@ describe 'The type calculator' do
|
|
862
862
|
context 'for Data, such that' do
|
863
863
|
let(:data) { TypeFactory.data }
|
864
864
|
data_compatible_types.map { |t2| type_from_class(t2) }.each do |tc|
|
865
|
-
it "#{tc.name}
|
865
|
+
it "it is assignable from #{tc.name}" do
|
866
866
|
expect(tc).to be_assignable_to(data)
|
867
867
|
end
|
868
868
|
end
|
869
869
|
|
870
|
-
|
870
|
+
data_compatible_types.map { |t2| type_from_class(t2) }.each do |tc|
|
871
|
+
it "it is assignable from Optional[#{tc.name}]" do
|
872
|
+
expect(optional_t(tc)).to be_assignable_to(data)
|
873
|
+
end
|
874
|
+
end
|
875
|
+
|
876
|
+
it 'it is not assignable to any of its subtypes' do
|
871
877
|
types_to_test = data_compatible_types
|
872
878
|
types_to_test.each {|t2| expect(data).not_to be_assignable_to(type_from_class(t2)) }
|
873
879
|
end
|
874
880
|
|
875
|
-
it '
|
876
|
-
tested_types = all_types - [PAnyType, POptionalType, PInitType] -
|
881
|
+
it 'it is not assignable to any disjunct type' do
|
882
|
+
tested_types = all_types - [PAnyType, POptionalType, PInitType] - scalar_data_types
|
877
883
|
tested_types.each {|t2| expect(data).not_to be_assignable_to(t2::DEFAULT) }
|
878
884
|
end
|
879
885
|
end
|
880
886
|
|
887
|
+
context 'for Rich Data, such that' do
|
888
|
+
let(:rich_data) { TypeFactory.rich_data }
|
889
|
+
rich_data_compatible_types.map { |t2| type_from_class(t2) }.each do |tc|
|
890
|
+
it "it is assignable from #{tc.name}" do
|
891
|
+
expect(tc).to be_assignable_to(rich_data)
|
892
|
+
end
|
893
|
+
end
|
894
|
+
|
895
|
+
rich_data_compatible_types.map { |t2| type_from_class(t2) }.each do |tc|
|
896
|
+
it "it is assignable from Optional[#{tc.name}]" do
|
897
|
+
expect(optional_t(tc)).to be_assignable_to(rich_data)
|
898
|
+
end
|
899
|
+
end
|
900
|
+
|
901
|
+
it 'it is not assignable to any of its subtypes' do
|
902
|
+
types_to_test = rich_data_compatible_types
|
903
|
+
types_to_test.each {|t2| expect(rich_data).not_to be_assignable_to(type_from_class(t2)) }
|
904
|
+
end
|
905
|
+
|
906
|
+
it 'it is not assignable to any disjunct type' do
|
907
|
+
tested_types = all_types - [PAnyType, POptionalType, PInitType] - scalar_types
|
908
|
+
tested_types.each {|t2| expect(rich_data).not_to be_assignable_to(t2::DEFAULT) }
|
909
|
+
end
|
910
|
+
end
|
911
|
+
|
881
912
|
context 'for Variant, such that' do
|
882
913
|
it 'it is assignable to a type if all contained types are assignable to that type' do
|
883
914
|
v = variant_t(range_t(10, 12),range_t(14, 20))
|
@@ -1744,11 +1775,12 @@ describe 'The type calculator' do
|
|
1744
1775
|
expect(calculator.instance?(PAnyType::DEFAULT, :default)).to eq(true)
|
1745
1776
|
end
|
1746
1777
|
|
1747
|
-
it 'should not consider "default" to be an instance of anything but Default, NotUndef, and Any' do
|
1778
|
+
it 'should not consider "default" to be an instance of anything but Default, Init, NotUndef, and Any' do
|
1748
1779
|
types_to_test = all_types - [
|
1749
1780
|
PAnyType,
|
1750
1781
|
PNotUndefType,
|
1751
1782
|
PDefaultType,
|
1783
|
+
PInitType,
|
1752
1784
|
]
|
1753
1785
|
|
1754
1786
|
types_to_test.each {|t| expect(calculator.instance?(t::DEFAULT, :default)).to eq(false) }
|
@@ -223,6 +223,18 @@ describe 'the type mismatch describer' do
|
|
223
223
|
expect(subject.describe_signatures('function', [dispatch], args_tuple)).to eq("'function' block return expects a String value, got Integer")
|
224
224
|
end
|
225
225
|
end
|
226
|
+
|
227
|
+
it "reports struct mismatch correctly when hash doesn't contain required keys" do
|
228
|
+
code = <<-PUPPET
|
229
|
+
type Test::Options = Struct[{
|
230
|
+
var => String
|
231
|
+
}]
|
232
|
+
class test(String $var, Test::Options $opts) {}
|
233
|
+
class { 'test': var => 'hello', opts => {} }
|
234
|
+
PUPPET
|
235
|
+
expect { eval_and_collect_notices(code) }.to(raise_error(Puppet::Error,
|
236
|
+
/Class\[Test\]: parameter 'opts' expects size to be 1, got 0/))
|
237
|
+
end
|
226
238
|
end
|
227
239
|
end
|
228
240
|
end
|
@@ -30,6 +30,11 @@ describe TypeParser do
|
|
30
30
|
/The expression <Array\[notAType\]> is not a valid type specification/)
|
31
31
|
end
|
32
32
|
|
33
|
+
it "rejects an unknown type parameter in a variant" do
|
34
|
+
expect { parser.parse("Variant[Integer,'not a type']") }.to raise_error(Puppet::ParseError,
|
35
|
+
/The expression <Variant\[Integer,'not a type'\]> is not a valid type specification/)
|
36
|
+
end
|
37
|
+
|
33
38
|
[
|
34
39
|
'Any', 'Data', 'CatalogEntry', 'Boolean', 'Scalar', 'Undef', 'Numeric', 'Default'
|
35
40
|
].each do |name|
|
@@ -371,6 +376,26 @@ describe TypeParser do
|
|
371
376
|
expect(t.type_string).to eql('Nonesuch[{a=>undef,b=>true,c=>false,d=>default,e=>"string",f=>0,g=>1.0,h=>[1,2,3]}]')
|
372
377
|
end
|
373
378
|
|
379
|
+
it 'parses a parameterized Enum using identifiers' do
|
380
|
+
t = parser.parse('Enum[a, b]')
|
381
|
+
expect(t).to be_a(PEnumType)
|
382
|
+
expect(t.to_s).to eql("Enum['a', 'b']")
|
383
|
+
end
|
384
|
+
|
385
|
+
it 'parses a parameterized Enum using strings' do
|
386
|
+
t = parser.parse("Enum['a', 'b']")
|
387
|
+
expect(t).to be_a(PEnumType)
|
388
|
+
expect(t.to_s).to eql("Enum['a', 'b']")
|
389
|
+
end
|
390
|
+
|
391
|
+
it 'rejects a parameterized Enum using type refs' do
|
392
|
+
expect { parser.parse('Enum[A, B]') }.to raise_error(/Enum parameters must be identifiers or strings/)
|
393
|
+
end
|
394
|
+
|
395
|
+
it 'rejects a parameterized Enum using integers' do
|
396
|
+
expect { parser.parse('Enum[1, 2]') }.to raise_error(/Enum parameters must be identifiers or strings/)
|
397
|
+
end
|
398
|
+
|
374
399
|
matcher :be_the_type do |type|
|
375
400
|
calc = TypeCalculator.new
|
376
401
|
|
@@ -472,12 +472,12 @@ describe "validating 4x" do
|
|
472
472
|
context 'that are type aliases' do
|
473
473
|
it 'raises errors when RHS is a name that is an invalid reference' do
|
474
474
|
source = 'type MyInt = integer'
|
475
|
-
expect
|
475
|
+
expect { parse(source) }.to raise_error(/Syntax error at 'integer'/)
|
476
476
|
end
|
477
477
|
|
478
478
|
it 'raises errors when RHS is an AccessExpression with a name that is an invalid reference on LHS' do
|
479
479
|
source = 'type IntegerArray = array[Integer]'
|
480
|
-
expect
|
480
|
+
expect { parse(source) }.to raise_error(/Syntax error at 'array'/)
|
481
481
|
end
|
482
482
|
end
|
483
483
|
|
@@ -25,7 +25,6 @@ describe provider_class do
|
|
25
25
|
|
26
26
|
describe "when installing" do
|
27
27
|
it "should install a package" do
|
28
|
-
@resource.stubs(:should).with(:ensure).returns(:installed)
|
29
28
|
@provider.expects(:installp).with('-acgwXY', '-d', 'mysource', 'mypackage')
|
30
29
|
@provider.install
|
31
30
|
end
|
@@ -98,10 +97,36 @@ mypackage 1.2.3.3 Already superseded by 1.2.3.4
|
|
98
97
|
@provider.stubs(:latest_info).returns( { :version => "1.2.3.5" } )
|
99
98
|
expect(@provider.latest).to eq("1.2.3.5")
|
100
99
|
end
|
100
|
+
|
101
|
+
it "should prefetch the right values" do
|
102
|
+
Process.stubs(:euid).returns(0)
|
103
|
+
resource = Puppet::Type.type(:package).
|
104
|
+
new(:name => 'sudo.rte', :ensure => :latest,
|
105
|
+
:source => 'mysource', :provider => :aix)
|
106
|
+
|
107
|
+
resource.stubs(:should).with(:ensure).returns(:latest)
|
108
|
+
resource.should(:ensure)
|
109
|
+
|
110
|
+
resource.provider.class.stubs(:execute).returns(<<-END.chomp)
|
111
|
+
sudo:sudo.rte:1.7.10.4::I:C:::::N:Configurable super-user privileges runtime::::0::
|
112
|
+
sudo:sudo.rte:1.8.6.4::I:T:::::N:Configurable super-user privileges runtime::::0::
|
113
|
+
END
|
114
|
+
|
115
|
+
resource.provider.class.prefetch('sudo.rte' => resource)
|
116
|
+
expect(resource.provider.latest).to eq('1.8.6.4')
|
117
|
+
end
|
101
118
|
end
|
102
119
|
|
103
120
|
it "update should install a package" do
|
104
121
|
@provider.expects(:install).with(false)
|
105
122
|
@provider.update
|
106
123
|
end
|
124
|
+
|
125
|
+
it "should prefetch when some packages lack sources" do
|
126
|
+
latest = Puppet::Type.type(:package).new(:name => 'mypackage', :ensure => :latest, :source => 'mysource', :provider => :aix)
|
127
|
+
absent = Puppet::Type.type(:package).new(:name => 'otherpackage', :ensure => :absent, :provider => :aix)
|
128
|
+
Process.stubs(:euid).returns(0)
|
129
|
+
provider_class.expects(:execute).returns 'mypackage:mypackage.rte:1.8.6.4::I:T:::::N:A Super Cool Package::::0::\n'
|
130
|
+
provider_class.prefetch({ 'mypackage' => latest, 'otherpackage' => absent })
|
131
|
+
end
|
107
132
|
end
|
@@ -69,5 +69,15 @@ describe provider_class do
|
|
69
69
|
}.to raise_exception(Exception, /Failed to parse/)
|
70
70
|
end
|
71
71
|
end
|
72
|
+
describe "with trailing plugin output" do
|
73
|
+
let(:check_update) { File.read(my_fixture("yum-check-update-plugin-output.txt")) }
|
74
|
+
let(:output) { described_class.parse_updates(check_update) }
|
75
|
+
it "parses correctly formatted entries" do
|
76
|
+
expect(output['bash']).to eq([{:name => 'bash', :epoch => '0', :version => '4.2.46', :release => '12.el7', :arch => 'x86_64'}])
|
77
|
+
end
|
78
|
+
it "ignores all mentions of plugin output" do
|
79
|
+
expect(output).not_to include("Random plugin")
|
80
|
+
end
|
81
|
+
end
|
72
82
|
end
|
73
83
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'puppet_spec/files'
|
4
|
+
require 'puppet_spec/modules'
|
5
|
+
require 'puppet/module/task'
|
6
|
+
|
7
|
+
describe Puppet::Module::Task do
|
8
|
+
include PuppetSpec::Files
|
9
|
+
|
10
|
+
let(:modpath) { tmpdir('task_modpath') }
|
11
|
+
let(:mymodpath) { File.join(modpath, 'mymod') }
|
12
|
+
let(:mymod) { Puppet::Module.new('mymod', mymodpath, nil) }
|
13
|
+
let(:tasks_path) { File.join(mymodpath, 'tasks') }
|
14
|
+
let(:tasks_glob) { File.join(mymodpath, 'tasks', '*') }
|
15
|
+
|
16
|
+
it "cannot construct tasks with illegal names" do
|
17
|
+
expect { Puppet::Module::Task.new(mymod, "iLegal", []) }
|
18
|
+
.to raise_error(Puppet::Module::Task::InvalidName,
|
19
|
+
"Task names must start with a lowercase letter and be composed of only lowercase letters, numbers, and underscores")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "cannot construct tasks whose files are outside of their module's tasks directory" do
|
23
|
+
outside_file = "/var/root/secret_tasks/classified"
|
24
|
+
expect { Puppet::Module::Task.new(mymod, "fail", [outside_file]) }
|
25
|
+
.to raise_error(Puppet::Module::Task::InvalidFile,
|
26
|
+
"The file '#{outside_file}' is not located in the mymod module's tasks directory")
|
27
|
+
end
|
28
|
+
|
29
|
+
it "constructs tasks as expected when every task has a metadata file with the same name (besides extension)" do
|
30
|
+
Dir.expects(:glob).with(tasks_glob).returns(%w{task1.json task1 task2.json task2.exe task3.json task3.sh})
|
31
|
+
tasks = Puppet::Module::Task.tasks_in_module(mymod)
|
32
|
+
|
33
|
+
expect(tasks.count).to eq(3)
|
34
|
+
expect(tasks.map{|t| t.name}).to eq(%w{mymod::task1 mymod::task2 mymod::task3})
|
35
|
+
expect(tasks.map{|t| t.metadata_file}).to eq(["#{tasks_path}/task1.json",
|
36
|
+
"#{tasks_path}/task2.json",
|
37
|
+
"#{tasks_path}/task3.json"])
|
38
|
+
expect(tasks.map{|t| t.files}).to eq([["#{tasks_path}/task1"],
|
39
|
+
["#{tasks_path}/task2.exe"],
|
40
|
+
["#{tasks_path}/task3.sh"]])
|
41
|
+
|
42
|
+
tasks.map{|t| t.metadata_file}.each do |metadata_file|
|
43
|
+
expect(metadata_file).to eq(File.absolute_path(metadata_file))
|
44
|
+
end
|
45
|
+
|
46
|
+
tasks.map{|t| t.files}.each do |task_files|
|
47
|
+
task_file = task_files[0]
|
48
|
+
expect(task_file).to eq(File.absolute_path(task_file))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it "constructs tasks as expected when some tasks don't have a metadata file" do
|
53
|
+
Dir.expects(:glob).with(tasks_glob).returns(%w{task1 task2.exe task3.json task3.sh})
|
54
|
+
tasks = Puppet::Module::Task.tasks_in_module(mymod)
|
55
|
+
|
56
|
+
expect(tasks.count).to eq(3)
|
57
|
+
expect(tasks.map{|t| t.name}).to eq(%w{mymod::task1 mymod::task2 mymod::task3})
|
58
|
+
expect(tasks.map{|t| t.metadata_file}).to eq([nil, nil, "#{tasks_path}/task3.json"])
|
59
|
+
expect(tasks.map{|t| t.files}).to eq([["#{tasks_path}/task1"],
|
60
|
+
["#{tasks_path}/task2.exe"],
|
61
|
+
["#{tasks_path}/task3.sh"]])
|
62
|
+
end
|
63
|
+
|
64
|
+
it "constructs tasks as expected when a task has multiple executable files" do
|
65
|
+
Dir.expects(:glob).with(tasks_glob).returns(%w{task1.elf task1.exe task1.json task2.ps1 task2.sh})
|
66
|
+
tasks = Puppet::Module::Task.tasks_in_module(mymod)
|
67
|
+
|
68
|
+
expect(tasks.count).to eq(2)
|
69
|
+
expect(tasks.map{|t| t.name}).to eq(%w{mymod::task1 mymod::task2})
|
70
|
+
expect(tasks.map{|t| t.metadata_file}).to eq(["#{tasks_path}/task1.json", nil])
|
71
|
+
expect(tasks.map{|t| t.files}).to eq([["#{tasks_path}/task1.elf", "#{tasks_path}/task1.exe"],
|
72
|
+
["#{tasks_path}/task2.ps1", "#{tasks_path}/task2.sh"]])
|
73
|
+
end
|
74
|
+
|
75
|
+
it "finds files whose names (besides extensions) are valid task names" do
|
76
|
+
Dir.expects(:glob).with(tasks_glob).returns(%w{task task_1 xx_t_a_s_k_2_xx})
|
77
|
+
tasks = Puppet::Module::Task.tasks_in_module(mymod)
|
78
|
+
|
79
|
+
expect(tasks.count).to eq(3)
|
80
|
+
expect(tasks.map{|t| t.name}).to eq(%w{mymod::task mymod::task_1 mymod::xx_t_a_s_k_2_xx})
|
81
|
+
end
|
82
|
+
|
83
|
+
it "ignores files that have names (besides extensions) that are not valid task names" do
|
84
|
+
Dir.expects(:glob).with(tasks_glob).returns(%w{.nottask.exe .wat !runme _task 2task2furious def_a_task_PSYCH Fake_task not-a-task realtask})
|
85
|
+
tasks = Puppet::Module::Task.tasks_in_module(mymod)
|
86
|
+
|
87
|
+
expect(tasks.count).to eq(1)
|
88
|
+
expect(tasks.map{|t| t.name}).to eq(%w{mymod::realtask})
|
89
|
+
end
|
90
|
+
|
91
|
+
it "ignores files that have names ending in .conf and .md" do
|
92
|
+
Dir.expects(:glob).with(tasks_glob).returns(%w{ginuwine_task task.conf readme.md other_task.md})
|
93
|
+
tasks = Puppet::Module::Task.tasks_in_module(mymod)
|
94
|
+
|
95
|
+
expect(tasks.count).to eq(1)
|
96
|
+
expect(tasks.map{|t| t.name}).to eq(%w{mymod::ginuwine_task})
|
97
|
+
end
|
98
|
+
|
99
|
+
it "gives the 'init' task a name that is just the module's name" do
|
100
|
+
expect(Puppet::Module::Task.new(mymod, 'init', ["#{tasks_path}/init.sh"]).name).to eq('mymod')
|
101
|
+
end
|
102
|
+
end
|
data/spec/unit/util/log_spec.rb
CHANGED
@@ -32,11 +32,11 @@ describe Puppet::Util::Log do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
it "includes a backtrace in the log" do
|
35
|
-
expect(logs.last.message).to match(/Backtrace:\n.*in `initialize'/ )
|
35
|
+
expect(logs.last.message).to match(/Backtrace:\n.*in `newmessage'\n.*in `initialize'/ )
|
36
36
|
end
|
37
37
|
|
38
38
|
it "warns that message included invalid encoding" do
|
39
|
-
expect(logs.last.message).to match(/Received a
|
39
|
+
expect(logs.last.message).to match(/Received a Log attribute with invalid encoding/)
|
40
40
|
end
|
41
41
|
|
42
42
|
it "includes the 'dump' of the invalid message" do
|
@@ -44,9 +44,18 @@ describe Puppet::Util::Log do
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
+
# need a string that cannot be converted to US-ASCII or other encodings easily
|
48
|
+
# different UTF-8 widths
|
49
|
+
# 1-byte A
|
50
|
+
# 2-byte ۿ - http://www.fileformat.info/info/unicode/char/06ff/index.htm - 0xDB 0xBF / 219 191
|
51
|
+
# 3-byte ᚠ - http://www.fileformat.info/info/unicode/char/16A0/index.htm - 0xE1 0x9A 0xA0 / 225 154 160
|
52
|
+
# 4-byte - http://www.fileformat.info/info/unicode/char/2070E/index.htm - 0xF0 0xA0 0x9C 0x8E / 240 160 156 142
|
53
|
+
let (:mixed_utf8) { "A\u06FF\u16A0\u{2070E}" } # Aۿᚠ
|
54
|
+
|
47
55
|
it "converts a given non-UTF-8 message to UTF-8" do
|
48
56
|
logs = []
|
49
57
|
Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(logs))
|
58
|
+
Puppet::Util::Log.newdestination(:console)
|
50
59
|
|
51
60
|
# HIRAGANA LETTER SO
|
52
61
|
# In Windows_31J: \x82 \xbb - 130 187
|
@@ -54,10 +63,30 @@ describe Puppet::Util::Log do
|
|
54
63
|
win_31j_msg = [130, 187].pack('C*').force_encoding(Encoding::Windows_31J)
|
55
64
|
utf_8_msg = "\u305d"
|
56
65
|
|
57
|
-
|
66
|
+
$stdout.expects(:puts).with("\e[mNotice: #{mixed_utf8}: #{utf_8_msg}\e[0m")
|
67
|
+
|
68
|
+
# most handlers do special things with a :source => 'Puppet', so use something else
|
69
|
+
Puppet::Util::Log.new(:level => :notice, :message => win_31j_msg, :source => mixed_utf8)
|
58
70
|
expect(logs.last.message).to eq(utf_8_msg)
|
59
71
|
end
|
60
72
|
|
73
|
+
it "converts a given non-UTF-8 source to UTF-8" do
|
74
|
+
logs = []
|
75
|
+
Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(logs))
|
76
|
+
Puppet::Util::Log.newdestination(:console)
|
77
|
+
|
78
|
+
# HIRAGANA LETTER SO
|
79
|
+
# In Windows_31J: \x82 \xbb - 130 187
|
80
|
+
# In Unicode: \u305d - \xe3 \x81 \x9d - 227 129 157
|
81
|
+
win_31j_msg = [130, 187].pack('C*').force_encoding(Encoding::Windows_31J)
|
82
|
+
utf_8_msg = "\u305d"
|
83
|
+
|
84
|
+
$stdout.expects(:puts).with("\e[mNotice: #{utf_8_msg}: #{mixed_utf8}\e[0m")
|
85
|
+
|
86
|
+
Puppet::Util::Log.new(:level => :notice, :message => mixed_utf8, :source => win_31j_msg)
|
87
|
+
expect(logs.last.source).to eq(utf_8_msg)
|
88
|
+
end
|
89
|
+
|
61
90
|
describe ".setup_default" do
|
62
91
|
it "should default to :syslog" do
|
63
92
|
Puppet.features.stubs(:syslog?).returns(true)
|
@@ -4,6 +4,10 @@
|
|
4
4
|
require 'spec_helper'
|
5
5
|
|
6
6
|
describe "FFI::MemoryPointer", :if => Puppet.features.microsoft_windows? do
|
7
|
+
# use 2 bad bytes at end so we have even number of bytes / characters
|
8
|
+
let (:bad_string) { "hello invalid world".encode(Encoding::UTF_16LE) + "\xDD\xDD".force_encoding(Encoding::UTF_16LE) }
|
9
|
+
let (:bad_string_bytes) { bad_string.bytes.to_a }
|
10
|
+
|
7
11
|
context "read_wide_string" do
|
8
12
|
let (:string) { "foo_bar" }
|
9
13
|
|
@@ -24,6 +28,40 @@ describe "FFI::MemoryPointer", :if => Puppet.features.microsoft_windows? do
|
|
24
28
|
|
25
29
|
expect(read_string.encoding).to eq(Encoding::UTF_8)
|
26
30
|
end
|
31
|
+
|
32
|
+
it "should raise an error and emit a debug message when receiving a string containing invalid bytes in the destination encoding" do
|
33
|
+
# enable a debug output sink to local string array
|
34
|
+
Puppet.debug = true
|
35
|
+
arraydest = []
|
36
|
+
Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(arraydest))
|
37
|
+
|
38
|
+
read_string = nil
|
39
|
+
|
40
|
+
expect {
|
41
|
+
FFI::MemoryPointer.new(:byte, bad_string_bytes.count) do |ptr|
|
42
|
+
# uchar here is synonymous with byte
|
43
|
+
ptr.put_array_of_uchar(0, bad_string_bytes)
|
44
|
+
|
45
|
+
read_string = ptr.read_wide_string(bad_string.length)
|
46
|
+
end
|
47
|
+
}.to raise_error(Encoding::InvalidByteSequenceError)
|
48
|
+
|
49
|
+
expect(read_string).to be_nil
|
50
|
+
expect(arraydest.last.message).to eq("Unable to convert value #{bad_string.dump} to encoding UTF-8 due to #<Encoding::InvalidByteSequenceError: \"\\xDD\\xDD\" on UTF-16LE>")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should not raise an error when receiving a string containing invalid bytes in the destination encoding, when specifying :invalid => :replace" do
|
54
|
+
read_string = nil
|
55
|
+
|
56
|
+
FFI::MemoryPointer.new(:byte, bad_string_bytes.count) do |ptr|
|
57
|
+
# uchar here is synonymous with byte
|
58
|
+
ptr.put_array_of_uchar(0, bad_string_bytes)
|
59
|
+
|
60
|
+
read_string = ptr.read_wide_string(bad_string.length, Encoding::UTF_8, :invalid => :replace)
|
61
|
+
end
|
62
|
+
|
63
|
+
expect(read_string).to eq("hello invalid world\uFFFD")
|
64
|
+
end
|
27
65
|
end
|
28
66
|
|
29
67
|
context "read_arbitrary_wide_string_up_to" do
|
@@ -66,5 +104,18 @@ describe "FFI::MemoryPointer", :if => Puppet.features.microsoft_windows? do
|
|
66
104
|
|
67
105
|
expect(read_string.encoding).to eq(Encoding::UTF_8)
|
68
106
|
end
|
107
|
+
|
108
|
+
it "should not raise an error when receiving a string containing invalid bytes in the destination encoding, when specifying :invalid => :replace" do
|
109
|
+
read_string = nil
|
110
|
+
|
111
|
+
FFI::MemoryPointer.new(:byte, bad_string_bytes.count) do |ptr|
|
112
|
+
# uchar here is synonymous with byte
|
113
|
+
ptr.put_array_of_uchar(0, bad_string_bytes)
|
114
|
+
|
115
|
+
read_string = ptr.read_arbitrary_wide_string_up_to(ptr.size / 2, :single_null, :invalid => :replace)
|
116
|
+
end
|
117
|
+
|
118
|
+
expect(read_string).to eq("hello invalid world\uFFFD")
|
119
|
+
end
|
69
120
|
end
|
70
121
|
end
|