From bc9faabfa188f8b38993f4dd3c58f7ed192f7423 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 17 Jul 2024 15:53:29 +1200 Subject: [PATCH] Fix failure logs and add explicit tests. --- gems.rb | 1 + lib/async/task.rb | 2 +- test/async/task.rb | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/gems.rb b/gems.rb index e9a6452..a79e4b9 100644 --- a/gems.rb +++ b/gems.rb @@ -23,6 +23,7 @@ gem "decode" gem "sus-fixtures-async" + gem "sus-fixtures-console", "~> 0.3" gem "bake-test" gem "bake-test-external" diff --git a/lib/async/task.rb b/lib/async/task.rb index 205217e..bc30349 100644 --- a/lib/async/task.rb +++ b/lib/async/task.rb @@ -191,7 +191,7 @@ def run(*arguments) rescue => error # I'm not completely happy with this overhead, but the alternative is to not log anything which makes debugging extremely difficult. Maybe we can introduce a debug wrapper which adds extra logging. if @finished.nil? - Console::Event::Failure.for(error).emit("Task may have ended with unhandled exception.", severity: :warn) + Console::Event::Failure.for(error).emit(self, "Task may have ended with unhandled exception.", severity: :warn) # else # Console::Event::Failure.for(error).emit(self, severity: :debug) end diff --git a/test/async/task.rb b/test/async/task.rb index 2c23950..5df6429 100644 --- a/test/async/task.rb +++ b/test/async/task.rb @@ -9,6 +9,8 @@ require 'async/clock' require 'async/queue' +require 'sus/fixtures/console' + require 'timer_quantum' describe Async::Task do @@ -909,4 +911,48 @@ def sleep_forever expect(child_task).to be(:stopped?) end end + + with "failing task" do + include_context Sus::Fixtures::Console::CapturedLogger + + it "logs a warning if a task fails without being waited on" do + failed_task = nil + + reactor.async do |task| + task.async do |task| + failed_task = task + raise "boom" + end + end + + reactor.run + + expect_console.to have_logged( + severity: be == :warn, + subject: be_equal(failed_task), + message: be == "Task may have ended with unhandled exception." + ) + end + + it "does not log a warning if a task fails and is waited on" do + failed_task = nil + + reactor.async do |task| + expect do + task.async do |task| + # This ensures #wait is called by the parent before proceeding to raise the exception: + task.yield + failed_task = task + raise "boom" + end.wait + end.to raise_exception(RuntimeError, message: be =~ /boom/) + end + + reactor.run + + expect_console.not.to have_logged( + severity: be == :warn, + ) + end + end end