• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/fuchsia/system_info.h"
6 #include "base/functional/callback_forward.h"
7 
8 #include <fidl/fuchsia.buildinfo/cpp/fidl.h>
9 #include <fidl/fuchsia.hwinfo/cpp/fidl.h>
10 #include <lib/async/default.h>
11 #include <lib/fidl/cpp/wire/connect_service.h>
12 
13 #include <memory>
14 #include <string>
15 
16 #include "base/fuchsia/scoped_service_binding.h"
17 #include "base/fuchsia/test_component_context_for_process.h"
18 #include "base/functional/bind.h"
19 #include "base/location.h"
20 #include "base/run_loop.h"
21 #include "base/strings/string_piece.h"
22 #include "base/test/bind.h"
23 #include "base/test/gtest_util.h"
24 #include "base/test/task_environment.h"
25 #include "base/test/test_future.h"
26 #include "base/threading/sequence_bound.h"
27 #include "base/threading/thread.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 
30 namespace base {
31 
32 namespace {
33 
34 class FakeHardwareInfoProduct : public fidl::Server<fuchsia_hwinfo::Product> {
35  public:
FakeHardwareInfoProduct(const base::StringPiece model,const base::StringPiece manufacturer,sys::OutgoingDirectory * outgoing_services)36   FakeHardwareInfoProduct(const base::StringPiece model,
37                           const base::StringPiece manufacturer,
38                           sys::OutgoingDirectory* outgoing_services)
39       : model_(model),
40         manufacturer_(manufacturer),
41         binding_(outgoing_services, this) {}
42   FakeHardwareInfoProduct(const FakeHardwareInfoProduct&) = delete;
43   FakeHardwareInfoProduct& operator=(const FakeHardwareInfoProduct&) = delete;
44   ~FakeHardwareInfoProduct() override = default;
45 
GetInfo(GetInfoCompleter::Sync & completer)46   void GetInfo(GetInfoCompleter::Sync& completer) override {
47     completer.Reply(fuchsia_hwinfo::ProductInfo{{
48         .model = model_,
49         .manufacturer = manufacturer_,
50     }});
51   }
52 
53  private:
54   std::string model_;
55   std::string manufacturer_;
56   ScopedNaturalServiceBinding<fuchsia_hwinfo::Product> binding_;
57 };
58 
59 }  // namespace
60 
61 // Uses a fake "fuchsia.hwinfo.Product" implementation.
62 // clears the cached ProductInfo to ensure that each test starts with no cached
63 // ProductInfo and that subsequent tests runs do not use fake values.
64 class ProductInfoTest : public testing::Test {
65  protected:
ProductInfoTest()66   ProductInfoTest()
67       : task_environment_(
68             base::test::SingleThreadTaskEnvironment::MainThreadType::IO),
69         thread_("ProductInfo Retrieval Thread") {
70     thread_.StartWithOptions(
71         base::Thread::Options(base::MessagePumpType::IO, 0));
72     ClearCachedSystemInfoForTesting();
73     component_context_.AddService(
74         fidl::DiscoverableProtocolName<fuchsia_buildinfo::Provider>);
75   }
~ProductInfoTest()76   ~ProductInfoTest() override { ClearCachedSystemInfoForTesting(); }
77 
78   // Fetch the product info in a separate thread, while servicing the
79   // FIDL fake implementation on the main thread.
GetProductInfoViaTask()80   fuchsia_hwinfo::ProductInfo GetProductInfoViaTask() {
81     fuchsia_hwinfo::ProductInfo product_info;
82     base::RunLoop run_loop;
83     thread_.task_runner()->PostTaskAndReplyWithResult(
84         FROM_HERE, base::BindOnce(&GetProductInfo),
85         base::BindOnce(
86             [](base::RunLoop& run_loop,
87                fuchsia_hwinfo::ProductInfo& product_info,
88                fuchsia_hwinfo::ProductInfo result) {
89               product_info = std::move(result);
90               run_loop.Quit();
91             },
92             std::ref(run_loop), std::ref(product_info)));
93     run_loop.Run();
94     return product_info;
95   }
96 
97   base::test::SingleThreadTaskEnvironment task_environment_;
98   TestComponentContextForProcess component_context_;
99   base::Thread thread_;
100 };
101 
102 using ProductInfoDeathTest = ProductInfoTest;
103 
TEST_F(ProductInfoTest,GetProductInfoReturnsFakedValues)104 TEST_F(ProductInfoTest, GetProductInfoReturnsFakedValues) {
105   FakeHardwareInfoProduct hwinfo_product_provider(
106       "test.model", "test.manufacturer",
107       component_context_.additional_services());
108 
109   const auto product_info = GetProductInfoViaTask();
110   EXPECT_EQ(product_info.model().value(), "test.model");
111   EXPECT_EQ(product_info.manufacturer().value(), "test.manufacturer");
112 }
113 
TEST_F(ProductInfoTest,SystemServiceReturnsValidValues)114 TEST_F(ProductInfoTest, SystemServiceReturnsValidValues) {
115   component_context_.AddService(
116       fidl::DiscoverableProtocolName<fuchsia_hwinfo::Product>);
117 
118   const auto product_info = GetProductInfoViaTask();
119   EXPECT_TRUE(product_info.model().has_value());
120   EXPECT_FALSE(product_info.model()->empty());
121 
122   EXPECT_TRUE(product_info.manufacturer().has_value());
123   EXPECT_FALSE(product_info.manufacturer()->empty());
124 }
125 
126 // TODO(crbug.com/101396): Re-enable once all clients
127 // provide this service.
TEST_F(ProductInfoDeathTest,DISABLED_DcheckOnServiceNotPresent)128 TEST_F(ProductInfoDeathTest, DISABLED_DcheckOnServiceNotPresent) {
129   EXPECT_DCHECK_DEATH_WITH(GetProductInfoViaTask(), "ZX_ERR_PEER_CLOSED");
130 }
131 
132 }  // namespace base
133