Skip to content

Commit

Permalink
Merge pull request #134 from da-ar/js_test
Browse files Browse the repository at this point in the history
Support non-ASCII characters on Windows
  • Loading branch information
sds authored Jan 12, 2019
2 parents f46f3c5 + 69e62a5 commit 0f336be
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 17 deletions.
4 changes: 2 additions & 2 deletions lib/childprocess/windows/lib.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ module Lib
# );
#

attach_function :create_process, :CreateProcessA, [
:pointer,
attach_function :create_process, :CreateProcessW, [
:pointer,
:buffer_inout,
:pointer,
:pointer,
:bool,
Expand Down
19 changes: 11 additions & 8 deletions lib/childprocess/windows/process_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,14 @@ def start

private

def to_wide_string(str)
newstr = str + "\0".encode(str.encoding)
newstr.encode!('UTF-16LE')
end

def create_command_pointer
string = @args.map { |arg| quote_if_necessary(arg.to_s) }.join ' '
@cmd_ptr = FFI::MemoryPointer.from_string string
string = @args.map { |arg| quote_if_necessary(arg.to_s) }.join(' ')
@cmd_ptr = to_wide_string(string)
end

def create_environment_pointer
Expand All @@ -59,15 +64,12 @@ def create_environment_pointer
strings << "#{key}=#{val}\0"
end

strings << "\0" # terminate the env block
env_str = strings.join

@env_ptr = FFI::MemoryPointer.new(:long, env_str.bytesize)
@env_ptr.put_bytes 0, env_str, 0, env_str.bytesize
env_str = to_wide_string(strings.join)
@env_ptr = FFI::MemoryPointer.from_string(env_str)
end

def create_cwd_pointer
@cwd_ptr = FFI::MemoryPointer.from_string(@cwd || Dir.pwd)
@cwd_ptr = FFI::MemoryPointer.from_string(to_wide_string(@cwd || Dir.pwd))
end

def create_process
Expand Down Expand Up @@ -98,6 +100,7 @@ def process_info
end

def setup_flags
@flags |= CREATE_UNICODE_ENVIRONMENT
@flags |= DETACHED_PROCESS if @detach
@flags |= CREATE_BREAKAWAY_FROM_JOB if @leader
end
Expand Down
25 changes: 25 additions & 0 deletions spec/childprocess_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,21 @@

it "lets child process inherit the environment of the current process" do
Tempfile.open("env-spec") do |file|
file.close
with_env('INHERITED' => 'yes') do
process = write_env(file.path).start
process.wait
end

file.open
child_env = eval rewind_and_read(file)
expect(child_env['INHERITED']).to eql 'yes'
end
end

it "can override env vars only for the current process" do
Tempfile.open("env-spec") do |file|
file.close
process = write_env(file.path)
process.environment['CHILD_ONLY'] = '1'
process.start
Expand All @@ -103,20 +106,38 @@

process.wait

file.open
child_env = eval rewind_and_read(file)
expect(child_env['CHILD_ONLY']).to eql '1'
end
end

it 'allows unicode characters in the environment' do
Tempfile.open("env-spec") do |file|
file.close
process = write_env(file.path)
process.environment['FOö'] = 'baör'
process.start
process.wait

file.open
child_env = eval rewind_and_read(file)

expect(child_env['FOö']).to eql 'baör'
end
end

it "inherits the parent's env vars also when some are overridden" do
Tempfile.open("env-spec") do |file|
file.close
with_env('INHERITED' => 'yes', 'CHILD_ONLY' => 'no') do
process = write_env(file.path)
process.environment['CHILD_ONLY'] = 'yes'

process.start
process.wait

file.open
child_env = eval rewind_and_read(file)

expect(child_env['INHERITED']).to eq 'yes'
Expand All @@ -127,26 +148,30 @@

it "can unset env vars" do
Tempfile.open("env-spec") do |file|
file.close
ENV['CHILDPROCESS_UNSET'] = '1'
process = write_env(file.path)
process.environment['CHILDPROCESS_UNSET'] = nil
process.start

process.wait

file.open
child_env = eval rewind_and_read(file)
expect(child_env).to_not have_key('CHILDPROCESS_UNSET')
end
end

it 'does not see env vars unset in parent' do
Tempfile.open('env-spec') do |file|
file.close
ENV['CHILDPROCESS_UNSET'] = nil
process = write_env(file.path)
process.start

process.wait

file.open
child_env = eval rewind_and_read(file)
expect(child_env).to_not have_key('CHILDPROCESS_UNSET')
end
Expand Down
13 changes: 13 additions & 0 deletions spec/get_env.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
param($p1)
$env_list = Get-ChildItem Env:

# Builds a ruby hash compatible string
$hash_string = "{"

foreach ($item in $env_list)
{
$hash_string += "`"" + $item.Name + "`" => `"" + $item.value.replace('\','\\').replace('"','\"') + "`","
}
$hash_string += "}"

$hash_string | out-File -Encoding "UTF8" $p1
23 changes: 16 additions & 7 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ def ruby_process(*args)
@process = ChildProcess.build(RUBY , *args)
end

def windows_process(*args)
@process = ChildProcess.build("powershell", *args)
end

def sleeping_ruby(seconds = nil)
if seconds
ruby_process("-e", "sleep #{seconds}")
Expand All @@ -42,11 +46,16 @@ def ignored(signal)
end

def write_env(path)
code = <<-RUBY
File.open(#{path.inspect}, "w") { |f| f << ENV.inspect }
RUBY

ruby_process tmp_script(code)
if ChildProcess.os == :windows
ps_env_file_path = File.expand_path(File.dirname(__FILE__))
args = ['-File', "#{ps_env_file_path}/get_env.ps1", path]
windows_process(*args)
else
code = <<-RUBY
File.open(#{path.inspect}, "w") { |f| f << ENV.inspect }
RUBY
ruby_process tmp_script(code)
end
end

def write_argv(path, *args)
Expand Down Expand Up @@ -102,7 +111,7 @@ def cat
ruby(<<-CODE)
STDIN.sync = STDOUT.sync = true
IO.copy_stream(STDIN, STDOUT)
CODE
CODE
else
ChildProcess.build("cat")
end
Expand All @@ -115,7 +124,7 @@ def echo
STDOUT.sync = true
puts "hello"
CODE
CODE
else
ChildProcess.build("echo", "hello")
end
Expand Down

0 comments on commit 0f336be

Please sign in to comment.