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 #if defined(OS_GENERIC)
53 tmp_dir_ = "/tmp/btwlXXXXXX";
54 #else
55 tmp_dir_ = "/data/local/tmp/btwlXXXXXX";
56 #endif // !defined(OS_GENERIC)
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 creat(lock_path_.c_str(), S_IRWXU);
69 creat(unlock_path_.c_str(), S_IRWXU);
70 }
71
TearDown()72 void TearDown() override {
73 is_wake_lock_acquired = false;
74 wakelock_cleanup();
75 wakelock_set_os_callouts(NULL);
76
77 // Clean up the temp wake lock directory
78 unlink(lock_path_.c_str());
79 unlink(unlock_path_.c_str());
80 rmdir(tmp_dir_.c_str());
81
82 AllocationTestHarness::TearDown();
83 }
84
85 //
86 // Test whether the file-based wakelock is acquired.
87 //
IsFileWakeLockAcquired()88 bool IsFileWakeLockAcquired() {
89 bool acquired = false;
90
91 int lock_fd = open(lock_path_.c_str(), O_RDONLY);
92 CHECK(lock_fd >= 0);
93
94 int unlock_fd = open(unlock_path_.c_str(), O_RDONLY);
95 CHECK(unlock_fd >= 0);
96
97 struct stat lock_stat, unlock_stat;
98 fstat(lock_fd, &lock_stat);
99 fstat(unlock_fd, &unlock_stat);
100
101 CHECK(lock_stat.st_size >= unlock_stat.st_size);
102
103 void* lock_file =
104 mmap(nullptr, lock_stat.st_size, PROT_READ, MAP_PRIVATE, lock_fd, 0);
105
106 void* unlock_file = mmap(nullptr, unlock_stat.st_size, PROT_READ,
107 MAP_PRIVATE, unlock_fd, 0);
108
109 if (memcmp(lock_file, unlock_file, unlock_stat.st_size) == 0) {
110 acquired = lock_stat.st_size > unlock_stat.st_size;
111 } else {
112 // these files should always either be with a lock that has more,
113 // or equal.
114 CHECK(false);
115 }
116
117 munmap(lock_file, lock_stat.st_size);
118 munmap(unlock_file, unlock_stat.st_size);
119 close(lock_fd);
120 close(unlock_fd);
121
122 return acquired;
123 }
124
125 std::string tmp_dir_;
126 std::string lock_path_;
127 std::string unlock_path_;
128 };
129
TEST_F(WakelockTest,test_set_os_callouts)130 TEST_F(WakelockTest, test_set_os_callouts) {
131 wakelock_set_os_callouts(&bt_wakelock_callouts);
132
133 // Initially, the wakelock is not acquired
134 ASSERT_FALSE(is_wake_lock_acquired);
135
136 for (size_t i = 0; i < 1000; i++) {
137 wakelock_acquire();
138 ASSERT_TRUE(is_wake_lock_acquired);
139 wakelock_release();
140 ASSERT_FALSE(is_wake_lock_acquired);
141 }
142 }
143
TEST_F(WakelockTest,test_set_paths)144 TEST_F(WakelockTest, test_set_paths) {
145 wakelock_set_os_callouts(NULL); // Make sure we use native wakelocks
146 wakelock_set_paths(lock_path_.c_str(), unlock_path_.c_str());
147
148 // Initially, the wakelock is not acquired
149 ASSERT_FALSE(IsFileWakeLockAcquired());
150
151 for (size_t i = 0; i < 1000; i++) {
152 wakelock_acquire();
153 ASSERT_TRUE(IsFileWakeLockAcquired());
154 wakelock_release();
155 ASSERT_FALSE(IsFileWakeLockAcquired());
156 }
157 }
158