1 /*
2  * Copyright 2020 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 <sys/socket.h>
19 #include <sys/types.h>
20 
21 #include <future>
22 
23 #include "module.h"
24 #include "os/thread.h"
25 #include "shim/dumpsys.h"
26 #include "shim/dumpsys_args.h"
27 #include "test_data/dumpsys_test_data_bin.h"
28 
29 namespace testing {
30 
31 using bluetooth::TestModuleRegistry;
32 using namespace bluetooth;
33 
34 namespace {
35 
SimpleJsonValidator(int fd,int * dumpsys_byte_cnt)36 bool SimpleJsonValidator(int fd, int* dumpsys_byte_cnt) {
37   char buf{0};
38   bool within_double_quotes{false};
39   int left_bracket{0}, right_bracket{0};
40   while (read(fd, &buf, 1) != -1) {
41     switch (buf) {
42       (*dumpsys_byte_cnt)++;
43       case '"':
44         within_double_quotes = !within_double_quotes;
45         break;
46       case '{':
47         if (!within_double_quotes) {
48           left_bracket++;
49         }
50         break;
51       case '}':
52         if (!within_double_quotes) {
53           right_bracket++;
54         }
55         break;
56       default:
57         break;
58     }
59   }
60   return left_bracket == right_bracket;
61 }
62 
63 }  // namespace
64 
65 // TODO(cmanton) maybe create in build
66 // To create dumpsys_test_header_bin.h:
67 // make bluetooth_flatbuffer_bundler
68 // ${ANDROID_BUILD_TOP}/out/host/linux-x86/bin/bluetooth_flatbuffer_bundler -w -m bluetooth.DumpsysData -f
69 // test_gen/dumpsys_test_data_bin -n bluetooth::test test_gen/*
70 
71 class DumpsysTest : public Test {
72  protected:
SetUp()73   void SetUp() override {
74     dumpsys_module_ = new bluetooth::shim::Dumpsys(bluetooth::test::GetBundledSchemaData());
75     fake_registry_.InjectTestModule(&shim::Dumpsys::Factory, dumpsys_module_);
76   }
77 
TearDown()78   void TearDown() override {
79     fake_registry_.StopAll();
80   }
81 
Print()82   void Print() {
83     dumpsys_module_->Dump(0, nullptr);
84   }
85 
GetSocketBufferSize(int sockfd)86   int GetSocketBufferSize(int sockfd) {
87     int socket_buffer_size;
88     socklen_t optlen = sizeof(socket_buffer_size);
89     getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (void*)&socket_buffer_size, &optlen);
90     return socket_buffer_size;
91   }
92 
SetSocketBufferSize(int sockfd,int socket_buffer_size)93   void SetSocketBufferSize(int sockfd, int socket_buffer_size) {
94     socklen_t optlen = sizeof(socket_buffer_size);
95     ASSERT_EQ(0, setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (const void*)&socket_buffer_size, optlen));
96   }
97 
98   TestModuleRegistry fake_registry_;
99   os::Thread& thread_ = fake_registry_.GetTestThread();
100   bluetooth::shim::Dumpsys* dumpsys_module_ = nullptr;
101   os::Handler* client_handler_ = nullptr;
102 };
103 
TEST_F(DumpsysTest,dump_as_developer)104 TEST_F(DumpsysTest, dump_as_developer) {
105   const char* args[]{bluetooth::shim::kArgumentDeveloper, nullptr};
106 
107   int sv[2];
108   ASSERT_EQ(0, socketpair(AF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK, 0, sv));
109   int socket_buffer_size = GetSocketBufferSize(sv[0]);
110 
111   std::promise<void> promise;
112   std::future future = promise.get_future();
113   dumpsys_module_->Dump(sv[0], args, std::move(promise));
114   future.wait();
115 
116   int dumpsys_byte_cnt = 0;
117   ASSERT_TRUE(SimpleJsonValidator(sv[1], &dumpsys_byte_cnt));
118   ASSERT_TRUE(dumpsys_byte_cnt < socket_buffer_size);
119 }
120 
TEST_F(DumpsysTest,dump_as_user)121 TEST_F(DumpsysTest, dump_as_user) {
122   const char* args[]{"not-a-developer-option", nullptr};
123 
124   int sv[2];
125   ASSERT_EQ(0, socketpair(AF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK, 0, sv));
126   int socket_buffer_size = GetSocketBufferSize(sv[0]);
127 
128   std::promise<void> promise;
129   std::future future = promise.get_future();
130   dumpsys_module_->Dump(sv[0], args, std::move(promise));
131   future.wait();
132 
133   int dumpsys_byte_cnt = 0;
134   ASSERT_TRUE(SimpleJsonValidator(sv[1], &dumpsys_byte_cnt));
135   ASSERT_TRUE(dumpsys_byte_cnt < socket_buffer_size);
136 }
137 
138 }  // namespace testing
139