// // Copyright (C) 2012 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "shill/vpn/l2tp_ipsec_driver.h" #include <base/files/file_util.h> #include <base/files/scoped_temp_dir.h> #include <base/memory/weak_ptr.h> #include <base/strings/string_util.h> #include <base/strings/stringprintf.h> #include <gtest/gtest.h> #include <vpn-manager/service_error.h> #include "shill/ipconfig.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_manager.h" #include "shill/mock_metrics.h" #include "shill/mock_ppp_device.h" #include "shill/mock_ppp_device_factory.h" #include "shill/mock_process_manager.h" #include "shill/nice_mock_control.h" #include "shill/test_event_dispatcher.h" #include "shill/vpn/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_), driver_(new L2TPIPSecDriver(&control_, &dispatcher_, &metrics_, &manager_, &device_info_, &process_manager_)), 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_->certificate_file_.reset(certificate_file_); // Passes ownership. } virtual ~L2TPIPSecDriverTest() {} virtual void SetUp() { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } virtual void TearDown() { driver_->device_ = nullptr; driver_->service_ = nullptr; 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() const { return driver_->IsConnectTimeoutStarted(); } bool IsPSKFileCleared(const FilePath& psk_file_path) const { return !base::PathExists(psk_file_path) && GetPSKFile().empty(); } bool IsXauthCredentialsFileCleared( const FilePath& xauth_credentials_file_path) const { return !base::PathExists(xauth_credentials_file_path) && GetXauthCredentialsFile().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 SetupXauthCredentialsFile(); FilePath GetPSKFile() const { return driver_->psk_file_; } FilePath GetXauthCredentialsFile() const { return driver_->xauth_credentials_file_; } void InvokeNotify(const string& reason, const map<string, string>& dict) { driver_->Notify(reason, dict); } void FakeUpConnect(FilePath* psk_file, FilePath* xauth_credentials_file) { *psk_file = SetupPSKFile(); *xauth_credentials_file = SetupXauthCredentialsFile(); SetService(service_); StartConnectTimeout(0); } void ExpectDeviceConnected(const map<string, string>& ppp_config) { EXPECT_CALL(*device_, SetEnabled(true)); EXPECT_CALL(*device_, SelectService(static_cast<ServiceRefPtr>(service_))); EXPECT_CALL(*device_, UpdateIPConfigFromPPPWithMTU( ppp_config, _, IPConfig::kMinIPv6MTU)); } 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_; EventDispatcherForTest dispatcher_; MockMetrics metrics_; MockProcessManager process_manager_; MockManager manager_; L2TPIPSecDriver* driver_; // Owned by |service_|. scoped_refptr<MockVPNService> service_; scoped_refptr<MockPPPDevice> device_; 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) { string flagValue = base::StringPrintf("%s=%s", flag.c_str(), value.c_str()); vector<string>::const_iterator it = find(options.begin(), options.end(), flagValue); EXPECT_TRUE(it != options.end()); } FilePath L2TPIPSecDriverTest::SetupPSKFile() { FilePath psk_file; EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &psk_file)); EXPECT_FALSE(psk_file.empty()); EXPECT_TRUE(base::PathExists(psk_file)); driver_->psk_file_ = psk_file; return psk_file; } FilePath L2TPIPSecDriverTest::SetupXauthCredentialsFile() { FilePath xauth_credentials_file; EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &xauth_credentials_file)); EXPECT_FALSE(xauth_credentials_file.empty()); EXPECT_TRUE(base::PathExists(xauth_credentials_file)); driver_->xauth_credentials_file_ = xauth_credentials_file; return xauth_credentials_file; } TEST_F(L2TPIPSecDriverTest, GetProviderType) { EXPECT_EQ(kProviderL2tpIpsec, GetProviderType()); } TEST_F(L2TPIPSecDriverTest, Cleanup) { driver_->IdleService(); // Ensure no crash. FilePath psk_file; FilePath xauth_credentials_file; FakeUpConnect(&psk_file, &xauth_credentials_file); driver_->device_ = device_; driver_->external_task_.reset( new MockExternalTask(&control_, &process_manager_, 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_TRUE(IsXauthCredentialsFileCleared(xauth_credentials_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, DeleteTemporaryFiles) { FilePath psk_file = SetupPSKFile(); FilePath xauth_credentials_file = SetupXauthCredentialsFile(); driver_->DeleteTemporaryFiles(); EXPECT_TRUE(IsPSKFileCleared(psk_file)); EXPECT_TRUE(IsXauthCredentialsFileCleared(xauth_credentials_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 kPSK[] = "foobar"; static const char kXauthUser[] = "silly"; static const char kXauthPassword[] = "rabbit"; const vector<string> kCaCertPEM{ "Insert PEM encoded data here" }; static const char kPEMCertfile[] = "/tmp/der-file-from-pem-cert"; FilePath pem_cert(kPEMCertfile); SetArg(kProviderHostProperty, kHost); SetArg(kL2tpIpsecPskProperty, kPSK); SetArg(kL2tpIpsecXauthUserProperty, kXauthUser); SetArg(kL2tpIpsecXauthPasswordProperty, kXauthPassword); SetArgArray(kL2tpIpsecCaCertPemProperty, kCaCertPEM); EXPECT_CALL(*certificate_file_, CreatePEMFromStrings(kCaCertPEM)) .WillOnce(Return(pem_cert)); const FilePath temp_dir(temp_dir_.path()); // Once each for PSK and Xauth options. EXPECT_CALL(manager_, run_path()) .WillOnce(ReturnRef(temp_dir)) .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()); ASSERT_FALSE(driver_->xauth_credentials_file_.empty()); ExpectInFlags(options, "--xauth_credentials_file", driver_->xauth_credentials_file_.value()); ExpectInFlags(options, "--server_ca_file", kPEMCertfile); } 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(base::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, 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, InitXauthOptions) { vector<string> options; EXPECT_CALL(manager_, run_path()).Times(0); { Error error; EXPECT_TRUE(driver_->InitXauthOptions(&options, &error)); EXPECT_TRUE(error.IsSuccess()); } EXPECT_TRUE(options.empty()); static const char kUser[] = "foobar"; SetArg(kL2tpIpsecXauthUserProperty, kUser); { Error error; EXPECT_FALSE(driver_->InitXauthOptions(&options, &error)); EXPECT_EQ(Error::kInvalidArguments, error.type()); } EXPECT_TRUE(options.empty()); static const char kPassword[] = "foobar"; SetArg(kL2tpIpsecXauthUserProperty, ""); SetArg(kL2tpIpsecXauthPasswordProperty, kPassword); { Error error; EXPECT_FALSE(driver_->InitXauthOptions(&options, &error)); EXPECT_EQ(Error::kInvalidArguments, error.type()); } EXPECT_TRUE(options.empty()); Mock::VerifyAndClearExpectations(&manager_); SetArg(kL2tpIpsecXauthUserProperty, kUser); 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)); { Error error; EXPECT_FALSE(driver_->InitXauthOptions(&options, &error)); EXPECT_EQ(Error::kInternalError, error.type()); } EXPECT_TRUE(options.empty()); { Error error; EXPECT_TRUE(driver_->InitXauthOptions(&options, &error)); EXPECT_TRUE(error.IsSuccess()); } ASSERT_FALSE(driver_->xauth_credentials_file_.empty()); ExpectInFlags(options, "--xauth_credentials_file", driver_->xauth_credentials_file_.value()); string contents; EXPECT_TRUE( base::ReadFileToString(driver_->xauth_credentials_file_, &contents)); string expected_contents(string(kUser) + "\n" + kPassword + "\n"); EXPECT_EQ(expected_contents, contents); struct stat buf; ASSERT_EQ(0, stat(driver_->xauth_credentials_file_.value().c_str(), &buf)); EXPECT_EQ(S_IFREG | S_IRUSR | S_IWUSR, buf.st_mode); } 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(2, options.size()); EXPECT_EQ(base::StringPrintf("%s=%s", kOption, kValue), options[0]); EXPECT_EQ(base::StringPrintf("%s=%s", kOption2, kValue2), options[1]); } 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(process_manager_, StartProcess(_, _, _, _, _, _)) .WillOnce(Return(-1)) .WillOnce(Return(1)); EXPECT_FALSE(driver_->SpawnL2TPIPSecVPN(&error)); EXPECT_FALSE(driver_->external_task_); EXPECT_TRUE(driver_->SpawnL2TPIPSecVPN(&error)); EXPECT_NE(nullptr, 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(process_manager_, StartProcess(_, _, _, _, _, _)) .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; SetArg(kL2tpIpsecClientCertIdProperty, ""); EXPECT_TRUE( store.GetKeyValueStoreProperty(kProviderProperty, &props, &error)); EXPECT_TRUE(props.LookupBool(kPassphraseRequiredProperty, false)); EXPECT_TRUE(props.LookupBool(kL2tpIpsecPskRequiredProperty, false)); } { KeyValueStore props; Error error; SetArg(kL2tpIpsecClientCertIdProperty, "some-cert-id"); EXPECT_TRUE( store.GetKeyValueStoreProperty(kProviderProperty, &props, &error)); EXPECT_TRUE(props.LookupBool(kPassphraseRequiredProperty, false)); EXPECT_FALSE(props.LookupBool(kL2tpIpsecPskRequiredProperty, true)); SetArg(kL2tpIpsecClientCertIdProperty, ""); } { 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; FilePath xauth_credentials_file; FakeUpConnect(&psk_file, &xauth_credentials_file); 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_.get())); // 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_TRUE(IsXauthCredentialsFileCleared(xauth_credentials_file)); EXPECT_FALSE(IsConnectTimeoutStarted()); } TEST_F(L2TPIPSecDriverTest, NotifyWithExistingDevice) { map<string, string> config{{kPPPInterfaceName, kInterfaceName}}; MockPPPDeviceFactory* mock_ppp_device_factory = MockPPPDeviceFactory::GetInstance(); FilePath psk_file; FilePath xauth_credentials_file; FakeUpConnect(&psk_file, &xauth_credentials_file); 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_TRUE(IsXauthCredentialsFileCleared(xauth_credentials_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_, &process_manager_, 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(base::MessageLoop::QuitWhenIdleClosure()); dispatcher_.DispatchForever(); } } // namespace shill