| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/dbus/chrome_features_service_provider.h" |
| |
| #include "base/feature_list.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "dbus/message.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace ash { |
| |
| namespace { |
| void ResponseSenderCallback(const std::string& expected_message, |
| std::unique_ptr<dbus::Response> response) { |
| EXPECT_EQ(expected_message, response->ToString()); |
| } |
| } // namespace |
| |
| class ChromeFeaturesServiceProviderTest : public testing::Test { |
| protected: |
| void GetFeatureParams(dbus::MethodCall* method_call, std::string expected) { |
| provider_->GetFeatureParams( |
| method_call, base::BindOnce(&ResponseSenderCallback, expected)); |
| } |
| void IsFeatureEnabled(dbus::MethodCall* method_call, std::string expected) { |
| provider_->IsFeatureEnabled( |
| method_call, base::BindOnce(&ResponseSenderCallback, expected)); |
| } |
| std::unique_ptr<ChromeFeaturesServiceProvider> provider_; |
| }; |
| |
| TEST_F(ChromeFeaturesServiceProviderTest, IsFeatureEnabled_Success) { |
| auto feature_list = std::make_unique<base::FeatureList>(); |
| auto feature_list_accessor = feature_list->ConstructAccessor(); |
| const char enabled[] = "CrOSLateBootA"; |
| const char disabled[] = ""; |
| feature_list->InitFromCommandLine(enabled, disabled); |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitWithFeatureList(std::move(feature_list)); |
| |
| provider_ = std::make_unique<ChromeFeaturesServiceProvider>( |
| std::move(feature_list_accessor)); |
| |
| const char kExpectedMessage[] = |
| R"--(message_type: MESSAGE_METHOD_RETURN |
| signature: b |
| reply_serial: 123 |
| |
| bool true |
| )--"; |
| |
| dbus::MethodCall method_call("com.example.Interface", "SomeMethod"); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString("CrOSLateBootA"); |
| |
| // Not setting the serial causes a crash. |
| method_call.SetSerial(123); |
| IsFeatureEnabled(&method_call, kExpectedMessage); |
| } |
| |
| TEST_F(ChromeFeaturesServiceProviderTest, IsFeatureEnabled_UnknownFeature) { |
| auto feature_list = std::make_unique<base::FeatureList>(); |
| auto feature_list_accessor = feature_list->ConstructAccessor(); |
| const char enabled[] = "CrOSLateBootA"; |
| const char disabled[] = ""; |
| feature_list->InitFromCommandLine(enabled, disabled); |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitWithFeatureList(std::move(feature_list)); |
| |
| provider_ = std::make_unique<ChromeFeaturesServiceProvider>( |
| std::move(feature_list_accessor)); |
| |
| const char kExpectedMessage[] = |
| R"--(message_type: MESSAGE_ERROR |
| error_name: org.freedesktop.DBus.Error.InvalidArgs |
| signature: s |
| reply_serial: 123 |
| |
| string "Chrome can't get state for 'CrOSLateBootB'; feature_library will decide" |
| )--"; |
| |
| dbus::MethodCall method_call("com.example.Interface", "SomeMethod"); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString("CrOSLateBootB"); |
| |
| // Not setting the serial causes a crash. |
| method_call.SetSerial(123); |
| IsFeatureEnabled(&method_call, kExpectedMessage); |
| } |
| |
| TEST_F(ChromeFeaturesServiceProviderTest, IsFeatureEnabled_InvalidPrefix) { |
| auto feature_list = std::make_unique<base::FeatureList>(); |
| auto feature_list_accessor = feature_list->ConstructAccessor(); |
| const char enabled[] = "CrOSLateBootA"; |
| const char disabled[] = ""; |
| feature_list->InitFromCommandLine(enabled, disabled); |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitWithFeatureList(std::move(feature_list)); |
| |
| provider_ = std::make_unique<ChromeFeaturesServiceProvider>( |
| std::move(feature_list_accessor)); |
| |
| const char kExpectedMessage[] = |
| R"--(message_type: MESSAGE_ERROR |
| error_name: org.freedesktop.DBus.Error.InvalidArgs |
| signature: s |
| reply_serial: 123 |
| |
| string "Invalid prefix for feature name: 'B'. Want CrOSLateBoot" |
| )--"; |
| |
| dbus::MethodCall method_call("com.example.Interface", "SomeMethod"); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString("B"); |
| |
| // Not setting the serial causes a crash. |
| method_call.SetSerial(123); |
| IsFeatureEnabled(&method_call, kExpectedMessage); |
| } |
| |
| TEST_F(ChromeFeaturesServiceProviderTest, IsFeatureEnabled_InvalidInput) { |
| auto feature_list = std::make_unique<base::FeatureList>(); |
| auto feature_list_accessor = feature_list->ConstructAccessor(); |
| const char enabled[] = ""; |
| const char disabled[] = ""; |
| feature_list->InitFromCommandLine(enabled, disabled); |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitWithFeatureList(std::move(feature_list)); |
| |
| provider_ = std::make_unique<ChromeFeaturesServiceProvider>( |
| std::move(feature_list_accessor)); |
| |
| const char kExpectedMessage[] = |
| R"--(message_type: MESSAGE_ERROR |
| error_name: org.freedesktop.DBus.Error.InvalidArgs |
| signature: s |
| reply_serial: 123 |
| |
| string "Missing or invalid feature_name string arg." |
| )--"; |
| |
| dbus::MethodCall method_call("com.example.Interface", "SomeMethod"); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendBool(true); |
| |
| // Not setting the serial causes a crash. |
| method_call.SetSerial(123); |
| IsFeatureEnabled(&method_call, kExpectedMessage); |
| } |
| |
| TEST_F(ChromeFeaturesServiceProviderTest, GetFeatureParams_Success) { |
| auto feature_list = std::make_unique<base::FeatureList>(); |
| auto feature_list_accessor = feature_list->ConstructAccessor(); |
| const char enabled[] = "CrOSLateBootA:key1/value1/key2/value2,CrOSLateBootB"; |
| const char disabled[] = "CrOSLateBootC"; |
| feature_list->InitFromCommandLine(enabled, disabled); |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitWithFeatureList(std::move(feature_list)); |
| |
| provider_ = std::make_unique<ChromeFeaturesServiceProvider>( |
| std::move(feature_list_accessor)); |
| |
| const char kExpectedMessage[] = |
| R"--(message_type: MESSAGE_METHOD_RETURN |
| signature: a{s(bba{ss})} |
| reply_serial: 123 |
| |
| array [ |
| dict entry { |
| string "CrOSLateBootA" |
| struct { |
| bool true |
| bool true |
| array [ |
| dict entry { |
| string "key1" |
| string "value1" |
| } |
| dict entry { |
| string "key2" |
| string "value2" |
| } |
| ] |
| } |
| } |
| dict entry { |
| string "CrOSLateBootB" |
| struct { |
| bool true |
| bool true |
| array [ |
| ] |
| } |
| } |
| dict entry { |
| string "CrOSLateBootC" |
| struct { |
| bool true |
| bool false |
| array [ |
| ] |
| } |
| } |
| dict entry { |
| string "CrOSLateBootD" |
| struct { |
| bool false |
| bool false |
| array [ |
| ] |
| } |
| } |
| ] |
| )--"; |
| |
| dbus::MethodCall method_call("com.example.Interface", "SomeMethod"); |
| dbus::MessageWriter writer(&method_call); |
| dbus::MessageWriter array_writer(nullptr); |
| writer.OpenArray("s", &array_writer); |
| array_writer.AppendString("CrOSLateBootA"); |
| array_writer.AppendString("CrOSLateBootB"); |
| array_writer.AppendString("CrOSLateBootC"); |
| array_writer.AppendString("CrOSLateBootD"); |
| writer.CloseContainer(&array_writer); |
| |
| // Not setting the serial causes a crash. |
| method_call.SetSerial(123); |
| GetFeatureParams(&method_call, kExpectedMessage); |
| } |
| |
| TEST_F(ChromeFeaturesServiceProviderTest, GetFeatureParams_NoInput) { |
| auto feature_list = std::make_unique<base::FeatureList>(); |
| auto feature_list_accessor = feature_list->ConstructAccessor(); |
| feature_list->InitFromCommandLine("", ""); |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitWithFeatureList(std::move(feature_list)); |
| |
| provider_ = std::make_unique<ChromeFeaturesServiceProvider>( |
| std::move(feature_list_accessor)); |
| |
| constexpr char kExpectedMessage[] = R"--(message_type: MESSAGE_ERROR |
| error_name: org.freedesktop.DBus.Error.InvalidArgs |
| signature: s |
| reply_serial: 123 |
| |
| string "Could not pop string array of feature names" |
| )--"; |
| |
| dbus::MethodCall method_call("com.example.Interface", "SomeMethod"); |
| // Not setting the serial causes a crash. |
| method_call.SetSerial(123); |
| GetFeatureParams(&method_call, kExpectedMessage); |
| } |
| |
| TEST_F(ChromeFeaturesServiceProviderTest, GetFeatureParams_BadInput) { |
| auto feature_list = std::make_unique<base::FeatureList>(); |
| auto feature_list_accessor = feature_list->ConstructAccessor(); |
| feature_list->InitFromCommandLine("", ""); |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitWithFeatureList(std::move(feature_list)); |
| |
| provider_ = std::make_unique<ChromeFeaturesServiceProvider>( |
| std::move(feature_list_accessor)); |
| |
| constexpr char kExpectedMessage[] = R"--(message_type: MESSAGE_ERROR |
| error_name: org.freedesktop.DBus.Error.InvalidArgs |
| signature: s |
| reply_serial: 123 |
| |
| string "Could not pop string array of feature names" |
| )--"; |
| |
| dbus::MethodCall method_call("com.example.Interface", "SomeMethod"); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString("CrOSLateBootA"); // not in an array! |
| // Not setting the serial causes a crash. |
| method_call.SetSerial(123); |
| GetFeatureParams(&method_call, kExpectedMessage); |
| } |
| |
| TEST_F(ChromeFeaturesServiceProviderTest, GetFeatureParams_BadArrayEntry) { |
| auto feature_list = std::make_unique<base::FeatureList>(); |
| auto feature_list_accessor = feature_list->ConstructAccessor(); |
| feature_list->InitFromCommandLine("", ""); |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitWithFeatureList(std::move(feature_list)); |
| |
| provider_ = std::make_unique<ChromeFeaturesServiceProvider>( |
| std::move(feature_list_accessor)); |
| |
| constexpr char kExpectedMessage[] = R"--(message_type: MESSAGE_ERROR |
| error_name: org.freedesktop.DBus.Error.InvalidArgs |
| signature: s |
| reply_serial: 123 |
| |
| string "Missing or invalid feature_name string arg in array." |
| )--"; |
| |
| dbus::MethodCall method_call("com.example.Interface", "SomeMethod"); |
| dbus::MessageWriter writer(&method_call); |
| dbus::MessageWriter array_writer(nullptr); |
| writer.OpenArray("b", &array_writer); |
| array_writer.AppendBool(true); // wrong type |
| writer.CloseContainer(&array_writer); |
| // Not setting the serial causes a crash. |
| method_call.SetSerial(123); |
| GetFeatureParams(&method_call, kExpectedMessage); |
| } |
| |
| TEST_F(ChromeFeaturesServiceProviderTest, GetFeatureParams_BadNameFormat) { |
| auto feature_list = std::make_unique<base::FeatureList>(); |
| auto feature_list_accessor = feature_list->ConstructAccessor(); |
| feature_list->InitFromCommandLine("", ""); |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitWithFeatureList(std::move(feature_list)); |
| |
| provider_ = std::make_unique<ChromeFeaturesServiceProvider>( |
| std::move(feature_list_accessor)); |
| |
| constexpr char kExpectedMessage[] = R"--(message_type: MESSAGE_ERROR |
| error_name: org.freedesktop.DBus.Error.InvalidArgs |
| signature: s |
| reply_serial: 123 |
| |
| string "Invalid prefix for feature name: 'B'. Want CrOSLateBoot" |
| )--"; |
| |
| dbus::MethodCall method_call("com.example.Interface", "SomeMethod"); |
| dbus::MessageWriter writer(&method_call); |
| dbus::MessageWriter array_writer(nullptr); |
| writer.OpenArray("s", &array_writer); |
| array_writer.AppendString("CrOSLateBootA"); |
| array_writer.AppendString("B"); // missing prefix! |
| writer.CloseContainer(&array_writer); |
| // Not setting the serial causes a crash. |
| method_call.SetSerial(123); |
| GetFeatureParams(&method_call, kExpectedMessage); |
| } |
| |
| } // namespace ash |