text: /**
   * hdr_histogram_test.c
   * Written by Michael Barker and released to the public domain,
   * as explained at http://creativecommons.org/publicdomain/zero/1.0/
   */
  
  #include <stdint.h>
  #include <stdbool.h>
  #include <stdlib.h>
  #include <errno.h>
  
  #include <stdio.h>
  #include <hdr_histogram.h>
  #include <pthread.h>
  
  #include "minunit.h"
  #include "hdr_test_util.h"
  
  int tests_run = 0;
  
  struct test_histogram_data
  {
      struct hdr_histogram* histogram;
      int64_t* values;
      int values_len;
  };
  
  static void* record_values(void* thread_context)
  {
      int i;
      struct test_histogram_data* thread_data = (struct test_histogram_data*) thread_context;
  
  
      for (i = 0; i < thread_data->values_len; i++)
      {
          hdr_record_value_atomic(thread_data->histogram, thread_data->values[i]);
      }
  
      pthread_exit(NULL);
  }
  
  
  static char* test_recording_concurrently()
  {
      const int value_count = 10000000;
      int64_t* values = calloc(value_count, sizeof(int64_t));
      struct hdr_histogram* expected_histogram;
      struct hdr_histogram* actual_histogram;
      struct test_histogram_data thread_data[2];
      struct hdr_iter expected_iter;
      struct hdr_iter actual_iter;
      pthread_t threads[2];
      int i;
  
      mu_assert("init", 0 == hdr_init(1, 10000000, 2, &expected_histogram));
      mu_assert("init", 0 == hdr_init(1, 10000000, 2, &actual_histogram));
  
  
      for (i = 0; i < value_count; i++)
      {
          values[i] = rand() % 20000;
      }
      
      for (i = 0; i < value_count; i++)
      {
          hdr_record_value(expected_histogram, values[i]);
      }
  
      thread_data[0].histogram = actual_histogram;
      thread_data[0].values = values;
      thread_data[0].values_len = value_count / 2;
      pthread_create(&threads[0], NULL, record_values, &thread_data[0]);
  
      thread_data[1].histogram = actual_histogram;
      thread_data[1].values = &values[value_count / 2];
      thread_data[1].values_len = value_count / 2;
      pthread_create(&threads[1], NULL, record_values, &thread_data[1]);
  
      pthread_join(threads[0], NULL);
      pthread_join(threads[1], NULL);
  
      hdr_iter_init(&expected_iter, expected_histogram);
      hdr_iter_init(&actual_iter, actual_histogram);
  
      return compare_histograms(expected_histogram, actual_histogram);
  }
  
  static struct mu_result all_tests()
  {
      mu_run_test(test_recording_concurrently);
  
      mu_ok;
  }
  
  static int hdr_histogram_run_tests()
  {
      struct mu_result result = all_tests();
  
      if (result.message != 0)
      {
          printf("hdr_histogram_test.%s(): %s\n", result.test, result.message);
      }
      else
      {
          printf("ALL TESTS PASSED\n");
      }
  
      printf("Tests run: %d\n", tests_run);
  
      return result.message == NULL ? 0 : -1;
  }
  
  int main()
  {
      return hdr_histogram_run_tests();
  }
  