blob: 674fe2267a26a912b0cf86f8dae1fdbf0c327ee0 [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Stefan Sauer2d16dfa2015-09-25 17:08:35 +02005#include "src/notification/xmpp_channel.h"
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -07006
Vitaly Buka10c69ec2015-08-12 16:17:16 -07007#include <algorithm>
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -07008#include <queue>
9
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070010#include <gtest/gtest.h>
Vitaly Buka727f3e62015-09-25 17:33:43 -070011#include <weave/provider/test/fake_task_runner.h>
Vitaly Buka1e363672015-09-25 14:01:16 -070012#include <weave/provider/test/mock_network.h>
Alex Vakulenko5a7a7da2015-09-25 16:10:23 -070013#include <weave/test/fake_stream.h>
Vitaly Buka823fdda2015-08-13 00:33:00 -070014
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020015#include "src/bind_lambda.h"
Vitaly Buka6ca868f2015-08-13 21:53:05 -070016
Vitaly Bukaa4b39832015-09-09 02:11:03 -070017using testing::_;
18using testing::Invoke;
19using testing::Return;
Vitaly Buka823fdda2015-08-13 00:33:00 -070020using testing::StrictMock;
Vitaly Bukaa4b39832015-09-09 02:11:03 -070021using testing::WithArgs;
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070022
Vitaly Bukab6f015a2015-07-09 14:59:23 -070023namespace weave {
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070024
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070025namespace {
26
27constexpr char kAccountName[] = "Account@Name";
28constexpr char kAccessToken[] = "AccessToken";
29
Vitaly Bukaa4b39832015-09-09 02:11:03 -070030constexpr char kStartStreamMessage[] =
31 "<stream:stream to='clouddevices.gserviceaccount.com' "
32 "xmlns:stream='http://etherx.jabber.org/streams' xml:lang='*' "
33 "version='1.0' xmlns='jabber:client'>";
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070034constexpr char kStartStreamResponse[] =
35 "<stream:stream from=\"clouddevices.gserviceaccount.com\" "
36 "id=\"0CCF520913ABA04B\" version=\"1.0\" "
37 "xmlns:stream=\"http://etherx.jabber.org/streams\" "
Vitaly Bukaa4b39832015-09-09 02:11:03 -070038 "xmlns=\"jabber:client\">";
39constexpr char kAuthenticationMessage[] =
40 "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='X-OAUTH2' "
41 "auth:service='oauth2' auth:allow-non-google-login='true' "
42 "auth:client-uses-full-bind-result='true' "
43 "xmlns:auth='http://www.google.com/talk/protocol/auth'>"
44 "AEFjY291bnRATmFtZQBBY2Nlc3NUb2tlbg==</auth>";
45constexpr char kConnectedResponse[] =
Alex Vakulenko2684b512015-05-19 13:42:10 -070046 "<stream:features><mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
47 "<mechanism>X-OAUTH2</mechanism>"
48 "<mechanism>X-GOOGLE-TOKEN</mechanism></mechanisms></stream:features>";
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070049constexpr char kAuthenticationSucceededResponse[] =
50 "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>";
51constexpr char kAuthenticationFailedResponse[] =
52 "<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"><not-authorized/>"
Alex Vakulenko94fe16c2015-06-23 12:30:11 -070053 "</failure>";
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070054constexpr char kRestartStreamResponse[] =
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070055 "<stream:features><bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>"
56 "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
57 "</stream:features>";
58constexpr char kBindResponse[] =
Alex Vakulenkodea76b22015-06-01 13:18:06 -070059 "<iq id=\"1\" type=\"result\">"
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070060 "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
61 "<jid>110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com"
62 "/19853128</jid></bind></iq>";
Vitaly Bukaa647c852015-07-06 14:51:01 -070063constexpr char kSessionResponse[] = "<iq type=\"result\" id=\"2\"/>";
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070064constexpr char kSubscribedResponse[] =
65 "<iq to=\""
66 "110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com/"
67 "19853128\" from=\""
68 "110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com\" "
Alex Vakulenkodea76b22015-06-01 13:18:06 -070069 "id=\"3\" type=\"result\"/>";
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070070constexpr char kBindMessage[] =
Alex Vakulenkodea76b22015-06-01 13:18:06 -070071 "<iq id='1' type='set'><bind "
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070072 "xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></iq>";
73constexpr char kSessionMessage[] =
Alex Vakulenkodea76b22015-06-01 13:18:06 -070074 "<iq id='2' type='set'><session "
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070075 "xmlns='urn:ietf:params:xml:ns:xmpp-session'/></iq>";
76constexpr char kSubscribeMessage[] =
Alex Vakulenkodea76b22015-06-01 13:18:06 -070077 "<iq id='3' type='set' to='Account@Name'>"
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070078 "<subscribe xmlns='google:push'><item channel='cloud_devices' from=''/>"
79 "</subscribe></iq>";
Vitaly Buka10c69ec2015-08-12 16:17:16 -070080
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070081} // namespace
82
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070083class FakeXmppChannel : public XmppChannel {
84 public:
Vitaly Buka1e363672015-09-25 14:01:16 -070085 explicit FakeXmppChannel(provider::TaskRunner* task_runner,
86 provider::Network* network)
Vitaly Bukaa4b39832015-09-09 02:11:03 -070087 : XmppChannel{kAccountName, kAccessToken, task_runner, network},
Alex Vakulenko5a7a7da2015-09-25 16:10:23 -070088 stream_{new test::FakeStream{task_runner_}},
Vitaly Bukaa4b39832015-09-09 02:11:03 -070089 fake_stream_{stream_.get()} {}
90
Vitaly Buka74763422015-10-11 00:39:52 -070091 void Connect(const base::Callback<void(std::unique_ptr<Stream>,
92 ErrorPtr error)>& callback) {
93 callback.Run(std::move(stream_), nullptr);
Vitaly Bukaa4b39832015-09-09 02:11:03 -070094 }
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070095
96 XmppState state() const { return state_; }
97 void set_state(XmppState state) { state_ = state; }
98
Vitaly Buka63cc3d22015-06-23 20:11:36 -070099 void SchedulePing(base::TimeDelta interval,
100 base::TimeDelta timeout) override {}
Alex Vakulenko5cd79972015-06-01 13:21:18 -0700101
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700102 void ExpectWritePacketString(base::TimeDelta delta, const std::string& data) {
103 fake_stream_->ExpectWritePacketString(delta, data);
104 }
105
106 void AddReadPacketString(base::TimeDelta delta, const std::string& data) {
107 fake_stream_->AddReadPacketString(delta, data);
108 }
109
Alex Vakulenko5a7a7da2015-09-25 16:10:23 -0700110 std::unique_ptr<test::FakeStream> stream_;
111 test::FakeStream* fake_stream_{nullptr};
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700112};
113
Vitaly Buka1e363672015-09-25 14:01:16 -0700114class MockNetwork : public provider::test::MockNetwork {
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700115 public:
Vitaly Buka1e363672015-09-25 14:01:16 -0700116 MockNetwork() {
Vitaly Buka3ab6f6e2015-09-24 13:16:16 -0700117 EXPECT_CALL(*this, AddConnectionChangedCallback(_))
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700118 .WillRepeatedly(Return());
119 }
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700120};
121
122class XmppChannelTest : public ::testing::Test {
123 protected:
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700124 XmppChannelTest() {
Vitaly Buka74763422015-10-11 00:39:52 -0700125 EXPECT_CALL(network_, OpenSslSocket("talk.google.com", 5223, _))
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700126 .WillOnce(
127 WithArgs<2>(Invoke(&xmpp_client_, &FakeXmppChannel::Connect)));
128 }
129
Alex Vakulenkobf71f702015-05-18 14:30:56 -0700130 void StartStream() {
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700131 xmpp_client_.ExpectWritePacketString({}, kStartStreamMessage);
132 xmpp_client_.AddReadPacketString({}, kStartStreamResponse);
Vitaly Buka8e507c22015-08-12 23:37:19 -0700133 xmpp_client_.Start(nullptr);
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700134 RunUntil(XmppChannel::XmppState::kConnected);
Alex Vakulenkobf71f702015-05-18 14:30:56 -0700135 }
136
137 void StartWithState(XmppChannel::XmppState state) {
138 StartStream();
Vitaly Buka8e507c22015-08-12 23:37:19 -0700139 xmpp_client_.set_state(state);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700140 }
141
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700142 void RunUntil(XmppChannel::XmppState st) {
Vitaly Buka8e507c22015-08-12 23:37:19 -0700143 for (size_t n = 15; n && xmpp_client_.state() != st; --n)
Vitaly Buka823fdda2015-08-13 00:33:00 -0700144 task_runner_.RunOnce();
Vitaly Buka8e507c22015-08-12 23:37:19 -0700145 EXPECT_EQ(st, xmpp_client_.state());
Bertrand SIMONNETd2828842015-08-12 12:18:02 -0700146 }
Alex Vakulenkodea76b22015-06-01 13:18:06 -0700147
Vitaly Buka727f3e62015-09-25 17:33:43 -0700148 StrictMock<provider::test::FakeTaskRunner> task_runner_;
Vitaly Buka1e363672015-09-25 14:01:16 -0700149 StrictMock<MockNetwork> network_;
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700150 FakeXmppChannel xmpp_client_{&task_runner_, &network_};
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700151};
152
153TEST_F(XmppChannelTest, StartStream) {
Vitaly Buka8e507c22015-08-12 23:37:19 -0700154 EXPECT_EQ(XmppChannel::XmppState::kNotStarted, xmpp_client_.state());
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700155 xmpp_client_.ExpectWritePacketString({}, kStartStreamMessage);
Vitaly Buka8e507c22015-08-12 23:37:19 -0700156 xmpp_client_.Start(nullptr);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700157 RunUntil(XmppChannel::XmppState::kConnected);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700158}
159
160TEST_F(XmppChannelTest, HandleStartedResponse) {
Alex Vakulenkobf71f702015-05-18 14:30:56 -0700161 StartStream();
Alex Vakulenko2684b512015-05-19 13:42:10 -0700162}
163
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700164TEST_F(XmppChannelTest, HandleConnected) {
165 StartWithState(XmppChannel::XmppState::kConnected);
166 xmpp_client_.AddReadPacketString({}, kConnectedResponse);
167 xmpp_client_.ExpectWritePacketString({}, kAuthenticationMessage);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700168 RunUntil(XmppChannel::XmppState::kAuthenticationStarted);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700169}
170
171TEST_F(XmppChannelTest, HandleAuthenticationSucceededResponse) {
172 StartWithState(XmppChannel::XmppState::kAuthenticationStarted);
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700173 xmpp_client_.AddReadPacketString({}, kAuthenticationSucceededResponse);
174 xmpp_client_.ExpectWritePacketString({}, kStartStreamMessage);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700175 RunUntil(XmppChannel::XmppState::kStreamRestartedPostAuthentication);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700176}
177
178TEST_F(XmppChannelTest, HandleAuthenticationFailedResponse) {
179 StartWithState(XmppChannel::XmppState::kAuthenticationStarted);
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700180 xmpp_client_.AddReadPacketString({}, kAuthenticationFailedResponse);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700181 RunUntil(XmppChannel::XmppState::kAuthenticationFailed);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700182}
183
184TEST_F(XmppChannelTest, HandleStreamRestartedResponse) {
185 StartWithState(XmppChannel::XmppState::kStreamRestartedPostAuthentication);
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700186 xmpp_client_.AddReadPacketString({}, kRestartStreamResponse);
187 xmpp_client_.ExpectWritePacketString({}, kBindMessage);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700188 RunUntil(XmppChannel::XmppState::kBindSent);
Vitaly Buka8e507c22015-08-12 23:37:19 -0700189 EXPECT_TRUE(xmpp_client_.jid().empty());
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700190
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700191 xmpp_client_.AddReadPacketString({}, kBindResponse);
192 xmpp_client_.ExpectWritePacketString({}, kSessionMessage);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700193 RunUntil(XmppChannel::XmppState::kSessionStarted);
Vitaly Bukaa647c852015-07-06 14:51:01 -0700194 EXPECT_EQ(
195 "110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com"
196 "/19853128",
Vitaly Buka8e507c22015-08-12 23:37:19 -0700197 xmpp_client_.jid());
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700198
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700199 xmpp_client_.AddReadPacketString({}, kSessionResponse);
200 xmpp_client_.ExpectWritePacketString({}, kSubscribeMessage);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700201 RunUntil(XmppChannel::XmppState::kSubscribeStarted);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700202
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700203 xmpp_client_.AddReadPacketString({}, kSubscribedResponse);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700204 RunUntil(XmppChannel::XmppState::kSubscribed);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700205}
206
Vitaly Bukab6f015a2015-07-09 14:59:23 -0700207} // namespace weave