right_agent 0.17.2 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. data/lib/right_agent.rb +0 -1
  2. data/lib/right_agent/agent_config.rb +1 -1
  3. data/lib/right_agent/minimal.rb +8 -7
  4. data/lib/right_agent/monkey_patches.rb +4 -2
  5. data/lib/right_agent/monkey_patches/ruby_patch.rb +9 -9
  6. data/lib/right_agent/monkey_patches/ruby_patch/linux_patch/file_patch.rb +2 -2
  7. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/file_patch.rb +21 -51
  8. data/lib/right_agent/packets.rb +5 -1
  9. data/lib/right_agent/platform.rb +727 -299
  10. data/lib/right_agent/platform/unix/darwin/platform.rb +102 -0
  11. data/lib/right_agent/platform/unix/linux/platform.rb +305 -0
  12. data/lib/right_agent/platform/unix/platform.rb +226 -0
  13. data/lib/right_agent/platform/windows/mingw/platform.rb +447 -0
  14. data/lib/right_agent/platform/windows/mswin/platform.rb +236 -0
  15. data/lib/right_agent/platform/windows/platform.rb +1808 -0
  16. data/right_agent.gemspec +13 -8
  17. data/spec/platform/spec_helper.rb +216 -0
  18. data/spec/platform/unix/darwin/platform_spec.rb +181 -0
  19. data/spec/platform/unix/linux/platform_spec.rb +540 -0
  20. data/spec/platform/unix/spec_helper.rb +149 -0
  21. data/spec/platform/windows/mingw/platform_spec.rb +222 -0
  22. data/spec/platform/windows/mswin/platform_spec.rb +259 -0
  23. data/spec/platform/windows/spec_helper.rb +720 -0
  24. metadata +45 -30
  25. data/lib/right_agent/platform/darwin.rb +0 -285
  26. data/lib/right_agent/platform/linux.rb +0 -537
  27. data/lib/right_agent/platform/windows.rb +0 -1384
  28. data/spec/platform/darwin_spec.rb +0 -13
  29. data/spec/platform/linux_spec.rb +0 -38
  30. data/spec/platform/linux_volume_manager_spec.rb +0 -201
  31. data/spec/platform/platform_spec.rb +0 -80
  32. data/spec/platform/windows_spec.rb +0 -13
  33. data/spec/platform/windows_volume_manager_spec.rb +0 -318
@@ -0,0 +1,149 @@
1
+ #
2
+ # Copyright (c) 2013 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require ::File.expand_path('../../spec_helper', __FILE__)
24
+
25
+ require 'stringio'
26
+
27
+ shared_examples_for 'supports unix platform filesystem' do
28
+
29
+ context '#find_executable_in_path' do
30
+ let(:path_env) { '/usr/local/bin:/usr/bin:/bin' }
31
+
32
+ it 'should find executable' do
33
+ mock_env = flexmock(::ENV)
34
+ mock_env.should_receive(:[]).with('PATH').and_return(path_env)
35
+
36
+ file_class.should_receive(:executable?).with('/usr/local/bin/foo').and_return(false).twice
37
+ file_class.should_receive(:executable?).with('/usr/bin/foo').and_return(true).twice
38
+ file_class.should_receive(:executable?).with('/usr/local/bin/bar').and_return(false).twice
39
+ file_class.should_receive(:executable?).with('/usr/bin/bar').and_return(false).twice
40
+ file_class.should_receive(:executable?).with('/bin/bar').and_return(false).twice
41
+
42
+ subject.find_executable_in_path('foo').should == '/usr/bin/foo'
43
+ subject.has_executable_in_path('foo').should be_true
44
+ subject.find_executable_in_path('bar').should be_nil
45
+ subject.has_executable_in_path('bar').should be_false
46
+ end
47
+ end # find_executable_in_path
48
+
49
+ context 'paths' do
50
+ it 'should return unix path constants' do
51
+ subject.right_agent_cfg_dir.should == '/var/lib/rightscale/right_agent'
52
+ subject.right_scale_static_state_dir.should == '/etc/rightscale.d'
53
+ subject.right_link_static_state_dir.should == '/etc/rightscale.d/right_link'
54
+ subject.right_link_dynamic_state_dir.should == '/var/lib/rightscale/right_link'
55
+ subject.spool_dir.should == '/var/spool'
56
+ subject.ssh_cfg_dir.should == '/etc/ssh'
57
+ subject.cache_dir.should == '/var/cache'
58
+ subject.log_dir.should == '/var/log'
59
+ subject.source_code_dir.should == '/usr/src'
60
+ subject.temp_dir.should == '/tmp'
61
+ subject.pid_dir.should == '/var/run'
62
+ subject.right_link_home_dir.should == '/opt/rightscale'
63
+ subject.private_bin_dir.should == '/opt/rightscale/bin'
64
+ subject.sandbox_dir.should == '/opt/rightscale/sandbox'
65
+ end
66
+
67
+ it 'should return unmodified paths from Windows compatibility methods' do
68
+ path = '/tmp/some_path_to_test'
69
+ subject.long_path_to_short_path(path).should == path
70
+ subject.pretty_path(path, false).should == path
71
+ subject.pretty_path(path, true).should == path
72
+ subject.ensure_local_drive_path(path, 'foo').should == path
73
+ end
74
+ end # paths
75
+
76
+ context '#create_symlink' do
77
+ it 'should use ruby file to create symlink (under unix)' do
78
+ file_class.should_receive(:symlink).with('/tmp/from', '/tmp/to').and_return(0)
79
+ subject.create_symlink('/tmp/from', '/tmp/to').should == 0
80
+ end
81
+ end # create_symlink
82
+ end # supports unix platform filesystem
83
+
84
+ shared_examples_for 'supports unix platform shell' do
85
+ it_should_behave_like 'supports any platform shell'
86
+
87
+ context 'paths' do
88
+ it 'should return path constants for unix' do
89
+ subject.null_output_name.should == '/dev/null'
90
+ subject.sandbox_ruby.should == '/opt/rightscale/sandbox/bin/ruby'
91
+ end
92
+ end # paths
93
+
94
+ context 'commands' do
95
+ it 'should return unmodified commands from Windows compatibility methods' do
96
+ cmd = 'sh -c echo foo'
97
+ subject.format_script_file_name(cmd).should == cmd
98
+ subject.format_script_file_name(cmd, '.foo').should == cmd
99
+ end
100
+
101
+ [:format_executable_command, :format_shell_command].each do |methud|
102
+ context methud do
103
+ it 'should format commands' do
104
+ subject.send(methud, 'foo').should == 'foo'
105
+ subject.send(methud, 'bar', 'foo').should == 'bar foo'
106
+ subject.send(methud, 'baz', 'a b', "c'd", 'foo').should == "baz \"a b\" \"c'd\" foo"
107
+ end
108
+ end # methud
109
+ end # for each method (having identical behavior under unix)
110
+
111
+ it 'should format ruby commands using sandbox ruby' do
112
+ script_path = '/tmp/foo.rb'
113
+ subject.format_ruby_command(script_path).should == '/opt/rightscale/sandbox/bin/ruby /tmp/foo.rb'
114
+ subject.format_ruby_command(script_path, 'bar').should == '/opt/rightscale/sandbox/bin/ruby /tmp/foo.rb bar'
115
+ end
116
+ end # commands
117
+ end # supports unix platform shell
118
+
119
+ shared_examples_for 'supports unix platform rng' do
120
+ context '#pseudorandom_bytes' do
121
+ it 'should read requested byte length from urandom device under unix' do
122
+ sio = StringIO.new
123
+ buffer = 0.chr * 256
124
+ 256.times.each { |i| buffer[i] = i.chr }
125
+ sio.write buffer
126
+ sio.rewind
127
+ file_class.should_receive(:open).with('/dev/urandom', 'r', Proc).and_yield(sio)
128
+ subject.pseudorandom_bytes(16).should == buffer[0, 16]
129
+ subject.pseudorandom_bytes(32).should == buffer[16, 32]
130
+ end
131
+ end # pseudorandom_bytes
132
+ end # supports unix platform rng
133
+
134
+ shared_examples_for 'supports unix platform process' do
135
+ context '#resident_set_size' do
136
+ it 'should return resident set size for current process' do
137
+ cmd = "ps -o rss= -p #{$$}"
138
+ platform_class.should_receive(:execute).with(cmd, {}).and_return('12345').once
139
+ subject.resident_set_size.should == 12345
140
+ end
141
+
142
+ it 'should return resident set size for other process' do
143
+ pid = 789
144
+ cmd = "ps -o rss= -p #{pid}"
145
+ platform_class.should_receive(:execute).with(cmd, {}).and_return('23456').once
146
+ subject.resident_set_size(pid).should == 23456
147
+ end
148
+ end # pseudorandom_bytes
149
+ end # supports unix platform rng
@@ -0,0 +1,222 @@
1
+ #
2
+ # Copyright (c) 2013 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require ::File.expand_path('../../spec_helper', __FILE__)
24
+
25
+ # stub FII for testing on non-mingw platforms; any mingw-specific tests must
26
+ # mock API calls.
27
+ module FFI
28
+ module Library
29
+
30
+ def typedef(*args)
31
+ true
32
+ end
33
+
34
+ def ffi_lib(*args)
35
+ true
36
+ end
37
+
38
+ def ffi_convention(*args)
39
+ true
40
+ end
41
+
42
+ def attach_function(*args)
43
+ true
44
+ end
45
+ end
46
+ end
47
+
48
+ describe RightScale::Platform do
49
+
50
+ include PlatformSpecHelper
51
+
52
+ context 'windows/mingw' do
53
+
54
+ # required by before_all_platform_tests
55
+ # called by before(:all) so not defined using let().
56
+ def expected_genus; :windows; end
57
+ def expected_species; :mingw; end
58
+
59
+ def to_wide(str)
60
+ str.encode(::RightScale::Platform::PlatformHelperBase::WIDE)
61
+ end
62
+
63
+ def instrument_win32_error(error_code, error_message)
64
+ flexmock(::FFI).should_receive(:errno).and_return(error_code).once
65
+ flexmock(described_class::WindowsCommon::API).
66
+ should_receive(:FormatMessageW).
67
+ with(0x1200, nil, error_code, 0, String, Integer, nil).
68
+ and_return do |flags, _, message_id, _, unicode_buffer, _, _|
69
+ if flags == 0x1200 && message_id == 5
70
+ unicode_message = to_wide(error_message)
71
+ unicode_message.chars.each_with_index do |c, index|
72
+ unicode_buffer[index] = c
73
+ end
74
+ unicode_message.length
75
+ else
76
+ fail "Unexpected arguments: #{[flags, message_id].inspect}"
77
+ end
78
+ end.once
79
+ end
80
+
81
+ before(:all) do
82
+ before_all_platform_tests
83
+ end
84
+
85
+ after(:all) do
86
+ after_all_platform_tests
87
+ end
88
+
89
+ before(:each) do
90
+ before_each_platform_test
91
+ end
92
+
93
+ after(:each) do
94
+ after_each_platform_test
95
+ end
96
+
97
+ context :statics do
98
+ subject { platform_class }
99
+
100
+ it_should_behave_like 'supports windows platform statics'
101
+ end
102
+
103
+ context :initialization do
104
+ def instrument_os_info(major, minor, build)
105
+ flexmock(::FFI).should_receive(:errno).and_return(0).once
106
+ flexmock(described_class::WindowsSystemInformation::API).
107
+ should_receive(:GetVersionExW).
108
+ with(String).
109
+ and_return do |vib|
110
+ vib[4,12] = [major, minor, build].pack('LLL')
111
+ end.once
112
+ end
113
+
114
+ it_should_behave_like 'supports windows platform initialization'
115
+ end # initialization
116
+
117
+ context :controller do
118
+ subject { described_class.controller }
119
+
120
+ def instrument_initiate_system_shutdown_api(reboot_after_shutdown)
121
+ controller_api = flexmock(described_class::Controller::API)
122
+ process_api = flexmock(described_class::Process::API)
123
+ windows_common_api = flexmock(described_class::WindowsCommon::API)
124
+ windows_security_api = flexmock(described_class::WindowsSecurity::API)
125
+
126
+ process_api.should_receive(:GetCurrentProcess).and_return(-1).once
127
+ process_api.should_receive(:OpenProcessToken).and_return(true).once
128
+ windows_security_api.should_receive(:LookupPrivilegeValueW).and_return(true).once
129
+ windows_security_api.should_receive(:AdjustTokenPrivileges).and_return(true).once
130
+ controller_api.
131
+ should_receive(:InitiateSystemShutdownW).
132
+ with(nil, nil, 1, true, reboot_after_shutdown).
133
+ and_return(true).
134
+ once
135
+ windows_common_api.should_receive(:CloseHandle).and_return(true).once
136
+ end
137
+
138
+ it_should_behave_like 'supports windows platform controller'
139
+ end # controller
140
+
141
+ context :filesystem do
142
+ subject { flexmock(described_class.filesystem) }
143
+
144
+ def instrument_create_symbolic_link_api(from_path, to_path, flags, &callback)
145
+ flexmock(described_class::Filesystem::API).
146
+ should_receive(:CreateSymbolicLinkW).
147
+ with(to_wide(to_path + 0.chr), to_wide(from_path + 0.chr), flags).
148
+ and_return { callback.call == 0 ? false : true }.
149
+ once
150
+ end
151
+
152
+ def instrument_get_short_path_name_api(long_path, short_path_from_api, &callback)
153
+ flexmock(described_class::Filesystem::API).
154
+ should_receive(:GetShortPathNameW).
155
+ with(to_wide(long_path + 0.chr), String, Integer).
156
+ and_return do |lp, short_path_buffer, _|
157
+ to_wide(short_path_from_api).chars.each_with_index do |c, index|
158
+ short_path_buffer[index] = c
159
+ end
160
+ callback.call
161
+ end.once
162
+ end
163
+
164
+ def instrument_get_temp_path_api(temp_path_from_api, &callback)
165
+ flexmock(described_class::Filesystem::API).
166
+ should_receive(:GetTempPathW).
167
+ with(Integer, String).
168
+ and_return do |_, buffer|
169
+ to_wide(temp_path_from_api).chars.each_with_index do |c, index|
170
+ buffer[index] = c
171
+ end
172
+ callback.call
173
+ end.once
174
+ end
175
+
176
+ it_should_behave_like 'supports windows platform filesystem'
177
+ end # filesystem
178
+
179
+ context :installer do
180
+ subject { described_class.installer }
181
+
182
+ it_should_behave_like 'supports windows platform installer'
183
+ end # installer
184
+
185
+ context :shell do
186
+ subject { flexmock(described_class.shell) }
187
+
188
+ it_should_behave_like 'supports windows platform shell'
189
+ end # shell
190
+
191
+ context :rng do
192
+ subject { described_class.rng }
193
+
194
+ it_should_behave_like 'supports windows platform rng'
195
+ end # rng
196
+
197
+ context :process do
198
+ subject { described_class.process }
199
+
200
+ def instrument_get_process_memory_info_api(resident_set_size)
201
+ process_api = flexmock(described_class::Process::API)
202
+ process_api.should_receive(:GetCurrentProcess).and_return(-1).once
203
+ process_api.
204
+ should_receive(:GetProcessMemoryInfo).
205
+ with(-1, String, Integer).
206
+ and_return do |_, pmib, _|
207
+ pmib[3 * 4, 4] = [resident_set_size * 1024].pack('L')
208
+ true
209
+ end.once
210
+ end
211
+
212
+ it_should_behave_like 'supports windows platform process'
213
+ end # process
214
+
215
+ context :volume_manager do
216
+ subject { flexmock(described_class.volume_manager) }
217
+
218
+ it_should_behave_like 'supports windows platform volume manager'
219
+ end # volume_manager
220
+
221
+ end # windows/mingw
222
+ end # RightScale::Platform
@@ -0,0 +1,259 @@
1
+ #
2
+ # Copyright (c) 2013 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require ::File.expand_path('../../spec_helper', __FILE__)
24
+
25
+ # stub out definition of ::Win32::API for testing on non-Windows platforms.
26
+ module Win32
27
+ class API; end
28
+ end
29
+
30
+ describe RightScale::Platform do
31
+
32
+ include PlatformSpecHelper
33
+
34
+ context 'windows/mswin' do
35
+
36
+ # required by before_all_platform_tests
37
+ # called by before(:all) so not defined using let().
38
+ def expected_genus; :windows; end
39
+ def expected_species; :mswin; end
40
+
41
+ def instrument_win32_error(error_code, error_message)
42
+ w32a = flexmock(::Win32::API)
43
+ w32a.
44
+ should_receive(:new).
45
+ with('GetLastError', 'V', 'L', 'kernel32').
46
+ and_return(lambda { error_code }).
47
+ once
48
+ w32a.
49
+ should_receive(:new).
50
+ with('FormatMessage', 'LLLLPLP', 'L', 'kernel32').
51
+ and_return do
52
+ lambda do |flags, _, message_id, _, buffer, _, _|
53
+
54
+ if flags == 0x1200 && message_id == 5
55
+ error_message.chars.each_with_index do |c, index|
56
+ buffer[index] = c
57
+ end
58
+ error_message.length
59
+ else
60
+ fail "Unexpected arguments: #{[mn, m, t, tac, ras].inspect}"
61
+ end
62
+ end
63
+ end.once
64
+ end
65
+
66
+ before(:all) do
67
+ before_all_platform_tests
68
+ end
69
+
70
+ after(:all) do
71
+ after_all_platform_tests
72
+ end
73
+
74
+ before(:each) do
75
+ before_each_platform_test
76
+ end
77
+
78
+ after(:each) do
79
+ after_each_platform_test
80
+ end
81
+
82
+ context :statics do
83
+ subject { platform_class }
84
+
85
+ it_should_behave_like 'supports windows platform statics'
86
+ end
87
+
88
+ context :initialization do
89
+ def instrument_os_info(major, minor, build)
90
+ w32a = flexmock(::Win32::API)
91
+ w32a.
92
+ should_receive(:new).
93
+ with('GetLastError', 'V', 'L', 'kernel32').
94
+ and_return(lambda { 0 }).
95
+ once
96
+ w32a.
97
+ should_receive(:new).
98
+ with('GetVersionEx', 'P', 'L', 'kernel32').
99
+ and_return(
100
+ lambda do |vib|
101
+ vib[4,12] = [major, minor, build].pack('LLL')
102
+ 1
103
+ end
104
+ ).once
105
+ end
106
+
107
+ it_should_behave_like 'supports windows platform initialization'
108
+ end # initialization
109
+
110
+ context :controller do
111
+ subject { described_class.controller }
112
+
113
+ def instrument_initiate_system_shutdown_api(reboot_after_shutdown)
114
+ w32a = flexmock(::Win32::API)
115
+ w32a.
116
+ should_receive(:new).
117
+ with('GetCurrentProcess', 'V', 'L', 'kernel32').
118
+ and_return(lambda { -1 }).
119
+ once
120
+ w32a.
121
+ should_receive(:new).
122
+ with('OpenProcessToken', 'LLP', 'B', 'advapi32').
123
+ and_return(lambda { |ph, da, th| 1 }).
124
+ once
125
+ w32a.
126
+ should_receive(:new).
127
+ with('LookupPrivilegeValue', 'PPP', 'B', 'advapi32').
128
+ and_return(lambda { |sn, n, luid| 1 }).
129
+ once
130
+ w32a.
131
+ should_receive(:new).
132
+ with('AdjustTokenPrivileges', 'LLPLPP', 'B', 'advapi32').
133
+ and_return(lambda { |th, dap, ns, bl, ps, rl| 1 }).
134
+ once
135
+ w32a.
136
+ should_receive(:new).
137
+ with('InitiateSystemShutdown', 'PPLLL', 'B', 'advapi32').
138
+ and_return(
139
+ lambda do |mn, m, t, tac, ras|
140
+ if mn == 0 && m == 0 && t == 1 && tac == 1 && ras == (reboot_after_shutdown ? 1 : 0)
141
+ 1
142
+ else
143
+ fail "Unexpected arguments: #{[mn, m, t, tac, ras].inspect}"
144
+ end
145
+ end
146
+ ).once
147
+ w32a.
148
+ should_receive(:new).
149
+ with('CloseHandle', 'L', 'B', 'kernel32').
150
+ and_return(lambda { |h| 1 }).
151
+ once
152
+ end
153
+
154
+ it_should_behave_like 'supports windows platform controller'
155
+ end # controller
156
+
157
+ context :filesystem do
158
+ subject { flexmock(described_class.filesystem) }
159
+
160
+ def instrument_create_symbolic_link_api(from_path, to_path, flags, &callback)
161
+ flexmock(::Win32::API).
162
+ should_receive(:new).
163
+ with('CreateSymbolicLink', 'SSL', 'B', 'kernel32').
164
+ and_return(
165
+ lambda do |tp, fp, fgs|
166
+ if fp == (from_path + 0.chr) && tp == (to_path + 0.chr) && fgs == flags
167
+ callback.call
168
+ else
169
+ fail "Unexpected arguments: #{[tp, fp, fgs].inspect}"
170
+ end
171
+ end
172
+ ).once
173
+ end
174
+
175
+ def instrument_get_short_path_name_api(long_path, short_path_from_api, &callback)
176
+ flexmock(::Win32::API).
177
+ should_receive(:new).
178
+ with('GetShortPathName', 'SPL', 'L', 'kernel32').
179
+ and_return(
180
+ lambda do |lp, short_path_buffer, short_path_buffer_length|
181
+ if lp == (long_path + 0.chr)
182
+ short_path_from_api.chars.each_with_index do |c, index|
183
+ short_path_buffer[index] = c
184
+ end
185
+ callback.call
186
+ else
187
+ fail "Unexpected arguments: #{lp.inspect}"
188
+ end
189
+ end
190
+ ).once
191
+ end
192
+
193
+ def instrument_get_temp_path_api(temp_path_from_api, &callback)
194
+ flexmock(::Win32::API).
195
+ should_receive(:new).
196
+ with('GetTempPath', 'LP', 'L', 'kernel32').
197
+ and_return(
198
+ lambda do |buffer_length, buffer|
199
+ temp_path_from_api.chars.each_with_index do |c, index|
200
+ buffer[index] = c
201
+ end
202
+ callback.call
203
+ end
204
+ ).once
205
+ end
206
+
207
+ it_should_behave_like 'supports windows platform filesystem'
208
+ end # filesystem
209
+
210
+ context :installer do
211
+ subject { described_class.installer }
212
+
213
+ it_should_behave_like 'supports windows platform installer'
214
+ end # installer
215
+
216
+ context :shell do
217
+ subject { flexmock(described_class.shell) }
218
+
219
+ it_should_behave_like 'supports windows platform shell'
220
+ end # shell
221
+
222
+ context :rng do
223
+ subject { described_class.rng }
224
+
225
+ it_should_behave_like 'supports windows platform rng'
226
+ end # rng
227
+
228
+ context :process do
229
+ subject { described_class.process }
230
+
231
+ def instrument_get_process_memory_info_api(resident_set_size)
232
+ w32a = flexmock(::Win32::API)
233
+ w32a.
234
+ should_receive(:new).
235
+ with('GetCurrentProcess', 'V', 'L', 'kernel32').
236
+ and_return(lambda { -1 }).
237
+ once
238
+ w32a.
239
+ should_receive(:new).
240
+ with('GetProcessMemoryInfo', 'LPL', 'B', 'psapi').
241
+ and_return(
242
+ lambda do |ph, pmib, pmibs|
243
+ pmib[3 * 4, 4] = [resident_set_size * 1024].pack('L')
244
+ 1
245
+ end
246
+ ).once
247
+ end
248
+
249
+ it_should_behave_like 'supports windows platform process'
250
+ end # process
251
+
252
+ context :volume_manager do
253
+ subject { flexmock(described_class.volume_manager) }
254
+
255
+ it_should_behave_like 'supports windows platform volume manager'
256
+ end # volume_manager
257
+
258
+ end # windows/mswin
259
+ end # RightScale::Platform