blob: 5257bbb3fb761c2213a24c5e85644a926044296f [file] [log] [blame] [edit]
// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIBHWSEC_FOUNDATION_ERROR_TESTING_HELPER_H_
#define LIBHWSEC_FOUNDATION_ERROR_TESTING_HELPER_H_
#include <string>
#include <type_traits>
#include <utility>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "libhwsec-foundation/status/status_chain.h"
namespace hwsec_foundation {
namespace error {
namespace testing {
using ::hwsec_foundation::status::MakeStatus;
using ::hwsec_foundation::status::OkStatus;
// Some generic matcher functions for StatusChain/StatusChainOr.
// For the example usage, please check testing_helper_test.cc
MATCHER(IsOk, "") {
if (!arg.ok()) {
*result_listener << "status: " << arg.status();
return false;
}
return true;
}
MATCHER_P(IsOkAndHolds, m, "") {
if (!arg.ok()) {
*result_listener << "status: " << arg.status();
return false;
}
if (!(arg.value() == m)) {
*result_listener << "value: " << ::testing::PrintToString(arg.value());
return false;
}
return true;
}
MATCHER_P(IsOkAnd, m, "") {
if (!arg.ok()) {
*result_listener << "status: " << arg.status();
return false;
}
return ExplainMatchResult(m, arg.value(), result_listener);
}
MATCHER(NotOk, "") {
if (arg.ok()) {
*result_listener << "is ok";
return false;
}
return true;
}
MATCHER_P(NotOkWith, expect_string, "") {
if (arg.ok()) {
*result_listener << "is ok";
return false;
}
std::string full = arg.status().ToFullString();
if (full.find(expect_string) == std::string::npos) {
*result_listener << "status: " << full;
return false;
}
return true;
}
MATCHER_P(NotOkAnd, matcher, "") {
if (arg.ok()) {
*result_listener << "is ok";
return false;
}
return ExplainMatchResult(matcher, arg.status(), result_listener);
}
// A helper function to return generic error object in unittest.
//
// Example Usage:
//
// using ::hwsec_foundation::error::testing::ReturnError;
//
// ON_CALL(tpm, EncryptBlob(_, _, aes_skey, _))
// .WillByDefault(ReturnOk<TPMErrorBase>()); // Always success.
//
// ON_CALL(tpm, EncryptBlob(_, _, _, _))
// .WillByDefault(
// ReturnError<TPMError>("fake", TPMRetryAction::kFatal));
template <typename T>
using remove_cvref_t =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
ACTION_P(ReturnErrorType, error_ptr) {
return OkStatus<remove_cvref_t<decltype(*error_ptr)>>();
}
ACTION_P2(ReturnErrorType, error_ptr, p1) {
return MakeStatus<remove_cvref_t<decltype(*error_ptr)>>(p1);
}
ACTION_P3(ReturnErrorType, error_ptr, p1, p2) {
return MakeStatus<remove_cvref_t<decltype(*error_ptr)>>(p1, p2);
}
ACTION_P4(ReturnErrorType, error_ptr, p1, p2, p3) {
return MakeStatus<remove_cvref_t<decltype(*error_ptr)>>(p1, p2, p3);
}
ACTION_P5(ReturnErrorType, error_ptr, p1, p2, p3, p4) {
return MakeStatus<remove_cvref_t<decltype(*error_ptr)>>(p1, p2, p3, p4);
}
ACTION_P6(ReturnErrorType, error_ptr, p1, p2, p3, p4, p5) {
return MakeStatus<remove_cvref_t<decltype(*error_ptr)>>(p1, p2, p3, p4, p5);
}
ACTION_P7(ReturnErrorType, error_ptr, p1, p2, p3, p4, p5, p6) {
return MakeStatus<remove_cvref_t<decltype(*error_ptr)>>(p1, p2, p3, p4, p5,
p6);
}
ACTION_P8(ReturnErrorType, error_ptr, p1, p2, p3, p4, p5, p6, p7) {
return MakeStatus<remove_cvref_t<decltype(*error_ptr)>>(p1, p2, p3, p4, p5,
p6, p7);
}
ACTION_P9(ReturnErrorType, error_ptr, p1, p2, p3, p4, p5, p6, p7, p8) {
return MakeStatus<remove_cvref_t<decltype(*error_ptr)>>(p1, p2, p3, p4, p5,
p6, p7, p8);
}
template <typename ErrType, typename... Args>
auto ReturnError(Args&&... args) {
return ReturnErrorType(static_cast<ErrType*>(nullptr),
std::forward<Args>(args)...);
}
template <typename ErrType>
auto ReturnOk() {
return ReturnErrorType(static_cast<ErrType*>(nullptr));
}
ACTION_P(ReturnValue, p1) {
return p1;
}
} // namespace testing
} // namespace error
} // namespace hwsec_foundation
// The Assert* API would be useful to ensure the consumable state of
// StatusChain/StatusChainOr. This is a workaround for CHECK/DCHECK/ASSERT
// macros that doesn't work with the consumable attribute.
// For more information: crbug/1336752#c12, b/223361459
#define ASSERT_OK(x) \
ASSERT_THAT((x).HintOk(), ::hwsec_foundation::error::testing::IsOk())
#define ASSERT_NOT_OK(x) \
ASSERT_THAT((x).HintNotOk(), ::hwsec_foundation::error::testing::NotOk())
#endif // LIBHWSEC_FOUNDATION_ERROR_TESTING_HELPER_H_