blob: 72e159df7cf7fae73c2f4b106e76617b38517dfe [file] [log] [blame]
/*
* Copyright (c) 2024 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <lib/support/UnitTestRegistration.h>
#include <tracing/backend.h>
#include <tracing/metric_event.h>
#include <nlunit-test.h>
#include <algorithm>
#include <string>
#include <vector>
using namespace chip;
using namespace chip::Tracing;
namespace chip {
namespace Tracing {
static bool operator==(const MetricEvent & lhs, const MetricEvent & rhs)
{
if (&lhs == &rhs)
{
return true;
}
if (lhs.type() == rhs.type() && std::string(lhs.key()) == std::string(rhs.key()) && lhs.ValueType() == rhs.ValueType())
{
switch (lhs.ValueType())
{
case MetricEvent::Value::Type::kInt32:
return lhs.ValueInt32() == rhs.ValueInt32();
case MetricEvent::Value::Type::kUInt32:
return lhs.ValueUInt32() == rhs.ValueUInt32();
case MetricEvent::Value::Type::kChipErrorCode:
return lhs.ValueErrorCode() == rhs.ValueErrorCode();
case MetricEvent::Value::Type::kUndefined:
return true;
}
}
return false;
}
} // namespace Tracing
} // namespace chip
namespace {
// This keeps a log of all received trace items
class MetricEventBackend : public Backend
{
public:
MetricEventBackend() {}
const std::vector<MetricEvent> & GetMetricEvents() const { return mMetricEvents; }
// Implementation
virtual void LogMetricEvent(const MetricEvent & event) { mMetricEvents.push_back(event); }
private:
std::vector<MetricEvent> mMetricEvents;
};
void TestBasicMetricEvent(nlTestSuite * inSuite, void * inContext)
{
{
MetricEvent event(MetricEvent::Type::kInstantEvent, "instant_event");
NL_TEST_ASSERT(inSuite, event.type() == MetricEvent::Type::kInstantEvent);
NL_TEST_ASSERT(inSuite, std::string(event.key()) == std::string("instant_event"));
NL_TEST_ASSERT(inSuite, event.ValueType() == MetricEvent::Value::Type::kUndefined);
}
{
MetricEvent event(MetricEvent::Type::kBeginEvent, "begin_event");
NL_TEST_ASSERT(inSuite, event.type() == MetricEvent::Type::kBeginEvent);
NL_TEST_ASSERT(inSuite, std::string(event.key()) == std::string("begin_event"));
NL_TEST_ASSERT(inSuite, event.ValueType() == MetricEvent::Value::Type::kUndefined);
}
{
MetricEvent event(MetricEvent::Type::kEndEvent, "end_event");
NL_TEST_ASSERT(inSuite, event.type() == MetricEvent::Type::kEndEvent);
NL_TEST_ASSERT(inSuite, std::string(event.key()) == std::string("end_event"));
NL_TEST_ASSERT(inSuite, event.ValueType() == MetricEvent::Value::Type::kUndefined);
}
{
MetricEvent event(MetricEvent::Type::kEndEvent, "end_event_with_int32_value", int32_t(42));
NL_TEST_ASSERT(inSuite, event.type() == MetricEvent::Type::kEndEvent);
NL_TEST_ASSERT(inSuite, std::string(event.key()) == std::string("end_event_with_int32_value"));
NL_TEST_ASSERT(inSuite, event.ValueType() == MetricEvent::Value::Type::kInt32);
NL_TEST_ASSERT(inSuite, event.ValueInt32() == 42);
}
{
MetricEvent event(MetricEvent::Type::kEndEvent, "end_event_with_uint32_value", uint32_t(42));
NL_TEST_ASSERT(inSuite, event.type() == MetricEvent::Type::kEndEvent);
NL_TEST_ASSERT(inSuite, std::string(event.key()) == std::string("end_event_with_uint32_value"));
NL_TEST_ASSERT(inSuite, event.ValueType() == MetricEvent::Value::Type::kUInt32);
NL_TEST_ASSERT(inSuite, event.ValueUInt32() == 42u);
}
{
MetricEvent event(MetricEvent::Type::kEndEvent, "end_event_with_error_value", CHIP_ERROR_BUSY);
NL_TEST_ASSERT(inSuite, event.type() == MetricEvent::Type::kEndEvent);
NL_TEST_ASSERT(inSuite, std::string(event.key()) == std::string("end_event_with_error_value"));
NL_TEST_ASSERT(inSuite, event.ValueType() == MetricEvent::Value::Type::kChipErrorCode);
NL_TEST_ASSERT(inSuite, chip::ChipError(event.ValueErrorCode()) == CHIP_ERROR_BUSY);
}
}
void TestInstantMetricEvent(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
{
ScopedRegistration scope(backend);
MATTER_LOG_METRIC("event1");
MATTER_LOG_METRIC("event2");
MATTER_LOG_METRIC("event3");
}
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event1"),
MetricEvent(MetricEvent::Type::kInstantEvent, "event2"),
MetricEvent(MetricEvent::Type::kInstantEvent, "event3"),
};
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
void TestBeginEndMetricEvent(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend1;
MetricEventBackend backend2;
{
ScopedRegistration scope1(backend1);
{
MATTER_LOG_METRIC_BEGIN("event1");
MATTER_LOG_METRIC_BEGIN("event2");
MATTER_LOG_METRIC_END("event2", 53);
MATTER_LOG_METRIC_END("event1");
}
std::vector<MetricEvent> expected1 = {
MetricEvent(MetricEvent::Type::kBeginEvent, "event1"),
MetricEvent(MetricEvent::Type::kBeginEvent, "event2"),
MetricEvent(MetricEvent::Type::kEndEvent, "event2", 53),
MetricEvent(MetricEvent::Type::kEndEvent, "event1"),
};
NL_TEST_ASSERT(inSuite, backend1.GetMetricEvents().size() == expected1.size());
NL_TEST_ASSERT(
inSuite,
std::equal(backend1.GetMetricEvents().begin(), backend1.GetMetricEvents().end(), expected1.begin(), expected1.end()));
{
ScopedRegistration scope2(backend2);
MATTER_LOG_METRIC_BEGIN("event1");
MATTER_LOG_METRIC_BEGIN("event2");
MATTER_LOG_METRIC_BEGIN("event3");
MATTER_LOG_METRIC_BEGIN("event4");
MATTER_LOG_METRIC_END("event3", CHIP_ERROR_UNKNOWN_KEY_TYPE);
MATTER_LOG_METRIC_END("event1", 91u);
MATTER_LOG_METRIC_END("event2", 53);
MATTER_LOG_METRIC_END("event4");
}
std::vector<MetricEvent> expected2 = {
MetricEvent(MetricEvent::Type::kBeginEvent, "event1"),
MetricEvent(MetricEvent::Type::kBeginEvent, "event2"),
MetricEvent(MetricEvent::Type::kBeginEvent, "event3"),
MetricEvent(MetricEvent::Type::kBeginEvent, "event4"),
MetricEvent(MetricEvent::Type::kEndEvent, "event3", CHIP_ERROR_UNKNOWN_KEY_TYPE),
MetricEvent(MetricEvent::Type::kEndEvent, "event1", 91u),
MetricEvent(MetricEvent::Type::kEndEvent, "event2", 53),
MetricEvent(MetricEvent::Type::kEndEvent, "event4"),
};
NL_TEST_ASSERT(inSuite, backend2.GetMetricEvents().size() == expected2.size());
NL_TEST_ASSERT(
inSuite,
std::equal(backend2.GetMetricEvents().begin(), backend2.GetMetricEvents().end(), expected2.begin(), expected2.end()));
}
}
void TestScopedMetricEvent(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend1;
MetricEventBackend backend2;
MetricEventBackend backend3;
chip::ChipError err1 = CHIP_NO_ERROR;
chip::ChipError err2 = CHIP_NO_ERROR;
chip::ChipError err3 = CHIP_NO_ERROR;
chip::ChipError err4 = CHIP_NO_ERROR;
{
ScopedRegistration scope1(backend1);
{
MATTER_LOG_METRIC_SCOPE("event1", err1);
err1 = CHIP_ERROR_BUSY;
{
ScopedRegistration scope2(backend2);
MATTER_LOG_METRIC_SCOPE("event2", err2);
err2 = CHIP_ERROR_BAD_REQUEST;
{
ScopedRegistration scope3(backend3);
MATTER_LOG_METRIC_SCOPE("event3", err3);
err3 = CHIP_ERROR_EVENT_ID_FOUND;
}
{
MATTER_LOG_METRIC_SCOPE("event4", err4);
err4 = CHIP_ERROR_BUFFER_TOO_SMALL;
}
}
}
std::vector<MetricEvent> expected1 = {
MetricEvent(MetricEvent::Type::kBeginEvent, "event1"),
MetricEvent(MetricEvent::Type::kBeginEvent, "event2"),
MetricEvent(MetricEvent::Type::kBeginEvent, "event3"),
MetricEvent(MetricEvent::Type::kEndEvent, "event3", CHIP_ERROR_EVENT_ID_FOUND),
MetricEvent(MetricEvent::Type::kBeginEvent, "event4"),
MetricEvent(MetricEvent::Type::kEndEvent, "event4", CHIP_ERROR_BUFFER_TOO_SMALL),
MetricEvent(MetricEvent::Type::kEndEvent, "event2", CHIP_ERROR_BAD_REQUEST),
MetricEvent(MetricEvent::Type::kEndEvent, "event1", CHIP_ERROR_BUSY),
};
NL_TEST_ASSERT(inSuite, backend1.GetMetricEvents().size() == expected1.size());
NL_TEST_ASSERT(
inSuite,
std::equal(backend1.GetMetricEvents().begin(), backend1.GetMetricEvents().end(), expected1.begin(), expected1.end()));
std::vector<MetricEvent> expected2 = {
MetricEvent(MetricEvent::Type::kBeginEvent, "event2"),
MetricEvent(MetricEvent::Type::kBeginEvent, "event3"),
MetricEvent(MetricEvent::Type::kEndEvent, "event3", CHIP_ERROR_EVENT_ID_FOUND),
MetricEvent(MetricEvent::Type::kBeginEvent, "event4"),
MetricEvent(MetricEvent::Type::kEndEvent, "event4", CHIP_ERROR_BUFFER_TOO_SMALL),
MetricEvent(MetricEvent::Type::kEndEvent, "event2", CHIP_ERROR_BAD_REQUEST),
};
NL_TEST_ASSERT(inSuite, backend2.GetMetricEvents().size() == expected2.size());
NL_TEST_ASSERT(
inSuite,
std::equal(backend2.GetMetricEvents().begin(), backend2.GetMetricEvents().end(), expected2.begin(), expected2.end()));
std::vector<MetricEvent> expected3 = {
MetricEvent(MetricEvent::Type::kBeginEvent, "event3"),
MetricEvent(MetricEvent::Type::kEndEvent, "event3", CHIP_ERROR_EVENT_ID_FOUND),
};
NL_TEST_ASSERT(inSuite, backend3.GetMetricEvents().size() == expected3.size());
NL_TEST_ASSERT(
inSuite,
std::equal(backend3.GetMetricEvents().begin(), backend3.GetMetricEvents().end(), expected3.begin(), expected3.end()));
}
}
static int DoubleOf(int input)
{
return input * 2;
}
void TestVerifyOrExitWithMetric(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
ScopedRegistration scope(backend);
chip::ChipError err = CHIP_NO_ERROR;
VerifyOrExitWithMetric("event0", DoubleOf(2) == 4, err = CHIP_ERROR_BAD_REQUEST);
VerifyOrExitWithMetric("event1", DoubleOf(3) == 9, err = CHIP_ERROR_INCORRECT_STATE);
exit:
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_INCORRECT_STATE),
};
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
void TestSuccessOrExitWithMetric(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
ScopedRegistration scope(backend);
chip::ChipError err = CHIP_NO_ERROR;
SuccessOrExitWithMetric("event1", err = CHIP_NO_ERROR);
SuccessOrExitWithMetric("event2", err = CHIP_ERROR_BUSY);
SuccessOrExitWithMetric("event3", err = CHIP_NO_ERROR);
exit:
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_BUSY),
};
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUSY);
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
static CHIP_ERROR InvokeReturnErrorOnFailureWithMetric(MetricKey key, const CHIP_ERROR & error)
{
ReturnErrorOnFailureWithMetric(key, error);
return CHIP_NO_ERROR;
}
void TestReturnErrorOnFailureWithMetric(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
ScopedRegistration scope(backend);
CHIP_ERROR err = InvokeReturnErrorOnFailureWithMetric("event0", CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = InvokeReturnErrorOnFailureWithMetric("event1", CHIP_ERROR_INCORRECT_STATE);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
err = InvokeReturnErrorOnFailureWithMetric("event2", CHIP_ERROR_BAD_REQUEST);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BAD_REQUEST);
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_INCORRECT_STATE),
MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_BAD_REQUEST),
};
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
static CHIP_ERROR InvokeReturnLogErrorOnFailureWithMetric(MetricKey key, const CHIP_ERROR & error)
{
ReturnLogErrorOnFailureWithMetric(key, error);
return CHIP_NO_ERROR;
}
void TestReturnLogErrorOnFailureWithMetric(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
ScopedRegistration scope(backend);
CHIP_ERROR err = InvokeReturnLogErrorOnFailureWithMetric("event0", CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = InvokeReturnLogErrorOnFailureWithMetric("event1", CHIP_ERROR_INCORRECT_STATE);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
err = InvokeReturnLogErrorOnFailureWithMetric("event2", CHIP_ERROR_BAD_REQUEST);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BAD_REQUEST);
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_INCORRECT_STATE),
MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_BAD_REQUEST),
};
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
static void InvokeReturnOnFailureWithMetric(MetricKey key, const CHIP_ERROR & error)
{
ReturnOnFailureWithMetric(key, error);
return;
}
void TestReturnOnFailureWithMetric(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
ScopedRegistration scope(backend);
InvokeReturnOnFailureWithMetric("event0", CHIP_NO_ERROR);
InvokeReturnOnFailureWithMetric("event1", CHIP_ERROR_INCORRECT_STATE);
InvokeReturnOnFailureWithMetric("event2", CHIP_ERROR_BAD_REQUEST);
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_INCORRECT_STATE),
MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_BAD_REQUEST),
};
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
static void InvokeVerifyOrReturnWithMetric(MetricKey key, bool result)
{
VerifyOrReturnWithMetric(key, result);
return;
}
void TestInvokeVerifyOrReturnWithMetric(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
ScopedRegistration scope(backend);
InvokeVerifyOrReturnWithMetric("event0", DoubleOf(2) == 4);
InvokeVerifyOrReturnWithMetric("event1", DoubleOf(3) == 9);
InvokeVerifyOrReturnWithMetric("event2", DoubleOf(4) == 8);
InvokeVerifyOrReturnWithMetric("event3", DoubleOf(5) == 11);
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event1", false),
MetricEvent(MetricEvent::Type::kInstantEvent, "event3", false),
};
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
static CHIP_ERROR InvokeVerifyOrReturnErrorWithMetric(MetricKey key, bool expr, const CHIP_ERROR & error)
{
VerifyOrReturnErrorWithMetric(key, expr, error);
return CHIP_NO_ERROR;
}
void TestVerifyOrReturnErrorWithMetric(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
ScopedRegistration scope(backend);
CHIP_ERROR err = InvokeVerifyOrReturnErrorWithMetric("event0", DoubleOf(2) == 4, CHIP_ERROR_BAD_REQUEST);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = InvokeVerifyOrReturnErrorWithMetric("event1", DoubleOf(3) == 9, CHIP_ERROR_ACCESS_DENIED);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_ACCESS_DENIED);
err = InvokeVerifyOrReturnErrorWithMetric("event2", DoubleOf(4) == 8, CHIP_ERROR_BUSY);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = InvokeVerifyOrReturnErrorWithMetric("event3", DoubleOf(5) == 11, CHIP_ERROR_CANCELLED);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_CANCELLED);
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_ACCESS_DENIED),
MetricEvent(MetricEvent::Type::kInstantEvent, "event3", CHIP_ERROR_CANCELLED),
};
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
template <typename return_code_type>
static return_code_type InvokeVerifyOrReturnValueWithMetric(MetricKey key, bool expr, return_code_type retval)
{
VerifyOrReturnValueWithMetric(key, expr, retval);
return return_code_type();
}
void TestVerifyOrReturnValueWithMetric(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
ScopedRegistration scope(backend);
auto retval = InvokeVerifyOrReturnValueWithMetric("event0", DoubleOf(2) == 4, 0);
NL_TEST_ASSERT(inSuite, retval == 0);
auto err = InvokeVerifyOrReturnValueWithMetric("event1", DoubleOf(3) == 9, CHIP_ERROR_ACCESS_DENIED);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_ACCESS_DENIED);
err = InvokeVerifyOrReturnValueWithMetric("event2", DoubleOf(4) == 8, CHIP_ERROR_BAD_REQUEST);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
retval = InvokeVerifyOrReturnValueWithMetric("event3", DoubleOf(5) == 11, 16);
NL_TEST_ASSERT(inSuite, retval == 16);
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_ACCESS_DENIED),
MetricEvent(MetricEvent::Type::kInstantEvent, "event3", 16),
};
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
static CHIP_ERROR InvokeVerifyOrReturnLogErrorWithMetric(MetricKey key, bool expr, const CHIP_ERROR & error)
{
VerifyOrReturnLogErrorWithMetric(key, expr, error);
return CHIP_NO_ERROR;
}
void TestVerifyOrReturnLogErrorWithMetric(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
ScopedRegistration scope(backend);
auto err = InvokeVerifyOrReturnLogErrorWithMetric("event0", DoubleOf(2) == 4, CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = InvokeVerifyOrReturnLogErrorWithMetric("event1", DoubleOf(3) == 9, CHIP_ERROR_CANCELLED);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_CANCELLED);
err = InvokeVerifyOrReturnLogErrorWithMetric("event2", DoubleOf(4) == 8, CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = InvokeVerifyOrReturnLogErrorWithMetric("event3", DoubleOf(5) == 11, CHIP_ERROR_BAD_REQUEST);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BAD_REQUEST);
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_CANCELLED),
MetricEvent(MetricEvent::Type::kInstantEvent, "event3", CHIP_ERROR_BAD_REQUEST),
};
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
template <typename return_code_type>
static return_code_type InvokeReturnErrorCodeWithMetricIf(MetricKey key, bool expr, const return_code_type & code)
{
ReturnErrorCodeWithMetricIf(key, expr, code);
return return_code_type();
}
void TestReturnErrorCodeWithMetricIf(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
ScopedRegistration scope(backend);
auto err = InvokeReturnErrorCodeWithMetricIf("event0", DoubleOf(2) == 4, CHIP_ERROR_DUPLICATE_KEY_ID);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_DUPLICATE_KEY_ID);
auto retval = InvokeReturnErrorCodeWithMetricIf("event1", DoubleOf(3) == 9, 11);
NL_TEST_ASSERT(inSuite, retval == 0);
retval = InvokeReturnErrorCodeWithMetricIf("event2", DoubleOf(4) == 8, 22);
NL_TEST_ASSERT(inSuite, retval == 22);
err = InvokeReturnErrorCodeWithMetricIf("event3", DoubleOf(5) == 11, CHIP_ERROR_ACCESS_DENIED);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event0", CHIP_ERROR_DUPLICATE_KEY_ID),
MetricEvent(MetricEvent::Type::kInstantEvent, "event2", 22),
};
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
void TestExitNowWithMetric(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
ScopedRegistration scope(backend);
chip::ChipError err = CHIP_NO_ERROR;
ExitNowWithMetric("event0", err = CHIP_ERROR_BUSY);
exit:
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event0"),
};
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUSY);
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
void TestLogErrorOnFailureWithMetric(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
ScopedRegistration scope(backend);
LogErrorOnFailureWithMetric("event0", CHIP_ERROR_BAD_REQUEST);
LogErrorOnFailureWithMetric("event1", CHIP_NO_ERROR);
LogErrorOnFailureWithMetric("event2", CHIP_ERROR_DATA_NOT_ALIGNED);
LogErrorOnFailureWithMetric("event3", CHIP_ERROR_BUSY);
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event0", CHIP_ERROR_BAD_REQUEST),
MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_DATA_NOT_ALIGNED),
MetricEvent(MetricEvent::Type::kInstantEvent, "event3", CHIP_ERROR_BUSY),
};
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
void TestVerifyOrDoWithMetric(nlTestSuite * inSuite, void * inContext)
{
MetricEventBackend backend;
ScopedRegistration scope(backend);
VerifyOrDoWithMetric("event0", DoubleOf(2) == 5);
VerifyOrDoWithMetric("event1", DoubleOf(3) == 6);
VerifyOrDoWithMetric("event2", DoubleOf(4) == 7, MATTER_LOG_METRIC("event4", 10));
VerifyOrDoWithMetric("event3", DoubleOf(5) == 8);
VerifyOrDoWithMetric("event5", DoubleOf(6) == 12);
std::vector<MetricEvent> expected = {
MetricEvent(MetricEvent::Type::kInstantEvent, "event0", false),
MetricEvent(MetricEvent::Type::kInstantEvent, "event2", false),
MetricEvent(MetricEvent::Type::kInstantEvent, "event4", 10),
MetricEvent(MetricEvent::Type::kInstantEvent, "event3", false),
};
NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size());
NL_TEST_ASSERT(
inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}
static const nlTest sMetricTests[] = {
NL_TEST_DEF("BasicMetricEvent", TestBasicMetricEvent), //
NL_TEST_DEF("InstantMetricEvent", TestInstantMetricEvent), //
NL_TEST_DEF("BeginEndMetricEvent", TestBeginEndMetricEvent), //
NL_TEST_DEF("ScopedMetricEvent", TestScopedMetricEvent), //
NL_TEST_DEF("VerifyOrExitWithMetric", TestVerifyOrExitWithMetric), //
NL_TEST_DEF("SuccessOrExitWithMetric", TestSuccessOrExitWithMetric), //
NL_TEST_DEF("ReturnErrorOnFailureWithMetric", TestReturnErrorOnFailureWithMetric), //
NL_TEST_DEF("ReturnLogErrorOnFailureWithMetric", TestReturnLogErrorOnFailureWithMetric), //
NL_TEST_DEF("ReturnOnFailureWithMetric", TestReturnOnFailureWithMetric), //
NL_TEST_DEF("VerifyOrReturnWithMetric", TestInvokeVerifyOrReturnWithMetric), //
NL_TEST_DEF("VerifyOrReturnErrorWithMetric", TestVerifyOrReturnErrorWithMetric), //
NL_TEST_DEF("VerifyOrReturnValueWithMetric", TestVerifyOrReturnValueWithMetric), //
NL_TEST_DEF("VerifyOrReturnLogErrorWithMetric", TestVerifyOrReturnLogErrorWithMetric), //
NL_TEST_DEF("ReturnErrorCodeWithMetricIf", TestReturnErrorCodeWithMetricIf), //
NL_TEST_DEF("ExitNowWithMetric", TestExitNowWithMetric), //
NL_TEST_DEF("LogErrorOnFailureWithMetric", TestLogErrorOnFailureWithMetric), //
NL_TEST_DEF("VerifyOrDoWithMetric", TestVerifyOrDoWithMetric), //
NL_TEST_SENTINEL() //
};
} // namespace
int TestMetricEvents()
{
nlTestSuite theSuite = { "Metric event tests", &sMetricTests[0], nullptr, nullptr };
// Run test suite against one context.
nlTestRunner(&theSuite, nullptr);
return nlTestRunnerStats(&theSuite);
}
CHIP_REGISTER_TEST_SUITE(TestMetricEvents)