blob: 10dccbe559f81f395adefeef6da631888cfcd65e [file] [log] [blame]
Darin Petkov27fa9c52010-07-15 15:11:55 -07001// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
adlr@google.com3defe6a2009-12-04 20:57:17 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <sys/stat.h>
6#include <sys/types.h>
7#include <unistd.h>
8#include <string>
9#include <vector>
10#include "base/string_util.h"
11#include <glib.h>
12#include <gtest/gtest.h>
13#include "update_engine/subprocess.h"
14#include "update_engine/test_utils.h"
15#include "update_engine/utils.h"
16
17using std::string;
18using std::vector;
19
20namespace chromeos_update_engine {
21
22class SubprocessTest : public ::testing::Test {
23 protected:
24 bool callback_done;
25};
26
27namespace {
28const int kLocalHttpPort = 8080;
29
30void Callback(int return_code, void *p) {
31 EXPECT_EQ(256, return_code);
32 GMainLoop* loop = reinterpret_cast<GMainLoop*>(p);
33 g_main_loop_quit(loop);
34}
35
36gboolean LaunchFalseInMainLoop(gpointer data) {
37 vector<string> cmd;
38 cmd.push_back("/bin/false");
39 Subprocess::Get().Exec(cmd, Callback, data);
40 return FALSE;
41}
42} // namespace {}
43
44TEST(SubprocessTest, SimpleTest) {
45 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE);
46 g_timeout_add(0, &LaunchFalseInMainLoop, loop);
47 g_main_loop_run(loop);
48 g_main_loop_unref(loop);
49}
50
51namespace {
52void CallbackBad(int return_code, void *p) {
53 CHECK(false) << "should never be called.";
54}
55
56struct CancelTestData {
57 bool spawned;
58 GMainLoop *loop;
59};
60
61gboolean StartAndCancelInRunLoop(gpointer data) {
62 CancelTestData* cancel_test_data = reinterpret_cast<CancelTestData*>(data);
63 vector<string> cmd;
64 cmd.push_back("./test_http_server");
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070065 uint32_t tag = Subprocess::Get().Exec(cmd, CallbackBad, NULL);
adlr@google.com3defe6a2009-12-04 20:57:17 +000066 EXPECT_NE(0, tag);
67 cancel_test_data->spawned = true;
68 printf("spawned\n");
69 // Wait for server to be up and running
Darin Petkov27fa9c52010-07-15 15:11:55 -070070 useconds_t total_wait_time = 0;
71 const useconds_t kMaxWaitTime = 3 * 1000000; // 3 seconds
adlr@google.com3defe6a2009-12-04 20:57:17 +000072 for (;;) {
73 int status =
74 System(StringPrintf("wget -O /dev/null http://127.0.0.1:%d/foo",
75 kLocalHttpPort));
76 EXPECT_NE(-1, status) << "system() failed";
77 EXPECT_TRUE(WIFEXITED(status))
78 << "command failed to run or died abnormally";
79 if (0 == WEXITSTATUS(status))
80 break;
Darin Petkov27fa9c52010-07-15 15:11:55 -070081
82 const useconds_t kSleepTime = 100 * 1000; // 100ms
83 usleep(kSleepTime); // 100 ms
84 total_wait_time += kSleepTime;
85 CHECK_LT(total_wait_time, kMaxWaitTime);
adlr@google.com3defe6a2009-12-04 20:57:17 +000086 }
87 Subprocess::Get().CancelExec(tag);
88 return FALSE;
89}
90} // namespace {}
91
92gboolean ExitWhenDone(gpointer data) {
93 CancelTestData* cancel_test_data = reinterpret_cast<CancelTestData*>(data);
94 if (cancel_test_data->spawned && !Subprocess::Get().SubprocessInFlight()) {
95 // tear down the sub process
96 printf("tear down time\n");
Darin Petkovb7de1d52010-08-24 13:38:33 -070097 int status = System(
98 StringPrintf("wget -O /dev/null http://127.0.0.1:%d/quitquitquit",
99 kLocalHttpPort));
adlr@google.com3defe6a2009-12-04 20:57:17 +0000100 EXPECT_NE(-1, status) << "system() failed";
101 EXPECT_TRUE(WIFEXITED(status))
102 << "command failed to run or died abnormally";
103 g_main_loop_quit(cancel_test_data->loop);
104 return FALSE;
105 }
106 return TRUE;
107}
108
109TEST(SubprocessTest, CancelTest) {
110 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE);
111 CancelTestData cancel_test_data;
112 cancel_test_data.spawned = false;
113 cancel_test_data.loop = loop;
114 g_timeout_add(100, &StartAndCancelInRunLoop, &cancel_test_data);
115 g_timeout_add(10, &ExitWhenDone, &cancel_test_data);
116 g_main_loop_run(loop);
117 g_main_loop_unref(loop);
118 printf("here\n");
119}
120
121} // namespace chromeos_update_engine