1//
2// Copyright (C) 2015 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 <map>
18#include <memory>
19#include <set>
20#include <string>
21#include <vector>
22
23#include <base/bind.h>
24#include <base/bind_helpers.h>
25#include <base/memory/weak_ptr.h>
26#include <gtest/gtest.h>
27
28#include "shill/error.h"
29#include "shill/external_task.h"
30#include "shill/mock_control.h"
31#include "shill/mock_process_manager.h"
32#include "shill/ppp_daemon.h"
33#include "shill/rpc_task.h"
34
35namespace shill {
36
37using std::string;
38using std::vector;
39using testing::_;
40using testing::Invoke;
41using testing::Return;
42using testing::Test;
43using testing::WithArg;
44
45class PPPDaemonTest : public Test, public RPCTaskDelegate {
46 public:
47  PPPDaemonTest() : weak_ptr_factory_(this) {}
48  virtual ~PPPDaemonTest() {}
49
50  std::unique_ptr<ExternalTask> Start(const PPPDaemon::Options& options,
51                                      const std::string& device,
52                                      Error* error) {
53    PPPDaemon::DeathCallback callback(base::Bind(&PPPDaemonTest::DeathCallback,
54                                                 base::Unretained(this)));
55    return PPPDaemon::Start(&control_, &process_manager_,
56                            weak_ptr_factory_.GetWeakPtr(),
57                            options, device, callback, error);
58  }
59
60  bool CaptureArgv(const vector<string>& argv) {
61    argv_ = argv;
62    return true;
63  }
64
65  MOCK_METHOD2(GetLogin, void(std::string* user, std::string* password));
66  MOCK_METHOD2(Notify, void(const std::string& reason,
67                            const std::map<std::string, std::string>& dict));
68
69 protected:
70  MockControl control_;
71  MockProcessManager process_manager_;
72
73  std::vector<std::string> argv_;
74  base::WeakPtrFactory<PPPDaemonTest> weak_ptr_factory_;
75
76  MOCK_METHOD2(DeathCallback, void(pid_t pid, int status));
77
78 private:
79  DISALLOW_COPY_AND_ASSIGN(PPPDaemonTest);
80};
81
82TEST_F(PPPDaemonTest, PluginUsed) {
83  EXPECT_CALL(process_manager_, StartProcess(_, _, _, _, _, _))
84      .WillOnce(WithArg<2>(Invoke(this, &PPPDaemonTest::CaptureArgv)));
85
86  Error error;
87  PPPDaemon::Options options;
88  std::unique_ptr<ExternalTask> task(Start(options, "eth0", &error));
89
90  for (size_t i = 0; i < argv_.size(); ++i) {
91    if (argv_[i] == "plugin") {
92      EXPECT_EQ(argv_[i + 1], PPPDaemon::kShimPluginPath);
93    }
94  }
95}
96
97TEST_F(PPPDaemonTest, OptionsConverted) {
98  EXPECT_CALL(process_manager_, StartProcess(_, _, _, _, _, _))
99      .WillOnce(WithArg<2>(Invoke(this, &PPPDaemonTest::CaptureArgv)));
100
101  PPPDaemon::Options options;
102  options.no_detach = true;
103  options.no_default_route = true;
104  options.use_peer_dns = true;
105  options.lcp_echo_interval = 1;
106  options.lcp_echo_failure = 1;
107  options.max_fail = 1;
108  options.use_ipv6 = true;
109
110  Error error;
111  std::unique_ptr<ExternalTask> task(Start(options, "eth0", &error));
112
113  std::set<std::string> expected_arguments = {
114    "nodetach", "nodefaultroute", "usepeerdns", "lcp-echo-interval",
115    "lcp-echo-failure", "maxfail", "+ipv6", "ipv6cp-use-ipaddr",
116  };
117  for (const auto& argument : argv_) {
118    expected_arguments.erase(argument);
119  }
120  EXPECT_TRUE(expected_arguments.empty());
121}
122
123TEST_F(PPPDaemonTest, ErrorPropagated) {
124  EXPECT_CALL(process_manager_, StartProcess(_, _, _, _, _, _))
125      .WillOnce(Return(-1));
126
127  PPPDaemon::Options options;
128  Error error;
129  std::unique_ptr<ExternalTask> task(Start(options, "eth0", &error));
130
131  EXPECT_NE(error.type(), Error::kSuccess);
132  EXPECT_EQ(task.get(), nullptr);
133}
134
135}  // namespace shill
136