blob: ac74203cf9f93cf7baa2a02e2d69ca6982dd0b61 [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 <algorithm>
17#include <map>
18#include <memory>
19#include <vector>
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "rtc_base/asyncsocket.h"
21#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "rtc_base/stream.h"
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020023
24namespace webrtc {
25namespace testing {
26
27using namespace rtc;
28
29///////////////////////////////////////////////////////////////////////////////
30// StreamSink - Monitor asynchronously signalled events from StreamInterface
31// or AsyncSocket (which should probably be a StreamInterface.
32///////////////////////////////////////////////////////////////////////////////
33
34// Note: Any event that is an error is treaded as SSE_ERROR instead of that
35// event.
36
37enum StreamSinkEvent {
Yves Gerey665174f2018-06-19 15:03:05 +020038 SSE_OPEN = SE_OPEN,
39 SSE_READ = SE_READ,
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020040 SSE_WRITE = SE_WRITE,
41 SSE_CLOSE = SE_CLOSE,
42 SSE_ERROR = 16
43};
44
45class StreamSink : public sigslot::has_slots<> {
46 public:
Steve Anton9de3aac2017-10-24 10:08:26 -070047 StreamSink();
48 ~StreamSink() override;
49
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020050 void Monitor(StreamInterface* stream) {
Yves Gerey665174f2018-06-19 15:03:05 +020051 stream->SignalEvent.connect(this, &StreamSink::OnEvent);
52 events_.erase(stream);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020053 }
54 void Unmonitor(StreamInterface* stream) {
Yves Gerey665174f2018-06-19 15:03:05 +020055 stream->SignalEvent.disconnect(this);
56 // In case you forgot to unmonitor a previous object with this address
57 events_.erase(stream);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020058 }
Yves Gerey665174f2018-06-19 15:03:05 +020059 bool Check(StreamInterface* stream,
60 StreamSinkEvent event,
61 bool reset = true) {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020062 return DoCheck(stream, event, reset);
63 }
64 int Events(StreamInterface* stream, bool reset = true) {
65 return DoEvents(stream, reset);
66 }
67
68 void Monitor(AsyncSocket* socket) {
Yves Gerey665174f2018-06-19 15:03:05 +020069 socket->SignalConnectEvent.connect(this, &StreamSink::OnConnectEvent);
70 socket->SignalReadEvent.connect(this, &StreamSink::OnReadEvent);
71 socket->SignalWriteEvent.connect(this, &StreamSink::OnWriteEvent);
72 socket->SignalCloseEvent.connect(this, &StreamSink::OnCloseEvent);
73 // In case you forgot to unmonitor a previous object with this address
74 events_.erase(socket);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020075 }
76 void Unmonitor(AsyncSocket* socket) {
Yves Gerey665174f2018-06-19 15:03:05 +020077 socket->SignalConnectEvent.disconnect(this);
78 socket->SignalReadEvent.disconnect(this);
79 socket->SignalWriteEvent.disconnect(this);
80 socket->SignalCloseEvent.disconnect(this);
81 events_.erase(socket);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020082 }
83 bool Check(AsyncSocket* socket, StreamSinkEvent event, bool reset = true) {
84 return DoCheck(socket, event, reset);
85 }
86 int Events(AsyncSocket* socket, bool reset = true) {
87 return DoEvents(socket, reset);
88 }
89
90 private:
Yves Gerey665174f2018-06-19 15:03:05 +020091 typedef std::map<void*, int> EventMap;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020092
93 void OnEvent(StreamInterface* stream, int events, int error) {
94 if (error) {
95 events = SSE_ERROR;
96 }
97 AddEvents(stream, events);
98 }
Yves Gerey665174f2018-06-19 15:03:05 +020099 void OnConnectEvent(AsyncSocket* socket) { AddEvents(socket, SSE_OPEN); }
100 void OnReadEvent(AsyncSocket* socket) { AddEvents(socket, SSE_READ); }
101 void OnWriteEvent(AsyncSocket* socket) { AddEvents(socket, SSE_WRITE); }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200102 void OnCloseEvent(AsyncSocket* socket, int error) {
103 AddEvents(socket, (0 == error) ? SSE_CLOSE : SSE_ERROR);
104 }
105
106 void AddEvents(void* obj, int events) {
107 EventMap::iterator it = events_.find(obj);
108 if (events_.end() == it) {
109 events_.insert(EventMap::value_type(obj, events));
110 } else {
111 it->second |= events;
112 }
113 }
114 bool DoCheck(void* obj, StreamSinkEvent event, bool reset) {
115 EventMap::iterator it = events_.find(obj);
116 if ((events_.end() == it) || (0 == (it->second & event))) {
117 return false;
118 }
119 if (reset) {
120 it->second &= ~event;
121 }
122 return true;
123 }
124 int DoEvents(void* obj, bool reset) {
125 EventMap::iterator it = events_.find(obj);
126 if (events_.end() == it)
127 return 0;
128 int events = it->second;
129 if (reset) {
130 it->second = 0;
131 }
132 return events;
133 }
134
135 EventMap events_;
136};
137
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200138} // namespace testing
139} // namespace webrtc
140
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200141#endif // RTC_BASE_TESTUTILS_H_