TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / external / android-emugl / shared / emugl / common / thread_store_unittest.cpp
1 // Copyright (C) 2014 The Android Open Source Project
2 //
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 #include "emugl/common/thread_store.h"
16
17 #include "emugl/common/mutex.h"
18 #include "emugl/common/testing/test_thread.h"
19
20 #include <gtest/gtest.h>
21
22 namespace emugl {
23
24 namespace {
25
26 // Helper class used to count instance creation and destruction.
27 class StaticCounter {
28 public:
29     enum {
30         kMaxInstances = 1000,
31     };
32
33     StaticCounter() {
34         Mutex::AutoLock lock(mMutex);
35         if (mCreationCount < kMaxInstances)
36             mInstances[mCreationCount] = this;
37         mCreationCount++;
38     }
39
40     ~StaticCounter() {
41         Mutex::AutoLock lock(mMutex);
42         mDestructionCount++;
43     }
44
45     static void reset() {
46         Mutex::AutoLock lock(mMutex);
47         mCreationCount = 0;
48         mDestructionCount = 0;
49     }
50
51     static size_t getCreationCount() {
52         Mutex::AutoLock lock(mMutex);
53         return mCreationCount;
54     }
55
56     static size_t getDestructionCount() {
57         Mutex::AutoLock lock(mMutex);
58         return mDestructionCount;
59     }
60
61     static void freeAll() {
62         for (size_t n = 0; n < kMaxInstances; ++n)
63             delete mInstances[n];
64     }
65
66 private:
67     static Mutex mMutex;
68     static size_t mCreationCount;
69     static size_t mDestructionCount;
70     static StaticCounter* mInstances[kMaxInstances];
71 };
72
73 Mutex StaticCounter::mMutex;
74 size_t StaticCounter::mCreationCount = 0;
75 size_t StaticCounter::mDestructionCount = 0;
76 StaticCounter* StaticCounter::mInstances[kMaxInstances];
77
78 }  // namespace
79
80 // Just check that we can create a new ThreadStore with an empty
81 // destructor, and use it in the current thread.
82 TEST(ThreadStore, MainThreadWithoutDestructor) {
83     ThreadStore store(NULL);
84     static int x = 42;
85     store.set(&x);
86     EXPECT_EQ(&x, store.get());
87 }
88
89 // The following test checks that exiting a thread correctly deletes
90 // any thread-local value stored in it.
91 static void simplyDestroy(void* value) {
92     delete (StaticCounter*) value;
93 }
94
95 static void* simpleThreadFunc(void* param) {
96     ThreadStore* store = static_cast<ThreadStore*>(param);
97     store->set(new StaticCounter());
98     ThreadStore::OnThreadExit();
99     return NULL;
100 }
101
102 TEST(ThreadStore, ThreadsWithDestructor) {
103     ThreadStore store(simplyDestroy);
104     const size_t kNumThreads = 1000;
105     TestThread* threads[kNumThreads];
106     StaticCounter::reset();
107
108     for (size_t n = 0; n < kNumThreads; ++n) {
109         threads[n] = new TestThread(&simpleThreadFunc, &store);
110     }
111     for (size_t n = 0; n < kNumThreads; ++n) {
112         threads[n]->join();
113     }
114
115     EXPECT_EQ(kNumThreads, StaticCounter::getCreationCount());
116     EXPECT_EQ(kNumThreads, StaticCounter::getDestructionCount());
117
118     for (size_t n = 0; n < kNumThreads; ++n) {
119         delete threads[n];
120     }
121 }
122
123 TEST(ThreadStore, ThreadsWithoutDestructor) {
124     ThreadStore store(NULL);
125     const size_t kNumThreads = 1000;
126     TestThread* threads[kNumThreads];
127     StaticCounter::reset();
128
129     for (size_t n = 0; n < kNumThreads; ++n) {
130         threads[n] = new TestThread(&simpleThreadFunc, &store);
131     }
132     for (size_t n = 0; n < kNumThreads; ++n) {
133         threads[n]->join();
134     }
135
136     EXPECT_EQ(kNumThreads, StaticCounter::getCreationCount());
137     EXPECT_EQ(0U, StaticCounter::getDestructionCount());
138
139     StaticCounter::freeAll();
140
141     for (size_t n = 0; n < kNumThreads; ++n) {
142         delete threads[n];
143     }
144 }
145
146 }  // namespace emugl