1 | /* |
2 | * Copyright (c) 2017, 2018, 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 "logging/log.hpp" |
36 | #include "jfr/jfrEvents.hpp" |
37 | #include "jfr/support/jfrThreadId.hpp" |
38 | #include "jfr/support/jfrThreadLocal.hpp" |
39 | #include "jfr/utilities/jfrTime.hpp" |
40 | #include "utilities/globalDefinitions.hpp" |
41 | #include "runtime/os.hpp" |
42 | #include "runtime/thread.inline.hpp" |
43 | #include "runtime/threadSMR.inline.hpp" |
44 | |
45 | #include "unittest.hpp" |
46 | |
47 | namespace { |
48 | |
49 | class MockEventThreadCPULoad : public ::EventThreadCPULoad |
50 | { |
51 | public: |
52 | float user; |
53 | float system; |
54 | |
55 | public: |
56 | MockEventThreadCPULoad(EventStartTime timing=TIMED) : ::EventThreadCPULoad(timing) {} |
57 | |
58 | void set_user(float new_value) { |
59 | user = new_value; |
60 | } |
61 | void set_system(float new_value) { |
62 | system = new_value; |
63 | } |
64 | }; |
65 | |
66 | class MockOs : public ::os { |
67 | public: |
68 | static jlong user_cpu_time; |
69 | static jlong system_cpu_time; |
70 | |
71 | static jlong thread_cpu_time(Thread *thread, bool user_sys_cpu_time) { |
72 | return user_sys_cpu_time ? user_cpu_time + system_cpu_time : user_cpu_time; |
73 | } |
74 | }; |
75 | |
76 | jlong MockOs::user_cpu_time; |
77 | jlong MockOs::system_cpu_time; |
78 | |
79 | class MockJavaThread : public ::JavaThread { |
80 | public: |
81 | MockJavaThread() : ::JavaThread() {} |
82 | }; |
83 | |
84 | class MockJavaThreadIteratorWithHandle |
85 | { |
86 | public: |
87 | MockJavaThread* next() { return NULL; } |
88 | int length() { return 0; } |
89 | }; |
90 | |
91 | // Reincluding source files in the anonymous namespace unfortunately seems to |
92 | // behave strangely with precompiled headers (only when using gcc though) |
93 | #ifndef DONT_USE_PRECOMPILED_HEADER |
94 | #define |
95 | #endif |
96 | |
97 | #define os MockOs |
98 | #define EventThreadCPULoad MockEventThreadCPULoad |
99 | #define JavaThread MockJavaThread |
100 | #define JavaThreadIteratorWithHandle MockJavaThreadIteratorWithHandle |
101 | |
102 | #include "jfr/periodic/jfrThreadCPULoadEvent.hpp" |
103 | #include "jfr/periodic/jfrThreadCPULoadEvent.cpp" |
104 | |
105 | #undef os |
106 | #undef EventThreadCPULoad |
107 | #undef JavaThread |
108 | #undef JavaThreadIteratorWithHandle |
109 | |
110 | } // anonymous namespace |
111 | |
112 | class JfrTestThreadCPULoadSingle : public ::testing::Test { |
113 | protected: |
114 | MockJavaThread* thread; |
115 | JfrThreadLocal* thread_data; |
116 | MockEventThreadCPULoad event; |
117 | |
118 | void SetUp() { |
119 | thread = new MockJavaThread(); |
120 | thread_data = thread->jfr_thread_local(); |
121 | thread_data->set_wallclock_time(0); |
122 | thread_data->set_user_time(0); |
123 | thread_data->set_cpu_time(0); |
124 | } |
125 | |
126 | void TearDown() { |
127 | delete thread; |
128 | } |
129 | |
130 | // Fix for gcc compilation warning about unused functions |
131 | bool TouchUnused() { |
132 | return (&JfrThreadCPULoadEvent::send_events && |
133 | &JfrThreadCPULoadEvent::send_event_for_thread); |
134 | } |
135 | }; |
136 | |
137 | TEST_VM_F(JfrTestThreadCPULoadSingle, SingleCpu) { |
138 | MockOs::user_cpu_time = 100 * NANOSECS_PER_MILLISEC; |
139 | MockOs::system_cpu_time = 100 * NANOSECS_PER_MILLISEC; |
140 | EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, 400 * NANOSECS_PER_MILLISEC, 1)); |
141 | EXPECT_FLOAT_EQ(0.25, event.user); |
142 | EXPECT_FLOAT_EQ(0.25, event.system); |
143 | } |
144 | |
145 | TEST_VM_F(JfrTestThreadCPULoadSingle, MultipleCpus) { |
146 | MockOs::user_cpu_time = 100 * NANOSECS_PER_MILLISEC; |
147 | MockOs::system_cpu_time = 100 * NANOSECS_PER_MILLISEC; |
148 | EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, 400 * NANOSECS_PER_MILLISEC, 2)); |
149 | EXPECT_FLOAT_EQ(0.125, event.user); |
150 | EXPECT_FLOAT_EQ(0.125, event.system); |
151 | } |
152 | |
153 | TEST_VM_F(JfrTestThreadCPULoadSingle, BelowThreshold) { |
154 | MockOs::user_cpu_time = 100; |
155 | MockOs::system_cpu_time = 100; |
156 | EXPECT_FALSE(JfrThreadCPULoadEvent::update_event(event, thread, 400 * NANOSECS_PER_MILLISEC, 2)); |
157 | } |
158 | |
159 | TEST_VM_F(JfrTestThreadCPULoadSingle, UserAboveMaximum) { |
160 | |
161 | // First call will not report above 100% |
162 | MockOs::user_cpu_time = 200 * NANOSECS_PER_MILLISEC; |
163 | MockOs::system_cpu_time = 100 * NANOSECS_PER_MILLISEC; |
164 | EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, 200 * NANOSECS_PER_MILLISEC, 1)); |
165 | EXPECT_FLOAT_EQ(0.5, event.user); |
166 | EXPECT_FLOAT_EQ(0.5, event.system); |
167 | |
168 | // Second call will see an extra 100 millisecs user time from the remainder |
169 | EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (200 + 400) * NANOSECS_PER_MILLISEC, 1)); |
170 | EXPECT_FLOAT_EQ(0.25, event.user); |
171 | EXPECT_FLOAT_EQ(0, event.system); |
172 | } |
173 | |
174 | TEST_VM_F(JfrTestThreadCPULoadSingle, SystemAboveMaximum) { |
175 | |
176 | // First call will not report above 100% |
177 | MockOs::user_cpu_time = 100 * NANOSECS_PER_MILLISEC; |
178 | MockOs::system_cpu_time = 300 * NANOSECS_PER_MILLISEC; |
179 | EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, 200 * NANOSECS_PER_MILLISEC, 1)); |
180 | EXPECT_FLOAT_EQ(0, event.user); |
181 | EXPECT_FLOAT_EQ(1, event.system); |
182 | |
183 | // Second call will see an extra 100 millisecs user and system time from the remainder |
184 | EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (200 + 400) * NANOSECS_PER_MILLISEC, 1)); |
185 | EXPECT_FLOAT_EQ(0.25, event.user); |
186 | EXPECT_FLOAT_EQ(0.25, event.system); |
187 | } |
188 | |
189 | TEST_VM_F(JfrTestThreadCPULoadSingle, SystemTimeDecreasing) { |
190 | |
191 | // As seen in an actual run - caused by different resolution for total and user time |
192 | // Total time User time (Calculated system time) |
193 | // 200 100 100 |
194 | // 210 200 10 |
195 | // 400 300 100 |
196 | |
197 | MockOs::user_cpu_time = 100 * NANOSECS_PER_MILLISEC; |
198 | MockOs::system_cpu_time = 100 * NANOSECS_PER_MILLISEC; |
199 | EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, 400 * NANOSECS_PER_MILLISEC, 1)); |
200 | EXPECT_FLOAT_EQ(0.25, event.user); |
201 | EXPECT_FLOAT_EQ(0.25, event.system); |
202 | |
203 | MockOs::user_cpu_time += 100 * NANOSECS_PER_MILLISEC; |
204 | MockOs::system_cpu_time -= 90 * NANOSECS_PER_MILLISEC; |
205 | EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (400 + 400) * NANOSECS_PER_MILLISEC, 1)); |
206 | EXPECT_FLOAT_EQ(0.25, event.user); |
207 | EXPECT_FLOAT_EQ(0, event.system); |
208 | |
209 | MockOs::user_cpu_time += 100 * NANOSECS_PER_MILLISEC; |
210 | MockOs::system_cpu_time += 90 * NANOSECS_PER_MILLISEC; |
211 | EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (400 + 400 + 400) * NANOSECS_PER_MILLISEC, 1)); |
212 | EXPECT_FLOAT_EQ(0.25, event.user); |
213 | EXPECT_FLOAT_EQ(0, event.system); |
214 | } |
215 | |