blob: 1e27aacbf804af149ba6ecab58e627763d397f48 [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 {
Alex Vakulenko95110752014-09-03 16:27:21 -070033const char kCommandCategory[] = "test_category";
34
35} // anonymous namespace
36
37class DBusCommandDispacherTest : public testing::Test {
38 public:
39 void SetUp() override {
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070040 command_queue_.SetNowForTest(base::Time::Max());
41
Alex Vakulenko95110752014-09-03 16:27:21 -070042 const dbus::ObjectPath kExportedObjectManagerPath("/test/om_path");
43 std::string cmd_path = dbus_constants::kCommandServicePathPrefix;
44 cmd_path += "1";
45 const dbus::ObjectPath kCmdObjPath(cmd_path);
46
47 dbus::Bus::Options options;
48 options.bus_type = dbus::Bus::SYSTEM;
49 bus_ = new dbus::MockBus(options);
50 // By default, don't worry about threading assertions.
51 EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber());
52 EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber());
53 // Use a mock exported object manager.
54 mock_exported_object_manager_ = new dbus::MockExportedObject(
55 bus_.get(), kExportedObjectManagerPath);
56 EXPECT_CALL(*bus_, GetExportedObject(kExportedObjectManagerPath))
57 .WillRepeatedly(Return(mock_exported_object_manager_.get()));
58 EXPECT_CALL(*mock_exported_object_manager_,
59 ExportMethod(_, _, _, _)).Times(AnyNumber());
60 om_.reset(new chromeos::dbus_utils::ExportedObjectManager(
61 bus_.get(), kExportedObjectManagerPath));
62 om_->RegisterAsync(AsyncEventSequencer::GetDefaultCompletionAction());
63 command_dispatcher_.reset(
64 new DBusCommandDispacher(om_->GetBus(), om_.get()));
65 command_queue_.SetCommandDispachInterface(command_dispatcher_.get());
66 // Use a mock exported object for command proxy.
67 mock_exported_command_proxy_ = new dbus::MockExportedObject(
68 bus_.get(), kCmdObjPath);
69 EXPECT_CALL(*bus_, GetExportedObject(kCmdObjPath))
70 .WillRepeatedly(Return(mock_exported_command_proxy_.get()));
71 EXPECT_CALL(*mock_exported_command_proxy_, ExportMethod(_, _, _, _))
72 .WillRepeatedly(Invoke(MockExportMethod));
73
74 auto json = CreateDictionaryValue(R"({
75 'base': {
76 'reboot': {
Anton Muhin71fb9d52014-11-21 22:22:39 +040077 'parameters': {'delay': 'integer'},
78 'results': {}
Alex Vakulenko95110752014-09-03 16:27:21 -070079 },
80 'shutdown': {
Anton Muhin71fb9d52014-11-21 22:22:39 +040081 'parameters': {},
82 'results': {}
Alex Vakulenko95110752014-09-03 16:27:21 -070083 }
84 }
85 })");
86 CHECK(dictionary_.LoadCommands(*json, kCommandCategory, nullptr, nullptr))
87 << "Failed to load command dictionary";
88 }
89
90 void TearDown() override {
91 EXPECT_CALL(*mock_exported_object_manager_, Unregister()).Times(1);
92 om_.reset();
93 bus_ = nullptr;
94 }
95
96 static void MockExportMethod(
97 const std::string& interface_name,
98 const std::string& method_name,
99 dbus::ExportedObject::MethodCallCallback method_call_callback,
100 dbus::ExportedObject::OnExportedCallback on_exported_callback) {
101 on_exported_callback.Run(interface_name, method_name, true);
102 }
103
104
Anton Muhin5191e812014-10-30 17:49:48 +0400105 void AddNewCommand(const std::string& json, const std::string& id) {
Alex Vakulenko95110752014-09-03 16:27:21 -0700106 auto command_instance = CommandInstance::FromJson(
107 CreateDictionaryValue(json.c_str()).get(), dictionary_, nullptr);
Anton Muhin5191e812014-10-30 17:49:48 +0400108 command_instance->SetID(id);
Alex Vakulenko95110752014-09-03 16:27:21 -0700109 // Two interfaces are added - Command and Properties.
110 EXPECT_CALL(*mock_exported_object_manager_, SendSignal(_)).Times(2);
Anton Muhin5191e812014-10-30 17:49:48 +0400111 command_queue_.Add(std::move(command_instance));
Alex Vakulenko95110752014-09-03 16:27:21 -0700112 }
113
Anton Muhina22f4be2014-11-10 15:02:15 +0400114 DBusCommandProxy* FindProxy(CommandInstance* command_instance) {
Mike Frysinger42e3a722014-11-15 06:48:08 -0500115 CHECK_EQ(command_instance->proxies_.size(), 1U);
Anton Muhinb66a9302014-11-10 22:15:22 +0400116 return static_cast<DBusCommandProxy*>(command_instance->proxies_[0].get());
Anton Muhina22f4be2014-11-10 15:02:15 +0400117 }
118
Alex Vakulenko95110752014-09-03 16:27:21 -0700119 void FinishCommand(DBusCommandProxy* proxy) {
Alex Vakulenko2348e422014-11-21 08:57:57 -0800120 proxy->Done();
Alex Vakulenko95110752014-09-03 16:27:21 -0700121 }
122
123 void SetProgress(DBusCommandProxy* proxy, int progress) {
Alex Vakulenko2348e422014-11-21 08:57:57 -0800124 proxy->SetProgress(nullptr, progress);
Alex Vakulenko95110752014-09-03 16:27:21 -0700125 }
126
127
128 scoped_refptr<dbus::MockBus> bus_;
129 scoped_refptr<dbus::MockExportedObject> mock_exported_object_manager_;
130 scoped_refptr<dbus::MockExportedObject> mock_exported_command_proxy_;
131 std::unique_ptr<chromeos::dbus_utils::ExportedObjectManager> om_;
132 CommandDictionary dictionary_;
133 CommandQueue command_queue_;
134 std::unique_ptr<DBusCommandDispacher> command_dispatcher_;
135};
136
137TEST_F(DBusCommandDispacherTest, Test_Command_Base_Shutdown) {
Anton Muhin5191e812014-10-30 17:49:48 +0400138 const std::string id = "id0000";
139 AddNewCommand("{'name':'base.shutdown'}", id);
Alex Vakulenko95110752014-09-03 16:27:21 -0700140 CommandInstance* command_instance = command_queue_.Find(id);
141 ASSERT_NE(nullptr, command_instance);
Anton Muhina22f4be2014-11-10 15:02:15 +0400142 DBusCommandProxy* command_proxy = FindProxy(command_instance);
Alex Vakulenko95110752014-09-03 16:27:21 -0700143 ASSERT_NE(nullptr, command_proxy);
144 EXPECT_EQ(CommandInstance::kStatusQueued, command_instance->GetStatus());
145
146 // Two properties are set, Progress = 50%, Status = "inProgress"
147 EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(2);
148 SetProgress(command_proxy, 50);
149 EXPECT_EQ(CommandInstance::kStatusInProgress, command_instance->GetStatus());
150 EXPECT_EQ(50, command_instance->GetProgress());
151
152 // Command must be removed from the queue and proxy destroyed after calling
153 // FinishCommand().
154 // Two properties are set, Progress = 100%, Status = "done"
155 EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(2);
156 // D-Bus command proxy is going away.
157 EXPECT_CALL(*mock_exported_command_proxy_, Unregister()).Times(1);
158 // Two interfaces are being removed on the D-Bus command object.
159 EXPECT_CALL(*mock_exported_object_manager_, SendSignal(_)).Times(2);
160 FinishCommand(command_proxy);
161
Alex Vakulenko95110752014-09-03 16:27:21 -0700162 EXPECT_EQ(nullptr, command_queue_.Find(id));
163}
164
165TEST_F(DBusCommandDispacherTest, Test_Command_Base_Reboot) {
Anton Muhin5191e812014-10-30 17:49:48 +0400166 const std::string id = "id0001";
167 AddNewCommand(R"({
Alex Vakulenko95110752014-09-03 16:27:21 -0700168 'name': 'base.reboot',
169 'parameters': {
170 'delay': 20
171 }
Anton Muhin5191e812014-10-30 17:49:48 +0400172 })", id);
Alex Vakulenko95110752014-09-03 16:27:21 -0700173 CommandInstance* command_instance = command_queue_.Find(id);
174 ASSERT_NE(nullptr, command_instance);
Anton Muhina22f4be2014-11-10 15:02:15 +0400175 DBusCommandProxy* command_proxy = FindProxy(command_instance);
Alex Vakulenko95110752014-09-03 16:27:21 -0700176 ASSERT_NE(nullptr, command_proxy);
177 EXPECT_EQ(CommandInstance::kStatusQueued, command_instance->GetStatus());
178
179 // Two properties are set, Progress = 50%, Status = "inProgress"
180 EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(2);
181 SetProgress(command_proxy, 50);
182 EXPECT_EQ(CommandInstance::kStatusInProgress, command_instance->GetStatus());
183 EXPECT_EQ(50, command_instance->GetProgress());
184
185 // Command must be removed from the queue and proxy destroyed after calling
186 // FinishCommand().
187 // Two properties are set, Progress = 100%, Status = "done"
188 EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(2);
189 // D-Bus command proxy is going away.
190 EXPECT_CALL(*mock_exported_command_proxy_, Unregister()).Times(1);
191 // Two interfaces are being removed on the D-Bus command object.
192 EXPECT_CALL(*mock_exported_object_manager_, SendSignal(_)).Times(2);
193 FinishCommand(command_proxy);
194
Alex Vakulenko95110752014-09-03 16:27:21 -0700195 EXPECT_EQ(nullptr, command_queue_.Find(id));
196}
197
198
199} // namespace buffet