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