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/compiler_specific.h" 6 #include "base/file_util.h" 7 #include "base/files/file_path.h" 8 #include "base/files/scoped_temp_dir.h" 9 #include "base/path_service.h" 10 #include "base/values.h" 11 #include "chrome/browser/component_updater/component_patcher.h" 12 #include "chrome/browser/component_updater/component_patcher_operation.h" 13 #include "chrome/browser/component_updater/component_updater_service.h" 14 #include "chrome/browser/component_updater/test/component_patcher_mock.h" 15 #include "chrome/browser/component_updater/test/component_patcher_unittest.h" 16 #include "chrome/browser/component_updater/test/test_installer.h" 17 #include "chrome/common/chrome_paths.h" 18 #include "courgette/courgette.h" 19 #include "courgette/third_party/bsdiff.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 22 base::FilePath test_file(const char* file) { 23 base::FilePath path; 24 PathService::Get(chrome::DIR_TEST_DATA, &path); 25 return path.AppendASCII("components").AppendASCII(file); 26 } 27 28 ComponentPatcherOperationTest::ComponentPatcherOperationTest() { 29 EXPECT_TRUE(unpack_dir_.CreateUniqueTempDir()); 30 EXPECT_TRUE(input_dir_.CreateUniqueTempDir()); 31 EXPECT_TRUE(installed_dir_.CreateUniqueTempDir()); 32 patcher_.reset(new MockComponentPatcher()); 33 installer_.reset(new ReadOnlyTestInstaller(installed_dir_.path())); 34 } 35 36 ComponentPatcherOperationTest::~ComponentPatcherOperationTest() { 37 } 38 39 ComponentUnpacker::Error MockComponentPatcher::Patch( 40 PatchType patch_type, 41 const base::FilePath& input_file, 42 const base::FilePath& patch_file, 43 const base::FilePath& output_file, 44 int* error) { 45 *error = 0; 46 int exit_code; 47 if (patch_type == kPatchTypeCourgette) { 48 exit_code = courgette::ApplyEnsemblePatch(input_file.value().c_str(), 49 patch_file.value().c_str(), 50 output_file.value().c_str()); 51 if (exit_code == courgette::C_OK) 52 return ComponentUnpacker::kNone; 53 *error = exit_code + kCourgetteErrorOffset; 54 } else if (patch_type == kPatchTypeBsdiff) { 55 exit_code = courgette::ApplyBinaryPatch(input_file, 56 patch_file, 57 output_file); 58 if (exit_code == courgette::OK) 59 return ComponentUnpacker::kNone; 60 *error = exit_code + kBsdiffErrorOffset; 61 } 62 return ComponentUnpacker::kDeltaOperationFailure; 63 } 64 65 // Verify that a 'create' delta update operation works correctly. 66 TEST_F(ComponentPatcherOperationTest, CheckCreateOperation) { 67 EXPECT_TRUE(base::CopyFile( 68 test_file("binary_output.bin"), 69 input_dir_.path().Append(FILE_PATH_LITERAL("binary_output.bin")))); 70 71 scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue()); 72 command_args->SetString("output", "output.bin"); 73 command_args->SetString("sha256", binary_output_hash); 74 command_args->SetString("op", "create"); 75 command_args->SetString("patch", "binary_output.bin"); 76 77 int error = 0; 78 scoped_ptr<DeltaUpdateOp> op(new DeltaUpdateOpCreate()); 79 ComponentUnpacker::Error result = op->Run(command_args.get(), 80 input_dir_.path(), 81 unpack_dir_.path(), 82 patcher_.get(), 83 NULL, 84 &error); 85 86 EXPECT_EQ(ComponentUnpacker::kNone, result); 87 EXPECT_EQ(0, error); 88 EXPECT_TRUE(base::ContentsEqual( 89 unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")), 90 test_file("binary_output.bin"))); 91 } 92 93 // Verify that a 'copy' delta update operation works correctly. 94 TEST_F(ComponentPatcherOperationTest, CheckCopyOperation) { 95 EXPECT_TRUE(base::CopyFile( 96 test_file("binary_output.bin"), 97 installed_dir_.path().Append(FILE_PATH_LITERAL("binary_output.bin")))); 98 99 scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue()); 100 command_args->SetString("output", "output.bin"); 101 command_args->SetString("sha256", binary_output_hash); 102 command_args->SetString("op", "copy"); 103 command_args->SetString("input", "binary_output.bin"); 104 105 int error = 0; 106 scoped_ptr<DeltaUpdateOp> op(new DeltaUpdateOpCopy()); 107 ComponentUnpacker::Error result = op->Run(command_args.get(), 108 input_dir_.path(), 109 unpack_dir_.path(), 110 patcher_.get(), 111 installer_.get(), 112 &error); 113 EXPECT_EQ(ComponentUnpacker::kNone, result); 114 EXPECT_EQ(0, error); 115 EXPECT_TRUE(base::ContentsEqual( 116 unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")), 117 test_file("binary_output.bin"))); 118 } 119 120 // Verify that a 'courgette' delta update operation works correctly. 121 TEST_F(ComponentPatcherOperationTest, CheckCourgetteOperation) { 122 EXPECT_TRUE(base::CopyFile( 123 test_file("binary_input.bin"), 124 installed_dir_.path().Append(FILE_PATH_LITERAL("binary_input.bin")))); 125 EXPECT_TRUE(base::CopyFile( 126 test_file("binary_courgette_patch.bin"), 127 input_dir_.path().Append( 128 FILE_PATH_LITERAL("binary_courgette_patch.bin")))); 129 130 scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue()); 131 command_args->SetString("output", "output.bin"); 132 command_args->SetString("sha256", binary_output_hash); 133 command_args->SetString("op", "courgette"); 134 command_args->SetString("input", "binary_input.bin"); 135 command_args->SetString("patch", "binary_courgette_patch.bin"); 136 137 int error = 0; 138 scoped_ptr<DeltaUpdateOp> op(new DeltaUpdateOpPatchCourgette()); 139 ComponentUnpacker::Error result = op->Run(command_args.get(), 140 input_dir_.path(), 141 unpack_dir_.path(), 142 patcher_.get(), 143 installer_.get(), 144 &error); 145 EXPECT_EQ(ComponentUnpacker::kNone, result); 146 EXPECT_EQ(0, error); 147 EXPECT_TRUE(base::ContentsEqual( 148 unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")), 149 test_file("binary_output.bin"))); 150 } 151 152 // Verify that a 'bsdiff' delta update operation works correctly. 153 TEST_F(ComponentPatcherOperationTest, CheckBsdiffOperation) { 154 EXPECT_TRUE(base::CopyFile( 155 test_file("binary_input.bin"), 156 installed_dir_.path().Append(FILE_PATH_LITERAL("binary_input.bin")))); 157 EXPECT_TRUE(base::CopyFile( 158 test_file("binary_bsdiff_patch.bin"), 159 input_dir_.path().Append(FILE_PATH_LITERAL("binary_bsdiff_patch.bin")))); 160 161 scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue()); 162 command_args->SetString("output", "output.bin"); 163 command_args->SetString("sha256", binary_output_hash); 164 command_args->SetString("op", "courgette"); 165 command_args->SetString("input", "binary_input.bin"); 166 command_args->SetString("patch", "binary_bsdiff_patch.bin"); 167 168 int error = 0; 169 scoped_ptr<DeltaUpdateOp> op(new DeltaUpdateOpPatchBsdiff()); 170 ComponentUnpacker::Error result = op->Run(command_args.get(), 171 input_dir_.path(), 172 unpack_dir_.path(), 173 patcher_.get(), 174 installer_.get(), 175 &error); 176 EXPECT_EQ(ComponentUnpacker::kNone, result); 177 EXPECT_EQ(0, error); 178 EXPECT_TRUE(base::ContentsEqual( 179 unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")), 180 test_file("binary_output.bin"))); 181 } 182