blob: dfa2a79ea265164cc6bd5d7f67d32ad24297ab26 [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";
Vitaly Buka3b8fbc52016-02-04 15:42:04 -080029constexpr char kEndpoint[] = "endpoint:456";
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070030
Vitaly Bukaa4b39832015-09-09 02:11:03 -070031constexpr char kStartStreamMessage[] =
32 "<stream:stream to='clouddevices.gserviceaccount.com' "
33 "xmlns:stream='http://etherx.jabber.org/streams' xml:lang='*' "
34 "version='1.0' xmlns='jabber:client'>";
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070035constexpr char kStartStreamResponse[] =
36 "<stream:stream from=\"clouddevices.gserviceaccount.com\" "
37 "id=\"0CCF520913ABA04B\" version=\"1.0\" "
38 "xmlns:stream=\"http://etherx.jabber.org/streams\" "
Vitaly Bukaa4b39832015-09-09 02:11:03 -070039 "xmlns=\"jabber:client\">";
40constexpr char kAuthenticationMessage[] =
41 "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='X-OAUTH2' "
42 "auth:service='oauth2' auth:allow-non-google-login='true' "
43 "auth:client-uses-full-bind-result='true' "
44 "xmlns:auth='http://www.google.com/talk/protocol/auth'>"
45 "AEFjY291bnRATmFtZQBBY2Nlc3NUb2tlbg==</auth>";
46constexpr char kConnectedResponse[] =
Alex Vakulenko2684b512015-05-19 13:42:10 -070047 "<stream:features><mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
48 "<mechanism>X-OAUTH2</mechanism>"
49 "<mechanism>X-GOOGLE-TOKEN</mechanism></mechanisms></stream:features>";
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070050constexpr char kAuthenticationSucceededResponse[] =
51 "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>";
52constexpr char kAuthenticationFailedResponse[] =
53 "<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"><not-authorized/>"
Alex Vakulenko94fe16c2015-06-23 12:30:11 -070054 "</failure>";
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070055constexpr char kRestartStreamResponse[] =
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070056 "<stream:features><bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>"
57 "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
58 "</stream:features>";
59constexpr char kBindResponse[] =
Alex Vakulenkodea76b22015-06-01 13:18:06 -070060 "<iq id=\"1\" type=\"result\">"
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070061 "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
62 "<jid>110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com"
63 "/19853128</jid></bind></iq>";
Vitaly Bukaa647c852015-07-06 14:51:01 -070064constexpr char kSessionResponse[] = "<iq type=\"result\" id=\"2\"/>";
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070065constexpr char kSubscribedResponse[] =
66 "<iq to=\""
67 "110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com/"
68 "19853128\" from=\""
69 "110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com\" "
Alex Vakulenkodea76b22015-06-01 13:18:06 -070070 "id=\"3\" type=\"result\"/>";
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070071constexpr char kBindMessage[] =
Alex Vakulenkodea76b22015-06-01 13:18:06 -070072 "<iq id='1' type='set'><bind "
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070073 "xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></iq>";
74constexpr char kSessionMessage[] =
Alex Vakulenkodea76b22015-06-01 13:18:06 -070075 "<iq id='2' type='set'><session "
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070076 "xmlns='urn:ietf:params:xml:ns:xmpp-session'/></iq>";
77constexpr char kSubscribeMessage[] =
Alex Vakulenkodea76b22015-06-01 13:18:06 -070078 "<iq id='3' type='set' to='Account@Name'>"
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070079 "<subscribe xmlns='google:push'><item channel='cloud_devices' from=''/>"
80 "</subscribe></iq>";
Vitaly Buka10c69ec2015-08-12 16:17:16 -070081
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070082} // namespace
83
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070084class FakeXmppChannel : public XmppChannel {
85 public:
Vitaly Buka1e363672015-09-25 14:01:16 -070086 explicit FakeXmppChannel(provider::TaskRunner* task_runner,
87 provider::Network* network)
Vitaly Buka3b8fbc52016-02-04 15:42:04 -080088 : XmppChannel{kAccountName, kAccessToken, kEndpoint, task_runner,
89 network},
Alex Vakulenko5a7a7da2015-09-25 16:10:23 -070090 stream_{new test::FakeStream{task_runner_}},
Vitaly Bukaa4b39832015-09-09 02:11:03 -070091 fake_stream_{stream_.get()} {}
92
Vitaly Buka74763422015-10-11 00:39:52 -070093 void Connect(const base::Callback<void(std::unique_ptr<Stream>,
94 ErrorPtr error)>& callback) {
95 callback.Run(std::move(stream_), nullptr);
Vitaly Bukaa4b39832015-09-09 02:11:03 -070096 }
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070097
98 XmppState state() const { return state_; }
99 void set_state(XmppState state) { state_ = state; }
100
Vitaly Buka63cc3d22015-06-23 20:11:36 -0700101 void SchedulePing(base::TimeDelta interval,
102 base::TimeDelta timeout) override {}
Alex Vakulenko5cd79972015-06-01 13:21:18 -0700103
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700104 void ExpectWritePacketString(base::TimeDelta delta, const std::string& data) {
105 fake_stream_->ExpectWritePacketString(delta, data);
106 }
107
108 void AddReadPacketString(base::TimeDelta delta, const std::string& data) {
109 fake_stream_->AddReadPacketString(delta, data);
110 }
111
Alex Vakulenko5a7a7da2015-09-25 16:10:23 -0700112 std::unique_ptr<test::FakeStream> stream_;
113 test::FakeStream* fake_stream_{nullptr};
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700114};
115
Vitaly Buka1e363672015-09-25 14:01:16 -0700116class MockNetwork : public provider::test::MockNetwork {
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700117 public:
Vitaly Buka1e363672015-09-25 14:01:16 -0700118 MockNetwork() {
Vitaly Buka3ab6f6e2015-09-24 13:16:16 -0700119 EXPECT_CALL(*this, AddConnectionChangedCallback(_))
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700120 .WillRepeatedly(Return());
121 }
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700122};
123
124class XmppChannelTest : public ::testing::Test {
125 protected:
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700126 XmppChannelTest() {
Vitaly Buka3b8fbc52016-02-04 15:42:04 -0800127 EXPECT_CALL(network_, OpenSslSocket("endpoint", 456, _))
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700128 .WillOnce(
129 WithArgs<2>(Invoke(&xmpp_client_, &FakeXmppChannel::Connect)));
130 }
131
Alex Vakulenkobf71f702015-05-18 14:30:56 -0700132 void StartStream() {
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700133 xmpp_client_.ExpectWritePacketString({}, kStartStreamMessage);
134 xmpp_client_.AddReadPacketString({}, kStartStreamResponse);
Vitaly Buka8e507c22015-08-12 23:37:19 -0700135 xmpp_client_.Start(nullptr);
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700136 RunUntil(XmppChannel::XmppState::kConnected);
Alex Vakulenkobf71f702015-05-18 14:30:56 -0700137 }
138
139 void StartWithState(XmppChannel::XmppState state) {
140 StartStream();
Vitaly Buka8e507c22015-08-12 23:37:19 -0700141 xmpp_client_.set_state(state);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700142 }
143
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700144 void RunUntil(XmppChannel::XmppState st) {
Vitaly Buka8e507c22015-08-12 23:37:19 -0700145 for (size_t n = 15; n && xmpp_client_.state() != st; --n)
Vitaly Buka823fdda2015-08-13 00:33:00 -0700146 task_runner_.RunOnce();
Vitaly Buka8e507c22015-08-12 23:37:19 -0700147 EXPECT_EQ(st, xmpp_client_.state());
Bertrand SIMONNETd2828842015-08-12 12:18:02 -0700148 }
Alex Vakulenkodea76b22015-06-01 13:18:06 -0700149
Vitaly Buka727f3e62015-09-25 17:33:43 -0700150 StrictMock<provider::test::FakeTaskRunner> task_runner_;
Vitaly Buka1e363672015-09-25 14:01:16 -0700151 StrictMock<MockNetwork> network_;
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700152 FakeXmppChannel xmpp_client_{&task_runner_, &network_};
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700153};
154
155TEST_F(XmppChannelTest, StartStream) {
Vitaly Buka8e507c22015-08-12 23:37:19 -0700156 EXPECT_EQ(XmppChannel::XmppState::kNotStarted, xmpp_client_.state());
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700157 xmpp_client_.ExpectWritePacketString({}, kStartStreamMessage);
Vitaly Buka8e507c22015-08-12 23:37:19 -0700158 xmpp_client_.Start(nullptr);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700159 RunUntil(XmppChannel::XmppState::kConnected);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700160}
161
162TEST_F(XmppChannelTest, HandleStartedResponse) {
Alex Vakulenkobf71f702015-05-18 14:30:56 -0700163 StartStream();
Alex Vakulenko2684b512015-05-19 13:42:10 -0700164}
165
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700166TEST_F(XmppChannelTest, HandleConnected) {
167 StartWithState(XmppChannel::XmppState::kConnected);
168 xmpp_client_.AddReadPacketString({}, kConnectedResponse);
169 xmpp_client_.ExpectWritePacketString({}, kAuthenticationMessage);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700170 RunUntil(XmppChannel::XmppState::kAuthenticationStarted);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700171}
172
173TEST_F(XmppChannelTest, HandleAuthenticationSucceededResponse) {
174 StartWithState(XmppChannel::XmppState::kAuthenticationStarted);
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700175 xmpp_client_.AddReadPacketString({}, kAuthenticationSucceededResponse);
176 xmpp_client_.ExpectWritePacketString({}, kStartStreamMessage);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700177 RunUntil(XmppChannel::XmppState::kStreamRestartedPostAuthentication);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700178}
179
180TEST_F(XmppChannelTest, HandleAuthenticationFailedResponse) {
181 StartWithState(XmppChannel::XmppState::kAuthenticationStarted);
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700182 xmpp_client_.AddReadPacketString({}, kAuthenticationFailedResponse);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700183 RunUntil(XmppChannel::XmppState::kAuthenticationFailed);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700184}
185
186TEST_F(XmppChannelTest, HandleStreamRestartedResponse) {
187 StartWithState(XmppChannel::XmppState::kStreamRestartedPostAuthentication);
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700188 xmpp_client_.AddReadPacketString({}, kRestartStreamResponse);
189 xmpp_client_.ExpectWritePacketString({}, kBindMessage);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700190 RunUntil(XmppChannel::XmppState::kBindSent);
Vitaly Buka8e507c22015-08-12 23:37:19 -0700191 EXPECT_TRUE(xmpp_client_.jid().empty());
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700192
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700193 xmpp_client_.AddReadPacketString({}, kBindResponse);
194 xmpp_client_.ExpectWritePacketString({}, kSessionMessage);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700195 RunUntil(XmppChannel::XmppState::kSessionStarted);
Vitaly Bukaa647c852015-07-06 14:51:01 -0700196 EXPECT_EQ(
197 "110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com"
198 "/19853128",
Vitaly Buka8e507c22015-08-12 23:37:19 -0700199 xmpp_client_.jid());
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700200
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700201 xmpp_client_.AddReadPacketString({}, kSessionResponse);
202 xmpp_client_.ExpectWritePacketString({}, kSubscribeMessage);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700203 RunUntil(XmppChannel::XmppState::kSubscribeStarted);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700204
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700205 xmpp_client_.AddReadPacketString({}, kSubscribedResponse);
Vitaly Buka8b13fa02015-08-12 13:34:26 -0700206 RunUntil(XmppChannel::XmppState::kSubscribed);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700207}
208
Vitaly Bukab6f015a2015-07-09 14:59:23 -0700209} // namespace weave