mirror of
https://github.com/samsonjs/csc360-a1-shell.git
synced 2026-03-25 08:45:52 +00:00
Update to Ruby 4, update gems, s/rubocop/standard/
This commit is contained in:
parent
71a7c7d6ed
commit
f72ddf7f32
14 changed files with 140 additions and 130 deletions
|
|
@ -1,26 +0,0 @@
|
||||||
AllCops:
|
|
||||||
NewCops: enable
|
|
||||||
|
|
||||||
Layout/EmptyLineAfterGuardClause:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
Layout/FirstHashElementIndentation:
|
|
||||||
EnforcedStyle: consistent
|
|
||||||
|
|
||||||
Metrics/AbcSize:
|
|
||||||
Max: 25
|
|
||||||
|
|
||||||
Metrics/MethodLength:
|
|
||||||
Max: 30
|
|
||||||
|
|
||||||
Style/Documentation:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
Style/FrozenStringLiteralComment:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
Style/HashSyntax:
|
|
||||||
EnforcedShorthandSyntax: never
|
|
||||||
|
|
||||||
Style/TrailingCommaInHashLiteral:
|
|
||||||
EnforcedStyleForMultiline: consistent_comma
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
3.2.2
|
4.0.0
|
||||||
|
|
|
||||||
4
ruby/.standard.yml
Normal file
4
ruby/.standard.yml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
fix: true
|
||||||
|
parallel: true
|
||||||
|
ignore:
|
||||||
|
- "test_bin/**/*"
|
||||||
10
ruby/Gemfile
10
ruby/Gemfile
|
|
@ -1,6 +1,8 @@
|
||||||
source "https://rubygems.org"
|
source "https://rubygems.org"
|
||||||
|
|
||||||
gem 'minitest', '~> 5.20'
|
gem "minitest", "~> 6.0"
|
||||||
gem 'rake', '~> 13.0'
|
gem "parser", "~> 3.3.10"
|
||||||
gem 'rubocop', '1.56.4'
|
gem "rake", "~> 13.0"
|
||||||
gem 'wordexp', '~> 0.2'
|
gem "reline", "~> 0.6"
|
||||||
|
gem "standard", "~> 1.52.0", require: false
|
||||||
|
gem "wordexp", "~> 0.2"
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,72 @@
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
ast (2.4.2)
|
ast (2.4.3)
|
||||||
base64 (0.1.1)
|
io-console (0.8.2)
|
||||||
json (2.6.3)
|
json (2.18.0)
|
||||||
language_server-protocol (3.17.0.3)
|
language_server-protocol (3.17.0.5)
|
||||||
minitest (5.20.0)
|
lint_roller (1.1.0)
|
||||||
parallel (1.23.0)
|
minitest (6.0.1)
|
||||||
parser (3.2.2.4)
|
prism (~> 1.5)
|
||||||
|
parallel (1.27.0)
|
||||||
|
parser (3.3.10.0)
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
racc
|
racc
|
||||||
racc (1.7.1)
|
prism (1.7.0)
|
||||||
|
racc (1.8.1)
|
||||||
rainbow (3.1.1)
|
rainbow (3.1.1)
|
||||||
rake (13.0.6)
|
rake (13.3.1)
|
||||||
regexp_parser (2.8.1)
|
regexp_parser (2.11.3)
|
||||||
rexml (3.2.6)
|
reline (0.6.3)
|
||||||
rubocop (1.56.4)
|
io-console (~> 0.5)
|
||||||
base64 (~> 0.1.1)
|
rubocop (1.81.7)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (>= 3.17.0)
|
language_server-protocol (~> 3.17.0.2)
|
||||||
|
lint_roller (~> 1.1.0)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
parser (>= 3.2.2.3)
|
parser (>= 3.3.0.2)
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
regexp_parser (>= 1.8, < 3.0)
|
regexp_parser (>= 2.9.3, < 3.0)
|
||||||
rexml (>= 3.2.5, < 4.0)
|
rubocop-ast (>= 1.47.1, < 2.0)
|
||||||
rubocop-ast (>= 1.28.1, < 2.0)
|
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 2.4.0, < 3.0)
|
unicode-display_width (>= 2.4.0, < 4.0)
|
||||||
rubocop-ast (1.29.0)
|
rubocop-ast (1.49.0)
|
||||||
parser (>= 3.2.1.0)
|
parser (>= 3.3.7.2)
|
||||||
|
prism (~> 1.7)
|
||||||
|
rubocop-performance (1.26.1)
|
||||||
|
lint_roller (~> 1.1)
|
||||||
|
rubocop (>= 1.75.0, < 2.0)
|
||||||
|
rubocop-ast (>= 1.47.1, < 2.0)
|
||||||
ruby-progressbar (1.13.0)
|
ruby-progressbar (1.13.0)
|
||||||
unicode-display_width (2.5.0)
|
standard (1.52.0)
|
||||||
|
language_server-protocol (~> 3.17.0.2)
|
||||||
|
lint_roller (~> 1.0)
|
||||||
|
rubocop (~> 1.81.7)
|
||||||
|
standard-custom (~> 1.0.0)
|
||||||
|
standard-performance (~> 1.8)
|
||||||
|
standard-custom (1.0.2)
|
||||||
|
lint_roller (~> 1.0)
|
||||||
|
rubocop (~> 1.50)
|
||||||
|
standard-performance (1.9.0)
|
||||||
|
lint_roller (~> 1.1)
|
||||||
|
rubocop-performance (~> 1.26.0)
|
||||||
|
unicode-display_width (3.2.0)
|
||||||
|
unicode-emoji (~> 4.1)
|
||||||
|
unicode-emoji (4.2.0)
|
||||||
wordexp (0.2.2)
|
wordexp (0.2.2)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
arm64-darwin-21
|
arm64-darwin-21
|
||||||
arm64-darwin-22
|
arm64-darwin-22
|
||||||
arm64-darwin-23
|
arm64-darwin-23
|
||||||
|
arm64-darwin-25
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
minitest (~> 5.20)
|
minitest (~> 6.0)
|
||||||
|
parser (~> 3.3.10)
|
||||||
rake (~> 13.0)
|
rake (~> 13.0)
|
||||||
rubocop (= 1.56.4)
|
reline (~> 0.6)
|
||||||
|
standard (~> 1.52.0)
|
||||||
wordexp (~> 0.2)
|
wordexp (~> 0.2)
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
require 'rake/testtask'
|
require "rake/testtask"
|
||||||
|
require "standard/rake"
|
||||||
|
|
||||||
task default: 'test'
|
task default: %i[test standard]
|
||||||
|
|
||||||
Rake::TestTask.new do |task|
|
Rake::TestTask.new do |task|
|
||||||
task.pattern = 'test/*_test.rb'
|
task.pattern = "test/*_test.rb"
|
||||||
end
|
end
|
||||||
|
|
||||||
task :clean do
|
task :clean do
|
||||||
FileUtils.rm_rf('test_bin')
|
FileUtils.rm_rf("test_bin")
|
||||||
end
|
end
|
||||||
|
|
|
||||||
4
ruby/a1
4
ruby/a1
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env ruby -w
|
#!/usr/bin/env ruby -w
|
||||||
|
|
||||||
require 'English'
|
require "English"
|
||||||
require_relative 'shell'
|
require_relative "shell"
|
||||||
|
|
||||||
Shell::CLI.new.run(args: ARGV) if $PROGRAM_NAME == __FILE__
|
Shell::CLI.new.run(args: ARGV) if $PROGRAM_NAME == __FILE__
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
$LOAD_PATH << File.expand_path(__dir__)
|
$LOAD_PATH << File.expand_path(__dir__)
|
||||||
|
|
||||||
require 'shell/cli'
|
require "shell/cli"
|
||||||
require 'shell/repl'
|
require "shell/repl"
|
||||||
|
|
||||||
module Shell
|
module Shell
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
require 'shell/job_control'
|
require "shell/job_control"
|
||||||
require 'shell/logger'
|
require "shell/logger"
|
||||||
|
|
||||||
module Shell
|
module Shell
|
||||||
class Builtins
|
class Builtins
|
||||||
|
|
@ -34,14 +34,14 @@ module Shell
|
||||||
jobs.each do |job|
|
jobs.each do |job|
|
||||||
puts job_control.format_job(job)
|
puts job_control.format_job(job)
|
||||||
end
|
end
|
||||||
plural = jobs.count == 1 ? '' : 's'
|
plural = (jobs.count == 1) ? "" : "s"
|
||||||
puts "#{jobs.count} background job#{plural}"
|
puts "#{jobs.count} background job#{plural}"
|
||||||
0
|
0
|
||||||
end
|
end
|
||||||
|
|
||||||
def builtin_bgkill(args)
|
def builtin_bgkill(args)
|
||||||
if args.count != 1
|
if args.count != 1
|
||||||
logger.warn 'Usage: bgkill <job>'
|
logger.warn "Usage: bgkill <job>"
|
||||||
return -1
|
return -1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -57,11 +57,11 @@ module Shell
|
||||||
|
|
||||||
def builtin_export(args)
|
def builtin_export(args)
|
||||||
# only supports one variable and doesn't support quoting
|
# only supports one variable and doesn't support quoting
|
||||||
name, *value_parts = args.first.strip.split('=')
|
name, *value_parts = args.first.strip.split("=")
|
||||||
if name.nil? || name.empty?
|
if name.nil? || name.empty?
|
||||||
logger.warn "#{red('[ERROR]')} Invalid export command"
|
logger.warn "#{red("[ERROR]")} Invalid export command"
|
||||||
else
|
else
|
||||||
ENV[name] = value_parts.join('=').gsub(/\$\w+/) { |m| ENV[m[1..]] || '' }
|
ENV[name] = value_parts.join("=").gsub(/\$\w+/) { |m| ENV[m[1..]] || "" }
|
||||||
end
|
end
|
||||||
0
|
0
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
require 'shell/colours'
|
require "shell/colours"
|
||||||
require 'shell/logger'
|
require "shell/logger"
|
||||||
require 'shell/repl'
|
require "shell/repl"
|
||||||
|
|
||||||
module Shell
|
module Shell
|
||||||
class CLI
|
class CLI
|
||||||
|
|
@ -29,20 +29,20 @@ module Shell
|
||||||
|
|
||||||
def parse_options(args)
|
def parse_options(args)
|
||||||
options = {
|
options = {
|
||||||
verbose: false,
|
verbose: false
|
||||||
}
|
}
|
||||||
while (arg = args.shift)
|
while (arg = args.shift)
|
||||||
case arg
|
case arg
|
||||||
when '-c'
|
when "-c"
|
||||||
options[:command] = args.shift
|
options[:command] = args.shift
|
||||||
if options[:command].nil?
|
if options[:command].nil?
|
||||||
warn 'ERROR: expected string after -c'
|
warn "ERROR: expected string after -c"
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
when '-v', '--verbose'
|
when "-v", "--verbose"
|
||||||
options[:verbose] = true
|
options[:verbose] = true
|
||||||
else
|
else
|
||||||
logger.warn "#{red('[ERROR]')} Unknown argument: #{arg}"
|
logger.warn "#{red("[ERROR]")} Unknown argument: #{arg}"
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
require 'English'
|
require "English"
|
||||||
|
|
||||||
require 'shell/colours'
|
require "shell/colours"
|
||||||
require 'shell/job'
|
require "shell/job"
|
||||||
require 'shell/logger'
|
require "shell/logger"
|
||||||
|
|
||||||
module Shell
|
module Shell
|
||||||
class JobControl
|
class JobControl
|
||||||
|
|
@ -17,7 +17,7 @@ module Shell
|
||||||
|
|
||||||
def exec_command(cmd, args, background: false)
|
def exec_command(cmd, args, background: false)
|
||||||
unless (path = resolve_executable(cmd))
|
unless (path = resolve_executable(cmd))
|
||||||
warn "#{red('[ERROR]')} command not found: #{cmd}"
|
warn "#{red("[ERROR]")} command not found: #{cmd}"
|
||||||
return -2
|
return -2
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ module Shell
|
||||||
if background
|
if background
|
||||||
job = Job.new(next_job_id, pid, cmd, args)
|
job = Job.new(next_job_id, pid, cmd, args)
|
||||||
@jobs_by_pid[pid] = job
|
@jobs_by_pid[pid] = job
|
||||||
puts white('Running job ') + yellow(job.id) + white(" (pid #{pid}) in background")
|
puts white("Running job ") + yellow(job.id) + white(" (pid #{pid}) in background")
|
||||||
Process.waitpid(pid, Process::WNOHANG)
|
Process.waitpid(pid, Process::WNOHANG)
|
||||||
0
|
0
|
||||||
else
|
else
|
||||||
|
|
@ -38,8 +38,8 @@ module Shell
|
||||||
0
|
0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue StandardError => e
|
rescue => e
|
||||||
warn "#{red('[ERROR]')} #{e.message} #{e.inspect}"
|
warn "#{red("[ERROR]")} #{e.message} #{e.inspect}"
|
||||||
-5
|
-5
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -50,7 +50,7 @@ module Shell
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
Process.kill('TERM', job.pid)
|
Process.kill("TERM", job.pid)
|
||||||
rescue Errno::ESRCH
|
rescue Errno::ESRCH
|
||||||
logger.warn "No such proccess: #{job.pid}"
|
logger.warn "No such proccess: #{job.pid}"
|
||||||
end
|
end
|
||||||
|
|
@ -60,24 +60,24 @@ module Shell
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_job(job)
|
def format_job(job)
|
||||||
args = job.args.join(' ')
|
args = job.args.join(" ")
|
||||||
"#{yellow(job.id)}: #{white('(pid ', job.pid, ')')} #{green(job.cmd)} #{args}"
|
"#{yellow(job.id)}: #{white("(pid ", job.pid, ")")} #{green(job.cmd)} #{args}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def trap_sigchld
|
def trap_sigchld
|
||||||
# handler for SIGCHLD when a child's state changes
|
# handler for SIGCHLD when a child's state changes
|
||||||
Signal.trap('CHLD') do |_signo|
|
Signal.trap("CHLD") do |_signo|
|
||||||
pid = Process.waitpid(-1, Process::WNOHANG)
|
pid = Process.waitpid(-1, Process::WNOHANG)
|
||||||
if pid.nil?
|
if pid.nil?
|
||||||
# no-op
|
# no-op
|
||||||
elsif (job = @jobs_by_pid[pid])
|
elsif (job = @jobs_by_pid[pid])
|
||||||
@jobs_by_pid.delete(pid)
|
@jobs_by_pid.delete(pid)
|
||||||
time = Time.now.strftime('%T')
|
time = Time.now.strftime("%T")
|
||||||
job_text = yellow('job ', job.id, ' exited')
|
job_text = yellow("job ", job.id, " exited")
|
||||||
args = job.args.join(' ')
|
args = job.args.join(" ")
|
||||||
puts "\n[#{time}] #{job_text} #{white('(pid ', job.pid, ')')}: #{green(job.cmd)} #{args}"
|
puts "\n[#{time}] #{job_text} #{white("(pid ", job.pid, ")")}: #{green(job.cmd)} #{args}"
|
||||||
else
|
else
|
||||||
warn "\n#{yellow('[WARN]')} No job found for child with PID #{pid}"
|
warn "\n#{yellow("[WARN]")} No job found for child with PID #{pid}"
|
||||||
end
|
end
|
||||||
Readline.refresh_line
|
Readline.refresh_line
|
||||||
end
|
end
|
||||||
|
|
@ -88,11 +88,11 @@ module Shell
|
||||||
# Returns nil when no such command was found.
|
# Returns nil when no such command was found.
|
||||||
def resolve_executable(path_or_filename)
|
def resolve_executable(path_or_filename)
|
||||||
# process absolute and relative paths directly
|
# process absolute and relative paths directly
|
||||||
return path_or_filename if path_or_filename['/'] && \
|
return path_or_filename if path_or_filename["/"] &&
|
||||||
File.executable?(path_or_filename)
|
File.executable?(path_or_filename)
|
||||||
|
|
||||||
filename = path_or_filename
|
filename = path_or_filename
|
||||||
ENV['PATH'].split(':').each do |dir|
|
ENV["PATH"].split(":").each do |dir|
|
||||||
path = File.join(dir, filename)
|
path = File.join(dir, filename)
|
||||||
next unless File.exist?(path)
|
next unless File.exist?(path)
|
||||||
return path if File.executable?(path)
|
return path if File.executable?(path)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
require 'shell/colours'
|
require "shell/colours"
|
||||||
|
|
||||||
module Shell
|
module Shell
|
||||||
# Queues up messages to be printed out when readline is waiting for input, to prevent
|
# Queues up messages to be printed out when readline is waiting for input, to prevent
|
||||||
|
|
@ -19,16 +19,16 @@ module Shell
|
||||||
end
|
end
|
||||||
|
|
||||||
def log(message)
|
def log(message)
|
||||||
@logs << Log.new(:info, "#{white('[INFO]')} #{message}")
|
@logs << Log.new(:info, "#{white("[INFO]")} #{message}")
|
||||||
end
|
end
|
||||||
alias info log
|
alias_method :info, :log
|
||||||
|
|
||||||
def warn(message)
|
def warn(message)
|
||||||
@logs << Log.new(:warning, "#{yellow('[WARN]')} #{message}")
|
@logs << Log.new(:warning, "#{yellow("[WARN]")} #{message}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def error(message)
|
def error(message)
|
||||||
@logs << Log.new(:error, "#{red('[ERROR]')} #{message}")
|
@logs << Log.new(:error, "#{red("[ERROR]")} #{message}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def verbose(message)
|
def verbose(message)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
require 'readline'
|
begin
|
||||||
require 'wordexp'
|
require "readline"
|
||||||
|
rescue LoadError
|
||||||
|
require "reline"
|
||||||
|
end
|
||||||
|
require "wordexp"
|
||||||
|
|
||||||
require 'shell/builtins'
|
require "shell/builtins"
|
||||||
require 'shell/colours'
|
require "shell/colours"
|
||||||
require 'shell/job_control'
|
require "shell/job_control"
|
||||||
require 'shell/logger'
|
require "shell/logger"
|
||||||
|
|
||||||
module Shell
|
module Shell
|
||||||
class REPL
|
class REPL
|
||||||
|
|
@ -55,13 +59,13 @@ module Shell
|
||||||
job_control.exec_command(cmd, args)
|
job_control.exec_command(cmd, args)
|
||||||
end
|
end
|
||||||
rescue Errno => e
|
rescue Errno => e
|
||||||
warn "#{red('[ERROR]')} #{e.message}"
|
warn "#{red("[ERROR]")} #{e.message}"
|
||||||
-1
|
-1
|
||||||
end
|
end
|
||||||
|
|
||||||
# Looks like this: /path/to/somewhere%
|
# Looks like this: /path/to/somewhere%
|
||||||
def prompt(pwd)
|
def prompt(pwd)
|
||||||
"#{blue(pwd)}#{white('%')} #{CLEAR}"
|
"#{blue(pwd)}#{white("%")} #{CLEAR}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
require 'minitest/autorun'
|
require "minitest/autorun"
|
||||||
|
|
||||||
class ShellTest < Minitest::Test
|
class ShellTest < Minitest::Test
|
||||||
TRIVIAL_SHELL_SCRIPT = "#!/bin/sh\ntrue".freeze
|
TRIVIAL_SHELL_SCRIPT = "#!/bin/sh\ntrue".freeze
|
||||||
|
|
||||||
A1_PATH = ENV.fetch('A1_PATH', './a1').freeze
|
A1_PATH = ENV.fetch("A1_PATH", "./a1").freeze
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
FileUtils.mkdir_p('test_bin')
|
FileUtils.mkdir_p("test_bin")
|
||||||
end
|
end
|
||||||
|
|
||||||
def teardown
|
def teardown
|
||||||
FileUtils.rm_rf('test_bin')
|
FileUtils.rm_rf("test_bin")
|
||||||
end
|
end
|
||||||
|
|
||||||
def unique_shell_script(code)
|
def unique_shell_script(code)
|
||||||
|
|
@ -31,42 +31,42 @@ class ShellTest < Minitest::Test
|
||||||
#################################
|
#################################
|
||||||
|
|
||||||
def test_background_job
|
def test_background_job
|
||||||
output = `#{A1_PATH} -c 'bg echo hello'`.gsub(/\e\[([;\d]+)?m/, '')
|
output = `#{A1_PATH} -c 'bg echo hello'`.gsub(/\e\[([;\d]+)?m/, "")
|
||||||
pid = /\(pid (\d+)\)/.match(output)[1]
|
pid = /\(pid (\d+)\)/.match(output)[1]
|
||||||
assert_equal "Running job 1 (pid #{pid}) in background\nhello\n", output
|
assert_equal "Running job 1 (pid #{pid}) in background\nhello\n", output
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_resolves_executables_with_absolute_paths
|
def test_resolves_executables_with_absolute_paths
|
||||||
assert_equal '/usr/bin/which', `#{A1_PATH} -c '/usr/bin/which -a which'`.chomp
|
assert_equal "/usr/bin/which", `#{A1_PATH} -c '/usr/bin/which -a which'`.chomp
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_resolves_executables_with_relative_paths
|
def test_resolves_executables_with_relative_paths
|
||||||
File.write('test_bin/something', TRIVIAL_SHELL_SCRIPT)
|
File.write("test_bin/something", TRIVIAL_SHELL_SCRIPT)
|
||||||
File.chmod(0o755, 'test_bin/something')
|
File.chmod(0o755, "test_bin/something")
|
||||||
assert system("#{A1_PATH} -c ./test_bin/something")
|
assert system("#{A1_PATH} -c ./test_bin/something")
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_resolves_executables_in_absolute_paths
|
def test_resolves_executables_in_absolute_paths
|
||||||
assert_equal '/usr/bin/which', `#{A1_PATH} -c 'which -a which'`.chomp
|
assert_equal "/usr/bin/which", `#{A1_PATH} -c 'which -a which'`.chomp
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_resolves_executables_in_relative_paths
|
def test_resolves_executables_in_relative_paths
|
||||||
code = rand(1_000_000).to_s
|
code = rand(1_000_000).to_s
|
||||||
File.write('test_bin/definitely_executable', unique_shell_script(code))
|
File.write("test_bin/definitely_executable", unique_shell_script(code))
|
||||||
File.chmod(0o755, 'test_bin/definitely_executable')
|
File.chmod(0o755, "test_bin/definitely_executable")
|
||||||
actual = `PATH="./test_bin:$PATH" #{A1_PATH} -c definitely_executable`.chomp
|
actual = `PATH="./test_bin:$PATH" #{A1_PATH} -c definitely_executable`.chomp
|
||||||
assert_equal code, actual
|
assert_equal code, actual
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_does_not_resolve_non_executable_files_in_path
|
def test_does_not_resolve_non_executable_files_in_path
|
||||||
File.write('test_bin/definitely_not_executable', TRIVIAL_SHELL_SCRIPT)
|
File.write("test_bin/definitely_not_executable", TRIVIAL_SHELL_SCRIPT)
|
||||||
File.chmod(0o644, 'test_bin/definitely_not_executable')
|
File.chmod(0o644, "test_bin/definitely_not_executable")
|
||||||
actual = system("PATH=\"./test_bin:$PATH\" #{A1_PATH} -c definitely_not_executable 2>/dev/null")
|
actual = system("PATH=\"./test_bin:$PATH\" #{A1_PATH} -c definitely_not_executable 2>/dev/null")
|
||||||
assert_equal false, actual
|
assert_equal false, actual
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_refreshes_readline_after_bg_execution
|
def test_refreshes_readline_after_bg_execution
|
||||||
skip 'unimplemented'
|
skip "unimplemented"
|
||||||
end
|
end
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
|
|
@ -74,25 +74,25 @@ class ShellTest < Minitest::Test
|
||||||
#########################
|
#########################
|
||||||
|
|
||||||
def test_builtin_cd_no_args
|
def test_builtin_cd_no_args
|
||||||
skip 'cannot easily implement without sequencing with ; or &&'
|
skip "cannot easily implement without sequencing with ; or &&"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_builtin_cd
|
def test_builtin_cd
|
||||||
skip 'cannot easily implement without sequencing with ; or &&'
|
skip "cannot easily implement without sequencing with ; or &&"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_builtin_cd_dash
|
def test_builtin_cd_dash
|
||||||
skip 'cannot easily implement without sequencing with ; or &&'
|
skip "cannot easily implement without sequencing with ; or &&"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_builtin_cd_parent
|
def test_builtin_cd_parent
|
||||||
skip 'cannot easily implement without sequencing with ; or &&'
|
skip "cannot easily implement without sequencing with ; or &&"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_builtin_pwd
|
def test_builtin_pwd
|
||||||
assert_equal Dir.pwd, `#{A1_PATH} -c pwd`.chomp
|
assert_equal Dir.pwd, `#{A1_PATH} -c pwd`.chomp
|
||||||
|
|
||||||
shell_path = File.expand_path(A1_PATH, Dir.pwd)
|
shell_path = File.expand_path(A1_PATH, Dir.pwd)
|
||||||
assert_equal '/usr/bin', `cd /usr/bin && '#{shell_path}' -c pwd`.chomp
|
assert_equal "/usr/bin", `cd /usr/bin && '#{shell_path}' -c pwd`.chomp
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue