/*
 *    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 <gtest/gtest.h>
#include <tracing/backend.h>
#include <tracing/metric_event.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;
};

TEST(TestMetricEvents, TestBasicMetricEvent)
{

    {
        MetricEvent event(MetricEvent::Type::kInstantEvent, "instant_event");
        EXPECT_EQ(event.type(), MetricEvent::Type::kInstantEvent);
        EXPECT_EQ(std::string(event.key()), std::string("instant_event"));
        EXPECT_EQ(event.ValueType(), MetricEvent::Value::Type::kUndefined);
    }

    {
        MetricEvent event(MetricEvent::Type::kBeginEvent, "begin_event");
        EXPECT_EQ(event.type(), MetricEvent::Type::kBeginEvent);
        EXPECT_EQ(std::string(event.key()), std::string("begin_event"));
        EXPECT_EQ(event.ValueType(), MetricEvent::Value::Type::kUndefined);
    }

    {
        MetricEvent event(MetricEvent::Type::kEndEvent, "end_event");
        EXPECT_EQ(event.type(), MetricEvent::Type::kEndEvent);
        EXPECT_EQ(std::string(event.key()), std::string("end_event"));
        EXPECT_EQ(event.ValueType(), MetricEvent::Value::Type::kUndefined);
    }

    {
        MetricEvent event(MetricEvent::Type::kEndEvent, "end_event_with_int32_value", int32_t(42));
        EXPECT_EQ(event.type(), MetricEvent::Type::kEndEvent);
        EXPECT_EQ(std::string(event.key()), std::string("end_event_with_int32_value"));
        EXPECT_EQ(event.ValueType(), MetricEvent::Value::Type::kInt32);
        EXPECT_EQ(event.ValueInt32(), 42);
    }

    {
        MetricEvent event(MetricEvent::Type::kEndEvent, "end_event_with_uint32_value", uint32_t(42));
        EXPECT_EQ(event.type(), MetricEvent::Type::kEndEvent);
        EXPECT_EQ(std::string(event.key()), std::string("end_event_with_uint32_value"));
        EXPECT_EQ(event.ValueType(), MetricEvent::Value::Type::kUInt32);
        EXPECT_EQ(event.ValueUInt32(), 42u);
    }

    {
        MetricEvent event(MetricEvent::Type::kEndEvent, "end_event_with_error_value", CHIP_ERROR_BUSY);
        EXPECT_EQ(event.type(), MetricEvent::Type::kEndEvent);
        EXPECT_EQ(std::string(event.key()), std::string("end_event_with_error_value"));
        EXPECT_EQ(event.ValueType(), MetricEvent::Value::Type::kChipErrorCode);
        EXPECT_EQ(chip::ChipError(event.ValueErrorCode()), CHIP_ERROR_BUSY);
    }
}

TEST(TestMetricEvents, TestInstantMetricEvent)
{
    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"),
    };

    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}

TEST(TestMetricEvents, TestBeginEndMetricEvent)
{
    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"),
        };

        EXPECT_EQ(backend1.GetMetricEvents().size(), expected1.size());
        EXPECT_TRUE(
            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"),
        };

        EXPECT_EQ(backend2.GetMetricEvents().size(), expected2.size());
        EXPECT_TRUE(
            std::equal(backend2.GetMetricEvents().begin(), backend2.GetMetricEvents().end(), expected2.begin(), expected2.end()));
    }
}

TEST(TestMetricEvents, TestScopedMetricEvent)
{
    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),
        };

        EXPECT_EQ(backend1.GetMetricEvents().size(), expected1.size());
        EXPECT_TRUE(
            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),
        };

        EXPECT_EQ(backend2.GetMetricEvents().size(), expected2.size());
        EXPECT_TRUE(
            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),
        };

        EXPECT_EQ(backend3.GetMetricEvents().size(), expected3.size());
        EXPECT_TRUE(
            std::equal(backend3.GetMetricEvents().begin(), backend3.GetMetricEvents().end(), expected3.begin(), expected3.end()));
    }
}

static int DoubleOf(int input)
{
    return input * 2;
}

TEST(TestMetricEvents, TestVerifyOrExitWithMetric)
{
    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),
    };

    EXPECT_EQ(err, CHIP_ERROR_INCORRECT_STATE);
    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}

TEST(TestMetricEvents, TestSuccessOrExitWithMetric)
{
    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),
    };

    EXPECT_EQ(err, CHIP_ERROR_BUSY);
    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(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;
}

TEST(TestMetricEvents, TestReturnErrorOnFailureWithMetric)
{
    MetricEventBackend backend;
    ScopedRegistration scope(backend);

    CHIP_ERROR err = InvokeReturnErrorOnFailureWithMetric("event0", CHIP_NO_ERROR);
    EXPECT_EQ(err, CHIP_NO_ERROR);

    err = InvokeReturnErrorOnFailureWithMetric("event1", CHIP_ERROR_INCORRECT_STATE);
    EXPECT_EQ(err, CHIP_ERROR_INCORRECT_STATE);

    err = InvokeReturnErrorOnFailureWithMetric("event2", CHIP_ERROR_BAD_REQUEST);
    EXPECT_EQ(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),
    };

    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(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;
}

TEST(TestMetricEvents, TestReturnLogErrorOnFailureWithMetric)
{
    MetricEventBackend backend;
    ScopedRegistration scope(backend);

    CHIP_ERROR err = InvokeReturnLogErrorOnFailureWithMetric("event0", CHIP_NO_ERROR);
    EXPECT_EQ(err, CHIP_NO_ERROR);

    err = InvokeReturnLogErrorOnFailureWithMetric("event1", CHIP_ERROR_INCORRECT_STATE);
    EXPECT_EQ(err, CHIP_ERROR_INCORRECT_STATE);

    err = InvokeReturnLogErrorOnFailureWithMetric("event2", CHIP_ERROR_BAD_REQUEST);
    EXPECT_EQ(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),
    };

    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(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;
}

TEST(TestMetricEvents, TestReturnOnFailureWithMetric)
{
    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),
    };

    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}

static void InvokeVerifyOrReturnWithMetric(MetricKey key, bool result)
{
    VerifyOrReturnWithMetric(key, result);
    return;
}

TEST(TestMetricEvents, TestInvokeVerifyOrReturnWithMetric)
{
    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),
    };

    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(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;
}

TEST(TestMetricEvents, TestVerifyOrReturnErrorWithMetric)
{
    MetricEventBackend backend;
    ScopedRegistration scope(backend);

    CHIP_ERROR err = InvokeVerifyOrReturnErrorWithMetric("event0", DoubleOf(2) == 4, CHIP_ERROR_BAD_REQUEST);
    EXPECT_EQ(err, CHIP_NO_ERROR);

    err = InvokeVerifyOrReturnErrorWithMetric("event1", DoubleOf(3) == 9, CHIP_ERROR_ACCESS_DENIED);
    EXPECT_EQ(err, CHIP_ERROR_ACCESS_DENIED);

    err = InvokeVerifyOrReturnErrorWithMetric("event2", DoubleOf(4) == 8, CHIP_ERROR_BUSY);
    EXPECT_EQ(err, CHIP_NO_ERROR);

    err = InvokeVerifyOrReturnErrorWithMetric("event3", DoubleOf(5) == 11, CHIP_ERROR_CANCELLED);
    EXPECT_EQ(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),
    };

    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(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();
}

TEST(TestMetricEvents, TestVerifyOrReturnValueWithMetric)
{
    MetricEventBackend backend;
    ScopedRegistration scope(backend);

    auto retval = InvokeVerifyOrReturnValueWithMetric("event0", DoubleOf(2) == 4, 0);
    EXPECT_EQ(retval, 0);

    auto err = InvokeVerifyOrReturnValueWithMetric("event1", DoubleOf(3) == 9, CHIP_ERROR_ACCESS_DENIED);
    EXPECT_EQ(err, CHIP_ERROR_ACCESS_DENIED);

    err = InvokeVerifyOrReturnValueWithMetric("event2", DoubleOf(4) == 8, CHIP_ERROR_BAD_REQUEST);
    EXPECT_EQ(err, CHIP_NO_ERROR);

    retval = InvokeVerifyOrReturnValueWithMetric("event3", DoubleOf(5) == 11, 16);
    EXPECT_EQ(retval, 16);

    std::vector<MetricEvent> expected = {
        MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_ACCESS_DENIED),
        MetricEvent(MetricEvent::Type::kInstantEvent, "event3", 16),
    };

    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(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;
}

TEST(TestMetricEvents, TestVerifyOrReturnLogErrorWithMetric)
{
    MetricEventBackend backend;
    ScopedRegistration scope(backend);

    auto err = InvokeVerifyOrReturnLogErrorWithMetric("event0", DoubleOf(2) == 4, CHIP_NO_ERROR);
    EXPECT_EQ(err, CHIP_NO_ERROR);

    err = InvokeVerifyOrReturnLogErrorWithMetric("event1", DoubleOf(3) == 9, CHIP_ERROR_CANCELLED);
    EXPECT_EQ(err, CHIP_ERROR_CANCELLED);

    err = InvokeVerifyOrReturnLogErrorWithMetric("event2", DoubleOf(4) == 8, CHIP_NO_ERROR);
    EXPECT_EQ(err, CHIP_NO_ERROR);

    err = InvokeVerifyOrReturnLogErrorWithMetric("event3", DoubleOf(5) == 11, CHIP_ERROR_BAD_REQUEST);
    EXPECT_EQ(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),
    };

    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(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();
}

TEST(TestMetricEvents, TestReturnErrorCodeWithMetricIf)
{
    MetricEventBackend backend;
    ScopedRegistration scope(backend);

    auto err = InvokeReturnErrorCodeWithMetricIf("event0", DoubleOf(2) == 4, CHIP_ERROR_DUPLICATE_KEY_ID);
    EXPECT_EQ(err, CHIP_ERROR_DUPLICATE_KEY_ID);

    auto retval = InvokeReturnErrorCodeWithMetricIf("event1", DoubleOf(3) == 9, 11);
    EXPECT_EQ(retval, 0);

    retval = InvokeReturnErrorCodeWithMetricIf("event2", DoubleOf(4) == 8, 22);
    EXPECT_EQ(retval, 22);

    err = InvokeReturnErrorCodeWithMetricIf("event3", DoubleOf(5) == 11, CHIP_ERROR_ACCESS_DENIED);
    EXPECT_EQ(err, CHIP_NO_ERROR);

    std::vector<MetricEvent> expected = {
        MetricEvent(MetricEvent::Type::kInstantEvent, "event0", CHIP_ERROR_DUPLICATE_KEY_ID),
        MetricEvent(MetricEvent::Type::kInstantEvent, "event2", 22),
    };

    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}

TEST(TestMetricEvents, TestExitNowWithMetric)
{
    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"),
    };

    EXPECT_EQ(err, CHIP_ERROR_BUSY);
    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}

TEST(TestMetricEvents, TestLogErrorOnFailureWithMetric)
{
    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),
    };

    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}

TEST(TestMetricEvents, TestVerifyOrDoWithMetric)
{
    MetricEventBackend backend;
    ScopedRegistration scope(backend);

    VerifyOrDoWithMetric("event0", DoubleOf(2) == 5, 11);
    VerifyOrDoWithMetric("event1", DoubleOf(3) == 6, 12);
    VerifyOrDoWithMetric("event2", DoubleOf(4) == 7, CHIP_ERROR_BAD_REQUEST, MATTER_LOG_METRIC("event4", 10));
    VerifyOrDoWithMetric("event3", DoubleOf(5) == 8, 13);
    VerifyOrDoWithMetric("event5", DoubleOf(6) == 12, 14);

    std::vector<MetricEvent> expected = {
        MetricEvent(MetricEvent::Type::kInstantEvent, "event0", 11),
        MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_BAD_REQUEST),
        MetricEvent(MetricEvent::Type::kInstantEvent, "event4", 10),
        MetricEvent(MetricEvent::Type::kInstantEvent, "event3", 13),
    };

    EXPECT_EQ(backend.GetMetricEvents().size(), expected.size());
    EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end()));
}

} // namespace
