blob: ef26f2e7d1a7d715de1afebcada91076c80d5063 [file] [log] [blame]
Nathan Bullockbdabded2015-02-10 20:15:53 -05001// Copyright 2015 The Chromium OS 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 "buffet/device_registration_info.h"
6
7#include <base/values.h>
8#include <chromeos/key_value_store.h>
9#include <chromeos/http/curl_api.h>
10#include <gmock/gmock.h>
11#include <gtest/gtest.h>
12
13#include "buffet/xmpp/xmpp_client.h"
14#include "buffet/xmpp/xmpp_connection.h"
15
16using ::testing::DoAll;
17using ::testing::Return;
18using ::testing::SetArgPointee;
19using ::testing::_;
20
21namespace buffet {
22
23namespace {
24
25constexpr char kAccountName[] = "Account@Name";
26constexpr char kAccessToken[] = "AccessToken";
27
28constexpr char kStartStreamResponse[] =
29 "<stream:stream from=\"clouddevices.gserviceaccount.com\" "
30 "id=\"0CCF520913ABA04B\" version=\"1.0\" "
31 "xmlns:stream=\"http://etherx.jabber.org/streams\" "
32 "xmlns=\"jabber:client\">"
33 "<stream:features><starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\">"
34 "<required/></starttls><mechanisms "
35 "xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"><mechanism>X-OAUTH2</mechanism>"
36 "<mechanism>X-GOOGLE-TOKEN</mechanism></mechanisms></stream:features>";
Nathan Bullockf12f7f02015-02-20 14:46:53 -050037constexpr char kAuthenticationSucceededResponse[] =
Nathan Bullockbdabded2015-02-10 20:15:53 -050038 "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>";
Nathan Bullockf12f7f02015-02-20 14:46:53 -050039constexpr char kAuthenticationFailedResponse[] =
40 "<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"><not-authorized/>"
41 "</failure></stream:stream>";
Nathan Bullockbdabded2015-02-10 20:15:53 -050042constexpr char kRestartStreamResponse[] =
43 "<stream:stream from=\"clouddevices.gserviceaccount.com\" "
44 "id=\"BE7D34E0B7589E2A\" version=\"1.0\" "
45 "xmlns:stream=\"http://etherx.jabber.org/streams\" "
46 "xmlns=\"jabber:client\">"
47 "<stream:features><bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>"
48 "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
49 "</stream:features>";
50constexpr char kBindResponse[] =
51 "<iq id=\"0\" type=\"result\">"
52 "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
53 "<jid>110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com"
54 "/19853128</jid></bind></iq>";
55constexpr char kSessionResponse[] =
56 "<iq type=\"result\" id=\"1\"/>";
57constexpr char kSubscribedResponse[] =
58 "<iq to=\""
59 "110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com/"
60 "19853128\" from=\""
61 "110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com\" "
62 "id=\"pushsubscribe1\" type=\"result\"/>";
63
64constexpr char kStartStreamMessage[] =
65 "<stream:stream to='clouddevices.gserviceaccount.com' "
66 "xmlns:stream='http://etherx.jabber.org/streams' xml:lang='*' "
67 "version='1.0' xmlns='jabber:client'>";
68constexpr char kAuthenticationMessage[] =
69 "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='X-OAUTH2' "
70 "auth:service='oauth2' auth:allow-non-google-login='true' "
71 "auth:client-uses-full-bind-result='true' "
72 "xmlns:auth='http://www.google.com/talk/protocol/auth'>"
73 "AEFjY291bnRATmFtZQBBY2Nlc3NUb2tlbg==</auth>";
74constexpr char kBindMessage[] =
75 "<iq type='set' id='0'><bind "
76 "xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></iq>";
77constexpr char kSessionMessage[] =
78 "<iq type='set' id='1'><session "
79 "xmlns='urn:ietf:params:xml:ns:xmpp-session'/></iq>";
80constexpr char kSubscribeMessage[] =
81 "<iq type='set' to='Account@Name' id='pushsubscribe1'>"
82 "<subscribe xmlns='google:push'><item channel='cloud_devices' from=''/>"
83 "</subscribe></iq>";
84
85class MockXmppConnection : public XmppConnection {
86 public:
87 MockXmppConnection() = default;
88
89 MOCK_CONST_METHOD1(Read, bool(std::string* msg));
90 MOCK_CONST_METHOD1(Write, bool(const std::string& msg));
91
92 private:
93 DISALLOW_COPY_AND_ASSIGN(MockXmppConnection);
94};
95
96} // namespace
97
98class TestHelper {
99 public:
100 static void SetState(XmppClient* client, XmppClient::XmppState state) {
101 client->state_ = state;
102 }
103
104 static XmppClient::XmppState GetState(const XmppClient& client) {
105 return client.state_;
106 }
107
108 static XmppConnection* GetConnection(const XmppClient& client) {
109 return client.connection_.get();
110 }
111};
112
113class XmppClientTest : public ::testing::Test {
114 protected:
115 void SetUp() override {
116 std::unique_ptr<XmppConnection> connection(new MockXmppConnection());
117 xmpp_client_.reset(new XmppClient(kAccountName, kAccessToken,
118 std::move(connection)));
119 connection_ = static_cast<MockXmppConnection*>(
120 TestHelper::GetConnection(*xmpp_client_));
121 }
122
123 std::unique_ptr<XmppClient> xmpp_client_;
124 MockXmppConnection* connection_; // xmpp_client_ owns this.
125};
126
127TEST_F(XmppClientTest, StartStream) {
128 EXPECT_EQ(TestHelper::GetState(*xmpp_client_),
129 XmppClient::XmppState::kNotStarted);
130 EXPECT_CALL(*connection_, Write(kStartStreamMessage))
131 .WillOnce(Return(true));
132 xmpp_client_->StartStream();
133 EXPECT_EQ(TestHelper::GetState(*xmpp_client_),
134 XmppClient::XmppState::kStarted);
135}
136
137TEST_F(XmppClientTest, HandleStartedResponse) {
138 TestHelper::SetState(xmpp_client_.get(),
139 XmppClient::XmppState::kStarted);
140 EXPECT_CALL(*connection_, Read(_))
141 .WillOnce(DoAll(SetArgPointee<0>(kStartStreamResponse), Return(true)));
142 EXPECT_CALL(*connection_, Write(kAuthenticationMessage))
143 .WillOnce(Return(true));
144 xmpp_client_->Read();
145 EXPECT_EQ(TestHelper::GetState(*xmpp_client_),
146 XmppClient::XmppState::kAuthenticationStarted);
147}
148
Nathan Bullockf12f7f02015-02-20 14:46:53 -0500149TEST_F(XmppClientTest, HandleAuthenticationSucceededResponse) {
Nathan Bullockbdabded2015-02-10 20:15:53 -0500150 TestHelper::SetState(
151 xmpp_client_.get(),
152 XmppClient::XmppState::kAuthenticationStarted);
153 EXPECT_CALL(*connection_, Read(_))
Nathan Bullockf12f7f02015-02-20 14:46:53 -0500154 .WillOnce(DoAll(SetArgPointee<0>(kAuthenticationSucceededResponse),
155 Return(true)));
Nathan Bullockbdabded2015-02-10 20:15:53 -0500156 EXPECT_CALL(*connection_, Write(kStartStreamMessage))
157 .WillOnce(Return(true));
158 xmpp_client_->Read();
159 EXPECT_EQ(TestHelper::GetState(*xmpp_client_),
160 XmppClient::XmppState::kStreamRestartedPostAuthentication);
161}
162
Nathan Bullockf12f7f02015-02-20 14:46:53 -0500163TEST_F(XmppClientTest, HandleAuthenticationFailedResponse) {
164 TestHelper::SetState(
165 xmpp_client_.get(),
166 XmppClient::XmppState::kAuthenticationStarted);
167 EXPECT_CALL(*connection_, Read(_))
168 .WillOnce(DoAll(SetArgPointee<0>(kAuthenticationFailedResponse),
169 Return(true)));
170 EXPECT_CALL(*connection_, Write(_))
171 .Times(0);
172 xmpp_client_->Read();
173 EXPECT_EQ(TestHelper::GetState(*xmpp_client_),
174 XmppClient::XmppState::kAuthenticationFailed);
175}
176
Nathan Bullockbdabded2015-02-10 20:15:53 -0500177TEST_F(XmppClientTest, HandleStreamRestartedResponse) {
178 TestHelper::SetState(
179 xmpp_client_.get(),
180 XmppClient::XmppState::kStreamRestartedPostAuthentication);
181 EXPECT_CALL(*connection_, Read(_))
182 .WillOnce(DoAll(SetArgPointee<0>(kRestartStreamResponse), Return(true)));
183 EXPECT_CALL(*connection_, Write(kBindMessage))
184 .WillOnce(Return(true));
185 xmpp_client_->Read();
186 EXPECT_EQ(TestHelper::GetState(*xmpp_client_),
187 XmppClient::XmppState::kBindSent);
188}
189
190TEST_F(XmppClientTest, HandleBindResponse) {
191 TestHelper::SetState(xmpp_client_.get(),
192 XmppClient::XmppState::kBindSent);
193 EXPECT_CALL(*connection_, Read(_))
194 .WillOnce(DoAll(SetArgPointee<0>(kBindResponse), Return(true)));
195 EXPECT_CALL(*connection_, Write(kSessionMessage))
196 .WillOnce(Return(true));
197 xmpp_client_->Read();
198 EXPECT_EQ(TestHelper::GetState(*xmpp_client_),
199 XmppClient::XmppState::kSessionStarted);
200}
201
202TEST_F(XmppClientTest, HandleSessionResponse) {
203 TestHelper::SetState(xmpp_client_.get(),
204 XmppClient::XmppState::kSessionStarted);
205 EXPECT_CALL(*connection_, Read(_))
206 .WillOnce(DoAll(SetArgPointee<0>(kSessionResponse), Return(true)));
207 EXPECT_CALL(*connection_, Write(kSubscribeMessage))
208 .WillOnce(Return(true));
209 xmpp_client_->Read();
210 EXPECT_EQ(TestHelper::GetState(*xmpp_client_),
211 XmppClient::XmppState::kSubscribeStarted);
212}
213
214TEST_F(XmppClientTest, HandleSubscribeResponse) {
215 TestHelper::SetState(xmpp_client_.get(),
216 XmppClient::XmppState::kSubscribeStarted);
217 EXPECT_CALL(*connection_, Read(_))
218 .WillOnce(DoAll(SetArgPointee<0>(kSubscribedResponse), Return(true)));
219 EXPECT_CALL(*connection_, Write(_))
220 .Times(0);
221 xmpp_client_->Read();
222 EXPECT_EQ(TestHelper::GetState(*xmpp_client_),
223 XmppClient::XmppState::kSubscribed);
224}
225
226} // namespace buffet