-
Notifications
You must be signed in to change notification settings - Fork 622
fix(naughty): ensure default timeout applies without ruled.notification #4081
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
JimmyCozza
wants to merge
4
commits into
awesomeWM:master
Choose a base branch
from
JimmyCozza:fix/naughty-default-timeout
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+93
−25
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
a645298
fix(naughty): ensure default timeout applies without ruled.notificati…
JimmyCozza 6169860
fix(tests): use `message` instead of deprecated `text` in timeout test
JimmyCozza ae04548
fix(tests): remove unused arguments to satisfy luacheck
JimmyCozza b8e919a
fix(tests): address review feedback on timeout test
JimmyCozza File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,37 +1,107 @@ | ||
| -- Test that setting timeout=0 on an existing notification stops and clears | ||
| -- the old timer (regression test for set_timeout() only stopping the timer | ||
| -- inside the timeout > 0 branch). | ||
| -- Test: Notification timeout bugs. | ||
| -- | ||
| -- 1. Setting timeout=0 doesn't stop existing timer: | ||
| -- set_timeout() at notification.lua only stops the old timer inside | ||
| -- the `if timeout > 0` block. When timeout is 0 (meaning "never expire"), | ||
| -- the else branch never stops the old timer. So setting n.timeout = 0 | ||
| -- after creation leaves the old timer running. | ||
| -- | ||
| -- 2. Default timeout never starts when no explicit timeout is given: | ||
| -- The constructor guard `if n._private.timeout then` skips set_timeout() | ||
| -- when timeout is nil (not provided). Without ruled.notification, this | ||
| -- means notifications with no explicit timeout never expire. | ||
|
|
||
| require("naughty") | ||
| local naughty = require("naughty") | ||
| local notification = require("naughty.notification") | ||
| local runner = require("_runner") | ||
|
|
||
| -- Register a request::preset handler to enable the new API path. | ||
| naughty.connect_signal("request::preset", function() end) | ||
|
|
||
| -- Register a display handler so notifications are "shown" | ||
| naughty.connect_signal("request::display", function(n) | ||
| require("naughty.layout.box") { notification = n } | ||
| end) | ||
|
|
||
| local n_timeout_zero = nil | ||
| local n_default = nil | ||
|
|
||
| local steps = {} | ||
|
|
||
| -- Setting timeout=0 after creation should stop the existing timer. | ||
| -- Create notification with timeout=5 (creates a timer), then set timeout=0. | ||
| -- The old timer should stop, but it doesn't because the timer-stop code is | ||
| -- inside the `if timeout > 0` block. | ||
| table.insert(steps, function() | ||
| -- Create a notification with a 5-second timeout (starts a timer). | ||
| local n = notification { | ||
| title = "timeout-test", | ||
| n_timeout_zero = notification { | ||
| title = "timeout zero after creation", | ||
| message = "Setting timeout=0 should stop the timer", | ||
| timeout = 5, | ||
| } | ||
|
|
||
| assert(n.timer, "expected a timer after timeout=5") | ||
| assert(n.timer.started, "expected timer to be started") | ||
| assert(n_timeout_zero, "notification was not created") | ||
| assert(n_timeout_zero.timer ~= nil, "timer should exist for timeout=5") | ||
| assert(n_timeout_zero.timer.started, | ||
| "timer should be running for timeout=5") | ||
|
|
||
| -- Now set timeout to 0, meaning "never expire" | ||
| n_timeout_zero.timeout = 0 | ||
|
|
||
| assert(n_timeout_zero.timeout == 0, | ||
| string.format("expected timeout=0, got %d", n_timeout_zero.timeout)) | ||
|
|
||
| -- Now set timeout=0 ("never expire"). The old timer must be stopped | ||
| -- and the reference cleared. | ||
| n.timeout = 0 | ||
| -- The old timer (5s) should have been stopped and cleared. | ||
| -- set_timeout(0) must stop the old timer and nil out self.timer so that | ||
| -- reset_timeout() doesn't accidentally restart a stale reference. | ||
| assert(n_timeout_zero.timer == nil, | ||
| "timer should be nil after setting timeout=0") | ||
|
|
||
| assert(not n.timer, "expected timer to be nil after timeout=0") | ||
| return true | ||
| end) | ||
|
|
||
| -- After setting timeout=0, reset_timeout() must not restart a stale timer. | ||
| -- reset_timeout() checks `self.timer and not self.timer.started` and would | ||
| -- restart the old (stopped) timer if set_timeout(0) forgot to nil it out. | ||
| table.insert(steps, function() | ||
| assert(n_timeout_zero, "notification should still exist") | ||
|
|
||
| -- reset_timeout() should be safe and not restart a stale timer. | ||
| n:reset_timeout() | ||
| n_timeout_zero:reset_timeout() | ||
|
|
||
| assert(not n.timer, "expected timer to still be nil after reset_timeout()") | ||
| assert(n_timeout_zero.timer == nil, | ||
| "regression: reset_timeout() after timeout=0 should not recreate timer") | ||
|
|
||
| -- Clean up. | ||
| n:destroy() | ||
| return true | ||
| end) | ||
|
|
||
| -- Default timeout never starts when no explicit timeout given. | ||
| table.insert(steps, function() | ||
| n_default = notification { | ||
| title = "default timeout test", | ||
| message = "Should expire with default timeout", | ||
| -- No timeout specified - should get default from cst.config | ||
| } | ||
|
|
||
| assert(n_default, "notification was not created") | ||
|
|
||
| -- The default timeout from cst.config.defaults is 5 seconds. | ||
| -- set_timeout() should have been called with that value. | ||
| assert(n_default.timer ~= nil, | ||
| "regression: notification without explicit timeout should get a timer") | ||
|
|
||
| assert(n_default.timer.started, | ||
| "timer exists but is not started") | ||
|
|
||
| assert(n_default.timeout == 5, | ||
| string.format("expected default timeout=5, got %d", n_default.timeout)) | ||
|
|
||
| return true | ||
| end) | ||
|
|
||
| -- Cleanup | ||
| table.insert(steps, function() | ||
| n_timeout_zero:destroy() | ||
| n_default:destroy() | ||
| return true | ||
| end) | ||
|
|
||
| require("_runner").run_steps(steps) | ||
| runner.run_steps(steps) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm yeah ok. I guess that's an alternative way to prevent the 5s wait from #3626 (comment) but makes the test aware of the internals.
That's not the best, but I guess I'm ok with it 🤷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me think about this one and see if I can find an alternative approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Aire-One
What do you think about a more "black-box" approach? No .timer or ._private checks at all.
For timeout=0: create with timeout=1, set to 0, wait ~1.5s, confirm the notification survives via the destroyed signal. Same pattern for reset_timeout().
For default timeout: call ruled.notification._clear() first so implicit_timeout doesn't mask the bug, then create without explicit timeout and wait for it to actually expire. (I found the previous version passed on master because ruled.notification was setting the timeout via implicit_timeout anyway.)
Tradeoff is a few extra seconds of runtime for real timer waits, and wait_per_step bumped to 8.