1 /*
  2  * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
  4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  5  *
  6  * This code is free software; you can redistribute it and/or modify it
  7  * under the terms of the GNU General Public License version 2 only, as
  8  * published by the Free Software Foundation.
  9  *
 10  * This code is distributed in the hope that it will be useful, but WITHOUT
 11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  */
 24 
 25 #include "precompiled.hpp"
 26 #include "gc/shenandoah/shenandoahNumberSeq.hpp"
 27 #include "utilities/ostream.hpp"
 28 
 29 #include "utilities/vmassert_uninstall.hpp"
 30 #include <iostream>
 31 #include "utilities/vmassert_reinstall.hpp"
 32 
 33 #include "unittest.hpp"
 34 
 35 class ShenandoahNumberSeqTest: public ::testing::Test {
 36  protected:
 37   const double err = 0.5;
 38 
 39   HdrSeq seq1;
 40   HdrSeq seq2;
 41   HdrSeq seq3;
 42 
 43   void print() {
 44     if (seq1.num() > 0) {
 45       print(seq1, "seq1");
 46     }
 47     if (seq2.num() > 0) {
 48       print(seq2, "seq2");
 49     }
 50     if (seq3.num() > 0) {
 51       print(seq3, "seq3");
 52     }
 53   }
 54 
 55   void print(HdrSeq& seq, const char* msg) {
 56     std::cout << "[";
 57     for (int i = 0; i <= 100; i += 10) {
 58       std::cout << "\t p" << i << ":" << seq.percentile(i);
 59     }
 60     std::cout << "\t] : " << msg << "\n";
 61   }
 62 };
 63 
 64 class BasicShenandoahNumberSeqTest: public ShenandoahNumberSeqTest {
 65  public:
 66   BasicShenandoahNumberSeqTest() {
 67     seq1.add(0);
 68     seq1.add(1);
 69     seq1.add(10);
 70     for (int i = 0; i < 7; i++) {
 71       seq1.add(100);
 72     }
 73     ShenandoahNumberSeqTest::print();
 74   }
 75 };
 76 
 77 class ShenandoahNumberSeqMergeTest: public ShenandoahNumberSeqTest {
 78  public:
 79   ShenandoahNumberSeqMergeTest() {
 80     for (int i = 0; i < 80; i++) {
 81       seq1.add(1);
 82       seq3.add(1);
 83     }
 84 
 85     for (int i = 0; i < 20; i++) {
 86       seq2.add(100);
 87       seq3.add(100);
 88     }
 89     ShenandoahNumberSeqTest::print();
 90   }
 91 };
 92 
 93 TEST_VM_F(BasicShenandoahNumberSeqTest, maximum_test) {
 94   EXPECT_EQ(seq1.maximum(), 100);
 95 }
 96 
 97 TEST_VM_F(BasicShenandoahNumberSeqTest, minimum_test) {
 98   EXPECT_EQ(0, seq1.percentile(0));
 99 }
100 
101 TEST_VM_F(BasicShenandoahNumberSeqTest, percentile_test) {
102   EXPECT_NEAR(0, seq1.percentile(10), err);
103   EXPECT_NEAR(1, seq1.percentile(20), err);
104   EXPECT_NEAR(10, seq1.percentile(30), err);
105   EXPECT_NEAR(100, seq1.percentile(40), err);
106   EXPECT_NEAR(100, seq1.percentile(50), err);
107   EXPECT_NEAR(100, seq1.percentile(75), err);
108   EXPECT_NEAR(100, seq1.percentile(90), err);
109   EXPECT_NEAR(100, seq1.percentile(100), err);
110 }
111 
112 TEST_VM_F(BasicShenandoahNumberSeqTest, clear_test) {
113   HdrSeq test;
114   test.add(1);
115 
116   EXPECT_NE(test.num(), 0);
117   EXPECT_NE(test.sum(), 0);
118   EXPECT_NE(test.maximum(), 0);
119   EXPECT_NE(test.avg(), 0);
120   EXPECT_EQ(test.sd(), 0);
121   EXPECT_NE(test.davg(), 0);
122   EXPECT_EQ(test.dvariance(), 0);
123   for (int i = 0; i <= 100; i += 10) {
124     EXPECT_NE(test.percentile(i), 0);
125   }
126 
127   test.clear();
128 
129   EXPECT_EQ(test.num(), 0);
130   EXPECT_EQ(test.sum(), 0);
131   EXPECT_EQ(test.maximum(), 0);
132   EXPECT_EQ(test.avg(), 0);
133   EXPECT_EQ(test.sd(), 0);
134   EXPECT_EQ(test.davg(), 0);
135   EXPECT_EQ(test.dvariance(), 0);
136   for (int i = 0; i <= 100; i += 10) {
137     EXPECT_EQ(test.percentile(i), 0);
138   }
139 }
140 
141 TEST_VM_F(ShenandoahNumberSeqMergeTest, merge_test) {
142   EXPECT_EQ(seq1.num(), 80);
143   EXPECT_EQ(seq2.num(), 20);
144   EXPECT_EQ(seq3.num(), 100);
145 
146   HdrSeq merged;
147   merged.add(seq1);
148   merged.add(seq2);
149 
150   EXPECT_EQ(merged.num(), seq3.num());
151 
152   EXPECT_EQ(merged.maximum(), seq3.maximum());
153   EXPECT_EQ(merged.percentile(0), seq3.percentile(0));
154   for (int i = 0; i <= 100; i += 10) {
155     EXPECT_NEAR(merged.percentile(i), seq3.percentile(i), err);
156   }
157   EXPECT_NEAR(merged.avg(), seq3.avg(), err);
158   EXPECT_NEAR(merged.sd(),  seq3.sd(),  err);
159 
160   // These are not implemented
161   EXPECT_TRUE(isnan(merged.davg()));
162   EXPECT_TRUE(isnan(merged.dvariance()));
163 }