summaryrefslogtreecommitdiffstats
path: root/sync
diff options
context:
space:
mode:
authorpvalenzuela@chromium.org <pvalenzuela@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-03 00:44:52 +0000
committerpvalenzuela@chromium.org <pvalenzuela@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-03 00:44:52 +0000
commit0f02f8a7f5bb9cb99b6323e1901ae6abac593adc (patch)
tree3be482121188c366a46ed81672d931660f608313 /sync
parent583cd380b86cfc3318e11bef2f564e8423983e59 (diff)
downloadchromium_src-0f02f8a7f5bb9cb99b6323e1901ae6abac593adc.zip
chromium_src-0f02f8a7f5bb9cb99b6323e1901ae6abac593adc.tar.gz
chromium_src-0f02f8a7f5bb9cb99b6323e1901ae6abac593adc.tar.bz2
Initial version of Test Accounts service client. This client will
allow Chrome Sync tests to utilize the upcoming Test Accounts service that allows short-term, exclusive access to test accounts for the purpose of testing against real servers. BUG= Review URL: https://chromiumcodereview.appspot.com/14295014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@198019 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sync')
-rw-r--r--sync/sync_tests.gypi41
-rw-r--r--sync/test/accounts_client/test_accounts_client.cc120
-rw-r--r--sync/test/accounts_client/test_accounts_client.h63
-rw-r--r--sync/test/accounts_client/test_accounts_client_unittest.cc95
4 files changed, 319 insertions, 0 deletions
diff --git a/sync/sync_tests.gypi b/sync/sync_tests.gypi
index f7e2b64..b570384 100644
--- a/sync/sync_tests.gypi
+++ b/sync/sync_tests.gypi
@@ -608,5 +608,46 @@
},
],
}],
+ # TODO(pvalenzuela): Remove these OS restrictions when moving end-to-end
+ # tests to other platforms.
+ ['OS != "ios" and OS != "win"', {
+ 'targets': [
+ # Test support files for using the Test Accounts service.
+ {
+ 'target_name': 'test_support_accounts_client',
+ 'type': 'static_library',
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '..',
+ ],
+ },
+ 'dependencies': [
+ '../base/base.gyp:base',
+ ],
+ 'sources': [
+ 'test/accounts_client/test_accounts_client.cc',
+ 'test/accounts_client/test_accounts_client.h',
+ ],
+ 'link_settings': {
+ 'libraries': [ '-lcurl', ],
+ },
+ },
+
+ # The Sync end-to-end (and associated infrastructure) tests.
+ {
+ 'target_name': 'sync_endtoend_tests',
+ 'type': '<(gtest_target_type)',
+ 'dependencies': [
+ '../base/base.gyp:run_all_unittests',
+ '../testing/gmock.gyp:gmock',
+ '../testing/gtest.gyp:gtest',
+ 'test_support_accounts_client',
+ ],
+ 'sources': [
+ 'test/accounts_client/test_accounts_client_unittest.cc',
+ ],
+ },
+ ]
+ }],
],
}
diff --git a/sync/test/accounts_client/test_accounts_client.cc b/sync/test/accounts_client/test_accounts_client.cc
new file mode 100644
index 0000000..9bf82c1
--- /dev/null
+++ b/sync/test/accounts_client/test_accounts_client.cc
@@ -0,0 +1,120 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/test/accounts_client/test_accounts_client.h"
+
+#include <algorithm>
+#include <curl/curl.h>
+#include <string>
+#include <vector>
+
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/stringprintf.h"
+#include "base/values.h"
+
+using std::string;
+using std::vector;
+
+static const int kMaxSessionLifetimeSeconds = 30 * 60;
+static const string kClaimPath = "claim";
+static const string kReleasePath = "release";
+
+AccountSession::AccountSession() {}
+AccountSession::~AccountSession() {}
+
+TestAccountsClient::TestAccountsClient(const string& server,
+ const string& account_space,
+ const vector<string>& usernames)
+ : server_(server), account_space_(account_space), usernames_(usernames) {
+}
+
+TestAccountsClient::~TestAccountsClient() {}
+
+AccountSession TestAccountsClient::ClaimAccount() {
+ string post_fields;
+ base::StringAppendF(&post_fields, "account_space=%s", account_space_.c_str());
+ base::StringAppendF(&post_fields, "&max_lifetime_seconds=%d",
+ kMaxSessionLifetimeSeconds);
+
+ // TODO(pvalenzuela): Select N random usernames instead of all usernames.
+ for (vector<string>::iterator it = usernames_.begin();
+ it != usernames_.end(); ++it) {
+ base::StringAppendF(&post_fields, "&username=%s", it->c_str());
+ }
+
+ string response = SendRequest(kClaimPath, post_fields);
+ scoped_ptr<Value> value(base::JSONReader::Read(response));
+ base::DictionaryValue* dict_value;
+ AccountSession session;
+ if (value != NULL && value->GetAsDictionary(&dict_value) &&
+ dict_value != NULL) {
+ dict_value->GetString("username", &session.username);
+ dict_value->GetString("account_space", &session.account_space);
+ dict_value->GetString("session_id", &session.session_id);
+ dict_value->GetString("expiration_time", &session.expiration_time);
+ } else {
+ session.error = response;
+ }
+ return session;
+}
+
+void TestAccountsClient::ReleaseAccount(const AccountSession& session) {
+ string post_fields;
+ // The expiration_time field is ignored since it isn't passed as part of the
+ // release request.
+ if (session.username.empty() || session.account_space.empty() ||
+ account_space_.compare(session.account_space) != 0 ||
+ session.session_id.empty()) {
+ return;
+ }
+
+ base::StringAppendF(&post_fields, "account_space=%s",
+ session.account_space.c_str());
+ base::StringAppendF(&post_fields, "&username=%s", session.username.c_str());
+ base::StringAppendF(&post_fields, "&session_id=%s",
+ session.session_id.c_str());
+
+ // This operation is best effort, so don't send any errors back to the caller.
+ SendRequest(kReleasePath, post_fields);
+}
+
+namespace {
+int CurlWriteFunction(char* data,
+ size_t size,
+ size_t nmemb,
+ string* write_data) {
+ if (write_data == NULL) {
+ return 0;
+ }
+ write_data->append(data, size * nmemb);
+ return size * nmemb;
+}
+} // namespace
+
+string TestAccountsClient::SendRequest(const string& path,
+ const string& post_fields) {
+ CURLcode res;
+ string response_buffer;
+ char error_buffer[CURL_ERROR_SIZE];
+ CURL* curl = curl_easy_init();
+ if (curl) {
+ string url;
+ base::SStringPrintf(&url, "%s/%s", server_.c_str(), path.c_str());
+ curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+ curl_easy_setopt(curl, CURLOPT_POST, 1L);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_fields.c_str());
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteFunction);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_buffer);
+ curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ if (res != CURLE_OK) {
+ string error(error_buffer);
+ return error;
+ }
+ return response_buffer;
+ }
+ return "There was an error establishing the connection.";
+}
diff --git a/sync/test/accounts_client/test_accounts_client.h b/sync/test/accounts_client/test_accounts_client.h
new file mode 100644
index 0000000..68f2b2e
--- /dev/null
+++ b/sync/test/accounts_client/test_accounts_client.h
@@ -0,0 +1,63 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_TEST_ACCOUNTS_CLIENT_TEST_ACCOUNTS_CLIENT_H_
+#define SYNC_TEST_ACCOUNTS_CLIENT_TEST_ACCOUNTS_CLIENT_H_
+
+#include <curl/curl.h>
+#include <string>
+#include <vector>
+
+using std::string;
+using std::vector;
+
+// The data associated with an account session.
+struct AccountSession {
+ AccountSession();
+ ~AccountSession();
+
+ string username;
+ string account_space;
+ string session_id;
+ string expiration_time;
+
+ // Only set if there was an error.
+ string error;
+};
+
+// A test-side client for the Test Accounts service. This service provides
+// short-term, exclusive access to test accounts for the purpose of testing
+// against real Chrome Sync servers.
+class TestAccountsClient {
+ public:
+ // Creates a client associated with the given |server| URL (e.g.,
+ // http://service-runs-here.com), |account_space| (for account segregation),
+ // and |usernames| (the collection of accounts to be chosen from).
+ TestAccountsClient(const string& server,
+ const string& account_space,
+ const vector<string>& usernames);
+
+ virtual ~TestAccountsClient();
+
+ // Attempts to claim an account via the Test Accounts service. If
+ // successful, an AccountSession is returned containing the data associated
+ // with the session. If an error occurred, then the AccountSession will only
+ // have its error field set.
+ AccountSession ClaimAccount();
+
+ // Attempts to release an account via the Test Accounts service. The value
+ // of |session| should be one returned from ClaimAccount(). This function
+ // is best-effort and fails silently.
+ void ReleaseAccount(const AccountSession& session);
+
+ // Sends an HTTP POST request to the Test Accounts service.
+ virtual string SendRequest(const string& path, const string& post_fields);
+
+ private:
+ const string server_;
+ const string account_space_;
+ vector<string> usernames_;
+};
+
+#endif // SYNC_TEST_ACCOUNTS_CLIENT_TEST_ACCOUNTS_CLIENT_H_
diff --git a/sync/test/accounts_client/test_accounts_client_unittest.cc b/sync/test/accounts_client/test_accounts_client_unittest.cc
new file mode 100644
index 0000000..f70eab9
--- /dev/null
+++ b/sync/test/accounts_client/test_accounts_client_unittest.cc
@@ -0,0 +1,95 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "sync/test/accounts_client/test_accounts_client.cc"
+#include "sync/test/accounts_client/test_accounts_client.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::string;
+using std::vector;
+using testing::_;
+using testing::HasSubstr;
+using testing::Return;
+
+namespace {
+static const string kServer = "https://test-account-service";
+static const string kUsername = "foobar@baz.com";
+static const string kAccountSpace = "test_account_space";
+static const string kSessionId = "1234-ABCD";
+static const string kExpirationTime = "12:00";
+} // namespace
+
+static AccountSession CreateValidAccountSession() {
+ AccountSession session;
+ session.username = kUsername;
+ session.account_space = kAccountSpace;
+ session.session_id = kSessionId;
+ session.expiration_time = kExpirationTime;
+ return session;
+}
+
+class NoNetworkTestAccountsClient : public TestAccountsClient {
+ public:
+ NoNetworkTestAccountsClient(const string& server,
+ const string& account_space,
+ vector<string> usernames)
+ : TestAccountsClient(server, account_space, usernames) {}
+ MOCK_METHOD2(SendRequest,
+ string(const string&, const string&));
+};
+
+TEST(TestAccountsClientTest, ClaimAccountError) {
+ vector<string> usernames;
+ NoNetworkTestAccountsClient client(kServer, kAccountSpace, usernames);
+ string error_response = "error!!!";
+ EXPECT_CALL(client, SendRequest(kClaimPath, _))
+ .WillOnce(Return(error_response));
+ AccountSession session = client.ClaimAccount();
+ EXPECT_EQ(error_response, session.error);
+}
+
+TEST(TestAccountsClientTest, ClaimAccountSuccess) {
+ vector<string> usernames;
+ usernames.push_back("foo0@gmail.com");
+ usernames.push_back("foo1@gmail.com");
+ usernames.push_back("foo2@gmail.com");
+ NoNetworkTestAccountsClient client(kServer, kAccountSpace, usernames);
+ string success_response;
+ base::StringAppendF(&success_response, "{ \"username\":\"%s\",",
+ kUsername.c_str());
+ base::StringAppendF(&success_response, "\"account_space\":\"%s\",",
+ kAccountSpace.c_str());
+ base::StringAppendF(&success_response, "\"session_id\":\"%s\",",
+ kSessionId.c_str());
+ base::StringAppendF(&success_response, "\"expiration_time\":\"%s\"}",
+ kExpirationTime.c_str());
+ EXPECT_CALL(client, SendRequest(kClaimPath, _))
+ .WillOnce(Return(success_response));
+ AccountSession session = client.ClaimAccount();
+ EXPECT_EQ(kUsername, session.username);
+ EXPECT_EQ(kAccountSpace, session.account_space);
+ EXPECT_EQ(kSessionId, session.session_id);
+ EXPECT_EQ(kExpirationTime, session.expiration_time);
+}
+
+TEST(TestAccountsClientTest, ReleaseAccountEmptySession) {
+ vector<string> usernames;
+ NoNetworkTestAccountsClient client(kServer, kAccountSpace, usernames);
+ AccountSession session;
+ // No expectation for SendRequest is made because no network call should be
+ // performed in this scenario.
+ client.ReleaseAccount(session);
+}
+
+TEST(TestAccountsClientTest, ReleaseAccountSuccess) {
+ vector<string> usernames;
+ NoNetworkTestAccountsClient client(kServer, kAccountSpace, usernames);
+ EXPECT_CALL(client, SendRequest(kReleasePath, _))
+ .WillOnce(Return(""));
+ AccountSession session = CreateValidAccountSession();
+ client.ReleaseAccount(session);
+}