1 /*
   2  * Copyright (c) 2017, 2019, 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 
  25 #include "precompiled.hpp"
  26 
  27 // This test performs mocking of certain JVM functionality. This works by
  28 // including the source file under test inside an anonymous namespace (which
  29 // prevents linking conflicts) with the mocked symbols redefined.
  30 
  31 // The include list should mirror the one found in the included source file -
  32 // with the ones that should pick up the mocks removed. Those should be included
  33 // later after the mocks have been defined.
  34 
  35 #include "jvm.h"
  36 #include "classfile/classLoaderStats.hpp"
  37 #include "classfile/javaClasses.hpp"
  38 #include "code/codeCache.hpp"
  39 #include "compiler/compileBroker.hpp"
  40 #include "gc/g1/g1HeapRegionEventSender.hpp"
  41 #include "gc/shared/gcConfiguration.hpp"
  42 #include "gc/shared/gcTrace.hpp"
  43 #include "gc/shared/objectCountEventSender.hpp"
  44 #include "gc/shared/vmGCOperations.hpp"
  45 #include "jfr/periodic/jfrModuleEvent.hpp"
  46 #include "jfr/periodic/jfrOSInterface.hpp"
  47 #include "jfr/periodic/jfrThreadCPULoadEvent.hpp"
  48 #include "jfr/periodic/jfrThreadDumpEvent.hpp"
  49 #include "jfr/recorder/jfrRecorder.hpp"
  50 #include "jfr/utilities/jfrTraceTime.hpp"
  51 #include "logging/log.hpp"
  52 #include "memory/heapInspection.hpp"
  53 #include "memory/resourceArea.hpp"
  54 #include "oops/oop.inline.hpp"
  55 #include "runtime/arguments.hpp"
  56 #include "runtime/globals.hpp"
  57 #include "runtime/os.hpp"
  58 #include "runtime/os_perf.hpp"
  59 #include "runtime/thread.inline.hpp"
  60 #include "runtime/threadSMR.hpp"
  61 #include "runtime/sweeper.hpp"
  62 #include "runtime/vmThread.hpp"
  63 #include "services/classLoadingService.hpp"
  64 #include "services/management.hpp"
  65 #include "services/threadService.hpp"
  66 #include "trace/tracing.hpp"
  67 #include "utilities/exceptions.hpp"
  68 #include "utilities/globalDefinitions.hpp"
  69 
  70 #include "unittest.hpp"
  71 
  72 namespace {
  73 
  74   class MockEventThreadCPULoad : public ::EventThreadCPULoad
  75   {
  76   public:
  77     float user;
  78     float system;
  79 
  80   public:
  81     MockEventThreadCPULoad(EventStartTime timing=TIMED) : ::EventThreadCPULoad(timing) {}
  82 
  83     void set_user(float new_value) {
  84       user = new_value;
  85     }
  86     void set_system(float new_value) {
  87       system = new_value;
  88     }
  89   };
  90 
  91   class MockOs : public ::os {
  92   public:
  93     static jlong user_cpu_time;
  94     static jlong system_cpu_time;
  95 
  96     static jlong thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
  97       return user_sys_cpu_time ? user_cpu_time + system_cpu_time : user_cpu_time;
  98     }
  99   };
 100 
 101   jlong MockOs::user_cpu_time;
 102   jlong MockOs::system_cpu_time;
 103 
 104 // Reincluding source files in the anonymous namespace unfortunately seems to
 105 // behave strangely with precompiled headers (only when using gcc though)
 106 #ifndef DONT_USE_PRECOMPILED_HEADER
 107 #define DONT_USE_PRECOMPILED_HEADER
 108 #endif
 109 
 110 #define os MockOs
 111 #define EventThreadCPULoad MockEventThreadCPULoad
 112 
 113 #include "tracefiles/tracePeriodic.hpp"
 114 #include "jfr/periodic/jfrPeriodic.cpp"
 115 
 116 #undef os
 117 #undef EventThreadCPULoad
 118 
 119 } // anonymous namespace
 120 
 121 class JfrTestThreadCPULoadSingle : public ::testing::Test {
 122 protected:
 123   JavaThread* thread;
 124   JfrThreadData* thread_data;
 125   MockEventThreadCPULoad event;
 126 
 127   void SetUp() {
 128     thread = new JavaThread();
 129     thread_data = thread->trace_data();
 130     thread_data->set_wallclock_time(0);
 131     thread_data->set_user_time(0);
 132     thread_data->set_cpu_time(0);
 133   }
 134 
 135   void TearDown() {
 136     delete thread;
 137   }
 138 };
 139 
 140 TEST_VM_F(JfrTestThreadCPULoadSingle, SingleCpu) {
 141   MockOs::user_cpu_time = 100 * NANOSECS_PER_MILLISEC;
 142   MockOs::system_cpu_time = 100 * NANOSECS_PER_MILLISEC;
 143   EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, 400 * NANOSECS_PER_MILLISEC, 1));
 144   EXPECT_FLOAT_EQ(0.25, event.user);
 145   EXPECT_FLOAT_EQ(0.25, event.system);
 146 }
 147 
 148 TEST_VM_F(JfrTestThreadCPULoadSingle, MultipleCpus) {
 149   MockOs::user_cpu_time = 100 * NANOSECS_PER_MILLISEC;
 150   MockOs::system_cpu_time = 100 * NANOSECS_PER_MILLISEC;
 151   EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, 400 * NANOSECS_PER_MILLISEC, 2));
 152   EXPECT_FLOAT_EQ(0.125, event.user);
 153   EXPECT_FLOAT_EQ(0.125, event.system);
 154 }
 155 
 156 TEST_VM_F(JfrTestThreadCPULoadSingle, BelowThreshold) {
 157   MockOs::user_cpu_time = 100;
 158   MockOs::system_cpu_time = 100;
 159   EXPECT_FALSE(JfrThreadCPULoadEvent::update_event(event, thread, 400 * NANOSECS_PER_MILLISEC, 2));
 160 }
 161 
 162 TEST_VM_F(JfrTestThreadCPULoadSingle, UserAboveMaximum) {
 163 
 164   // First call will not report above 100%
 165   MockOs::user_cpu_time = 200 * NANOSECS_PER_MILLISEC;
 166   MockOs::system_cpu_time = 100 * NANOSECS_PER_MILLISEC;
 167   EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, 200 * NANOSECS_PER_MILLISEC, 1));
 168   EXPECT_FLOAT_EQ(0.5, event.user);
 169   EXPECT_FLOAT_EQ(0.5, event.system);
 170 
 171   // Second call will see an extra 100 millisecs user time from the remainder
 172   EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (200 + 400) * NANOSECS_PER_MILLISEC, 1));
 173   EXPECT_FLOAT_EQ(0.25, event.user);
 174   EXPECT_FLOAT_EQ(0, event.system);
 175 }
 176 
 177 TEST_VM_F(JfrTestThreadCPULoadSingle, SystemAboveMaximum) {
 178 
 179   // First call will not report above 100%
 180   MockOs::user_cpu_time = 100 * NANOSECS_PER_MILLISEC;
 181   MockOs::system_cpu_time = 300 * NANOSECS_PER_MILLISEC;
 182   EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, 200 * NANOSECS_PER_MILLISEC, 1));
 183   EXPECT_FLOAT_EQ(0, event.user);
 184   EXPECT_FLOAT_EQ(1, event.system);
 185 
 186   // Second call will see an extra 100 millisecs user and system time from the remainder
 187   EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (200 + 400) * NANOSECS_PER_MILLISEC, 1));
 188   EXPECT_FLOAT_EQ(0.25, event.user);
 189   EXPECT_FLOAT_EQ(0.25, event.system);
 190 }
 191 
 192 TEST_VM_F(JfrTestThreadCPULoadSingle, SystemTimeDecreasing) {
 193 
 194   // As seen in an actual run - caused by different resolution for total and user time
 195   // Total time    User time    (Calculated system time)
 196   //       200          100         100
 197   //       210          200          10
 198   //       400          300         100
 199 
 200   MockOs::user_cpu_time = 100 * NANOSECS_PER_MILLISEC;
 201   MockOs::system_cpu_time = 100 * NANOSECS_PER_MILLISEC;
 202   EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, 400 * NANOSECS_PER_MILLISEC, 1));
 203   EXPECT_FLOAT_EQ(0.25, event.user);
 204   EXPECT_FLOAT_EQ(0.25, event.system);
 205 
 206   MockOs::user_cpu_time += 100 * NANOSECS_PER_MILLISEC;
 207   MockOs::system_cpu_time -= 90 * NANOSECS_PER_MILLISEC;
 208   EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (400 + 400) * NANOSECS_PER_MILLISEC, 1));
 209   EXPECT_FLOAT_EQ(0.25, event.user);
 210   EXPECT_FLOAT_EQ(0, event.system);
 211 
 212   MockOs::user_cpu_time += 100 * NANOSECS_PER_MILLISEC;
 213   MockOs::system_cpu_time += 90 * NANOSECS_PER_MILLISEC;
 214   EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (400 + 400 + 400) * NANOSECS_PER_MILLISEC, 1));
 215   EXPECT_FLOAT_EQ(0.25, event.user);
 216   EXPECT_FLOAT_EQ(0, event.system);
 217 }