1// Copyright 2013 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 "base/files/file_util.h" 6#include "base/files/scoped_temp_dir.h" 7#include "base/message_loop/message_loop.h" 8#include "base/run_loop.h" 9#include "chrome/browser/extensions/api/image_writer_private/error_messages.h" 10#include "chrome/browser/extensions/api/image_writer_private/operation.h" 11#include "chrome/browser/extensions/api/image_writer_private/operation_manager.h" 12#include "chrome/browser/extensions/api/image_writer_private/test_utils.h" 13#include "chrome/test/base/testing_profile.h" 14#include "content/public/browser/browser_thread.h" 15#include "content/public/test/test_browser_thread_bundle.h" 16#include "testing/gmock/include/gmock/gmock.h" 17#include "testing/gtest/include/gtest/gtest.h" 18#include "third_party/zlib/google/zip.h" 19 20namespace extensions { 21namespace image_writer { 22 23namespace { 24 25using testing::_; 26using testing::AnyNumber; 27using testing::AtLeast; 28using testing::Gt; 29using testing::Lt; 30 31// This class gives us a generic Operation with the ability to set or inspect 32// the current path to the image file. 33class OperationForTest : public Operation { 34 public: 35 OperationForTest(base::WeakPtr<OperationManager> manager_, 36 const ExtensionId& extension_id, 37 const std::string& device_path) 38 : Operation(manager_, extension_id, device_path) {} 39 40 virtual void StartImpl() OVERRIDE {} 41 42 // Expose internal stages for testing. 43 void Unzip(const base::Closure& continuation) { 44 Operation::Unzip(continuation); 45 } 46 47 void Write(const base::Closure& continuation) { 48 Operation::Write(continuation); 49 } 50 51 void VerifyWrite(const base::Closure& continuation) { 52 Operation::VerifyWrite(continuation); 53 } 54 55 // Helpers to set-up state for intermediate stages. 56 void SetImagePath(const base::FilePath image_path) { 57 image_path_ = image_path; 58 } 59 60 base::FilePath GetImagePath() { return image_path_; } 61 62 private: 63 virtual ~OperationForTest() {}; 64}; 65 66class ImageWriterOperationTest : public ImageWriterUnitTestBase { 67 protected: 68 ImageWriterOperationTest() 69 : profile_(new TestingProfile), manager_(profile_.get()) {} 70 virtual void SetUp() OVERRIDE { 71 ImageWriterUnitTestBase::SetUp(); 72 73 // Create the zip file. 74 base::FilePath image_dir = test_utils_.GetTempDir().AppendASCII("zip"); 75 ASSERT_TRUE(base::CreateDirectory(image_dir)); 76 ASSERT_TRUE(base::CreateTemporaryFileInDir(image_dir, &image_path_)); 77 78 test_utils_.FillFile(image_path_, kImagePattern, kTestFileSize); 79 80 zip_file_ = test_utils_.GetTempDir().AppendASCII("test_image.zip"); 81 ASSERT_TRUE(zip::Zip(image_dir, zip_file_, true)); 82 83 // Operation setup. 84 operation_ = 85 new OperationForTest(manager_.AsWeakPtr(), 86 kDummyExtensionId, 87 test_utils_.GetDevicePath().AsUTF8Unsafe()); 88 operation_->SetImagePath(test_utils_.GetImagePath()); 89 } 90 91 virtual void TearDown() OVERRIDE { 92 // Ensure all callbacks have been destroyed and cleanup occurs. 93 operation_->Cancel(); 94 95 ImageWriterUnitTestBase::TearDown(); 96 } 97 98 base::FilePath image_path_; 99 base::FilePath zip_file_; 100 101 scoped_ptr<TestingProfile> profile_; 102 103 MockOperationManager manager_; 104 scoped_refptr<OperationForTest> operation_; 105}; 106 107} // namespace 108 109// Unizpping a non-zip should do nothing. 110TEST_F(ImageWriterOperationTest, UnzipNonZipFile) { 111 EXPECT_CALL(manager_, OnProgress(kDummyExtensionId, _, _)).Times(0); 112 113 EXPECT_CALL(manager_, OnError(kDummyExtensionId, _, _, _)).Times(0); 114 EXPECT_CALL(manager_, OnProgress(kDummyExtensionId, _, _)).Times(0); 115 EXPECT_CALL(manager_, OnComplete(kDummyExtensionId)).Times(0); 116 117 operation_->Start(); 118 content::BrowserThread::PostTask( 119 content::BrowserThread::FILE, 120 FROM_HERE, 121 base::Bind( 122 &OperationForTest::Unzip, operation_, base::Bind(&base::DoNothing))); 123 124 base::RunLoop().RunUntilIdle(); 125} 126 127TEST_F(ImageWriterOperationTest, UnzipZipFile) { 128 EXPECT_CALL(manager_, OnError(kDummyExtensionId, _, _, _)).Times(0); 129 EXPECT_CALL(manager_, 130 OnProgress(kDummyExtensionId, image_writer_api::STAGE_UNZIP, _)) 131 .Times(AtLeast(1)); 132 EXPECT_CALL(manager_, 133 OnProgress(kDummyExtensionId, image_writer_api::STAGE_UNZIP, 0)) 134 .Times(AtLeast(1)); 135 EXPECT_CALL(manager_, 136 OnProgress(kDummyExtensionId, image_writer_api::STAGE_UNZIP, 100)) 137 .Times(AtLeast(1)); 138 139 operation_->SetImagePath(zip_file_); 140 141 operation_->Start(); 142 content::BrowserThread::PostTask( 143 content::BrowserThread::FILE, 144 FROM_HERE, 145 base::Bind( 146 &OperationForTest::Unzip, operation_, base::Bind(&base::DoNothing))); 147 148 base::RunLoop().RunUntilIdle(); 149 150 EXPECT_TRUE(base::ContentsEqual(image_path_, operation_->GetImagePath())); 151} 152 153#if defined(OS_LINUX) 154TEST_F(ImageWriterOperationTest, WriteImageToDevice) { 155 EXPECT_CALL(manager_, OnError(kDummyExtensionId, _, _, _)).Times(0); 156 EXPECT_CALL(manager_, 157 OnProgress(kDummyExtensionId, image_writer_api::STAGE_WRITE, _)) 158 .Times(AtLeast(1)); 159 EXPECT_CALL(manager_, 160 OnProgress(kDummyExtensionId, image_writer_api::STAGE_WRITE, 0)) 161 .Times(AtLeast(1)); 162 EXPECT_CALL(manager_, 163 OnProgress(kDummyExtensionId, image_writer_api::STAGE_WRITE, 100)) 164 .Times(AtLeast(1)); 165 166 operation_->Start(); 167 content::BrowserThread::PostTask( 168 content::BrowserThread::FILE, 169 FROM_HERE, 170 base::Bind( 171 &OperationForTest::Write, operation_, base::Bind(&base::DoNothing))); 172 173 base::RunLoop().RunUntilIdle(); 174 175#if !defined(OS_CHROMEOS) 176 test_utils_.GetUtilityClient()->Progress(0); 177 test_utils_.GetUtilityClient()->Progress(kTestFileSize / 2); 178 test_utils_.GetUtilityClient()->Progress(kTestFileSize); 179 test_utils_.GetUtilityClient()->Success(); 180 181 base::RunLoop().RunUntilIdle(); 182#endif 183} 184#endif 185 186#if !defined(OS_CHROMEOS) 187// Chrome OS doesn't support verification in the ImageBurner, so these two tests 188// are skipped. 189 190TEST_F(ImageWriterOperationTest, VerifyFileSuccess) { 191 EXPECT_CALL(manager_, OnError(kDummyExtensionId, _, _, _)).Times(0); 192 EXPECT_CALL( 193 manager_, 194 OnProgress(kDummyExtensionId, image_writer_api::STAGE_VERIFYWRITE, _)) 195 .Times(AtLeast(1)); 196 EXPECT_CALL( 197 manager_, 198 OnProgress(kDummyExtensionId, image_writer_api::STAGE_VERIFYWRITE, 0)) 199 .Times(AtLeast(1)); 200 EXPECT_CALL( 201 manager_, 202 OnProgress(kDummyExtensionId, image_writer_api::STAGE_VERIFYWRITE, 100)) 203 .Times(AtLeast(1)); 204 205 test_utils_.FillFile( 206 test_utils_.GetDevicePath(), kImagePattern, kTestFileSize); 207 208 operation_->Start(); 209 content::BrowserThread::PostTask(content::BrowserThread::FILE, 210 FROM_HERE, 211 base::Bind(&OperationForTest::VerifyWrite, 212 operation_, 213 base::Bind(&base::DoNothing))); 214 215 base::RunLoop().RunUntilIdle(); 216 217#if !defined(OS_CHROMEOS) 218 test_utils_.GetUtilityClient()->Progress(0); 219 test_utils_.GetUtilityClient()->Progress(kTestFileSize / 2); 220 test_utils_.GetUtilityClient()->Progress(kTestFileSize); 221 test_utils_.GetUtilityClient()->Success(); 222#endif 223 224 base::RunLoop().RunUntilIdle(); 225} 226 227TEST_F(ImageWriterOperationTest, VerifyFileFailure) { 228 EXPECT_CALL( 229 manager_, 230 OnProgress(kDummyExtensionId, image_writer_api::STAGE_VERIFYWRITE, _)) 231 .Times(AnyNumber()); 232 EXPECT_CALL( 233 manager_, 234 OnProgress(kDummyExtensionId, image_writer_api::STAGE_VERIFYWRITE, 100)) 235 .Times(0); 236 EXPECT_CALL(manager_, OnComplete(kDummyExtensionId)).Times(0); 237 EXPECT_CALL( 238 manager_, 239 OnError(kDummyExtensionId, image_writer_api::STAGE_VERIFYWRITE, _, _)) 240 .Times(1); 241 242 test_utils_.FillFile( 243 test_utils_.GetDevicePath(), kDevicePattern, kTestFileSize); 244 245 operation_->Start(); 246 content::BrowserThread::PostTask(content::BrowserThread::FILE, 247 FROM_HERE, 248 base::Bind(&OperationForTest::VerifyWrite, 249 operation_, 250 base::Bind(&base::DoNothing))); 251 252 base::RunLoop().RunUntilIdle(); 253 254 test_utils_.GetUtilityClient()->Progress(0); 255 test_utils_.GetUtilityClient()->Progress(kTestFileSize / 2); 256 test_utils_.GetUtilityClient()->Error(error::kVerificationFailed); 257 258 base::RunLoop().RunUntilIdle(); 259} 260#endif 261 262// Tests that on creation the operation_ has the expected state. 263TEST_F(ImageWriterOperationTest, Creation) { 264 EXPECT_EQ(0, operation_->GetProgress()); 265 EXPECT_EQ(image_writer_api::STAGE_UNKNOWN, operation_->GetStage()); 266} 267 268} // namespace image_writer 269} // namespace extensions 270