#include "TestInterruptRaces.h" #include "IPDLUnitTests.h" // fail etc. using mozilla::ipc::MessageChannel; template<> struct RunnableMethodTraits { static void RetainCallee(mozilla::_ipdltest::TestInterruptRacesParent* obj) { } static void ReleaseCallee(mozilla::_ipdltest::TestInterruptRacesParent* obj) { } }; namespace mozilla { namespace _ipdltest { ipc::RacyInterruptPolicy MediateRace(const MessageChannel::Message& parent, const MessageChannel::Message& child) { return (PTestInterruptRaces::Msg_Child__ID == parent.type()) ? ipc::RIPParentWins : ipc::RIPChildWins; } //----------------------------------------------------------------------------- // parent void TestInterruptRacesParent::Main() { if (!SendStart()) fail("sending Start()"); } bool TestInterruptRacesParent::RecvStartRace() { MessageLoop::current()->PostTask( FROM_HERE, NewRunnableMethod(this, &TestInterruptRacesParent::OnRaceTime)); return true; } void TestInterruptRacesParent::OnRaceTime() { if (!CallRace(&mChildHasReply)) fail("problem calling Race()"); if (!mChildHasReply) fail("child should have got a reply already"); mHasReply = true; MessageLoop::current()->PostTask( FROM_HERE, NewRunnableMethod(this, &TestInterruptRacesParent::Test2)); } bool TestInterruptRacesParent::AnswerRace(bool* hasReply) { if (mHasReply) fail("apparently the parent won the Interrupt race!"); *hasReply = hasReply; return true; } void TestInterruptRacesParent::Test2() { puts(" passed"); puts("Test 2"); mHasReply = false; mChildHasReply = false; if (!CallStackFrame()) fail("can't set up a stack frame"); puts(" passed"); MessageLoop::current()->PostTask( FROM_HERE, NewRunnableMethod(this, &TestInterruptRacesParent::Test3)); } bool TestInterruptRacesParent::AnswerStackFrame() { if (!SendWakeup()) fail("can't wake up the child"); if (!CallRace(&mChildHasReply)) fail("can't set up race condition"); mHasReply = true; if (!mChildHasReply) fail("child should have got a reply already"); return true; } void TestInterruptRacesParent::Test3() { puts("Test 3"); if (!CallStackFrame3()) fail("can't set up a stack frame"); puts(" passed"); Close(); } bool TestInterruptRacesParent::AnswerStackFrame3() { if (!SendWakeup3()) fail("can't wake up the child"); if (!CallChild()) fail("can't set up race condition"); return true; } bool TestInterruptRacesParent::AnswerParent() { mAnsweredParent = true; return true; } bool TestInterruptRacesParent::RecvGetAnsweredParent(bool* answeredParent) { *answeredParent = mAnsweredParent; return true; } //----------------------------------------------------------------------------- // child bool TestInterruptRacesChild::RecvStart() { puts("Test 1"); if (!SendStartRace()) fail("problem sending StartRace()"); bool dontcare; if (!CallRace(&dontcare)) fail("problem calling Race()"); mHasReply = true; return true; } bool TestInterruptRacesChild::AnswerRace(bool* hasReply) { if (!mHasReply) fail("apparently the child lost the Interrupt race!"); *hasReply = mHasReply; return true; } bool TestInterruptRacesChild::AnswerStackFrame() { // reset for the second test mHasReply = false; if (!CallStackFrame()) fail("can't set up stack frame"); if (!mHasReply) fail("should have had reply by now"); return true; } bool TestInterruptRacesChild::RecvWakeup() { bool dontcare; if (!CallRace(&dontcare)) fail("can't set up race condition"); mHasReply = true; return true; } bool TestInterruptRacesChild::AnswerStackFrame3() { if (!CallStackFrame3()) fail("can't set up stack frame"); return true; } bool TestInterruptRacesChild::RecvWakeup3() { if (!CallParent()) fail("can't set up race condition"); return true; } bool TestInterruptRacesChild::AnswerChild() { bool parentAnsweredParent; // the parent is supposed to win the race, which means its // message, Child(), is supposed to be processed before the // child's message, Parent() if (!SendGetAnsweredParent(&parentAnsweredParent)) fail("sending GetAnsweredParent"); if (parentAnsweredParent) fail("parent was supposed to win the race!"); return true; } } // namespace _ipdltest } // namespace mozilla