// Copyright (c) 2012 The Chromium 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 "base/bind.h" #include "base/values.h" #include "chromeos/dbus/shill_client_unittest_base.h" #include "chromeos/dbus/shill_manager_client.h" #include "dbus/message.h" #include "dbus/object_path.h" #include "dbus/values_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/cros_system_api/dbus/service_constants.h" using testing::_; using testing::ByRef; namespace chromeos { namespace { void ExpectStringArguments(const std::vector& arguments, dbus::MessageReader* reader) { for (std::vector::const_iterator iter = arguments.begin(); iter != arguments.end(); ++iter) { std::string arg_string; ASSERT_TRUE(reader->PopString(&arg_string)); EXPECT_EQ(*iter, arg_string); } EXPECT_FALSE(reader->HasMoreData()); } void ExpectStringArgumentsFollowedByObjectPath( const std::vector& arguments, const dbus::ObjectPath& object_path, dbus::MessageReader* reader) { for (std::vector::const_iterator iter = arguments.begin(); iter != arguments.end(); ++iter) { std::string arg_string; ASSERT_TRUE(reader->PopString(&arg_string)); EXPECT_EQ(*iter, arg_string); } dbus::ObjectPath path; ASSERT_TRUE(reader->PopObjectPath(&path)); EXPECT_EQ(object_path, path); EXPECT_FALSE(reader->HasMoreData()); } } // namespace class ShillManagerClientTest : public ShillClientUnittestBase { public: ShillManagerClientTest() : ShillClientUnittestBase(shill::kFlimflamManagerInterface, dbus::ObjectPath(shill::kFlimflamServicePath)) { } virtual void SetUp() { ShillClientUnittestBase::SetUp(); // Create a client with the mock bus. client_.reset(ShillManagerClient::Create()); client_->Init(mock_bus_.get()); // Run the message loop to run the signal connection result callback. message_loop_.RunUntilIdle(); } virtual void TearDown() { ShillClientUnittestBase::TearDown(); } protected: scoped_ptr client_; }; TEST_F(ShillManagerClientTest, PropertyChanged) { // Create a signal. base::FundamentalValue kOfflineMode(true); dbus::Signal signal(shill::kFlimflamManagerInterface, shill::kMonitorPropertyChanged); dbus::MessageWriter writer(&signal); writer.AppendString(shill::kOfflineModeProperty); dbus::AppendBasicTypeValueData(&writer, kOfflineMode); // Set expectations. MockPropertyChangeObserver observer; EXPECT_CALL(observer, OnPropertyChanged(shill::kOfflineModeProperty, ValueEq(ByRef(kOfflineMode)))).Times(1); // Add the observer client_->AddPropertyChangedObserver(&observer); // Run the signal callback. SendPropertyChangedSignal(&signal); // Remove the observer. client_->RemovePropertyChangedObserver(&observer); // Make sure it's not called anymore. EXPECT_CALL(observer, OnPropertyChanged(_, _)).Times(0); // Run the signal callback again and make sure the observer isn't called. SendPropertyChangedSignal(&signal); } TEST_F(ShillManagerClientTest, GetProperties) { // Create response. scoped_ptr response(dbus::Response::CreateEmpty()); dbus::MessageWriter writer(response.get()); dbus::MessageWriter array_writer(NULL); writer.OpenArray("{sv}", &array_writer); dbus::MessageWriter entry_writer(NULL); array_writer.OpenDictEntry(&entry_writer); entry_writer.AppendString(shill::kOfflineModeProperty); entry_writer.AppendVariantOfBool(true); array_writer.CloseContainer(&entry_writer); writer.CloseContainer(&array_writer); // Create the expected value. base::DictionaryValue value; value.SetWithoutPathExpansion(shill::kOfflineModeProperty, new base::FundamentalValue(true)); // Set expectations. PrepareForMethodCall(shill::kGetPropertiesFunction, base::Bind(&ExpectNoArgument), response.get()); // Call method. client_->GetProperties(base::Bind(&ExpectDictionaryValueResult, &value)); // Run the message loop. message_loop_.RunUntilIdle(); } TEST_F(ShillManagerClientTest, GetNetworksForGeolocation) { // Create response. scoped_ptr response(dbus::Response::CreateEmpty()); dbus::MessageWriter writer(response.get()); dbus::MessageWriter type_dict_writer(NULL); writer.OpenArray("{sv}", &type_dict_writer); dbus::MessageWriter type_entry_writer(NULL); type_dict_writer.OpenDictEntry(&type_entry_writer); type_entry_writer.AppendString(shill::kTypeWifi); dbus::MessageWriter variant_writer(NULL); type_entry_writer.OpenVariant("aa{ss}", &variant_writer); dbus::MessageWriter wap_list_writer(NULL); variant_writer.OpenArray("a{ss}", &wap_list_writer); dbus::MessageWriter property_dict_writer(NULL); wap_list_writer.OpenArray("{ss}", &property_dict_writer); dbus::MessageWriter property_entry_writer(NULL); property_dict_writer.OpenDictEntry(&property_entry_writer); property_entry_writer.AppendString(shill::kGeoMacAddressProperty); property_entry_writer.AppendString("01:23:45:67:89:AB"); property_dict_writer.CloseContainer(&property_entry_writer); wap_list_writer.CloseContainer(&property_dict_writer); variant_writer.CloseContainer(&wap_list_writer); type_entry_writer.CloseContainer(&wap_list_writer); type_dict_writer.CloseContainer(&type_entry_writer); writer.CloseContainer(&type_dict_writer); // Create the expected value. base::DictionaryValue type_dict_value; base::ListValue* type_entry_value = new base::ListValue; base::DictionaryValue* property_dict_value = new base::DictionaryValue; property_dict_value->SetWithoutPathExpansion( shill::kGeoMacAddressProperty, new base::StringValue("01:23:45:67:89:AB")); type_entry_value->Append(property_dict_value); type_dict_value.SetWithoutPathExpansion("wifi", type_entry_value); // Set expectations. PrepareForMethodCall(shill::kGetNetworksForGeolocation, base::Bind(&ExpectNoArgument), response.get()); // Call method. client_->GetNetworksForGeolocation(base::Bind(&ExpectDictionaryValueResult, &type_dict_value)); // Run the message loop. message_loop_.RunUntilIdle(); } TEST_F(ShillManagerClientTest, SetProperty) { // Create response. scoped_ptr response(dbus::Response::CreateEmpty()); // Set expectations. base::StringValue value("portal list"); PrepareForMethodCall(shill::kSetPropertyFunction, base::Bind(ExpectStringAndValueArguments, shill::kCheckPortalListProperty, &value), response.get()); // Call method. MockClosure mock_closure; MockErrorCallback mock_error_callback; client_->SetProperty(shill::kCheckPortalListProperty, value, mock_closure.GetCallback(), mock_error_callback.GetCallback()); EXPECT_CALL(mock_closure, Run()).Times(1); EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0); // Run the message loop. message_loop_.RunUntilIdle(); } TEST_F(ShillManagerClientTest, RequestScan) { // Create response. scoped_ptr response(dbus::Response::CreateEmpty()); // Set expectations. PrepareForMethodCall(shill::kRequestScanFunction, base::Bind(&ExpectStringArgument, shill::kTypeWifi), response.get()); // Call method. MockClosure mock_closure; MockErrorCallback mock_error_callback; client_->RequestScan(shill::kTypeWifi, mock_closure.GetCallback(), mock_error_callback.GetCallback()); EXPECT_CALL(mock_closure, Run()).Times(1); EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0); // Run the message loop. message_loop_.RunUntilIdle(); } TEST_F(ShillManagerClientTest, EnableTechnology) { // Create response. scoped_ptr response(dbus::Response::CreateEmpty()); // Set expectations. PrepareForMethodCall(shill::kEnableTechnologyFunction, base::Bind(&ExpectStringArgument, shill::kTypeWifi), response.get()); // Call method. MockClosure mock_closure; MockErrorCallback mock_error_callback; client_->EnableTechnology(shill::kTypeWifi, mock_closure.GetCallback(), mock_error_callback.GetCallback()); EXPECT_CALL(mock_closure, Run()).Times(1); EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0); // Run the message loop. message_loop_.RunUntilIdle(); } TEST_F(ShillManagerClientTest, DisableTechnology) { // Create response. scoped_ptr response(dbus::Response::CreateEmpty()); // Set expectations. PrepareForMethodCall(shill::kDisableTechnologyFunction, base::Bind(&ExpectStringArgument, shill::kTypeWifi), response.get()); // Call method. MockClosure mock_closure; MockErrorCallback mock_error_callback; client_->DisableTechnology(shill::kTypeWifi, mock_closure.GetCallback(), mock_error_callback.GetCallback()); EXPECT_CALL(mock_closure, Run()).Times(1); EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0); // Run the message loop. message_loop_.RunUntilIdle(); } TEST_F(ShillManagerClientTest, ConfigureService) { // Create response. const dbus::ObjectPath object_path("/"); scoped_ptr response(dbus::Response::CreateEmpty()); dbus::MessageWriter writer(response.get()); writer.AppendObjectPath(object_path); // Create the argument dictionary. scoped_ptr arg(CreateExampleServiceProperties()); // Use a variant valued dictionary rather than a string valued one. const bool string_valued = false; // Set expectations. PrepareForMethodCall( shill::kConfigureServiceFunction, base::Bind(&ExpectDictionaryValueArgument, arg.get(), string_valued), response.get()); // Call method. MockErrorCallback mock_error_callback; client_->ConfigureService(*arg, base::Bind(&ExpectObjectPathResultWithoutStatus, object_path), mock_error_callback.GetCallback()); EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0); // Run the message loop. message_loop_.RunUntilIdle(); } TEST_F(ShillManagerClientTest, GetService) { // Create response. const dbus::ObjectPath object_path("/"); scoped_ptr response(dbus::Response::CreateEmpty()); dbus::MessageWriter writer(response.get()); writer.AppendObjectPath(object_path); // Create the argument dictionary. scoped_ptr arg(CreateExampleServiceProperties()); // Use a variant valued dictionary rather than a string valued one. const bool string_valued = false; // Set expectations. PrepareForMethodCall( shill::kGetServiceFunction, base::Bind(&ExpectDictionaryValueArgument, arg.get(), string_valued), response.get()); // Call method. MockErrorCallback mock_error_callback; client_->GetService(*arg, base::Bind(&ExpectObjectPathResultWithoutStatus, object_path), mock_error_callback.GetCallback()); EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0); // Run the message loop. message_loop_.RunUntilIdle(); } TEST_F(ShillManagerClientTest, VerifyDestination) { // Create response. scoped_ptr response(dbus::Response::CreateEmpty()); dbus::MessageWriter writer(response.get()); bool expected = true; writer.AppendBool(expected); // Set expectations. std::vector arguments; arguments.push_back("certificate"); arguments.push_back("public_key"); arguments.push_back("nonce"); arguments.push_back("signed_data"); arguments.push_back("device_serial"); arguments.push_back("device_ssid"); arguments.push_back("device_bssid"); PrepareForMethodCall(shill::kVerifyDestinationFunction, base::Bind(&ExpectStringArguments, arguments), response.get()); // Call method. MockErrorCallback mock_error_callback; ShillManagerClient::VerificationProperties properties; properties.certificate = arguments[0]; properties.public_key = arguments[1]; properties.nonce = arguments[2]; properties.signed_data = arguments[3]; properties.device_serial = arguments[4]; properties.device_ssid = arguments[5]; properties.device_bssid = arguments[6]; client_->VerifyDestination( properties, base::Bind(&ExpectBoolResultWithoutStatus, expected), mock_error_callback.GetCallback()); EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0); // Run the message loop. message_loop_.RunUntilIdle(); } TEST_F(ShillManagerClientTest, VerifyAndEncryptCredentials) { // Create response. scoped_ptr response(dbus::Response::CreateEmpty()); dbus::MessageWriter writer(response.get()); std::string expected = "encrypted_credentials"; writer.AppendString(expected); // Set expectations. std::vector arguments; arguments.push_back("certificate"); arguments.push_back("public_key"); arguments.push_back("nonce"); arguments.push_back("signed_data"); arguments.push_back("device_serial"); arguments.push_back("device_ssid"); arguments.push_back("device_bssid"); std::string service_path = "/"; dbus::ObjectPath service_path_obj(service_path); PrepareForMethodCall(shill::kVerifyAndEncryptCredentialsFunction, base::Bind(&ExpectStringArgumentsFollowedByObjectPath, arguments, service_path_obj), response.get()); // Call method. MockErrorCallback mock_error_callback; ShillManagerClient::VerificationProperties properties; properties.certificate = arguments[0]; properties.public_key = arguments[1]; properties.nonce = arguments[2]; properties.signed_data = arguments[3]; properties.device_serial = arguments[4]; properties.device_ssid = arguments[5]; properties.device_bssid = arguments[6]; client_->VerifyAndEncryptCredentials( properties, service_path, base::Bind(&ExpectStringResultWithoutStatus, expected), mock_error_callback.GetCallback()); EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0); // Run the message loop. message_loop_.RunUntilIdle(); } TEST_F(ShillManagerClientTest, VerifyAndEncryptData) { // Create response. scoped_ptr response(dbus::Response::CreateEmpty()); dbus::MessageWriter writer(response.get()); std::string expected = "encrypted_data"; writer.AppendString(expected); // Set expectations. std::vector arguments; arguments.push_back("certificate"); arguments.push_back("public_key"); arguments.push_back("nonce"); arguments.push_back("signed_data"); arguments.push_back("device_serial"); arguments.push_back("device_ssid"); arguments.push_back("device_bssid"); arguments.push_back("data"); PrepareForMethodCall(shill::kVerifyAndEncryptDataFunction, base::Bind(&ExpectStringArguments, arguments), response.get()); // Call method. MockErrorCallback mock_error_callback; ShillManagerClient::VerificationProperties properties; properties.certificate = arguments[0]; properties.public_key = arguments[1]; properties.nonce = arguments[2]; properties.signed_data = arguments[3]; properties.device_serial = arguments[4]; properties.device_ssid = arguments[5]; properties.device_bssid = arguments[6]; client_->VerifyAndEncryptData( properties, arguments[7], base::Bind(&ExpectStringResultWithoutStatus, expected), mock_error_callback.GetCallback()); EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0); // Run the message loop. message_loop_.RunUntilIdle(); } } // namespace chromeos