static char* test_encode_and_decode_compressed_large()
{
    const int64_t limit = INT64_C(3600) * 1000 * 1000;
    struct hdr_histogram* actual = NULL;
    struct hdr_histogram* expected = NULL;
    uint8_t* buffer = NULL;
    size_t len = 0;
    int rc = 0;
    hdr_init(1, limit, 4, &expected);
    srand(5);

    int i;
    for (i = 0; i < 8070; i++)
    {
        hdr_record_value(expected, rand() % limit);
    }

    rc = hdr_encode_compressed(expected, &buffer, &len);
    mu_assert("Did not encode", validate_return_code(rc));

    rc = hdr_decode_compressed(buffer, len, &actual);
    mu_assert("Did not decode", validate_return_code(rc));

    mu_assert("Loaded histogram is null", actual != NULL);

    mu_assert(
        "Comparison did not match",
        compare_histogram(expected, actual));

    free(expected);
    free(actual);

    return 0;
}
static char* test_encode_and_decode_compressed2()
{
    load_histograms();

    uint8_t* buffer = NULL;
    size_t len = 0;
    int rc = 0;
    struct hdr_histogram* actual = NULL;
    struct hdr_histogram* expected = cor_histogram;

    rc = hdr_encode_compressed(expected, &buffer, &len);
    mu_assert("Did not encode", validate_return_code(rc));

    rc = hdr_decode_compressed(buffer, len, &actual);
    mu_assert("Did not decode", validate_return_code(rc));

    mu_assert("Loaded histogram is null", actual != NULL);

    mu_assert(
            "Comparison did not match",
            compare_histogram(expected, actual));

    free(actual);

    return 0;
}
static char* test_encode_and_decode_base64()
{
    load_histograms();

    uint8_t* buffer = NULL;
    uint8_t* decoded = NULL;
    char* encoded = NULL;
    size_t len = 0;
    int rc = 0;

    rc = hdr_encode_compressed(cor_histogram, &buffer, &len);
    mu_assert("Did not encode", validate_return_code(rc));

    size_t encoded_len = hdr_base64_encoded_len(len);
    size_t decoded_len = hdr_base64_decoded_len(encoded_len);
    encoded = calloc(encoded_len + 1, sizeof(char));
    decoded = calloc(decoded_len, sizeof(uint8_t));

    hdr_base64_encode(buffer, len, encoded, encoded_len);
    hdr_base64_decode(encoded, encoded_len, decoded, decoded_len);

    mu_assert("Should be same", memcmp(buffer, decoded, len) == 0);

    return 0;
}
ERL_NIF_TERM _hh_to_binary(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    hh_ctx_t* ctx = NULL;
    ErlNifBinary target;

    ErlNifResourceType* ctx_type = get_hh_ctx_type(env);
    if (argc != 1 ||
        ctx_type == NULL ||
        !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx))

    {
        return enif_make_badarg(env);
    }

    int size = 0;
    uint8_t* data = NULL;
    int success = hdr_encode_compressed(ctx->data, &data, &size);

    if (!enif_alloc_binary(size, &target))
    {
        return make_error(env, "bad_hdr_binary_alloc");
    }
    target.size = size;
    memcpy(target.data,data,size);
    free(data);

    if (success != 0)
    {
        return make_error(env, "bad_hdr_binary");
    }

    return enif_make_binary(env, &target);
}
int hdr_log_encode(struct hdr_histogram* histogram, char** encoded_histogram)
{
    char *encoded_histogram_tmp = NULL;
    uint8_t* compressed_histogram = NULL;
    size_t compressed_len = 0;
    int rc = 0;
    int result = 0;
    size_t encoded_len;

    rc = hdr_encode_compressed(histogram, &compressed_histogram, &compressed_len);
    if (rc != 0)
    {
        FAIL_AND_CLEANUP(cleanup, result, rc);
    }

    encoded_len = hdr_base64_encoded_len(compressed_len);
    encoded_histogram_tmp = calloc(encoded_len + 1, sizeof(char));

    rc = hdr_base64_encode(
             compressed_histogram, compressed_len, encoded_histogram_tmp, encoded_len);
    if (rc != 0)
    {
        FAIL_AND_CLEANUP(cleanup, result, rc);
    }

    *encoded_histogram = encoded_histogram_tmp;

cleanup:
    free(compressed_histogram);

    return result;
}
static char* test_encode_and_decode_compressed()
{
    load_histograms();

    size_t raw_histogram_size = hdr_get_memory_size(raw_histogram);

    uint8_t* buffer = (uint8_t*) malloc(hdr_get_memory_size(raw_histogram));

    size_t encode_result = hdr_encode_compressed(raw_histogram, buffer, raw_histogram_size);

    mu_assert("Did not encode", encode_result == 0);

    int32_t compressed_length = hdr_get_compressed_length(buffer);

    struct hdr_histogram* loaded_histogram = NULL;
    int decode_result = hdr_decode_compressed(buffer, compressed_length, &loaded_histogram);

    if (decode_result != 0)
    {
        printf("%s\n", hdr_strerror(decode_result));
    }
    mu_assert("Did not decode", decode_result == 0);

    mu_assert("Loaded histogram is null", loaded_histogram != NULL);
    int compare_result = memcmp(raw_histogram, loaded_histogram, raw_histogram_size);

    mu_assert("Comparison did not match", compare_result == 0);

    return 0;
}
int hdr_log_write(
    struct hdr_log_writer* writer,
    FILE* file,
    const struct timespec* start_timestamp,
    const struct timespec* end_timestamp,
    struct hdr_histogram* histogram)
{
    uint8_t* compressed_histogram = NULL;
    size_t compressed_len = 0;
    char* encoded_histogram = NULL;
    int rc = 0;
    int result = 0;
    size_t encoded_len;

    (void)writer;

    rc = hdr_encode_compressed(histogram, &compressed_histogram, &compressed_len);
    if (rc != 0)
    {
        FAIL_AND_CLEANUP(cleanup, result, rc);
    }

    encoded_len = hdr_base64_encoded_len(compressed_len);
    encoded_histogram = calloc(encoded_len + 1, sizeof(char));

    rc = hdr_base64_encode(
             compressed_histogram, compressed_len, encoded_histogram, encoded_len);
    if (rc != 0)
    {
        FAIL_AND_CLEANUP(cleanup, result, rc);
    }

    if (fprintf(
                file, "%d.%d,%d.%d,%"PRIu64".0,%s\n",
                (int) start_timestamp->tv_sec, (int) (start_timestamp->tv_nsec / 1000000),
                (int) end_timestamp->tv_sec, (int) (end_timestamp->tv_nsec / 1000000),
                hdr_max(histogram),
                encoded_histogram) < 0)
    {
        result = EIO;
    }

cleanup:
    free(compressed_histogram);
    free(encoded_histogram);

    return result;
}
static char* test_bounds_check_on_decode()
{
    load_histograms();

    uint8_t* buffer = NULL;
    size_t len = 0;
    int rc = 0;
    struct hdr_histogram* actual = NULL;
    struct hdr_histogram* expected = cor_histogram;

    rc = hdr_encode_compressed(expected, &buffer, &len);
    mu_assert("Did not encode", validate_return_code(rc));

    rc = hdr_decode_compressed(buffer, len - 1, &actual);
    mu_assert("Should have be invalid", compare_int64(EINVAL, rc));
    mu_assert("Should not have built histogram", NULL == actual);

    return 0;
}