1223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov/******************************************************************************
2223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *
3223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *  Copyright (C) 2016 Google, Inc.
4223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *
5223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *  Licensed under the Apache License, Version 2.0 (the "License");
6223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *  you may not use this file except in compliance with the License.
7223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *  You may obtain a copy of the License at:
8223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *
9223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *  http://www.apache.org/licenses/LICENSE-2.0
10223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *
11223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *  Unless required by applicable law or agreed to in writing, software
12223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *  distributed under the License is distributed on an "AS IS" BASIS,
13223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *  See the License for the specific language governing permissions and
15223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *  limitations under the License.
16223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov *
17223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov ******************************************************************************/
18223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
19223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov#include <gtest/gtest.h>
20223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
21f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He#include <base/logging.h>
22b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson#include <fcntl.h>
23223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov#include <sys/mman.h>
24223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov#include <sys/stat.h>
25b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson#include <sys/types.h>
26223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
27223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov#include "osi/include/wakelock.h"
28223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
29223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov#include "AllocationTestHarness.h"
30223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
31223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavovstatic bool is_wake_lock_acquired = false;
32223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
33b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic int acquire_wake_lock_cb(const char* lock_name) {
34223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  is_wake_lock_acquired = true;
35223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  return BT_STATUS_SUCCESS;
36223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov}
37223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
38b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic int release_wake_lock_cb(const char* lock_name) {
39223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  is_wake_lock_acquired = false;
40223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  return BT_STATUS_SUCCESS;
41223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov}
42223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
43223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavovstatic bt_os_callouts_t bt_wakelock_callouts = {
44b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson    sizeof(bt_os_callouts_t), NULL, acquire_wake_lock_cb, release_wake_lock_cb};
45223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
46223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavovclass WakelockTest : public AllocationTestHarness {
47b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson protected:
48223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  virtual void SetUp() {
49223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    AllocationTestHarness::SetUp();
50223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
51b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson// TODO (jamuraa): maybe use base::CreateNewTempDirectory instead?
52223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov#if defined(OS_GENERIC)
53223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    tmp_dir_ = "/tmp/btwlXXXXXX";
54223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov#else
55223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    tmp_dir_ = "/data/local/tmp/btwlXXXXXX";
56b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson#endif  // !defined(OS_GENERIC)
57223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
58b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson    char* buffer = const_cast<char*>(tmp_dir_.c_str());
59b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson    char* dtemp = mkdtemp(buffer);
60223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    if (!dtemp) {
61223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov      perror("Can't make wake lock test directory: ");
62f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He      CHECK(false);
63223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    }
64223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
65223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    lock_path_ = tmp_dir_ + "/wake_lock";
66223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    unlock_path_ = tmp_dir_ + "/wake_unlock";
67223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
68223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    creat(lock_path_.c_str(), S_IRWXU);
69223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    creat(unlock_path_.c_str(), S_IRWXU);
70223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  }
71223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
72223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  virtual void TearDown() {
73223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    is_wake_lock_acquired = false;
74223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    wakelock_cleanup();
75223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    wakelock_set_os_callouts(NULL);
76223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
77223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    // Clean up the temp wake lock directory
78223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    unlink(lock_path_.c_str());
79223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    unlink(unlock_path_.c_str());
80223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    rmdir(tmp_dir_.c_str());
81223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
82223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    AllocationTestHarness::TearDown();
83223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  }
84223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
85223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  //
86223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  // Test whether the file-based wakelock is acquired.
87223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  //
88223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  bool IsFileWakeLockAcquired() {
89223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    bool acquired = false;
90223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
91223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    int lock_fd = open(lock_path_.c_str(), O_RDONLY);
92f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He    CHECK(lock_fd >= 0);
93223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
94223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    int unlock_fd = open(unlock_path_.c_str(), O_RDONLY);
95f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He    CHECK(unlock_fd >= 0);
96223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
97223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    struct stat lock_stat, unlock_stat;
98223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    fstat(lock_fd, &lock_stat);
99223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    fstat(unlock_fd, &unlock_stat);
100223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
101f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He    CHECK(lock_stat.st_size >= unlock_stat.st_size);
102223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
103b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson    void* lock_file =
104b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson        mmap(nullptr, lock_stat.st_size, PROT_READ, MAP_PRIVATE, lock_fd, 0);
105223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
106b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson    void* unlock_file = mmap(nullptr, unlock_stat.st_size, PROT_READ,
107223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov                             MAP_PRIVATE, unlock_fd, 0);
108223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
109223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    if (memcmp(lock_file, unlock_file, unlock_stat.st_size) == 0) {
110223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov      acquired = lock_stat.st_size > unlock_stat.st_size;
111223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    } else {
112223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov      // these files should always either be with a lock that has more,
113223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov      // or equal.
114f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He      CHECK(false);
115223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    }
116223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
117223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    munmap(lock_file, lock_stat.st_size);
118223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    munmap(unlock_file, unlock_stat.st_size);
119223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    close(lock_fd);
120223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    close(unlock_fd);
121223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
122223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    return acquired;
123223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  }
124223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
125223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  std::string tmp_dir_;
126223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  std::string lock_path_;
127223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  std::string unlock_path_;
128223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov};
129223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
130223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin RadoslavovTEST_F(WakelockTest, test_set_os_callouts) {
131223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  wakelock_set_os_callouts(&bt_wakelock_callouts);
132223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
133223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  // Initially, the wakelock is not acquired
134223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  ASSERT_FALSE(is_wake_lock_acquired);
135223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
136223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  for (size_t i = 0; i < 1000; i++) {
137223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    wakelock_acquire();
138223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    ASSERT_TRUE(is_wake_lock_acquired);
139223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    wakelock_release();
140223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    ASSERT_FALSE(is_wake_lock_acquired);
141223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  }
142223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov}
143223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
144223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin RadoslavovTEST_F(WakelockTest, test_set_paths) {
145b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson  wakelock_set_os_callouts(NULL);  // Make sure we use native wakelocks
146223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  wakelock_set_paths(lock_path_.c_str(), unlock_path_.c_str());
147223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
148223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  // Initially, the wakelock is not acquired
149223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  ASSERT_FALSE(IsFileWakeLockAcquired());
150223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov
151223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  for (size_t i = 0; i < 1000; i++) {
152223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    wakelock_acquire();
153223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    ASSERT_TRUE(IsFileWakeLockAcquired());
154223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    wakelock_release();
155223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov    ASSERT_FALSE(IsFileWakeLockAcquired());
156223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov  }
157223cecf8b6905fec65c509cf85b20edbdbd28344Pavlin Radoslavov}
158