1 /*
   2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 #include "precompiled.hpp"
  25 #include "gc/g1/workerDataArray.inline.hpp"
  26 #include "utilities/ostream.hpp"
  27 #include "memory/resourceArea.hpp"
  28 #include "unittest.hpp"
  29 
  30 static ::testing::AssertionResult verify_string(const char* expected_string, const char* actual_string) {
  31   const size_t expected_len = strlen(expected_string);
  32   const size_t actual_len = strlen(actual_string);
  33 
  34   if (expected_len != actual_len) {
  35     return ::testing::AssertionFailure() << "Wrong string length " << actual_len << ", expected " << expected_len;
  36   }
  37 
  38   // Can't use strncmp here because floating point values use different decimal points for different locales.
  39   // Allow strings to differ in "." vs. "," only. This should still catch most errors.
  40   for (size_t i = 0; i < expected_len; i++) {
  41     char e = expected_string[i];
  42     char a = actual_string[i];
  43     if (e != a) {
  44       if ((e == '.' || e == ',') && (a == '.' || a == ',')) {
  45         // Most likely just a difference in locale
  46       } else {
  47         return ::testing::AssertionFailure() <<
  48           "Actual string \"" << actual_string <<
  49           "\" is not equal to expected \"" << expected_string << "\"";
  50       }
  51     }
  52   }
  53 
  54   return ::testing::AssertionSuccess();
  55 }
  56 
  57 template<typename T>
  58 static void print_summary_on(const WorkerDataArray<T>& array, stringStream* out) {
  59   array.print_summary_on(out);
  60 }
  61 
  62 template<typename T>
  63 static void print_details_on(const WorkerDataArray<T>& array, stringStream* out) {
  64   array.print_details_on(out);
  65 }
  66 
  67 template<typename T>
  68 static ::testing::AssertionResult verify_method(void (*method)(const WorkerDataArray<T>&, stringStream*),
  69                                                 const char* expected_string,
  70                                                 const WorkerDataArray<T>& array) {
  71   ResourceMark rm;
  72   stringStream out;
  73   method(array, &out);
  74   return verify_string(expected_string, out.as_string());
  75 }
  76 
  77 class WorkerDataArrayTest : public ::testing::Test {
  78  protected:
  79   WorkerDataArrayTest() :
  80     basic_array(3, "Test array"),
  81     add_array(3, "Test array"),
  82     with_uninitialized_array(3, "Test array"),
  83     uninitialized_array(3, "Test array"),
  84     double_with_uninitialized_array(3, "Test array") {
  85 
  86     setup_basic_array(&basic_array);
  87     setup_add_array(&add_array);
  88     setup_with_uninitialized_array(&with_uninitialized_array);
  89     setup_uninitialized_array(&uninitialized_array);
  90     setup_double_with_uninitialized_array(&double_with_uninitialized_array);
  91   }
  92 
  93   static const double epsilon;
  94 
  95   WorkerDataArray<size_t> basic_array;
  96   WorkerDataArray<size_t> add_array;
  97   WorkerDataArray<size_t> with_uninitialized_array;
  98   WorkerDataArray<size_t> uninitialized_array;
  99   WorkerDataArray<double> double_with_uninitialized_array;
 100 
 101  private:
 102   static void setup_basic_array(WorkerDataArray<size_t>* array) {
 103     array->set(0, 5);
 104     array->set(1, 3);
 105     array->set(2, 7);
 106   }
 107 
 108   static void setup_add_array(WorkerDataArray<size_t>* array) {
 109     array->set(0, 5);
 110     array->set(1, 3);
 111     array->set(2, 7);
 112 
 113     for (uint i = 0; i < 3; i++) {
 114       array->add(i, 1);
 115     }
 116   }
 117 
 118   static void setup_with_uninitialized_array(WorkerDataArray<size_t>* array) {
 119     array->set(0, 5);
 120     array->set(1, WorkerDataArray<size_t>::uninitialized());
 121     array->set(2, 7);
 122   }
 123 
 124   static void setup_uninitialized_array(WorkerDataArray<size_t>* array) {
 125     array->set(0, WorkerDataArray<size_t>::uninitialized());
 126     array->set(1, WorkerDataArray<size_t>::uninitialized());
 127     array->set(2, WorkerDataArray<size_t>::uninitialized());
 128   }
 129 
 130   static void setup_double_with_uninitialized_array(WorkerDataArray<double>* array) {
 131     array->set(0, 5.1 / MILLIUNITS);
 132     array->set(1, WorkerDataArray<double>::uninitialized());
 133     array->set(2, 7.2 / MILLIUNITS);
 134   }
 135 };
 136 
 137 const double WorkerDataArrayTest::epsilon = 0.0001;
 138 
 139 TEST_F(WorkerDataArrayTest, sum) {
 140   ASSERT_EQ(15u, basic_array.sum());
 141   ASSERT_EQ(18u, add_array.sum());
 142   ASSERT_EQ(12u, with_uninitialized_array.sum());
 143   ASSERT_EQ(0u, uninitialized_array.sum());
 144   ASSERT_NEAR(12.3 / MILLIUNITS, double_with_uninitialized_array.sum(), epsilon);
 145 }
 146 
 147 TEST_F(WorkerDataArrayTest, average) {
 148   ASSERT_NEAR(5.0, basic_array.average(), epsilon);
 149   ASSERT_NEAR(6.0, add_array.average(), epsilon);
 150   ASSERT_NEAR(6.0, with_uninitialized_array.average(), epsilon);
 151   ASSERT_NEAR(0.0, uninitialized_array.average(), epsilon);
 152   ASSERT_NEAR(6.15 / MILLIUNITS, double_with_uninitialized_array.average(), epsilon);
 153 }
 154 
 155 TEST_F(WorkerDataArrayTest, print_summary_on) {
 156   // use explicit template parameter to workaround old bug of Solaris Studio C++ compiler
 157   ASSERT_TRUE(verify_method<size_t>(print_summary_on,
 158                 "Test array                Min: 3, Avg:  5.0, Max: 7, Diff: 4, Sum: 15, Workers: 3\n", basic_array));
 159   ASSERT_TRUE(verify_method<size_t>(print_summary_on,
 160                 "Test array                Min: 4, Avg:  6.0, Max: 8, Diff: 4, Sum: 18, Workers: 3\n", add_array));
 161   ASSERT_TRUE(verify_method<size_t>(print_summary_on,
 162                 "Test array                Min: 5, Avg:  6.0, Max: 7, Diff: 2, Sum: 12, Workers: 2\n", with_uninitialized_array));
 163   ASSERT_TRUE(verify_method<size_t>(print_summary_on,
 164                 "Test array                skipped\n", uninitialized_array));
 165   ASSERT_TRUE(verify_method<double>(print_summary_on,
 166                 "Test array                Min:  5.1, Avg:  6.1, Max:  7.2, Diff:  2.1, Sum: 12.3, Workers: 2\n", double_with_uninitialized_array));
 167 }
 168 
 169 TEST_F(WorkerDataArrayTest, print_details_on) {
 170   ASSERT_TRUE(verify_method<size_t>(print_details_on, "                           5  3  7\n", basic_array));
 171   ASSERT_TRUE(verify_method<size_t>(print_details_on, "                           6  4  8\n", add_array));
 172   ASSERT_TRUE(verify_method<size_t>(print_details_on, "                           5 -  7\n", with_uninitialized_array));
 173   ASSERT_TRUE(verify_method<size_t>(print_details_on, "                          - - -\n", uninitialized_array));
 174   ASSERT_TRUE(verify_method<double>(print_details_on, "                           5.1 -  7.2\n", double_with_uninitialized_array));
 175 }