| // Copyright (c) 2012 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 "shill/l2tp_ipsec_driver.h" |
| |
| #include <base/file_util.h> |
| #include <base/files/scoped_temp_dir.h> |
| #include <base/memory/weak_ptr.h> |
| #include <base/string_util.h> |
| #include <chromeos/vpn-manager/service_error.h> |
| #include <gtest/gtest.h> |
| |
| #include "shill/event_dispatcher.h" |
| #include "shill/nice_mock_control.h" |
| #include "shill/mock_adaptors.h" |
| #include "shill/mock_certificate_file.h" |
| #include "shill/mock_device_info.h" |
| #include "shill/mock_external_task.h" |
| #include "shill/mock_glib.h" |
| #include "shill/mock_manager.h" |
| #include "shill/mock_metrics.h" |
| #include "shill/mock_nss.h" |
| #include "shill/mock_ppp_device.h" |
| #include "shill/mock_ppp_device_factory.h" |
| #include "shill/mock_vpn_service.h" |
| |
| using base::FilePath; |
| using std::find; |
| using std::map; |
| using std::string; |
| using std::vector; |
| using testing::_; |
| using testing::ElementsAreArray; |
| using testing::Mock; |
| using testing::NiceMock; |
| using testing::Return; |
| using testing::ReturnRef; |
| using testing::SetArgumentPointee; |
| using testing::StrictMock; |
| |
| namespace shill { |
| |
| class L2TPIPSecDriverTest : public testing::Test, |
| public RPCTaskDelegate { |
| public: |
| L2TPIPSecDriverTest() |
| : device_info_(&control_, &dispatcher_, &metrics_, &manager_), |
| metrics_(&dispatcher_), |
| manager_(&control_, &dispatcher_, &metrics_, &glib_), |
| driver_(new L2TPIPSecDriver(&control_, &dispatcher_, &metrics_, |
| &manager_, &device_info_, &glib_)), |
| service_(new MockVPNService(&control_, &dispatcher_, &metrics_, |
| &manager_, driver_)), |
| device_(new MockPPPDevice(&control_, &dispatcher_, &metrics_, &manager_, |
| kInterfaceName, kInterfaceIndex)), |
| certificate_file_(new MockCertificateFile()), |
| weak_ptr_factory_(this) { |
| driver_->nss_ = &nss_; |
| driver_->certificate_file_.reset(certificate_file_); // Passes ownership. |
| } |
| |
| virtual ~L2TPIPSecDriverTest() {} |
| |
| virtual void SetUp() { |
| ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| } |
| |
| virtual void TearDown() { |
| driver_->device_ = NULL; |
| driver_->service_ = NULL; |
| ASSERT_TRUE(temp_dir_.Delete()); |
| } |
| |
| protected: |
| static const char kInterfaceName[]; |
| static const int kInterfaceIndex; |
| |
| void SetArg(const string &arg, const string &value) { |
| driver_->args()->SetString(arg, value); |
| } |
| |
| void SetArgArray(const string &arg, const vector<string> &value) { |
| driver_->args()->SetStrings(arg, value); |
| } |
| |
| KeyValueStore *GetArgs() { |
| return driver_->args(); |
| } |
| |
| string GetProviderType() { |
| return driver_->GetProviderType(); |
| } |
| |
| void SetDevice(const PPPDeviceRefPtr &device) { |
| driver_->device_ = device; |
| } |
| |
| void SetService(const VPNServiceRefPtr &service) { |
| driver_->service_ = service; |
| } |
| |
| VPNServiceRefPtr GetService() { |
| return driver_->service_; |
| } |
| |
| void OnConnectTimeout() { |
| driver_->OnConnectTimeout(); |
| } |
| |
| void StartConnectTimeout(int timeout_seconds) { |
| driver_->StartConnectTimeout(timeout_seconds); |
| } |
| |
| bool IsConnectTimeoutStarted() { |
| return driver_->IsConnectTimeoutStarted(); |
| } |
| |
| bool IsPSKFileCleared(const FilePath &psk_file_path) { |
| return !file_util::PathExists(psk_file_path) && GetPSKFile().empty(); |
| } |
| |
| // Used to assert that a flag appears in the options. |
| void ExpectInFlags(const vector<string> &options, const string &flag, |
| const string &value); |
| |
| FilePath SetupPSKFile(); |
| |
| FilePath GetPSKFile() { return driver_->psk_file_; } |
| |
| void InvokeNotify(const string &reason, const map<string, string> &dict) { |
| driver_->Notify(reason, dict); |
| } |
| |
| FilePath FakeUpConnect() { |
| FilePath new_psk_file = SetupPSKFile(); |
| SetService(service_); |
| StartConnectTimeout(0); |
| return new_psk_file; |
| } |
| |
| void ExpectDeviceConnected(const map<string, string> &ppp_config) { |
| EXPECT_CALL(*device_, SetEnabled(true)); |
| EXPECT_CALL(*device_, SelectService(static_cast<ServiceRefPtr>(service_))); |
| EXPECT_CALL(*device_, UpdateIPConfigFromPPP(ppp_config, _)); |
| } |
| |
| void ExpectMetricsReported() { |
| Error unused_error; |
| PropertyStore store; |
| driver_->InitPropertyStore(&store); |
| store.SetStringProperty(kL2tpIpsecPskProperty, "x", &unused_error); |
| store.SetStringProperty(kL2tpIpsecPasswordProperty, "y", &unused_error); |
| EXPECT_CALL(metrics_, SendEnumToUMA( |
| Metrics::kMetricVpnDriver, |
| Metrics::kVpnDriverL2tpIpsec, |
| Metrics::kMetricVpnDriverMax)); |
| EXPECT_CALL(metrics_, SendEnumToUMA( |
| Metrics::kMetricVpnRemoteAuthenticationType, |
| Metrics::kVpnRemoteAuthenticationTypeL2tpIpsecPsk, |
| Metrics::kVpnRemoteAuthenticationTypeMax)); |
| EXPECT_CALL(metrics_, SendEnumToUMA( |
| Metrics::kMetricVpnUserAuthenticationType, |
| Metrics::kVpnUserAuthenticationTypeL2tpIpsecUsernamePassword, |
| Metrics::kVpnUserAuthenticationTypeMax)); |
| } |
| |
| // Inherited from RPCTaskDelegate. |
| virtual void GetLogin(string *user, string *password); |
| virtual void Notify(const string &reason, const map<string, string> &dict); |
| |
| base::ScopedTempDir temp_dir_; |
| NiceMockControl control_; |
| NiceMock<MockDeviceInfo> device_info_; |
| EventDispatcher dispatcher_; |
| MockMetrics metrics_; |
| MockGLib glib_; |
| MockManager manager_; |
| L2TPIPSecDriver *driver_; // Owned by |service_|. |
| scoped_refptr<MockVPNService> service_; |
| scoped_refptr<MockPPPDevice> device_; |
| MockNSS nss_; |
| MockCertificateFile *certificate_file_; // Owned by |driver_|. |
| base::WeakPtrFactory<L2TPIPSecDriverTest> weak_ptr_factory_; |
| }; |
| |
| const char L2TPIPSecDriverTest::kInterfaceName[] = "ppp0"; |
| const int L2TPIPSecDriverTest::kInterfaceIndex = 123; |
| |
| void L2TPIPSecDriverTest::GetLogin(string */*user*/, string */*password*/) {} |
| |
| void L2TPIPSecDriverTest::Notify( |
| const string &/*reason*/, const map<string, string> &/*dict*/) {} |
| |
| void L2TPIPSecDriverTest::ExpectInFlags( |
| const vector<string> &options, const string &flag, const string &value) { |
| vector<string>::const_iterator it = |
| find(options.begin(), options.end(), flag); |
| |
| ASSERT_TRUE(it != options.end()); // Don't crash below. |
| EXPECT_EQ(flag, *it); |
| it++; |
| ASSERT_TRUE(it != options.end()); // Don't crash below. |
| EXPECT_EQ(value, *it); |
| } |
| |
| FilePath L2TPIPSecDriverTest::SetupPSKFile() { |
| FilePath psk_file; |
| EXPECT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &psk_file)); |
| EXPECT_FALSE(psk_file.empty()); |
| EXPECT_TRUE(file_util::PathExists(psk_file)); |
| driver_->psk_file_ = psk_file; |
| return psk_file; |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, GetProviderType) { |
| EXPECT_EQ(kProviderL2tpIpsec, GetProviderType()); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, Cleanup) { |
| driver_->IdleService(); // Ensure no crash. |
| |
| FilePath psk_file = FakeUpConnect(); |
| driver_->device_ = device_; |
| driver_->external_task_.reset( |
| new MockExternalTask(&control_, |
| &glib_, |
| weak_ptr_factory_.GetWeakPtr(), |
| base::Callback<void(pid_t, int)>())); |
| EXPECT_CALL(*device_, DropConnection()); |
| EXPECT_CALL(*device_, SetEnabled(false)); |
| EXPECT_CALL(*service_, SetFailure(Service::kFailureBadPassphrase)); |
| driver_->FailService(Service::kFailureBadPassphrase); // Trigger Cleanup. |
| EXPECT_TRUE(IsPSKFileCleared(psk_file)); |
| EXPECT_FALSE(driver_->device_); |
| EXPECT_FALSE(driver_->service_); |
| EXPECT_FALSE(driver_->IsConnectTimeoutStarted()); |
| EXPECT_FALSE(driver_->external_task_); |
| |
| driver_->service_ = service_; |
| EXPECT_CALL(*service_, SetState(Service::kStateIdle)); |
| driver_->IdleService(); |
| EXPECT_FALSE(driver_->service_); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, DeletePSKFile) { |
| FilePath psk_file = SetupPSKFile(); |
| driver_->DeletePSKFile(); |
| EXPECT_TRUE(IsPSKFileCleared(psk_file)); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, InitOptionsNoHost) { |
| Error error; |
| vector<string> options; |
| EXPECT_FALSE(driver_->InitOptions(&options, &error)); |
| EXPECT_EQ(Error::kInvalidArguments, error.type()); |
| EXPECT_TRUE(options.empty()); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, InitOptions) { |
| static const char kHost[] = "192.168.2.254"; |
| static const char kCaCertNSS[] = "{1234}"; |
| static const char kPSK[] = "foobar"; |
| |
| SetArg(kProviderHostProperty, kHost); |
| SetArg(kL2tpIpsecCaCertNssProperty, kCaCertNSS); |
| SetArg(kL2tpIpsecPskProperty, kPSK); |
| |
| FilePath empty_cert; |
| EXPECT_CALL(nss_, GetDERCertfile(kCaCertNSS, _)).WillOnce(Return(empty_cert)); |
| |
| const FilePath temp_dir(temp_dir_.path()); |
| EXPECT_CALL(manager_, run_path()).WillOnce(ReturnRef(temp_dir)); |
| |
| Error error; |
| vector<string> options; |
| EXPECT_TRUE(driver_->InitOptions(&options, &error)); |
| EXPECT_TRUE(error.IsSuccess()); |
| |
| ExpectInFlags(options, "--remote_host", kHost); |
| ASSERT_FALSE(driver_->psk_file_.empty()); |
| ExpectInFlags(options, "--psk_file", driver_->psk_file_.value()); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, InitPSKOptions) { |
| Error error; |
| vector<string> options; |
| static const char kPSK[] = "foobar"; |
| const FilePath bad_dir("/non/existent/directory"); |
| const FilePath temp_dir(temp_dir_.path()); |
| EXPECT_CALL(manager_, run_path()) |
| .WillOnce(ReturnRef(bad_dir)) |
| .WillOnce(ReturnRef(temp_dir)); |
| |
| EXPECT_TRUE(driver_->InitPSKOptions(&options, &error)); |
| EXPECT_TRUE(options.empty()); |
| EXPECT_TRUE(error.IsSuccess()); |
| |
| SetArg(kL2tpIpsecPskProperty, kPSK); |
| |
| EXPECT_FALSE(driver_->InitPSKOptions(&options, &error)); |
| EXPECT_TRUE(options.empty()); |
| EXPECT_EQ(Error::kInternalError, error.type()); |
| error.Reset(); |
| |
| EXPECT_TRUE(driver_->InitPSKOptions(&options, &error)); |
| ASSERT_FALSE(driver_->psk_file_.empty()); |
| ExpectInFlags(options, "--psk_file", driver_->psk_file_.value()); |
| EXPECT_TRUE(error.IsSuccess()); |
| string contents; |
| EXPECT_TRUE( |
| file_util::ReadFileToString(driver_->psk_file_, &contents)); |
| EXPECT_EQ(kPSK, contents); |
| struct stat buf; |
| ASSERT_EQ(0, stat(driver_->psk_file_.value().c_str(), &buf)); |
| EXPECT_EQ(S_IFREG | S_IRUSR | S_IWUSR, buf.st_mode); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, InitNSSOptions) { |
| static const char kHost[] = "192.168.2.254"; |
| static const char kCaCertNSS[] = "{1234}"; |
| static const char kNSSCertfile[] = "/tmp/nss-cert"; |
| FilePath empty_cert; |
| FilePath nss_cert(kNSSCertfile); |
| SetArg(kProviderHostProperty, kHost); |
| SetArg(kL2tpIpsecCaCertNssProperty, kCaCertNSS); |
| EXPECT_CALL(nss_, |
| GetDERCertfile(kCaCertNSS, |
| ElementsAreArray(kHost, arraysize(kHost) - 1))) |
| .WillOnce(Return(empty_cert)) |
| .WillOnce(Return(nss_cert)); |
| |
| vector<string> options; |
| driver_->InitNSSOptions(&options); |
| EXPECT_TRUE(options.empty()); |
| driver_->InitNSSOptions(&options); |
| ExpectInFlags(options, "--server_ca_file", kNSSCertfile); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, InitPEMOptions) { |
| const vector<string> kCaCertPEM{ "Insert PEM encoded data here" }; |
| static const char kPEMCertfile[] = "/tmp/der-file-from-pem-cert"; |
| FilePath empty_cert; |
| FilePath pem_cert(kPEMCertfile); |
| SetArgArray(kL2tpIpsecCaCertPemProperty, kCaCertPEM); |
| EXPECT_CALL(*certificate_file_, CreatePEMFromStrings(kCaCertPEM)) |
| .WillOnce(Return(empty_cert)) |
| .WillOnce(Return(pem_cert)); |
| |
| vector<string> options; |
| driver_->InitPEMOptions(&options); |
| EXPECT_TRUE(options.empty()); |
| driver_->InitPEMOptions(&options); |
| ExpectInFlags(options, "--server_ca_file", kPEMCertfile); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, AppendValueOption) { |
| static const char kOption[] = "--l2tpipsec-option"; |
| static const char kProperty[] = "L2TPIPSec.SomeProperty"; |
| static const char kValue[] = "some-property-value"; |
| static const char kOption2[] = "--l2tpipsec-option2"; |
| static const char kProperty2[] = "L2TPIPSec.SomeProperty2"; |
| static const char kValue2[] = "some-property-value2"; |
| |
| vector<string> options; |
| EXPECT_FALSE( |
| driver_->AppendValueOption( |
| "L2TPIPSec.UnknownProperty", kOption, &options)); |
| EXPECT_TRUE(options.empty()); |
| |
| SetArg(kProperty, ""); |
| EXPECT_FALSE(driver_->AppendValueOption(kProperty, kOption, &options)); |
| EXPECT_TRUE(options.empty()); |
| |
| SetArg(kProperty, kValue); |
| SetArg(kProperty2, kValue2); |
| EXPECT_TRUE(driver_->AppendValueOption(kProperty, kOption, &options)); |
| EXPECT_TRUE(driver_->AppendValueOption(kProperty2, kOption2, &options)); |
| EXPECT_EQ(4, options.size()); |
| EXPECT_EQ(kOption, options[0]); |
| EXPECT_EQ(kValue, options[1]); |
| EXPECT_EQ(kOption2, options[2]); |
| EXPECT_EQ(kValue2, options[3]); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, AppendFlag) { |
| static const char kTrueOption[] = "--l2tpipsec-option"; |
| static const char kFalseOption[] = "--nol2tpipsec-option"; |
| static const char kProperty[] = "L2TPIPSec.SomeProperty"; |
| static const char kTrueOption2[] = "--l2tpipsec-option2"; |
| static const char kFalseOption2[] = "--nol2tpipsec-option2"; |
| static const char kProperty2[] = "L2TPIPSec.SomeProperty2"; |
| |
| vector<string> options; |
| EXPECT_FALSE(driver_->AppendFlag("L2TPIPSec.UnknownProperty", |
| kTrueOption, kFalseOption, &options)); |
| EXPECT_TRUE(options.empty()); |
| |
| SetArg(kProperty, ""); |
| EXPECT_FALSE( |
| driver_->AppendFlag(kProperty, kTrueOption, kFalseOption, &options)); |
| EXPECT_TRUE(options.empty()); |
| |
| SetArg(kProperty, "true"); |
| SetArg(kProperty2, "false"); |
| EXPECT_TRUE( |
| driver_->AppendFlag(kProperty, kTrueOption, kFalseOption, &options)); |
| EXPECT_TRUE( |
| driver_->AppendFlag(kProperty2, kTrueOption2, kFalseOption2, &options)); |
| EXPECT_EQ(2, options.size()); |
| EXPECT_EQ(kTrueOption, options[0]); |
| EXPECT_EQ(kFalseOption2, options[1]); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, GetLogin) { |
| static const char kUser[] = "joesmith"; |
| static const char kPassword[] = "random-password"; |
| string user, password; |
| SetArg(kL2tpIpsecUserProperty, kUser); |
| driver_->GetLogin(&user, &password); |
| EXPECT_TRUE(user.empty()); |
| EXPECT_TRUE(password.empty()); |
| SetArg(kL2tpIpsecUserProperty, ""); |
| SetArg(kL2tpIpsecPasswordProperty, kPassword); |
| driver_->GetLogin(&user, &password); |
| EXPECT_TRUE(user.empty()); |
| EXPECT_TRUE(password.empty()); |
| SetArg(kL2tpIpsecUserProperty, kUser); |
| driver_->GetLogin(&user, &password); |
| EXPECT_EQ(kUser, user); |
| EXPECT_EQ(kPassword, password); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, OnL2TPIPSecVPNDied) { |
| const int kPID = 123456; |
| driver_->service_ = service_; |
| EXPECT_CALL(*service_, SetFailure(Service::kFailureDNSLookup)); |
| driver_->OnL2TPIPSecVPNDied( |
| kPID, vpn_manager::kServiceErrorResolveHostnameFailed << 8); |
| EXPECT_FALSE(driver_->service_); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, SpawnL2TPIPSecVPN) { |
| Error error; |
| // Fail without sufficient arguments. |
| EXPECT_FALSE(driver_->SpawnL2TPIPSecVPN(&error)); |
| EXPECT_TRUE(error.IsFailure()); |
| |
| // Provide the required arguments. |
| static const char kHost[] = "192.168.2.254"; |
| SetArg(kProviderHostProperty, kHost); |
| |
| // TODO(quiche): Instead of setting expectations based on what |
| // ExternalTask will call, mock out ExternalTask. Non-trivial, |
| // though, because ExternalTask is constructed during the |
| // call to driver_->Connect. |
| EXPECT_CALL(glib_, SpawnAsync(_, _, _, _, _, _, _, _)). |
| WillOnce(Return(false)). |
| WillOnce(Return(true)); |
| EXPECT_CALL(glib_, ChildWatchAdd(_, _, _)); |
| |
| EXPECT_FALSE(driver_->SpawnL2TPIPSecVPN(&error)); |
| EXPECT_FALSE(driver_->external_task_); |
| EXPECT_TRUE(driver_->SpawnL2TPIPSecVPN(&error)); |
| EXPECT_TRUE(driver_->external_task_); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, Connect) { |
| EXPECT_CALL(*service_, SetState(Service::kStateConfiguring)); |
| static const char kHost[] = "192.168.2.254"; |
| SetArg(kProviderHostProperty, kHost); |
| |
| // TODO(quiche): Instead of setting expectations based on what |
| // ExternalTask will call, mock out ExternalTask. Non-trivial, |
| // though, because ExternalTask is constructed during the |
| // call to driver_->Connect. |
| EXPECT_CALL(glib_, SpawnAsync(_, _, _, _, _, _, _, _)).WillOnce(Return(true)); |
| EXPECT_CALL(glib_, ChildWatchAdd(_, _, _)).WillOnce(Return(1)); |
| |
| Error error; |
| driver_->Connect(service_, &error); |
| EXPECT_TRUE(error.IsSuccess()); |
| EXPECT_TRUE(driver_->IsConnectTimeoutStarted()); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, Disconnect) { |
| driver_->device_ = device_; |
| driver_->service_ = service_; |
| EXPECT_CALL(*device_, DropConnection()); |
| EXPECT_CALL(*device_, SetEnabled(false)); |
| EXPECT_CALL(*service_, SetState(Service::kStateIdle)); |
| driver_->Disconnect(); |
| EXPECT_FALSE(driver_->device_); |
| EXPECT_FALSE(driver_->service_); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, OnConnectionDisconnected) { |
| driver_->service_ = service_; |
| EXPECT_CALL(*service_, SetState(Service::kStateIdle)); |
| driver_->OnConnectionDisconnected(); |
| EXPECT_FALSE(driver_->service_); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, OnConnectTimeout) { |
| StartConnectTimeout(0); |
| SetService(service_); |
| EXPECT_CALL(*service_, SetFailure(Service::kFailureConnect)); |
| OnConnectTimeout(); |
| EXPECT_FALSE(GetService()); |
| EXPECT_FALSE(IsConnectTimeoutStarted()); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, InitPropertyStore) { |
| // Sanity test property store initialization. |
| PropertyStore store; |
| driver_->InitPropertyStore(&store); |
| const string kUser = "joe"; |
| Error error; |
| EXPECT_TRUE(store.SetStringProperty(kL2tpIpsecUserProperty, kUser, &error)); |
| EXPECT_TRUE(error.IsSuccess()); |
| EXPECT_EQ(kUser, GetArgs()->LookupString(kL2tpIpsecUserProperty, "")); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, GetProvider) { |
| PropertyStore store; |
| driver_->InitPropertyStore(&store); |
| { |
| KeyValueStore props; |
| Error error; |
| EXPECT_TRUE( |
| store.GetKeyValueStoreProperty(kProviderProperty, &props, &error)); |
| EXPECT_TRUE(props.LookupBool(kPassphraseRequiredProperty, false)); |
| EXPECT_TRUE(props.LookupBool(kL2tpIpsecPskRequiredProperty, false)); |
| } |
| { |
| KeyValueStore props; |
| SetArg(kL2tpIpsecPasswordProperty, "random-password"); |
| SetArg(kL2tpIpsecPskProperty, "random-psk"); |
| Error error; |
| EXPECT_TRUE( |
| store.GetKeyValueStoreProperty(kProviderProperty, &props, &error)); |
| EXPECT_FALSE(props.LookupBool(kPassphraseRequiredProperty, true)); |
| EXPECT_FALSE( |
| props.LookupBool(kL2tpIpsecPskRequiredProperty, true)); |
| EXPECT_FALSE(props.ContainsString(kL2tpIpsecPasswordProperty)); |
| } |
| } |
| |
| namespace { |
| MATCHER_P(IsIPAddress, address, "") { |
| IPAddress ip_address(IPAddress::kFamilyIPv4); |
| EXPECT_TRUE(ip_address.SetAddressFromString(address)); |
| return ip_address.Equals(arg); |
| } |
| } // namespace |
| |
| TEST_F(L2TPIPSecDriverTest, Notify) { |
| map<string, string> config{{kPPPInterfaceName, kInterfaceName}}; |
| MockPPPDeviceFactory *mock_ppp_device_factory = |
| MockPPPDeviceFactory::GetInstance(); |
| FilePath psk_file = FakeUpConnect(); |
| driver_->ppp_device_factory_ = mock_ppp_device_factory; |
| EXPECT_CALL(device_info_, GetIndex(kInterfaceName)) |
| .WillOnce(Return(kInterfaceIndex)); |
| EXPECT_CALL(*mock_ppp_device_factory, |
| CreatePPPDevice(_, _, _, _, kInterfaceName, kInterfaceIndex)) |
| .WillOnce(Return(device_)); |
| |
| // Make sure that a notification of an intermediate state doesn't cause |
| // the driver to fail the connection. |
| ASSERT_TRUE(driver_->service_); |
| VPNServiceConstRefPtr service = driver_->service_; |
| InvokeNotify(kPPPReasonAuthenticating, config); |
| InvokeNotify(kPPPReasonAuthenticated, config); |
| EXPECT_TRUE(driver_->service_); |
| EXPECT_FALSE(service->IsFailed()); |
| |
| ExpectDeviceConnected(config); |
| ExpectMetricsReported(); |
| InvokeNotify(kPPPReasonConnect, config); |
| EXPECT_TRUE(IsPSKFileCleared(psk_file)); |
| EXPECT_FALSE(IsConnectTimeoutStarted()); |
| } |
| |
| |
| TEST_F(L2TPIPSecDriverTest, NotifyWithExistingDevice) { |
| map<string, string> config{{kPPPInterfaceName, kInterfaceName}}; |
| MockPPPDeviceFactory *mock_ppp_device_factory = |
| MockPPPDeviceFactory::GetInstance(); |
| FilePath psk_file = FakeUpConnect(); |
| driver_->ppp_device_factory_ = mock_ppp_device_factory; |
| SetDevice(device_); |
| EXPECT_CALL(device_info_, GetIndex(kInterfaceName)) |
| .WillOnce(Return(kInterfaceIndex)); |
| EXPECT_CALL(*mock_ppp_device_factory, |
| CreatePPPDevice(_, _, _, _, _, _)).Times(0); |
| ExpectDeviceConnected(config); |
| ExpectMetricsReported(); |
| InvokeNotify(kPPPReasonConnect, config); |
| EXPECT_TRUE(IsPSKFileCleared(psk_file)); |
| EXPECT_FALSE(IsConnectTimeoutStarted()); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, NotifyDisconnected) { |
| map<string, string> dict; |
| base::Callback<void(pid_t, int)> death_callback; |
| MockExternalTask *local_external_task = |
| new MockExternalTask(&control_, &glib_, weak_ptr_factory_.GetWeakPtr(), |
| death_callback); |
| driver_->device_ = device_; |
| driver_->external_task_.reset(local_external_task); // passes ownership |
| EXPECT_CALL(*device_, DropConnection()); |
| EXPECT_CALL(*device_, SetEnabled(false)); |
| EXPECT_CALL(*local_external_task, OnDelete()) |
| .Times(0); // Not until event loop. |
| driver_->Notify(kPPPReasonDisconnect, dict); |
| EXPECT_FALSE(driver_->device_); |
| EXPECT_FALSE(driver_->external_task_.get()); |
| Mock::VerifyAndClearExpectations(local_external_task); |
| |
| EXPECT_CALL(*local_external_task, OnDelete()); |
| dispatcher_.PostTask(MessageLoop::QuitClosure()); |
| dispatcher_.DispatchForever(); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, VerifyPaths) { |
| // Ensure that the various path constants that the L2TP/IPSec driver uses |
| // actually exists in the build image. Due to build dependencies, they should |
| // already exist by the time we run unit tests. |
| |
| // The L2TPIPSecDriver path constants are absolute. FilePath::Append asserts |
| // that its argument is not an absolute path, so we need to strip the leading |
| // separators. There's nothing built into FilePath to do so. |
| static const char *kPaths[] = { |
| L2TPIPSecDriver::kL2TPIPSecVPNPath, |
| PPPDevice::kPluginPath, |
| }; |
| for (size_t i = 0; i < arraysize(kPaths); i++) { |
| string path(kPaths[i]); |
| TrimString(path, FilePath::kSeparators, &path); |
| EXPECT_TRUE(file_util::PathExists(FilePath(SYSROOT).Append(path))) |
| << kPaths[i]; |
| } |
| } |
| |
| } // namespace shill |