// Copyright (c) 2012 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 "chrome/browser/history/android/sqlite_cursor.h" #include #include "base/android/jni_android.h" #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "chrome/browser/history/android/android_history_provider_service.h" #include "chrome/browser/history/android/android_history_types.h" #include "chrome/browser/history/android/android_time.h" #include "chrome/browser/history/history_service.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/common/chrome_constants.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_browser_thread.h" #include "content/public/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace { using base::Bind; using base::Time; using content::BrowserThread; using history::AndroidStatement; using history::HistoryAndBookmarkRow; using history::SearchRow; // The test cases in this file don't test the JNI interface which will be // covered in Java tests. class SQLiteCursorTest : public testing::Test, public SQLiteCursor::TestObserver { public: SQLiteCursorTest() : profile_manager_( TestingBrowserProcess::GetGlobal()), ui_thread_(BrowserThread::UI, &message_loop_), file_thread_(BrowserThread::FILE, &message_loop_) { } virtual ~SQLiteCursorTest() { } protected: virtual void SetUp() OVERRIDE { // Setup the testing profile, so the bookmark_model_sql_handler could // get the bookmark model from it. ASSERT_TRUE(profile_manager_.SetUp()); // It seems that the name has to be chrome::kInitialProfile, so it // could be found by ProfileManager::GetLastUsedProfile(). testing_profile_ = profile_manager_.CreateTestingProfile( chrome::kInitialProfile); testing_profile_->CreateBookmarkModel(true); ui_test_utils::WaitForBookmarkModelToLoad(testing_profile_); testing_profile_->CreateFaviconService(); ASSERT_TRUE(testing_profile_->CreateHistoryService(true, false)); service_.reset(new AndroidHistoryProviderService(testing_profile_)); hs_ = HistoryServiceFactory::GetForProfile(testing_profile_, Profile::EXPLICIT_ACCESS); } virtual void TearDown() OVERRIDE { testing_profile_->DestroyHistoryService(); profile_manager_.DeleteTestingProfile(chrome::kInitialProfile); testing_profile_ = NULL; } // Override SQLiteCursor::TestObserver. virtual void OnPostMoveToTask() OVERRIDE { base::MessageLoop::current()->Run(); } virtual void OnGetMoveToResult() OVERRIDE { base::MessageLoop::current()->Quit(); } virtual void OnPostGetFaviconTask() OVERRIDE { base::MessageLoop::current()->Run(); } virtual void OnGetFaviconResult() OVERRIDE { base::MessageLoop::current()->Quit(); } protected: TestingProfileManager profile_manager_; base::MessageLoop message_loop_; content::TestBrowserThread ui_thread_; content::TestBrowserThread file_thread_; scoped_ptr service_; CancelableRequestConsumer cancelable_consumer_; TestingProfile* testing_profile_; HistoryService* hs_; private: DISALLOW_COPY_AND_ASSIGN(SQLiteCursorTest); }; class CallbackHelper : public base::RefCountedThreadSafe { public: CallbackHelper() : success_(false), statement_(NULL) { } bool success() const { return success_; } AndroidStatement* statement() const { return statement_; } void OnInserted(AndroidHistoryProviderService::Handle handle, bool success, int64 id) { success_ = success; base::MessageLoop::current()->Quit(); } void OnQueryResult(AndroidHistoryProviderService::Handle handle, bool success, AndroidStatement* statement) { success_ = success; statement_ = statement; base::MessageLoop::current()->Quit(); } private: friend class base::RefCountedThreadSafe; ~CallbackHelper() { } bool success_; AndroidStatement* statement_; DISALLOW_COPY_AND_ASSIGN(CallbackHelper); }; } // namespace TEST_F(SQLiteCursorTest, Run) { HistoryAndBookmarkRow row; row.set_raw_url("http://www.google.com/"); row.set_url(GURL("http://www.google.com/")); std::vector favicon_data; favicon_data.push_back(1); base::RefCountedBytes *data_bytes = base::RefCountedBytes::TakeVector(&favicon_data); row.set_favicon(data_bytes); row.set_last_visit_time(Time::Now()); row.set_visit_count(2); row.set_title(UTF8ToUTF16("cnn")); scoped_refptr callback(new CallbackHelper()); // Insert a row and verify it succeeded. service_->InsertHistoryAndBookmark(row, &cancelable_consumer_, Bind(&CallbackHelper::OnInserted, callback.get())); base::MessageLoop::current()->Run(); EXPECT_TRUE(callback->success()); std::vector projections; projections.push_back(HistoryAndBookmarkRow::URL); projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME); projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT); projections.push_back(HistoryAndBookmarkRow::FAVICON); // Query the inserted row. service_->QueryHistoryAndBookmarks(projections, std::string(), std::vector(), std::string(), &cancelable_consumer_, Bind(&CallbackHelper::OnQueryResult, callback.get())); base::MessageLoop::current()->Run(); ASSERT_TRUE(callback->success()); AndroidStatement* statement = callback->statement(); std::vector column_names; column_names.push_back( HistoryAndBookmarkRow::GetAndroidName(HistoryAndBookmarkRow::URL)); column_names.push_back(HistoryAndBookmarkRow::GetAndroidName( HistoryAndBookmarkRow::LAST_VISIT_TIME)); column_names.push_back(HistoryAndBookmarkRow::GetAndroidName( HistoryAndBookmarkRow::VISIT_COUNT)); column_names.push_back(HistoryAndBookmarkRow::GetAndroidName( HistoryAndBookmarkRow::FAVICON)); FaviconService* favicon_service = new FaviconService(hs_); SQLiteCursor* cursor = new SQLiteCursor(column_names, statement, service_.get(), favicon_service); cursor->set_test_observer(this); JNIEnv* env = base::android::AttachCurrentThread(); EXPECT_EQ(1, cursor->GetCount(env, NULL)); EXPECT_EQ(0, cursor->MoveTo(env, NULL, 0)); EXPECT_EQ(row.url().spec(), base::android::ConvertJavaStringToUTF8( cursor->GetString(env, NULL, 0)).c_str()); EXPECT_EQ(history::ToDatabaseTime(row.last_visit_time()), cursor->GetLong(env, NULL, 1)); EXPECT_EQ(row.visit_count(), cursor->GetInt(env, NULL, 2)); base::android::ScopedJavaLocalRef data = cursor->GetBlob(env, NULL, 3); std::vector out; base::android::JavaByteArrayToByteVector(env, data.obj(), &out); EXPECT_EQ(data_bytes->data().size(), out.size()); EXPECT_EQ(data_bytes->data()[0], out[0]); cursor->Destroy(env, NULL); // Cursor::Destroy posts the task in UI thread, run Message loop to release // the statement, delete SQLiteCursor itself etc. content::RunAllPendingInMessageLoop(); }