facter 1.7.6 → 2.0.1.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of facter might be problematic. Click here for more details.

Files changed (155) hide show
  1. checksums.yaml +7 -0
  2. data/COMMITTERS.md +194 -0
  3. data/CONTRIBUTING.md +63 -235
  4. data/Gemfile +12 -8
  5. data/README.md +1 -2
  6. data/Rakefile +1 -1
  7. data/bin/facter +0 -4
  8. data/ext/build_defaults.yaml +2 -2
  9. data/ext/project_data.yaml +18 -0
  10. data/install.rb +1 -16
  11. data/lib/facter.rb +171 -171
  12. data/lib/facter/application.rb +65 -54
  13. data/lib/facter/core/aggregate.rb +220 -0
  14. data/lib/facter/core/directed_graph.rb +46 -0
  15. data/lib/facter/core/execution.rb +100 -0
  16. data/lib/facter/core/execution/base.rb +73 -0
  17. data/lib/facter/core/execution/posix.rb +50 -0
  18. data/lib/facter/core/execution/windows.rb +57 -0
  19. data/lib/facter/core/logging.rb +169 -0
  20. data/lib/facter/core/resolvable.rb +94 -0
  21. data/lib/facter/core/suitable.rb +117 -0
  22. data/lib/facter/domain.rb +15 -9
  23. data/lib/facter/filesystems.rb +1 -1
  24. data/lib/facter/hardwaremodel.rb +1 -1
  25. data/lib/facter/hostname.rb +3 -3
  26. data/lib/facter/interfaces.rb +6 -1
  27. data/lib/facter/ipaddress.rb +2 -2
  28. data/lib/facter/kernel.rb +1 -1
  29. data/lib/facter/kernelrelease.rb +1 -1
  30. data/lib/facter/ldom.rb +1 -1
  31. data/lib/facter/lsbdistcodename.rb +1 -1
  32. data/lib/facter/lsbdistdescription.rb +1 -1
  33. data/lib/facter/lsbdistid.rb +1 -1
  34. data/lib/facter/lsbdistrelease.rb +1 -1
  35. data/lib/facter/lsbrelease.rb +1 -1
  36. data/lib/facter/macaddress.rb +1 -14
  37. data/lib/facter/macosx.rb +2 -2
  38. data/lib/facter/memory.rb +8 -19
  39. data/lib/facter/operatingsystem.rb +1 -1
  40. data/lib/facter/operatingsystemrelease.rb +34 -1
  41. data/lib/facter/physicalprocessorcount.rb +6 -6
  42. data/lib/facter/processor.rb +11 -10
  43. data/lib/facter/selinux.rb +4 -15
  44. data/lib/facter/ssh.rb +5 -2
  45. data/lib/facter/util/architecture.rb +2 -2
  46. data/lib/facter/util/collection.rb +42 -38
  47. data/lib/facter/util/config.rb +19 -9
  48. data/lib/facter/util/confine.rb +34 -4
  49. data/lib/facter/util/ec2.rb +1 -1
  50. data/lib/facter/util/fact.rb +108 -36
  51. data/lib/facter/util/file_read.rb +7 -6
  52. data/lib/facter/util/formatter.rb +38 -0
  53. data/lib/facter/util/ip.rb +3 -3
  54. data/lib/facter/util/loader.rb +62 -42
  55. data/lib/facter/util/macosx.rb +7 -8
  56. data/lib/facter/util/manufacturer.rb +3 -3
  57. data/lib/facter/util/memory.rb +13 -13
  58. data/lib/facter/util/monkey_patches.rb +0 -31
  59. data/lib/facter/util/netmask.rb +3 -3
  60. data/lib/facter/util/normalization.rb +94 -0
  61. data/lib/facter/util/nothing_loader.rb +3 -6
  62. data/lib/facter/util/parser.rb +3 -5
  63. data/lib/facter/util/plist/generator.rb +1 -1
  64. data/lib/facter/util/processor.rb +15 -15
  65. data/lib/facter/util/resolution.rb +112 -289
  66. data/lib/facter/util/solaris_zones.rb +4 -4
  67. data/lib/facter/util/uptime.rb +8 -3
  68. data/lib/facter/util/values.rb +67 -1
  69. data/lib/facter/util/virtual.rb +10 -10
  70. data/lib/facter/util/xendomains.rb +1 -1
  71. data/lib/facter/version.rb +42 -39
  72. data/lib/facter/virtual.rb +6 -7
  73. data/lib/facter/zfs_version.rb +3 -3
  74. data/lib/facter/zpool_version.rb +3 -3
  75. data/spec/fixtures/unit/netmask/darwin_10_8_5.txt +30 -0
  76. data/spec/unit/application_spec.rb +46 -1
  77. data/spec/unit/core/aggregate_spec.rb +125 -0
  78. data/spec/unit/core/directed_graph_spec.rb +79 -0
  79. data/spec/unit/core/execution/base_spec.rb +119 -0
  80. data/spec/unit/core/execution/posix_spec.rb +86 -0
  81. data/spec/unit/core/execution/windows_spec.rb +106 -0
  82. data/spec/unit/core/execution_spec.rb +37 -0
  83. data/spec/unit/core/logging_spec.rb +104 -0
  84. data/spec/unit/core/resolvable_spec.rb +81 -0
  85. data/spec/unit/core/suitable_spec.rb +96 -0
  86. data/spec/unit/domain_spec.rb +5 -5
  87. data/spec/unit/facter_spec.rb +61 -222
  88. data/spec/unit/filesystems_spec.rb +2 -2
  89. data/spec/unit/hardwareisa_spec.rb +5 -5
  90. data/spec/unit/hardwaremodel_spec.rb +1 -1
  91. data/spec/unit/hostname_spec.rb +4 -4
  92. data/spec/unit/id_spec.rb +3 -3
  93. data/spec/unit/interfaces_spec.rb +10 -0
  94. data/spec/unit/ipaddress6_spec.rb +4 -4
  95. data/spec/unit/ipaddress_spec.rb +1 -1
  96. data/spec/unit/kernel_spec.rb +2 -2
  97. data/spec/unit/kernelmajversion_spec.rb +1 -1
  98. data/spec/unit/kernelrelease_spec.rb +4 -4
  99. data/spec/unit/kernelversion_spec.rb +2 -2
  100. data/spec/unit/ldom_spec.rb +2 -2
  101. data/spec/unit/lsbdistcodename_spec.rb +2 -2
  102. data/spec/unit/lsbdistdescription_spec.rb +2 -2
  103. data/spec/unit/lsbdistid_spec.rb +2 -2
  104. data/spec/unit/lsbdistrelease_spec.rb +2 -2
  105. data/spec/unit/lsbrelease_spec.rb +2 -2
  106. data/spec/unit/manufacturer_spec.rb +1 -1
  107. data/spec/unit/memory_spec.rb +24 -31
  108. data/spec/unit/netmask_spec.rb +9 -0
  109. data/spec/unit/operatingsystem_spec.rb +1 -1
  110. data/spec/unit/operatingsystemrelease_spec.rb +62 -4
  111. data/spec/unit/physicalprocessorcount_spec.rb +10 -10
  112. data/spec/unit/processor_spec.rb +11 -11
  113. data/spec/unit/selinux_spec.rb +2 -8
  114. data/spec/unit/ssh_spec.rb +3 -2
  115. data/spec/unit/uniqueid_spec.rb +3 -3
  116. data/spec/unit/util/collection_spec.rb +37 -35
  117. data/spec/unit/util/config_spec.rb +20 -0
  118. data/spec/unit/util/confine_spec.rb +21 -0
  119. data/spec/unit/util/directory_loader_spec.rb +1 -0
  120. data/spec/unit/util/ec2_spec.rb +6 -6
  121. data/spec/unit/util/fact_spec.rb +92 -90
  122. data/spec/unit/util/ip_spec.rb +2 -2
  123. data/spec/unit/util/loader_spec.rb +127 -186
  124. data/spec/unit/util/macaddress_spec.rb +2 -2
  125. data/spec/unit/util/macosx_spec.rb +8 -8
  126. data/spec/unit/util/manufacturer_spec.rb +3 -3
  127. data/spec/unit/util/normalization_spec.rb +113 -0
  128. data/spec/unit/util/parser_spec.rb +25 -3
  129. data/spec/unit/util/processor_spec.rb +2 -2
  130. data/spec/unit/util/resolution_spec.rb +60 -631
  131. data/spec/unit/util/solaris_zones_spec.rb +5 -5
  132. data/spec/unit/util/uptime_spec.rb +1 -1
  133. data/spec/unit/util/values_spec.rb +131 -0
  134. data/spec/unit/util/virtual_spec.rb +16 -16
  135. data/spec/unit/util/xendomains_spec.rb +2 -2
  136. data/spec/unit/virtual_spec.rb +39 -39
  137. data/spec/unit/zfs_version_spec.rb +11 -11
  138. data/spec/unit/zonename_spec.rb +2 -2
  139. data/spec/unit/zones_spec.rb +1 -1
  140. data/spec/unit/zpool_version_spec.rb +11 -11
  141. metadata +466 -447
  142. data/lib/facter/util/cfpropertylist.rb +0 -6
  143. data/lib/facter/util/cfpropertylist/LICENSE +0 -19
  144. data/lib/facter/util/cfpropertylist/README +0 -44
  145. data/lib/facter/util/cfpropertylist/Rakefile +0 -44
  146. data/lib/facter/util/cfpropertylist/THANKS +0 -7
  147. data/lib/facter/util/cfpropertylist/lib/cfpropertylist.rb +0 -6
  148. data/lib/facter/util/cfpropertylist/lib/rbBinaryCFPropertyList.rb +0 -562
  149. data/lib/facter/util/cfpropertylist/lib/rbCFPlistError.rb +0 -26
  150. data/lib/facter/util/cfpropertylist/lib/rbCFPropertyList.rb +0 -407
  151. data/lib/facter/util/cfpropertylist/lib/rbCFTypes.rb +0 -244
  152. data/lib/facter/util/cfpropertylist/lib/rbLibXMLParser.rb +0 -135
  153. data/lib/facter/util/cfpropertylist/lib/rbNokogiriParser.rb +0 -140
  154. data/lib/facter/util/cfpropertylist/lib/rbREXMLParser.rb +0 -136
  155. data/spec/unit/util/monkey_patches_spec.rb +0 -42
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+ require 'facter/core/aggregate'
3
+
4
+ describe Facter::Core::Aggregate do
5
+
6
+ let(:fact) { stub('stub_fact', :name => 'stub_fact') }
7
+
8
+ subject { obj = described_class.new('aggregated', fact) }
9
+
10
+ it "can be resolved" do
11
+ expect(subject).to be_a_kind_of Facter::Core::Resolvable
12
+ end
13
+
14
+ it "can be confined and weighted" do
15
+ expect(subject).to be_a_kind_of Facter::Core::Suitable
16
+ end
17
+
18
+ describe "setting options" do
19
+
20
+ it "can set the timeout" do
21
+ subject.set_options(:timeout => 314)
22
+ expect(subject.limit).to eq 314
23
+ end
24
+
25
+ it "can set the weight" do
26
+ subject.set_options(:weight => 27)
27
+ expect(subject.weight).to eq 27
28
+ end
29
+
30
+ it "can set the name" do
31
+ subject.set_options(:name => 'something')
32
+ expect(subject.name).to eq 'something'
33
+ end
34
+
35
+ it "fails on unhandled options" do
36
+ expect do
37
+ subject.set_options(:foo => 'bar')
38
+ end.to raise_error(ArgumentError, /Invalid aggregate options .*foo/)
39
+ end
40
+ end
41
+
42
+ describe "declaring chunks" do
43
+ it "requires that an chunk is given a block" do
44
+ expect { subject.chunk(:fail) }.to raise_error(ArgumentError, /requires a block/)
45
+ end
46
+
47
+ it "allows an chunk to have a list of requirements" do
48
+ subject.chunk(:data, :require => [:other]) { }
49
+ expect(subject.deps[:data]).to eq [:other]
50
+ end
51
+
52
+ it "converts a single chunk requirement to an array" do
53
+ subject.chunk(:data, :require => :other) { }
54
+ expect(subject.deps[:data]).to eq [:other]
55
+ end
56
+
57
+ it "raises an error when an unhandled option is passed" do
58
+ expect {
59
+ subject.chunk(:data, :before => [:other]) { }
60
+ }.to raise_error(ArgumentError, /Unexpected options.*#chunk: .*before/)
61
+ end
62
+ end
63
+
64
+ describe "handling interactions between chunks" do
65
+ it "generates a warning when there is a dependency cycle in chunks" do
66
+ subject.chunk(:first, :require => [:second]) { }
67
+ subject.chunk(:second, :require => [:first]) { }
68
+
69
+ Facter.expects(:warn) do |msg|
70
+ expect(msg).to match /dependency cycles: .*[:first, :second]/
71
+ end
72
+
73
+ subject.value
74
+ end
75
+
76
+ it "passes all requested chunk results to the depending chunk" do
77
+ subject.chunk(:first) { ['foo'] }
78
+ subject.chunk(:second, :require => [:first]) do |first|
79
+ [first[0] + ' bar']
80
+ end
81
+
82
+ output = subject.value
83
+ expect(output).to include 'foo'
84
+ expect(output).to include 'foo bar'
85
+ end
86
+
87
+ it "clones and freezes chunk results passed to other chunks" do
88
+ subject.chunk(:first) { 'foo' }
89
+ subject.chunk(:second, :require => [:first]) do |first|
90
+ expect(first).to be_frozen
91
+ end
92
+
93
+ subject.aggregate do |chunks|
94
+ chunks.values.each do |chunk|
95
+ expect(chunk).to be_frozen
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ describe "aggregating chunks" do
102
+ it "passes all chunk results as a hash to the aggregate block" do
103
+ subject.chunk(:data) { 'data chunk' }
104
+ subject.chunk(:datum) { 'datum chunk' }
105
+
106
+ subject.aggregate do |chunks|
107
+ expect(chunks).to eq(:data => 'data chunk', :datum => 'datum chunk')
108
+ end
109
+
110
+ subject.value
111
+ end
112
+
113
+ it "uses the result of the aggregate block as the value" do
114
+ subject.aggregate { "who needs chunks anyways" }
115
+ expect(subject.value).to eq "who needs chunks anyways"
116
+ end
117
+ end
118
+
119
+ describe "evaluating" do
120
+ it "evaluates the block in the context of the aggregate" do
121
+ subject.expects(:has_weight).with(5)
122
+ subject.evaluate { has_weight(5) }
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+ require 'facter/core/directed_graph'
3
+
4
+ describe Facter::Core::DirectedGraph do
5
+ subject(:graph) { described_class.new }
6
+
7
+ describe "detecting cycles" do
8
+ it "is acyclic if the graph is empty" do
9
+ expect(graph).to be_acyclic
10
+ end
11
+
12
+ it "is acyclic if the graph has no edges" do
13
+ graph[:one] = []
14
+ graph[:two] = []
15
+
16
+ expect(graph).to be_acyclic
17
+ end
18
+
19
+ it "is acyclic if a vertex has an edge to itself" do
20
+ graph[:one] = [:one]
21
+ expect(graph).to be_acyclic
22
+ end
23
+
24
+ it "is acyclic if there are no loops in the graph" do
25
+ graph[:one] = [:two, :three]
26
+ graph[:two] = [:four]
27
+ graph[:three] = [:four]
28
+ graph[:four] = []
29
+
30
+ expect(graph).to be_acyclic
31
+ end
32
+
33
+ it "is cyclic if there is a loop in the graph" do
34
+ graph[:one] = [:two]
35
+ graph[:two] = [:one]
36
+ expect(graph).to_not be_acyclic
37
+ end
38
+
39
+ it "can return the cycles in the graph" do
40
+ graph[:one] = [:two]
41
+ graph[:two] = [:one]
42
+
43
+ graph[:three] = [:four]
44
+ graph[:four] = [:three]
45
+
46
+ first_cycle = graph.cycles.find { |cycle| cycle.include? :one }
47
+ second_cycle = graph.cycles.find { |cycle| cycle.include? :three }
48
+
49
+ expect(first_cycle).to include :two
50
+ expect(second_cycle).to include :four
51
+ end
52
+ end
53
+
54
+ describe "sorting" do
55
+ it "returns the vertices in topologically sorted order" do
56
+ graph[:one] = [:two, :three]
57
+ graph[:two] = [:three]
58
+ graph[:three] = []
59
+ expect(graph.tsort).to eq [:three, :two, :one]
60
+ end
61
+
62
+ it "raises an error if there is a cycle in the graph" do
63
+ graph[:one] = [:two]
64
+ graph[:two] = [:one]
65
+
66
+ expect {
67
+ graph.tsort
68
+ }.to raise_error(Facter::Core::DirectedGraph::CycleError, /found the following cycles:/)
69
+ end
70
+
71
+ it "raises an error if there is an edge to a non-existent vertex" do
72
+ graph[:one] = [:two, :three]
73
+ graph[:two] = [:three]
74
+ expect {
75
+ graph.tsort
76
+ }.to raise_error(Facter::Core::DirectedGraph::MissingVertex, /missing elements.*three/)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+ require 'facter/core/execution'
3
+
4
+ describe Facter::Core::Execution::Base do
5
+
6
+ describe "#with_env" do
7
+ it "should execute the caller's block with the specified env vars" do
8
+ test_env = { "LANG" => "C", "FOO" => "BAR" }
9
+ subject.with_env test_env do
10
+ test_env.keys.each do |key|
11
+ ENV[key].should == test_env[key]
12
+ end
13
+ end
14
+ end
15
+
16
+ it "should restore pre-existing environment variables to their previous values" do
17
+ orig_env = {}
18
+ new_env = {}
19
+ # an arbitrary sentinel value to use to temporarily set the environment vars to
20
+ sentinel_value = "Abracadabra"
21
+
22
+ # grab some values from the existing ENV (arbitrarily choosing 3 here)
23
+ ENV.keys.first(3).each do |key|
24
+ # save the original values so that we can test against them later
25
+ orig_env[key] = ENV[key]
26
+ # create bogus temp values for the chosen keys
27
+ new_env[key] = sentinel_value
28
+ end
29
+
30
+ # verify that, during the 'with_env', the new values are used
31
+ subject.with_env new_env do
32
+ orig_env.keys.each do |key|
33
+ ENV[key].should == new_env[key]
34
+ end
35
+ end
36
+
37
+ # verify that, after the 'with_env', the old values are restored
38
+ orig_env.keys.each do |key|
39
+ ENV[key].should == orig_env[key]
40
+ end
41
+ end
42
+
43
+ it "should not be affected by a 'return' statement in the yield block" do
44
+ @sentinel_var = :resolution_test_foo.to_s
45
+
46
+ # the intent of this test case is to test a yield block that contains a return statement. However, it's illegal
47
+ # to use a return statement outside of a method, so we need to create one here to give scope to the 'return'
48
+ def handy_method()
49
+ ENV[@sentinel_var] = "foo"
50
+ new_env = { @sentinel_var => "bar" }
51
+
52
+ subject.with_env new_env do
53
+ ENV[@sentinel_var].should == "bar"
54
+ return
55
+ end
56
+ end
57
+
58
+ handy_method()
59
+
60
+ ENV[@sentinel_var].should == "foo"
61
+
62
+ end
63
+ end
64
+
65
+ describe "#exec" do
66
+
67
+ it "switches LANG to C when executing the command" do
68
+ subject.expects(:with_env).with('LANG' => 'C')
69
+ subject.exec('foo')
70
+ end
71
+
72
+ it "switches LC_ALL to C when executing the command"
73
+
74
+ it "expands the command before running it" do
75
+ subject.stubs(:`).returns ''
76
+ subject.expects(:expand_command).with('foo').returns '/bin/foo'
77
+ subject.exec('foo')
78
+ end
79
+
80
+ it "returns an empty string when the command could not be expanded" do
81
+ subject.expects(:expand_command).with('foo').returns nil
82
+ expect(subject.exec('foo')).to be_empty
83
+ end
84
+
85
+ it "logs a warning and returns an empty string when the command execution fails" do
86
+ subject.expects(:`).with("/bin/foo").raises "kaboom!"
87
+ Facter.expects(:warn).with("kaboom!")
88
+
89
+ subject.expects(:expand_command).with('foo').returns '/bin/foo'
90
+
91
+ expect(subject.exec("foo")).to be_empty
92
+ end
93
+
94
+ it "launches a thread to wait on children if the command was interrupted" do
95
+ subject.expects(:`).with("/bin/foo").raises "kaboom!"
96
+ subject.expects(:expand_command).with('foo').returns '/bin/foo'
97
+
98
+ Facter.stubs(:warn)
99
+ Thread.expects(:new).yields
100
+ Process.expects(:waitall).once
101
+
102
+ subject.exec("foo")
103
+ end
104
+
105
+ it "returns the output of the command" do
106
+ subject.expects(:`).with("/bin/foo").returns 'hi'
107
+ subject.expects(:expand_command).with('foo').returns '/bin/foo'
108
+
109
+ expect(subject.exec("foo")).to eq 'hi'
110
+ end
111
+
112
+ it "strips off trailing newlines" do
113
+ subject.expects(:`).with("/bin/foo").returns "hi\n"
114
+ subject.expects(:expand_command).with('foo').returns '/bin/foo'
115
+
116
+ expect(subject.exec("foo")).to eq 'hi'
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe Facter::Core::Execution::Posix, :as_plaform => :posix do
4
+
5
+ describe "#search_paths" do
6
+ it "should use the PATH environment variable plus /sbin and /usr/sbin on unix" do
7
+ ENV.expects(:[]).with('PATH').returns "/bin:/usr/bin"
8
+ subject.search_paths.should == %w{/bin /usr/bin /sbin /usr/sbin}
9
+ end
10
+ end
11
+
12
+ describe "#which" do
13
+ before :each do
14
+ subject.stubs(:search_paths).returns [ '/bin', '/sbin', '/usr/sbin']
15
+ end
16
+
17
+ context "and provided with an absolute path" do
18
+ it "should return the binary if executable" do
19
+ File.expects(:executable?).with('/opt/foo').returns true
20
+ subject.which('/opt/foo').should == '/opt/foo'
21
+ end
22
+
23
+ it "should return nil if the binary is not executable" do
24
+ File.expects(:executable?).with('/opt/foo').returns false
25
+ subject.which('/opt/foo').should be_nil
26
+ end
27
+ end
28
+
29
+ context "and not provided with an absolute path" do
30
+ it "should return the absolute path if found" do
31
+ File.expects(:executable?).with('/bin/foo').returns false
32
+ File.expects(:executable?).with('/sbin/foo').returns true
33
+ File.expects(:executable?).with('/usr/sbin/foo').never
34
+ subject.which('foo').should == '/sbin/foo'
35
+ end
36
+
37
+ it "should return nil if not found" do
38
+ File.expects(:executable?).with('/bin/foo').returns false
39
+ File.expects(:executable?).with('/sbin/foo').returns false
40
+ File.expects(:executable?).with('/usr/sbin/foo').returns false
41
+ subject.which('foo').should be_nil
42
+ end
43
+ end
44
+ end
45
+
46
+ describe "#expand_command" do
47
+ it "should expand binary" do
48
+ subject.expects(:which).with('foo').returns '/bin/foo'
49
+ subject.expand_command('foo -a | stuff >> /dev/null').should == '/bin/foo -a | stuff >> /dev/null'
50
+ end
51
+
52
+ it "should expand double quoted binary" do
53
+ subject.expects(:which).with('/tmp/my foo').returns '/tmp/my foo'
54
+ subject.expand_command(%q{"/tmp/my foo" bar}).should == %q{'/tmp/my foo' bar}
55
+ end
56
+
57
+ it "should expand single quoted binary" do
58
+ subject.expects(:which).with('my foo').returns '/home/bob/my path/my foo'
59
+ subject.expand_command(%q{'my foo' -a}).should == %q{'/home/bob/my path/my foo' -a}
60
+ end
61
+
62
+ it "should quote expanded binary if found in path with spaces" do
63
+ subject.expects(:which).with('foo.sh').returns '/home/bob/my tools/foo.sh'
64
+ subject.expand_command('foo.sh /a /b').should == %q{'/home/bob/my tools/foo.sh' /a /b}
65
+ end
66
+
67
+ it "should return nil if not found" do
68
+ subject.expects(:which).with('foo').returns nil
69
+ subject.expand_command('foo -a | stuff >> /dev/null').should be_nil
70
+ end
71
+ end
72
+
73
+ describe "#absolute_path?" do
74
+ %w[/ /foo /foo/../bar //foo //Server/Foo/Bar //?/C:/foo/bar /\Server/Foo /foo//bar/baz].each do |path|
75
+ it "should return true for #{path}" do
76
+ subject.should be_absolute_path(path)
77
+ end
78
+ end
79
+
80
+ %w[. ./foo \foo C:/foo \\Server\Foo\Bar \\?\C:\foo\bar \/?/foo\bar \/Server/foo foo//bar/baz].each do |path|
81
+ it "should return false for #{path}" do
82
+ subject.should_not be_absolute_path(path)
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,106 @@
1
+ require 'spec_helper'
2
+
3
+ describe Facter::Core::Execution::Windows, :as_platform => :windows do
4
+
5
+ describe "#search_paths" do
6
+ it "should use the PATH environment variable to determine locations" do
7
+ ENV.expects(:[]).with('PATH').returns 'C:\Windows;C:\Windows\System32'
8
+ subject.search_paths.should == %w{C:\Windows C:\Windows\System32}
9
+ end
10
+ end
11
+
12
+ describe "#which" do
13
+ before :each do
14
+ subject.stubs(:search_paths).returns ['C:\Windows\system32', 'C:\Windows', 'C:\Windows\System32\Wbem' ]
15
+ ENV.stubs(:[]).with('PATHEXT').returns nil
16
+ end
17
+
18
+ context "and provided with an absolute path" do
19
+ it "should return the binary if executable" do
20
+ File.expects(:executable?).with('C:\Tools\foo.exe').returns true
21
+ File.expects(:executable?).with('\\\\remote\dir\foo.exe').returns true
22
+ subject.which('C:\Tools\foo.exe').should == 'C:\Tools\foo.exe'
23
+ subject.which('\\\\remote\dir\foo.exe').should == '\\\\remote\dir\foo.exe'
24
+ end
25
+
26
+ it "should return nil if the binary is not executable" do
27
+ File.expects(:executable?).with('C:\Tools\foo.exe').returns false
28
+ File.expects(:executable?).with('\\\\remote\dir\foo.exe').returns false
29
+ subject.which('C:\Tools\foo.exe').should be_nil
30
+ subject.which('\\\\remote\dir\foo.exe').should be_nil
31
+ end
32
+ end
33
+
34
+ context "and not provided with an absolute path" do
35
+ it "should return the absolute path if found" do
36
+ File.expects(:executable?).with('C:\Windows\system32\foo.exe').returns false
37
+ File.expects(:executable?).with('C:\Windows\foo.exe').returns true
38
+ File.expects(:executable?).with('C:\Windows\System32\Wbem\foo.exe').never
39
+ subject.which('foo.exe').should == 'C:\Windows\foo.exe'
40
+ end
41
+
42
+ it "should return the absolute path with file extension if found" do
43
+ ['.COM', '.EXE', '.BAT', '.CMD', '' ].each do |ext|
44
+ File.stubs(:executable?).with('C:\Windows\system32\foo'+ext).returns false
45
+ File.stubs(:executable?).with('C:\Windows\System32\Wbem\foo'+ext).returns false
46
+ end
47
+ ['.COM', '.BAT', '.CMD', '' ].each do |ext|
48
+ File.stubs(:executable?).with('C:\Windows\foo'+ext).returns false
49
+ end
50
+ File.stubs(:executable?).with('C:\Windows\foo.EXE').returns true
51
+
52
+ subject.which('foo').should == 'C:\Windows\foo.EXE'
53
+ end
54
+
55
+ it "should return nil if not found" do
56
+ File.expects(:executable?).with('C:\Windows\system32\foo.exe').returns false
57
+ File.expects(:executable?).with('C:\Windows\foo.exe').returns false
58
+ File.expects(:executable?).with('C:\Windows\System32\Wbem\foo.exe').returns false
59
+ subject.which('foo.exe').should be_nil
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#expand_command" do
65
+ it "should expand binary" do
66
+ subject.expects(:which).with('cmd').returns 'C:\Windows\System32\cmd'
67
+ subject.expand_command(
68
+ 'cmd /c echo foo > C:\bar'
69
+ ).should == 'C:\Windows\System32\cmd /c echo foo > C:\bar'
70
+ end
71
+
72
+ it "should expand double quoted binary" do
73
+ subject.expects(:which).with('my foo').returns 'C:\My Tools\my foo.exe'
74
+ subject.expand_command('"my foo" /a /b').should == '"C:\My Tools\my foo.exe" /a /b'
75
+ end
76
+
77
+ it "should not expand single quoted binary" do
78
+ subject.expects(:which).with('\'C:\My').returns nil
79
+ subject.expand_command('\'C:\My Tools\foo.exe\' /a /b').should be_nil
80
+ end
81
+
82
+ it "should quote expanded binary if found in path with spaces" do
83
+ subject.expects(:which).with('foo').returns 'C:\My Tools\foo.exe'
84
+ subject.expand_command('foo /a /b').should == '"C:\My Tools\foo.exe" /a /b'
85
+ end
86
+
87
+ it "should return nil if not found" do
88
+ subject.expects(:which).with('foo').returns nil
89
+ subject.expand_command('foo /a | stuff >> NUL').should be_nil
90
+ end
91
+ end
92
+
93
+ describe "#absolute_path?" do
94
+ %w[C:/foo C:\foo \\\\Server\Foo\Bar \\\\?\C:\foo\bar //Server/Foo/Bar //?/C:/foo/bar /\?\C:/foo\bar \/Server\Foo/Bar c:/foo//bar//baz].each do |path|
95
+ it "should return true for #{path}" do
96
+ subject.should be_absolute_path(path)
97
+ end
98
+ end
99
+
100
+ %w[/ . ./foo \foo /foo /foo/../bar //foo C:foo/bar foo//bar/baz].each do |path|
101
+ it "should return false for #{path}" do
102
+ subject.should_not be_absolute_path(path)
103
+ end
104
+ end
105
+ end
106
+ end