// Copyright 2018 The Fuchsia 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 <float.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
#include <unistd.h>

#include <cobalt-client/cpp/histogram-internal.h>
#include <cobalt-client/cpp/histogram-options.h>
#include <cobalt-client/cpp/histogram.h>
#include <fbl/auto_call.h>
#include <fbl/string.h>
#include <fbl/string_printf.h>
#include <fuchsia/cobalt/c/fidl.h>
#include <lib/sync/completion.h>
#include <lib/zx/time.h>
#include <unittest/unittest.h>

namespace cobalt_client {
namespace internal {
namespace {

// Number of threads for running multi threaded tests.
constexpr uint64_t kThreads = 20;

// Number of buckets used for histogram(CUT).
constexpr uint32_t kBuckets = 40;

// Default id for the histogram.
constexpr uint64_t kMetricId = 1;

// Returns an immutable vector of metadata.
fbl::Vector<Metadata>& GetMetadata() {
    static fbl::Vector<Metadata> metadata = {{/*event_type =*/1, /*event_type_index =*/2},
                                             {/*event_type =*/2, /*event_type_index =*/4}};
    return metadata;
}

// Returns true if both vectors contains the same metadata entries in the same order.
bool MetadataEq(const fbl::Vector<Metadata>& lhs, const fbl::Vector<Metadata>& rhs) {
    if (lhs.size() != rhs.size()) {
        return false;
    }

    for (size_t i = 0; i < rhs.size(); ++i) {
        if (memcmp(&lhs[i], &rhs[i], sizeof(Metadata)) != 0) {
            return false;
        }
    }

    return true;
}

RemoteHistogram MakeRemoteHistogram() {
    return RemoteHistogram(kBuckets, kMetricId, GetMetadata());
}

bool HistEventValuesEq(fidl::VectorView<HistogramBucket> actual,
                       fidl::VectorView<HistogramBucket> expected) {
    BEGIN_HELPER;
    ASSERT_EQ(actual.count(), expected.count());
    for (size_t i = 0; i < actual.count(); ++i) {
        HistogramBucket& actual_bucket = actual[i];
        bool found = false;
        for (size_t j = 0; j < expected.count(); ++j) {
            HistogramBucket& expected_bucket = expected[j];
            if (actual_bucket.index != expected_bucket.index) {
                continue;
            }
            EXPECT_EQ(actual_bucket.count, expected_bucket.count);
            found = true;
            break;
        }
        ASSERT_TRUE(found);
    }
    END_HELPER;
}

// Verify the count of the appropiate bucket is updated on increment.
bool TestIncrement() {
    BEGIN_TEST;
    BaseHistogram histogram(kBuckets);

    // Increase the count of each bucket bucket_index times.
    for (uint32_t bucket_index = 0; bucket_index < kBuckets; ++bucket_index) {
        ASSERT_EQ(histogram.GetCount(bucket_index), 0);
        for (uint32_t times = 0; times < bucket_index; ++times) {
            histogram.IncrementCount(bucket_index);
        }
        ASSERT_EQ(histogram.GetCount(bucket_index), bucket_index);
    }

    // Verify that the operations are isolated, each bucket should have bucket_index counts.
    for (uint32_t bucket_index = 0; bucket_index < kBuckets; ++bucket_index) {
        ASSERT_EQ(histogram.GetCount(bucket_index), bucket_index);
    }
    END_TEST;
}

// Verify the count of the appropiate bucket is updated on increment with a specified value. This
// verifies the behaviour for weighted histograms, where the weight is limited to an integer.
bool TestIncrementByVal() {
    BEGIN_TEST;
    BaseHistogram histogram(kBuckets);

    // Increase the count of each bucket bucket_index times.
    for (uint32_t bucket_index = 0; bucket_index < kBuckets; ++bucket_index) {
        ASSERT_EQ(histogram.GetCount(bucket_index), 0);
        histogram.IncrementCount(bucket_index, bucket_index);
        ASSERT_EQ(histogram.GetCount(bucket_index), bucket_index);
    }

    // Verify that the operations are isolated, each bucket should have bucket_index counts.
    for (uint32_t bucket_index = 0; bucket_index < kBuckets; ++bucket_index) {
        ASSERT_EQ(histogram.GetCount(bucket_index), bucket_index);
    }
    END_TEST;
}

struct IncrementArgs {
    // Target histogram.
    BaseHistogram* histogram;

    // Used for signaling the worker thread to start incrementing.
    sync_completion_t* start;

    // Number of times to call Increment.
    size_t operations = 0;
};

// Increment each bucket by 2* operations * bucket_index.
int IncrementFn(void* args) {
    IncrementArgs* increment_args = static_cast<IncrementArgs*>(args);
    sync_completion_wait(increment_args->start, zx::sec(20).get());

    for (uint32_t bucket = 0; bucket < kBuckets; ++bucket) {
        for (size_t i = 0; i < increment_args->operations; ++i) {
            increment_args->histogram->IncrementCount(bucket, bucket);
        }
        increment_args->histogram->IncrementCount(bucket, bucket * increment_args->operations);
    }

    return thrd_success;
}

// Verifies that calling increment from multiple threads, yields consistent results.
// Multiple threads will call Increment a known number of times, then the total count
// per bucket should be sum of the times each thread called Increment one each bucket.
bool TestIncrementMultiThread() {
    BEGIN_TEST;
    sync_completion_t start;
    BaseHistogram histogram(kBuckets);
    fbl::Vector<thrd_t> thread_ids;
    IncrementArgs args[kThreads];

    thread_ids.reserve(kThreads);
    for (uint64_t i = 0; i < kThreads; ++i) {
        thread_ids.push_back({});
    }

    for (uint64_t i = 0; i < kThreads; ++i) {
        auto& thread_id = thread_ids[i];
        args[i].histogram = &histogram;
        args[i].operations = i;
        args[i].start = &start;
        ASSERT_EQ(thrd_create(&thread_id, IncrementFn, &args[i]), thrd_success);
    }

    // Notify threads to start incrementing the count.
    sync_completion_signal(&start);

    // Wait for all threads to finish.
    for (const auto& thread_id : thread_ids) {
        thrd_join(thread_id, nullptr);
    }

    // Each thread increses each bucket by 2 * bucket_index, so the expected amount for each bucket
    // is: 2 * bucket_index * Sum(i=0, kThreads -1) i = 2 * bucket_index * kThreads* (kThreads - 1)
    // / 2;
    constexpr size_t amount = (kThreads - 1) * (kThreads);
    for (uint32_t i = 0; i < kBuckets; ++i) {
        // We take the sum of the accumulated and what is left, because the last increment may have
        // been scheduled after the last flush.
        EXPECT_EQ(histogram.GetCount(i), i * amount);
    }
    END_TEST;
}

// Verifies that when flushing an histogram, all the flushed data matches that of the
// count in the histogram.
bool TestFlush() {
    BEGIN_TEST;
    RemoteHistogram histogram = MakeRemoteHistogram();
    fidl::VectorView<HistogramBucket> flushed_event_data;
    uint32_t flushed_metric_id;
    RemoteHistogram::FlushCompleteFn complete_fn;
    const fbl::Vector<Metadata>* flushed_metadata;

    // Increase the count of each bucket bucket_index times.
    for (uint32_t bucket_index = 0; bucket_index < kBuckets; ++bucket_index) {
        ASSERT_EQ(histogram.GetCount(bucket_index), 0);
        histogram.IncrementCount(bucket_index, bucket_index);
        ASSERT_EQ(histogram.GetCount(bucket_index), bucket_index);
    }

    ASSERT_TRUE(histogram.Flush(
        [&flushed_event_data, &flushed_metadata, &flushed_metric_id, &complete_fn](
            uint32_t metric_id, const EventBuffer<fidl::VectorView<HistogramBucket>>& buffer,
            RemoteHistogram::FlushCompleteFn comp_fn) {
            flushed_event_data = buffer.event_data();
            flushed_metadata = &buffer.metadata();
            flushed_metric_id = metric_id;
            complete_fn = fbl::move(comp_fn);
        }));

    // Check that flushed data is actually what we expect:
    // The metadata is the same, and each bucket contains bucket_index count.
    ASSERT_EQ(flushed_metric_id, kMetricId);
    for (uint64_t metadata_index = 0; metadata_index < GetMetadata().size(); ++metadata_index) {
        EXPECT_TRUE(MetadataEq(*flushed_metadata, GetMetadata()));
    }

    fbl::Vector<HistogramBucket> buckets;
    buckets.reserve(kBuckets);
    for (size_t i = 0; i < kBuckets; ++i) {
        buckets.push_back({.index = static_cast<uint32_t>(i), .count = i});
    }
    fidl::VectorView<HistogramBucket> expected_buckets;
    expected_buckets.set_data(buckets.get());
    expected_buckets.set_count(buckets.size());

    // Verify there is a bucket event_data.
    EXPECT_TRUE(HistEventValuesEq(flushed_event_data, expected_buckets));

    // Until complete_fn is called this should be false.
    ASSERT_FALSE(histogram.Flush(RemoteHistogram::FlushFn()));

    complete_fn();

    // Verify all buckets are 0.
    for (uint32_t bucket_index = 0; bucket_index < kBuckets; ++bucket_index) {
        ASSERT_EQ(histogram.GetCount(bucket_index), 0);
    }

    // Check that after calling complete_fn we can call flush again.
    ASSERT_TRUE(histogram.Flush([](uint32_t metric_id,
                                   const EventBuffer<fidl::VectorView<HistogramBucket>>& values,
                                   RemoteHistogram::FlushCompleteFn comp_fn) {}));

    END_TEST;
}

struct FlushArgs {
    // Pointer to the histogram which is flushing incremental snapshot to a 'remote' histogram.
    RemoteHistogram* histogram;

    // Pointer to the 'Remote' histogram that is accumulating the data of each flush.
    BaseHistogram* accumulated_histogram;

    // Used to enforce the threads start together. The main thread will signal after
    // all threads have been started.
    sync_completion_t* start;

    // Number of times to perform the given operation.
    size_t operations = 0;

    // Whether the thread will flush, if flase it will be incrementing the buckets.
    bool flush = false;
};

int FlushFn(void* args) {
    FlushArgs* flush_args = static_cast<FlushArgs*>(args);

    sync_completion_wait(flush_args->start, zx::sec(20).get());

    for (size_t i = 0; i < flush_args->operations; ++i) {
        if (flush_args->flush) {
            flush_args->histogram->Flush(
                [&flush_args](uint32_t metric_id,
                              const EventBuffer<fidl::VectorView<HistogramBucket>>& buffer,
                              RemoteHistogram::FlushCompleteFn complete_fn) {
                    uint64_t count = buffer.event_data().count();
                    for (uint32_t i = 0; i < count; ++i) {
                        flush_args->accumulated_histogram->IncrementCount(
                            buffer.event_data()[i].index, buffer.event_data()[i].count);
                    }
                });
        } else {
            for (uint32_t j = 0; j < kBuckets; ++j) {
                flush_args->histogram->IncrementCount(j, j);
            }
        }
    }
    return thrd_success;
}

// Verify that under concurrent environment the final results are consistent. This test
// will have |kThreads|/2 threads increment bucket counts, and |kThreads|/2 Flush them
// a certain amount of times, and collect into a BaseHistogram the final results. At the end,
// each bucket of the BaseHistogram should be the expected value.
bool TestFlushMultithread() {
    BEGIN_TEST;
    sync_completion_t start;
    BaseHistogram accumulated(kBuckets);
    RemoteHistogram histogram = MakeRemoteHistogram();
    fbl::Vector<thrd_t> thread_ids;
    FlushArgs args[kThreads];

    thread_ids.reserve(kThreads);
    for (uint64_t i = 0; i < kThreads; ++i) {
        thread_ids.push_back({});
    }

    for (uint64_t i = 0; i < kThreads; ++i) {
        auto& thread_id = thread_ids[i];
        args[i].histogram = &histogram;
        args[i].accumulated_histogram = &accumulated;
        args[i].operations = i;
        args[i].flush = i % 2;
        args[i].start = &start;
        ASSERT_EQ(thrd_create(&thread_id, FlushFn, &args[i]), thrd_success);
    }

    // Notify threads to start incrementing the count.
    sync_completion_signal(&start);

    // Wait for all threads to finish.
    for (const auto& thread_id : thread_ids) {
        thrd_join(thread_id, nullptr);
    }

    // Each thread at an even position, increases the the count of a bucket by bucket_index.
    constexpr size_t ceil_threads = ((kThreads - 1) / 2 * ((kThreads - 1) / 2 + 1));
    for (uint32_t i = 0; i < kBuckets; ++i) {
        // We take the sum of the accumulated and what is left, because the last increment may have
        // been scheduled after the last flush.
        EXPECT_EQ(accumulated.GetCount(i) + histogram.GetCount(i), i * ceil_threads);
    }
    END_TEST;
}

bool TestAdd() {
    BEGIN_TEST;
    // Buckets 2^i + offset.
    HistogramOptions options = HistogramOptions::Exponential(/*bucket_count=*/kBuckets, /*base=*/2,
                                                             /*scalar=*/1, /*offset=*/-10);
    RemoteHistogram remote_histogram(kBuckets + 2, kMetricId, {});
    ASSERT_TRUE(options.IsValid());
    Histogram histogram(&options, &remote_histogram);

    histogram.Add(25);
    ASSERT_EQ(histogram.GetRemoteCount(25), 1);
    histogram.Add(25, 4);
    histogram.Add(1500, 2);

    ASSERT_EQ(histogram.GetRemoteCount(25), 5);
    ASSERT_EQ(histogram.GetRemoteCount(1500), 2);

    END_TEST;
}

// Verify that from the public point of view, changes are reflected accurately, while internally
// the buckets are accessed correctly.
// Note: The two extra buckets, are for underflow and overflow buckets.
bool TestAddMultiple() {
    BEGIN_TEST;
    // Buckets 2^i + offset.
    HistogramOptions options = HistogramOptions::Exponential(/*bucket_count=*/kBuckets, /*base=*/2,
                                                             /*scalar=*/1, /*offset=*/-10);
    RemoteHistogram remote_histogram(kBuckets + 2, kMetricId, {});
    BaseHistogram expected_hist(kBuckets + 2);
    ASSERT_TRUE(options.IsValid());
    Histogram histogram(&options, &remote_histogram);

    struct ValueBucket {
        double value;
        uint32_t bucket;
    };
    fbl::Vector<ValueBucket> data;
    unsigned int seed = static_cast<unsigned int>(zx::ticks::now().get());

    // 500 random observation.
    for (int i = 0; i < 500; ++i) {
        ValueBucket curr;
        curr.bucket = rand_r(&seed) % (kBuckets + 2);
        double min;
        double max;
        if (curr.bucket == 0) {
            min = -DBL_MAX;
        } else {
            min = options.reverse_map_fn(curr.bucket, options);
        }
        max = nextafter(options.reverse_map_fn(curr.bucket + 1, options), min);
        curr.value = min + (max - min) * (static_cast<double>(rand_r(&seed)) / RAND_MAX);
        ASSERT_EQ(options.map_fn(curr.value, options), curr.bucket);

        Histogram::Count count = 1 + rand_r(&seed) % 20;
        expected_hist.IncrementCount(curr.bucket, count);
        histogram.Add(curr.value, count);
    }

    // Verify that the data stored through public API, matches the expected values.
    for (auto& val_bucket : data) {
        EXPECT_EQ(histogram.GetRemoteCount(val_bucket.value),
                  expected_hist.GetCount(val_bucket.bucket));
    }

    // Sanity-Check that the internal representation also matches the expected values.
    for (uint32_t bucket = 0; bucket < kBuckets + 2; ++bucket) {
        EXPECT_EQ(remote_histogram.GetCount(bucket), remote_histogram.GetCount(bucket));
    }

    END_TEST;
}

// Verify we are always exposing the delta since last FlushFn.
bool TestAddAfterFlush() {
    BEGIN_TEST;
    // Buckets 2^i + offset.
    HistogramOptions options = HistogramOptions::Exponential(/*bucket_count=*/kBuckets, /*base=*/2,
                                                             /*scalar=*/1, /*offset=*/-10);
    RemoteHistogram remote_histogram(kBuckets + 2, kMetricId, {});
    BaseHistogram expected_hist(kBuckets + 2);
    ASSERT_TRUE(options.IsValid());
    Histogram histogram(&options, &remote_histogram);

    histogram.Add(25, 4);
    ASSERT_EQ(histogram.GetRemoteCount(25), 4);
    remote_histogram.Flush([](uint32_t metric_id,
                              const EventBuffer<fidl::VectorView<HistogramBucket>>&,
                              RemoteHistogram::FlushCompleteFn complete) { complete(); });
    histogram.Add(25, 4);
    histogram.Add(1500, 2);

    ASSERT_EQ(histogram.GetRemoteCount(25), 4);
    ASSERT_EQ(histogram.GetRemoteCount(1500), 2);

    END_TEST;
}

struct Observation {
    double value;
    Histogram::Count count;
};

struct HistogramFnArgs {
    // Public histogram which is used to add observations.
    Histogram histogram = Histogram(nullptr, nullptr);

    // When we are flushing we act as the collector, so we need
    // a pointer to the underlying histogram.
    RemoteHistogram* remote_histogram = nullptr;

    // We flush the contents at each step into this histogram.
    BaseHistogram* flushed_histogram = nullptr;

    // Synchronize thread start.
    sync_completion_t* start = nullptr;

    // Observations each thread will add.
    fbl::Vector<Observation>* observed_values = nullptr;

    // The thread will flush contents if set to true.
    bool flush = false;
};

// Wait until all threads are started, then start adding observations or flushing, depending
// on the thread parameters.
int HistogramFn(void* v_args) {
    HistogramFnArgs* args = reinterpret_cast<HistogramFnArgs*>(v_args);
    sync_completion_wait(args->start, zx::sec(20).get());
    for (auto& obs : *args->observed_values) {
        if (!args->flush) {
            args->histogram.Add(obs.value, obs.count);
        } else {
            args->remote_histogram->Flush(
                [args](uint64_t, const EventBuffer<fidl::VectorView<HistogramBucket>>& buffer,
                       RemoteHistogram::FlushCompleteFn complete_fn) {
                    for (auto& hist_bucket : buffer.event_data()) {
                        args->flushed_histogram->IncrementCount(hist_bucket.index,
                                                                hist_bucket.count);
                    }
                });
        }
    }
    return thrd_success;
}

// Verify that when multiple threads call Add the result is eventually consistent,
// meaning that the total count in each bucket should match the count in an histogram
// that is being kept manually(BaseHistogram).
bool TestAddMultiThread() {
    BEGIN_TEST;
    // Buckets 2^i + offset.
    HistogramOptions options = HistogramOptions::Linear(/*bucket_count=*/kBuckets,
                                                        /*scalar=*/2, /*offset=*/0);
    RemoteHistogram remote_histogram(kBuckets + 2, kMetricId, {});
    BaseHistogram expected_hist(kBuckets + 2);
    ASSERT_TRUE(options.IsValid());
    Histogram histogram(&options, &remote_histogram);
    fbl::Vector<Observation> observations;

    // 1500 random observation.
    unsigned int seed = static_cast<unsigned int>(zx::ticks::now().get());
    for (int i = 0; i < 1500; ++i) {
        Observation obs;
        uint32_t bucket = rand_r(&seed) % (kBuckets + 2);
        double min;
        double max;
        if (bucket == 0) {
            min = -DBL_MAX;
        } else {
            min = options.reverse_map_fn(bucket, options);
        }
        max = nextafter(options.reverse_map_fn(bucket + 1, options), min);
        obs.value = min + (max - min) * (static_cast<double>(rand_r(&seed)) / RAND_MAX);
        ASSERT_EQ(options.map_fn(obs.value, options), bucket);
        obs.count = 1 + rand_r(&seed) % 20;
        expected_hist.IncrementCount(bucket, kThreads * obs.count);
        observations.push_back(obs);
    }

    // Thread data.
    HistogramFnArgs args;
    sync_completion_t start;
    fbl::Vector<thrd_t> thread_ids;
    args.histogram = histogram;
    args.start = &start;
    args.observed_values = &observations;

    for (size_t thread = 0; thread < kThreads; ++thread) {
        thread_ids.push_back({});
        auto& thread_id = thread_ids[thread];
        ASSERT_EQ(thrd_create(&thread_id, HistogramFn, &args), thrd_success);
    }
    sync_completion_signal(&start);

    for (auto& thread_id : thread_ids) {
        thrd_join(thread_id, nullptr);
    }

    // Verify each bucket has the exact value as the expected histogram,
    for (uint32_t bucket = 0; bucket < kBuckets + 2; ++bucket) {
        double value;
        value = options.reverse_map_fn(bucket, options);
        EXPECT_EQ(histogram.GetRemoteCount(value), expected_hist.GetCount(bucket));
    }
    END_TEST;
}

// Verify that when multiple threads call Add and Flush consistently, the result
// is eventually consistent, meaning that for each bucket, the amount in expected_hist
// is equal to what remains in the remote histogram plus the amount in the flushed hist.
// Essentially a sanity check that data is not lost.
bool TestAddAndFlushMultiThread() {
    BEGIN_TEST;
    // Buckets 2^i + offset.
    HistogramOptions options = HistogramOptions::Linear(/*bucket_count=*/kBuckets,
                                                        /*scalar=*/2, /*offset=*/0);
    RemoteHistogram remote_histogram(kBuckets + 2, kMetricId, {});
    BaseHistogram expected_hist(kBuckets + 2);
    BaseHistogram flushed_hist(kBuckets + 2);
    ASSERT_TRUE(options.IsValid());
    Histogram histogram(&options, &remote_histogram);
    fbl::Vector<Observation> observations;

    // 1500 random observation.
    unsigned int seed = static_cast<unsigned int>(zx::ticks::now().get());
    for (int i = 0; i < 1500; ++i) {
        Observation obs;
        uint32_t bucket = rand_r(&seed) % (kBuckets + 2);
        double min;
        double max;
        if (bucket == 0) {
            min = -DBL_MAX;
        } else {
            min = options.reverse_map_fn(bucket, options);
        }
        max = nextafter(options.reverse_map_fn(bucket + 1, options), min);
        obs.value = min + (max - min) * (static_cast<double>(rand_r(&seed)) / RAND_MAX);
        ASSERT_EQ(options.map_fn(obs.value, options), bucket);
        obs.count = 1 + rand_r(&seed) % 20;
        expected_hist.IncrementCount(bucket, (kThreads / 2 + kThreads % 2) * obs.count);
        observations.push_back(obs);
    }

    sync_completion_t start;
    HistogramFnArgs add_args;
    fbl::Vector<thrd_t> thread_ids;
    add_args.start = &start;
    add_args.histogram = histogram;
    add_args.observed_values = &observations;

    HistogramFnArgs flush_args = add_args;
    flush_args.flush = true;
    flush_args.flushed_histogram = &flushed_hist;
    flush_args.remote_histogram = &remote_histogram;

    for (size_t thread = 0; thread < kThreads; ++thread) {
        thread_ids.push_back({});
        auto& thread_id = thread_ids[thread];
        if (thread % 2 != 0) {
            ASSERT_EQ(thrd_create(&thread_id, HistogramFn, &add_args), thrd_success);
        } else {
            ASSERT_EQ(thrd_create(&thread_id, HistogramFn, &flush_args), thrd_success);
        }
    }

    sync_completion_signal(&start);

    for (auto& thread_id : thread_ids) {
        thrd_join(thread_id, nullptr);
    }

    // Verify each bucket has the exact value as the expected histogram.
    // The addition here, is just because we have no guarantee that the last flush
    // happened after the last add. Essentially what we have not yet flushed,
    // plus what we flushed, should be equal to the expected value if we didnt flush at all.
    for (uint32_t bucket = 0; bucket < kBuckets + 2; ++bucket) {
        double value;
        value = options.reverse_map_fn(bucket, options);
        EXPECT_EQ(histogram.GetRemoteCount(value) + flushed_hist.GetCount(bucket),
                  expected_hist.GetCount(bucket));
    }
    END_TEST;
}

BEGIN_TEST_CASE(BaseHistogramTest)
RUN_TEST(TestIncrement)
RUN_TEST(TestIncrementByVal)
RUN_TEST(TestIncrementMultiThread)
END_TEST_CASE(BaseHistogramTest)

BEGIN_TEST_CASE(RemoteHistogramTest)
RUN_TEST(TestFlush)
RUN_TEST(TestFlushMultithread)
END_TEST_CASE(RemoteHistogramTest)

BEGIN_TEST_CASE(HistogramTest)
RUN_TEST(TestAdd)
RUN_TEST(TestAddAfterFlush)
RUN_TEST(TestAddMultiple)
RUN_TEST(TestAddMultiThread)
RUN_TEST(TestAddAndFlushMultiThread)
END_TEST_CASE(HistogramTest)

} // namespace
} // namespace internal
} // namespace cobalt_client
