1// Copyright 2014 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 <string>
6
7#include "base/files/file_util.h"
8#include "base/files/scoped_temp_dir.h"
9#include "base/run_loop.h"
10#include "chrome/utility/image_writer/error_messages.h"
11#include "chrome/utility/image_writer/image_writer.h"
12#include "chrome/utility/image_writer/image_writer_handler.h"
13#include "testing/gmock/include/gmock/gmock.h"
14#include "testing/gtest/include/gtest/gtest.h"
15
16namespace image_writer {
17
18using testing::_;
19using testing::AnyNumber;
20using testing::AtLeast;
21using testing::Lt;
22
23namespace {
24
25const int64 kTestFileSize = 1 << 15;  // 32 kB
26const int kTestPattern = 0x55555555;
27
28class ImageWriterUtilityTest : public testing::Test {
29 protected:
30  virtual void SetUp() OVERRIDE {
31    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
32    ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &image_path_));
33    ASSERT_TRUE(
34        base::CreateTemporaryFileInDir(temp_dir_.path(), &device_path_));
35  }
36
37  virtual void TearDown() OVERRIDE {}
38
39  void FillFile(const base::FilePath& path, int pattern) {
40    scoped_ptr<char[]> buffer(new char[kTestFileSize]);
41    memset(buffer.get(), pattern, kTestFileSize);
42
43    ASSERT_TRUE(base::WriteFile(path, buffer.get(), kTestFileSize));
44  }
45
46  void FillDefault(const base::FilePath& path) { FillFile(path, kTestPattern); }
47
48  base::FilePath image_path_;
49  base::FilePath device_path_;
50
51 private:
52  base::MessageLoop message_loop_;
53  base::ScopedTempDir temp_dir_;
54};
55
56class MockHandler : public ImageWriterHandler {
57 public:
58  MOCK_METHOD1(SendProgress, void(int64));
59  MOCK_METHOD1(SendFailed, void(const std::string& message));
60  MOCK_METHOD0(SendSucceeded, void());
61  MOCK_METHOD1(OnMessageReceived, bool(const IPC::Message& message));
62};
63
64// This Mock has the additional feature that it will start verification when
65// the write completes.
66class VerifyingHandler : public MockHandler {
67 public:
68  VerifyingHandler() : image_writer_(NULL), verified_(false) {}
69
70  virtual void SendSucceeded() OVERRIDE {
71    MockHandler::SendSucceeded();
72    if (!verified_) {
73      image_writer_->Verify();
74      verified_ = true;
75    }
76  }
77  ImageWriter* image_writer_;
78
79 private:
80  bool verified_;
81};
82
83}  // namespace
84
85TEST_F(ImageWriterUtilityTest, Getters) {
86  MockHandler mock_handler;
87  ImageWriter image_writer(&mock_handler, image_path_, device_path_);
88
89  EXPECT_EQ(image_path_, image_writer.GetImagePath());
90  EXPECT_EQ(device_path_, image_writer.GetDevicePath());
91}
92
93TEST_F(ImageWriterUtilityTest, WriteSuccessful) {
94  MockHandler mock_handler;
95  ImageWriter image_writer(&mock_handler, image_path_, device_path_);
96
97  EXPECT_CALL(mock_handler, SendProgress(_)).Times(AnyNumber());
98  EXPECT_CALL(mock_handler, SendProgress(kTestFileSize)).Times(1);
99  EXPECT_CALL(mock_handler, SendProgress(0)).Times(1);
100  EXPECT_CALL(mock_handler, SendSucceeded()).Times(1);
101  EXPECT_CALL(mock_handler, SendFailed(_)).Times(0);
102
103  FillDefault(image_path_);
104  image_writer.Write();
105  base::RunLoop().RunUntilIdle();
106}
107
108TEST_F(ImageWriterUtilityTest, WriteInvalidImageFile) {
109  MockHandler mock_handler;
110  ImageWriter image_writer(&mock_handler, image_path_, device_path_);
111
112  EXPECT_CALL(mock_handler, SendProgress(_)).Times(0);
113  EXPECT_CALL(mock_handler, SendSucceeded()).Times(0);
114  EXPECT_CALL(mock_handler, SendFailed(error::kOpenImage)).Times(1);
115
116  ASSERT_TRUE(base::DeleteFile(image_path_, false));
117  image_writer.Write();
118  base::RunLoop().RunUntilIdle();
119}
120
121TEST_F(ImageWriterUtilityTest, WriteInvalidDeviceFile) {
122  MockHandler mock_handler;
123  ImageWriter image_writer(&mock_handler, image_path_, device_path_);
124
125  EXPECT_CALL(mock_handler, SendProgress(_)).Times(0);
126  EXPECT_CALL(mock_handler, SendSucceeded()).Times(0);
127  EXPECT_CALL(mock_handler, SendFailed(error::kOpenDevice)).Times(1);
128
129  ASSERT_TRUE(base::DeleteFile(device_path_, false));
130  image_writer.Write();
131  base::RunLoop().RunUntilIdle();
132}
133
134TEST_F(ImageWriterUtilityTest, VerifySuccessful) {
135  MockHandler mock_handler;
136  ImageWriter image_writer(&mock_handler, image_path_, device_path_);
137
138  EXPECT_CALL(mock_handler, SendProgress(_)).Times(AnyNumber());
139  EXPECT_CALL(mock_handler, SendProgress(kTestFileSize)).Times(1);
140  EXPECT_CALL(mock_handler, SendProgress(0)).Times(1);
141  EXPECT_CALL(mock_handler, SendSucceeded()).Times(1);
142  EXPECT_CALL(mock_handler, SendFailed(_)).Times(0);
143
144  FillDefault(image_path_);
145  FillDefault(device_path_);
146
147  image_writer.Verify();
148
149  base::RunLoop().RunUntilIdle();
150}
151
152TEST_F(ImageWriterUtilityTest, VerifyInvalidImageFile) {
153  MockHandler mock_handler;
154  ImageWriter image_writer(&mock_handler, image_path_, device_path_);
155
156  EXPECT_CALL(mock_handler, SendProgress(_)).Times(0);
157  EXPECT_CALL(mock_handler, SendSucceeded()).Times(0);
158  EXPECT_CALL(mock_handler, SendFailed(error::kOpenImage)).Times(1);
159
160  ASSERT_TRUE(base::DeleteFile(image_path_, false));
161
162  image_writer.Verify();
163
164  base::RunLoop().RunUntilIdle();
165}
166
167TEST_F(ImageWriterUtilityTest, VerifyInvalidDeviceFile) {
168  MockHandler mock_handler;
169  ImageWriter image_writer(&mock_handler, image_path_, device_path_);
170
171  EXPECT_CALL(mock_handler, SendProgress(_)).Times(0);
172  EXPECT_CALL(mock_handler, SendSucceeded()).Times(0);
173  EXPECT_CALL(mock_handler, SendFailed(error::kOpenDevice)).Times(1);
174
175  ASSERT_TRUE(base::DeleteFile(device_path_, false));
176
177  image_writer.Verify();
178
179  base::RunLoop().RunUntilIdle();
180}
181
182TEST_F(ImageWriterUtilityTest, VerifyEmptyDevice) {
183  MockHandler mock_handler;
184  ImageWriter image_writer(&mock_handler, image_path_, device_path_);
185
186  EXPECT_CALL(mock_handler, SendProgress(_)).Times(AnyNumber());
187  EXPECT_CALL(mock_handler, SendSucceeded()).Times(0);
188  EXPECT_CALL(mock_handler, SendFailed(error::kReadDevice)).Times(1);
189
190  FillDefault(image_path_);
191  image_writer.Verify();
192
193  base::RunLoop().RunUntilIdle();
194}
195
196TEST_F(ImageWriterUtilityTest, VerifyFailed) {
197  MockHandler mock_handler;
198  ImageWriter image_writer(&mock_handler, image_path_, device_path_);
199
200  EXPECT_CALL(mock_handler, SendProgress(_)).Times(AnyNumber());
201  EXPECT_CALL(mock_handler, SendSucceeded()).Times(0);
202  EXPECT_CALL(mock_handler, SendFailed(error::kVerificationFailed)).Times(1);
203
204  FillDefault(image_path_);
205  FillFile(device_path_, ~kTestPattern);
206  image_writer.Verify();
207
208  base::RunLoop().RunUntilIdle();
209}
210
211TEST_F(ImageWriterUtilityTest, WriteWithVerifySuccessful) {
212  VerifyingHandler mock_handler;
213  ImageWriter image_writer(&mock_handler, image_path_, device_path_);
214
215  mock_handler.image_writer_ = &image_writer;
216
217  EXPECT_CALL(mock_handler, SendProgress(_)).Times(AnyNumber());
218  EXPECT_CALL(mock_handler, SendProgress(kTestFileSize)).Times(2);
219  EXPECT_CALL(mock_handler, SendProgress(0)).Times(2);
220  EXPECT_CALL(mock_handler, SendSucceeded()).Times(2);
221  EXPECT_CALL(mock_handler, SendFailed(_)).Times(0);
222
223  FillDefault(image_path_);
224
225  image_writer.Write();
226
227  base::RunLoop().RunUntilIdle();
228}
229
230}  // namespace image_writer
231