blob: 0726c651744ba9176ecb4776aefc4aad765dc188 [file] [log] [blame] [edit]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "vtpm/vtpm_service.h"
#include <string>
#include <utility>
#include <base/functional/bind.h>
#include <base/task/single_thread_task_executor.h>
#include <base/task/single_thread_task_runner.h>
#include <base/test/task_environment.h>
#include <base/test/test_future.h>
#include <base/threading/thread.h>
#include <brillo/dbus/mock_dbus_method_response.h>
#include <brillo/message_loops/base_message_loop.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/mock_bus.h>
#include <dbus/mock_object_proxy.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using ::brillo::dbus_utils::MockDBusMethodResponse;
using ::testing::_;
using ::testing::DoAll;
using ::testing::Matcher;
using ::testing::MatchesRegex;
using ::testing::Pointee;
using ::testing::Return;
using ::testing::SetArgPointee;
using ::testing::StrictMock;
using ::testing::Unused;
namespace vtpm {
namespace {
constexpr char kTestMessage[] = "test message";
class EchoCommand : public Command {
public:
void Run(const std::string& command,
CommandResponseCallback callback) override {
std::move(callback).Run(command);
}
};
class EchoCommandWithThread : public Command {
public:
EchoCommandWithThread() {
worker_thread_.reset(new base::Thread("EchoCommandWithThreadWorker"));
}
~EchoCommandWithThread() override { worker_thread_->Stop(); }
void Run(const std::string& command,
CommandResponseCallback callback) override {
worker_thread_->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(
[](const std::string& command, CommandResponseCallback callback) {
std::move(callback).Run(command);
},
command, std::move(callback)));
}
void Start() {
worker_thread_->StartWithOptions(
base::Thread::Options(base::MessagePumpType::IO, 0));
}
private:
std::unique_ptr<base::Thread> worker_thread_;
};
class EchoCommandSelector : public Command {
public:
void SetIsThreaded(bool is_threaded) { is_threaded_ = is_threaded; }
void Run(const std::string& command,
CommandResponseCallback callback) override {
if (is_threaded_) {
threaded_echo_command_.Start();
threaded_echo_command_.Run(command, std::move(callback));
} else {
echo_command_.Run(command, std::move(callback));
}
}
private:
bool is_threaded_ = false;
EchoCommand echo_command_;
EchoCommandWithThread threaded_echo_command_;
};
} // namespace
class VtpmServiceTest : public ::testing::Test {
public:
// No setup needed for this test.
protected:
base::test::SingleThreadTaskEnvironment task_environment_;
EchoCommandSelector selector_;
VtpmService service_{&selector_};
};
namespace {
TEST_F(VtpmServiceTest, GetResponseWorkerThread) {
selector_.SetIsThreaded(true);
base::test::TestFuture<const SendCommandResponse&> future;
std::unique_ptr<MockDBusMethodResponse<SendCommandResponse>> response(
new MockDBusMethodResponse<SendCommandResponse>());
response->set_return_callback(future.GetCallback());
SendCommandRequest request;
request.set_command(kTestMessage);
service_.SendCommand(std::move(response), request);
EXPECT_EQ(future.Get().response(), kTestMessage);
}
TEST_F(VtpmServiceTest, GetResponseNoWorkerThread) {
selector_.SetIsThreaded(false);
base::test::TestFuture<const SendCommandResponse&> future;
std::unique_ptr<MockDBusMethodResponse<SendCommandResponse>> response(
new MockDBusMethodResponse<SendCommandResponse>());
response->set_return_callback(future.GetCallback());
SendCommandRequest request;
request.set_command(kTestMessage);
service_.SendCommand(std::move(response), request);
EXPECT_EQ(future.Get().response(), kTestMessage);
}
} // namespace
} // namespace vtpm