103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo// Copyright 2015 The Chromium OS Authors. All rights reserved.
203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo// Use of this source code is governed by a BSD-style license that can be
303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo// found in the LICENSE file.
403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
5ddf9db52938e67d4dcbf7c4f159b094eaddbabebAlex Deymo#include "bsdiff/extents_file.h"
603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include <gtest/gtest.h>
803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include <gmock/gmock.h>
903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include <string>
1003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include <vector>
1103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
12ddf9db52938e67d4dcbf7c4f159b094eaddbabebAlex Deymo#include "bsdiff/file_interface.h"
1303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
1403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymousing std::string;
1503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymousing std::vector;
1603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymousing testing::AnyNumber;
1703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymousing testing::StrictMock;
1803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymousing testing::Return;
1903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymousing testing::InSequence;
2003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymousing testing::_;
2103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
2203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymonamespace bsdiff {
2303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
2403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo// Mock class for the underlying file interface.
2503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymoclass MockFile : public FileInterface {
2603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo public:
2703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  MOCK_METHOD3(Read, bool(void*, size_t, size_t*));
2803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  MOCK_METHOD3(Write, bool(const void*, size_t, size_t*));
2903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  MOCK_METHOD1(Seek, bool(off_t));
3003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  MOCK_METHOD0(Close, bool());
31daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo  MOCK_METHOD1(GetSize, bool(uint64_t*));
3203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo};
3303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
3403f1debab429e673ba5e9e317c5a04e36e850cefAlex DeymoACTION(SucceedIO) {
3503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  // Check that arg1 (count) can be converted
3603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  *arg2 = arg1;
3703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  return true;
3803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo}
3903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
4003f1debab429e673ba5e9e317c5a04e36e850cefAlex DeymoACTION_P(SucceedPartialIO, bytes) {
4103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  // Check that arg1 (count) can be converted
4203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  *arg2 = bytes;
4303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  return true;
4403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo}
4503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
4603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymoclass ExtentsFileTest : public testing::Test {
4703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo protected:
4803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  void SetUp() {
4903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo    mock_file_ = new StrictMock<MockFile>();
5003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo    mock_file_ptr_.reset(mock_file_);
5103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo    // The destructor of the ExtentsFile will call Close once.
5203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo    EXPECT_CALL(*mock_file_, Close()).WillOnce(Return(true));
5303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  }
5403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
5503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  // Pointer to the underlying File owned by the ExtentsFile under test. This
5603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  // pointer is invalidated whenever the ExtentsFile is destroyed.
5703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  StrictMock<MockFile>* mock_file_;
5803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  std::unique_ptr<FileInterface> mock_file_ptr_;
5903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo};
6003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
6103f1debab429e673ba5e9e317c5a04e36e850cefAlex DeymoTEST_F(ExtentsFileTest, DestructorCloses) {
6203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  ExtentsFile file(std::move(mock_file_ptr_), {});
6303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo}
6403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
6503f1debab429e673ba5e9e317c5a04e36e850cefAlex DeymoTEST_F(ExtentsFileTest, CloseIsForwarded) {
6603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  ExtentsFile file(std::move(mock_file_ptr_), {});
6703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_TRUE(file.Close());
6803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Close()).WillOnce(Return(false));
6903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo}
7003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
71daf35169e3fa51cc9ff468f12acd435a9b075266Alex DeymoTEST_F(ExtentsFileTest, GetSizeSumExtents) {
72daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo  ExtentsFile file(std::move(mock_file_ptr_),
73daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo                   {ex_t{10, 5}, ex_t{20, 5}, {25, 2}});
74daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo  uint64_t size;
75daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo  EXPECT_TRUE(file.GetSize(&size));
76daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo  EXPECT_EQ(12U, size);
77daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo}
78daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo
7903f1debab429e673ba5e9e317c5a04e36e850cefAlex DeymoTEST_F(ExtentsFileTest, SeekToRightOffsets) {
8003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  ExtentsFile file(std::move(mock_file_ptr_),
8103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo                   {ex_t{10, 5}, ex_t{20, 5}, {25, 2}});
8203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  vector<std::pair<off_t, off_t>> tests = {
8303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo      // Seek to the beginning of the file.
8403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo      {0, 10},
8503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo      // Seek to the middle of a extent.
8603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo      {3, 13},
8703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo      {11, 26},
8803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo      // Seek to the extent boundary.
8903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo      {5, 20},  // Seeks to the first byte in the second extent.
9003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo      {10, 25},
9103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  };
9203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  for (const auto& offset_pair : tests) {
9303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo    // We use a failing Read() call to trigger the actual seek call to the
9403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo    // underlying file.
9503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo    EXPECT_CALL(*mock_file_, Seek(offset_pair.second)).WillOnce(Return(true));
9603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo    EXPECT_CALL(*mock_file_, Read(_, _, _)).WillOnce(Return(false));
9703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
9803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo    EXPECT_TRUE(file.Seek(offset_pair.first));
9903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo    size_t bytes_read;
10003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo    EXPECT_FALSE(file.Read(nullptr, 1, &bytes_read));
10103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  }
10203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
10303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  // Seeking to the end of the file is ok, but not past it.
10403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_TRUE(file.Seek(12));
10503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_FALSE(file.Seek(13));
10603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
10703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_FALSE(file.Seek(-1));
10803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo}
10903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
11003f1debab429e673ba5e9e317c5a04e36e850cefAlex DeymoTEST_F(ExtentsFileTest, ReadAcrossAllExtents) {
11103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  ExtentsFile file(std::move(mock_file_ptr_),
11203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo                   {ex_t{10, 5}, ex_t{20, 7}, {27, 3}});
11303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  InSequence s;
11403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  char* buf = reinterpret_cast<char*>(0x1234);
11503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
11603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Seek(10)).WillOnce(Return(true));
11703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Read(buf, 5, _)).WillOnce(SucceedIO());
11803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Seek(20)).WillOnce(Return(true));
11903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Read(buf + 5, 7, _)).WillOnce(SucceedIO());
12003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Seek(27)).WillOnce(Return(true));
12103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Read(buf + 12, 3, _)).WillOnce(SucceedIO());
12203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
12303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  // FileExtents::Read() should read everything in one shot, by reading all
12403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  // the little chunks. Note that it doesn't attempt to read past the end of the
12503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  // FileExtents.
12603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  size_t bytes_read = 0;
12703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_TRUE(file.Read(buf, 100, &bytes_read));
12803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_EQ(15U, bytes_read);
12903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo}
13003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
131f822e6c031de113b790d622b0cd0e98f7d49ea5eSen JiangTEST_F(ExtentsFileTest, MultiReadAcrossAllExtents) {
132f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  ExtentsFile file(std::move(mock_file_ptr_),
133f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang                   {ex_t{10, 5}, ex_t{20, 7}, {27, 3}});
134f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  InSequence s;
135f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  char* buf = reinterpret_cast<char*>(0x1234);
136f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang
137f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_CALL(*mock_file_, Seek(10)).WillOnce(Return(true));
138f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_CALL(*mock_file_, Read(buf, 2, _)).WillOnce(SucceedIO());
139f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_CALL(*mock_file_, Seek(12)).WillOnce(Return(true));
140f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_CALL(*mock_file_, Read(buf, 3, _)).WillOnce(SucceedIO());
141f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_CALL(*mock_file_, Seek(20)).WillOnce(Return(true));
142f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_CALL(*mock_file_, Read(buf + 3, 5, _)).WillOnce(SucceedIO());
143f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_CALL(*mock_file_, Seek(25)).WillOnce(Return(true));
144f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_CALL(*mock_file_, Read(buf, 2, _)).WillOnce(SucceedIO());
145f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_CALL(*mock_file_, Seek(27)).WillOnce(Return(true));
146f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_CALL(*mock_file_, Read(buf + 2, 3, _)).WillOnce(SucceedIO());
147f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang
148f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  size_t bytes_read = 0;
149f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_TRUE(file.Read(buf, 2, &bytes_read));
150f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_EQ(2U, bytes_read);
151f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_TRUE(file.Read(buf, 8, &bytes_read));
152f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_EQ(8U, bytes_read);
153f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_TRUE(file.Read(buf, 100, &bytes_read));
154f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang  EXPECT_EQ(5U, bytes_read);
155f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang}
156f822e6c031de113b790d622b0cd0e98f7d49ea5eSen Jiang
15703f1debab429e673ba5e9e317c5a04e36e850cefAlex DeymoTEST_F(ExtentsFileTest, ReadSmallChunks) {
15803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  ExtentsFile file(std::move(mock_file_ptr_), {ex_t{10, 1}, ex_t{20, 10}});
15903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  InSequence s;
16003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  char* buf = reinterpret_cast<char*>(0x1234);
16103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
16203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Seek(10)).WillOnce(Return(true));
16303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Read(buf, 1, _)).WillOnce(SucceedIO());
16403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Seek(20)).WillOnce(Return(true));
16503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  // We expect to read only part of the second extent.
16603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Read(buf + 1, 1, _)).WillOnce(SucceedIO());
16703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
16803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  size_t bytes_read = 0;
16903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_TRUE(file.Read(buf, 2, &bytes_read));
17003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_EQ(2U, bytes_read);
17103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo}
17203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
17303f1debab429e673ba5e9e317c5a04e36e850cefAlex DeymoTEST_F(ExtentsFileTest, ReadFailureFails) {
17403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  ExtentsFile file(std::move(mock_file_ptr_), {ex_t{10, 1}, ex_t{20, 10}});
17503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Seek(_))
17603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo      .Times(AnyNumber())
17703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo      .WillRepeatedly(Return(true));
17803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Read(_, 1, _)).WillOnce(SucceedIO());
17903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  // A second read that fails will succeed if there was partial data read.
18003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Read(_, 10, _)).WillOnce(Return(false));
18103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
18203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  size_t bytes_read = 0;
18303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_TRUE(file.Read(nullptr, 100, &bytes_read));
18403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_EQ(1U, bytes_read);
18503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo}
18603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
18703f1debab429e673ba5e9e317c5a04e36e850cefAlex DeymoTEST_F(ExtentsFileTest, ReadFails) {
18803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  ExtentsFile file(std::move(mock_file_ptr_), {ex_t{10, 1}, ex_t{20, 10}});
18903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Seek(10)).WillOnce(Return(true));
19003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Read(_, 1, _)).WillOnce(Return(false));
19103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  size_t bytes_read;
19203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_FALSE(file.Read(nullptr, 1, &bytes_read));
19303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo}
19403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
19503f1debab429e673ba5e9e317c5a04e36e850cefAlex DeymoTEST_F(ExtentsFileTest, ReadPartialReadsAndEOF) {
19603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  ExtentsFile file(std::move(mock_file_ptr_), {ex_t{10, 1}, ex_t{20, 10}});
19703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Seek(_))
19803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo      .Times(AnyNumber())
19903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo      .WillRepeatedly(Return(true));
20003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  char* buf = reinterpret_cast<char*>(0x1234);
20103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  InSequence s;
20203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Read(buf, 1, _)).WillOnce(SucceedIO());
20303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Read(buf + 1, _, _)).WillOnce(SucceedPartialIO(3));
20403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_CALL(*mock_file_, Read(buf + 4, _, _)).WillOnce(SucceedPartialIO(0));
20503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
20603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  size_t bytes_read = 0;
20703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_TRUE(file.Read(buf, 100, &bytes_read));
20803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo  EXPECT_EQ(4U, bytes_read);
20903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo}
21003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo
21103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo}  // namespace bsdiff
212