• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "gtest/gtest.h"
17 #include "runtime/include/runtime.h"
18 
19 namespace panda::test {
20 
21 class ThreadTest : public testing::Test {
22 public:
23     MTManagedThread *thread;
ThreadTest()24     ThreadTest()
25     {
26         RuntimeOptions options;
27         options.SetShouldLoadBootPandaFiles(false);
28         options.SetShouldInitializeIntrinsics(false);
29         /*
30          * gtest ASSERT_DEATH doesn't work with multiple threads:
31          * "In particular, death tests don't like having multiple threads in the parent process"
32          * turn off gc-thread & compiler-thread here, because we use a lot of ASSERT_DEATH and test can hang.
33          */
34         options.SetCompilerEnableJit(false);
35         options.SetGcType("epsilon");
36         Logger::InitializeStdLogging(Logger::Level::ERROR, 0);
37         Runtime::Create(options);
38         thread = MTManagedThread::GetCurrent();
39     }
40 
~ThreadTest()41     ~ThreadTest() override
42     {
43         Runtime::Destroy();
44     }
45 
AssertNative() const46     void AssertNative() const
47     {
48         ASSERT_TRUE(thread->IsInNativeCode());
49         ASSERT_FALSE(thread->IsManagedCode());
50     }
51 
AssertManaged() const52     void AssertManaged() const
53     {
54         ASSERT_FALSE(thread->IsInNativeCode());
55         ASSERT_TRUE(thread->IsManagedCode());
56     }
57 
BeginToStateAndEnd(MTManagedThread::ThreadState state) const58     void BeginToStateAndEnd(MTManagedThread::ThreadState state) const
59     {
60         if (state == MTManagedThread::ThreadState::NATIVE_CODE) {
61             thread->NativeCodeBegin();
62             AssertNative();
63             thread->NativeCodeEnd();
64         } else if (state == MTManagedThread::ThreadState::MANAGED_CODE) {
65             thread->ManagedCodeBegin();
66             AssertManaged();
67             thread->ManagedCodeEnd();
68         } else {
69             UNREACHABLE();
70         }
71     }
72 };
73 
74 /**
75  * call stack:
76  *
77  * native #0
78  *   managed #1
79  *      native #2
80  *          access #3
81  *   access #4
82  *
83  */
TEST_F(ThreadTest,LegalThreadStatesTest)84 TEST_F(ThreadTest, LegalThreadStatesTest)
85 {
86     AssertNative();
87     thread->ManagedCodeBegin();  // #1
88     AssertManaged();
89     thread->NativeCodeBegin();  // #2
90     AssertNative();
91 
92     thread->NativeCodeEnd();  // #2
93     AssertManaged();
94     thread->ManagedCodeEnd();  // #1
95     AssertNative();
96 }
97 
TEST_F(ThreadTest,BeginForbiddenStatesFromNativeFrame)98 TEST_F(ThreadTest, BeginForbiddenStatesFromNativeFrame)
99 {
100     testing::FLAGS_gtest_death_test_style = "fast";
101 
102     AssertNative();
103 #ifndef NDEBUG
104     ASSERT_DEATH(thread->NativeCodeBegin(), "last frame is: NATIVE_CODE");
105 #endif
106     AssertNative();
107 }
108 
TEST_F(ThreadTest,BeginForbiddenStatesFromManagedFrame)109 TEST_F(ThreadTest, BeginForbiddenStatesFromManagedFrame)
110 {
111     testing::FLAGS_gtest_death_test_style = "fast";
112 
113     AssertNative();
114     thread->ManagedCodeBegin();
115     AssertManaged();
116 #ifndef NDEBUG
117     ASSERT_DEATH(thread->ManagedCodeBegin(), "last frame is: MANAGED_CODE");
118 #endif
119     AssertManaged();
120     thread->ManagedCodeEnd();
121     AssertNative();
122 }
123 
TEST_F(ThreadTest,EndNativeStateByOtherStates)124 TEST_F(ThreadTest, EndNativeStateByOtherStates)
125 {
126     testing::FLAGS_gtest_death_test_style = "fast";
127 
128     AssertNative();
129 
130 #ifndef NDEBUG
131     ASSERT_DEATH(thread->ManagedCodeEnd(), "last frame is: NATIVE_CODE");
132     ASSERT_DEATH(thread->ManagedCodeEnd(), "last frame is: NATIVE_CODE");
133 #endif
134 }
135 
TEST_F(ThreadTest,EndManagedStateByOtherStates)136 TEST_F(ThreadTest, EndManagedStateByOtherStates)
137 {
138     testing::FLAGS_gtest_death_test_style = "fast";
139 
140     AssertNative();
141     thread->ManagedCodeBegin();
142 
143 #ifndef NDEBUG
144     ASSERT_DEATH(thread->NativeCodeEnd(), "last frame is: MANAGED_CODE");
145 #endif
146     thread->ManagedCodeEnd();
147 }
148 
TEST_F(ThreadTest,TestAllConversions)149 TEST_F(ThreadTest, TestAllConversions)
150 {
151     testing::FLAGS_gtest_death_test_style = "fast";
152 
153     // from NATIVE_CODE
154     AssertNative();
155 #ifndef NDEBUG
156     ASSERT_DEATH(BeginToStateAndEnd(MTManagedThread::ThreadState::NATIVE_CODE), "last frame is: NATIVE_CODE");
157 #endif
158     BeginToStateAndEnd(MTManagedThread::ThreadState::MANAGED_CODE);
159 
160     // from MANAGED_CODE
161     thread->ManagedCodeBegin();
162     AssertManaged();
163 
164     BeginToStateAndEnd(MTManagedThread::ThreadState::NATIVE_CODE);
165 #ifndef NDEBUG
166     ASSERT_DEATH(BeginToStateAndEnd(MTManagedThread::ThreadState::MANAGED_CODE), "last frame is: MANAGED_CODE");
167 #endif
168     thread->ManagedCodeEnd();
169     AssertNative();
170 }
171 }  // namespace panda::test
172