blob: 332857d371c36d693930f33ca65aa3d644994e01 [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
11#ifndef WEBRTC_BASE_TESTUTILS_H__
12#define WEBRTC_BASE_TESTUTILS_H__
13
14// Utilities for testing rtc infrastructure in unittests
15
16#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
17#include <X11/Xlib.h>
18#include <X11/extensions/Xrandr.h>
19
20// X defines a few macros that stomp on types that gunit.h uses.
21#undef None
22#undef Bool
23#endif
24
andresp@webrtc.orgff689be2015-02-12 11:54:26 +000025#include <algorithm>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000026#include <map>
jbauch555604a2016-04-26 03:13:22 -070027#include <memory>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000028#include <vector>
tfarina5237aaf2015-11-10 23:44:30 -080029#include "webrtc/base/arraysize.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000030#include "webrtc/base/asyncsocket.h"
nissec8ee8822017-01-18 07:20:55 -080031#include "webrtc/base/checks.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000032#include "webrtc/base/common.h"
33#include "webrtc/base/gunit.h"
34#include "webrtc/base/nethelpers.h"
henrike@webrtc.orgcfdf4202014-05-15 16:33:04 +000035#include "webrtc/base/pathutils.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000036#include "webrtc/base/stream.h"
37#include "webrtc/base/stringencode.h"
38#include "webrtc/base/stringutils.h"
39#include "webrtc/base/thread.h"
40
41namespace testing {
42
43using namespace rtc;
44
45///////////////////////////////////////////////////////////////////////////////
46// StreamSink - Monitor asynchronously signalled events from StreamInterface
47// or AsyncSocket (which should probably be a StreamInterface.
48///////////////////////////////////////////////////////////////////////////////
49
50// Note: Any event that is an error is treaded as SSE_ERROR instead of that
51// event.
52
53enum StreamSinkEvent {
54 SSE_OPEN = SE_OPEN,
55 SSE_READ = SE_READ,
56 SSE_WRITE = SE_WRITE,
57 SSE_CLOSE = SE_CLOSE,
58 SSE_ERROR = 16
59};
60
61class StreamSink : public sigslot::has_slots<> {
62 public:
63 void Monitor(StreamInterface* stream) {
64 stream->SignalEvent.connect(this, &StreamSink::OnEvent);
65 events_.erase(stream);
66 }
67 void Unmonitor(StreamInterface* stream) {
68 stream->SignalEvent.disconnect(this);
69 // In case you forgot to unmonitor a previous object with this address
70 events_.erase(stream);
71 }
72 bool Check(StreamInterface* stream, StreamSinkEvent event, bool reset = true) {
73 return DoCheck(stream, event, reset);
74 }
75 int Events(StreamInterface* stream, bool reset = true) {
76 return DoEvents(stream, reset);
77 }
78
79 void Monitor(AsyncSocket* socket) {
80 socket->SignalConnectEvent.connect(this, &StreamSink::OnConnectEvent);
81 socket->SignalReadEvent.connect(this, &StreamSink::OnReadEvent);
82 socket->SignalWriteEvent.connect(this, &StreamSink::OnWriteEvent);
83 socket->SignalCloseEvent.connect(this, &StreamSink::OnCloseEvent);
84 // In case you forgot to unmonitor a previous object with this address
85 events_.erase(socket);
86 }
87 void Unmonitor(AsyncSocket* socket) {
88 socket->SignalConnectEvent.disconnect(this);
89 socket->SignalReadEvent.disconnect(this);
90 socket->SignalWriteEvent.disconnect(this);
91 socket->SignalCloseEvent.disconnect(this);
92 events_.erase(socket);
93 }
94 bool Check(AsyncSocket* socket, StreamSinkEvent event, bool reset = true) {
95 return DoCheck(socket, event, reset);
96 }
97 int Events(AsyncSocket* socket, bool reset = true) {
98 return DoEvents(socket, reset);
99 }
100
101 private:
102 typedef std::map<void*,int> EventMap;
103
104 void OnEvent(StreamInterface* stream, int events, int error) {
105 if (error) {
106 events = SSE_ERROR;
107 }
108 AddEvents(stream, events);
109 }
110 void OnConnectEvent(AsyncSocket* socket) {
111 AddEvents(socket, SSE_OPEN);
112 }
113 void OnReadEvent(AsyncSocket* socket) {
114 AddEvents(socket, SSE_READ);
115 }
116 void OnWriteEvent(AsyncSocket* socket) {
117 AddEvents(socket, SSE_WRITE);
118 }
119 void OnCloseEvent(AsyncSocket* socket, int error) {
120 AddEvents(socket, (0 == error) ? SSE_CLOSE : SSE_ERROR);
121 }
122
123 void AddEvents(void* obj, int events) {
124 EventMap::iterator it = events_.find(obj);
125 if (events_.end() == it) {
126 events_.insert(EventMap::value_type(obj, events));
127 } else {
128 it->second |= events;
129 }
130 }
131 bool DoCheck(void* obj, StreamSinkEvent event, bool reset) {
132 EventMap::iterator it = events_.find(obj);
133 if ((events_.end() == it) || (0 == (it->second & event))) {
134 return false;
135 }
136 if (reset) {
137 it->second &= ~event;
138 }
139 return true;
140 }
141 int DoEvents(void* obj, bool reset) {
142 EventMap::iterator it = events_.find(obj);
143 if (events_.end() == it)
144 return 0;
145 int events = it->second;
146 if (reset) {
147 it->second = 0;
148 }
149 return events;
150 }
151
152 EventMap events_;
153};
154
155///////////////////////////////////////////////////////////////////////////////
156// StreamSource - Implements stream interface and simulates asynchronous
157// events on the stream, without a network. Also buffers written data.
158///////////////////////////////////////////////////////////////////////////////
159
160class StreamSource : public StreamInterface {
161public:
162 StreamSource() {
163 Clear();
164 }
165
166 void Clear() {
167 readable_data_.clear();
168 written_data_.clear();
169 state_ = SS_CLOSED;
170 read_block_ = 0;
171 write_block_ = SIZE_UNKNOWN;
172 }
173 void QueueString(const char* data) {
174 QueueData(data, strlen(data));
175 }
176 void QueueStringF(const char* format, ...) {
177 va_list args;
178 va_start(args, format);
179 char buffer[1024];
180 size_t len = vsprintfn(buffer, sizeof(buffer), format, args);
nissec8ee8822017-01-18 07:20:55 -0800181 RTC_CHECK(len < sizeof(buffer) - 1);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000182 va_end(args);
183 QueueData(buffer, len);
184 }
185 void QueueData(const char* data, size_t len) {
186 readable_data_.insert(readable_data_.end(), data, data + len);
187 if ((SS_OPEN == state_) && (readable_data_.size() == len)) {
188 SignalEvent(this, SE_READ, 0);
189 }
190 }
191 std::string ReadData() {
192 std::string data;
193 // avoid accessing written_data_[0] if it is undefined
194 if (written_data_.size() > 0) {
195 data.insert(0, &written_data_[0], written_data_.size());
196 }
197 written_data_.clear();
198 return data;
199 }
200 void SetState(StreamState state) {
201 int events = 0;
202 if ((SS_OPENING == state_) && (SS_OPEN == state)) {
203 events |= SE_OPEN;
204 if (!readable_data_.empty()) {
205 events |= SE_READ;
206 }
207 } else if ((SS_CLOSED != state_) && (SS_CLOSED == state)) {
208 events |= SE_CLOSE;
209 }
210 state_ = state;
211 if (events) {
212 SignalEvent(this, events, 0);
213 }
214 }
215 // Will cause Read to block when there are pos bytes in the read queue.
216 void SetReadBlock(size_t pos) { read_block_ = pos; }
217 // Will cause Write to block when there are pos bytes in the write queue.
218 void SetWriteBlock(size_t pos) { write_block_ = pos; }
219
220 virtual StreamState GetState() const { return state_; }
221 virtual StreamResult Read(void* buffer, size_t buffer_len,
222 size_t* read, int* error) {
223 if (SS_CLOSED == state_) {
224 if (error) *error = -1;
225 return SR_ERROR;
226 }
227 if ((SS_OPENING == state_) || (readable_data_.size() <= read_block_)) {
228 return SR_BLOCK;
229 }
andresp@webrtc.orgff689be2015-02-12 11:54:26 +0000230 size_t count = std::min(buffer_len, readable_data_.size() - read_block_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000231 memcpy(buffer, &readable_data_[0], count);
232 size_t new_size = readable_data_.size() - count;
233 // Avoid undefined access beyond the last element of the vector.
234 // This only happens when new_size is 0.
235 if (count < readable_data_.size()) {
236 memmove(&readable_data_[0], &readable_data_[count], new_size);
237 }
238 readable_data_.resize(new_size);
239 if (read) *read = count;
240 return SR_SUCCESS;
241 }
242 virtual StreamResult Write(const void* data, size_t data_len,
243 size_t* written, int* error) {
244 if (SS_CLOSED == state_) {
245 if (error) *error = -1;
246 return SR_ERROR;
247 }
248 if (SS_OPENING == state_) {
249 return SR_BLOCK;
250 }
251 if (SIZE_UNKNOWN != write_block_) {
252 if (written_data_.size() >= write_block_) {
253 return SR_BLOCK;
254 }
255 if (data_len > (write_block_ - written_data_.size())) {
256 data_len = write_block_ - written_data_.size();
257 }
258 }
259 if (written) *written = data_len;
260 const char* cdata = static_cast<const char*>(data);
261 written_data_.insert(written_data_.end(), cdata, cdata + data_len);
262 return SR_SUCCESS;
263 }
264 virtual void Close() { state_ = SS_CLOSED; }
265
266private:
267 typedef std::vector<char> Buffer;
268 Buffer readable_data_, written_data_;
269 StreamState state_;
270 size_t read_block_, write_block_;
271};
272
273///////////////////////////////////////////////////////////////////////////////
274// SocketTestClient
275// Creates a simulated client for testing. Works on real and virtual networks.
276///////////////////////////////////////////////////////////////////////////////
277
278class SocketTestClient : public sigslot::has_slots<> {
279public:
280 SocketTestClient() {
281 Init(NULL, AF_INET);
282 }
283 SocketTestClient(AsyncSocket* socket) {
284 Init(socket, socket->GetLocalAddress().family());
285 }
286 SocketTestClient(const SocketAddress& address) {
287 Init(NULL, address.family());
288 socket_->Connect(address);
289 }
290
291 AsyncSocket* socket() { return socket_.get(); }
292
293 void QueueString(const char* data) {
294 QueueData(data, strlen(data));
295 }
296 void QueueStringF(const char* format, ...) {
297 va_list args;
298 va_start(args, format);
299 char buffer[1024];
300 size_t len = vsprintfn(buffer, sizeof(buffer), format, args);
nissec8ee8822017-01-18 07:20:55 -0800301 RTC_CHECK(len < sizeof(buffer) - 1);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000302 va_end(args);
303 QueueData(buffer, len);
304 }
305 void QueueData(const char* data, size_t len) {
306 send_buffer_.insert(send_buffer_.end(), data, data + len);
307 if (Socket::CS_CONNECTED == socket_->GetState()) {
308 Flush();
309 }
310 }
311 std::string ReadData() {
312 std::string data(&recv_buffer_[0], recv_buffer_.size());
313 recv_buffer_.clear();
314 return data;
315 }
316
317 bool IsConnected() const {
318 return (Socket::CS_CONNECTED == socket_->GetState());
319 }
320 bool IsClosed() const {
321 return (Socket::CS_CLOSED == socket_->GetState());
322 }
323
324private:
325 typedef std::vector<char> Buffer;
326
327 void Init(AsyncSocket* socket, int family) {
328 if (!socket) {
329 socket = Thread::Current()->socketserver()
330 ->CreateAsyncSocket(family, SOCK_STREAM);
331 }
332 socket_.reset(socket);
333 socket_->SignalConnectEvent.connect(this,
334 &SocketTestClient::OnConnectEvent);
335 socket_->SignalReadEvent.connect(this, &SocketTestClient::OnReadEvent);
336 socket_->SignalWriteEvent.connect(this, &SocketTestClient::OnWriteEvent);
337 socket_->SignalCloseEvent.connect(this, &SocketTestClient::OnCloseEvent);
338 }
339
340 void Flush() {
341 size_t sent = 0;
342 while (sent < send_buffer_.size()) {
343 int result = socket_->Send(&send_buffer_[sent],
344 send_buffer_.size() - sent);
345 if (result > 0) {
346 sent += result;
347 } else {
348 break;
349 }
350 }
351 size_t new_size = send_buffer_.size() - sent;
352 memmove(&send_buffer_[0], &send_buffer_[sent], new_size);
353 send_buffer_.resize(new_size);
354 }
355
356 void OnConnectEvent(AsyncSocket* socket) {
357 if (!send_buffer_.empty()) {
358 Flush();
359 }
360 }
361 void OnReadEvent(AsyncSocket* socket) {
362 char data[64 * 1024];
Stefan Holmer9131efd2016-05-23 18:19:26 +0200363 int result = socket_->Recv(data, arraysize(data), nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000364 if (result > 0) {
365 recv_buffer_.insert(recv_buffer_.end(), data, data + result);
366 }
367 }
368 void OnWriteEvent(AsyncSocket* socket) {
369 if (!send_buffer_.empty()) {
370 Flush();
371 }
372 }
373 void OnCloseEvent(AsyncSocket* socket, int error) {
374 }
375
jbauch555604a2016-04-26 03:13:22 -0700376 std::unique_ptr<AsyncSocket> socket_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000377 Buffer send_buffer_, recv_buffer_;
378};
379
380///////////////////////////////////////////////////////////////////////////////
381// SocketTestServer
382// Creates a simulated server for testing. Works on real and virtual networks.
383///////////////////////////////////////////////////////////////////////////////
384
385class SocketTestServer : public sigslot::has_slots<> {
386 public:
387 SocketTestServer(const SocketAddress& address)
388 : socket_(Thread::Current()->socketserver()
389 ->CreateAsyncSocket(address.family(), SOCK_STREAM))
390 {
391 socket_->SignalReadEvent.connect(this, &SocketTestServer::OnReadEvent);
392 socket_->Bind(address);
393 socket_->Listen(5);
394 }
395 virtual ~SocketTestServer() {
396 clear();
397 }
398
399 size_t size() const { return clients_.size(); }
400 SocketTestClient* client(size_t index) const { return clients_[index]; }
401 SocketTestClient* operator[](size_t index) const { return client(index); }
402
403 void clear() {
404 for (size_t i=0; i<clients_.size(); ++i) {
405 delete clients_[i];
406 }
407 clients_.clear();
408 }
409
410 private:
411 void OnReadEvent(AsyncSocket* socket) {
412 AsyncSocket* accepted =
413 static_cast<AsyncSocket*>(socket_->Accept(NULL));
414 if (!accepted)
415 return;
416 clients_.push_back(new SocketTestClient(accepted));
417 }
418
jbauch555604a2016-04-26 03:13:22 -0700419 std::unique_ptr<AsyncSocket> socket_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000420 std::vector<SocketTestClient*> clients_;
421};
422
423///////////////////////////////////////////////////////////////////////////////
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000424// Unittest predicates which are similar to STREQ, but for raw memory
425///////////////////////////////////////////////////////////////////////////////
426
427inline AssertionResult CmpHelperMemEq(const char* expected_expression,
428 const char* expected_length_expression,
429 const char* actual_expression,
430 const char* actual_length_expression,
431 const void* expected,
432 size_t expected_length,
433 const void* actual,
434 size_t actual_length)
435{
436 if ((expected_length == actual_length)
437 && (0 == memcmp(expected, actual, expected_length))) {
438 return AssertionSuccess();
439 }
440
441 Message msg;
442 msg << "Value of: " << actual_expression
443 << " [" << actual_length_expression << "]";
444 if (true) { //!actual_value.Equals(actual_expression)) {
445 size_t buffer_size = actual_length * 2 + 1;
446 char* buffer = STACK_ARRAY(char, buffer_size);
447 hex_encode(buffer, buffer_size,
448 reinterpret_cast<const char*>(actual), actual_length);
449 msg << "\n Actual: " << buffer << " [" << actual_length << "]";
450 }
451
452 msg << "\nExpected: " << expected_expression
453 << " [" << expected_length_expression << "]";
454 if (true) { //!expected_value.Equals(expected_expression)) {
455 size_t buffer_size = expected_length * 2 + 1;
456 char* buffer = STACK_ARRAY(char, buffer_size);
457 hex_encode(buffer, buffer_size,
458 reinterpret_cast<const char*>(expected), expected_length);
459 msg << "\nWhich is: " << buffer << " [" << expected_length << "]";
460 }
461
462 return AssertionFailure(msg);
463}
464
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000465#define EXPECT_MEMEQ(expected, expected_length, actual, actual_length) \
466 EXPECT_PRED_FORMAT4(::testing::CmpHelperMemEq, expected, expected_length, \
467 actual, actual_length)
468
469#define ASSERT_MEMEQ(expected, expected_length, actual, actual_length) \
470 ASSERT_PRED_FORMAT4(::testing::CmpHelperMemEq, expected, expected_length, \
471 actual, actual_length)
472
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000473///////////////////////////////////////////////////////////////////////////////
474// Helpers for initializing constant memory with integers in a particular byte
475// order
476///////////////////////////////////////////////////////////////////////////////
477
Peter Boström0c4e06b2015-10-07 12:23:21 +0200478#define BYTE_CAST(x) static_cast<uint8_t>((x)&0xFF)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000479
480// Declare a N-bit integer as a little-endian sequence of bytes
Peter Boström0c4e06b2015-10-07 12:23:21 +0200481#define LE16(x) BYTE_CAST(((uint16_t)x) >> 0), BYTE_CAST(((uint16_t)x) >> 8)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000482
Peter Boström0c4e06b2015-10-07 12:23:21 +0200483#define LE32(x) \
484 BYTE_CAST(((uint32_t)x) >> 0), BYTE_CAST(((uint32_t)x) >> 8), \
485 BYTE_CAST(((uint32_t)x) >> 16), BYTE_CAST(((uint32_t)x) >> 24)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000486
Peter Boström0c4e06b2015-10-07 12:23:21 +0200487#define LE64(x) \
488 BYTE_CAST(((uint64_t)x) >> 0), BYTE_CAST(((uint64_t)x) >> 8), \
489 BYTE_CAST(((uint64_t)x) >> 16), BYTE_CAST(((uint64_t)x) >> 24), \
490 BYTE_CAST(((uint64_t)x) >> 32), BYTE_CAST(((uint64_t)x) >> 40), \
491 BYTE_CAST(((uint64_t)x) >> 48), BYTE_CAST(((uint64_t)x) >> 56)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000492
493// Declare a N-bit integer as a big-endian (Internet) sequence of bytes
Peter Boström0c4e06b2015-10-07 12:23:21 +0200494#define BE16(x) BYTE_CAST(((uint16_t)x) >> 8), BYTE_CAST(((uint16_t)x) >> 0)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000495
Peter Boström0c4e06b2015-10-07 12:23:21 +0200496#define BE32(x) \
497 BYTE_CAST(((uint32_t)x) >> 24), BYTE_CAST(((uint32_t)x) >> 16), \
498 BYTE_CAST(((uint32_t)x) >> 8), BYTE_CAST(((uint32_t)x) >> 0)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000499
Peter Boström0c4e06b2015-10-07 12:23:21 +0200500#define BE64(x) \
501 BYTE_CAST(((uint64_t)x) >> 56), BYTE_CAST(((uint64_t)x) >> 48), \
502 BYTE_CAST(((uint64_t)x) >> 40), BYTE_CAST(((uint64_t)x) >> 32), \
503 BYTE_CAST(((uint64_t)x) >> 24), BYTE_CAST(((uint64_t)x) >> 16), \
504 BYTE_CAST(((uint64_t)x) >> 8), BYTE_CAST(((uint64_t)x) >> 0)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000505
506// Declare a N-bit integer as a this-endian (local machine) sequence of bytes
507#ifndef BIG_ENDIAN
508#define BIG_ENDIAN 1
509#endif // BIG_ENDIAN
510
511#if BIG_ENDIAN
512#define TE16 BE16
513#define TE32 BE32
514#define TE64 BE64
515#else // !BIG_ENDIAN
516#define TE16 LE16
517#define TE32 LE32
518#define TE64 LE64
519#endif // !BIG_ENDIAN
520
521///////////////////////////////////////////////////////////////////////////////
522
523// Helpers for determining if X/screencasting is available (on linux).
524
525#define MAYBE_SKIP_SCREENCAST_TEST() \
526 if (!testing::IsScreencastingAvailable()) { \
527 LOG(LS_WARNING) << "Skipping test, since it doesn't have the requisite " \
528 << "X environment for screen capture."; \
529 return; \
530 } \
531
532#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
533struct XDisplay {
534 XDisplay() : display_(XOpenDisplay(NULL)) { }
535 ~XDisplay() { if (display_) XCloseDisplay(display_); }
536 bool IsValid() const { return display_ != NULL; }
537 operator Display*() { return display_; }
538 private:
539 Display* display_;
540};
541#endif
542
543// Returns true if screencasting is available. When false, anything that uses
544// screencasting features may fail.
545inline bool IsScreencastingAvailable() {
546#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
547 XDisplay display;
548 if (!display.IsValid()) {
549 LOG(LS_WARNING) << "No X Display available.";
550 return false;
551 }
552 int ignored_int, major_version, minor_version;
553 if (!XRRQueryExtension(display, &ignored_int, &ignored_int) ||
554 !XRRQueryVersion(display, &major_version, &minor_version) ||
555 major_version < 1 ||
556 (major_version < 2 && minor_version < 3)) {
557 LOG(LS_WARNING) << "XRandr version: " << major_version << "."
558 << minor_version;
559 LOG(LS_WARNING) << "XRandr is not supported or is too old (pre 1.3).";
560 return false;
561 }
562#endif
563 return true;
564}
565} // namespace testing
566
567#endif // WEBRTC_BASE_TESTUTILS_H__