• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 <limits>
6 #include <string>
7 
8 #include "app/sql/statement.h"
9 #include "base/file_util.h"
10 #include "base/memory/scoped_temp_dir.h"
11 #include "base/utf_string_conversions.h"
12 #include "build/build_config.h"
13 #include "chrome/browser/password_manager/encryptor.h"
14 #include "chrome/browser/sync/syncable/directory_manager.h"
15 #include "chrome/browser/sync/util/user_settings.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 using std::numeric_limits;
19 
20 namespace {
21 
22 const FilePath::CharType kV10UserSettingsDB[] =
23     FILE_PATH_LITERAL("Version10Settings.sqlite3");
24 const FilePath::CharType kV11UserSettingsDB[] =
25     FILE_PATH_LITERAL("Version11Settings.sqlite3");
26 const FilePath::CharType kOldStyleSyncDataDB[] =
27     FILE_PATH_LITERAL("OldStyleSyncData.sqlite3");
28 
29 }  // namespace
30 
31 class UserSettingsTest : public testing::Test {
32  public:
UserSettingsTest()33   UserSettingsTest() : sync_data_("Some sync data") {}
34 
SetUp()35   virtual void SetUp() {
36 #if defined(OS_MACOSX)
37     // Need to mock the Keychain for unit tests on Mac to avoid possible
38     // blocking UI.  |SetAuthTokenForService| uses Encryptor.
39     Encryptor::UseMockKeychain(true);
40 #endif
41   }
42 
43   // Creates and populates the V10 database files within
44   // |destination_directory|.
SetUpVersion10Databases(const FilePath & destination_directory)45   void SetUpVersion10Databases(const FilePath& destination_directory) {
46     v10_user_setting_db_path_ =
47         destination_directory.Append(FilePath(kV10UserSettingsDB));
48 
49     sql::Connection db;
50     ASSERT_TRUE(db.Open(v10_user_setting_db_path_));
51 
52     old_style_sync_data_path_ =
53         destination_directory.Append(FilePath(kOldStyleSyncDataDB));
54 
55     ASSERT_EQ(sync_data_.length(),
56               static_cast<size_t>(file_util::WriteFile(
57                   old_style_sync_data_path_, sync_data_.data(),
58                   sync_data_.length())));
59 
60     // Create settings table.
61     ASSERT_TRUE(db.Execute(
62         "CREATE TABLE settings (email, key, value,  PRIMARY KEY(email, key)"
63         " ON CONFLICT REPLACE)"));
64 
65     // Add a blank signin table.
66     ASSERT_TRUE(db.Execute(
67         "CREATE TABLE signin_types (signin, signin_type)"));
68 
69     // Create and populate version table.
70     ASSERT_TRUE(db.Execute("CREATE TABLE db_version (version)"));
71     {
72       const char* query = "INSERT INTO db_version VALUES(?)";
73       sql::Statement s(db.GetUniqueStatement(query));
74       if (!s)
75         LOG(FATAL) << query << "\n" << db.GetErrorMessage();
76 
77       s.BindInt(0, 10);
78       if (!s.Run())
79         LOG(FATAL) << query << "\n" << db.GetErrorMessage();
80     }
81 
82     // Create shares table.
83     ASSERT_TRUE(db.Execute(
84         "CREATE TABLE shares (email, share_name, file_name,"
85         " PRIMARY KEY(email, share_name) ON CONFLICT REPLACE)"));
86     // Populate a share.
87     {
88       const char* query = "INSERT INTO shares VALUES(?, ?, ?)";
89       sql::Statement s(db.GetUniqueStatement(query));
90       if (!s)
91         LOG(FATAL) << query << "\n" << db.GetErrorMessage();
92 
93       s.BindString(0, "foo@foo.com");
94       s.BindString(1, "foo@foo.com");
95 #if defined(OS_WIN)
96       s.BindString(2, WideToUTF8(old_style_sync_data_path_.value()));
97 #elif defined(OS_POSIX)
98       s.BindString(2, old_style_sync_data_path_.value());
99 #endif
100       if (!s.Run())
101         LOG(FATAL) << query << "\n" << db.GetErrorMessage();
102     }
103   }
104 
105    // Creates and populates the V11 database file within
106   // |destination_directory|.
SetUpVersion11Database(const FilePath & destination_directory)107   void SetUpVersion11Database(const FilePath& destination_directory) {
108     v11_user_setting_db_path_ =
109         destination_directory.Append(FilePath(kV11UserSettingsDB));
110 
111     sql::Connection db;
112     ASSERT_TRUE(db.Open(v11_user_setting_db_path_));
113 
114     // Create settings table.
115     ASSERT_TRUE(db.Execute(
116         "CREATE TABLE settings (email, key, value, PRIMARY KEY(email, key)"
117         " ON CONFLICT REPLACE)"));
118 
119     // Create and populate version table.
120     ASSERT_TRUE(db.Execute("CREATE TABLE db_version (version)"));
121     {
122       const char* query = "INSERT INTO db_version VALUES(?)";
123       sql::Statement s(db.GetUniqueStatement(query));
124       if (!s)
125         LOG(FATAL) << query << "\n" << db.GetErrorMessage();
126 
127       s.BindInt(0, 11);
128       if (!s.Run())
129         LOG(FATAL) << query << "\n" << db.GetErrorMessage();
130     }
131 
132     ASSERT_TRUE(db.Execute(
133         "CREATE TABLE signin_types (signin, signin_type)"));
134     {
135       const char* query = "INSERT INTO signin_types VALUES(?, ?)";
136       sql::Statement s(db.GetUniqueStatement(query));
137       if (!s)
138         LOG(FATAL) << query << "\n" << db.GetErrorMessage();
139 
140       s.BindString(0, "test");
141       s.BindString(1, "test");
142       if (!s.Run())
143         LOG(FATAL) << query << "\n" << db.GetErrorMessage();
144     }
145   }
146 
sync_data() const147   const std::string& sync_data() const { return sync_data_; }
v10_user_setting_db_path() const148   const FilePath& v10_user_setting_db_path() const {
149     return v10_user_setting_db_path_;
150   }
v11_user_setting_db_path() const151   const FilePath& v11_user_setting_db_path() const {
152     return v11_user_setting_db_path_;
153   }
old_style_sync_data_path() const154   const FilePath& old_style_sync_data_path() const {
155     return old_style_sync_data_path_;
156   }
157 
158  private:
159   FilePath v10_user_setting_db_path_;
160   FilePath old_style_sync_data_path_;
161 
162   FilePath v11_user_setting_db_path_;
163 
164   std::string sync_data_;
165 };
166 
TEST_F(UserSettingsTest,MigrateFromV10ToV11)167 TEST_F(UserSettingsTest, MigrateFromV10ToV11) {
168   ScopedTempDir temp_dir;
169   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
170   SetUpVersion10Databases(temp_dir.path());
171   {
172     // Create a UserSettings, which should trigger migration code. We do this
173     // inside a scoped block so it closes itself and we can poke around to see
174     // what happened later.
175     browser_sync::UserSettings settings;
176     settings.Init(v10_user_setting_db_path());
177   }
178 
179   // Now poke around using sqlite to see if UserSettings migrated properly.
180   sql::Connection db;
181   ASSERT_TRUE(db.Open(v10_user_setting_db_path()));
182 
183   // Note that we don't use ScopedStatement to avoid closing the sqlite handle
184   // before finalizing the statement.
185   {
186     const char* query = "SELECT version FROM db_version";
187     sql::Statement version_query(db.GetUniqueStatement(query));
188     if (!version_query)
189       LOG(FATAL) << query << "\n" << db.GetErrorMessage();
190 
191     ASSERT_TRUE(version_query.Step());
192     const int version = version_query.ColumnInt(0);
193     EXPECT_GE(version, 11);
194   }
195 
196   EXPECT_FALSE(file_util::PathExists(old_style_sync_data_path()));
197 
198   FilePath new_style_path = temp_dir.path().Append(
199       syncable::DirectoryManager::GetSyncDataDatabaseFilename());
200 
201   std::string contents;
202   ASSERT_TRUE(file_util::ReadFileToString(new_style_path, &contents));
203   EXPECT_TRUE(sync_data() == contents);
204 }
205 
TEST_F(UserSettingsTest,MigrateFromV11ToV12)206 TEST_F(UserSettingsTest, MigrateFromV11ToV12) {
207   ScopedTempDir temp_dir;
208   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
209   SetUpVersion11Database(temp_dir.path());
210   {
211     browser_sync::UserSettings settings;
212     settings.Init(v11_user_setting_db_path());
213   }
214   sql::Connection db;
215   ASSERT_TRUE(db.Open(v11_user_setting_db_path()));
216 
217   {
218     const char* query = "SELECT version FROM db_version";
219     sql::Statement version_query(db.GetUniqueStatement(query));
220     if (!version_query)
221       LOG(FATAL) << query << "\n" << db.GetErrorMessage();
222 
223     ASSERT_TRUE(version_query.Step());
224     const int version = version_query.ColumnInt(0);
225     EXPECT_GE(version, 12);
226 
227     const char* query2 = "SELECT name FROM sqlite_master "
228                          "WHERE type='table' AND name='signin_types'";
229     sql::Statement table_query(db.GetUniqueStatement(query2));
230     if (!table_query)
231       LOG(FATAL) << query2 << "\n" << db.GetErrorMessage();
232 
233     ASSERT_FALSE(table_query.Step());
234   }
235 }
236 
TEST_F(UserSettingsTest,APEncode)237 TEST_F(UserSettingsTest, APEncode) {
238   std::string test;
239   char i;
240   for (i = numeric_limits<char>::min(); i < numeric_limits<char>::max(); ++i)
241     test.push_back(i);
242   test.push_back(i);
243   const std::string encoded = browser_sync::APEncode(test);
244   const std::string decoded = browser_sync::APDecode(encoded);
245   ASSERT_EQ(test, decoded);
246 }
247 
TEST_F(UserSettingsTest,PersistEmptyToken)248 TEST_F(UserSettingsTest, PersistEmptyToken) {
249   ScopedTempDir temp_dir;
250   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
251   browser_sync::UserSettings settings;
252   settings.Init(temp_dir.path().AppendASCII("UserSettings.sqlite3"));
253   settings.SetAuthTokenForService("username", "service", "");
254   std::string username;
255   std::string token;
256   ASSERT_TRUE(settings.GetLastUserAndServiceToken("service", &username,
257       &token));
258   EXPECT_EQ("", token);
259   EXPECT_EQ("username", username);
260 }
261 
TEST_F(UserSettingsTest,PersistNonEmptyToken)262 TEST_F(UserSettingsTest, PersistNonEmptyToken) {
263   ScopedTempDir temp_dir;
264   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
265   browser_sync::UserSettings settings;
266   settings.Init(temp_dir.path().AppendASCII("UserSettings.sqlite3"));
267   settings.SetAuthTokenForService("username", "service",
268       "oonetuhasonteuhasonetuhasonetuhasonetuhasouhasonetuhasonetuhasonetuhah"
269       "oonetuhasonteuhasonetuhasonetuhasonetuhasouhasonetuhasonetuhasonetuhah"
270       "oonetuhasonteuhasonetuhasonetuhasonetuhasouhasonetuhasonetuhasonetuhah");
271   std::string username;
272   std::string token;
273   ASSERT_TRUE(settings.GetLastUserAndServiceToken("service", &username,
274       &token));
275   EXPECT_EQ(
276       "oonetuhasonteuhasonetuhasonetuhasonetuhasouhasonetuhasonetuhasonetuhah"
277       "oonetuhasonteuhasonetuhasonetuhasonetuhasouhasonetuhasonetuhasonetuhah"
278       "oonetuhasonteuhasonetuhasonetuhasonetuhasouhasonetuhasonetuhasonetuhah",
279       token);
280   EXPECT_EQ("username", username);
281 }
282