blob: c302b5240e63ca19e8b7a4a4d8aa323384f3d0e9 [file] [log] [blame]
Narayan Kamatha5ace892017-01-06 15:10:02 +00001/*
2 * Copyright 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <string>
Lorenzo Colitti173da322017-02-05 01:56:40 +090018#include <fcntl.h>
19#include <signal.h>
Narayan Kamatha5ace892017-01-06 15:10:02 +000020
21#include <gtest/gtest.h>
22
Lorenzo Colitti173da322017-02-05 01:56:40 +090023#define LOG_TAG "IptablesRestoreControllerTest"
24#include <cutils/log.h>
25#include <android-base/stringprintf.h>
26
Narayan Kamatha5ace892017-01-06 15:10:02 +000027#include "IptablesRestoreController.h"
28#include "NetdConstants.h"
29
Lorenzo Colitti173da322017-02-05 01:56:40 +090030using android::base::StringPrintf;
Narayan Kamatha5ace892017-01-06 15:10:02 +000031
Lorenzo Colitti173da322017-02-05 01:56:40 +090032class IptablesRestoreControllerTest : public ::testing::Test {
33public:
34 IptablesRestoreController con;
35
36 pid_t getIpRestorePid(const IptablesRestoreController::IptablesProcessType type) {
37 return con.getIpRestorePid(type);
38 };
39
40 void expectNoIptablesRestoreProcess(pid_t pid) {
41 // We can't readlink /proc/PID/exe, because zombie processes don't have it.
42 // Parse /proc/PID/stat instead.
43 std::string statPath = StringPrintf("/proc/%d/stat", pid);
44 int fd = open(statPath.c_str(), O_RDONLY);
45 if (fd == -1) {
46 // ENOENT means the process is gone (expected).
47 ASSERT_EQ(errno, ENOENT)
48 << "Unexpected error opening " << statPath << ": " << strerror(errno);
49 return;
50 }
51
52 // If the PID exists, it's possible (though very unlikely) that the PID was reused. Check the
53 // binary name as well, to ensure the test isn't flaky.
54 char statBuf[1024];
55 ASSERT_NE(-1, read(fd, statBuf, sizeof(statBuf)))
56 << "Could not read from " << statPath << ": " << strerror(errno);
57 close(fd);
58
59 std::string statString(statBuf);
60 EXPECT_FALSE(statString.find("iptables-restor") || statString.find("ip6tables-resto"))
61 << "Previous iptables-restore pid " << pid << " still alive: " << statString;
62 }
Narayan Kamatha5ace892017-01-06 15:10:02 +000063};
64
Lorenzo Colitti173da322017-02-05 01:56:40 +090065TEST_F(IptablesRestoreControllerTest, TestBasicCommand) {
Narayan Kamatha5ace892017-01-06 15:10:02 +000066 EXPECT_EQ(0, con.execute(IptablesTarget::V4V6, "#Test\n"));
Lorenzo Colitti173da322017-02-05 01:56:40 +090067
68 pid_t pid4 = getIpRestorePid(IptablesRestoreController::IPTABLES_PROCESS);
69 pid_t pid6 = getIpRestorePid(IptablesRestoreController::IP6TABLES_PROCESS);
70
Narayan Kamatha5ace892017-01-06 15:10:02 +000071 EXPECT_EQ(0, con.execute(IptablesTarget::V6, "#Test\n"));
Lorenzo Colitti173da322017-02-05 01:56:40 +090072 EXPECT_EQ(0, con.execute(IptablesTarget::V4, "#Test\n"));
73
74 // Check the PIDs are the same as they were before. If they're not, the child processes were
75 // restarted, which causes a 30-60ms delay.
76 EXPECT_EQ(pid4, getIpRestorePid(IptablesRestoreController::IPTABLES_PROCESS));
77 EXPECT_EQ(pid6, getIpRestorePid(IptablesRestoreController::IP6TABLES_PROCESS));
Narayan Kamatha5ace892017-01-06 15:10:02 +000078}
79
Lorenzo Colitti173da322017-02-05 01:56:40 +090080TEST_F(IptablesRestoreControllerTest, TestRestartOnMalformedCommand) {
81 for (int i = 0; i < 50; i++) {
82 IptablesTarget target = (IptablesTarget) (i % 3);
83 ASSERT_EQ(-1, con.execute(target, "malformed command\n")) <<
84 "Malformed command did not fail at iteration " << i;
85 ASSERT_EQ(0, con.execute(target, "#Test\n")) <<
86 "No-op command did not succeed at iteration " << i;
87 }
88}
89
90TEST_F(IptablesRestoreControllerTest, TestRestartOnProcessDeath) {
91 // Run a command to ensure that the processes are running.
Narayan Kamatha5ace892017-01-06 15:10:02 +000092 EXPECT_EQ(0, con.execute(IptablesTarget::V4V6, "#Test\n"));
Lorenzo Colitti173da322017-02-05 01:56:40 +090093
94 pid_t pid4 = getIpRestorePid(IptablesRestoreController::IPTABLES_PROCESS);
95 pid_t pid6 = getIpRestorePid(IptablesRestoreController::IP6TABLES_PROCESS);
96
97 ASSERT_EQ(0, kill(pid4, 0)) << "iptables-restore pid " << pid4 << " does not exist";
98 ASSERT_EQ(0, kill(pid6, 0)) << "ip6tables-restore pid " << pid6 << " does not exist";
99 ASSERT_EQ(0, kill(pid4, SIGTERM)) << "Failed to send SIGTERM to iptables-restore pid " << pid4;
100 ASSERT_EQ(0, kill(pid6, SIGTERM)) << "Failed to send SIGTERM to ip6tables-restore pid " << pid6;
101
102 // Wait 100ms for processes to terminate.
103 TEMP_FAILURE_RETRY(usleep(100 * 1000));
104
105 // Ensure that running a new command properly restarts the processes.
106 EXPECT_EQ(0, con.execute(IptablesTarget::V4V6, "#Test\n"));
107 EXPECT_NE(pid4, getIpRestorePid(IptablesRestoreController::IPTABLES_PROCESS));
108 EXPECT_NE(pid6, getIpRestorePid(IptablesRestoreController::IP6TABLES_PROCESS));
109
110 // Check there are no zombies.
111 expectNoIptablesRestoreProcess(pid4);
112 expectNoIptablesRestoreProcess(pid6);
Narayan Kamatha5ace892017-01-06 15:10:02 +0000113}