AU: Update Downloader to support our image formats.
The downloader used to be dumb in the sense that it would pipe output
to either a DirectFileWriter or a DirectFileWriter via a
GzipDecompressingFileWriter, depending on if we were downloading an
update that was compressed or not. Sadly, things have gotten more
complex: we need to download to two partitions (kernel + rootfs), and
we may stream data via a DeltaPerformer (a type of FileWriter) to the
disk. Thus, the Downloader streams to either
1. gzip decompress->split_writer->direct to disk OR
2. delta performer
Other misc changes: Change FilesystemCopierAction to support
optionally copying the kernel partition rather than root partition.
InstallPlan struct: add an entry for destiation kernel partition.
Test Utils: a new ScopedTempFile class
Utils: support for getting the booted kernel partition device.
BUG=None
TEST=attached unittests
Review URL: http://codereview.chromium.org/1694025
diff --git a/download_action_unittest.cc b/download_action_unittest.cc
index d2c5cb1..6353584 100644
--- a/download_action_unittest.cc
+++ b/download_action_unittest.cc
@@ -65,32 +65,30 @@
return FALSE;
}
-void TestWithData(const vector<char>& data, bool compress) {
- vector<char> use_data;
- if (compress) {
- use_data = GzipCompressData(data);
- } else {
- use_data = data;
- }
-
+void TestWithData(const vector<char>& data) {
GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE);
// TODO(adlr): see if we need a different file for build bots
- const string path("/tmp/DownloadActionTest");
+ ScopedTempFile output_temp_file;
+ DirectFileWriter writer;
+
// takes ownership of passed in HttpFetcher
- InstallPlan install_plan(compress, "",
- OmahaHashCalculator::OmahaHashOfData(use_data),
- path);
+ InstallPlan install_plan(true,
+ "",
+ OmahaHashCalculator::OmahaHashOfData(data),
+ output_temp_file.GetPath(),
+ "");
ObjectFeederAction<InstallPlan> feeder_action;
feeder_action.set_obj(install_plan);
- DownloadAction download_action(new MockHttpFetcher(&use_data[0],
- use_data.size()));
+ DownloadAction download_action(new MockHttpFetcher(&data[0],
+ data.size()));
+ download_action.SetTestFileWriter(&writer);
BondActions(&feeder_action, &download_action);
DownloadActionTestProcessorDelegate delegate;
delegate.loop_ = loop;
delegate.expected_data_ = data;
- delegate.path_ = path;
+ delegate.path_ = output_temp_file.GetPath();
ActionProcessor processor;
processor.set_delegate(&delegate);
processor.EnqueueAction(&feeder_action);
@@ -99,9 +97,6 @@
g_timeout_add(0, &StartProcessorInRunLoop, &processor);
g_main_loop_run(loop);
g_main_loop_unref(loop);
-
- // remove temp file; don't care if there are errors here
- unlink(path.c_str());
}
} // namespace {}
@@ -109,8 +104,7 @@
vector<char> small;
const char* foo = "foo";
small.insert(small.end(), foo, foo + strlen(foo));
- TestWithData(small, false);
- TestWithData(small, true);
+ TestWithData(small);
}
TEST(DownloadActionTest, LargeTest) {
@@ -123,8 +117,7 @@
else
c++;
}
- TestWithData(big, false);
- TestWithData(big, true);
+ TestWithData(big);
}
namespace {
@@ -153,13 +146,16 @@
vector<char> data(kMockHttpFetcherChunkSize + kMockHttpFetcherChunkSize / 2);
memset(&data[0], 0, data.size());
- const string path("/tmp/DownloadActionTest");
+ ScopedTempFile temp_file;
{
+ DirectFileWriter writer;
+
// takes ownership of passed in HttpFetcher
ObjectFeederAction<InstallPlan> feeder_action;
- InstallPlan install_plan(false, "", "", path);
+ InstallPlan install_plan(true, "", "", temp_file.GetPath(), "");
feeder_action.set_obj(install_plan);
DownloadAction download_action(new MockHttpFetcher(&data[0], data.size()));
+ download_action.SetTestFileWriter(&writer);
TerminateEarlyTestProcessorDelegate delegate;
delegate.loop_ = loop;
ActionProcessor processor;
@@ -174,7 +170,8 @@
}
// 1 or 0 chunks should have come through
- const off_t resulting_file_size(utils::FileSize(path));
+ const off_t resulting_file_size(utils::FileSize(temp_file.GetPath()));
+ EXPECT_GE(resulting_file_size, 0);
if (resulting_file_size != 0)
EXPECT_EQ(kMockHttpFetcherChunkSize, resulting_file_size);
}
@@ -231,13 +228,18 @@
TEST(DownloadActionTest, PassObjectOutTest) {
GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE);
+ DirectFileWriter writer;
+
// takes ownership of passed in HttpFetcher
- InstallPlan install_plan(false, "",
+ InstallPlan install_plan(true,
+ "",
OmahaHashCalculator::OmahaHashOfString("x"),
+ "/dev/null",
"/dev/null");
ObjectFeederAction<InstallPlan> feeder_action;
feeder_action.set_obj(install_plan);
DownloadAction download_action(new MockHttpFetcher("x", 1));
+ download_action.SetTestFileWriter(&writer);
DownloadActionTestAction test_action;
test_action.expected_input_object_ = install_plan;
@@ -263,12 +265,15 @@
GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE);
const string path("/fake/path/that/cant/be/created/because/of/missing/dirs");
+ DirectFileWriter writer;
// takes ownership of passed in HttpFetcher
- InstallPlan install_plan(false, "", "", path);
+ InstallPlan install_plan(true, "", "", path, "");
ObjectFeederAction<InstallPlan> feeder_action;
feeder_action.set_obj(install_plan);
DownloadAction download_action(new MockHttpFetcher("x", 1));
+ download_action.SetTestFileWriter(&writer);
+
BondActions(&feeder_action, &download_action);
ActionProcessor processor;