diff --git a/lib/uh/wm/cli.rb b/lib/uh/wm/cli.rb index c52f073..b11715a 100644 --- a/lib/uh/wm/cli.rb +++ b/lib/uh/wm/cli.rb @@ -5,7 +5,8 @@ module Uh USAGE = "Usage: #{File.basename $0} [options]".freeze - EX_USAGE = 64 + EX_USAGE = 64 + EX_SOFTWARE = 70 class << self def run arguments, stdout: $stdout, stderr: $stderr @@ -15,6 +16,10 @@ module Uh rescue ArgumentError => e stderr.puts e exit EX_USAGE + rescue RuntimeError => e + stderr.puts "#{e.class.name}: #{e.message}" + stderr.puts e.backtrace.map { |e| ' %s' % e } if cli.env.debug? + exit EX_SOFTWARE end end diff --git a/spec/uh/wm/cli_spec.rb b/spec/uh/wm/cli_spec.rb index 24cb07c..32a53ac 100644 --- a/spec/uh/wm/cli_spec.rb +++ b/spec/uh/wm/cli_spec.rb @@ -52,6 +52,39 @@ module Uh end end end + + context 'when the new CLI raises a runtime error' do + before do + allow(cli).to receive(:run) { fail RuntimeError, 'some error' } + allow(described_class).to receive(:new) { cli } + end + + it 'exits with a return status of 70' do + expect { run }.to raise_error(SystemExit) do |e| + expect(e.status).to eq 70 + end + end + + it 'formats the error' do + trap_exit { run } + expect(stderr.string) + .to match /\AUh::WM::RuntimeError: some error\n/ + end + + it 'does not output a backtrace' do + trap_exit { run } + expect(stderr.string).not_to include __FILE__ + end + + context 'when debug mode is enabled' do + let(:arguments) { %w[-d] } + + it 'outputs a backtrace' do + trap_exit { run } + expect(stderr.string).to include __FILE__ + end + end + end end describe '#initialize' do