Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Unified Diff: mojo/edk/system/awakable_list_unittest.cc

Issue 2085583006: Add more tests for AwakableList (esp. persistent vs one-shot awakables). (Closed) Base URL: https://github.com/domokit/mojo.git@work794_wait_set_4.6
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/edk/system/awakable_list.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/edk/system/awakable_list_unittest.cc
diff --git a/mojo/edk/system/awakable_list_unittest.cc b/mojo/edk/system/awakable_list_unittest.cc
index 497478c7cfda20862728756d3947d1ecfdb42f7e..483d86edb8dc0bb55c33d7d0ca48acb190fd5205 100644
--- a/mojo/edk/system/awakable_list_unittest.cc
+++ b/mojo/edk/system/awakable_list_unittest.cc
@@ -22,7 +22,7 @@ namespace mojo {
namespace system {
namespace {
-TEST(AwakableListTest, BasicCancel) {
+TEST(AwakableListTest, BasicCancelAndRemoveAll) {
MojoResult result;
uint64_t context;
@@ -329,7 +329,7 @@ TEST(AwakableListTest, MultipleAwakables) {
EXPECT_EQ(10u, context4);
}
-TEST(AwakableListTest, RemoveMatchContext) {
+TEST(AwakableListTest, RemoveMatchContext1) {
MojoResult result;
uint64_t context;
@@ -379,65 +379,342 @@ class TestAwakable : public Awakable {
public:
TestAwakable() {}
- void Awake(uint64_t /*context*/,
- AwakeReason /*reason*/,
- const HandleSignalsState& /*signals_state*/) override {
+ void Awake(uint64_t context,
+ AwakeReason reason,
+ const HandleSignalsState& signals_state) override {
awake_count++;
+ last_context = context;
+ last_reason = reason;
+ last_state = signals_state;
}
unsigned awake_count = 0;
+ uint64_t last_context = static_cast<uint64_t>(-1);
+ AwakeReason last_reason = AwakeReason::CANCELLED;
+ HandleSignalsState last_state;
MOJO_DISALLOW_COPY_AND_ASSIGN(TestAwakable);
};
-TEST(AwakableListTest, PersistentVsNonPersistent) {
+TEST(AwakableListTest, PersistentVsOneShot1) {
+ AwakableList awakable_list;
TestAwakable persistent0;
TestAwakable persistent1;
TestAwakable oneshot0;
TestAwakable oneshot1;
- TestAwakable oneshot2;
- AwakableList remove_all;
- remove_all.Add(&oneshot0, 0, false, MOJO_HANDLE_SIGNAL_WRITABLE);
- remove_all.Add(&oneshot1, 0, false, MOJO_HANDLE_SIGNAL_WRITABLE);
+ awakable_list.Add(&persistent0, 100, true, MOJO_HANDLE_SIGNAL_WRITABLE);
+ awakable_list.Add(&persistent1, 101, true, MOJO_HANDLE_SIGNAL_WRITABLE);
+ awakable_list.Add(&oneshot0, 200, false, MOJO_HANDLE_SIGNAL_WRITABLE);
+ awakable_list.Add(&oneshot1, 201, false, MOJO_HANDLE_SIGNAL_WRITABLE);
+ EXPECT_EQ(persistent0.awake_count, 0u);
+ EXPECT_EQ(persistent1.awake_count, 0u);
+ EXPECT_EQ(oneshot0.awake_count, 0u);
+ EXPECT_EQ(oneshot1.awake_count, 0u);
- remove_all.OnStateChange(
+ awakable_list.OnStateChange(
HandleSignalsState(MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE),
HandleSignalsState(MOJO_HANDLE_SIGNAL_WRITABLE,
MOJO_HANDLE_SIGNAL_WRITABLE));
+ EXPECT_EQ(persistent0.awake_count, 1u);
+ EXPECT_EQ(persistent0.last_context, 100u);
+ EXPECT_EQ(persistent0.last_reason, Awakable::AwakeReason::CHANGED);
+ EXPECT_TRUE(persistent0.last_state.equals(HandleSignalsState(
+ MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_HANDLE_SIGNAL_WRITABLE)));
+ EXPECT_EQ(persistent1.awake_count, 1u);
+ EXPECT_EQ(persistent1.last_context, 101u);
+ EXPECT_EQ(persistent1.last_reason, Awakable::AwakeReason::CHANGED);
+ EXPECT_TRUE(persistent1.last_state.equals(HandleSignalsState(
+ MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_HANDLE_SIGNAL_WRITABLE)));
+ EXPECT_EQ(oneshot0.awake_count, 1u);
+ EXPECT_EQ(oneshot0.last_context, 200u);
+ EXPECT_EQ(oneshot0.last_reason, Awakable::AwakeReason::SATISFIED);
+ EXPECT_TRUE(oneshot0.last_state.equals(HandleSignalsState(
+ MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_HANDLE_SIGNAL_WRITABLE)));
+ EXPECT_EQ(oneshot1.awake_count, 1u);
+ EXPECT_EQ(oneshot1.last_context, 201u);
+ EXPECT_EQ(oneshot1.last_reason, Awakable::AwakeReason::SATISFIED);
+ EXPECT_TRUE(oneshot1.last_state.equals(HandleSignalsState(
+ MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_HANDLE_SIGNAL_WRITABLE)));
+
+ awakable_list.OnStateChange(
+ HandleSignalsState(MOJO_HANDLE_SIGNAL_WRITABLE,
+ MOJO_HANDLE_SIGNAL_WRITABLE),
+ HandleSignalsState(MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE));
+ EXPECT_EQ(persistent0.awake_count, 2u);
+ EXPECT_EQ(persistent0.last_context, 100u);
+ EXPECT_EQ(persistent0.last_reason, Awakable::AwakeReason::CHANGED);
+ EXPECT_TRUE(persistent0.last_state.equals(HandleSignalsState(
+ MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE)));
+ EXPECT_EQ(persistent1.awake_count, 2u);
+ EXPECT_EQ(persistent1.last_context, 101u);
+ EXPECT_EQ(persistent1.last_reason, Awakable::AwakeReason::CHANGED);
+ EXPECT_TRUE(persistent1.last_state.equals(HandleSignalsState(
+ MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE)));
EXPECT_EQ(oneshot0.awake_count, 1u);
EXPECT_EQ(oneshot1.awake_count, 1u);
- remove_all.OnStateChange(
+ awakable_list.OnStateChange(
HandleSignalsState(MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE),
HandleSignalsState(MOJO_HANDLE_SIGNAL_WRITABLE,
MOJO_HANDLE_SIGNAL_WRITABLE));
+ EXPECT_EQ(persistent0.awake_count, 3u);
+ EXPECT_EQ(persistent0.last_context, 100u);
+ EXPECT_EQ(persistent0.last_reason, Awakable::AwakeReason::CHANGED);
+ EXPECT_TRUE(persistent0.last_state.equals(HandleSignalsState(
+ MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_HANDLE_SIGNAL_WRITABLE)));
+ EXPECT_EQ(persistent1.awake_count, 3u);
+ EXPECT_EQ(persistent1.last_context, 101u);
+ EXPECT_EQ(persistent1.last_reason, Awakable::AwakeReason::CHANGED);
+ EXPECT_TRUE(persistent1.last_state.equals(HandleSignalsState(
+ MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_HANDLE_SIGNAL_WRITABLE)));
EXPECT_EQ(oneshot0.awake_count, 1u);
EXPECT_EQ(oneshot1.awake_count, 1u);
- AwakableList remove_first;
- remove_first.Add(&oneshot2, 0, false, MOJO_HANDLE_SIGNAL_WRITABLE);
- remove_first.Add(&persistent0, 0, true, MOJO_HANDLE_SIGNAL_WRITABLE);
- remove_first.Add(&persistent1, 0, true, MOJO_HANDLE_SIGNAL_WRITABLE);
+ awakable_list.Remove(false, &persistent0, 0);
+ awakable_list.Remove(false, &persistent1, 0);
+ EXPECT_EQ(persistent0.awake_count, 3u);
+ EXPECT_EQ(persistent1.awake_count, 3u);
+ EXPECT_EQ(oneshot0.awake_count, 1u);
+ EXPECT_EQ(oneshot1.awake_count, 1u);
- remove_first.OnStateChange(
- HandleSignalsState(MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE),
+ awakable_list.OnStateChange(
HandleSignalsState(MOJO_HANDLE_SIGNAL_WRITABLE,
- MOJO_HANDLE_SIGNAL_WRITABLE));
- EXPECT_EQ(persistent0.awake_count, 1u);
+ MOJO_HANDLE_SIGNAL_WRITABLE),
+ HandleSignalsState(MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE));
+ EXPECT_EQ(persistent0.awake_count, 3u);
+ EXPECT_EQ(persistent1.awake_count, 3u);
+ EXPECT_EQ(oneshot0.awake_count, 1u);
+ EXPECT_EQ(oneshot1.awake_count, 1u);
+}
+
+// Checks carefully that persistent awakables see all changes whereas one-shot
+// awakables see only "leading edges".
+TEST(AwakableListTest, PersistentVsOneShot2) {
+ static constexpr MojoHandleSignals kNone = MOJO_HANDLE_SIGNAL_NONE;
+ static constexpr MojoHandleSignals kR = MOJO_HANDLE_SIGNAL_READABLE;
+ static constexpr MojoHandleSignals kW = MOJO_HANDLE_SIGNAL_WRITABLE;
+ static constexpr MojoHandleSignals kPC = MOJO_HANDLE_SIGNAL_PEER_CLOSED;
+
+ AwakableList awakable_list;
+ TestAwakable persistent;
+ TestAwakable oneshot;
+
+ // Starting state: Satisfied: None. Satisfiable: R | W | PC.
+ HandleSignalsState old_state(kNone, kR | kW | kPC);
+ HandleSignalsState new_state = old_state;
+
+ // Watch R and PC; we'll do the same for |oneshot|, but add/remove each time.
+ awakable_list.Add(&persistent, 123, true, kR | kPC);
+ EXPECT_EQ(persistent.awake_count, 0u);
+
+ // Satisfied: +R.
+ awakable_list.Add(&oneshot, 456, false, kR | kPC);
+ new_state.satisfied_signals |= kR;
+ awakable_list.OnStateChange(old_state, new_state);
+ old_state = new_state;
+ EXPECT_EQ(persistent.awake_count, 1u);
+ EXPECT_EQ(oneshot.awake_count, 1u);
+ EXPECT_EQ(oneshot.last_reason, Awakable::AwakeReason::SATISFIED);
+ awakable_list.Remove(true, &oneshot, 456);
+
+ // Satisfied: -R.
+ oneshot.awake_count = 0;
+ awakable_list.Add(&oneshot, 456, false, kR | kPC);
+ new_state.satisfied_signals &= ~kR;
+ awakable_list.OnStateChange(old_state, new_state);
+ old_state = new_state;
+ EXPECT_EQ(persistent.awake_count, 2u);
+ EXPECT_EQ(oneshot.awake_count, 0u);
+ awakable_list.Remove(true, &oneshot, 456);
+
+ // Satisfied: +W.
+ oneshot.awake_count = 0;
+ awakable_list.Add(&oneshot, 456, false, kR | kPC);
+ new_state.satisfied_signals |= kW;
+ awakable_list.OnStateChange(old_state, new_state);
+ old_state = new_state;
+ EXPECT_EQ(persistent.awake_count, 2u);
+ EXPECT_EQ(oneshot.awake_count, 0u);
+ awakable_list.Remove(true, &oneshot, 456);
+
+ // Satisfied: +PC -W.
+ oneshot.awake_count = 0;
+ awakable_list.Add(&oneshot, 456, false, kR | kPC);
+ new_state.satisfied_signals |= kPC;
+ new_state.satisfied_signals &= ~kW;
+ awakable_list.OnStateChange(old_state, new_state);
+ old_state = new_state;
+ EXPECT_EQ(persistent.awake_count, 3u);
+ EXPECT_EQ(oneshot.awake_count, 1u);
+ EXPECT_EQ(oneshot.last_reason, Awakable::AwakeReason::SATISFIED);
+ awakable_list.Remove(true, &oneshot, 456);
+
+ // Satisfied: +R -PC.
+ oneshot.awake_count = 0;
+ awakable_list.Add(&oneshot, 456, false, kR | kPC);
+ new_state.satisfied_signals |= kR;
+ new_state.satisfied_signals &= ~kPC;
+ awakable_list.OnStateChange(old_state, new_state);
+ old_state = new_state;
+ EXPECT_EQ(persistent.awake_count, 4u);
+ // It was previously satisfied and remains satisfied (for different reasons),
+ // so the one-shot does not observe this change.
+ EXPECT_EQ(oneshot.awake_count, 0u);
+ awakable_list.Remove(true, &oneshot, 456);
+
+ // Satisfiable: -PC.
+ oneshot.awake_count = 0;
+ awakable_list.Add(&oneshot, 456, false, kR | kPC);
+ new_state.satisfiable_signals &= ~kPC;
+ awakable_list.OnStateChange(old_state, new_state);
+ old_state = new_state;
+ EXPECT_EQ(persistent.awake_count, 5u);
+ EXPECT_EQ(oneshot.awake_count, 0u);
+ awakable_list.Remove(true, &oneshot, 456);
+
+ // Satisfiable: -W.
+ oneshot.awake_count = 0;
+ awakable_list.Add(&oneshot, 456, false, kR | kPC);
+ new_state.satisfiable_signals &= ~kW;
+ awakable_list.OnStateChange(old_state, new_state);
+ old_state = new_state;
+ EXPECT_EQ(persistent.awake_count, 5u);
+ EXPECT_EQ(oneshot.awake_count, 0u);
+ awakable_list.Remove(true, &oneshot, 456);
+
+ // Satisfied: -R. Satisfiable: -R.
+ oneshot.awake_count = 0;
+ awakable_list.Add(&oneshot, 456, false, kR | kPC);
+ new_state.satisfied_signals &= ~kR;
+ new_state.satisfiable_signals &= ~kR;
+ awakable_list.OnStateChange(old_state, new_state);
+ old_state = new_state;
+ EXPECT_EQ(persistent.awake_count, 6u);
+ // "Leading edge" for one-shot is "rising" for (overall) satisfied-ness and
+ // "falling" for (overall) satisfiability, so it's really picking up the -R in
+ // satisfiability here.
+ EXPECT_EQ(oneshot.awake_count, 1u);
+ EXPECT_EQ(oneshot.last_reason, Awakable::AwakeReason::UNSATISFIABLE);
+ awakable_list.Remove(true, &oneshot, 456);
+
+ // Satisfiable: +R:
+ oneshot.awake_count = 0;
+ awakable_list.Add(&oneshot, 456, false, kR | kPC);
+ new_state.satisfiable_signals |= kR;
+ awakable_list.OnStateChange(old_state, new_state);
+ old_state = new_state;
+ EXPECT_EQ(persistent.awake_count, 7u);
+ // And the one-shot doesn't pick up the +R in satisfiability here.
+ EXPECT_EQ(oneshot.awake_count, 0u);
+ awakable_list.Remove(true, &oneshot, 456);
+
+ awakable_list.Remove(true, &persistent, 123);
+ EXPECT_EQ(persistent.awake_count, 7u);
+}
+
+TEST(AwakableListTest, RemoveNoMatchContext) {
+ static constexpr MojoHandleSignals kNone = MOJO_HANDLE_SIGNAL_NONE;
+ static constexpr MojoHandleSignals kR = MOJO_HANDLE_SIGNAL_READABLE;
+
+ AwakableList awakable_list;
+ TestAwakable persistent0;
+ TestAwakable persistent1;
+
+ // Add |persistent0| twice, with different contexts.
+ awakable_list.Add(&persistent0, 12, true, kR);
+ awakable_list.Add(&persistent0, 34, true, kR);
+ awakable_list.Add(&persistent1, 56, true, kR);
+ EXPECT_EQ(persistent0.awake_count, 0u);
+ EXPECT_EQ(persistent1.awake_count, 0u);
+
+ awakable_list.OnStateChange(HandleSignalsState(kNone, kR),
+ HandleSignalsState(kR, kR));
+ EXPECT_EQ(persistent0.awake_count, 2u);
EXPECT_EQ(persistent1.awake_count, 1u);
- EXPECT_EQ(oneshot2.awake_count, 1u);
- remove_first.OnStateChange(
- HandleSignalsState(MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE),
- HandleSignalsState(MOJO_HANDLE_SIGNAL_WRITABLE,
- MOJO_HANDLE_SIGNAL_WRITABLE));
+ awakable_list.OnStateChange(HandleSignalsState(kNone, kR),
+ HandleSignalsState(kNone, kR));
+ EXPECT_EQ(persistent0.awake_count, 2u);
+ EXPECT_EQ(persistent1.awake_count, 1u);
+
+ awakable_list.Remove(false, &persistent0, 0);
EXPECT_EQ(persistent0.awake_count, 2u);
+ EXPECT_EQ(persistent1.awake_count, 1u);
+
+ awakable_list.OnStateChange(HandleSignalsState(kNone, kR),
+ HandleSignalsState(kR, kR));
+ EXPECT_EQ(persistent0.awake_count, 2u);
+ EXPECT_EQ(persistent1.awake_count, 2u);
+
+ awakable_list.Remove(false, &persistent1, 0);
+ EXPECT_EQ(persistent0.awake_count, 2u);
+ EXPECT_EQ(persistent1.awake_count, 2u);
+}
+
+TEST(AwakableListTest, RemoveMatchContext2) {
+ static constexpr MojoHandleSignals kNone = MOJO_HANDLE_SIGNAL_NONE;
+ static constexpr MojoHandleSignals kR = MOJO_HANDLE_SIGNAL_READABLE;
+
+ AwakableList awakable_list;
+ TestAwakable persistent0;
+ TestAwakable persistent1;
+
+ // Add |persistent0| twice, with different contexts.
+ awakable_list.Add(&persistent0, 12, true, kR);
+ awakable_list.Add(&persistent0, 34, true, kR);
+ awakable_list.Add(&persistent1, 56, true, kR);
+ EXPECT_EQ(persistent0.awake_count, 0u);
+ EXPECT_EQ(persistent1.awake_count, 0u);
+
+ awakable_list.OnStateChange(HandleSignalsState(kNone, kR),
+ HandleSignalsState(kR, kR));
+ EXPECT_EQ(persistent0.awake_count, 2u);
+ EXPECT_EQ(persistent1.awake_count, 1u);
+
+ awakable_list.OnStateChange(HandleSignalsState(kNone, kR),
+ HandleSignalsState(kNone, kR));
+ EXPECT_EQ(persistent0.awake_count, 2u);
+ EXPECT_EQ(persistent1.awake_count, 1u);
+
+ awakable_list.Remove(true, &persistent0, 34);
+ EXPECT_EQ(persistent0.awake_count, 2u);
+ EXPECT_EQ(persistent1.awake_count, 1u);
+
+ awakable_list.OnStateChange(HandleSignalsState(kNone, kR),
+ HandleSignalsState(kR, kR));
+ EXPECT_EQ(persistent0.awake_count, 3u);
+ EXPECT_EQ(persistent0.last_context, 12u);
EXPECT_EQ(persistent1.awake_count, 2u);
- EXPECT_EQ(oneshot2.awake_count, 1u);
- remove_first.Remove(false, &persistent0, 0);
- remove_first.Remove(false, &persistent1, 0);
+ // No-op: non-existent context.
+ awakable_list.Remove(true, &persistent1, 0);
+ EXPECT_EQ(persistent0.awake_count, 3u);
+ EXPECT_EQ(persistent1.awake_count, 2u);
+
+ awakable_list.OnStateChange(HandleSignalsState(kNone, kR),
+ HandleSignalsState(kNone, kR));
+ EXPECT_EQ(persistent0.awake_count, 3u);
+ EXPECT_EQ(persistent1.awake_count, 2u);
+
+ awakable_list.OnStateChange(HandleSignalsState(kNone, kR),
+ HandleSignalsState(kR, kR));
+ EXPECT_EQ(persistent0.awake_count, 4u);
+ EXPECT_EQ(persistent0.last_context, 12u);
+ EXPECT_EQ(persistent1.awake_count, 3u);
+
+ awakable_list.Remove(true, &persistent0, 12);
+ awakable_list.Remove(true, &persistent1, 56);
+
+ awakable_list.OnStateChange(HandleSignalsState(kNone, kR),
+ HandleSignalsState(kNone, kR));
+ EXPECT_EQ(persistent0.awake_count, 4u);
+ EXPECT_EQ(persistent1.awake_count, 3u);
+
+ awakable_list.OnStateChange(HandleSignalsState(kNone, kR),
+ HandleSignalsState(kR, kR));
+ EXPECT_EQ(persistent0.awake_count, 4u);
+ EXPECT_EQ(persistent1.awake_count, 3u);
}
} // namespace
« no previous file with comments | « mojo/edk/system/awakable_list.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698