1 /*
   2  * Copyright (c) 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 "memory/resourceArea.hpp"
  27 #include "unittest.hpp"
  28 #include "utilities/ostream.hpp"
  29 
  30 static const double epsilon = 0.0001;
  31 
  32 template<typename T>
  33 class WorkerDataArrayTest : public ::testing::Test {
  34  protected:
  35   WorkerDataArrayTest() :
  36     title("Test array"),
  37     array(3, title) {
  38   }
  39 
  40   const char* print_summary() {
  41     stringStream out;
  42     array.print_summary_on(&out);
  43     return out.as_string();
  44   }
  45 
  46   const char* print_details() {
  47     stringStream out;
  48     array.print_details_on(&out);
  49     return out.as_string();
  50   }
  51 
  52   const char* print_expected_summary() {
  53     return prepend_with(title, expected_summary());
  54   }
  55 
  56   const char* print_expected_details() {
  57     return prepend_with("", expected_details());
  58   }
  59 
  60   // returns expected summary for array without uninitialized elements
  61   // used it because string representation of double depends on locale
  62   static const char* format_summary(
  63     T min, double avg, T max, T diff, T sum, size_t workers);
  64 
  65   const char* title;
  66   WorkerDataArray<T> array;
  67 
  68  private:
  69   virtual const char* expected_summary() = 0;
  70   virtual const char* expected_details() = 0;
  71 
  72   static const char* prepend_with(const char* str, const char* orig) {
  73     stringStream out;
  74     out.print("%-25s", str);
  75     out.print("%s", orig);
  76     return out.as_string();
  77   }
  78 
  79   ResourceMark rm;
  80 };
  81 
  82 template<>
  83 const char* WorkerDataArrayTest<size_t>::format_summary(
  84   size_t min, double avg, size_t max, size_t diff, size_t sum, size_t workers) {
  85 
  86   stringStream out;
  87   out.print(" Min: " SIZE_FORMAT
  88             ", Avg: %4.1lf, Max: " SIZE_FORMAT
  89             ", Diff: " SIZE_FORMAT ", Sum: " SIZE_FORMAT
  90             ", Workers: " SIZE_FORMAT "\n",
  91             min, avg, max, diff, sum, workers);
  92   return out.as_string();
  93 }
  94 
  95 template<>
  96 const char* WorkerDataArrayTest<double>::format_summary(
  97   double min, double avg, double max, double diff, double sum, size_t workers) {
  98 
  99   stringStream out;
 100   out.print(" Min: %4.1lf"
 101             ", Avg: %4.1lf, Max: %4.1lf"
 102             ", Diff: %4.1lf, Sum: %4.1lf"
 103             ", Workers: " SIZE_FORMAT "\n",
 104             min, avg, max, diff, sum, workers);
 105   return out.as_string();
 106 }
 107 
 108 class BasicWorkerDataArrayTest : public WorkerDataArrayTest<size_t> {
 109  protected:
 110   BasicWorkerDataArrayTest() {
 111     array.set(0, 5);
 112     array.set(1, 3);
 113     array.set(2, 7);
 114   }
 115 
 116  private:
 117   virtual const char* expected_summary() {
 118     return format_summary(3, 5.0, 7, 4, 15, 3);
 119   }
 120 
 121   virtual const char* expected_details() {
 122     return "  5  3  7\n";
 123   }
 124 };
 125 
 126 TEST_F(BasicWorkerDataArrayTest, sum_test) {
 127   ASSERT_EQ(15u, array.sum());
 128 }
 129 
 130 TEST_F(BasicWorkerDataArrayTest, average_test) {
 131   ASSERT_NEAR(5.0, array.average(), epsilon);
 132 }
 133 
 134 TEST_F(BasicWorkerDataArrayTest, print_summary_on_test) {
 135   ASSERT_STREQ(print_expected_summary(), print_summary());
 136 }
 137 
 138 TEST_F(BasicWorkerDataArrayTest, print_details_on_test) {
 139   ASSERT_STREQ(print_expected_details(), print_details());
 140 }
 141 
 142 class AddWorkerDataArrayTest : public WorkerDataArrayTest<size_t> {
 143  protected:
 144   AddWorkerDataArrayTest() {
 145     array.set(0, 5);
 146     array.set(1, 3);
 147     array.set(2, 7);
 148 
 149     for (uint i = 0; i < 3; i++) {
 150       array.add(i, 1);
 151     }
 152   }
 153 
 154  private:
 155   virtual const char* expected_summary() {
 156     return format_summary(4, 6.0, 8, 4, 18, 3);
 157   }
 158 
 159   virtual const char* expected_details() {
 160     return "  6  4  8\n";
 161   }
 162 };
 163 
 164 TEST_F(AddWorkerDataArrayTest, sum_test) {
 165   ASSERT_EQ(18u, array.sum());
 166 }
 167 
 168 TEST_F(AddWorkerDataArrayTest, average_test) {
 169   ASSERT_NEAR(6.0, array.average(), epsilon);
 170 }
 171 
 172 TEST_F(AddWorkerDataArrayTest, print_summary_on_test) {
 173   ASSERT_STREQ(print_expected_summary(), print_summary());
 174 }
 175 
 176 TEST_F(AddWorkerDataArrayTest, print_details_on_test) {
 177   ASSERT_STREQ(print_expected_details(), print_details());
 178 }
 179 
 180 class UninitializedElementWorkerDataArrayTest : public WorkerDataArrayTest<size_t> {
 181  protected:
 182   UninitializedElementWorkerDataArrayTest() {
 183     array.set(0, 5);
 184     array.set(1, WorkerDataArray<size_t>::uninitialized());
 185     array.set(2, 7);
 186   }
 187 
 188  private:
 189   virtual const char* expected_summary() {
 190     return format_summary(5, 6.0, 7, 2, 12, 2);
 191   }
 192 
 193   virtual const char* expected_details() {
 194     return "  5 -  7\n";
 195   }
 196 };
 197 
 198 TEST_F(UninitializedElementWorkerDataArrayTest, sum_test) {
 199   ASSERT_EQ(12u, array.sum());
 200 }
 201 
 202 TEST_F(UninitializedElementWorkerDataArrayTest, average_test) {
 203   ASSERT_NEAR(6.0, array.average(), epsilon);
 204 }
 205 
 206 TEST_F(UninitializedElementWorkerDataArrayTest, print_summary_on_test) {
 207   ASSERT_STREQ(print_expected_summary(), print_summary());
 208 }
 209 
 210 TEST_F(UninitializedElementWorkerDataArrayTest, print_details_on_test) {
 211   ASSERT_STREQ(print_expected_details(), print_details());
 212 }
 213 
 214 class UninitializedWorkerDataArrayTest : public WorkerDataArrayTest<size_t> {
 215  protected:
 216   UninitializedWorkerDataArrayTest() {
 217     array.set(0, WorkerDataArray<size_t>::uninitialized());
 218     array.set(1, WorkerDataArray<size_t>::uninitialized());
 219     array.set(2, WorkerDataArray<size_t>::uninitialized());
 220   }
 221 
 222  private:
 223   virtual const char* expected_summary() {
 224     return " skipped\n";
 225   }
 226 
 227   virtual const char* expected_details() {
 228     return " - - -\n";
 229   }
 230 };
 231 
 232 TEST_F(UninitializedWorkerDataArrayTest, sum_test) {
 233   ASSERT_EQ(0u, array.sum());
 234 }
 235 
 236 TEST_F(UninitializedWorkerDataArrayTest, average_test) {
 237   ASSERT_NEAR(0.0, array.average(), epsilon);
 238 }
 239 
 240 TEST_F(UninitializedWorkerDataArrayTest, print_summary_on_test) {
 241   ASSERT_STREQ(print_expected_summary(), print_summary());
 242 }
 243 
 244 TEST_F(UninitializedWorkerDataArrayTest, print_details_on_test) {
 245   ASSERT_STREQ(print_expected_details(), print_details());
 246 }
 247 
 248 class UninitializedDoubleElementWorkerDataArrayTest : public WorkerDataArrayTest<double> {
 249  protected:
 250   UninitializedDoubleElementWorkerDataArrayTest() {
 251     array.set(0, 5.1 / MILLIUNITS);
 252     array.set(1, WorkerDataArray<double>::uninitialized());
 253     array.set(2, 7.2 / MILLIUNITS);
 254   }
 255 
 256  private:
 257   virtual const char* expected_summary() {
 258     return format_summary(5.1, 6.1, 7.2, 2.1, 12.3, 2);
 259   }
 260 
 261   virtual const char* expected_details() {
 262     stringStream out;
 263     out.print(" %4.1lf - %4.1lf\n", 5.1, 7.2);
 264     return out.as_string();
 265   }
 266 };
 267 
 268 TEST_F(UninitializedDoubleElementWorkerDataArrayTest, sum_test) {
 269   ASSERT_NEAR(12.3 / MILLIUNITS, array.sum(), epsilon);
 270 }
 271 
 272 TEST_F(UninitializedDoubleElementWorkerDataArrayTest, average_test) {
 273   ASSERT_NEAR(6.15 / MILLIUNITS, array.average(), epsilon);
 274 }
 275 
 276 TEST_F(UninitializedDoubleElementWorkerDataArrayTest, print_summary_on_test) {
 277   ASSERT_STREQ(print_expected_summary(), print_summary());
 278 }
 279 
 280 TEST_F(UninitializedDoubleElementWorkerDataArrayTest, print_details_on_test) {
 281   ASSERT_STREQ(print_expected_details(), print_details());
 282 }