• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
11 #ifndef RTC_BASE_TEST_UTILS_H_
12 #define RTC_BASE_TEST_UTILS_H_
13 
14 // Utilities for testing rtc infrastructure in unittests
15 
16 #include <map>
17 #include <utility>
18 
19 #include "rtc_base/async_socket.h"
20 #include "rtc_base/stream.h"
21 #include "rtc_base/third_party/sigslot/sigslot.h"
22 
23 namespace webrtc {
24 namespace testing {
25 
26 ///////////////////////////////////////////////////////////////////////////////
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 
34 enum StreamSinkEvent {
35   SSE_OPEN = rtc::SE_OPEN,
36   SSE_READ = rtc::SE_READ,
37   SSE_WRITE = rtc::SE_WRITE,
38   SSE_CLOSE = rtc::SE_CLOSE,
39   SSE_ERROR = 16
40 };
41 
42 class StreamSink : public sigslot::has_slots<> {
43  public:
44   StreamSink();
45   ~StreamSink() override;
46 
Monitor(rtc::StreamInterface * stream)47   void Monitor(rtc::StreamInterface* stream) {
48     stream->SignalEvent.connect(this, &StreamSink::OnEvent);
49     events_.erase(stream);
50   }
Unmonitor(rtc::StreamInterface * stream)51   void Unmonitor(rtc::StreamInterface* stream) {
52     stream->SignalEvent.disconnect(this);
53     // In case you forgot to unmonitor a previous object with this address
54     events_.erase(stream);
55   }
56   bool Check(rtc::StreamInterface* stream,
57              StreamSinkEvent event,
58              bool reset = true) {
59     return DoCheck(stream, event, reset);
60   }
61   int Events(rtc::StreamInterface* stream, bool reset = true) {
62     return DoEvents(stream, reset);
63   }
64 
Monitor(rtc::AsyncSocket * socket)65   void Monitor(rtc::AsyncSocket* socket) {
66     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);
72   }
Unmonitor(rtc::AsyncSocket * socket)73   void Unmonitor(rtc::AsyncSocket* socket) {
74     socket->SignalConnectEvent.disconnect(this);
75     socket->SignalReadEvent.disconnect(this);
76     socket->SignalWriteEvent.disconnect(this);
77     socket->SignalCloseEvent.disconnect(this);
78     events_.erase(socket);
79   }
80   bool Check(rtc::AsyncSocket* socket,
81              StreamSinkEvent event,
82              bool reset = true) {
83     return DoCheck(socket, event, reset);
84   }
85   int Events(rtc::AsyncSocket* socket, bool reset = true) {
86     return DoEvents(socket, reset);
87   }
88 
89  private:
90   typedef std::map<void*, int> EventMap;
91 
OnEvent(rtc::StreamInterface * stream,int events,int error)92   void OnEvent(rtc::StreamInterface* stream, int events, int error) {
93     if (error) {
94       events = SSE_ERROR;
95     }
96     AddEvents(stream, events);
97   }
OnConnectEvent(rtc::AsyncSocket * socket)98   void OnConnectEvent(rtc::AsyncSocket* socket) { AddEvents(socket, SSE_OPEN); }
OnReadEvent(rtc::AsyncSocket * socket)99   void OnReadEvent(rtc::AsyncSocket* socket) { AddEvents(socket, SSE_READ); }
OnWriteEvent(rtc::AsyncSocket * socket)100   void OnWriteEvent(rtc::AsyncSocket* socket) { AddEvents(socket, SSE_WRITE); }
OnCloseEvent(rtc::AsyncSocket * socket,int error)101   void OnCloseEvent(rtc::AsyncSocket* socket, int error) {
102     AddEvents(socket, (0 == error) ? SSE_CLOSE : SSE_ERROR);
103   }
104 
AddEvents(void * obj,int events)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   }
DoCheck(void * obj,StreamSinkEvent event,bool reset)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   }
DoEvents(void * obj,bool reset)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 
137 }  // namespace testing
138 }  // namespace webrtc
139 
140 #endif  // RTC_BASE_TEST_UTILS_H_
141