1 // Copyright 2011 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef IPC_IPC_TEST_SINK_H_ 6 #define IPC_IPC_TEST_SINK_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <utility> 12 #include <vector> 13 14 #include "base/observer_list.h" 15 #include "build/build_config.h" 16 #include "ipc/ipc_channel.h" 17 18 namespace IPC { 19 20 class Message; 21 22 // This test sink provides a "sink" for IPC messages that are sent. It allows 23 // the caller to query messages received in various different ways. It is 24 // designed for tests for objects that use the IPC system. 25 // 26 // Typical usage: 27 // 28 // test_sink.ClearMessages(); 29 // do_something(); 30 // 31 // // We should have gotten exactly one update state message. 32 // EXPECT_TRUE(test_sink.GetUniqeMessageMatching(ViewHostMsg_Update::ID)); 33 // // ...and no start load messages. 34 // EXPECT_FALSE(test_sink.GetFirstMessageMatching(ViewHostMsg_Start::ID)); 35 // 36 // // Now inspect a message. This assumes a message that was declared like 37 // // this: IPC_MESSAGE_ROUTED2(ViewMsg_Foo, bool, int) 38 // IPC::Message* msg = test_sink.GetFirstMessageMatching(ViewMsg_Foo::ID)); 39 // ASSERT_TRUE(msg); 40 // bool first_param; 41 // int second_param; 42 // ViewMsg_Foo::Read(msg, &first_param, &second_param); 43 // 44 // // Go on to the next phase of the test. 45 // test_sink.ClearMessages(); 46 // 47 // To read a sync reply, do this: 48 // 49 // IPC::Message* msg = test_sink.GetUniqueMessageMatching(IPC_REPLY_ID); 50 // ASSERT_TRUE(msg); 51 // base::TupleTypes<ViewHostMsg_Foo::ReplyParam>::ValueTuple reply_data; 52 // EXPECT_TRUE(ViewHostMsg_Foo::ReadReplyParam(msg, &reply_data)); 53 // 54 // You can also register to be notified when messages are posted to the sink. 55 // This can be useful if you need to wait for a particular message that will 56 // be posted asynchronously. Example usage: 57 // 58 // class MyListener : public IPC::Listener { 59 // public: 60 // MyListener(const base::RepeatingClosure& closure) 61 // : message_received_closure_(closure) {} 62 // virtual bool OnMessageReceived(const IPC::Message& msg) { 63 // <do something with the message> 64 // message_received_closure_.Run(); 65 // return false; // to store the message in the sink, or true to drop it 66 // } 67 // private: 68 // base::RepeatingClosure message_received_closure_; 69 // }; 70 // 71 // base::RunLoop run_loop; 72 // MyListener listener(run_loop.QuitClosure()); 73 // test_sink.AddFilter(&listener); 74 // StartSomeAsynchronousProcess(&test_sink); 75 // run_loop.Run(); 76 // <inspect the results> 77 // ... 78 // 79 // To hook up the sink, all you need to do is call OnMessageReceived when a 80 // message is received. 81 class TestSink : public Channel { 82 public: 83 TestSink(); 84 85 TestSink(const TestSink&) = delete; 86 TestSink& operator=(const TestSink&) = delete; 87 88 ~TestSink() override; 89 90 // Interface in IPC::Channel. This copies the message to the sink and then 91 // deletes it. 92 bool Send(IPC::Message* message) override; 93 [[nodiscard]] bool Connect() override; 94 void Close() override; 95 96 // Used by the source of the messages to send the message to the sink. This 97 // will make a copy of the message and store it in the list. 98 bool OnMessageReceived(const Message& msg); 99 100 // Returns the number of messages in the queue. message_count()101 size_t message_count() const { return messages_.size(); } 102 103 // Clears the message queue of saved messages. 104 void ClearMessages(); 105 106 // Returns the message at the given index in the queue. The index may be out 107 // of range, in which case the return value is NULL. The returned pointer will 108 // only be valid until another message is received or the list is cleared. 109 const Message* GetMessageAt(size_t index) const; 110 111 // Returns the first message with the given ID in the queue. If there is no 112 // message with the given ID, returns NULL. The returned pointer will only be 113 // valid until another message is received or the list is cleared. 114 const Message* GetFirstMessageMatching(uint32_t id) const; 115 116 // Returns the message with the given ID in the queue. If there is no such 117 // message or there is more than one of that message, this will return NULL 118 // (with the expectation that you'll do an ASSERT_TRUE() on the result). 119 // The returned pointer will only be valid until another message is received 120 // or the list is cleared. 121 const Message* GetUniqueMessageMatching(uint32_t id) const; 122 123 // Adds the given listener as a filter to the TestSink. 124 // When a message is received by the TestSink, it will be dispatched to 125 // the filters, in the order they were added. If a filter returns true 126 // from OnMessageReceived, subsequent filters will not receive the message 127 // and the TestSink will not store it. 128 void AddFilter(Listener* filter); 129 130 // Removes the given filter from the TestSink. 131 void RemoveFilter(Listener* filter); 132 133 private: 134 // The actual list of received messages. 135 std::vector<Message> messages_; 136 base::ObserverList<Listener>::Unchecked filter_list_; 137 }; 138 139 } // namespace IPC 140 141 #endif // IPC_IPC_TEST_SINK_H_ 142