blob: c7cc68adf8bdb57fe33ecd153188f626c27bfcf6 [file] [log] [blame]
Sebastien Hertz0462c4c2015-04-01 16:34:17 +02001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "instrumentation.h"
18
19#include "common_runtime_test.h"
20#include "common_throws.h"
21#include "class_linker-inl.h"
22#include "dex_file.h"
23#include "handle_scope-inl.h"
24#include "jvalue.h"
25#include "runtime.h"
26#include "scoped_thread_state_change.h"
27#include "thread_list.h"
28#include "thread-inl.h"
29
30namespace art {
31namespace instrumentation {
32
33class TestInstrumentationListener FINAL : public instrumentation::InstrumentationListener {
34 public:
35 TestInstrumentationListener()
36 : received_method_enter_event(false), received_method_exit_event(false),
37 received_method_unwind_event(false), received_dex_pc_moved_event(false),
38 received_field_read_event(false), received_field_written_event(false),
Nicolas Geoffray5550ca82015-08-21 18:38:30 +010039 received_exception_caught_event(false), received_backward_branch_event(false),
40 received_invoke_virtual_or_interface_event(false) {}
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020041
42 virtual ~TestInstrumentationListener() {}
43
44 void MethodEntered(Thread* thread ATTRIBUTE_UNUSED,
45 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070046 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020047 uint32_t dex_pc ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070048 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020049 received_method_enter_event = true;
50 }
51
52 void MethodExited(Thread* thread ATTRIBUTE_UNUSED,
53 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070054 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020055 uint32_t dex_pc ATTRIBUTE_UNUSED,
56 const JValue& return_value ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070057 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020058 received_method_exit_event = true;
59 }
60
61 void MethodUnwind(Thread* thread ATTRIBUTE_UNUSED,
62 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070063 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020064 uint32_t dex_pc ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070065 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020066 received_method_unwind_event = true;
67 }
68
69 void DexPcMoved(Thread* thread ATTRIBUTE_UNUSED,
70 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070071 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020072 uint32_t new_dex_pc ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070073 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020074 received_dex_pc_moved_event = true;
75 }
76
77 void FieldRead(Thread* thread ATTRIBUTE_UNUSED,
78 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070079 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020080 uint32_t dex_pc ATTRIBUTE_UNUSED,
81 ArtField* field ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070082 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020083 received_field_read_event = true;
84 }
85
86 void FieldWritten(Thread* thread ATTRIBUTE_UNUSED,
87 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070088 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020089 uint32_t dex_pc ATTRIBUTE_UNUSED,
90 ArtField* field ATTRIBUTE_UNUSED,
91 const JValue& field_value ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070092 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020093 received_field_written_event = true;
94 }
95
96 void ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED,
97 mirror::Throwable* exception_object ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070098 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020099 received_exception_caught_event = true;
100 }
101
102 void BackwardBranch(Thread* thread ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700103 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200104 int32_t dex_pc_offset ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -0700105 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200106 received_backward_branch_event = true;
107 }
108
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100109 void InvokeVirtualOrInterface(Thread* thread ATTRIBUTE_UNUSED,
110 mirror::Object* this_object ATTRIBUTE_UNUSED,
111 ArtMethod* caller ATTRIBUTE_UNUSED,
112 uint32_t dex_pc ATTRIBUTE_UNUSED,
113 ArtMethod* callee ATTRIBUTE_UNUSED)
114 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
115 received_invoke_virtual_or_interface_event = true;
116 }
117
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200118 void Reset() {
119 received_method_enter_event = false;
120 received_method_exit_event = false;
121 received_method_unwind_event = false;
122 received_dex_pc_moved_event = false;
123 received_field_read_event = false;
124 received_field_written_event = false;
125 received_exception_caught_event = false;
126 received_backward_branch_event = false;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100127 received_invoke_virtual_or_interface_event = false;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200128 }
129
130 bool received_method_enter_event;
131 bool received_method_exit_event;
132 bool received_method_unwind_event;
133 bool received_dex_pc_moved_event;
134 bool received_field_read_event;
135 bool received_field_written_event;
136 bool received_exception_caught_event;
137 bool received_backward_branch_event;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100138 bool received_invoke_virtual_or_interface_event;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200139
140 private:
141 DISALLOW_COPY_AND_ASSIGN(TestInstrumentationListener);
142};
143
144class InstrumentationTest : public CommonRuntimeTest {
145 public:
146 // Unique keys used to test Instrumentation::ConfigureStubs.
147 static constexpr const char* kClientOneKey = "TestClient1";
148 static constexpr const char* kClientTwoKey = "TestClient2";
149
150 void CheckConfigureStubs(const char* key, Instrumentation::InstrumentationLevel level) {
151 ScopedObjectAccess soa(Thread::Current());
152 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
153 {
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700154 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200155 Runtime* runtime = Runtime::Current();
156 runtime->GetThreadList()->SuspendAll("Instrumentation::ConfigureStubs");
157 instr->ConfigureStubs(key, level);
158 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200159 }
160 }
161
162 Instrumentation::InstrumentationLevel GetCurrentInstrumentationLevel() {
163 return Runtime::Current()->GetInstrumentation()->GetCurrentInstrumentationLevel();
164 }
165
166 size_t GetInstrumentationUserCount() {
167 ScopedObjectAccess soa(Thread::Current());
168 return Runtime::Current()->GetInstrumentation()->requested_instrumentation_levels_.size();
169 }
170
171 void TestEvent(uint32_t instrumentation_event) {
172 ScopedObjectAccess soa(Thread::Current());
173 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
174 TestInstrumentationListener listener;
175 {
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700176 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200177 Runtime* runtime = Runtime::Current();
178 runtime->GetThreadList()->SuspendAll("Add instrumentation listener");
179 instr->AddListener(&listener, instrumentation_event);
180 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200181 }
182
Mathieu Chartiere401d142015-04-22 13:56:20 -0700183 ArtMethod* const event_method = nullptr;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200184 mirror::Object* const event_obj = nullptr;
185 const uint32_t event_dex_pc = 0;
186
187 // Check the listener is registered and is notified of the event.
188 EXPECT_TRUE(HasEventListener(instr, instrumentation_event));
189 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
190 ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
191 EXPECT_TRUE(DidListenerReceiveEvent(listener, instrumentation_event));
192
193 listener.Reset();
194 {
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700195 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200196 Runtime* runtime = Runtime::Current();
197 runtime->GetThreadList()->SuspendAll("Remove instrumentation listener");
198 instr->RemoveListener(&listener, instrumentation_event);
199 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200200 }
201
202 // Check the listener is not registered and is not notified of the event.
203 EXPECT_FALSE(HasEventListener(instr, instrumentation_event));
204 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
205 ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
206 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
207 }
208
Mathieu Chartiere401d142015-04-22 13:56:20 -0700209 void DeoptimizeMethod(Thread* self, ArtMethod* method, bool enable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700210 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200211 Runtime* runtime = Runtime::Current();
212 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700213 ScopedThreadSuspension sts(self, kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200214 runtime->GetThreadList()->SuspendAll("Single method deoptimization");
215 if (enable_deoptimization) {
216 instrumentation->EnableDeoptimization();
217 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700218 instrumentation->Deoptimize(method);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200219 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200220 }
221
Mathieu Chartiere401d142015-04-22 13:56:20 -0700222 void UndeoptimizeMethod(Thread* self, ArtMethod* method,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200223 const char* key, bool disable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700224 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200225 Runtime* runtime = Runtime::Current();
226 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700227 ScopedThreadSuspension sts(self, kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200228 runtime->GetThreadList()->SuspendAll("Single method undeoptimization");
Mathieu Chartiere401d142015-04-22 13:56:20 -0700229 instrumentation->Undeoptimize(method);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200230 if (disable_deoptimization) {
231 instrumentation->DisableDeoptimization(key);
232 }
233 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200234 }
235
236 void DeoptimizeEverything(Thread* self, const char* key, bool enable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700237 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200238 Runtime* runtime = Runtime::Current();
239 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700240 ScopedThreadSuspension sts(self, kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200241 runtime->GetThreadList()->SuspendAll("Full deoptimization");
242 if (enable_deoptimization) {
243 instrumentation->EnableDeoptimization();
244 }
245 instrumentation->DeoptimizeEverything(key);
246 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200247 }
248
249 void UndeoptimizeEverything(Thread* self, const char* key, bool disable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700250 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200251 Runtime* runtime = Runtime::Current();
252 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700253 ScopedThreadSuspension sts(self, kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200254 runtime->GetThreadList()->SuspendAll("Full undeoptimization");
255 instrumentation->UndeoptimizeEverything(key);
256 if (disable_deoptimization) {
257 instrumentation->DisableDeoptimization(key);
258 }
259 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200260 }
261
262 void EnableMethodTracing(Thread* self, const char* key, bool needs_interpreter)
Mathieu Chartier90443472015-07-16 20:32:27 -0700263 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200264 Runtime* runtime = Runtime::Current();
265 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700266 ScopedThreadSuspension sts(self, kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200267 runtime->GetThreadList()->SuspendAll("EnableMethodTracing");
268 instrumentation->EnableMethodTracing(key, needs_interpreter);
269 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200270 }
271
272 void DisableMethodTracing(Thread* self, const char* key)
Mathieu Chartier90443472015-07-16 20:32:27 -0700273 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200274 Runtime* runtime = Runtime::Current();
275 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700276 ScopedThreadSuspension sts(self, kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200277 runtime->GetThreadList()->SuspendAll("EnableMethodTracing");
278 instrumentation->DisableMethodTracing(key);
279 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200280 }
281
282 private:
283 static bool HasEventListener(const instrumentation::Instrumentation* instr, uint32_t event_type)
Mathieu Chartier90443472015-07-16 20:32:27 -0700284 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200285 switch (event_type) {
286 case instrumentation::Instrumentation::kMethodEntered:
287 return instr->HasMethodEntryListeners();
288 case instrumentation::Instrumentation::kMethodExited:
289 return instr->HasMethodExitListeners();
290 case instrumentation::Instrumentation::kMethodUnwind:
291 return instr->HasMethodUnwindListeners();
292 case instrumentation::Instrumentation::kDexPcMoved:
293 return instr->HasDexPcListeners();
294 case instrumentation::Instrumentation::kFieldRead:
295 return instr->HasFieldReadListeners();
296 case instrumentation::Instrumentation::kFieldWritten:
297 return instr->HasFieldWriteListeners();
298 case instrumentation::Instrumentation::kExceptionCaught:
299 return instr->HasExceptionCaughtListeners();
300 case instrumentation::Instrumentation::kBackwardBranch:
301 return instr->HasBackwardBranchListeners();
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100302 case instrumentation::Instrumentation::kInvokeVirtualOrInterface:
303 return instr->HasInvokeVirtualOrInterfaceListeners();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200304 default:
305 LOG(FATAL) << "Unknown instrumentation event " << event_type;
306 UNREACHABLE();
307 }
308 }
309
310 static void ReportEvent(const instrumentation::Instrumentation* instr, uint32_t event_type,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700311 Thread* self, ArtMethod* method, mirror::Object* obj,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200312 uint32_t dex_pc)
Mathieu Chartier90443472015-07-16 20:32:27 -0700313 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200314 switch (event_type) {
315 case instrumentation::Instrumentation::kMethodEntered:
316 instr->MethodEnterEvent(self, obj, method, dex_pc);
317 break;
318 case instrumentation::Instrumentation::kMethodExited: {
319 JValue value;
320 instr->MethodExitEvent(self, obj, method, dex_pc, value);
321 break;
322 }
323 case instrumentation::Instrumentation::kMethodUnwind:
324 instr->MethodUnwindEvent(self, obj, method, dex_pc);
325 break;
326 case instrumentation::Instrumentation::kDexPcMoved:
327 instr->DexPcMovedEvent(self, obj, method, dex_pc);
328 break;
329 case instrumentation::Instrumentation::kFieldRead:
330 instr->FieldReadEvent(self, obj, method, dex_pc, nullptr);
331 break;
332 case instrumentation::Instrumentation::kFieldWritten: {
333 JValue value;
334 instr->FieldWriteEvent(self, obj, method, dex_pc, nullptr, value);
335 break;
336 }
337 case instrumentation::Instrumentation::kExceptionCaught: {
338 ThrowArithmeticExceptionDivideByZero();
339 mirror::Throwable* event_exception = self->GetException();
340 instr->ExceptionCaughtEvent(self, event_exception);
341 self->ClearException();
342 break;
343 }
344 case instrumentation::Instrumentation::kBackwardBranch:
345 instr->BackwardBranch(self, method, dex_pc);
346 break;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100347 case instrumentation::Instrumentation::kInvokeVirtualOrInterface:
348 instr->InvokeVirtualOrInterface(self, obj, method, dex_pc, method);
349 break;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200350 default:
351 LOG(FATAL) << "Unknown instrumentation event " << event_type;
352 UNREACHABLE();
353 }
354 }
355
356 static bool DidListenerReceiveEvent(const TestInstrumentationListener& listener,
357 uint32_t event_type) {
358 switch (event_type) {
359 case instrumentation::Instrumentation::kMethodEntered:
360 return listener.received_method_enter_event;
361 case instrumentation::Instrumentation::kMethodExited:
362 return listener.received_method_exit_event;
363 case instrumentation::Instrumentation::kMethodUnwind:
364 return listener.received_method_unwind_event;
365 case instrumentation::Instrumentation::kDexPcMoved:
366 return listener.received_dex_pc_moved_event;
367 case instrumentation::Instrumentation::kFieldRead:
368 return listener.received_field_read_event;
369 case instrumentation::Instrumentation::kFieldWritten:
370 return listener.received_field_written_event;
371 case instrumentation::Instrumentation::kExceptionCaught:
372 return listener.received_exception_caught_event;
373 case instrumentation::Instrumentation::kBackwardBranch:
374 return listener.received_backward_branch_event;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100375 case instrumentation::Instrumentation::kInvokeVirtualOrInterface:
376 return listener.received_invoke_virtual_or_interface_event;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200377 default:
378 LOG(FATAL) << "Unknown instrumentation event " << event_type;
379 UNREACHABLE();
380 }
381 }
382};
383
384TEST_F(InstrumentationTest, NoInstrumentation) {
385 ScopedObjectAccess soa(Thread::Current());
386 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
387 ASSERT_NE(instr, nullptr);
388
389 EXPECT_FALSE(instr->AreExitStubsInstalled());
390 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
391 EXPECT_FALSE(instr->IsActive());
392 EXPECT_FALSE(instr->ShouldNotifyMethodEnterExitEvents());
393
394 // Test interpreter table is the default one.
395 EXPECT_EQ(instrumentation::kMainHandlerTable, instr->GetInterpreterHandlerTable());
396
397 // Check there is no registered listener.
398 EXPECT_FALSE(instr->HasDexPcListeners());
399 EXPECT_FALSE(instr->HasExceptionCaughtListeners());
400 EXPECT_FALSE(instr->HasFieldReadListeners());
401 EXPECT_FALSE(instr->HasFieldWriteListeners());
402 EXPECT_FALSE(instr->HasMethodEntryListeners());
403 EXPECT_FALSE(instr->HasMethodExitListeners());
404 EXPECT_FALSE(instr->IsActive());
405}
406
407// Test instrumentation listeners for each event.
408TEST_F(InstrumentationTest, MethodEntryEvent) {
409 TestEvent(instrumentation::Instrumentation::kMethodEntered);
410}
411
412TEST_F(InstrumentationTest, MethodExitEvent) {
413 TestEvent(instrumentation::Instrumentation::kMethodExited);
414}
415
416TEST_F(InstrumentationTest, MethodUnwindEvent) {
417 TestEvent(instrumentation::Instrumentation::kMethodUnwind);
418}
419
420TEST_F(InstrumentationTest, DexPcMovedEvent) {
421 TestEvent(instrumentation::Instrumentation::kDexPcMoved);
422}
423
424TEST_F(InstrumentationTest, FieldReadEvent) {
425 TestEvent(instrumentation::Instrumentation::kFieldRead);
426}
427
428TEST_F(InstrumentationTest, FieldWriteEvent) {
429 TestEvent(instrumentation::Instrumentation::kFieldWritten);
430}
431
432TEST_F(InstrumentationTest, ExceptionCaughtEvent) {
433 TestEvent(instrumentation::Instrumentation::kExceptionCaught);
434}
435
436TEST_F(InstrumentationTest, BackwardBranchEvent) {
437 TestEvent(instrumentation::Instrumentation::kBackwardBranch);
438}
439
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100440TEST_F(InstrumentationTest, InvokeVirtualOrInterfaceEvent) {
441 TestEvent(instrumentation::Instrumentation::kInvokeVirtualOrInterface);
442}
443
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200444TEST_F(InstrumentationTest, DeoptimizeDirectMethod) {
445 ScopedObjectAccess soa(Thread::Current());
446 jobject class_loader = LoadDex("Instrumentation");
447 Runtime* const runtime = Runtime::Current();
448 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
449 ClassLinker* class_linker = runtime->GetClassLinker();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700450 StackHandleScope<1> hs(soa.Self());
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200451 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
452 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
453 ASSERT_TRUE(klass != nullptr);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700454 ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
455 sizeof(void*));
456 ASSERT_TRUE(method_to_deoptimize != nullptr);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200457
458 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700459 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200460
461 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
462
463 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
464 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700465 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200466
467 constexpr const char* instrumentation_key = "DeoptimizeDirectMethod";
468 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
469
470 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700471 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200472}
473
474TEST_F(InstrumentationTest, FullDeoptimization) {
475 ScopedObjectAccess soa(Thread::Current());
476 Runtime* const runtime = Runtime::Current();
477 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
478 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
479
480 constexpr const char* instrumentation_key = "FullDeoptimization";
481 DeoptimizeEverything(soa.Self(), instrumentation_key, true);
482
483 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
484 EXPECT_TRUE(instr->AreExitStubsInstalled());
485
486 UndeoptimizeEverything(soa.Self(), instrumentation_key, true);
487
488 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
489}
490
491TEST_F(InstrumentationTest, MixedDeoptimization) {
492 ScopedObjectAccess soa(Thread::Current());
493 jobject class_loader = LoadDex("Instrumentation");
494 Runtime* const runtime = Runtime::Current();
495 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
496 ClassLinker* class_linker = runtime->GetClassLinker();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700497 StackHandleScope<1> hs(soa.Self());
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200498 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
499 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
500 ASSERT_TRUE(klass != nullptr);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700501 ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
502 sizeof(void*));
503 ASSERT_TRUE(method_to_deoptimize != nullptr);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200504
505 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700506 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200507
508 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
509 // Deoptimizing a method does not change instrumentation level.
510 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
511 GetCurrentInstrumentationLevel());
512 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
513 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700514 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200515
516 constexpr const char* instrumentation_key = "MixedDeoptimization";
517 DeoptimizeEverything(soa.Self(), instrumentation_key, false);
518 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
519 GetCurrentInstrumentationLevel());
520 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
521 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700522 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200523
524 UndeoptimizeEverything(soa.Self(), instrumentation_key, false);
525 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
526 GetCurrentInstrumentationLevel());
527 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
528 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700529 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200530
531 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
532 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
533 GetCurrentInstrumentationLevel());
534 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700535 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200536}
537
538TEST_F(InstrumentationTest, MethodTracing_Interpreter) {
539 ScopedObjectAccess soa(Thread::Current());
540 Runtime* const runtime = Runtime::Current();
541 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
542 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
543
544 constexpr const char* instrumentation_key = "MethodTracing";
545 EnableMethodTracing(soa.Self(), instrumentation_key, true);
546 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
547 GetCurrentInstrumentationLevel());
548 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
549 EXPECT_TRUE(instr->AreExitStubsInstalled());
550
551 DisableMethodTracing(soa.Self(), instrumentation_key);
552 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
553 GetCurrentInstrumentationLevel());
554 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
555}
556
557TEST_F(InstrumentationTest, MethodTracing_InstrumentationEntryExitStubs) {
558 ScopedObjectAccess soa(Thread::Current());
559 Runtime* const runtime = Runtime::Current();
560 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
561 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
562
563 constexpr const char* instrumentation_key = "MethodTracing";
564 EnableMethodTracing(soa.Self(), instrumentation_key, false);
565 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
566 GetCurrentInstrumentationLevel());
567 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
568 EXPECT_TRUE(instr->AreExitStubsInstalled());
569
570 DisableMethodTracing(soa.Self(), instrumentation_key);
571 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
572 GetCurrentInstrumentationLevel());
573 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
574}
575
576// We use a macro to print the line number where the test is failing.
577#define CHECK_INSTRUMENTATION(_level, _user_count) \
578 do { \
579 Instrumentation* const instr = Runtime::Current()->GetInstrumentation(); \
580 bool interpreter = \
581 (_level == Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); \
582 EXPECT_EQ(_level, GetCurrentInstrumentationLevel()); \
583 EXPECT_EQ(_user_count, GetInstrumentationUserCount()); \
584 if (instr->IsForcedInterpretOnly()) { \
585 EXPECT_TRUE(instr->InterpretOnly()); \
586 } else if (interpreter) { \
587 EXPECT_TRUE(instr->InterpretOnly()); \
588 } else { \
589 EXPECT_FALSE(instr->InterpretOnly()); \
590 } \
591 if (interpreter) { \
592 EXPECT_TRUE(instr->AreAllMethodsDeoptimized()); \
593 } else { \
594 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); \
595 } \
596 } while (false)
597
598TEST_F(InstrumentationTest, ConfigureStubs_Nothing) {
599 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
600
601 // Check no-op.
602 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
603 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
604}
605
606TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubs) {
607 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
608
609 // Check we can switch to instrumentation stubs
610 CheckConfigureStubs(kClientOneKey,
611 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
612 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
613 1U);
614
615 // Check we can disable instrumentation.
616 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
617 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
618}
619
620TEST_F(InstrumentationTest, ConfigureStubs_Interpreter) {
621 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
622
623 // Check we can switch to interpreter
624 CheckConfigureStubs(kClientOneKey,
625 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
626 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
627
628 // Check we can disable instrumentation.
629 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
630 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
631}
632
633TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubsToInterpreter) {
634 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
635
636 // Configure stubs with instrumentation stubs.
637 CheckConfigureStubs(kClientOneKey,
638 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
639 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
640 1U);
641
642 // Configure stubs with interpreter.
643 CheckConfigureStubs(kClientOneKey,
644 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
645 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
646
647 // Check we can disable instrumentation.
648 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
649 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
650}
651
652TEST_F(InstrumentationTest, ConfigureStubs_InterpreterToInstrumentationStubs) {
653 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
654
655 // Configure stubs with interpreter.
656 CheckConfigureStubs(kClientOneKey,
657 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
658 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
659
660 // Configure stubs with instrumentation stubs.
661 CheckConfigureStubs(kClientOneKey,
662 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
663 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
664 1U);
665
666 // Check we can disable instrumentation.
667 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
668 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
669}
670
671TEST_F(InstrumentationTest,
672 ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs) {
673 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
674
675 // Configure stubs with instrumentation stubs.
676 CheckConfigureStubs(kClientOneKey,
677 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
678 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
679 1U);
680
681 // Configure stubs with interpreter.
682 CheckConfigureStubs(kClientOneKey,
683 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
684 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
685
686 // Configure stubs with instrumentation stubs again.
687 CheckConfigureStubs(kClientOneKey,
688 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
689 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
690 1U);
691
692 // Check we can disable instrumentation.
693 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
694 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
695}
696
697TEST_F(InstrumentationTest, MultiConfigureStubs_Nothing) {
698 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
699
700 // Check kInstrumentNothing with two clients.
701 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
702 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
703
704 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
705 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
706}
707
708TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubs) {
709 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
710
711 // Configure stubs with instrumentation stubs for 1st client.
712 CheckConfigureStubs(kClientOneKey,
713 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
714 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
715 1U);
716
717 // Configure stubs with instrumentation stubs for 2nd client.
718 CheckConfigureStubs(kClientTwoKey,
719 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
720 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
721 2U);
722
723 // 1st client requests instrumentation deactivation but 2nd client still needs
724 // instrumentation stubs.
725 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
726 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
727 1U);
728
729 // 2nd client requests instrumentation deactivation
730 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
731 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
732}
733
734TEST_F(InstrumentationTest, MultiConfigureStubs_Interpreter) {
735 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
736
737 // Configure stubs with interpreter for 1st client.
738 CheckConfigureStubs(kClientOneKey,
739 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
740 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
741
742 // Configure stubs with interpreter for 2nd client.
743 CheckConfigureStubs(kClientTwoKey,
744 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
745 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
746
747 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
748 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
749 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
750
751 // 2nd client requests instrumentation deactivation
752 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
753 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
754}
755
756TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubsThenInterpreter) {
757 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
758
759 // Configure stubs with instrumentation stubs for 1st client.
760 CheckConfigureStubs(kClientOneKey,
761 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
762 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
763 1U);
764
765 // Configure stubs with interpreter for 2nd client.
766 CheckConfigureStubs(kClientTwoKey,
767 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
768 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
769
770 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
771 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
772 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
773
774 // 2nd client requests instrumentation deactivation
775 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
776 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
777}
778
779TEST_F(InstrumentationTest, MultiConfigureStubs_InterpreterThenInstrumentationStubs) {
780 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
781
782 // Configure stubs with interpreter for 1st client.
783 CheckConfigureStubs(kClientOneKey,
784 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
785 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
786
787 // Configure stubs with instrumentation stubs for 2nd client.
788 CheckConfigureStubs(kClientTwoKey,
789 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
790 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
791
792 // 1st client requests instrumentation deactivation but 2nd client still needs
793 // instrumentation stubs.
794 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
795 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
796 1U);
797
798 // 2nd client requests instrumentation deactivation
799 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
800 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
801}
802
803} // namespace instrumentation
804} // namespace art