1 /******************************************************************************
2 *
3 * Copyright 2016 Google, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 #include <gtest/gtest.h>
20
21 #include <base/logging.h>
22 #include <fcntl.h>
23 #include <sys/mman.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26
27 #include "osi/include/wakelock.h"
28
29 #include "AllocationTestHarness.h"
30
31 static bool is_wake_lock_acquired = false;
32
acquire_wake_lock_cb(const char * lock_name)33 static int acquire_wake_lock_cb(const char* lock_name) {
34 is_wake_lock_acquired = true;
35 return BT_STATUS_SUCCESS;
36 }
37
release_wake_lock_cb(const char * lock_name)38 static int release_wake_lock_cb(const char* lock_name) {
39 is_wake_lock_acquired = false;
40 return BT_STATUS_SUCCESS;
41 }
42
43 static bt_os_callouts_t bt_wakelock_callouts = {
44 sizeof(bt_os_callouts_t), NULL, acquire_wake_lock_cb, release_wake_lock_cb};
45
46 class WakelockTest : public AllocationTestHarness {
47 protected:
SetUp()48 void SetUp() override {
49 AllocationTestHarness::SetUp();
50
51 // TODO (jamuraa): maybe use base::CreateNewTempDirectory instead?
52 #ifdef __ANDROID__
53 tmp_dir_ = "/data/local/tmp/btwlXXXXXX";
54 #else // !__ANDROID__
55 tmp_dir_ = "/tmp/btwlXXXXXX";
56 #endif // __ANDROID__
57
58 char* buffer = const_cast<char*>(tmp_dir_.c_str());
59 char* dtemp = mkdtemp(buffer);
60 if (!dtemp) {
61 perror("Can't make wake lock test directory: ");
62 CHECK(false);
63 }
64
65 lock_path_ = tmp_dir_ + "/wake_lock";
66 unlock_path_ = tmp_dir_ + "/wake_unlock";
67
68 lock_path_fd = creat(lock_path_.c_str(), S_IRWXU);
69 unlock_path_fd = creat(unlock_path_.c_str(), S_IRWXU);
70 }
71
72 int lock_path_fd{-1};
73 int unlock_path_fd{-1};
74
TearDown()75 void TearDown() override {
76 is_wake_lock_acquired = false;
77 wakelock_cleanup();
78 wakelock_set_os_callouts(NULL);
79
80 // Clean up the temp wake lock directory
81 unlink(lock_path_.c_str());
82 unlink(unlock_path_.c_str());
83 rmdir(tmp_dir_.c_str());
84
85 close(lock_path_fd);
86 close(unlock_path_fd);
87
88 AllocationTestHarness::TearDown();
89 }
90
91 //
92 // Test whether the file-based wakelock is acquired.
93 //
IsFileWakeLockAcquired()94 bool IsFileWakeLockAcquired() {
95 bool acquired = false;
96
97 int lock_fd = open(lock_path_.c_str(), O_RDONLY);
98 CHECK(lock_fd >= 0);
99
100 int unlock_fd = open(unlock_path_.c_str(), O_RDONLY);
101 CHECK(unlock_fd >= 0);
102
103 struct stat lock_stat, unlock_stat;
104 fstat(lock_fd, &lock_stat);
105 fstat(unlock_fd, &unlock_stat);
106
107 CHECK(lock_stat.st_size >= unlock_stat.st_size);
108
109 void* lock_file =
110 mmap(nullptr, lock_stat.st_size, PROT_READ, MAP_PRIVATE, lock_fd, 0);
111
112 void* unlock_file = mmap(nullptr, unlock_stat.st_size, PROT_READ,
113 MAP_PRIVATE, unlock_fd, 0);
114
115 if (memcmp(lock_file, unlock_file, unlock_stat.st_size) == 0) {
116 acquired = lock_stat.st_size > unlock_stat.st_size;
117 } else {
118 // these files should always either be with a lock that has more,
119 // or equal.
120 CHECK(false);
121 }
122
123 munmap(lock_file, lock_stat.st_size);
124 munmap(unlock_file, unlock_stat.st_size);
125 close(lock_fd);
126 close(unlock_fd);
127
128 return acquired;
129 }
130
131 std::string tmp_dir_;
132 std::string lock_path_;
133 std::string unlock_path_;
134 };
135
TEST_F(WakelockTest,test_set_os_callouts)136 TEST_F(WakelockTest, test_set_os_callouts) {
137 wakelock_set_os_callouts(&bt_wakelock_callouts);
138
139 // Initially, the wakelock is not acquired
140 ASSERT_FALSE(is_wake_lock_acquired);
141
142 for (size_t i = 0; i < 1000; i++) {
143 wakelock_acquire();
144 ASSERT_TRUE(is_wake_lock_acquired);
145 wakelock_release();
146 ASSERT_FALSE(is_wake_lock_acquired);
147 }
148 }
149
TEST_F(WakelockTest,test_set_paths)150 TEST_F(WakelockTest, test_set_paths) {
151 wakelock_set_os_callouts(NULL); // Make sure we use native wakelocks
152 wakelock_set_paths(lock_path_.c_str(), unlock_path_.c_str());
153
154 // Initially, the wakelock is not acquired
155 ASSERT_FALSE(IsFileWakeLockAcquired());
156
157 for (size_t i = 0; i < 1000; i++) {
158 wakelock_acquire();
159 ASSERT_TRUE(IsFileWakeLockAcquired());
160 wakelock_release();
161 ASSERT_FALSE(IsFileWakeLockAcquired());
162 }
163 }
164