This is an archive of the discontinued LLVM Phabricator instance.

[lldb/test] Add events listener helper function to lldbtest
ClosedPublic

Authored by mib on Mar 21 2022, 4:56 PM.

Details

Summary

This patch introduces 2 new lldb utility functions:

  • lldbutil.start_listening_from: This can be called in the test setup to create a listener and set it up for a specific event mask and add it to the user-provided broadcaster's list.
  • lldbutil.fetch_next_event: This will use fetch a single event from the provided istener and return it if it matches the provided broadcaster.

The motivation behind this is to easily test new kinds of events
(i.e. Swift type-system progress events). However, this patch also
updates TestProgressReporting.py and TestDiagnosticReporting.py
to make use of these new helper functions.

Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>

Diff Detail

Event Timeline

mib created this revision.Mar 21 2022, 4:56 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 21 2022, 4:56 PM
mib requested review of this revision.Mar 21 2022, 4:56 PM

I like this implementation a lot. The less threads we use, the better. I have a couple of remarks/questions though:

  • given how simple the new approach is, is a dedicated test class really needed? It seems like it should be sufficient to add two utility functions to: create a listener; and fetch an event from it. This would be more flexible, and could be placed next to lldbutil.expect_state_changes which is our existing helper function for dealing with state-changed events
  • instead of taking a callback, I think it would be simpler if the event retrieval function just returned the event, and let the caller do what ever it deems fit
  • listener.GetNextEvent will now wait indefinitely if the event is not sent (due to a bug). In this setup I'd replace it with WaitForEvent(timeout), where timeout can be zero if we can guarantee that the event has been sent by the time we call the event retrieval function (this would be ideal as failures would be instantaneous), or a reasonably large value (but less than infinity) if we can't. I think the first option should be possible since that's essentially what eBroadcastBitStopDiagnosticThread was doing.

This reverts commit 8bf893466632cc2597188b431160effcd8cedeef

If you hadn't said that I don't think anyone would notice, as the implementation is completely different. :)

mib added a comment.EditedMar 22 2022, 9:40 AM

Hey @labath, thanks for the feedback! Here are some other questions ?

I like this implementation a lot. The less threads we use, the better. I have a couple of remarks/questions though:

  • given how simple the new approach is, is a dedicated test class really needed? It seems like it should be sufficient to add two utility functions to: create a listener; and fetch an event from it. This would be more flexible, and could be placed next to lldbutil.expect_state_changes which is our existing helper function for dealing with state-changed events

I think we could replace the class by a function. Also, at the moment, I'm not sure the tested events (progress/diagnostic) are really related to state change (regarding where this should go).

  • instead of taking a callback, I think it would be simpler if the event retrieval function just returned the event, and let the caller do what ever it deems fit

Should we remove the assertEvent method and let the users handle the check themselves by returning the event ?

  • listener.GetNextEvent will now wait indefinitely if the event is not sent (due to a bug). In this setup I'd replace it with WaitForEvent(timeout), where timeout can be zero if we can guarantee that the event has been sent by the time we call the event retrieval function (this would be ideal as failures would be instantaneous), or a reasonably large value (but less than infinity) if we can't. I think the first option should be possible since that's essentially what eBroadcastBitStopDiagnosticThread was doing.

I expected to use the test suite timeout to stop the infinite loop, but with this suggestion and the previous one, what should the function return after timing out ?

This reverts commit 8bf893466632cc2597188b431160effcd8cedeef

If you hadn't said that I don't think anyone would notice, as the implementation is completely different. :)

Right :p but I wanted to keep the history

Hey @labath, thanks for the feedback! Here are some other questions ?

I like this implementation a lot. The less threads we use, the better. I have a couple of remarks/questions though:

  • given how simple the new approach is, is a dedicated test class really needed? It seems like it should be sufficient to add two utility functions to: create a listener; and fetch an event from it. This would be more flexible, and could be placed next to lldbutil.expect_state_changes which is our existing helper function for dealing with state-changed events

I think we could replace the class by a function. Also, at the moment, I'm not sure the tested events (progress/diagnostic) are really related to state change (regarding where this should go).

They're not related to state change, but they are related to events. My point was simply that it'd be nice to have event-handling code grouped together.

  • instead of taking a callback, I think it would be simpler if the event retrieval function just returned the event, and let the caller do what ever it deems fit

Should we remove the assertEvent method and let the users handle the check themselves by returning the event ?

Yes, that's the general idea.

  • listener.GetNextEvent will now wait indefinitely if the event is not sent (due to a bug). In this setup I'd replace it with WaitForEvent(timeout), where timeout can be zero if we can guarantee that the event has been sent by the time we call the event retrieval function (this would be ideal as failures would be instantaneous), or a reasonably large value (but less than infinity) if we can't. I think the first option should be possible since that's essentially what eBroadcastBitStopDiagnosticThread was doing.

I expected to use the test suite timeout to stop the infinite loop, but with this suggestion and the previous one, what should the function return after timing out ?

The test suite timeout is rather large and relies on the an optional python module. I think it would be better to have a separate timeout here, which would also give a better error message

The function can just fail if the event retrieval times out. Most of the lldbutil methods achieve that by taking an test object so they can call some unittest methods on (fail(msg) would probably be appropriate here).

mib updated this revision to Diff 417474.Mar 22 2022, 8:03 PM
mib retitled this revision from Reland "[lldb/test] Add events listener helper class to lldbtest" to [lldb/test] Add events listener helper function to lldbtest.
mib edited the summary of this revision. (Show Details)

Address @labath comments:

  • Split the class into 2 functions
  • Let the user handle the event
labath accepted this revision.Mar 23 2022, 11:47 AM
labath added inline comments.
lldb/packages/Python/lldbsuite/test/lldbutil.py
1265 ↗(On Diff #417474)

1 is definitely not a good default. If you can't/don't want to use zero, then I'd recommend at least 10 seconds.

1273 ↗(On Diff #417474)
else:
  test.fail("got event '%s' from unexpected broadcaster '%s'%(event.GetDescription(), event.GetBroadcaster().GetName())

(or something along those line)

This revision is now accepted and ready to land.Mar 23 2022, 11:47 AM
This revision was automatically updated to reflect the committed changes.
mib marked 2 inline comments as done.