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 "osi/include/wakelock.h"
20
21 #include <fcntl.h>
22 #include <gtest/gtest.h>
23 #include <sys/mman.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26
27 static bool is_wake_lock_acquired = false;
28
acquire_wake_lock_cb(const char *)29 static int acquire_wake_lock_cb(const char* /*lock_name*/) {
30 is_wake_lock_acquired = true;
31 return BT_STATUS_SUCCESS;
32 }
33
release_wake_lock_cb(const char *)34 static int release_wake_lock_cb(const char* /*lock_name*/) {
35 is_wake_lock_acquired = false;
36 return BT_STATUS_SUCCESS;
37 }
38
39 static bt_os_callouts_t bt_wakelock_callouts = {sizeof(bt_os_callouts_t), acquire_wake_lock_cb,
40 release_wake_lock_cb};
41
42 class WakelockTest : public ::testing::Test {
43 protected:
SetUp()44 void SetUp() override {
45 // TODO (jamuraa): maybe use base::CreateNewTempDirectory instead?
46 #ifdef __ANDROID__
47 tmp_dir_ = "/data/local/tmp/btwlXXXXXX";
48 #else // !__ANDROID__
49 tmp_dir_ = "/tmp/btwlXXXXXX";
50 #endif // __ANDROID__
51
52 char* buffer = const_cast<char*>(tmp_dir_.c_str());
53 char* dtemp = mkdtemp(buffer);
54 ASSERT_NE(dtemp, nullptr) << "Can't make wake lock test directory";
55
56 lock_path_ = tmp_dir_ + "/wake_lock";
57 unlock_path_ = tmp_dir_ + "/wake_unlock";
58
59 lock_path_fd = creat(lock_path_.c_str(), S_IRWXU);
60 unlock_path_fd = creat(unlock_path_.c_str(), S_IRWXU);
61 }
62
63 int lock_path_fd{-1};
64 int unlock_path_fd{-1};
65
TearDown()66 void TearDown() override {
67 is_wake_lock_acquired = false;
68 wakelock_cleanup();
69 wakelock_set_os_callouts(NULL);
70
71 // Clean up the temp wake lock directory
72 unlink(lock_path_.c_str());
73 unlink(unlock_path_.c_str());
74 rmdir(tmp_dir_.c_str());
75
76 close(lock_path_fd);
77 close(unlock_path_fd);
78 }
79
80 //
81 // Test whether the file-based wakelock is acquired.
82 //
IsFileWakeLockAcquired()83 bool IsFileWakeLockAcquired() {
84 bool acquired = false;
85
86 int lock_fd = open(lock_path_.c_str(), O_RDONLY);
87 EXPECT_GE(lock_fd, 0);
88
89 int unlock_fd = open(unlock_path_.c_str(), O_RDONLY);
90 EXPECT_GE(unlock_fd, 0);
91
92 struct stat lock_stat, unlock_stat;
93 fstat(lock_fd, &lock_stat);
94 fstat(unlock_fd, &unlock_stat);
95
96 EXPECT_GE(lock_stat.st_size, unlock_stat.st_size);
97
98 void* lock_file = mmap(nullptr, lock_stat.st_size, PROT_READ, MAP_PRIVATE, lock_fd, 0);
99
100 void* unlock_file = mmap(nullptr, unlock_stat.st_size, PROT_READ, MAP_PRIVATE, unlock_fd, 0);
101
102 if (memcmp(lock_file, unlock_file, unlock_stat.st_size) == 0) {
103 acquired = lock_stat.st_size > unlock_stat.st_size;
104 } else {
105 // these files should always either be with a lock that has more,
106 // or equal.
107 ADD_FAILURE();
108 }
109
110 munmap(lock_file, lock_stat.st_size);
111 munmap(unlock_file, unlock_stat.st_size);
112 close(lock_fd);
113 close(unlock_fd);
114
115 return acquired;
116 }
117
118 std::string tmp_dir_;
119 std::string lock_path_;
120 std::string unlock_path_;
121 };
122
TEST_F(WakelockTest,test_set_os_callouts)123 TEST_F(WakelockTest, test_set_os_callouts) {
124 wakelock_set_os_callouts(&bt_wakelock_callouts);
125
126 // Initially, the wakelock is not acquired
127 ASSERT_FALSE(is_wake_lock_acquired);
128
129 for (size_t i = 0; i < 1000; i++) {
130 wakelock_acquire();
131 ASSERT_TRUE(is_wake_lock_acquired);
132 wakelock_release();
133 ASSERT_FALSE(is_wake_lock_acquired);
134 }
135 }
136
TEST_F(WakelockTest,test_set_paths)137 TEST_F(WakelockTest, test_set_paths) {
138 wakelock_set_os_callouts(NULL); // Make sure we use native wakelocks
139 wakelock_set_paths(lock_path_.c_str(), unlock_path_.c_str());
140
141 // Initially, the wakelock is not acquired
142 ASSERT_FALSE(IsFileWakeLockAcquired());
143
144 for (size_t i = 0; i < 1000; i++) {
145 wakelock_acquire();
146 ASSERT_TRUE(IsFileWakeLockAcquired());
147 wakelock_release();
148 ASSERT_FALSE(IsFileWakeLockAcquired());
149 }
150 }
151