blob: 5a2a3bda4df636ab0b3cb220791b18188b5164bd [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef RTC_BASE_TESTUTILS_H_
12#define RTC_BASE_TESTUTILS_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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/asyncsocket.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
26using namespace rtc;
27
28///////////////////////////////////////////////////////////////////////////////
29// StreamSink - Monitor asynchronously signalled events from StreamInterface
30// or AsyncSocket (which should probably be a StreamInterface.
31///////////////////////////////////////////////////////////////////////////////
32
33// Note: Any event that is an error is treaded as SSE_ERROR instead of that
34// event.
35
36enum StreamSinkEvent {
Yves Gerey665174f2018-06-19 15:03:05 +020037 SSE_OPEN = SE_OPEN,
38 SSE_READ = SE_READ,
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020039 SSE_WRITE = SE_WRITE,
40 SSE_CLOSE = SE_CLOSE,
41 SSE_ERROR = 16
42};
43
44class StreamSink : public sigslot::has_slots<> {
45 public:
Steve Anton9de3aac2017-10-24 10:08:26 -070046 StreamSink();
47 ~StreamSink() override;
48
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020049 void Monitor(StreamInterface* stream) {
Yves Gerey665174f2018-06-19 15:03:05 +020050 stream->SignalEvent.connect(this, &StreamSink::OnEvent);
51 events_.erase(stream);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020052 }
53 void Unmonitor(StreamInterface* stream) {
Yves Gerey665174f2018-06-19 15:03:05 +020054 stream->SignalEvent.disconnect(this);
55 // In case you forgot to unmonitor a previous object with this address
56 events_.erase(stream);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020057 }
Yves Gerey665174f2018-06-19 15:03:05 +020058 bool Check(StreamInterface* stream,
59 StreamSinkEvent event,
60 bool reset = true) {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020061 return DoCheck(stream, event, reset);
62 }
63 int Events(StreamInterface* stream, bool reset = true) {
64 return DoEvents(stream, reset);
65 }
66
67 void Monitor(AsyncSocket* socket) {
Yves Gerey665174f2018-06-19 15:03:05 +020068 socket->SignalConnectEvent.connect(this, &StreamSink::OnConnectEvent);
69 socket->SignalReadEvent.connect(this, &StreamSink::OnReadEvent);
70 socket->SignalWriteEvent.connect(this, &StreamSink::OnWriteEvent);
71 socket->SignalCloseEvent.connect(this, &StreamSink::OnCloseEvent);
72 // In case you forgot to unmonitor a previous object with this address
73 events_.erase(socket);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020074 }
75 void Unmonitor(AsyncSocket* socket) {
Yves Gerey665174f2018-06-19 15:03:05 +020076 socket->SignalConnectEvent.disconnect(this);
77 socket->SignalReadEvent.disconnect(this);
78 socket->SignalWriteEvent.disconnect(this);
79 socket->SignalCloseEvent.disconnect(this);
80 events_.erase(socket);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020081 }
82 bool Check(AsyncSocket* socket, StreamSinkEvent event, bool reset = true) {
83 return DoCheck(socket, event, reset);
84 }
85 int Events(AsyncSocket* socket, bool reset = true) {
86 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
92 void OnEvent(StreamInterface* stream, int events, int error) {
93 if (error) {
94 events = SSE_ERROR;
95 }
96 AddEvents(stream, events);
97 }
Yves Gerey665174f2018-06-19 15:03:05 +020098 void OnConnectEvent(AsyncSocket* socket) { AddEvents(socket, SSE_OPEN); }
99 void OnReadEvent(AsyncSocket* socket) { AddEvents(socket, SSE_READ); }
100 void OnWriteEvent(AsyncSocket* socket) { AddEvents(socket, SSE_WRITE); }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200101 void OnCloseEvent(AsyncSocket* socket, int error) {
102 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200140#endif // RTC_BASE_TESTUTILS_H_