Index: omaha_request_action_unittest.cc |
diff --git a/omaha_request_action_unittest.cc b/omaha_request_action_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..778f408e268f2a7e46ca6e01e1c4539eca3f13c4 |
--- /dev/null |
+++ b/omaha_request_action_unittest.cc |
@@ -0,0 +1,538 @@ |
+// Copyright (c) 2009 The Chromium OS Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <string> |
+#include <vector> |
+#include <glib.h> |
+#include <gtest/gtest.h> |
+#include "update_engine/action_pipe.h" |
+#include "update_engine/mock_http_fetcher.h" |
+#include "update_engine/omaha_hash_calculator.h" |
+#include "update_engine/omaha_request_action.h" |
+#include "update_engine/test_utils.h" |
+ |
+using std::string; |
+using std::vector; |
+ |
+namespace chromeos_update_engine { |
+ |
+class OmahaRequestActionTest : public ::testing::Test { }; |
+ |
+namespace { |
+string GetNoUpdateResponse(const string& app_id) { |
+ return string( |
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><gupdate " |
+ "xmlns=\"http://www.google.com/update2/response\" protocol=\"2.0\"><app " |
+ "appid=\"") + app_id + "\" status=\"ok\"><ping " |
+ "status=\"ok\"/><updatecheck status=\"noupdate\"/></app></gupdate>"; |
+} |
+ |
+string GetUpdateResponse(const string& app_id, |
+ const string& display_version, |
+ const string& more_info_url, |
+ const string& prompt, |
+ const string& codebase, |
+ const string& hash, |
+ const string& needsadmin, |
+ const string& size) { |
+ return string("<?xml version=\"1.0\" encoding=\"UTF-8\"?><gupdate " |
+ "xmlns=\"http://www.google.com/update2/response\" " |
+ "protocol=\"2.0\"><app " |
+ "appid=\"") + app_id + "\" status=\"ok\"><ping " |
+ "status=\"ok\"/><updatecheck DisplayVersion=\"" + display_version + "\" " |
+ "MoreInfo=\"" + more_info_url + "\" Prompt=\"" + prompt + "\" " |
+ "codebase=\"" + codebase + "\" " |
+ "hash=\"" + hash + "\" needsadmin=\"" + needsadmin + "\" " |
+ "size=\"" + size + "\" status=\"ok\"/></app></gupdate>"; |
+} |
+ |
+class OmahaRequestActionTestProcessorDelegate : public ActionProcessorDelegate { |
+ public: |
+ OmahaRequestActionTestProcessorDelegate() |
+ : loop_(NULL), |
+ expected_success_(true) {} |
+ virtual ~OmahaRequestActionTestProcessorDelegate() { |
+ } |
+ virtual void ProcessingDone(const ActionProcessor* processor, bool success) { |
+ ASSERT_TRUE(loop_); |
+ g_main_loop_quit(loop_); |
+ } |
+ |
+ virtual void ActionCompleted(ActionProcessor* processor, |
+ AbstractAction* action, |
+ bool success) { |
+ // make sure actions always succeed |
+ if (action->Type() == OmahaRequestAction::StaticType()) |
+ EXPECT_EQ(expected_success_, success); |
+ else |
+ EXPECT_TRUE(success); |
+ } |
+ GMainLoop *loop_; |
+ bool expected_success_; |
+}; |
+ |
+gboolean StartProcessorInRunLoop(gpointer data) { |
+ ActionProcessor *processor = reinterpret_cast<ActionProcessor*>(data); |
+ processor->StartProcessing(); |
+ return FALSE; |
+} |
+ |
+} // namespace {} |
+ |
+class OutputObjectCollectorAction; |
+ |
+template<> |
+class ActionTraits<OutputObjectCollectorAction> { |
+ public: |
+ // Does not take an object for input |
+ typedef OmahaResponse InputObjectType; |
+ // On success, puts the output path on output |
+ typedef NoneType OutputObjectType; |
+}; |
+ |
+class OutputObjectCollectorAction : public Action<OutputObjectCollectorAction> { |
+ public: |
+ OutputObjectCollectorAction() : has_input_object_(false) {} |
+ void PerformAction() { |
+ // copy input object |
+ has_input_object_ = HasInputObject(); |
+ if (has_input_object_) |
+ omaha_response_ = GetInputObject(); |
+ processor_->ActionComplete(this, true); |
+ } |
+ // Should never be called |
+ void TerminateProcessing() { |
+ CHECK(false); |
+ } |
+ // Debugging/logging |
+ static std::string StaticType() { |
+ return "OutputObjectCollectorAction"; |
+ } |
+ std::string Type() const { return StaticType(); } |
+ bool has_input_object_; |
+ OmahaResponse omaha_response_; |
+}; |
+ |
+// returns true iff an output response was obtained from the |
+// OmahaRequestAction. out_response may be NULL. |
+// out_post_data may be null; if non-null, the post-data received by the |
+// mock HttpFetcher is returned. |
+bool TestOmahaRequestAction(const OmahaRequestParams& params, |
+ const string& http_response, |
+ bool expected_success, |
+ OmahaResponse* out_response, |
+ vector<char> *out_post_data) { |
+ GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); |
+ MockHttpFetcher *fetcher = new MockHttpFetcher(http_response.data(), |
+ http_response.size()); |
+ ObjectFeederAction<OmahaRequestParams> feeder_action; |
+ OmahaRequestAction action(fetcher); // takes ownership of fetcher |
+ OmahaRequestActionTestProcessorDelegate delegate; |
+ delegate.loop_ = loop; |
+ delegate.expected_success_ = expected_success; |
+ ActionProcessor processor; |
+ feeder_action.set_obj(params); |
+ processor.set_delegate(&delegate); |
+ processor.EnqueueAction(&feeder_action); |
+ processor.EnqueueAction(&action); |
+ |
+ OutputObjectCollectorAction collector_action; |
+ |
+ BondActions(&feeder_action, &action); |
+ BondActions(&action, &collector_action); |
+ processor.EnqueueAction(&collector_action); |
+ |
+ g_timeout_add(0, &StartProcessorInRunLoop, &processor); |
+ g_main_loop_run(loop); |
+ g_main_loop_unref(loop); |
+ if (collector_action.has_input_object_ && out_response) |
+ *out_response = collector_action.omaha_response_; |
+ if (out_post_data) |
+ *out_post_data = fetcher->post_data(); |
+ return collector_action.has_input_object_; |
+} |
+ |
+TEST(OmahaRequestActionTest, NoUpdateTest) { |
+ OmahaRequestParams params("", // machine_id |
+ "", // user_id |
+ OmahaRequestParams::kOsPlatform, |
+ OmahaRequestParams::kOsVersion, |
+ "", // os_sp |
+ "x86-generic", |
+ OmahaRequestParams::kAppId, |
+ "0.1.0.0", |
+ "en-US", |
+ "unittest", |
+ ""); // url |
+ OmahaResponse response; |
+ ASSERT_TRUE( |
+ TestOmahaRequestAction(params, |
+ GetNoUpdateResponse(OmahaRequestParams::kAppId), |
+ true, |
+ &response, |
+ NULL)); |
+ EXPECT_FALSE(response.update_exists); |
+} |
+ |
+TEST(OmahaRequestActionTest, ValidUpdateTest) { |
+ OmahaRequestParams params("machine_id", |
+ "user_id", |
+ OmahaRequestParams::kOsPlatform, |
+ OmahaRequestParams::kOsVersion, |
+ "service_pack", |
+ "arm-generic", |
+ OmahaRequestParams::kAppId, |
+ "0.1.0.0", |
+ "en-US", |
+ "unittest_track", |
+ ""); // url |
+ OmahaResponse response; |
+ ASSERT_TRUE( |
+ TestOmahaRequestAction(params, |
+ GetUpdateResponse(OmahaRequestParams::kAppId, |
+ "1.2.3.4", // version |
+ "http://more/info", |
+ "true", // prompt |
+ "http://code/base", // dl url |
+ "HASH1234=", // checksum |
+ "false", // needs admin |
+ "123"), // size |
+ true, |
+ &response, |
+ NULL)); |
+ EXPECT_TRUE(response.update_exists); |
+ EXPECT_EQ("1.2.3.4", response.display_version); |
+ EXPECT_EQ("http://code/base", response.codebase); |
+ EXPECT_EQ("http://more/info", response.more_info_url); |
+ EXPECT_EQ("HASH1234=", response.hash); |
+ EXPECT_EQ(123, response.size); |
+ EXPECT_FALSE(response.needs_admin); |
+ EXPECT_TRUE(response.prompt); |
+} |
+ |
+TEST(OmahaRequestActionTest, NoOutputPipeTest) { |
+ OmahaRequestParams params("", // machine_id |
+ "", // usr_id |
+ OmahaRequestParams::kOsPlatform, |
+ OmahaRequestParams::kOsVersion, |
+ "", // os_sp |
+ "", // os_board |
+ OmahaRequestParams::kAppId, |
+ "0.1.0.0", |
+ "en-US", |
+ "unittest", |
+ ""); // url |
+ const string http_response(GetNoUpdateResponse(OmahaRequestParams::kAppId)); |
+ |
+ GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); |
+ |
+ ObjectFeederAction<OmahaRequestParams> feeder_action; |
+ feeder_action.set_obj(params); |
+ OmahaRequestAction action(new MockHttpFetcher(http_response.data(), |
+ http_response.size())); |
+ OmahaRequestActionTestProcessorDelegate delegate; |
+ delegate.loop_ = loop; |
+ ActionProcessor processor; |
+ processor.set_delegate(&delegate); |
+ processor.EnqueueAction(&feeder_action); |
+ processor.EnqueueAction(&action); |
+ BondActions(&feeder_action, &action); |
+ |
+ g_timeout_add(0, &StartProcessorInRunLoop, &processor); |
+ g_main_loop_run(loop); |
+ g_main_loop_unref(loop); |
+ EXPECT_FALSE(processor.IsRunning()); |
+} |
+ |
+TEST(OmahaRequestActionTest, InvalidXmlTest) { |
+ OmahaRequestParams params("machine_id", |
+ "user_id", |
+ OmahaRequestParams::kOsPlatform, |
+ OmahaRequestParams::kOsVersion, |
+ "service_pack", |
+ "x86-generic", |
+ OmahaRequestParams::kAppId, |
+ "0.1.0.0", |
+ "en-US", |
+ "unittest_track", |
+ "http://url"); |
+ OmahaResponse response; |
+ ASSERT_FALSE( |
+ TestOmahaRequestAction(params, |
+ "invalid xml>", |
+ false, |
+ &response, |
+ NULL)); |
+ EXPECT_FALSE(response.update_exists); |
+} |
+ |
+TEST(OmahaRequestActionTest, MissingStatusTest) { |
+ OmahaRequestParams params("machine_id", |
+ "user_id", |
+ OmahaRequestParams::kOsPlatform, |
+ OmahaRequestParams::kOsVersion, |
+ "service_pack", |
+ "x86-generic", |
+ OmahaRequestParams::kAppId, |
+ "0.1.0.0", |
+ "en-US", |
+ "unittest_track", |
+ "http://url"); |
+ OmahaResponse response; |
+ ASSERT_FALSE(TestOmahaRequestAction( |
+ params, |
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><gupdate " |
+ "xmlns=\"http://www.google.com/update2/response\" protocol=\"2.0\"><app " |
+ "appid=\"foo\" status=\"ok\"><ping " |
+ "status=\"ok\"/><updatecheck/></app></gupdate>", |
+ false, |
+ &response, |
+ NULL)); |
+ EXPECT_FALSE(response.update_exists); |
+} |
+ |
+TEST(OmahaRequestActionTest, InvalidStatusTest) { |
+ OmahaRequestParams params("machine_id", |
+ "user_id", |
+ OmahaRequestParams::kOsPlatform, |
+ OmahaRequestParams::kOsVersion, |
+ "service_pack", |
+ "x86-generic", |
+ OmahaRequestParams::kAppId, |
+ "0.1.0.0", |
+ "en-US", |
+ "unittest_track", |
+ "http://url"); |
+ OmahaResponse response; |
+ ASSERT_FALSE(TestOmahaRequestAction( |
+ params, |
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><gupdate " |
+ "xmlns=\"http://www.google.com/update2/response\" protocol=\"2.0\"><app " |
+ "appid=\"foo\" status=\"ok\"><ping " |
+ "status=\"ok\"/><updatecheck status=\"foo\"/></app></gupdate>", |
+ false, |
+ &response, |
+ NULL)); |
+ EXPECT_FALSE(response.update_exists); |
+} |
+ |
+TEST(OmahaRequestActionTest, MissingNodesetTest) { |
+ OmahaRequestParams params("machine_id", |
+ "user_id", |
+ OmahaRequestParams::kOsPlatform, |
+ OmahaRequestParams::kOsVersion, |
+ "service_pack", |
+ "x86-generic", |
+ OmahaRequestParams::kAppId, |
+ "0.1.0.0", |
+ "en-US", |
+ "unittest_track", |
+ "http://url"); |
+ OmahaResponse response; |
+ ASSERT_FALSE(TestOmahaRequestAction( |
+ params, |
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><gupdate " |
+ "xmlns=\"http://www.google.com/update2/response\" protocol=\"2.0\"><app " |
+ "appid=\"foo\" status=\"ok\"><ping " |
+ "status=\"ok\"/></app></gupdate>", |
+ false, |
+ &response, |
+ NULL)); |
+ EXPECT_FALSE(response.update_exists); |
+} |
+ |
+TEST(OmahaRequestActionTest, MissingFieldTest) { |
+ OmahaRequestParams params("machine_id", |
+ "user_id", |
+ OmahaRequestParams::kOsPlatform, |
+ OmahaRequestParams::kOsVersion, |
+ "service_pack", |
+ "x86-generic", |
+ OmahaRequestParams::kAppId, |
+ "0.1.0.0", |
+ "en-US", |
+ "unittest_track", |
+ "http://url"); |
+ OmahaResponse response; |
+ ASSERT_TRUE(TestOmahaRequestAction(params, |
+ string("<?xml version=\"1.0\" " |
+ "encoding=\"UTF-8\"?><gupdate " |
+ "xmlns=\"http://www.google.com/" |
+ "update2/response\" " |
+ "protocol=\"2.0\"><app appid=\"") + |
+ OmahaRequestParams::kAppId |
+ + "\" status=\"ok\"><ping " |
+ "status=\"ok\"/><updatecheck " |
+ "DisplayVersion=\"1.2.3.4\" " |
+ "Prompt=\"false\" " |
+ "codebase=\"http://code/base\" " |
+ "hash=\"HASH1234=\" needsadmin=\"true\" " |
+ "size=\"123\" " |
+ "status=\"ok\"/></app></gupdate>", |
+ true, |
+ &response, |
+ NULL)); |
+ EXPECT_TRUE(response.update_exists); |
+ EXPECT_EQ("1.2.3.4", response.display_version); |
+ EXPECT_EQ("http://code/base", response.codebase); |
+ EXPECT_EQ("", response.more_info_url); |
+ EXPECT_EQ("HASH1234=", response.hash); |
+ EXPECT_EQ(123, response.size); |
+ EXPECT_TRUE(response.needs_admin); |
+ EXPECT_FALSE(response.prompt); |
+} |
+ |
+namespace { |
+class TerminateEarlyTestProcessorDelegate : public ActionProcessorDelegate { |
+ public: |
+ void ProcessingStopped(const ActionProcessor* processor) { |
+ ASSERT_TRUE(loop_); |
+ g_main_loop_quit(loop_); |
+ } |
+ GMainLoop *loop_; |
+}; |
+ |
+gboolean TerminateTransferTestStarter(gpointer data) { |
+ ActionProcessor *processor = reinterpret_cast<ActionProcessor*>(data); |
+ processor->StartProcessing(); |
+ CHECK(processor->IsRunning()); |
+ processor->StopProcessing(); |
+ return FALSE; |
+} |
+} // namespace {} |
+ |
+TEST(OmahaRequestActionTest, TerminateTransferTest) { |
+ OmahaRequestParams params("", // machine_id |
+ "", // usr_id |
+ OmahaRequestParams::kOsPlatform, |
+ OmahaRequestParams::kOsVersion, |
+ "", // os_sp |
+ "", // os_board |
+ OmahaRequestParams::kAppId, |
+ "0.1.0.0", |
+ "en-US", |
+ "unittest", |
+ "http://url"); |
+ string http_response("doesn't matter"); |
+ GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); |
+ |
+ ObjectFeederAction<OmahaRequestParams> feeder_action; |
+ feeder_action.set_obj(params); |
+ OmahaRequestAction action(new MockHttpFetcher(http_response.data(), |
+ http_response.size())); |
+ TerminateEarlyTestProcessorDelegate delegate; |
+ delegate.loop_ = loop; |
+ ActionProcessor processor; |
+ processor.set_delegate(&delegate); |
+ processor.EnqueueAction(&feeder_action); |
+ processor.EnqueueAction(&action); |
+ BondActions(&feeder_action, &action); |
+ |
+ g_timeout_add(0, &TerminateTransferTestStarter, &processor); |
+ g_main_loop_run(loop); |
+ g_main_loop_unref(loop); |
+} |
+ |
+TEST(OmahaRequestActionTest, XmlEncodeTest) { |
+ EXPECT_EQ("ab", XmlEncode("ab")); |
+ EXPECT_EQ("a<b", XmlEncode("a<b")); |
+ EXPECT_EQ("foo-Ω", XmlEncode("foo-\xce\xa9")); |
+ EXPECT_EQ("<&>", XmlEncode("<&>")); |
+ EXPECT_EQ("&lt;&amp;&gt;", XmlEncode("<&>")); |
+ |
+ vector<char> post_data; |
+ |
+ // Make sure XML Encode is being called on the params |
+ OmahaRequestParams params("testthemachine<id", |
+ "testtheuser_id<", |
+ OmahaRequestParams::kOsPlatform, |
+ OmahaRequestParams::kOsVersion, |
+ "testtheservice_pack>", |
+ "x86 generic", |
+ OmahaRequestParams::kAppId, |
+ "0.1.0.0", |
+ "en-US", |
+ "unittest_track", |
+ "http://url"); |
+ OmahaResponse response; |
+ ASSERT_FALSE( |
+ TestOmahaRequestAction(params, |
+ "invalid xml>", |
+ false, |
+ &response, |
+ &post_data)); |
+ // convert post_data to string |
+ string post_str(&post_data[0], post_data.size()); |
+ EXPECT_NE(post_str.find("testthemachine<id"), string::npos); |
+ EXPECT_EQ(post_str.find("testthemachine<id"), string::npos); |
+ EXPECT_NE(post_str.find("testtheuser_id&lt;"), string::npos); |
+ EXPECT_EQ(post_str.find("testtheuser_id<"), string::npos); |
+ EXPECT_NE(post_str.find("testtheservice_pack>"), string::npos); |
+ EXPECT_EQ(post_str.find("testtheservice_pack>"), string::npos); |
+ EXPECT_NE(post_str.find("x86 generic"), string::npos); |
+} |
+ |
+TEST(OmahaRequestActionTest, XmlDecodeTest) { |
+ OmahaRequestParams params("machine_id", |
+ "user_id", |
+ OmahaRequestParams::kOsPlatform, |
+ OmahaRequestParams::kOsVersion, |
+ "service_pack", |
+ "x86-generic", |
+ OmahaRequestParams::kAppId, |
+ "0.1.0.0", |
+ "en-US", |
+ "unittest_track", |
+ "http://url"); |
+ OmahaResponse response; |
+ ASSERT_TRUE( |
+ TestOmahaRequestAction(params, |
+ GetUpdateResponse(OmahaRequestParams::kAppId, |
+ "1.2.3.4", // version |
+ "testthe<url", // more info |
+ "true", // prompt |
+ "testthe&code", // dl url |
+ "HASH1234=", // checksum |
+ "false", // needs admin |
+ "123"), // size |
+ true, |
+ &response, |
+ NULL)); |
+ |
+ EXPECT_EQ(response.more_info_url, "testthe<url"); |
+ EXPECT_EQ(response.codebase, "testthe&code"); |
+} |
+ |
+TEST(OmahaRequestActionTest, ParseIntTest) { |
+ OmahaRequestParams params("machine_id", |
+ "user_id", |
+ OmahaRequestParams::kOsPlatform, |
+ OmahaRequestParams::kOsVersion, |
+ "service_pack", |
+ "the_board", |
+ OmahaRequestParams::kAppId, |
+ "0.1.0.0", |
+ "en-US", |
+ "unittest_track", |
+ "http://url"); |
+ OmahaResponse response; |
+ ASSERT_TRUE( |
+ TestOmahaRequestAction(params, |
+ GetUpdateResponse(OmahaRequestParams::kAppId, |
+ "1.2.3.4", // version |
+ "theurl", // more info |
+ "true", // prompt |
+ "thecodebase", // dl url |
+ "HASH1234=", // checksum |
+ "false", // needs admin |
+ // overflows int32: |
+ "123123123123123"), // size |
+ true, |
+ &response, |
+ NULL)); |
+ |
+ EXPECT_EQ(response.size, 123123123123123ll); |
+} |
+ |
+} // namespace chromeos_update_engine |