blob: 5f2d5974d33eadfea000b39ca71005458606caa6 [file] [log] [blame]
// Copyright 2022 The Chromium OS Authors. All rights reserved.
// 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/bind.h>
#include <base/run_loop.h>
#include <base/task/single_thread_task_executor.h>
#include <base/test/task_environment.h>
#include <base/threading/thread.h>
#include <base/threading/thread_task_runner_handle.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::RunLoop run_loop;
std::unique_ptr<MockDBusMethodResponse<SendCommandResponse>> response(
new MockDBusMethodResponse<SendCommandResponse>());
std::string response_message;
response->set_return_callback(base::BindRepeating(
[](base::RunLoop* run_loop, std::string* response_message,
const SendCommandResponse& response) {
*response_message = response.response();
run_loop->Quit();
},
&run_loop, &response_message));
SendCommandRequest request;
request.set_command(kTestMessage);
service_.SendCommand(std::move(response), request);
run_loop.Run();
EXPECT_EQ(response_message, kTestMessage);
}
TEST_F(VtpmServiceTest, GetResponseNoWorkerThread) {
selector_.SetIsThreaded(false);
base::RunLoop run_loop;
std::unique_ptr<MockDBusMethodResponse<SendCommandResponse>> response(
new MockDBusMethodResponse<SendCommandResponse>());
std::string response_message;
response->set_return_callback(base::BindRepeating(
[](base::RunLoop* run_loop, std::string* response_message,
const SendCommandResponse& response) {
*response_message = response.response();
run_loop->Quit();
},
&run_loop, &response_message));
SendCommandRequest request;
request.set_command(kTestMessage);
service_.SendCommand(std::move(response), request);
run_loop.Run();
EXPECT_EQ(response_message, kTestMessage);
}
} // namespace
} // namespace vtpm