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