blob: 9de6889159a03167431c29b2fd97bfca66ee59a2 [file] [log] [blame]
Alex Vakulenko95110752014-09-03 16:27:21 -07001// Copyright 2014 The Chromium OS Authors. All rights reserved.
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 <memory>
6#include <string>
7
8#include <chromeos/dbus/exported_object_manager.h>
9#include <dbus/mock_bus.h>
10#include <dbus/mock_exported_object.h>
11#include <dbus/object_manager.h>
12#include <dbus/object_path.h>
13#include <gtest/gtest.h>
14
15#include "buffet/commands/command_dictionary.h"
16#include "buffet/commands/command_queue.h"
17#include "buffet/commands/dbus_command_dispatcher.h"
18#include "buffet/commands/unittest_utils.h"
Alex Vakulenko89d9d5e2014-09-12 10:27:23 -070019#include "buffet/libbuffet/dbus_constants.h"
Alex Vakulenko95110752014-09-03 16:27:21 -070020
21using buffet::unittests::CreateDictionaryValue;
22using chromeos::dbus_utils::AsyncEventSequencer;
23using testing::AnyNumber;
24using testing::InSequence;
25using testing::Invoke;
26using testing::Return;
27using testing::_;
28
29namespace buffet {
30
31namespace {
32
33const char kCommandCategory[] = "test_category";
34
35} // anonymous namespace
36
37class DBusCommandDispacherTest : public testing::Test {
38 public:
39 void SetUp() override {
40 const dbus::ObjectPath kExportedObjectManagerPath("/test/om_path");
41 std::string cmd_path = dbus_constants::kCommandServicePathPrefix;
42 cmd_path += "1";
43 const dbus::ObjectPath kCmdObjPath(cmd_path);
44
45 dbus::Bus::Options options;
46 options.bus_type = dbus::Bus::SYSTEM;
47 bus_ = new dbus::MockBus(options);
48 // By default, don't worry about threading assertions.
49 EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber());
50 EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber());
51 // Use a mock exported object manager.
52 mock_exported_object_manager_ = new dbus::MockExportedObject(
53 bus_.get(), kExportedObjectManagerPath);
54 EXPECT_CALL(*bus_, GetExportedObject(kExportedObjectManagerPath))
55 .WillRepeatedly(Return(mock_exported_object_manager_.get()));
56 EXPECT_CALL(*mock_exported_object_manager_,
57 ExportMethod(_, _, _, _)).Times(AnyNumber());
58 om_.reset(new chromeos::dbus_utils::ExportedObjectManager(
59 bus_.get(), kExportedObjectManagerPath));
60 om_->RegisterAsync(AsyncEventSequencer::GetDefaultCompletionAction());
61 command_dispatcher_.reset(
62 new DBusCommandDispacher(om_->GetBus(), om_.get()));
63 command_queue_.SetCommandDispachInterface(command_dispatcher_.get());
64 // Use a mock exported object for command proxy.
65 mock_exported_command_proxy_ = new dbus::MockExportedObject(
66 bus_.get(), kCmdObjPath);
67 EXPECT_CALL(*bus_, GetExportedObject(kCmdObjPath))
68 .WillRepeatedly(Return(mock_exported_command_proxy_.get()));
69 EXPECT_CALL(*mock_exported_command_proxy_, ExportMethod(_, _, _, _))
70 .WillRepeatedly(Invoke(MockExportMethod));
71
72 auto json = CreateDictionaryValue(R"({
73 'base': {
74 'reboot': {
75 'parameters': {'delay': 'integer'}
76 },
77 'shutdown': {
78 'parameters': {}
79 }
80 }
81 })");
82 CHECK(dictionary_.LoadCommands(*json, kCommandCategory, nullptr, nullptr))
83 << "Failed to load command dictionary";
84 }
85
86 void TearDown() override {
87 EXPECT_CALL(*mock_exported_object_manager_, Unregister()).Times(1);
88 om_.reset();
89 bus_ = nullptr;
90 }
91
92 static void MockExportMethod(
93 const std::string& interface_name,
94 const std::string& method_name,
95 dbus::ExportedObject::MethodCallCallback method_call_callback,
96 dbus::ExportedObject::OnExportedCallback on_exported_callback) {
97 on_exported_callback.Run(interface_name, method_name, true);
98 }
99
100
101 std::string AddNewCommand(const std::string& json) {
102 auto command_instance = CommandInstance::FromJson(
103 CreateDictionaryValue(json.c_str()).get(), dictionary_, nullptr);
104 // Two interfaces are added - Command and Properties.
105 EXPECT_CALL(*mock_exported_object_manager_, SendSignal(_)).Times(2);
106 return command_instance ?
107 command_queue_.Add(std::move(command_instance)) : std::string();
108 }
109
110 void FinishCommand(DBusCommandProxy* proxy) {
Alex Vakulenko5c7bf012014-10-30 16:28:38 -0700111 proxy->HandleDone();
Alex Vakulenko95110752014-09-03 16:27:21 -0700112 }
113
114 void SetProgress(DBusCommandProxy* proxy, int progress) {
115 proxy->HandleSetProgress(nullptr, progress);
116 }
117
118
119 scoped_refptr<dbus::MockBus> bus_;
120 scoped_refptr<dbus::MockExportedObject> mock_exported_object_manager_;
121 scoped_refptr<dbus::MockExportedObject> mock_exported_command_proxy_;
122 std::unique_ptr<chromeos::dbus_utils::ExportedObjectManager> om_;
123 CommandDictionary dictionary_;
124 CommandQueue command_queue_;
125 std::unique_ptr<DBusCommandDispacher> command_dispatcher_;
126};
127
128TEST_F(DBusCommandDispacherTest, Test_Command_Base_Shutdown) {
129 std::string id = AddNewCommand("{'name':'base.shutdown'}");
130 EXPECT_EQ("1", id);
131 CommandInstance* command_instance = command_queue_.Find(id);
132 ASSERT_NE(nullptr, command_instance);
133 DBusCommandProxy* command_proxy =
134 command_dispatcher_->FindProxy(command_instance);
135 ASSERT_NE(nullptr, command_proxy);
136 EXPECT_EQ(CommandInstance::kStatusQueued, command_instance->GetStatus());
137
138 // Two properties are set, Progress = 50%, Status = "inProgress"
139 EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(2);
140 SetProgress(command_proxy, 50);
141 EXPECT_EQ(CommandInstance::kStatusInProgress, command_instance->GetStatus());
142 EXPECT_EQ(50, command_instance->GetProgress());
143
144 // Command must be removed from the queue and proxy destroyed after calling
145 // FinishCommand().
146 // Two properties are set, Progress = 100%, Status = "done"
147 EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(2);
148 // D-Bus command proxy is going away.
149 EXPECT_CALL(*mock_exported_command_proxy_, Unregister()).Times(1);
150 // Two interfaces are being removed on the D-Bus command object.
151 EXPECT_CALL(*mock_exported_object_manager_, SendSignal(_)).Times(2);
152 FinishCommand(command_proxy);
153
154 EXPECT_EQ(nullptr,
155 command_dispatcher_->FindProxy(command_instance));
156 EXPECT_EQ(nullptr, command_queue_.Find(id));
157}
158
159TEST_F(DBusCommandDispacherTest, Test_Command_Base_Reboot) {
160 std::string id = AddNewCommand(R"({
161 'name': 'base.reboot',
162 'parameters': {
163 'delay': 20
164 }
165 })");
166 EXPECT_EQ("1", id);
167 CommandInstance* command_instance = command_queue_.Find(id);
168 ASSERT_NE(nullptr, command_instance);
169 DBusCommandProxy* command_proxy =
170 command_dispatcher_->FindProxy(command_instance);
171 ASSERT_NE(nullptr, command_proxy);
172 EXPECT_EQ(CommandInstance::kStatusQueued, command_instance->GetStatus());
173
174 // Two properties are set, Progress = 50%, Status = "inProgress"
175 EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(2);
176 SetProgress(command_proxy, 50);
177 EXPECT_EQ(CommandInstance::kStatusInProgress, command_instance->GetStatus());
178 EXPECT_EQ(50, command_instance->GetProgress());
179
180 // Command must be removed from the queue and proxy destroyed after calling
181 // FinishCommand().
182 // Two properties are set, Progress = 100%, Status = "done"
183 EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(2);
184 // D-Bus command proxy is going away.
185 EXPECT_CALL(*mock_exported_command_proxy_, Unregister()).Times(1);
186 // Two interfaces are being removed on the D-Bus command object.
187 EXPECT_CALL(*mock_exported_object_manager_, SendSignal(_)).Times(2);
188 FinishCommand(command_proxy);
189
190 EXPECT_EQ(nullptr,
191 command_dispatcher_->FindProxy(command_instance));
192 EXPECT_EQ(nullptr, command_queue_.Find(id));
193}
194
195
196} // namespace buffet