blob: 4746e962ae4a235b4261b3051b46136ddc0cf056 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#ifndef RTC_BASE_TEST_UTILS_H_
12#define RTC_BASE_TEST_UTILS_H_
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000013
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020014// Utilities for testing rtc infrastructure in unittests
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000015
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020016#include <map>
Yves Gerey3e707812018-11-28 16:47:49 +010017#include <utility>
18
Steve Anton10542f22019-01-11 09:11:00 -080019#include "rtc_base/async_socket.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "rtc_base/stream.h"
Yves Gerey3e707812018-11-28 16:47:49 +010021#include "rtc_base/third_party/sigslot/sigslot.h"
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020022
23namespace webrtc {
24namespace testing {
25
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020026///////////////////////////////////////////////////////////////////////////////
27// StreamSink - Monitor asynchronously signalled events from StreamInterface
28// or AsyncSocket (which should probably be a StreamInterface.
29///////////////////////////////////////////////////////////////////////////////
30
31// Note: Any event that is an error is treaded as SSE_ERROR instead of that
32// event.
33
34enum StreamSinkEvent {
Mirko Bonadeie10b1632018-12-11 18:43:40 +010035 SSE_OPEN = rtc::SE_OPEN,
36 SSE_READ = rtc::SE_READ,
37 SSE_WRITE = rtc::SE_WRITE,
38 SSE_CLOSE = rtc::SE_CLOSE,
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020039 SSE_ERROR = 16
40};
41
42class StreamSink : public sigslot::has_slots<> {
43 public:
Steve Anton9de3aac2017-10-24 10:08:26 -070044 StreamSink();
45 ~StreamSink() override;
46
Mirko Bonadeie10b1632018-12-11 18:43:40 +010047 void Monitor(rtc::StreamInterface* stream) {
Yves Gerey665174f2018-06-19 15:03:05 +020048 stream->SignalEvent.connect(this, &StreamSink::OnEvent);
49 events_.erase(stream);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020050 }
Mirko Bonadeie10b1632018-12-11 18:43:40 +010051 void Unmonitor(rtc::StreamInterface* stream) {
Yves Gerey665174f2018-06-19 15:03:05 +020052 stream->SignalEvent.disconnect(this);
53 // In case you forgot to unmonitor a previous object with this address
54 events_.erase(stream);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020055 }
Mirko Bonadeie10b1632018-12-11 18:43:40 +010056 bool Check(rtc::StreamInterface* stream,
Yves Gerey665174f2018-06-19 15:03:05 +020057 StreamSinkEvent event,
58 bool reset = true) {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020059 return DoCheck(stream, event, reset);
60 }
Mirko Bonadeie10b1632018-12-11 18:43:40 +010061 int Events(rtc::StreamInterface* stream, bool reset = true) {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020062 return DoEvents(stream, reset);
63 }
64
Mirko Bonadeie10b1632018-12-11 18:43:40 +010065 void Monitor(rtc::AsyncSocket* socket) {
Yves Gerey665174f2018-06-19 15:03:05 +020066 socket->SignalConnectEvent.connect(this, &StreamSink::OnConnectEvent);
67 socket->SignalReadEvent.connect(this, &StreamSink::OnReadEvent);
68 socket->SignalWriteEvent.connect(this, &StreamSink::OnWriteEvent);
69 socket->SignalCloseEvent.connect(this, &StreamSink::OnCloseEvent);
70 // In case you forgot to unmonitor a previous object with this address
71 events_.erase(socket);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020072 }
Mirko Bonadeie10b1632018-12-11 18:43:40 +010073 void Unmonitor(rtc::AsyncSocket* socket) {
Yves Gerey665174f2018-06-19 15:03:05 +020074 socket->SignalConnectEvent.disconnect(this);
75 socket->SignalReadEvent.disconnect(this);
76 socket->SignalWriteEvent.disconnect(this);
77 socket->SignalCloseEvent.disconnect(this);
78 events_.erase(socket);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020079 }
Mirko Bonadeie10b1632018-12-11 18:43:40 +010080 bool Check(rtc::AsyncSocket* socket,
81 StreamSinkEvent event,
82 bool reset = true) {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020083 return DoCheck(socket, event, reset);
84 }
Mirko Bonadeie10b1632018-12-11 18:43:40 +010085 int Events(rtc::AsyncSocket* socket, bool reset = true) {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020086 return DoEvents(socket, reset);
87 }
88
89 private:
Yves Gerey665174f2018-06-19 15:03:05 +020090 typedef std::map<void*, int> EventMap;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020091
Mirko Bonadeie10b1632018-12-11 18:43:40 +010092 void OnEvent(rtc::StreamInterface* stream, int events, int error) {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020093 if (error) {
94 events = SSE_ERROR;
95 }
96 AddEvents(stream, events);
97 }
Mirko Bonadeie10b1632018-12-11 18:43:40 +010098 void OnConnectEvent(rtc::AsyncSocket* socket) { AddEvents(socket, SSE_OPEN); }
99 void OnReadEvent(rtc::AsyncSocket* socket) { AddEvents(socket, SSE_READ); }
100 void OnWriteEvent(rtc::AsyncSocket* socket) { AddEvents(socket, SSE_WRITE); }
101 void OnCloseEvent(rtc::AsyncSocket* socket, int error) {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200102 AddEvents(socket, (0 == error) ? SSE_CLOSE : SSE_ERROR);
103 }
104
105 void AddEvents(void* obj, int events) {
106 EventMap::iterator it = events_.find(obj);
107 if (events_.end() == it) {
108 events_.insert(EventMap::value_type(obj, events));
109 } else {
110 it->second |= events;
111 }
112 }
113 bool DoCheck(void* obj, StreamSinkEvent event, bool reset) {
114 EventMap::iterator it = events_.find(obj);
115 if ((events_.end() == it) || (0 == (it->second & event))) {
116 return false;
117 }
118 if (reset) {
119 it->second &= ~event;
120 }
121 return true;
122 }
123 int DoEvents(void* obj, bool reset) {
124 EventMap::iterator it = events_.find(obj);
125 if (events_.end() == it)
126 return 0;
127 int events = it->second;
128 if (reset) {
129 it->second = 0;
130 }
131 return events;
132 }
133
134 EventMap events_;
135};
136
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200137} // namespace testing
138} // namespace webrtc
139
Steve Anton10542f22019-01-11 09:11:00 -0800140#endif // RTC_BASE_TEST_UTILS_H_