summaryrefslogtreecommitdiff
path: root/spec/ruby/core/process
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/process')
-rw-r--r--spec/ruby/core/process/_fork_spec.rb24
-rw-r--r--spec/ruby/core/process/argv0_spec.rb25
-rw-r--r--spec/ruby/core/process/clock_getres_spec.rb43
-rw-r--r--spec/ruby/core/process/clock_gettime_spec.rb110
-rw-r--r--spec/ruby/core/process/constants_spec.rb141
-rw-r--r--spec/ruby/core/process/daemon_spec.rb5
-rw-r--r--spec/ruby/core/process/detach_spec.rb37
-rw-r--r--spec/ruby/core/process/egid_spec.rb41
-rw-r--r--spec/ruby/core/process/euid_spec.rb18
-rw-r--r--spec/ruby/core/process/exec_spec.rb105
-rw-r--r--spec/ruby/core/process/exit_spec.rb2
-rw-r--r--spec/ruby/core/process/fixtures/argv0.rb6
-rw-r--r--spec/ruby/core/process/fixtures/clocks.rb44
-rw-r--r--spec/ruby/core/process/fixtures/common.rb8
-rw-r--r--spec/ruby/core/process/fixtures/kill.rb2
-rw-r--r--spec/ruby/core/process/getpriority_spec.rb8
-rw-r--r--spec/ruby/core/process/getrlimit_spec.rb19
-rw-r--r--spec/ruby/core/process/gid_spec.rb4
-rw-r--r--spec/ruby/core/process/groups_spec.rb10
-rw-r--r--spec/ruby/core/process/initgroups_spec.rb4
-rw-r--r--spec/ruby/core/process/kill_spec.rb10
-rw-r--r--spec/ruby/core/process/last_status_spec.rb26
-rw-r--r--spec/ruby/core/process/maxgroups_spec.rb2
-rw-r--r--spec/ruby/core/process/pid_spec.rb2
-rw-r--r--spec/ruby/core/process/setrlimit_spec.rb51
-rw-r--r--spec/ruby/core/process/spawn_spec.rb262
-rw-r--r--spec/ruby/core/process/status/bit_and_spec.rb37
-rw-r--r--spec/ruby/core/process/status/equal_value_spec.rb12
-rw-r--r--spec/ruby/core/process/status/exited_spec.rb7
-rw-r--r--spec/ruby/core/process/status/exitstatus_spec.rb4
-rw-r--r--spec/ruby/core/process/status/right_shift_spec.rb36
-rw-r--r--spec/ruby/core/process/status/signaled_spec.rb6
-rw-r--r--spec/ruby/core/process/status/success_spec.rb14
-rw-r--r--spec/ruby/core/process/status/termsig_spec.rb14
-rw-r--r--spec/ruby/core/process/status/to_i_spec.rb10
-rw-r--r--spec/ruby/core/process/status/wait_spec.rb100
-rw-r--r--spec/ruby/core/process/times_spec.rb26
-rw-r--r--spec/ruby/core/process/tms/cstime_spec.rb12
-rw-r--r--spec/ruby/core/process/tms/cutime_spec.rb12
-rw-r--r--spec/ruby/core/process/tms/element_reference_spec.rb5
-rw-r--r--spec/ruby/core/process/tms/members_spec.rb5
-rw-r--r--spec/ruby/core/process/tms/new_spec.rb5
-rw-r--r--spec/ruby/core/process/tms/stime_spec.rb12
-rw-r--r--spec/ruby/core/process/tms/utime_spec.rb12
-rw-r--r--spec/ruby/core/process/uid_spec.rb6
-rw-r--r--spec/ruby/core/process/wait2_spec.rb17
-rw-r--r--spec/ruby/core/process/wait_spec.rb17
-rw-r--r--spec/ruby/core/process/waitall_spec.rb4
-rw-r--r--spec/ruby/core/process/waitpid_spec.rb3
-rw-r--r--spec/ruby/core/process/warmup_spec.rb11
50 files changed, 952 insertions, 444 deletions
diff --git a/spec/ruby/core/process/_fork_spec.rb b/spec/ruby/core/process/_fork_spec.rb
new file mode 100644
index 0000000000..e1f45e2656
--- /dev/null
+++ b/spec/ruby/core/process/_fork_spec.rb
@@ -0,0 +1,24 @@
+require_relative '../../spec_helper'
+
+describe "Process._fork" do
+ it "for #respond_to? returns the same as Process.respond_to?(:fork)" do
+ Process.respond_to?(:_fork).should == Process.respond_to?(:fork)
+ end
+
+ # Using respond_to? in a guard here is OK because the correct semantics
+ # are that _fork is implemented if and only if fork is (see above).
+ guard_not -> { Process.respond_to?(:fork) } do
+ it "raises a NotImplementedError when called" do
+ -> { Process._fork }.should raise_error(NotImplementedError)
+ end
+ end
+
+ guard -> { Process.respond_to?(:fork) } do
+ it "is called by Process#fork" do
+ Process.should_receive(:_fork).once.and_return(42)
+
+ pid = Process.fork {}
+ pid.should equal(42)
+ end
+ end
+end
diff --git a/spec/ruby/core/process/argv0_spec.rb b/spec/ruby/core/process/argv0_spec.rb
new file mode 100644
index 0000000000..f5aba719e9
--- /dev/null
+++ b/spec/ruby/core/process/argv0_spec.rb
@@ -0,0 +1,25 @@
+require_relative '../../spec_helper'
+
+describe "Process.argv0" do
+ it "returns a String" do
+ Process.argv0.should be_kind_of(String)
+ end
+
+ it "is the path given as the main script and the same as __FILE__" do
+ script = "fixtures/argv0.rb"
+
+ Dir.chdir(__dir__) do
+ ruby_exe(script).should == "#{script}\n#{script}\nOK"
+ end
+ end
+
+ ruby_bug "#19597", ""..."3.3" do
+ it "returns a frozen object" do
+ Process.argv0.should.frozen?
+ end
+ end
+
+ it "returns every time the same object" do
+ Process.argv0.should.equal?(Process.argv0)
+ end
+end
diff --git a/spec/ruby/core/process/clock_getres_spec.rb b/spec/ruby/core/process/clock_getres_spec.rb
index 7112b0520a..85aa2b25f1 100644
--- a/spec/ruby/core/process/clock_getres_spec.rb
+++ b/spec/ruby/core/process/clock_getres_spec.rb
@@ -1,37 +1,6 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/clocks'
describe "Process.clock_getres" do
- # clock_getres() seems completely buggy on FreeBSD:
- # https://rubyci.org/logs/rubyci.s3.amazonaws.com/freebsd11zfs/ruby-trunk/log/20190428T093003Z.fail.html.gz
- platform_is_not :freebsd, :openbsd do
- # NOTE: Look at fixtures/clocks.rb for clock and OS-specific exclusions
- ProcessSpecs.clock_constants_for_resolution_checks.each do |name, value|
- it "matches the clock in practice for Process::#{name}" do
- times = []
- 10_000.times do
- times << Process.clock_gettime(value, :nanosecond)
- end
- reported = Process.clock_getres(value, :nanosecond)
-
- # The clock should not be more accurate than reported (times should be
- # a multiple of reported precision.)
- times.select { |t| t % reported > 0 }.should be_empty
-
- # We're assuming precision is a multiple of ten - it may or may not
- # be an incompatibility if it isn't but we'd like to notice this,
- # and the spec following these wouldn't work if it isn't.
- reported.should > 0
- (reported == 1 || reported % 10 == 0).should be_true
-
- # The clock should not be less accurate than reported (times should
- # not all be a multiple of the next precision up, assuming precisions
- # are multiples of ten.)
- times.select { |t| t % (reported * 10) == 0 }.size.should_not == times.size
- end
- end
- end
-
# These are documented
it "with :GETTIMEOFDAY_BASED_CLOCK_REALTIME reports 1 microsecond" do
@@ -50,15 +19,15 @@ describe "Process.clock_getres" do
# These are observed
- platform_is_not :solaris, :aix, :openbsd do
- it "with Process::CLOCK_REALTIME reports at least 1 microsecond" do
- Process.clock_getres(Process::CLOCK_REALTIME, :nanosecond).should <= 1_000
+ platform_is :linux, :darwin, :windows do
+ it "with Process::CLOCK_REALTIME reports at least 10 millisecond" do
+ Process.clock_getres(Process::CLOCK_REALTIME, :nanosecond).should <= 10_000_000
end
end
- platform_is_not :aix, :openbsd do
- it "with Process::CLOCK_MONOTONIC reports at least 1 microsecond" do
- Process.clock_getres(Process::CLOCK_MONOTONIC, :nanosecond).should <= 1_000
+ platform_is :linux, :darwin, :windows do
+ it "with Process::CLOCK_MONOTONIC reports at least 10 millisecond" do
+ Process.clock_getres(Process::CLOCK_MONOTONIC, :nanosecond).should <= 10_000_000
end
end
end
diff --git a/spec/ruby/core/process/clock_gettime_spec.rb b/spec/ruby/core/process/clock_gettime_spec.rb
index 4cd13857ea..6c1a52f21e 100644
--- a/spec/ruby/core/process/clock_gettime_spec.rb
+++ b/spec/ruby/core/process/clock_gettime_spec.rb
@@ -20,7 +20,7 @@ describe "Process.clock_gettime" do
end
it 'raises an ArgumentError for an invalid time unit' do
- lambda { Process.clock_gettime(Process::CLOCK_MONOTONIC, :bad) }.should raise_error(ArgumentError)
+ -> { Process.clock_gettime(Process::CLOCK_MONOTONIC, :bad) }.should raise_error(ArgumentError)
end
it 'defaults to :float_second' do
@@ -41,4 +41,112 @@ describe "Process.clock_gettime" do
t2.should be_close(t1, TIME_TOLERANCE)
end
end
+
+ describe "supports the platform clocks mentioned in the documentation" do
+ it "CLOCK_REALTIME" do
+ Process.clock_gettime(Process::CLOCK_REALTIME).should be_an_instance_of(Float)
+ end
+
+ it "CLOCK_MONOTONIC" do
+ Process.clock_gettime(Process::CLOCK_MONOTONIC).should be_an_instance_of(Float)
+ end
+
+ # These specs need macOS 10.12+ / darwin 16+
+ guard -> { platform_is_not(:darwin) or kernel_version_is '16' } do
+ platform_is :linux, :openbsd, :darwin do
+ it "CLOCK_PROCESS_CPUTIME_ID" do
+ Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID).should be_an_instance_of(Float)
+ end
+ end
+
+ platform_is :linux, :freebsd, :openbsd, :darwin do
+ it "CLOCK_THREAD_CPUTIME_ID" do
+ Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID).should be_an_instance_of(Float)
+ end
+ end
+
+ platform_is :linux, :darwin do
+ it "CLOCK_MONOTONIC_RAW" do
+ Process.clock_gettime(Process::CLOCK_MONOTONIC_RAW).should be_an_instance_of(Float)
+ end
+ end
+
+ platform_is :darwin do
+ it "CLOCK_MONOTONIC_RAW_APPROX" do
+ Process.clock_gettime(Process::CLOCK_MONOTONIC_RAW_APPROX).should be_an_instance_of(Float)
+ end
+
+ it "CLOCK_UPTIME_RAW and CLOCK_UPTIME_RAW_APPROX" do
+ Process.clock_gettime(Process::CLOCK_UPTIME_RAW).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_UPTIME_RAW_APPROX).should be_an_instance_of(Float)
+ end
+ end
+ end
+
+ platform_is :freebsd do
+ it "CLOCK_VIRTUAL" do
+ Process.clock_gettime(Process::CLOCK_VIRTUAL).should be_an_instance_of(Float)
+ end
+
+ it "CLOCK_PROF" do
+ Process.clock_gettime(Process::CLOCK_PROF).should be_an_instance_of(Float)
+ end
+ end
+
+ platform_is :freebsd, :openbsd do
+ it "CLOCK_UPTIME" do
+ Process.clock_gettime(Process::CLOCK_UPTIME).should be_an_instance_of(Float)
+ end
+ end
+
+ platform_is :freebsd do
+ it "CLOCK_REALTIME_FAST and CLOCK_REALTIME_PRECISE" do
+ Process.clock_gettime(Process::CLOCK_REALTIME_FAST).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_REALTIME_PRECISE).should be_an_instance_of(Float)
+ end
+
+ it "CLOCK_MONOTONIC_FAST and CLOCK_MONOTONIC_PRECISE" do
+ Process.clock_gettime(Process::CLOCK_MONOTONIC_FAST).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_MONOTONIC_PRECISE).should be_an_instance_of(Float)
+ end
+
+ it "CLOCK_UPTIME_FAST and CLOCK_UPTIME_PRECISE" do
+ Process.clock_gettime(Process::CLOCK_UPTIME_FAST).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_UPTIME_PRECISE).should be_an_instance_of(Float)
+ end
+
+ it "CLOCK_SECOND" do
+ Process.clock_gettime(Process::CLOCK_SECOND).should be_an_instance_of(Float)
+ end
+ end
+
+ guard -> { platform_is :linux and kernel_version_is '2.6.32' } do
+ it "CLOCK_REALTIME_COARSE" do
+ Process.clock_gettime(Process::CLOCK_REALTIME_COARSE).should be_an_instance_of(Float)
+ end
+
+ it "CLOCK_MONOTONIC_COARSE" do
+ Process.clock_gettime(Process::CLOCK_MONOTONIC_COARSE).should be_an_instance_of(Float)
+ end
+ end
+
+ guard -> { platform_is :linux and kernel_version_is '2.6.39' } do
+ it "CLOCK_BOOTTIME" do
+ skip "No Process::CLOCK_BOOTTIME" unless defined?(Process::CLOCK_BOOTTIME)
+ Process.clock_gettime(Process::CLOCK_BOOTTIME).should be_an_instance_of(Float)
+ end
+ end
+
+ guard -> { platform_is "x86_64-linux" and kernel_version_is '3.0' } do
+ it "CLOCK_REALTIME_ALARM" do
+ skip "No Process::CLOCK_REALTIME_ALARM" unless defined?(Process::CLOCK_REALTIME_ALARM)
+ Process.clock_gettime(Process::CLOCK_REALTIME_ALARM).should be_an_instance_of(Float)
+ end
+
+ it "CLOCK_BOOTTIME_ALARM" do
+ skip "No Process::CLOCK_BOOTTIME_ALARM" unless defined?(Process::CLOCK_BOOTTIME_ALARM)
+ Process.clock_gettime(Process::CLOCK_BOOTTIME_ALARM).should be_an_instance_of(Float)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/process/constants_spec.rb b/spec/ruby/core/process/constants_spec.rb
index 2fa93ad8bf..57cacadef2 100644
--- a/spec/ruby/core/process/constants_spec.rb
+++ b/spec/ruby/core/process/constants_spec.rb
@@ -1,63 +1,114 @@
+require_relative '../../spec_helper'
describe "Process::Constants" do
platform_is :darwin, :netbsd, :freebsd do
- it "has the correct constant values on BSD-like systems" do
- Process::WNOHANG.should == 1
- Process::WUNTRACED.should == 2
- Process::PRIO_PROCESS.should == 0
- Process::PRIO_PGRP.should == 1
- Process::PRIO_USER.should == 2
- Process::RLIM_INFINITY.should == 9223372036854775807
- Process::RLIMIT_CPU.should == 0
- Process::RLIMIT_FSIZE.should == 1
- Process::RLIMIT_DATA.should == 2
- Process::RLIMIT_STACK.should == 3
- Process::RLIMIT_CORE.should == 4
- Process::RLIMIT_RSS.should == 5
- Process::RLIMIT_MEMLOCK.should == 6
- Process::RLIMIT_NPROC.should == 7
- Process::RLIMIT_NOFILE.should == 8
+ it "are all present on BSD-like systems" do
+ %i[
+ WNOHANG
+ WUNTRACED
+ PRIO_PROCESS
+ PRIO_PGRP
+ PRIO_USER
+ RLIM_INFINITY
+ RLIMIT_CPU
+ RLIMIT_FSIZE
+ RLIMIT_DATA
+ RLIMIT_STACK
+ RLIMIT_CORE
+ RLIMIT_RSS
+ RLIMIT_MEMLOCK
+ RLIMIT_NPROC
+ RLIMIT_NOFILE
+ ].each do |const|
+ Process.const_defined?(const).should be_true
+ Process.const_get(const).should be_an_instance_of(Integer)
+ end
end
end
platform_is :darwin do
- it "has the correct constant values on Darwin" do
- Process::RLIM_SAVED_MAX.should == 9223372036854775807
- Process::RLIM_SAVED_CUR.should == 9223372036854775807
- Process::RLIMIT_AS.should == 5
+ it "are all present on Darwin" do
+ %i[
+ RLIM_SAVED_MAX
+ RLIM_SAVED_CUR
+ RLIMIT_AS
+ ].each do |const|
+ Process.const_defined?(const).should be_true
+ Process.const_get(const).should be_an_instance_of(Integer)
+ end
end
end
platform_is :linux do
- it "has the correct constant values on Linux" do
- Process::WNOHANG.should == 1
- Process::WUNTRACED.should == 2
- Process::PRIO_PROCESS.should == 0
- Process::PRIO_PGRP.should == 1
- Process::PRIO_USER.should == 2
- Process::RLIMIT_CPU.should == 0
- Process::RLIMIT_FSIZE.should == 1
- Process::RLIMIT_DATA.should == 2
- Process::RLIMIT_STACK.should == 3
- Process::RLIMIT_CORE.should == 4
- Process::RLIMIT_RSS.should == 5
- Process::RLIMIT_NPROC.should == 6
- Process::RLIMIT_NOFILE.should == 7
- Process::RLIMIT_MEMLOCK.should == 8
- Process::RLIMIT_AS.should == 9
-
- # These values appear to change according to the platform.
- values = [4294967295, 9223372036854775807, 18446744073709551615]
- values.include?(Process::RLIM_INFINITY).should be_true
- values.include?(Process::RLIM_SAVED_MAX).should be_true
- values.include?(Process::RLIM_SAVED_CUR).should be_true
+ it "are all present on Linux" do
+ %i[
+ WNOHANG
+ WUNTRACED
+ PRIO_PROCESS
+ PRIO_PGRP
+ PRIO_USER
+ RLIMIT_CPU
+ RLIMIT_FSIZE
+ RLIMIT_DATA
+ RLIMIT_STACK
+ RLIMIT_CORE
+ RLIMIT_RSS
+ RLIMIT_NPROC
+ RLIMIT_NOFILE
+ RLIMIT_MEMLOCK
+ RLIMIT_AS
+ RLIM_INFINITY
+ RLIM_SAVED_MAX
+ RLIM_SAVED_CUR
+ ].each do |const|
+ Process.const_defined?(const).should be_true
+ Process.const_get(const).should be_an_instance_of(Integer)
+ end
end
end
platform_is :netbsd, :freebsd do
- it "Process::RLIMIT_SBSIZE" do
- Process::RLIMIT_SBSIZE.should == 9 # FIXME: what's it equal?
- Process::RLIMIT_AS.should == 10
+ it "are all present on NetBSD and FreeBSD" do
+ %i[
+ RLIMIT_SBSIZE
+ RLIMIT_AS
+ ].each do |const|
+ Process.const_defined?(const).should be_true
+ Process.const_get(const).should be_an_instance_of(Integer)
+ end
+ end
+ end
+
+ platform_is :freebsd do
+ it "are all present on FreeBSD" do
+ %i[
+ RLIMIT_NPTS
+ ].each do |const|
+ Process.const_defined?(const).should be_true
+ Process.const_get(const).should be_an_instance_of(Integer)
+ end
+ end
+ end
+
+ platform_is :windows do
+ it "does not define RLIMIT constants" do
+ %i[
+ RLIMIT_CPU
+ RLIMIT_FSIZE
+ RLIMIT_DATA
+ RLIMIT_STACK
+ RLIMIT_CORE
+ RLIMIT_RSS
+ RLIMIT_NPROC
+ RLIMIT_NOFILE
+ RLIMIT_MEMLOCK
+ RLIMIT_AS
+ RLIM_INFINITY
+ RLIM_SAVED_MAX
+ RLIM_SAVED_CUR
+ ].each do |const|
+ Process.const_defined?(const).should be_false
+ end
end
end
end
diff --git a/spec/ruby/core/process/daemon_spec.rb b/spec/ruby/core/process/daemon_spec.rb
index b472a3b9e9..20b0d743b9 100644
--- a/spec/ruby/core/process/daemon_spec.rb
+++ b/spec/ruby/core/process/daemon_spec.rb
@@ -2,6 +2,9 @@ require_relative '../../spec_helper'
require_relative 'fixtures/common'
platform_is_not :windows do
+ # macOS 15 is not working this examples
+ return if /darwin/ =~ RUBY_PLATFORM && /15/ =~ `sw_vers -productVersion`
+
describe :process_daemon_keep_stdio_open_false, shared: true do
it "redirects stdout to /dev/null" do
@daemon.invoke("keep_stdio_open_false_stdout", @object).should == ""
@@ -107,7 +110,7 @@ end
platform_is :windows do
describe "Process.daemon" do
it "raises a NotImplementedError" do
- lambda {
+ -> {
Process.daemon
}.should raise_error(NotImplementedError)
end
diff --git a/spec/ruby/core/process/detach_spec.rb b/spec/ruby/core/process/detach_spec.rb
index 74169a2fed..f13bda1f5d 100644
--- a/spec/ruby/core/process/detach_spec.rb
+++ b/spec/ruby/core/process/detach_spec.rb
@@ -23,7 +23,7 @@ describe "Process.detach" do
it "reaps the child process's status automatically" do
pid = Process.fork { Process.exit! }
Process.detach(pid).join
- lambda { Process.waitpid(pid) }.should raise_error(Errno::ECHILD)
+ -> { Process.waitpid(pid) }.should raise_error(Errno::ECHILD)
end
end
@@ -42,5 +42,40 @@ describe "Process.detach" do
thr.pid.should == pid
end
+
+ it "tolerates not existing child process pid" do
+ # Use a value that is close to the INT_MAX (pid usually is signed int).
+ # It should (at least) be greater than allowed pid limit value that depends on OS.
+ pid_not_existing = 2.pow(30)
+
+ # Check that there is no a child process with this hardcoded pid.
+ # Command `kill 0 pid`:
+ # - returns "1" if a process exists and
+ # - raises Errno::ESRCH otherwise
+ -> { Process.kill(0, pid_not_existing) }.should raise_error(Errno::ESRCH)
+
+ thr = Process.detach(pid_not_existing)
+ thr.join
+
+ thr.should be_kind_of(Thread)
+ end
+
+ it "calls #to_int to implicitly convert non-Integer pid to Integer" do
+ pid = MockObject.new('mock-enumerable')
+ pid.should_receive(:to_int).and_return(100500)
+
+ Process.detach(pid).join
+ end
+
+ it "raises TypeError when pid argument does not have #to_int method" do
+ -> { Process.detach(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into Integer")
+ end
+
+ it "raises TypeError when #to_int returns non-Integer value" do
+ pid = MockObject.new('mock-enumerable')
+ pid.should_receive(:to_int).and_return(:symbol)
+
+ -> { Process.detach(pid) }.should raise_error(TypeError, "can't convert MockObject to Integer (MockObject#to_int gives Symbol)")
+ end
end
end
diff --git a/spec/ruby/core/process/egid_spec.rb b/spec/ruby/core/process/egid_spec.rb
index 24dda43804..a67b623d5c 100644
--- a/spec/ruby/core/process/egid_spec.rb
+++ b/spec/ruby/core/process/egid_spec.rb
@@ -15,5 +15,44 @@ describe "Process.egid" do
end
describe "Process.egid=" do
- it "needs to be reviewed for spec completeness"
+
+ platform_is_not :windows do
+ it "raises TypeError if not passed an Integer or String" do
+ -> { Process.egid = Object.new }.should raise_error(TypeError)
+ end
+
+ it "sets the effective group id to its own gid if given the username corresponding to its own gid" do
+ raise unless Process.gid == Process.egid
+
+ require "etc"
+ group = Etc.getgrgid(Process.gid).name
+
+ Process.egid = group
+ Process.egid.should == Process.gid
+ end
+
+ as_user do
+ it "raises Errno::ERPERM if run by a non superuser trying to set the root group id" do
+ -> { Process.egid = 0 }.should raise_error(Errno::EPERM)
+ end
+
+ platform_is :linux do
+ it "raises Errno::ERPERM if run by a non superuser trying to set the group id from group name" do
+ -> { Process.egid = "root" }.should raise_error(Errno::EPERM)
+ end
+ end
+ end
+
+ as_superuser do
+ context "when ran by a superuser" do
+ it "sets the effective group id for the current process if run by a superuser" do
+ code = <<-RUBY
+ Process.egid = 1
+ puts Process.egid
+ RUBY
+ ruby_exe(code).should == "1\n"
+ end
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/process/euid_spec.rb b/spec/ruby/core/process/euid_spec.rb
index ffb71a7178..c1ec4171d0 100644
--- a/spec/ruby/core/process/euid_spec.rb
+++ b/spec/ruby/core/process/euid_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Process.euid" do
it "returns the effective user ID for this process" do
- Process.euid.should be_kind_of(Fixnum)
+ Process.euid.should be_kind_of(Integer)
end
it "also goes by Process::UID.eid" do
@@ -18,16 +18,26 @@ describe "Process.euid=" do
platform_is_not :windows do
it "raises TypeError if not passed an Integer" do
- lambda { Process.euid = Object.new }.should raise_error(TypeError)
+ -> { Process.euid = Object.new }.should raise_error(TypeError)
+ end
+
+ it "sets the effective user id to its own uid if given the username corresponding to its own uid" do
+ raise unless Process.uid == Process.euid
+
+ require "etc"
+ user = Etc.getpwuid(Process.uid).name
+
+ Process.euid = user
+ Process.euid.should == Process.uid
end
as_user do
it "raises Errno::ERPERM if run by a non superuser trying to set the superuser id" do
- lambda { (Process.euid = 0)}.should raise_error(Errno::EPERM)
+ -> { Process.euid = 0 }.should raise_error(Errno::EPERM)
end
it "raises Errno::ERPERM if run by a non superuser trying to set the superuser id from username" do
- lambda { Process.euid = "root" }.should raise_error(Errno::EPERM)
+ -> { Process.euid = "root" }.should raise_error(Errno::EPERM)
end
end
diff --git a/spec/ruby/core/process/exec_spec.rb b/spec/ruby/core/process/exec_spec.rb
index 098898d42e..0f371b39c8 100644
--- a/spec/ruby/core/process/exec_spec.rb
+++ b/spec/ruby/core/process/exec_spec.rb
@@ -2,56 +2,48 @@ require_relative '../../spec_helper'
describe "Process.exec" do
it "raises Errno::ENOENT for an empty string" do
- lambda { Process.exec "" }.should raise_error(Errno::ENOENT)
+ -> { Process.exec "" }.should raise_error(Errno::ENOENT)
end
it "raises Errno::ENOENT for a command which does not exist" do
- lambda { Process.exec "bogus-noent-script.sh" }.should raise_error(Errno::ENOENT)
+ -> { Process.exec "bogus-noent-script.sh" }.should raise_error(Errno::ENOENT)
end
it "raises an ArgumentError if the command includes a null byte" do
- lambda { Process.exec "\000" }.should raise_error(ArgumentError)
+ -> { Process.exec "\000" }.should raise_error(ArgumentError)
end
unless File.executable?(__FILE__) # Some FS (e.g. vboxfs) locate all files executable
platform_is_not :windows do
it "raises Errno::EACCES when the file does not have execute permissions" do
- lambda { Process.exec __FILE__ }.should raise_error(Errno::EACCES)
+ -> { Process.exec __FILE__ }.should raise_error(Errno::EACCES)
end
end
platform_is :windows do
it "raises Errno::EACCES or Errno::ENOEXEC when the file is not an executable file" do
- lambda { Process.exec __FILE__ }.should raise_error(SystemCallError) { |e|
+ -> { Process.exec __FILE__ }.should raise_error(SystemCallError) { |e|
[Errno::EACCES, Errno::ENOEXEC].should include(e.class)
}
end
end
end
- platform_is_not :openbsd do
- it "raises Errno::EACCES when passed a directory" do
- lambda { Process.exec File.dirname(__FILE__) }.should raise_error(Errno::EACCES)
- end
- end
-
- platform_is :openbsd do
- it "raises Errno::EISDIR when passed a directory" do
- lambda { Process.exec File.dirname(__FILE__) }.should raise_error(Errno::EISDIR)
- end
+ it "raises Errno::EACCES when passed a directory" do
+ -> { Process.exec __dir__ }.should raise_error(Errno::EACCES)
end
it "runs the specified command, replacing current process" do
- ruby_exe('Process.exec "echo hello"; puts "fail"', escape: true).should == "hello\n"
+ ruby_exe('Process.exec "echo hello"; puts "fail"').should == "hello\n"
end
it "sets the current directory when given the :chdir option" do
tmpdir = tmp("")[0..-2]
platform_is_not :windows do
- ruby_exe("Process.exec(\"pwd\", chdir: #{tmpdir.inspect})", escape: true).should == "#{tmpdir}\n"
+ ruby_exe("Process.exec(\"pwd\", chdir: #{tmpdir.inspect})").should == "#{tmpdir}\n"
end
platform_is :windows do
- ruby_exe("Process.exec(\"cd\", chdir: #{tmpdir.inspect})", escape: true).tr('\\', '/').should == "#{tmpdir}\n"
+ ruby_exe("Process.exec(\"cd\", chdir: #{tmpdir.inspect})").tr('\\', '/').should == "#{tmpdir}\n"
end
end
@@ -81,13 +73,13 @@ describe "Process.exec" do
platform_is_not :windows do
it "subjects the specified command to shell expansion" do
result = Dir.chdir(@dir) do
- ruby_exe('Process.exec "echo *"', escape: true)
+ ruby_exe('Process.exec "echo *"')
end
result.chomp.should == @name
end
it "creates an argument array with shell parsing semantics for whitespace" do
- ruby_exe('Process.exec "echo a b c d"', escape: true).should == "a b c d\n"
+ ruby_exe('Process.exec "echo a b c d"').should == "a b c d\n"
end
end
@@ -95,13 +87,13 @@ describe "Process.exec" do
# There is no shell expansion on Windows
it "does not subject the specified command to shell expansion on Windows" do
result = Dir.chdir(@dir) do
- ruby_exe('Process.exec "echo *"', escape: true)
+ ruby_exe('Process.exec "echo *"')
end
result.should == "*\n"
end
it "does not create an argument array with shell parsing semantics for whitespace on Windows" do
- ruby_exe('Process.exec "echo a b c d"', escape: true).should == "a b c d\n"
+ ruby_exe('Process.exec "echo a b c d"').should == "a b c d\n"
end
end
@@ -113,7 +105,7 @@ describe "Process.exec" do
platform_is :windows do
cmd = '"cmd.exe", "/C", "echo", "*"'
end
- ruby_exe("Process.exec #{cmd}", escape: true).should == "*\n"
+ ruby_exe("Process.exec #{cmd}").should == "*\n"
end
end
@@ -132,29 +124,29 @@ describe "Process.exec" do
end
it "sets environment variables in the child environment" do
- ruby_exe('Process.exec({"FOO" => "BAR"}, "echo ' + var + '")', escape: true).should == "BAR\n"
+ ruby_exe('Process.exec({"FOO" => "BAR"}, "echo ' + var + '")').should == "BAR\n"
end
it "unsets environment variables whose value is nil" do
platform_is_not :windows do
- ruby_exe('Process.exec({"FOO" => nil}, "echo ' + var + '")', escape: true).should == "\n"
+ ruby_exe('Process.exec({"FOO" => nil}, "echo ' + var + '")').should == "\n"
end
platform_is :windows do
# On Windows, echo-ing a non-existent env var is treated as echo-ing any other string of text
- ruby_exe('Process.exec({"FOO" => nil}, "echo ' + var + '")', escape: true).should == var + "\n"
+ ruby_exe('Process.exec({"FOO" => nil}, "echo ' + var + '")').should == var + "\n"
end
end
it "coerces environment argument using to_hash" do
- ruby_exe('o = Object.new; def o.to_hash; {"FOO" => "BAR"}; end; Process.exec(o, "echo ' + var + '")', escape: true).should == "BAR\n"
+ ruby_exe('o = Object.new; def o.to_hash; {"FOO" => "BAR"}; end; Process.exec(o, "echo ' + var + '")').should == "BAR\n"
end
it "unsets other environment variables when given a true :unsetenv_others option" do
platform_is_not :windows do
- ruby_exe('Process.exec("echo ' + var + '", unsetenv_others: true)', escape: true).should == "\n"
+ ruby_exe('Process.exec("echo ' + var + '", unsetenv_others: true)').should == "\n"
end
platform_is :windows do
- ruby_exe('Process.exec("' + ENV['COMSPEC'].gsub('\\', '\\\\\\') + ' /C echo ' + var + '", unsetenv_others: true)', escape: true).should == var + "\n"
+ ruby_exe('Process.exec("' + ENV['COMSPEC'].gsub('\\', '\\\\\\') + ' /C echo ' + var + '", unsetenv_others: true)').should == var + "\n"
end
end
end
@@ -162,26 +154,26 @@ describe "Process.exec" do
describe "with a command array" do
it "uses the first element as the command name and the second as the argv[0] value" do
platform_is_not :windows do
- ruby_exe('Process.exec(["/bin/sh", "argv_zero"], "-c", "echo $0")', escape: true).should == "argv_zero\n"
+ ruby_exe('Process.exec(["/bin/sh", "argv_zero"], "-c", "echo $0")').should == "argv_zero\n"
end
platform_is :windows do
- ruby_exe('Process.exec(["cmd.exe", "/C"], "/C", "echo", "argv_zero")', escape: true).should == "argv_zero\n"
+ ruby_exe('Process.exec(["cmd.exe", "/C"], "/C", "echo", "argv_zero")').should == "argv_zero\n"
end
end
it "coerces the argument using to_ary" do
platform_is_not :windows do
- ruby_exe('o = Object.new; def o.to_ary; ["/bin/sh", "argv_zero"]; end; Process.exec(o, "-c", "echo $0")', escape: true).should == "argv_zero\n"
+ ruby_exe('o = Object.new; def o.to_ary; ["/bin/sh", "argv_zero"]; end; Process.exec(o, "-c", "echo $0")').should == "argv_zero\n"
end
platform_is :windows do
- ruby_exe('o = Object.new; def o.to_ary; ["cmd.exe", "/C"]; end; Process.exec(o, "/C", "echo", "argv_zero")', escape: true).should == "argv_zero\n"
+ ruby_exe('o = Object.new; def o.to_ary; ["cmd.exe", "/C"]; end; Process.exec(o, "/C", "echo", "argv_zero")').should == "argv_zero\n"
end
end
it "raises an ArgumentError if the Array does not have exactly two elements" do
- lambda { Process.exec([]) }.should raise_error(ArgumentError)
- lambda { Process.exec([:a]) }.should raise_error(ArgumentError)
- lambda { Process.exec([:a, :b, :c]) }.should raise_error(ArgumentError)
+ -> { Process.exec([]) }.should raise_error(ArgumentError)
+ -> { Process.exec([:a]) }.should raise_error(ArgumentError)
+ -> { Process.exec([:a, :b, :c]) }.should raise_error(ArgumentError)
end
end
@@ -200,18 +192,49 @@ describe "Process.exec" do
it "maps the key to a file descriptor in the child that inherits the file descriptor from the parent specified by the value" do
map_fd_fixture = fixture __FILE__, "map_fd.rb"
cmd = <<-EOC
- f = File.open("#{@name}", "w+")
- child_fd = f.fileno + 1
- File.open("#{@child_fd_file}", "w") { |io| io.print child_fd }
- Process.exec "#{ruby_cmd(map_fd_fixture)} \#{child_fd}", { child_fd => f }
+ f = File.open(#{@name.inspect}, "w+")
+ File.open(#{__FILE__.inspect}, "r") do |io|
+ child_fd = io.fileno
+ File.open(#{@child_fd_file.inspect}, "w") { |io| io.print child_fd }
+ Process.exec "#{ruby_cmd(map_fd_fixture)} \#{child_fd}", { child_fd => f }
+ end
EOC
- ruby_exe(cmd, escape: true)
+ ruby_exe(cmd)
child_fd = IO.read(@child_fd_file).to_i
child_fd.to_i.should > STDERR.fileno
File.read(@name).should == "writing to fd: #{child_fd}"
end
+
+ it "lets the process after exec have specified file descriptor despite close_on_exec" do
+ map_fd_fixture = fixture __FILE__, "map_fd.rb"
+ cmd = <<-EOC
+ f = File.open(#{@name.inspect}, 'w+')
+ puts(f.fileno, f.close_on_exec?)
+ STDOUT.flush
+ Process.exec("#{ruby_cmd(map_fd_fixture)} \#{f.fileno}", f.fileno => f.fileno)
+ EOC
+
+ output = ruby_exe(cmd)
+ child_fd, close_on_exec = output.split
+
+ child_fd.to_i.should > STDERR.fileno
+ close_on_exec.should == 'true'
+ File.read(@name).should == "writing to fd: #{child_fd}"
+ end
+
+ it "sets close_on_exec to false on specified fd even when it fails" do
+ cmd = <<-EOC
+ f = File.open(#{__FILE__.inspect}, 'r')
+ puts(f.close_on_exec?)
+ Process.exec('/', f.fileno => f.fileno) rescue nil
+ puts(f.close_on_exec?)
+ EOC
+
+ output = ruby_exe(cmd)
+ output.split.should == ['true', 'false']
+ end
end
end
end
diff --git a/spec/ruby/core/process/exit_spec.rb b/spec/ruby/core/process/exit_spec.rb
index 70d79d789d..4f7dc94407 100644
--- a/spec/ruby/core/process/exit_spec.rb
+++ b/spec/ruby/core/process/exit_spec.rb
@@ -6,5 +6,5 @@ describe "Process.exit" do
end
describe "Process.exit!" do
- it_behaves_like :process_exit!, :exit!, Process
+ it_behaves_like :process_exit!, :exit!, "Process"
end
diff --git a/spec/ruby/core/process/fixtures/argv0.rb b/spec/ruby/core/process/fixtures/argv0.rb
new file mode 100644
index 0000000000..847a3e903e
--- /dev/null
+++ b/spec/ruby/core/process/fixtures/argv0.rb
@@ -0,0 +1,6 @@
+puts Process.argv0
+puts __FILE__
+
+if Process.argv0 == __FILE__
+ print "OK"
+end
diff --git a/spec/ruby/core/process/fixtures/clocks.rb b/spec/ruby/core/process/fixtures/clocks.rb
index 2b4916661c..5757e280be 100644
--- a/spec/ruby/core/process/fixtures/clocks.rb
+++ b/spec/ruby/core/process/fixtures/clocks.rb
@@ -2,7 +2,7 @@ module ProcessSpecs
def self.clock_constants
clocks = []
- platform_is_not :windows, :solaris do
+ platform_is_not :windows do
clocks += Process.constants.select { |c| c.to_s.start_with?('CLOCK_') }
# These require CAP_WAKE_ALARM and are not documented in
@@ -15,46 +15,4 @@ module ProcessSpecs
[c, Process.const_get(c)]
}
end
-
- def self.clock_constants_for_resolution_checks
- clocks = clock_constants
-
- # These clocks in practice on Linux do not seem to match their reported resolution.
- platform_is :linux do
- clocks = clocks.reject { |clock, value|
- [:CLOCK_REALTIME_COARSE, :CLOCK_MONOTONIC_COARSE].include?(clock)
- }
- end
-
- # These clocks in practice on macOS seem to be less precise than advertised by clock_getres
- platform_is :darwin do
- clocks = clocks.reject { |clock, value|
- [:CLOCK_UPTIME_RAW_APPROX, :CLOCK_MONOTONIC_RAW_APPROX].include?(clock)
- }
- end
-
- # These clocks in practice on ARM on Linux do not seem to match their reported resolution.
- platform_is :armv7l, :aarch64 do
- clocks = clocks.reject { |clock, value|
- [:CLOCK_PROCESS_CPUTIME_ID, :CLOCK_THREAD_CPUTIME_ID, :CLOCK_MONOTONIC_RAW].include?(clock)
- }
- end
-
- # These clocks in practice on AIX seem to be more precise than their reported resolution.
- platform_is :aix do
- clocks = clocks.reject { |clock, value|
- [:CLOCK_REALTIME, :CLOCK_MONOTONIC].include?(clock)
- }
- end
-
- # On a Hyper-V Linux guest machine, these clocks in practice
- # seem to be less precise than advertised by clock_getres
- platform_is :linux do
- clocks = clocks.reject { |clock, value|
- clock == :CLOCK_MONOTONIC_RAW
- }
- end
-
- clocks
- end
end
diff --git a/spec/ruby/core/process/fixtures/common.rb b/spec/ruby/core/process/fixtures/common.rb
index bdbf1e654b..f49513d262 100644
--- a/spec/ruby/core/process/fixtures/common.rb
+++ b/spec/ruby/core/process/fixtures/common.rb
@@ -3,11 +3,15 @@ module ProcessSpecs
if defined?(MSpecScript::SYSTEM_RUBY)
context.send(:before, :all) do
@ruby = ::RUBY_EXE
- Object.const_set(:RUBY_EXE, MSpecScript::SYSTEM_RUBY)
+ suppress_warning {
+ Object.const_set(:RUBY_EXE, MSpecScript::SYSTEM_RUBY)
+ }
end
context.send(:after, :all) do
- Object.const_set(:RUBY_EXE, @ruby)
+ suppress_warning {
+ Object.const_set(:RUBY_EXE, @ruby)
+ }
end
end
end
diff --git a/spec/ruby/core/process/fixtures/kill.rb b/spec/ruby/core/process/fixtures/kill.rb
index 0b88f8ee1f..b922a043f1 100644
--- a/spec/ruby/core/process/fixtures/kill.rb
+++ b/spec/ruby/core/process/fixtures/kill.rb
@@ -1,5 +1,3 @@
-require 'thread'
-
pid_file = ARGV.shift
scenario = ARGV.shift
diff --git a/spec/ruby/core/process/getpriority_spec.rb b/spec/ruby/core/process/getpriority_spec.rb
index 4b66e18679..a35e5956a5 100644
--- a/spec/ruby/core/process/getpriority_spec.rb
+++ b/spec/ruby/core/process/getpriority_spec.rb
@@ -5,19 +5,19 @@ describe "Process.getpriority" do
it "coerces arguments to Integers" do
ret = Process.getpriority mock_int(Process::PRIO_PROCESS), mock_int(0)
- ret.should be_kind_of(Fixnum)
+ ret.should be_kind_of(Integer)
end
it "gets the scheduling priority for a specified process" do
- Process.getpriority(Process::PRIO_PROCESS, 0).should be_kind_of(Fixnum)
+ Process.getpriority(Process::PRIO_PROCESS, 0).should be_kind_of(Integer)
end
it "gets the scheduling priority for a specified process group" do
- Process.getpriority(Process::PRIO_PGRP, 0).should be_kind_of(Fixnum)
+ Process.getpriority(Process::PRIO_PGRP, 0).should be_kind_of(Integer)
end
it "gets the scheduling priority for a specified user" do
- Process.getpriority(Process::PRIO_USER, 0).should be_kind_of(Fixnum)
+ Process.getpriority(Process::PRIO_USER, 0).should be_kind_of(Integer)
end
end
end
diff --git a/spec/ruby/core/process/getrlimit_spec.rb b/spec/ruby/core/process/getrlimit_spec.rb
index d866a48186..883b8fac48 100644
--- a/spec/ruby/core/process/getrlimit_spec.rb
+++ b/spec/ruby/core/process/getrlimit_spec.rb
@@ -11,8 +11,8 @@ platform_is :aix do
Process.getrlimit(:DATA)
end
-platform_is_not :windows do
- describe "Process.getrlimit" do
+describe "Process.getrlimit" do
+ platform_is_not :windows do
it "returns a two-element Array of Integers" do
result = Process.getrlimit Process::RLIMIT_CORE
result.size.should == 2
@@ -36,7 +36,7 @@ platform_is_not :windows do
obj = mock("process getrlimit integer")
obj.should_receive(:to_int).and_return(nil)
- lambda { Process.getrlimit(obj) }.should raise_error(TypeError)
+ -> { Process.getrlimit(obj) }.should raise_error(TypeError)
end
end
@@ -49,7 +49,7 @@ platform_is_not :windows do
end
it "raises ArgumentError when passed an unknown resource" do
- lambda { Process.getrlimit(:FOO) }.should raise_error(ArgumentError)
+ -> { Process.getrlimit(:FOO) }.should raise_error(ArgumentError)
end
end
@@ -62,7 +62,7 @@ platform_is_not :windows do
end
it "raises ArgumentError when passed an unknown resource" do
- lambda { Process.getrlimit("FOO") }.should raise_error(ArgumentError)
+ -> { Process.getrlimit("FOO") }.should raise_error(ArgumentError)
end
end
@@ -88,4 +88,13 @@ platform_is_not :windows do
end
end
end
+
+ platform_is :windows do
+ it "is not implemented" do
+ Process.respond_to?(:getrlimit).should be_false
+ -> do
+ Process.getrlimit(nil)
+ end.should raise_error NotImplementedError
+ end
+ end
end
diff --git a/spec/ruby/core/process/gid_spec.rb b/spec/ruby/core/process/gid_spec.rb
index 07221da420..ca935ed520 100644
--- a/spec/ruby/core/process/gid_spec.rb
+++ b/spec/ruby/core/process/gid_spec.rb
@@ -3,8 +3,8 @@ require_relative '../../spec_helper'
describe "Process.gid" do
platform_is_not :windows do
it "returns the correct gid for the user executing this process" do
- current_gid_according_to_unix = `id -gr`.to_i
- Process.gid.should == current_gid_according_to_unix
+ current_gid_according_to_unix = `id -gr`.to_i
+ Process.gid.should == current_gid_according_to_unix
end
end
diff --git a/spec/ruby/core/process/groups_spec.rb b/spec/ruby/core/process/groups_spec.rb
index 325deb5977..33e0f9d7b3 100644
--- a/spec/ruby/core/process/groups_spec.rb
+++ b/spec/ruby/core/process/groups_spec.rb
@@ -4,6 +4,10 @@ describe "Process.groups" do
platform_is_not :windows do
it "gets an Array of the gids of groups in the supplemental group access list" do
groups = `id -G`.scan(/\d+/).map { |i| i.to_i }
+ # Include the standard `id` command output. On macOS, GNU
+ # coreutils `id` is limited to NGROUPS_MAX groups, because of
+ # the backward compatibility of getgroups(2).
+ (groups |= `/usr/bin/id -G`.scan(/\d+/).map { |i| i.to_i }) rescue nil
gid = Process.gid
expected = (groups.sort - [gid]).uniq.sort
@@ -14,7 +18,7 @@ describe "Process.groups" do
end
describe "Process.groups=" do
- platform_is_not :windows do
+ platform_is_not :windows, :android do
as_superuser do
it "sets the list of gids of groups in the supplemental group access list" do
groups = Process.groups
@@ -46,14 +50,14 @@ describe "Process.groups=" do
Process.groups.should == [ Process.gid ]
supplementary = groups - [ Process.gid ]
if supplementary.length > 0
- lambda { Process.groups = supplementary }.should raise_error(Errno::EPERM)
+ -> { Process.groups = supplementary }.should raise_error(Errno::EPERM)
end
end
end
platform_is_not :aix do
it "raises Errno::EPERM" do
- lambda {
+ -> {
Process.groups = [0]
}.should raise_error(Errno::EPERM)
end
diff --git a/spec/ruby/core/process/initgroups_spec.rb b/spec/ruby/core/process/initgroups_spec.rb
index e711fc0798..ffc7f282b6 100644
--- a/spec/ruby/core/process/initgroups_spec.rb
+++ b/spec/ruby/core/process/initgroups_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe "Process.initgroups" do
- platform_is_not :windows do
+ platform_is_not :windows, :android do
as_user do
it "initializes the supplemental group access list" do
name = `id -un`.strip
@@ -14,7 +14,7 @@ describe "Process.initgroups" do
Process.groups.sort.should == augmented_groups.sort
Process.groups = groups
else
- lambda { Process.initgroups(name, gid) }.should raise_error(Errno::EPERM)
+ -> { Process.initgroups(name, gid) }.should raise_error(Errno::EPERM)
end
end
end
diff --git a/spec/ruby/core/process/kill_spec.rb b/spec/ruby/core/process/kill_spec.rb
index 14deba2451..af9c9e6deb 100644
--- a/spec/ruby/core/process/kill_spec.rb
+++ b/spec/ruby/core/process/kill_spec.rb
@@ -9,25 +9,25 @@ describe "Process.kill" do
end
it "raises an ArgumentError for unknown signals" do
- lambda { Process.kill("FOO", @pid) }.should raise_error(ArgumentError)
+ -> { Process.kill("FOO", @pid) }.should raise_error(ArgumentError)
end
it "raises an ArgumentError if passed a lowercase signal name" do
- lambda { Process.kill("term", @pid) }.should raise_error(ArgumentError)
+ -> { Process.kill("term", @pid) }.should raise_error(ArgumentError)
end
- it "raises an ArgumentError if signal is not a Fixnum or String" do
+ it "raises an ArgumentError if signal is not an Integer or String" do
signal = mock("process kill signal")
signal.should_not_receive(:to_int)
- lambda { Process.kill(signal, @pid) }.should raise_error(ArgumentError)
+ -> { Process.kill(signal, @pid) }.should raise_error(ArgumentError)
end
it "raises Errno::ESRCH if the process does not exist" do
pid = Process.spawn(*ruby_exe, "-e", "sleep 10")
Process.kill("SIGKILL", pid)
Process.wait(pid)
- lambda {
+ -> {
Process.kill("SIGKILL", pid)
}.should raise_error(Errno::ESRCH)
end
diff --git a/spec/ruby/core/process/last_status_spec.rb b/spec/ruby/core/process/last_status_spec.rb
index 3898dd6b95..2372f2aae3 100644
--- a/spec/ruby/core/process/last_status_spec.rb
+++ b/spec/ruby/core/process/last_status_spec.rb
@@ -1,20 +1,18 @@
require_relative '../../spec_helper'
-ruby_version_is '2.5' do
- describe 'Process#last_status' do
- it 'returns the status of the last executed child process in the current thread' do
- pid = Process.wait Process.spawn("exit 0")
- Process.last_status.pid.should == pid
- end
+describe 'Process#last_status' do
+ it 'returns the status of the last executed child process in the current thread' do
+ pid = Process.wait Process.spawn("exit 0")
+ Process.last_status.pid.should == pid
+ end
- it 'returns nil if no child process has been ever executed in the current thread' do
- Thread.new do
- Process.last_status.should == nil
- end.join
- end
+ it 'returns nil if no child process has been ever executed in the current thread' do
+ Thread.new do
+ Process.last_status.should == nil
+ end.join
+ end
- it 'raises an ArgumentError if any arguments are provided' do
- -> { Process.last_status(1) }.should raise_error(ArgumentError)
- end
+ it 'raises an ArgumentError if any arguments are provided' do
+ -> { Process.last_status(1) }.should raise_error(ArgumentError)
end
end
diff --git a/spec/ruby/core/process/maxgroups_spec.rb b/spec/ruby/core/process/maxgroups_spec.rb
index 362f788ab2..2549a7a971 100644
--- a/spec/ruby/core/process/maxgroups_spec.rb
+++ b/spec/ruby/core/process/maxgroups_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
platform_is_not :windows do
describe "Process.maxgroups" do
it "returns the maximum number of gids allowed in the supplemental group access list" do
- Process.maxgroups.should be_kind_of(Fixnum)
+ Process.maxgroups.should be_kind_of(Integer)
end
it "sets the maximum number of gids allowed in the supplemental group access list" do
diff --git a/spec/ruby/core/process/pid_spec.rb b/spec/ruby/core/process/pid_spec.rb
index c5947ab50d..2d008bc4b7 100644
--- a/spec/ruby/core/process/pid_spec.rb
+++ b/spec/ruby/core/process/pid_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Process.pid" do
it "returns the process id of this process" do
pid = Process.pid
- pid.should be_kind_of(Fixnum)
+ pid.should be_kind_of(Integer)
Process.pid.should == pid
end
end
diff --git a/spec/ruby/core/process/setrlimit_spec.rb b/spec/ruby/core/process/setrlimit_spec.rb
index f4ff607b7b..ba8d1e04ca 100644
--- a/spec/ruby/core/process/setrlimit_spec.rb
+++ b/spec/ruby/core/process/setrlimit_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
-platform_is_not :windows do
- describe "Process.setrlimit" do
+describe "Process.setrlimit" do
+ platform_is_not :windows do
context "when passed an Object" do
before do
@resource = Process::RLIMIT_CORE
@@ -16,7 +16,7 @@ platform_is_not :windows do
obj = mock("process getrlimit integer")
obj.should_receive(:to_int).and_return(nil)
- lambda { Process.setrlimit(obj, @limit, @max) }.should raise_error(TypeError)
+ -> { Process.setrlimit(obj, @limit, @max) }.should raise_error(TypeError)
end
it "calls #to_int to convert the soft limit to an Integer" do
@@ -27,7 +27,7 @@ platform_is_not :windows do
obj = mock("process getrlimit integer")
obj.should_receive(:to_int).and_return(nil)
- lambda { Process.setrlimit(@resource, obj, @max) }.should raise_error(TypeError)
+ -> { Process.setrlimit(@resource, obj, @max) }.should raise_error(TypeError)
end
it "calls #to_int to convert the hard limit to an Integer" do
@@ -38,7 +38,7 @@ platform_is_not :windows do
obj = mock("process getrlimit integer")
obj.should_receive(:to_int).and_return(nil)
- lambda { Process.setrlimit(@resource, @limit, obj) }.should raise_error(TypeError)
+ -> { Process.setrlimit(@resource, @limit, obj) }.should raise_error(TypeError)
end
end
@@ -73,20 +73,18 @@ platform_is_not :windows do
Process.setrlimit(:STACK, *Process.getrlimit(Process::RLIMIT_STACK)).should be_nil
end
- platform_is_not :solaris, :aix do
+ platform_is_not :aix do
it "coerces :MEMLOCK into RLIMIT_MEMLOCK" do
Process.setrlimit(:MEMLOCK, *Process.getrlimit(Process::RLIMIT_MEMLOCK)).should be_nil
end
end
- platform_is_not :solaris do
- it "coerces :NPROC into RLIMIT_NPROC" do
- Process.setrlimit(:NPROC, *Process.getrlimit(Process::RLIMIT_NPROC)).should be_nil
- end
+ it "coerces :NPROC into RLIMIT_NPROC" do
+ Process.setrlimit(:NPROC, *Process.getrlimit(Process::RLIMIT_NPROC)).should be_nil
+ end
- it "coerces :RSS into RLIMIT_RSS" do
- Process.setrlimit(:RSS, *Process.getrlimit(Process::RLIMIT_RSS)).should be_nil
- end
+ it "coerces :RSS into RLIMIT_RSS" do
+ Process.setrlimit(:RSS, *Process.getrlimit(Process::RLIMIT_RSS)).should be_nil
end
platform_is :netbsd, :freebsd do
@@ -120,7 +118,7 @@ platform_is_not :windows do
end
it "raises ArgumentError when passed an unknown resource" do
- lambda { Process.setrlimit(:FOO, 1, 1) }.should raise_error(ArgumentError)
+ -> { Process.setrlimit(:FOO, 1, 1) }.should raise_error(ArgumentError)
end
end
@@ -155,20 +153,18 @@ platform_is_not :windows do
Process.setrlimit("STACK", *Process.getrlimit(Process::RLIMIT_STACK)).should be_nil
end
- platform_is_not :solaris, :aix do
+ platform_is_not :aix do
it "coerces 'MEMLOCK' into RLIMIT_MEMLOCK" do
Process.setrlimit("MEMLOCK", *Process.getrlimit(Process::RLIMIT_MEMLOCK)).should be_nil
end
end
- platform_is_not :solaris do
- it "coerces 'NPROC' into RLIMIT_NPROC" do
- Process.setrlimit("NPROC", *Process.getrlimit(Process::RLIMIT_NPROC)).should be_nil
- end
+ it "coerces 'NPROC' into RLIMIT_NPROC" do
+ Process.setrlimit("NPROC", *Process.getrlimit(Process::RLIMIT_NPROC)).should be_nil
+ end
- it "coerces 'RSS' into RLIMIT_RSS" do
- Process.setrlimit("RSS", *Process.getrlimit(Process::RLIMIT_RSS)).should be_nil
- end
+ it "coerces 'RSS' into RLIMIT_RSS" do
+ Process.setrlimit("RSS", *Process.getrlimit(Process::RLIMIT_RSS)).should be_nil
end
platform_is :netbsd, :freebsd do
@@ -202,7 +198,7 @@ platform_is_not :windows do
end
it "raises ArgumentError when passed an unknown resource" do
- lambda { Process.setrlimit("FOO", 1, 1) }.should raise_error(ArgumentError)
+ -> { Process.setrlimit("FOO", 1, 1) }.should raise_error(ArgumentError)
end
end
@@ -229,4 +225,13 @@ platform_is_not :windows do
end
end
end
+
+ platform_is :windows do
+ it "is not implemented" do
+ Process.respond_to?(:setrlimit).should be_false
+ -> do
+ Process.setrlimit(nil, nil)
+ end.should raise_error NotImplementedError
+ end
+ end
end
diff --git a/spec/ruby/core/process/spawn_spec.rb b/spec/ruby/core/process/spawn_spec.rb
index aa7a7dc3aa..283a7f033d 100644
--- a/spec/ruby/core/process/spawn_spec.rb
+++ b/spec/ruby/core/process/spawn_spec.rb
@@ -45,13 +45,13 @@ describe "Process.spawn" do
end
it "executes the given command" do
- lambda { Process.wait Process.spawn("echo spawn") }.should output_to_fd("spawn\n")
+ -> { Process.wait Process.spawn("echo spawn") }.should output_to_fd("spawn\n")
end
- it "returns the process ID of the new process as a Fixnum" do
+ it "returns the process ID of the new process as an Integer" do
pid = Process.spawn(*ruby_exe, "-e", "exit")
Process.wait pid
- pid.should be_an_instance_of(Fixnum)
+ pid.should be_an_instance_of(Integer)
end
it "returns immediately" do
@@ -67,43 +67,43 @@ describe "Process.spawn" do
describe "with a single argument" do
platform_is_not :windows do
it "subjects the specified command to shell expansion" do
- lambda { Process.wait Process.spawn("echo *") }.should_not output_to_fd("*\n")
+ -> { Process.wait Process.spawn("echo *") }.should_not output_to_fd("*\n")
end
it "creates an argument array with shell parsing semantics for whitespace" do
- lambda { Process.wait Process.spawn("echo a b c d") }.should output_to_fd("a b c d\n")
+ -> { Process.wait Process.spawn("echo a b c d") }.should output_to_fd("a b c d\n")
end
end
platform_is :windows do
# There is no shell expansion on Windows
it "does not subject the specified command to shell expansion on Windows" do
- lambda { Process.wait Process.spawn("echo *") }.should output_to_fd("*\n")
+ -> { Process.wait Process.spawn("echo *") }.should output_to_fd("*\n")
end
it "does not create an argument array with shell parsing semantics for whitespace on Windows" do
- lambda { Process.wait Process.spawn("echo a b c d") }.should output_to_fd("a b c d\n")
+ -> { Process.wait Process.spawn("echo a b c d") }.should output_to_fd("a b c d\n")
end
end
it "calls #to_str to convert the argument to a String" do
o = mock("to_str")
o.should_receive(:to_str).and_return("echo foo")
- lambda { Process.wait Process.spawn(o) }.should output_to_fd("foo\n")
+ -> { Process.wait Process.spawn(o) }.should output_to_fd("foo\n")
end
it "raises an ArgumentError if the command includes a null byte" do
- lambda { Process.spawn "\000" }.should raise_error(ArgumentError)
+ -> { Process.spawn "\000" }.should raise_error(ArgumentError)
end
it "raises a TypeError if the argument does not respond to #to_str" do
- lambda { Process.spawn :echo }.should raise_error(TypeError)
+ -> { Process.spawn :echo }.should raise_error(TypeError)
end
end
describe "with multiple arguments" do
it "does not subject the arguments to shell expansion" do
- lambda { Process.wait Process.spawn("echo", "*") }.should output_to_fd("*\n")
+ -> { Process.wait Process.spawn("echo", "*") }.should output_to_fd("*\n")
end
it "preserves whitespace in passed arguments" do
@@ -112,36 +112,36 @@ describe "Process.spawn" do
# The echo command on Windows takes quotes literally
out = "\"a b c d\"\n"
end
- lambda { Process.wait Process.spawn("echo", "a b c d") }.should output_to_fd(out)
+ -> { Process.wait Process.spawn("echo", "a b c d") }.should output_to_fd(out)
end
it "calls #to_str to convert the arguments to Strings" do
o = mock("to_str")
o.should_receive(:to_str).and_return("foo")
- lambda { Process.wait Process.spawn("echo", o) }.should output_to_fd("foo\n")
+ -> { Process.wait Process.spawn("echo", o) }.should output_to_fd("foo\n")
end
it "raises an ArgumentError if an argument includes a null byte" do
- lambda { Process.spawn "echo", "\000" }.should raise_error(ArgumentError)
+ -> { Process.spawn "echo", "\000" }.should raise_error(ArgumentError)
end
it "raises a TypeError if an argument does not respond to #to_str" do
- lambda { Process.spawn "echo", :foo }.should raise_error(TypeError)
+ -> { Process.spawn "echo", :foo }.should raise_error(TypeError)
end
end
describe "with a command array" do
it "uses the first element as the command name and the second as the argv[0] value" do
platform_is_not :windows do
- lambda { Process.wait Process.spawn(["/bin/sh", "argv_zero"], "-c", "echo $0") }.should output_to_fd("argv_zero\n")
+ -> { Process.wait Process.spawn(["/bin/sh", "argv_zero"], "-c", "echo $0") }.should output_to_fd("argv_zero\n")
end
platform_is :windows do
- lambda { Process.wait Process.spawn(["cmd.exe", "/C"], "/C", "echo", "argv_zero") }.should output_to_fd("argv_zero\n")
+ -> { Process.wait Process.spawn(["cmd.exe", "/C"], "/C", "echo", "argv_zero") }.should output_to_fd("argv_zero\n")
end
end
it "does not subject the arguments to shell expansion" do
- lambda { Process.wait Process.spawn(["echo", "echo"], "*") }.should output_to_fd("*\n")
+ -> { Process.wait Process.spawn(["echo", "echo"], "*") }.should output_to_fd("*\n")
end
it "preserves whitespace in passed arguments" do
@@ -150,47 +150,47 @@ describe "Process.spawn" do
# The echo command on Windows takes quotes literally
out = "\"a b c d\"\n"
end
- lambda { Process.wait Process.spawn(["echo", "echo"], "a b c d") }.should output_to_fd(out)
+ -> { Process.wait Process.spawn(["echo", "echo"], "a b c d") }.should output_to_fd(out)
end
it "calls #to_ary to convert the argument to an Array" do
o = mock("to_ary")
platform_is_not :windows do
o.should_receive(:to_ary).and_return(["/bin/sh", "argv_zero"])
- lambda { Process.wait Process.spawn(o, "-c", "echo $0") }.should output_to_fd("argv_zero\n")
+ -> { Process.wait Process.spawn(o, "-c", "echo $0") }.should output_to_fd("argv_zero\n")
end
platform_is :windows do
o.should_receive(:to_ary).and_return(["cmd.exe", "/C"])
- lambda { Process.wait Process.spawn(o, "/C", "echo", "argv_zero") }.should output_to_fd("argv_zero\n")
+ -> { Process.wait Process.spawn(o, "/C", "echo", "argv_zero") }.should output_to_fd("argv_zero\n")
end
end
it "calls #to_str to convert the first element to a String" do
o = mock("to_str")
o.should_receive(:to_str).and_return("echo")
- lambda { Process.wait Process.spawn([o, "echo"], "foo") }.should output_to_fd("foo\n")
+ -> { Process.wait Process.spawn([o, "echo"], "foo") }.should output_to_fd("foo\n")
end
it "calls #to_str to convert the second element to a String" do
o = mock("to_str")
o.should_receive(:to_str).and_return("echo")
- lambda { Process.wait Process.spawn(["echo", o], "foo") }.should output_to_fd("foo\n")
+ -> { Process.wait Process.spawn(["echo", o], "foo") }.should output_to_fd("foo\n")
end
it "raises an ArgumentError if the Array does not have exactly two elements" do
- lambda { Process.spawn([]) }.should raise_error(ArgumentError)
- lambda { Process.spawn([:a]) }.should raise_error(ArgumentError)
- lambda { Process.spawn([:a, :b, :c]) }.should raise_error(ArgumentError)
+ -> { Process.spawn([]) }.should raise_error(ArgumentError)
+ -> { Process.spawn([:a]) }.should raise_error(ArgumentError)
+ -> { Process.spawn([:a, :b, :c]) }.should raise_error(ArgumentError)
end
it "raises an ArgumentError if the Strings in the Array include a null byte" do
- lambda { Process.spawn ["\000", "echo"] }.should raise_error(ArgumentError)
- lambda { Process.spawn ["echo", "\000"] }.should raise_error(ArgumentError)
+ -> { Process.spawn ["\000", "echo"] }.should raise_error(ArgumentError)
+ -> { Process.spawn ["echo", "\000"] }.should raise_error(ArgumentError)
end
it "raises a TypeError if an element in the Array does not respond to #to_str" do
- lambda { Process.spawn ["echo", :echo] }.should raise_error(TypeError)
- lambda { Process.spawn [:echo, "echo"] }.should raise_error(TypeError)
+ -> { Process.spawn ["echo", :echo] }.should raise_error(TypeError)
+ -> { Process.spawn [:echo, "echo"] }.should raise_error(TypeError)
end
end
@@ -207,13 +207,29 @@ describe "Process.spawn" do
it "unsets environment variables whose value is nil" do
ENV["FOO"] = "BAR"
- Process.wait Process.spawn({"FOO" => nil}, "echo #{@var}>#{@name}")
- expected = "\n"
- platform_is :windows do
- # Windows does not expand the variable if it is unset
- expected = "#{@var}\n"
+ -> do
+ Process.wait Process.spawn({"FOO" => nil}, ruby_cmd("p ENV['FOO']"))
+ end.should output_to_fd("nil\n")
+ end
+
+ platform_is_not :windows do
+ it "uses the passed env['PATH'] to search the executable" do
+ dir = tmp("spawn_path_dir")
+ mkdir_p dir
+ begin
+ exe = 'process-spawn-executable-in-path'
+ path = "#{dir}/#{exe}"
+ File.write(path, "#!/bin/sh\necho $1")
+ File.chmod(0755, path)
+
+ env = { "PATH" => "#{dir}#{File::PATH_SEPARATOR}#{ENV['PATH']}" }
+ Process.wait Process.spawn(env, exe, 'OK', out: @name)
+ $?.should.success?
+ File.read(@name).should == "OK\n"
+ ensure
+ rm_r dir
+ end
end
- File.read(@name).should == expected
end
it "calls #to_hash to convert the environment" do
@@ -238,19 +254,19 @@ describe "Process.spawn" do
end
it "raises an ArgumentError if an environment key includes an equals sign" do
- lambda do
+ -> do
Process.spawn({"FOO=" => "BAR"}, "echo #{@var}>#{@name}")
end.should raise_error(ArgumentError)
end
it "raises an ArgumentError if an environment key includes a null byte" do
- lambda do
+ -> do
Process.spawn({"\000" => "BAR"}, "echo #{@var}>#{@name}")
end.should raise_error(ArgumentError)
end
it "raises an ArgumentError if an environment value includes a null byte" do
- lambda do
+ -> do
Process.spawn({"FOO" => "\000"}, "echo #{@var}>#{@name}")
end.should raise_error(ArgumentError)
end
@@ -294,25 +310,25 @@ describe "Process.spawn" do
platform_is_not :windows do
it "joins the current process group by default" do
- lambda do
+ -> do
Process.wait Process.spawn(ruby_cmd("print Process.getpgid(Process.pid)"))
end.should output_to_fd(Process.getpgid(Process.pid).to_s)
end
it "joins the current process if pgroup: false" do
- lambda do
+ -> do
Process.wait Process.spawn(ruby_cmd("print Process.getpgid(Process.pid)"), pgroup: false)
end.should output_to_fd(Process.getpgid(Process.pid).to_s)
end
it "joins the current process if pgroup: nil" do
- lambda do
+ -> do
Process.wait Process.spawn(ruby_cmd("print Process.getpgid(Process.pid)"), pgroup: nil)
end.should output_to_fd(Process.getpgid(Process.pid).to_s)
end
it "joins a new process group if pgroup: true" do
- process = lambda do
+ process = -> do
Process.wait Process.spawn(ruby_cmd("print Process.getpgid(Process.pid)"), pgroup: true)
end
@@ -321,7 +337,7 @@ describe "Process.spawn" do
end
it "joins a new process group if pgroup: 0" do
- process = lambda do
+ process = -> do
Process.wait Process.spawn(ruby_cmd("print Process.getpgid(Process.pid)"), pgroup: 0)
end
@@ -331,23 +347,33 @@ describe "Process.spawn" do
it "joins the specified process group if pgroup: pgid" do
pgid = Process.getpgid(Process.pid)
- lambda do
- Process.wait Process.spawn(ruby_cmd("print Process.getpgid(Process.pid)"), pgroup: pgid)
- end.should output_to_fd(pgid.to_s)
+ # The process group is not available on all platforms.
+ # See "man proc" - /proc/[pid]/stat - (5) pgrp
+ # In Travis aarch64 environment, the value is 0.
+ #
+ # $ cat /proc/[pid]/stat
+ # 19179 (ruby) S 19160 0 0 ...
+ unless pgid.zero?
+ -> do
+ Process.wait Process.spawn(ruby_cmd("print Process.getpgid(Process.pid)"), pgroup: pgid)
+ end.should output_to_fd(pgid.to_s)
+ else
+ skip "The process group is not available."
+ end
end
it "raises an ArgumentError if given a negative :pgroup option" do
- lambda { Process.spawn("echo", pgroup: -1) }.should raise_error(ArgumentError)
+ -> { Process.spawn("echo", pgroup: -1) }.should raise_error(ArgumentError)
end
it "raises a TypeError if given a symbol as :pgroup option" do
- lambda { Process.spawn("echo", pgroup: :true) }.should raise_error(TypeError)
+ -> { Process.spawn("echo", pgroup: :true) }.should raise_error(TypeError)
end
end
platform_is :windows do
it "raises an ArgumentError if given :pgroup option" do
- lambda { Process.spawn("echo", pgroup: false) }.should raise_error(ArgumentError)
+ -> { Process.spawn("echo", pgroup: false) }.should raise_error(ArgumentError)
end
end
@@ -358,7 +384,7 @@ describe "Process.spawn" do
# :chdir
it "uses the current working directory as its working directory" do
- lambda do
+ -> do
Process.wait Process.spawn(ruby_cmd("print Dir.pwd"))
end.should output_to_fd(Dir.pwd)
end
@@ -374,7 +400,7 @@ describe "Process.spawn" do
end
it "changes to the directory passed for :chdir" do
- lambda do
+ -> do
Process.wait Process.spawn(ruby_cmd("print Dir.pwd"), chdir: @dir)
end.should output_to_fd(@dir)
end
@@ -383,7 +409,7 @@ describe "Process.spawn" do
dir = mock("spawn_to_path")
dir.should_receive(:to_path).and_return(@dir)
- lambda do
+ -> do
Process.wait Process.spawn(ruby_cmd("print Dir.pwd"), chdir: dir)
end.should output_to_fd(@dir)
end
@@ -409,7 +435,7 @@ describe "Process.spawn" do
it "kills extra chdir processes" do
pid = nil
- Dir.chdir("/tmp") do
+ Dir.chdir("/") do
pid = Process.spawn("sleep 10")
end
@@ -424,7 +450,7 @@ describe "Process.spawn" do
sleep(1)
children.each do |child|
- lambda do
+ -> do
Process.kill("TERM", child)
end.should raise_error(Errno::ESRCH)
end
@@ -436,14 +462,14 @@ describe "Process.spawn" do
# :umask
it "uses the current umask by default" do
- lambda do
+ -> do
Process.wait Process.spawn(ruby_cmd("print File.umask"))
end.should output_to_fd(File.umask.to_s)
end
platform_is_not :windows do
it "sets the umask if given the :umask option" do
- lambda do
+ -> do
Process.wait Process.spawn(ruby_cmd("print File.umask"), umask: 146)
end.should output_to_fd("146")
end
@@ -451,9 +477,19 @@ describe "Process.spawn" do
# redirection
- it "redirects STDOUT to the given file descriptor if out: Fixnum" do
+ it 'redirects to the wrapped IO using wrapped_io.to_io if out: wrapped_io' do
File.open(@name, 'w') do |file|
- lambda do
+ -> do
+ wrapped_io = mock('wrapped IO')
+ wrapped_io.should_receive(:to_io).and_return(file)
+ Process.wait Process.spawn('echo Hello World', out: wrapped_io)
+ end.should output_to_fd("Hello World\n", file)
+ end
+ end
+
+ it "redirects STDOUT to the given file descriptor if out: Integer" do
+ File.open(@name, 'w') do |file|
+ -> do
Process.wait Process.spawn("echo glark", out: file.fileno)
end.should output_to_fd("glark\n", file)
end
@@ -461,7 +497,7 @@ describe "Process.spawn" do
it "redirects STDOUT to the given file if out: IO" do
File.open(@name, 'w') do |file|
- lambda do
+ -> do
Process.wait Process.spawn("echo glark", out: file)
end.should output_to_fd("glark\n", file)
end
@@ -477,9 +513,9 @@ describe "Process.spawn" do
File.read(@name).should == "glark\n"
end
- it "redirects STDERR to the given file descriptor if err: Fixnum" do
+ it "redirects STDERR to the given file descriptor if err: Integer" do
File.open(@name, 'w') do |file|
- lambda do
+ -> do
Process.wait Process.spawn("echo glark>&2", err: file.fileno)
end.should output_to_fd("glark\n", file)
end
@@ -487,7 +523,7 @@ describe "Process.spawn" do
it "redirects STDERR to the given file descriptor if err: IO" do
File.open(@name, 'w') do |file|
- lambda do
+ -> do
Process.wait Process.spawn("echo glark>&2", err: file)
end.should output_to_fd("glark\n", file)
end
@@ -500,7 +536,7 @@ describe "Process.spawn" do
it "redirects STDERR to child STDOUT if :err => [:child, :out]" do
File.open(@name, 'w') do |file|
- lambda do
+ -> do
Process.wait Process.spawn("echo glark>&2", :out => file, :err => [:child, :out])
end.should output_to_fd("glark\n", file)
end
@@ -508,7 +544,7 @@ describe "Process.spawn" do
it "redirects both STDERR and STDOUT to the given file descriptor" do
File.open(@name, 'w') do |file|
- lambda do
+ -> do
Process.wait Process.spawn(ruby_cmd("print(:glark); STDOUT.flush; STDERR.print(:bang)"),
[:out, :err] => file.fileno)
end.should output_to_fd("glarkbang", file)
@@ -517,7 +553,7 @@ describe "Process.spawn" do
it "redirects both STDERR and STDOUT to the given IO" do
File.open(@name, 'w') do |file|
- lambda do
+ -> do
Process.wait Process.spawn(ruby_cmd("print(:glark); STDOUT.flush; STDERR.print(:bang)"),
[:out, :err] => file)
end.should output_to_fd("glarkbang", file)
@@ -530,31 +566,47 @@ describe "Process.spawn" do
File.read(@name).should == "glarkbang"
end
- # :close_others
+ platform_is_not :windows, :android do
+ it "closes STDERR in the child if :err => :close" do
+ File.open(@name, 'w') do |file|
+ -> do
+ code = "begin; STDOUT.puts 'out'; STDERR.puts 'hello'; rescue => e; puts 'rescued'; end"
+ Process.wait Process.spawn(ruby_cmd(code), :out => file, :err => :close)
+ end.should output_to_fd("out\nrescued\n", file)
+ end
+ end
+ end
platform_is_not :windows do
- context "defaults :close_others to" do
- ruby_version_is ""..."2.6" do
- it "true" do
- IO.pipe do |r, w|
- w.close_on_exec = false
- code = "begin; IO.new(#{w.fileno}).close; rescue Errno::EBADF; puts 'not inherited'; end"
- Process.wait Process.spawn(ruby_cmd(code), :out => @name)
- File.read(@name).should == "not inherited\n"
- end
- end
+ it "redirects non-default file descriptor to itself" do
+ File.open(@name, 'w') do |file|
+ -> do
+ Process.wait Process.spawn(
+ ruby_cmd("f = IO.new(#{file.fileno}, 'w'); f.print(:bang); f.flush"), file.fileno => file.fileno)
+ end.should output_to_fd("bang", file)
end
+ end
+ end
- ruby_version_is "2.6" do
- it "false" do
- IO.pipe do |r, w|
- w.close_on_exec = false
- code = "io = IO.new(#{w.fileno}); io.puts('inherited'); io.close"
- pid = Process.spawn(ruby_cmd(code))
- w.close
- Process.wait(pid)
- r.read.should == "inherited\n"
- end
+ it "redirects default file descriptor to itself" do
+ -> do
+ Process.wait Process.spawn(
+ ruby_cmd("f = IO.new(#{STDOUT.fileno}, 'w'); f.print(:bang); f.flush"), STDOUT.fileno => STDOUT.fileno)
+ end.should output_to_fd("bang", STDOUT)
+ end
+
+ # :close_others
+
+ platform_is_not :windows do
+ context "defaults :close_others to" do
+ it "false" do
+ IO.pipe do |r, w|
+ w.close_on_exec = false
+ code = "io = IO.new(#{w.fileno}); io.puts('inherited'); io.close"
+ pid = Process.spawn(ruby_cmd(code))
+ w.close
+ Process.wait(pid)
+ r.read.should == "inherited\n"
end
end
end
@@ -626,35 +678,35 @@ describe "Process.spawn" do
# error handling
it "raises an ArgumentError if passed no command arguments" do
- lambda { Process.spawn }.should raise_error(ArgumentError)
+ -> { Process.spawn }.should raise_error(ArgumentError)
end
it "raises an ArgumentError if passed env or options but no command arguments" do
- lambda { Process.spawn({}) }.should raise_error(ArgumentError)
+ -> { Process.spawn({}) }.should raise_error(ArgumentError)
end
it "raises an ArgumentError if passed env and options but no command arguments" do
- lambda { Process.spawn({}, {}) }.should raise_error(ArgumentError)
+ -> { Process.spawn({}, {}) }.should raise_error(ArgumentError)
end
it "raises an Errno::ENOENT for an empty string" do
- lambda { Process.spawn "" }.should raise_error(Errno::ENOENT)
+ -> { Process.spawn "" }.should raise_error(Errno::ENOENT)
end
it "raises an Errno::ENOENT if the command does not exist" do
- lambda { Process.spawn "nonesuch" }.should raise_error(Errno::ENOENT)
+ -> { Process.spawn "nonesuch" }.should raise_error(Errno::ENOENT)
end
unless File.executable?(__FILE__) # Some FS (e.g. vboxfs) locate all files executable
platform_is_not :windows do
it "raises an Errno::EACCES when the file does not have execute permissions" do
- lambda { Process.spawn __FILE__ }.should raise_error(Errno::EACCES)
+ -> { Process.spawn __FILE__ }.should raise_error(Errno::EACCES)
end
end
platform_is :windows do
it "raises Errno::EACCES or Errno::ENOEXEC when the file is not an executable file" do
- lambda { Process.spawn __FILE__ }.should raise_error(SystemCallError) { |e|
+ -> { Process.spawn __FILE__ }.should raise_error(SystemCallError) { |e|
[Errno::EACCES, Errno::ENOEXEC].should include(e.class)
}
end
@@ -662,17 +714,17 @@ describe "Process.spawn" do
end
it "raises an Errno::EACCES or Errno::EISDIR when passed a directory" do
- lambda { Process.spawn File.dirname(__FILE__) }.should raise_error(SystemCallError) { |e|
+ -> { Process.spawn __dir__ }.should raise_error(SystemCallError) { |e|
[Errno::EACCES, Errno::EISDIR].should include(e.class)
}
end
it "raises an ArgumentError when passed a string key in options" do
- lambda { Process.spawn("echo", "chdir" => Dir.pwd) }.should raise_error(ArgumentError)
+ -> { Process.spawn("echo", "chdir" => Dir.pwd) }.should raise_error(ArgumentError)
end
it "raises an ArgumentError when passed an unknown option key" do
- lambda { Process.spawn("echo", nonesuch: :foo) }.should raise_error(ArgumentError)
+ -> { Process.spawn("echo", nonesuch: :foo) }.should raise_error(ArgumentError)
end
platform_is_not :windows, :aix do
@@ -689,13 +741,15 @@ describe "Process.spawn" do
end
it "maps the key to a file descriptor in the child that inherits the file descriptor from the parent specified by the value" do
- child_fd = find_unused_fd
- args = ruby_cmd(fixture(__FILE__, "map_fd.rb"), args: [child_fd.to_s])
- pid = Process.spawn(*args, { child_fd => @io })
- Process.waitpid pid
- @io.rewind
-
- @io.read.should == "writing to fd: #{child_fd}"
+ File.open(__FILE__, "r") do |f|
+ child_fd = f.fileno
+ args = ruby_cmd(fixture(__FILE__, "map_fd.rb"), args: [child_fd.to_s])
+ pid = Process.spawn(*args, { child_fd => @io })
+ Process.waitpid pid
+ @io.rewind
+
+ @io.read.should == "writing to fd: #{child_fd}"
+ end
end
end
end
diff --git a/spec/ruby/core/process/status/bit_and_spec.rb b/spec/ruby/core/process/status/bit_and_spec.rb
index 97f768fdc1..a805364629 100644
--- a/spec/ruby/core/process/status/bit_and_spec.rb
+++ b/spec/ruby/core/process/status/bit_and_spec.rb
@@ -1,5 +1,38 @@
require_relative '../../../spec_helper'
-describe "Process::Status#&" do
- it "needs to be reviewed for spec completeness"
+ruby_version_is ""..."4.0" do
+
+ describe "Process::Status#&" do
+ it "returns a bitwise and of the integer status of an exited child" do
+ suppress_warning do
+ ruby_exe("exit(29)", exit_status: 29)
+ ($? & 0).should == 0
+ ($? & $?.to_i).should == $?.to_i
+
+ # Actual value is implementation specific
+ platform_is :linux do
+ # 29 == 0b11101
+ ($? & 0b1011100000000).should == 0b1010100000000
+ end
+ end
+ end
+
+ ruby_version_is "3.3"..."4.0" do
+ it "raises an ArgumentError if mask is negative" do
+ suppress_warning do
+ ruby_exe("exit(0)")
+ -> {
+ $? & -1
+ }.should raise_error(ArgumentError, 'negative mask value: -1')
+ end
+ end
+
+ it "shows a deprecation warning" do
+ ruby_exe("exit(0)")
+ -> {
+ $? & 0
+ }.should complain(/warning: Process::Status#& is deprecated and will be removed .*use other Process::Status predicates instead/)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/process/status/equal_value_spec.rb b/spec/ruby/core/process/status/equal_value_spec.rb
index 9e9a2d0a2b..d8a2be26b8 100644
--- a/spec/ruby/core/process/status/equal_value_spec.rb
+++ b/spec/ruby/core/process/status/equal_value_spec.rb
@@ -1,5 +1,15 @@
require_relative '../../../spec_helper'
describe "Process::Status#==" do
- it "needs to be reviewed for spec completeness"
+ it "returns true when compared to the integer status of an exited child" do
+ ruby_exe("exit(29)", exit_status: 29)
+ $?.to_i.should == $?
+ $?.should == $?.to_i
+ end
+
+ it "returns true when compared to the integer status of a terminated child" do
+ ruby_exe("Process.kill(:KILL, $$); exit(29)", exit_status: platform_is(:windows) ? 0 : :SIGKILL)
+ $?.to_i.should == $?
+ $?.should == $?.to_i
+ end
end
diff --git a/spec/ruby/core/process/status/exited_spec.rb b/spec/ruby/core/process/status/exited_spec.rb
index 0ae3f9e7ae..a61292b146 100644
--- a/spec/ruby/core/process/status/exited_spec.rb
+++ b/spec/ruby/core/process/status/exited_spec.rb
@@ -1,9 +1,7 @@
require_relative '../../../spec_helper'
describe "Process::Status#exited?" do
-
describe "for a child that exited normally" do
-
before :each do
ruby_exe("exit(0)")
end
@@ -15,9 +13,8 @@ describe "Process::Status#exited?" do
describe "for a terminated child" do
-
before :each do
- ruby_exe("Process.kill(:KILL, $$); exit(42)")
+ ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : :SIGKILL)
end
platform_is_not :windows do
@@ -31,7 +28,5 @@ describe "Process::Status#exited?" do
$?.exited?.should be_true
end
end
-
end
-
end
diff --git a/spec/ruby/core/process/status/exitstatus_spec.rb b/spec/ruby/core/process/status/exitstatus_spec.rb
index cd46b2081f..5c86c2b3c8 100644
--- a/spec/ruby/core/process/status/exitstatus_spec.rb
+++ b/spec/ruby/core/process/status/exitstatus_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../../spec_helper'
describe "Process::Status#exitstatus" do
before :each do
- ruby_exe("exit(42)")
+ ruby_exe("exit(42)", exit_status: 42)
end
it "returns the process exit code" do
@@ -11,7 +11,7 @@ describe "Process::Status#exitstatus" do
describe "for a child that raised SignalException" do
before :each do
- ruby_exe("raise SignalException, 'SIGTERM'")
+ ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : :SIGKILL)
end
platform_is_not :windows do
diff --git a/spec/ruby/core/process/status/right_shift_spec.rb b/spec/ruby/core/process/status/right_shift_spec.rb
index e9dda437e8..355aaf4c95 100644
--- a/spec/ruby/core/process/status/right_shift_spec.rb
+++ b/spec/ruby/core/process/status/right_shift_spec.rb
@@ -1,5 +1,37 @@
require_relative '../../../spec_helper'
-describe "Process::Status#>>" do
- it "needs to be reviewed for spec completeness"
+ruby_version_is ""..."4.0" do
+
+ describe "Process::Status#>>" do
+ it "returns a right shift of the integer status of an exited child" do
+ suppress_warning do
+ ruby_exe("exit(29)", exit_status: 29)
+ ($? >> 0).should == $?.to_i
+ ($? >> 1).should == $?.to_i >> 1
+
+ # Actual value is implementation specific
+ platform_is :linux do
+ ($? >> 8).should == 29
+ end
+ end
+ end
+
+ ruby_version_is "3.3"..."4.0" do
+ it "raises an ArgumentError if shift value is negative" do
+ suppress_warning do
+ ruby_exe("exit(0)")
+ -> {
+ $? >> -1
+ }.should raise_error(ArgumentError, 'negative shift value: -1')
+ end
+ end
+
+ it "shows a deprecation warning" do
+ ruby_exe("exit(0)")
+ -> {
+ $? >> 0
+ }.should complain(/warning: Process::Status#>> is deprecated and will be removed .*use other Process::Status attributes instead/)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/process/status/signaled_spec.rb b/spec/ruby/core/process/status/signaled_spec.rb
index f23c95025f..c0de7b8006 100644
--- a/spec/ruby/core/process/status/signaled_spec.rb
+++ b/spec/ruby/core/process/status/signaled_spec.rb
@@ -1,9 +1,7 @@
require_relative '../../../spec_helper'
describe "Process::Status#signaled?" do
-
describe "for a cleanly exited child" do
-
before :each do
ruby_exe("exit(0)")
end
@@ -14,9 +12,8 @@ describe "Process::Status#signaled?" do
end
describe "for a terminated child" do
-
before :each do
- ruby_exe("Process.kill(:KILL, $$); exit(42)")
+ ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : :SIGKILL)
end
platform_is_not :windows do
@@ -30,6 +27,5 @@ describe "Process::Status#signaled?" do
$?.signaled?.should be_false
end
end
-
end
end
diff --git a/spec/ruby/core/process/status/success_spec.rb b/spec/ruby/core/process/status/success_spec.rb
index 28a1721800..3589cc611f 100644
--- a/spec/ruby/core/process/status/success_spec.rb
+++ b/spec/ruby/core/process/status/success_spec.rb
@@ -1,9 +1,7 @@
require_relative '../../../spec_helper'
describe "Process::Status#success?" do
-
describe "for a child that exited normally" do
-
before :each do
ruby_exe("exit(0)")
end
@@ -14,9 +12,8 @@ describe "Process::Status#success?" do
end
describe "for a child that exited with a non zero status" do
-
before :each do
- ruby_exe("exit(42)")
+ ruby_exe("exit(42)", exit_status: 42)
end
it "returns false" do
@@ -25,27 +22,20 @@ describe "Process::Status#success?" do
end
describe "for a child that was terminated" do
-
before :each do
- ruby_exe("Process.kill(:KILL, $$); exit(42)")
+ ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : :SIGKILL)
end
platform_is_not :windows do
-
it "returns nil" do
$?.success?.should be_nil
end
-
end
platform_is :windows do
-
it "always returns true" do
$?.success?.should be_true
end
-
end
-
end
-
end
diff --git a/spec/ruby/core/process/status/termsig_spec.rb b/spec/ruby/core/process/status/termsig_spec.rb
index 1482d27146..9a22dbea71 100644
--- a/spec/ruby/core/process/status/termsig_spec.rb
+++ b/spec/ruby/core/process/status/termsig_spec.rb
@@ -1,21 +1,19 @@
require_relative '../../../spec_helper'
describe "Process::Status#termsig" do
-
describe "for a child that exited normally" do
-
before :each do
ruby_exe("exit(0)")
end
- it "returns true" do
+ it "returns nil" do
$?.termsig.should be_nil
end
end
describe "for a child that raised SignalException" do
before :each do
- ruby_exe("raise SignalException, 'SIGTERM'")
+ ruby_exe("raise SignalException, 'SIGTERM'", exit_status: :SIGTERM)
end
platform_is_not :windows do
@@ -26,26 +24,20 @@ describe "Process::Status#termsig" do
end
describe "for a child that was sent a signal" do
-
before :each do
- ruby_exe("Process.kill(:KILL, $$); exit(42)")
+ ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : :SIGKILL)
end
platform_is_not :windows do
-
it "returns the signal" do
$?.termsig.should == Signal.list["KILL"]
end
-
end
platform_is :windows do
-
it "always returns nil" do
$?.termsig.should be_nil
end
-
end
-
end
end
diff --git a/spec/ruby/core/process/status/to_i_spec.rb b/spec/ruby/core/process/status/to_i_spec.rb
index 37b7bdb1e4..39f8e2d84c 100644
--- a/spec/ruby/core/process/status/to_i_spec.rb
+++ b/spec/ruby/core/process/status/to_i_spec.rb
@@ -1,5 +1,13 @@
require_relative '../../../spec_helper'
describe "Process::Status#to_i" do
- it "needs to be reviewed for spec completeness"
+ it "returns an integer when the child exits" do
+ ruby_exe('exit 48', exit_status: 48)
+ $?.to_i.should be_an_instance_of(Integer)
+ end
+
+ it "returns an integer when the child is signaled" do
+ ruby_exe('raise SignalException, "TERM"', exit_status: platform_is(:windows) ? 3 : :SIGTERM)
+ $?.to_i.should be_an_instance_of(Integer)
+ end
end
diff --git a/spec/ruby/core/process/status/wait_spec.rb b/spec/ruby/core/process/status/wait_spec.rb
new file mode 100644
index 0000000000..57d56209a9
--- /dev/null
+++ b/spec/ruby/core/process/status/wait_spec.rb
@@ -0,0 +1,100 @@
+require_relative '../../../spec_helper'
+require_relative '../fixtures/common'
+
+describe "Process::Status.wait" do
+ ProcessSpecs.use_system_ruby(self)
+
+ before :all do
+ begin
+ leaked = Process.waitall
+ # Ruby-space should not see PIDs used by rjit
+ raise "subprocesses leaked before wait specs: #{leaked}" unless leaked.empty?
+ rescue NotImplementedError
+ end
+ end
+
+ it "returns a status with pid -1 if there are no child processes" do
+ Process::Status.wait.pid.should == -1
+ end
+
+ platform_is_not :windows do
+ it "returns a status with its child pid" do
+ pid = Process.spawn(ruby_cmd('exit'))
+ status = Process::Status.wait
+ status.should be_an_instance_of(Process::Status)
+ status.pid.should == pid
+ end
+
+ it "should not set $? to the Process::Status" do
+ pid = Process.spawn(ruby_cmd('exit'))
+ status = Process::Status.wait
+ $?.should_not equal(status)
+ end
+
+ it "should not change the value of $?" do
+ pid = Process.spawn(ruby_cmd('exit'))
+ Process.wait
+ status = $?
+ Process::Status.wait
+ status.should equal($?)
+ end
+
+ it "waits for any child process if no pid is given" do
+ pid = Process.spawn(ruby_cmd('exit'))
+ Process::Status.wait.pid.should == pid
+ -> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
+ end
+
+ it "waits for a specific child if a pid is given" do
+ pid1 = Process.spawn(ruby_cmd('exit'))
+ pid2 = Process.spawn(ruby_cmd('exit'))
+ Process::Status.wait(pid2).pid.should == pid2
+ Process::Status.wait(pid1).pid.should == pid1
+ -> { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH)
+ -> { Process.kill(0, pid2) }.should raise_error(Errno::ESRCH)
+ end
+
+ it "coerces the pid to an Integer" do
+ pid1 = Process.spawn(ruby_cmd('exit'))
+ Process::Status.wait(mock_int(pid1)).pid.should == pid1
+ -> { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH)
+ end
+
+ # This spec is probably system-dependent.
+ it "waits for a child whose process group ID is that of the calling process" do
+ pid1 = Process.spawn(ruby_cmd('exit'), pgroup: true)
+ pid2 = Process.spawn(ruby_cmd('exit'))
+
+ Process::Status.wait(0).pid.should == pid2
+ Process::Status.wait.pid.should == pid1
+ end
+
+ # This spec is probably system-dependent.
+ it "doesn't block if no child is available when WNOHANG is used" do
+ read, write = IO.pipe
+ pid = Process.fork do
+ read.close
+ Signal.trap("TERM") { Process.exit! }
+ write << 1
+ write.close
+ sleep
+ end
+
+ Process::Status.wait(pid, Process::WNOHANG).should be_nil
+
+ # wait for the child to setup its TERM handler
+ write.close
+ read.read(1)
+ read.close
+
+ Process.kill("TERM", pid)
+ Process::Status.wait.pid.should == pid
+ end
+
+ it "always accepts flags=0" do
+ pid = Process.spawn(ruby_cmd('exit'))
+ Process::Status.wait(-1, 0).pid.should == pid
+ -> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
+ end
+ end
+end
diff --git a/spec/ruby/core/process/times_spec.rb b/spec/ruby/core/process/times_spec.rb
index 07b4fa5c9f..d3bff2cda9 100644
--- a/spec/ruby/core/process/times_spec.rb
+++ b/spec/ruby/core/process/times_spec.rb
@@ -5,23 +5,15 @@ describe "Process.times" do
Process.times.should be_kind_of(Process::Tms)
end
- it "returns current cpu times" do
- t = Process.times
+ # TODO: Intel C Compiler does not work this example
+ # http://rubyci.s3.amazonaws.com/icc-x64/ruby-master/log/20221013T030005Z.fail.html.gz
+ unless RbConfig::CONFIG['CC']&.include?("icx")
+ it "returns current cpu times" do
+ t = Process.times
+ user = t.utime
- # Do busy work for a wall-clock interval.
- start = Time.now
- 1 until (Time.now - start) > 0.5
-
- # Ensure times is larger. NOTE that there is no
- # guarantee of an upper bound since anything may be
- # happening at the OS level, so we ONLY check that at
- # least an interval has elapsed. Also, we are assuming
- # there is a correlation between wall clock time and
- # process time. In practice, there is an observed
- # discrepancy often 10% or greater. In other words,
- # this is a very fuzzy test.
- t2 = Process.times
- diff = (t2.utime + t2.stime) - (t.utime + t.stime)
- diff.should > 0
+ 1 until Process.times.utime > user
+ Process.times.utime.should > user
+ end
end
end
diff --git a/spec/ruby/core/process/tms/cstime_spec.rb b/spec/ruby/core/process/tms/cstime_spec.rb
index 207d4391c0..9c2d9e8632 100644
--- a/spec/ruby/core/process/tms/cstime_spec.rb
+++ b/spec/ruby/core/process/tms/cstime_spec.rb
@@ -1,9 +1,17 @@
require_relative '../../../spec_helper'
describe "Process::Tms#cstime" do
- it "needs to be reviewed for spec completeness"
+ it "returns cstime attribute" do
+ cstime = Object.new
+ Process::Tms.new(nil, nil, nil, cstime).cstime.should == cstime
+ end
end
describe "Process::Tms#cstime=" do
- it "needs to be reviewed for spec completeness"
+ it "assigns a value to the cstime attribute" do
+ cstime = Object.new
+ tms = Process::Tms.new
+ tms.cstime = cstime
+ tms.cstime.should == cstime
+ end
end
diff --git a/spec/ruby/core/process/tms/cutime_spec.rb b/spec/ruby/core/process/tms/cutime_spec.rb
index 390280f005..0ac3ff1964 100644
--- a/spec/ruby/core/process/tms/cutime_spec.rb
+++ b/spec/ruby/core/process/tms/cutime_spec.rb
@@ -1,9 +1,17 @@
require_relative '../../../spec_helper'
describe "Process::Tms#cutime" do
- it "needs to be reviewed for spec completeness"
+ it "returns cutime attribute" do
+ cutime = Object.new
+ Process::Tms.new(nil, nil, cutime, nil).cutime.should == cutime
+ end
end
describe "Process::Tms#cutime=" do
- it "needs to be reviewed for spec completeness"
+ it "assigns a value to the cutime attribute" do
+ cutime = Object.new
+ tms = Process::Tms.new
+ tms.cutime = cutime
+ tms.cutime.should == cutime
+ end
end
diff --git a/spec/ruby/core/process/tms/element_reference_spec.rb b/spec/ruby/core/process/tms/element_reference_spec.rb
deleted file mode 100644
index 84a34089ae..0000000000
--- a/spec/ruby/core/process/tms/element_reference_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../../spec_helper'
-
-describe "Process::Tms.[]" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/process/tms/members_spec.rb b/spec/ruby/core/process/tms/members_spec.rb
deleted file mode 100644
index 005a8baec1..0000000000
--- a/spec/ruby/core/process/tms/members_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../../spec_helper'
-
-describe "Process::Tms.members" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/process/tms/new_spec.rb b/spec/ruby/core/process/tms/new_spec.rb
deleted file mode 100644
index 9dd1f5a8f2..0000000000
--- a/spec/ruby/core/process/tms/new_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../../spec_helper'
-
-describe "Process::Tms.new" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/process/tms/stime_spec.rb b/spec/ruby/core/process/tms/stime_spec.rb
index 4104b625e2..1e8371475f 100644
--- a/spec/ruby/core/process/tms/stime_spec.rb
+++ b/spec/ruby/core/process/tms/stime_spec.rb
@@ -1,9 +1,17 @@
require_relative '../../../spec_helper'
describe "Process::Tms#stime" do
- it "needs to be reviewed for spec completeness"
+ it "returns stime attribute" do
+ stime = Object.new
+ Process::Tms.new(nil, stime, nil, nil).stime.should == stime
+ end
end
describe "Process::Tms#stime=" do
- it "needs to be reviewed for spec completeness"
+ it "assigns a value to the stime attribute" do
+ stime = Object.new
+ tms = Process::Tms.new
+ tms.stime = stime
+ tms.stime.should == stime
+ end
end
diff --git a/spec/ruby/core/process/tms/utime_spec.rb b/spec/ruby/core/process/tms/utime_spec.rb
index 28371590e9..403a31e2e6 100644
--- a/spec/ruby/core/process/tms/utime_spec.rb
+++ b/spec/ruby/core/process/tms/utime_spec.rb
@@ -1,9 +1,17 @@
require_relative '../../../spec_helper'
describe "Process::Tms#utime" do
- it "needs to be reviewed for spec completeness"
+ it "returns utime attribute" do
+ utime = Object.new
+ Process::Tms.new(utime, nil, nil, nil).utime.should == utime
+ end
end
describe "Process::Tms#utime=" do
- it "needs to be reviewed for spec completeness"
+ it "assigns a value to the ctime attribute" do
+ utime = Object.new
+ tms = Process::Tms.new
+ tms.utime = utime
+ tms.utime.should == utime
+ end
end
diff --git a/spec/ruby/core/process/uid_spec.rb b/spec/ruby/core/process/uid_spec.rb
index 350779aff3..a068b1a2c1 100644
--- a/spec/ruby/core/process/uid_spec.rb
+++ b/spec/ruby/core/process/uid_spec.rb
@@ -20,16 +20,16 @@ end
describe "Process.uid=" do
platform_is_not :windows do
it "raises TypeError if not passed an Integer" do
- lambda { Process.uid = Object.new }.should raise_error(TypeError)
+ -> { Process.uid = Object.new }.should raise_error(TypeError)
end
as_user do
it "raises Errno::ERPERM if run by a non privileged user trying to set the superuser id" do
- lambda { (Process.uid = 0)}.should raise_error(Errno::EPERM)
+ -> { (Process.uid = 0)}.should raise_error(Errno::EPERM)
end
it "raises Errno::ERPERM if run by a non privileged user trying to set the superuser id from username" do
- lambda { Process.uid = "root" }.should raise_error(Errno::EPERM)
+ -> { Process.uid = "root" }.should raise_error(Errno::EPERM)
end
end
diff --git a/spec/ruby/core/process/wait2_spec.rb b/spec/ruby/core/process/wait2_spec.rb
index 4b6491ccd2..8ba429dc96 100644
--- a/spec/ruby/core/process/wait2_spec.rb
+++ b/spec/ruby/core/process/wait2_spec.rb
@@ -4,14 +4,14 @@ describe "Process.wait2" do
before :all do
# HACK: this kludge is temporarily necessary because some
# misbehaving spec somewhere else does not clear processes
- # Note: background processes are unavoidable with MJIT,
+ # Note: background processes are unavoidable with RJIT,
# but we shouldn't reap them from Ruby-space
begin
Process.wait(-1, Process::WNOHANG)
$stderr.puts "Leaked process before wait2 specs! Waiting for it"
leaked = Process.waitall
$stderr.puts "leaked before wait2 specs: #{leaked}" unless leaked.empty?
- # Ruby-space should not see PIDs used by mjit
+ # Ruby-space should not see PIDs used by rjit
leaked.should be_empty
rescue Errno::ECHILD # No child processes
rescue NotImplementedError
@@ -30,7 +30,16 @@ describe "Process.wait2" do
end
it "raises a StandardError if no child processes exist" do
- lambda { Process.wait2 }.should raise_error(Errno::ECHILD)
- lambda { Process.wait2 }.should raise_error(StandardError)
+ -> { Process.wait2 }.should raise_error(Errno::ECHILD)
+ -> { Process.wait2 }.should raise_error(StandardError)
+ end
+
+ it "returns nil if the child process is still running when given the WNOHANG flag" do
+ IO.popen(ruby_cmd('STDIN.getbyte'), "w") do |io|
+ pid, status = Process.wait2(io.pid, Process::WNOHANG)
+ pid.should be_nil
+ status.should be_nil
+ io.write('a')
+ end
end
end
diff --git a/spec/ruby/core/process/wait_spec.rb b/spec/ruby/core/process/wait_spec.rb
index 000ff684d4..385acc9928 100644
--- a/spec/ruby/core/process/wait_spec.rb
+++ b/spec/ruby/core/process/wait_spec.rb
@@ -7,15 +7,14 @@ describe "Process.wait" do
before :all do
begin
leaked = Process.waitall
- puts "leaked before wait specs: #{leaked}" unless leaked.empty?
- # Ruby-space should not see PIDs used by mjit
- leaked.should be_empty
+ # Ruby-space should not see PIDs used by rjit
+ raise "subprocesses leaked before wait specs: #{leaked}" unless leaked.empty?
rescue NotImplementedError
end
end
it "raises an Errno::ECHILD if there are no child processes" do
- lambda { Process.wait }.should raise_error(Errno::ECHILD)
+ -> { Process.wait }.should raise_error(Errno::ECHILD)
end
platform_is_not :windows do
@@ -34,7 +33,7 @@ describe "Process.wait" do
it "waits for any child process if no pid is given" do
pid = Process.spawn(ruby_cmd('exit'))
Process.wait.should == pid
- lambda { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
+ -> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
end
it "waits for a specific child if a pid is given" do
@@ -42,14 +41,14 @@ describe "Process.wait" do
pid2 = Process.spawn(ruby_cmd('exit'))
Process.wait(pid2).should == pid2
Process.wait(pid1).should == pid1
- lambda { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH)
- lambda { Process.kill(0, pid2) }.should raise_error(Errno::ESRCH)
+ -> { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH)
+ -> { Process.kill(0, pid2) }.should raise_error(Errno::ESRCH)
end
it "coerces the pid to an Integer" do
pid1 = Process.spawn(ruby_cmd('exit'))
Process.wait(mock_int(pid1)).should == pid1
- lambda { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH)
+ -> { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH)
end
# This spec is probably system-dependent.
@@ -86,7 +85,7 @@ describe "Process.wait" do
it "always accepts flags=0" do
pid = Process.spawn(ruby_cmd('exit'))
Process.wait(-1, 0).should == pid
- lambda { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
+ -> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
end
end
end
diff --git a/spec/ruby/core/process/waitall_spec.rb b/spec/ruby/core/process/waitall_spec.rb
index bdc1ea7490..6cf4e32bc9 100644
--- a/spec/ruby/core/process/waitall_spec.rb
+++ b/spec/ruby/core/process/waitall_spec.rb
@@ -13,7 +13,7 @@ describe "Process.waitall" do
end
it "takes no arguments" do
- lambda { Process.waitall(0) }.should raise_error(ArgumentError)
+ -> { Process.waitall(0) }.should raise_error(ArgumentError)
end
platform_is_not :windows do
@@ -24,7 +24,7 @@ describe "Process.waitall" do
pids << Process.fork { Process.exit! 0 }
Process.waitall
pids.each { |pid|
- lambda { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
+ -> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
}
end
diff --git a/spec/ruby/core/process/waitpid_spec.rb b/spec/ruby/core/process/waitpid_spec.rb
index f7cf1a45a8..a02147b663 100644
--- a/spec/ruby/core/process/waitpid_spec.rb
+++ b/spec/ruby/core/process/waitpid_spec.rb
@@ -2,7 +2,8 @@ require_relative '../../spec_helper'
describe "Process.waitpid" do
it "returns nil when the process has not yet completed and WNOHANG is specified" do
- pid = spawn("sleep 5")
+ cmd = platform_is(:windows) ? "timeout" : "sleep"
+ pid = spawn("#{cmd} 5")
begin
Process.waitpid(pid, Process::WNOHANG).should == nil
Process.kill("KILL", pid)
diff --git a/spec/ruby/core/process/warmup_spec.rb b/spec/ruby/core/process/warmup_spec.rb
new file mode 100644
index 0000000000..b562d52d22
--- /dev/null
+++ b/spec/ruby/core/process/warmup_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../spec_helper'
+
+describe "Process.warmup" do
+ ruby_version_is "3.3" do
+ # The behavior is entirely implementation specific.
+ # Other implementations are free to just make it a noop
+ it "is implemented" do
+ Process.warmup.should == true
+ end
+ end
+end