1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/memory/scoped_ptr.h"
6#include "base/message_loop/message_loop.h"
7#include "base/values.h"
8#include "content/browser/media/webrtc_internals.h"
9#include "content/browser/media/webrtc_internals_ui_observer.h"
10#include "content/public/test/test_browser_thread.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace content {
14
15namespace {
16
17static const std::string kContraints = "c";
18static const std::string kRtcConfiguration = "r";
19static const std::string kUrl = "u";
20
21class MockWebRTCInternalsProxy : public WebRTCInternalsUIObserver {
22 public:
23  virtual void OnUpdate(const std::string& command,
24                        const base::Value* value) OVERRIDE {
25    command_ = command;
26    if (value)
27      value_.reset(value->DeepCopy());
28  }
29
30  std::string command() {
31    return command_;
32  }
33
34  base::Value* value() {
35    return value_.get();
36  }
37
38 private:
39   std::string command_;
40   scoped_ptr<base::Value> value_;
41};
42
43class WebRTCInternalsTest : public testing::Test {
44 public:
45  WebRTCInternalsTest() : io_thread_(BrowserThread::UI, &io_loop_) {
46    WebRTCInternals::GetInstance()->ResetForTesting();
47  }
48
49 protected:
50  void VerifyString(const base::DictionaryValue* dict,
51                    const std::string& key,
52                    const std::string& expected) {
53    std::string actual;
54    EXPECT_TRUE(dict->GetString(key, &actual));
55    EXPECT_EQ(expected, actual);
56  }
57
58  void VerifyInt(const base::DictionaryValue* dict,
59                 const std::string& key,
60                 int expected) {
61    int actual;
62    EXPECT_TRUE(dict->GetInteger(key, &actual));
63    EXPECT_EQ(expected, actual);
64  }
65
66  void VerifyList(const base::DictionaryValue* dict,
67                  const std::string& key,
68                  const base::ListValue& expected) {
69    const base::ListValue* actual = NULL;
70    EXPECT_TRUE(dict->GetList(key, &actual));
71    EXPECT_TRUE(expected.Equals(actual));
72  }
73
74  void VerifyGetUserMediaData(base::Value* actual_data,
75                              int rid,
76                              int pid,
77                              const std::string& origin,
78                              const std::string& audio,
79                              const std::string& video) {
80    base::DictionaryValue* dict = NULL;
81    EXPECT_TRUE(actual_data->GetAsDictionary(&dict));
82
83    VerifyInt(dict, "rid", rid);
84    VerifyInt(dict, "pid", pid);
85    VerifyString(dict, "origin", origin);
86    VerifyString(dict, "audio", audio);
87    VerifyString(dict, "video", video);
88  }
89
90  base::MessageLoop io_loop_;
91  TestBrowserThread io_thread_;
92};
93
94}  // namespace
95
96TEST_F(WebRTCInternalsTest, AddRemoveObserver) {
97  scoped_ptr<MockWebRTCInternalsProxy> observer(
98      new MockWebRTCInternalsProxy());
99  WebRTCInternals::GetInstance()->AddObserver(observer.get());
100  WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
101  WebRTCInternals::GetInstance()->OnAddPeerConnection(
102      0, 3, 4, kUrl, kRtcConfiguration, kContraints);
103  EXPECT_EQ("", observer->command());
104
105  WebRTCInternals::GetInstance()->OnRemovePeerConnection(3, 4);
106}
107
108TEST_F(WebRTCInternalsTest, SendAddPeerConnectionUpdate) {
109  scoped_ptr<MockWebRTCInternalsProxy> observer(
110      new MockWebRTCInternalsProxy());
111  WebRTCInternals::GetInstance()->AddObserver(observer.get());
112  WebRTCInternals::GetInstance()->OnAddPeerConnection(
113      0, 1, 2, kUrl, kRtcConfiguration, kContraints);
114  EXPECT_EQ("addPeerConnection", observer->command());
115
116  base::DictionaryValue* dict = NULL;
117  EXPECT_TRUE(observer->value()->GetAsDictionary(&dict));
118
119  VerifyInt(dict, "pid", 1);
120  VerifyInt(dict, "lid", 2);
121  VerifyString(dict, "url", kUrl);
122  VerifyString(dict, "rtcConfiguration", kRtcConfiguration);
123  VerifyString(dict, "constraints", kContraints);
124
125  WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
126  WebRTCInternals::GetInstance()->OnRemovePeerConnection(1, 2);
127}
128
129TEST_F(WebRTCInternalsTest, SendRemovePeerConnectionUpdate) {
130  scoped_ptr<MockWebRTCInternalsProxy> observer(
131      new MockWebRTCInternalsProxy());
132  WebRTCInternals::GetInstance()->AddObserver(observer.get());
133  WebRTCInternals::GetInstance()->OnAddPeerConnection(
134      0, 1, 2, kUrl, kRtcConfiguration, kContraints);
135  WebRTCInternals::GetInstance()->OnRemovePeerConnection(1, 2);
136  EXPECT_EQ("removePeerConnection", observer->command());
137
138  base::DictionaryValue* dict = NULL;
139  EXPECT_TRUE(observer->value()->GetAsDictionary(&dict));
140
141  VerifyInt(dict, "pid", 1);
142  VerifyInt(dict, "lid", 2);
143
144  WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
145}
146
147TEST_F(WebRTCInternalsTest, SendUpdatePeerConnectionUpdate) {
148  scoped_ptr<MockWebRTCInternalsProxy> observer(
149      new MockWebRTCInternalsProxy());
150  WebRTCInternals::GetInstance()->AddObserver(observer.get());
151  WebRTCInternals::GetInstance()->OnAddPeerConnection(
152      0, 1, 2, kUrl, kRtcConfiguration, kContraints);
153
154  const std::string update_type = "fakeType";
155  const std::string update_value = "fakeValue";
156  WebRTCInternals::GetInstance()->OnUpdatePeerConnection(
157      1, 2, update_type, update_value);
158
159  EXPECT_EQ("updatePeerConnection", observer->command());
160
161  base::DictionaryValue* dict = NULL;
162  EXPECT_TRUE(observer->value()->GetAsDictionary(&dict));
163
164  VerifyInt(dict, "pid", 1);
165  VerifyInt(dict, "lid", 2);
166  VerifyString(dict, "type", update_type);
167  VerifyString(dict, "value", update_value);
168
169  std::string time;
170  EXPECT_TRUE(dict->GetString("time", &time));
171  EXPECT_FALSE(time.empty());
172
173  WebRTCInternals::GetInstance()->OnRemovePeerConnection(1, 2);
174  WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
175}
176
177TEST_F(WebRTCInternalsTest, AddGetUserMedia) {
178  scoped_ptr<MockWebRTCInternalsProxy> observer(new MockWebRTCInternalsProxy());
179
180  // Add one observer before "getUserMedia".
181  WebRTCInternals::GetInstance()->AddObserver(observer.get());
182
183  const int rid = 1;
184  const int pid = 2;
185  const std::string audio_constraint = "aaa";
186  const std::string video_constraint = "vvv";
187  WebRTCInternals::GetInstance()->OnGetUserMedia(
188      rid, pid, kUrl, true, true, audio_constraint, video_constraint);
189
190  EXPECT_EQ("addGetUserMedia", observer->command());
191  VerifyGetUserMediaData(
192      observer->value(), rid, pid, kUrl, audio_constraint, video_constraint);
193
194  WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
195}
196
197TEST_F(WebRTCInternalsTest, SendAllUpdateWithGetUserMedia) {
198  const int rid = 1;
199  const int pid = 2;
200  const std::string audio_constraint = "aaa";
201  const std::string video_constraint = "vvv";
202  WebRTCInternals::GetInstance()->OnGetUserMedia(
203      rid, pid, kUrl, true, true, audio_constraint, video_constraint);
204
205  scoped_ptr<MockWebRTCInternalsProxy> observer(new MockWebRTCInternalsProxy());
206  // Add one observer after "getUserMedia".
207  WebRTCInternals::GetInstance()->AddObserver(observer.get());
208  WebRTCInternals::GetInstance()->UpdateObserver(observer.get());
209
210  EXPECT_EQ("addGetUserMedia", observer->command());
211  VerifyGetUserMediaData(
212      observer->value(), rid, pid, kUrl, audio_constraint, video_constraint);
213
214  WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
215}
216
217TEST_F(WebRTCInternalsTest, SendAllUpdatesWithPeerConnectionUpdate) {
218  const int rid = 0, pid = 1, lid = 2;
219  const std::string update_type = "fakeType";
220  const std::string update_value = "fakeValue";
221
222  WebRTCInternals::GetInstance()->OnAddPeerConnection(
223      rid, pid, lid, kUrl, kRtcConfiguration, kContraints);
224  WebRTCInternals::GetInstance()->OnUpdatePeerConnection(
225      pid, lid, update_type, update_value);
226
227  scoped_ptr<MockWebRTCInternalsProxy> observer(new MockWebRTCInternalsProxy());
228  WebRTCInternals::GetInstance()->AddObserver(observer.get());
229
230  WebRTCInternals::GetInstance()->UpdateObserver(observer.get());
231
232  EXPECT_EQ("updateAllPeerConnections", observer->command());
233
234  base::ListValue* list = NULL;
235  EXPECT_TRUE(observer->value()->GetAsList(&list));
236  EXPECT_EQ(1U, list->GetSize());
237
238  base::DictionaryValue* dict = NULL;
239  EXPECT_TRUE((*list->begin())->GetAsDictionary(&dict));
240
241  VerifyInt(dict, "rid", rid);
242  VerifyInt(dict, "pid", pid);
243  VerifyInt(dict, "lid", lid);
244  VerifyString(dict, "url", kUrl);
245  VerifyString(dict, "rtcConfiguration", kRtcConfiguration);
246  VerifyString(dict, "constraints", kContraints);
247
248  base::ListValue* log = NULL;
249  EXPECT_TRUE(dict->GetList("log", &log));
250  EXPECT_EQ(1U, log->GetSize());
251
252  EXPECT_TRUE((*log->begin())->GetAsDictionary(&dict));
253  VerifyString(dict, "type", update_type);
254  VerifyString(dict, "value", update_value);
255  std::string time;
256  EXPECT_TRUE(dict->GetString("time", &time));
257  EXPECT_FALSE(time.empty());
258}
259
260TEST_F(WebRTCInternalsTest, OnAddStats) {
261  const int rid = 0, pid = 1, lid = 2;
262  scoped_ptr<MockWebRTCInternalsProxy> observer(new MockWebRTCInternalsProxy());
263  WebRTCInternals::GetInstance()->AddObserver(observer.get());
264  WebRTCInternals::GetInstance()->OnAddPeerConnection(
265      rid, pid, lid, kUrl, kRtcConfiguration, kContraints);
266
267  base::ListValue list;
268  list.AppendString("xxx");
269  list.AppendString("yyy");
270  WebRTCInternals::GetInstance()->OnAddStats(pid, lid, list);
271
272  EXPECT_EQ("addStats", observer->command());
273  base::DictionaryValue* dict = NULL;
274  EXPECT_TRUE(observer->value()->GetAsDictionary(&dict));
275
276  VerifyInt(dict, "pid", pid);
277  VerifyInt(dict, "lid", lid);
278  VerifyList(dict, "reports", list);
279}
280
281TEST_F(WebRTCInternalsTest, AecRecordingFileSelectionCanceled) {
282  scoped_ptr<MockWebRTCInternalsProxy> observer(new MockWebRTCInternalsProxy());
283  WebRTCInternals::GetInstance()->AddObserver(observer.get());
284  WebRTCInternals::GetInstance()->FileSelectionCanceled(NULL);
285  EXPECT_EQ("aecRecordingFileSelectionCancelled", observer->command());
286  EXPECT_EQ(NULL, observer->value());
287}
288
289}  // namespace content
290