blob: ec3c6585af45bbd4d5a9d3884743bdde6fdde4a4 [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
Alex Deymof6cbe322014-11-10 19:55:35 -08005#include "buffet/commands/dbus_command_dispatcher.h"
6
Alex Vakulenko95110752014-09-03 16:27:21 -07007#include <memory>
8#include <string>
9
10#include <chromeos/dbus/exported_object_manager.h>
11#include <dbus/mock_bus.h>
12#include <dbus/mock_exported_object.h>
13#include <dbus/object_manager.h>
14#include <dbus/object_path.h>
15#include <gtest/gtest.h>
16
17#include "buffet/commands/command_dictionary.h"
18#include "buffet/commands/command_queue.h"
Alex Vakulenko95110752014-09-03 16:27:21 -070019#include "buffet/commands/unittest_utils.h"
Alex Vakulenko420e49f2014-12-01 17:53:27 -080020#include "buffet/dbus_constants.h"
Alex Vakulenko95110752014-09-03 16:27:21 -070021
22using buffet::unittests::CreateDictionaryValue;
23using chromeos::dbus_utils::AsyncEventSequencer;
24using testing::AnyNumber;
25using testing::InSequence;
26using testing::Invoke;
27using testing::Return;
28using testing::_;
29
30namespace buffet {
31
32namespace {
33
34const char kCommandCategory[] = "test_category";
35
36} // anonymous namespace
37
38class DBusCommandDispacherTest : public testing::Test {
39 public:
40 void SetUp() override {
41 const dbus::ObjectPath kExportedObjectManagerPath("/test/om_path");
42 std::string cmd_path = dbus_constants::kCommandServicePathPrefix;
43 cmd_path += "1";
44 const dbus::ObjectPath kCmdObjPath(cmd_path);
45
46 dbus::Bus::Options options;
47 options.bus_type = dbus::Bus::SYSTEM;
48 bus_ = new dbus::MockBus(options);
49 // By default, don't worry about threading assertions.
50 EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber());
51 EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber());
52 // Use a mock exported object manager.
53 mock_exported_object_manager_ = new dbus::MockExportedObject(
54 bus_.get(), kExportedObjectManagerPath);
55 EXPECT_CALL(*bus_, GetExportedObject(kExportedObjectManagerPath))
56 .WillRepeatedly(Return(mock_exported_object_manager_.get()));
57 EXPECT_CALL(*mock_exported_object_manager_,
58 ExportMethod(_, _, _, _)).Times(AnyNumber());
59 om_.reset(new chromeos::dbus_utils::ExportedObjectManager(
60 bus_.get(), kExportedObjectManagerPath));
61 om_->RegisterAsync(AsyncEventSequencer::GetDefaultCompletionAction());
62 command_dispatcher_.reset(
63 new DBusCommandDispacher(om_->GetBus(), om_.get()));
64 command_queue_.SetCommandDispachInterface(command_dispatcher_.get());
65 // Use a mock exported object for command proxy.
66 mock_exported_command_proxy_ = new dbus::MockExportedObject(
67 bus_.get(), kCmdObjPath);
68 EXPECT_CALL(*bus_, GetExportedObject(kCmdObjPath))
69 .WillRepeatedly(Return(mock_exported_command_proxy_.get()));
70 EXPECT_CALL(*mock_exported_command_proxy_, ExportMethod(_, _, _, _))
71 .WillRepeatedly(Invoke(MockExportMethod));
72
73 auto json = CreateDictionaryValue(R"({
74 'base': {
75 'reboot': {
Anton Muhin71fb9d52014-11-21 22:22:39 +040076 'parameters': {'delay': 'integer'},
77 'results': {}
Alex Vakulenko95110752014-09-03 16:27:21 -070078 },
79 'shutdown': {
Anton Muhin71fb9d52014-11-21 22:22:39 +040080 'parameters': {},
81 'results': {}
Alex Vakulenko95110752014-09-03 16:27:21 -070082 }
83 }
84 })");
85 CHECK(dictionary_.LoadCommands(*json, kCommandCategory, nullptr, nullptr))
86 << "Failed to load command dictionary";
87 }
88
89 void TearDown() override {
90 EXPECT_CALL(*mock_exported_object_manager_, Unregister()).Times(1);
91 om_.reset();
92 bus_ = nullptr;
93 }
94
95 static void MockExportMethod(
96 const std::string& interface_name,
97 const std::string& method_name,
98 dbus::ExportedObject::MethodCallCallback method_call_callback,
99 dbus::ExportedObject::OnExportedCallback on_exported_callback) {
100 on_exported_callback.Run(interface_name, method_name, true);
101 }
102
103
Anton Muhin5191e812014-10-30 17:49:48 +0400104 void AddNewCommand(const std::string& json, const std::string& id) {
Alex Vakulenko95110752014-09-03 16:27:21 -0700105 auto command_instance = CommandInstance::FromJson(
106 CreateDictionaryValue(json.c_str()).get(), dictionary_, nullptr);
Anton Muhin5191e812014-10-30 17:49:48 +0400107 command_instance->SetID(id);
Alex Vakulenko95110752014-09-03 16:27:21 -0700108 // Two interfaces are added - Command and Properties.
109 EXPECT_CALL(*mock_exported_object_manager_, SendSignal(_)).Times(2);
Anton Muhin5191e812014-10-30 17:49:48 +0400110 command_queue_.Add(std::move(command_instance));
Alex Vakulenko95110752014-09-03 16:27:21 -0700111 }
112
Anton Muhina22f4be2014-11-10 15:02:15 +0400113 DBusCommandProxy* FindProxy(CommandInstance* command_instance) {
Mike Frysinger42e3a722014-11-15 06:48:08 -0500114 CHECK_EQ(command_instance->proxies_.size(), 1U);
Anton Muhinb66a9302014-11-10 22:15:22 +0400115 return static_cast<DBusCommandProxy*>(command_instance->proxies_[0].get());
Anton Muhina22f4be2014-11-10 15:02:15 +0400116 }
117
Alex Vakulenko95110752014-09-03 16:27:21 -0700118 void FinishCommand(DBusCommandProxy* proxy) {
Alex Vakulenko2348e422014-11-21 08:57:57 -0800119 proxy->Done();
Alex Vakulenko95110752014-09-03 16:27:21 -0700120 }
121
122 void SetProgress(DBusCommandProxy* proxy, int progress) {
Alex Vakulenko2348e422014-11-21 08:57:57 -0800123 proxy->SetProgress(nullptr, progress);
Alex Vakulenko95110752014-09-03 16:27:21 -0700124 }
125
126
127 scoped_refptr<dbus::MockBus> bus_;
128 scoped_refptr<dbus::MockExportedObject> mock_exported_object_manager_;
129 scoped_refptr<dbus::MockExportedObject> mock_exported_command_proxy_;
130 std::unique_ptr<chromeos::dbus_utils::ExportedObjectManager> om_;
131 CommandDictionary dictionary_;
132 CommandQueue command_queue_;
133 std::unique_ptr<DBusCommandDispacher> command_dispatcher_;
134};
135
136TEST_F(DBusCommandDispacherTest, Test_Command_Base_Shutdown) {
Anton Muhin5191e812014-10-30 17:49:48 +0400137 const std::string id = "id0000";
138 AddNewCommand("{'name':'base.shutdown'}", id);
Alex Vakulenko95110752014-09-03 16:27:21 -0700139 CommandInstance* command_instance = command_queue_.Find(id);
140 ASSERT_NE(nullptr, command_instance);
Anton Muhina22f4be2014-11-10 15:02:15 +0400141 DBusCommandProxy* command_proxy = FindProxy(command_instance);
Alex Vakulenko95110752014-09-03 16:27:21 -0700142 ASSERT_NE(nullptr, command_proxy);
143 EXPECT_EQ(CommandInstance::kStatusQueued, command_instance->GetStatus());
144
145 // Two properties are set, Progress = 50%, Status = "inProgress"
146 EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(2);
147 SetProgress(command_proxy, 50);
148 EXPECT_EQ(CommandInstance::kStatusInProgress, command_instance->GetStatus());
149 EXPECT_EQ(50, command_instance->GetProgress());
150
151 // Command must be removed from the queue and proxy destroyed after calling
152 // FinishCommand().
153 // Two properties are set, Progress = 100%, Status = "done"
154 EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(2);
155 // D-Bus command proxy is going away.
156 EXPECT_CALL(*mock_exported_command_proxy_, Unregister()).Times(1);
157 // Two interfaces are being removed on the D-Bus command object.
158 EXPECT_CALL(*mock_exported_object_manager_, SendSignal(_)).Times(2);
159 FinishCommand(command_proxy);
160
Alex Vakulenko95110752014-09-03 16:27:21 -0700161 EXPECT_EQ(nullptr, command_queue_.Find(id));
162}
163
164TEST_F(DBusCommandDispacherTest, Test_Command_Base_Reboot) {
Anton Muhin5191e812014-10-30 17:49:48 +0400165 const std::string id = "id0001";
166 AddNewCommand(R"({
Alex Vakulenko95110752014-09-03 16:27:21 -0700167 'name': 'base.reboot',
168 'parameters': {
169 'delay': 20
170 }
Anton Muhin5191e812014-10-30 17:49:48 +0400171 })", id);
Alex Vakulenko95110752014-09-03 16:27:21 -0700172 CommandInstance* command_instance = command_queue_.Find(id);
173 ASSERT_NE(nullptr, command_instance);
Anton Muhina22f4be2014-11-10 15:02:15 +0400174 DBusCommandProxy* command_proxy = FindProxy(command_instance);
Alex Vakulenko95110752014-09-03 16:27:21 -0700175 ASSERT_NE(nullptr, command_proxy);
176 EXPECT_EQ(CommandInstance::kStatusQueued, command_instance->GetStatus());
177
178 // Two properties are set, Progress = 50%, Status = "inProgress"
179 EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(2);
180 SetProgress(command_proxy, 50);
181 EXPECT_EQ(CommandInstance::kStatusInProgress, command_instance->GetStatus());
182 EXPECT_EQ(50, command_instance->GetProgress());
183
184 // Command must be removed from the queue and proxy destroyed after calling
185 // FinishCommand().
186 // Two properties are set, Progress = 100%, Status = "done"
187 EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(2);
188 // D-Bus command proxy is going away.
189 EXPECT_CALL(*mock_exported_command_proxy_, Unregister()).Times(1);
190 // Two interfaces are being removed on the D-Bus command object.
191 EXPECT_CALL(*mock_exported_object_manager_, SendSignal(_)).Times(2);
192 FinishCommand(command_proxy);
193
Alex Vakulenko95110752014-09-03 16:27:21 -0700194 EXPECT_EQ(nullptr, command_queue_.Find(id));
195}
196
197
198} // namespace buffet