1/*
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 <gtest/gtest.h>
18#include <pthread.h>
19#include <unistd.h>
20
21#include <utility>
22
23#include "Action.h"
24#include "Pointers.h"
25#include "Thread.h"
26
27typedef std::pair<Thread*, volatile bool*> thread_data_t;
28
29TEST(ThreadTest, ready) {
30  Thread thread;
31
32  // A thread should be ready immediately. If not, this will hang forever.
33  thread.WaitForReady();
34}
35
36void* ThreadWaitForReady(void* data) {
37  thread_data_t* thread_data = reinterpret_cast<thread_data_t*>(data);
38  Thread* thread = thread_data->first;
39  volatile bool* finish = thread_data->second;
40
41  thread->WaitForReady();
42  *finish = true;
43
44  return nullptr;
45}
46
47TEST(ThreadTest, ready_thread) {
48  Thread thread;
49  volatile bool finish = false;
50  thread_data_t thread_data = std::make_pair(&thread, &finish);
51
52  thread.SetPending();
53
54  pthread_t thread_id;
55  ASSERT_TRUE(pthread_create(&thread_id, nullptr, ThreadWaitForReady, &thread_data) == 0);
56
57  ASSERT_FALSE(finish);
58  sleep(1);
59  ASSERT_FALSE(finish);
60
61  thread.ClearPending();
62  ASSERT_TRUE(pthread_join(thread_id, nullptr) == 0);
63  ASSERT_TRUE(finish);
64}
65
66void* ThreadWaitForPending(void* data) {
67  thread_data_t* thread_data = reinterpret_cast<thread_data_t*>(data);
68  Thread* thread = thread_data->first;
69  volatile bool* finish = thread_data->second;
70
71  thread->WaitForPending();
72  *finish = true;
73
74  return nullptr;
75}
76
77TEST(ThreadTest, pending) {
78  Thread thread;
79  volatile bool finish = false;
80  thread_data_t thread_data = std::make_pair(&thread, &finish);
81
82  pthread_t thread_id;
83  ASSERT_TRUE(pthread_create(&thread_id, nullptr, ThreadWaitForPending, &thread_data) == 0);
84
85  ASSERT_FALSE(finish);
86  sleep(1);
87  ASSERT_FALSE(finish);
88
89  thread.SetPending();
90  ASSERT_TRUE(pthread_join(thread_id, nullptr) == 0);
91  ASSERT_TRUE(finish);
92}
93
94TEST(ThreadTest, pointers) {
95  Pointers pointers(2);
96  Thread thread;
97
98  ASSERT_TRUE(thread.pointers() == nullptr);
99  thread.set_pointers(&pointers);
100  ASSERT_TRUE(thread.pointers() == &pointers);
101}
102
103TEST(ThreadTest, action) {
104  Thread thread;
105
106  Action* action = thread.CreateAction(0x1234, "thread_done", "");
107  ASSERT_EQ(action, thread.GetAction());
108
109  // Verify the action object is not garbage.
110  action->Execute(nullptr);
111
112  ASSERT_TRUE(action->EndThread());
113  ASSERT_FALSE(action->DoesFree());
114}
115